Sync to HEAD
[bpt/emacs.git] / src / xdisp.c
CommitLineData
a2889657 1/* Display generation from window structure and buffer text.
6b61353c 2 Copyright (C) 1985,86,87,88,93,94,95,97,98,99,2000,01,02,03,04
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"
ea0ffe21 179#include "character.h"
1c9241f5 180#include "charset.h"
a2889657
JB
181#include "indent.h"
182#include "commands.h"
fa3c6b4d 183#include "keymap.h"
a2889657
JB
184#include "macros.h"
185#include "disptab.h"
30c566e4 186#include "termhooks.h"
b0a0fbda 187#include "intervals.h"
1c9241f5
KH
188#include "coding.h"
189#include "process.h"
dfcf069d 190#include "region-cache.h"
0ef75e87 191#include "fontset.h"
f9b3d256 192#include "blockinput.h"
dfcf069d 193
6d55d620 194#ifdef HAVE_X_WINDOWS
dfcf069d
AS
195#include "xterm.h"
196#endif
a75dfea0
AI
197#ifdef WINDOWSNT
198#include "w32term.h"
199#endif
e0f712ba 200#ifdef MAC_OS
1a578e9b 201#include "macterm.h"
365fa1b3
AC
202
203Cursor No_Cursor;
1a578e9b 204#endif
a2889657 205
1dabd0cf
KS
206#ifndef FRAME_X_OUTPUT
207#define FRAME_X_OUTPUT(f) ((f)->output_data.x)
208#endif
209
5f5c8ee5
GM
210#define INFINITY 10000000
211
488dd4c4
JD
212#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (MAC_OS) \
213 || defined (USE_GTK)
2e621225 214extern void set_frame_menubar P_ ((struct frame *f, int, int));
cd6dfed6 215extern int pending_menu_activation;
76412d64
RS
216#endif
217
a2889657
JB
218extern int interrupt_input;
219extern int command_loop_level;
220
b6436d4e 221extern int minibuffer_auto_raise;
b2b5455d 222extern Lisp_Object Vminibuffer_list;
b6436d4e 223
c4628384 224extern Lisp_Object Qface;
fec8f23e 225extern Lisp_Object Qmode_line, Qmode_line_inactive, Qheader_line;
c4628384 226
399164b4
KH
227extern Lisp_Object Voverriding_local_map;
228extern Lisp_Object Voverriding_local_map_menu_flag;
5f5c8ee5 229extern Lisp_Object Qmenu_item;
0b063c27 230extern Lisp_Object Qwhen;
fa3c6b4d 231extern Lisp_Object Qhelp_echo;
399164b4 232
d46fb96a 233Lisp_Object Qoverriding_local_map, Qoverriding_terminal_local_map;
75c43375 234Lisp_Object Qwindow_scroll_functions, Vwindow_scroll_functions;
e0bfbde6 235Lisp_Object Qredisplay_end_trigger_functions;
2e54982e 236Lisp_Object Qinhibit_point_motion_hooks;
0b063c27 237Lisp_Object QCeval, QCfile, QCdata, QCpropertize;
5f5c8ee5 238Lisp_Object Qfontified;
6422c1d7 239Lisp_Object Qgrow_only;
869fb12c 240Lisp_Object Qinhibit_eval_during_redisplay;
b384d6f8 241Lisp_Object Qbuffer_position, Qposition, Qobject;
5f5c8ee5 242
cfe03a41
KS
243/* Cursor shapes */
244Lisp_Object Qbar, Qhbar, Qbox, Qhollow;
245
6b61353c
KH
246/* Pointer shapes */
247Lisp_Object Qarrow, Qhand, Qtext;
248
c53a1624
RS
249Lisp_Object Qrisky_local_variable;
250
7033d6df
RS
251/* Holds the list (error). */
252Lisp_Object list_of_error;
253
5f5c8ee5
GM
254/* Functions called to fontify regions of text. */
255
256Lisp_Object Vfontification_functions;
257Lisp_Object Qfontification_functions;
258
fa3c6b4d
KS
259/* Non-zero means automatically select any window when the mouse
260 cursor moves into it. */
261int mouse_autoselect_window;
262
e037b9ec 263/* Non-zero means draw tool bar buttons raised when the mouse moves
5f5c8ee5
GM
264 over them. */
265
e037b9ec 266int auto_raise_tool_bar_buttons_p;
5f5c8ee5 267
e037b9ec 268/* Margin around tool bar buttons in pixels. */
5f5c8ee5 269
35a41507 270Lisp_Object Vtool_bar_button_margin;
5f5c8ee5 271
e037b9ec 272/* Thickness of shadow to draw around tool bar buttons. */
5f5c8ee5 273
31ade731 274EMACS_INT tool_bar_button_relief;
5f5c8ee5 275
e037b9ec 276/* Non-zero means automatically resize tool-bars so that all tool-bar
5f5c8ee5
GM
277 items are visible, and no blank lines remain. */
278
e037b9ec 279int auto_resize_tool_bars_p;
399164b4 280
fa3c6b4d
KS
281/* Non-zero means draw block and hollow cursor as wide as the glyph
282 under it. For example, if a block cursor is over a tab, it will be
283 drawn as wide as that tab on the display. */
284
285int x_stretch_cursor_p;
286
735c094c
KH
287/* Non-nil means don't actually do any redisplay. */
288
289Lisp_Object Vinhibit_redisplay, Qinhibit_redisplay;
290
30a3f61c
GM
291/* Non-zero means Lisp evaluation during redisplay is inhibited. */
292
869fb12c 293int inhibit_eval_during_redisplay;
30a3f61c 294
5f5c8ee5
GM
295/* Names of text properties relevant for redisplay. */
296
6b61353c 297Lisp_Object Qdisplay;
4b41cebb 298extern Lisp_Object Qface, Qinvisible, Qwidth;
5f5c8ee5
GM
299
300/* Symbols used in text property values. */
301
6b61353c 302Lisp_Object Vdisplay_pixels_per_inch;
5f5c8ee5 303Lisp_Object Qspace, QCalign_to, QCrelative_width, QCrelative_height;
a7e27ef7 304Lisp_Object Qleft_margin, Qright_margin, Qspace_width, Qraise;
6b61353c
KH
305Lisp_Object Qcenter;
306Lisp_Object Qmargin, Qpointer;
a7e27ef7 307extern Lisp_Object Qheight;
133c764e 308extern Lisp_Object QCwidth, QCheight, QCascent;
6b61353c 309extern Lisp_Object Qscroll_bar;
5f5c8ee5 310
8f897821 311/* Non-nil means highlight trailing whitespace. */
5f5c8ee5 312
8f897821 313Lisp_Object Vshow_trailing_whitespace;
5f5c8ee5 314
6b61353c
KH
315#ifdef HAVE_WINDOW_SYSTEM
316extern Lisp_Object Voverflow_newline_into_fringe;
317
318/* Test if overflow newline into fringe. Called with iterator IT
319 at or past right window margin, and with IT->current_x set. */
320
321#define IT_OVERFLOW_NEWLINE_INTO_FRINGE(it) \
322 (!NILP (Voverflow_newline_into_fringe) \
323 && FRAME_WINDOW_P (it->f) \
324 && WINDOW_RIGHT_FRINGE_WIDTH (it->w) > 0 \
325 && it->current_x == it->last_visible_x)
326
327#endif /* HAVE_WINDOW_SYSTEM */
328
329/* Non-nil means show the text cursor in void text areas
330 i.e. in blank areas after eol and eob. This used to be
331 the default in 21.3. */
332
333Lisp_Object Vvoid_text_area_pointer;
334
5f5c8ee5
GM
335/* Name of the face used to highlight trailing whitespace. */
336
337Lisp_Object Qtrailing_whitespace;
338
339/* The symbol `image' which is the car of the lists used to represent
340 images in Lisp. */
341
342Lisp_Object Qimage;
343
6b61353c
KH
344/* The image map types. */
345Lisp_Object QCmap, QCpointer;
346Lisp_Object Qrect, Qcircle, Qpoly;
347
5f5c8ee5
GM
348/* Non-zero means print newline to stdout before next mini-buffer
349 message. */
a2889657
JB
350
351int noninteractive_need_newline;
352
5f5c8ee5 353/* Non-zero means print newline to message log before next message. */
f88eb0b6 354
3c6595e0 355static int message_log_need_newline;
f88eb0b6 356
b14bc55e
RS
357/* Three markers that message_dolog uses.
358 It could allocate them itself, but that causes trouble
359 in handling memory-full errors. */
360static Lisp_Object message_dolog_marker1;
361static Lisp_Object message_dolog_marker2;
362static Lisp_Object message_dolog_marker3;
5f5c8ee5
GM
363\f
364/* The buffer position of the first character appearing entirely or
365 partially on the line of the selected window which contains the
366 cursor; <= 0 if not known. Set by set_cursor_from_row, used for
367 redisplay optimization in redisplay_internal. */
a2889657 368
5f5c8ee5 369static struct text_pos this_line_start_pos;
a2889657 370
5f5c8ee5
GM
371/* Number of characters past the end of the line above, including the
372 terminating newline. */
373
374static struct text_pos this_line_end_pos;
375
376/* The vertical positions and the height of this line. */
a2889657 377
a2889657 378static int this_line_vpos;
5f5c8ee5
GM
379static int this_line_y;
380static int this_line_pixel_height;
381
382/* X position at which this display line starts. Usually zero;
383 negative if first character is partially visible. */
384
385static int this_line_start_x;
a2889657 386
5f5c8ee5 387/* Buffer that this_line_.* variables are referring to. */
a2889657 388
a2889657
JB
389static struct buffer *this_line_buffer;
390
5f5c8ee5
GM
391/* Nonzero means truncate lines in all windows less wide than the
392 frame. */
a2889657 393
a2889657
JB
394int truncate_partial_width_windows;
395
7bbe686f 396/* A flag to control how to display unibyte 8-bit character. */
5f5c8ee5 397
7bbe686f 398int unibyte_display_via_language_environment;
2311178e 399
5f5c8ee5
GM
400/* Nonzero means we have more than one non-mini-buffer-only frame.
401 Not guaranteed to be accurate except while parsing
402 frame-title-format. */
7bbe686f 403
d39b6696
KH
404int multiple_frames;
405
a2889657
JB
406Lisp_Object Vglobal_mode_string;
407
6b61353c
KH
408
409/* List of variables (symbols) which hold markers for overlay arrows.
410 The symbols on this list are examined during redisplay to determine
411 where to display overlay arrows. */
412
413Lisp_Object Voverlay_arrow_variable_list;
414
a2889657 415/* Marker for where to display an arrow on top of the buffer text. */
5f5c8ee5 416
a2889657
JB
417Lisp_Object Voverlay_arrow_position;
418
5f5c8ee5
GM
419/* String to display for the arrow. Only used on terminal frames. */
420
a2889657
JB
421Lisp_Object Voverlay_arrow_string;
422
6b61353c
KH
423/* Values of those variables at last redisplay are stored as
424 properties on `overlay-arrow-position' symbol. However, if
425 Voverlay_arrow_position is a marker, last-arrow-position is its
5f5c8ee5
GM
426 numerical position. */
427
6b61353c
KH
428Lisp_Object Qlast_arrow_position, Qlast_arrow_string;
429
430/* Alternative overlay-arrow-string and overlay-arrow-bitmap
431 properties on a symbol in overlay-arrow-variable-list. */
432
433Lisp_Object Qoverlay_arrow_string, Qoverlay_arrow_bitmap;
d45de95b 434
5f5c8ee5
GM
435/* Like mode-line-format, but for the title bar on a visible frame. */
436
d39b6696
KH
437Lisp_Object Vframe_title_format;
438
5f5c8ee5
GM
439/* Like mode-line-format, but for the title bar on an iconified frame. */
440
d39b6696
KH
441Lisp_Object Vicon_title_format;
442
08b610e4
RS
443/* List of functions to call when a window's size changes. These
444 functions get one arg, a frame on which one or more windows' sizes
445 have changed. */
5f5c8ee5 446
08b610e4
RS
447static Lisp_Object Vwindow_size_change_functions;
448
0bca8940 449Lisp_Object Qmenu_bar_update_hook, Vmenu_bar_update_hook;
cf074754 450
a2889657 451/* Nonzero if overlay arrow has been displayed once in this window. */
a2889657 452
5f5c8ee5 453static int overlay_arrow_seen;
ca26e1c8 454
fba9ce76 455/* Nonzero means highlight the region even in nonselected windows. */
fba9ce76 456
5f5c8ee5
GM
457int highlight_nonselected_windows;
458
459/* If cursor motion alone moves point off frame, try scrolling this
460 many lines up or down if that will bring it back. */
461
31ade731 462static EMACS_INT scroll_step;
a2889657 463
4b41cebb 464/* Nonzero means scroll just far enough to bring point back on the
5f5c8ee5
GM
465 screen, when appropriate. */
466
31ade731 467static EMACS_INT scroll_conservatively;
0789adb2 468
5f5c8ee5
GM
469/* Recenter the window whenever point gets within this many lines of
470 the top or bottom of the window. This value is translated into a
da8b7f4f
KS
471 pixel value by multiplying it with FRAME_LINE_HEIGHT, which means
472 that there is really a fixed pixel height scroll margin. */
5f5c8ee5 473
31ade731 474EMACS_INT scroll_margin;
9afd2168 475
5f5c8ee5
GM
476/* Number of windows showing the buffer of the selected window (or
477 another buffer with the same base buffer). keyboard.c refers to
478 this. */
a2889657 479
a2889657
JB
480int buffer_shared;
481
5f5c8ee5 482/* Vector containing glyphs for an ellipsis `...'. */
a2889657 483
5f5c8ee5 484static Lisp_Object default_invis_vector[3];
a2889657 485
1862a24e
MB
486/* Zero means display the mode-line/header-line/menu-bar in the default face
487 (this slightly odd definition is for compatibility with previous versions
488 of emacs), non-zero means display them using their respective faces.
489
490 This variable is deprecated. */
a2889657 491
a2889657
JB
492int mode_line_inverse_video;
493
5f5c8ee5
GM
494/* Prompt to display in front of the mini-buffer contents. */
495
8c5b6a0a 496Lisp_Object minibuf_prompt;
a2889657 497
5f5c8ee5
GM
498/* Width of current mini-buffer prompt. Only set after display_line
499 of the line that contains the prompt. */
500
a2889657 501int minibuf_prompt_width;
5f5c8ee5 502
5f5c8ee5
GM
503/* This is the window where the echo area message was displayed. It
504 is always a mini-buffer window, but it may not be the same window
505 currently active as a mini-buffer. */
506
73af359d
RS
507Lisp_Object echo_area_window;
508
c6e89d6c
GM
509/* List of pairs (MESSAGE . MULTIBYTE). The function save_message
510 pushes the current message and the value of
511 message_enable_multibyte on the stack, the function restore_message
512 pops the stack and displays MESSAGE again. */
513
514Lisp_Object Vmessage_stack;
515
a3788d53
RS
516/* Nonzero means multibyte characters were enabled when the echo area
517 message was specified. */
5f5c8ee5 518
a3788d53
RS
519int message_enable_multibyte;
520
4b41cebb 521/* Nonzero if we should redraw the mode lines on the next redisplay. */
5f5c8ee5 522
a2889657
JB
523int update_mode_lines;
524
5f5c8ee5 525/* Nonzero if window sizes or contents have changed since last
4b41cebb 526 redisplay that finished. */
5f5c8ee5 527
a2889657
JB
528int windows_or_buffers_changed;
529
5fb96e96
RS
530/* Nonzero means a frame's cursor type has been changed. */
531
532int cursor_type_changed;
533
5f5c8ee5
GM
534/* Nonzero after display_mode_line if %l was used and it displayed a
535 line number. */
536
aa6d10fa
RS
537int line_number_displayed;
538
539/* Maximum buffer size for which to display line numbers. */
5f5c8ee5 540
090703f4 541Lisp_Object Vline_number_display_limit;
5992c4f7 542
4b41cebb 543/* Line width to consider when repositioning for line number display. */
5d121aec 544
31ade731 545static EMACS_INT line_number_display_limit_width;
5d121aec 546
5f5c8ee5
GM
547/* Number of lines to keep in the message log buffer. t means
548 infinite. nil means don't log at all. */
549
5992c4f7 550Lisp_Object Vmessage_log_max;
d45de95b 551
6a94510a
GM
552/* The name of the *Messages* buffer, a string. */
553
554static Lisp_Object Vmessages_buffer_name;
555
c6e89d6c
GM
556/* Current, index 0, and last displayed echo area message. Either
557 buffers from echo_buffers, or nil to indicate no message. */
558
559Lisp_Object echo_area_buffer[2];
560
561/* The buffers referenced from echo_area_buffer. */
562
563static Lisp_Object echo_buffer[2];
564
565/* A vector saved used in with_area_buffer to reduce consing. */
566
567static Lisp_Object Vwith_echo_area_save_vector;
568
569/* Non-zero means display_echo_area should display the last echo area
570 message again. Set by redisplay_preserve_echo_area. */
571
572static int display_last_displayed_message_p;
573
574/* Nonzero if echo area is being used by print; zero if being used by
575 message. */
576
577int message_buf_print;
578
e1477f43
GM
579/* The symbol `inhibit-menubar-update' and its DEFVAR_BOOL variable. */
580
581Lisp_Object Qinhibit_menubar_update;
582int inhibit_menubar_update;
583
9142dd5b
GM
584/* Maximum height for resizing mini-windows. Either a float
585 specifying a fraction of the available height, or an integer
586 specifying a number of lines. */
c6e89d6c 587
ad4f174e
GM
588Lisp_Object Vmax_mini_window_height;
589
590/* Non-zero means messages should be displayed with truncated
591 lines instead of being continued. */
592
593int message_truncate_lines;
594Lisp_Object Qmessage_truncate_lines;
c6e89d6c 595
6e019995
GM
596/* Set to 1 in clear_message to make redisplay_internal aware
597 of an emptied echo area. */
598
599static int message_cleared_p;
600
d6d26ed3
GM
601/* Non-zero means we want a hollow cursor in windows that are not
602 selected. Zero means there's no cursor in such windows. */
603
cfe03a41 604Lisp_Object Vcursor_in_non_selected_windows;
af79bccb 605Lisp_Object Qcursor_in_non_selected_windows;
d6d26ed3 606
cfe03a41
KS
607/* How to blink the default frame cursor off. */
608Lisp_Object Vblink_cursor_alist;
609
5f5c8ee5
GM
610/* A scratch glyph row with contents used for generating truncation
611 glyphs. Also used in direct_output_for_insert. */
12adba34 612
5f5c8ee5
GM
613#define MAX_SCRATCH_GLYPHS 100
614struct glyph_row scratch_glyph_row;
615static struct glyph scratch_glyphs[MAX_SCRATCH_GLYPHS];
1adc55de 616
5f5c8ee5
GM
617/* Ascent and height of the last line processed by move_it_to. */
618
619static int last_max_ascent, last_height;
620
21fdfb65
GM
621/* Non-zero if there's a help-echo in the echo area. */
622
623int help_echo_showing_p;
624
04612a64
GM
625/* If >= 0, computed, exact values of mode-line and header-line height
626 to use in the macros CURRENT_MODE_LINE_HEIGHT and
627 CURRENT_HEADER_LINE_HEIGHT. */
628
629int current_mode_line_height, current_header_line_height;
630
5f5c8ee5 631/* The maximum distance to look ahead for text properties. Values
2311178e 632 that are too small let us call compute_char_face and similar
5f5c8ee5
GM
633 functions too often which is expensive. Values that are too large
634 let us call compute_char_face and alike too often because we
635 might not be interested in text properties that far away. */
636
637#define TEXT_PROP_DISTANCE_LIMIT 100
638
47589c8c
GM
639#if GLYPH_DEBUG
640
76cb5e06
GM
641/* Variables to turn off display optimizations from Lisp. */
642
643int inhibit_try_window_id, inhibit_try_window_reusing;
644int inhibit_try_cursor_movement;
645
5f5c8ee5
GM
646/* Non-zero means print traces of redisplay if compiled with
647 GLYPH_DEBUG != 0. */
648
5f5c8ee5 649int trace_redisplay_p;
47589c8c 650
546a4f00 651#endif /* GLYPH_DEBUG */
47589c8c 652
546a4f00
AI
653#ifdef DEBUG_TRACE_MOVE
654/* Non-zero means trace with TRACE_MOVE to stderr. */
47589c8c
GM
655int trace_move;
656
47589c8c
GM
657#define TRACE_MOVE(x) if (trace_move) fprintf x; else (void) 0
658#else
91c3f500 659#define TRACE_MOVE(x) (void) 0
5f5c8ee5 660#endif
2311178e 661
d475bcb8
GM
662/* Non-zero means automatically scroll windows horizontally to make
663 point visible. */
664
665int automatic_hscrolling_p;
666
1df7e8f0
EZ
667/* How close to the margin can point get before the window is scrolled
668 horizontally. */
5d335845 669EMACS_INT hscroll_margin;
1df7e8f0
EZ
670
671/* How much to scroll horizontally when point is inside the above margin. */
e76d28d5 672Lisp_Object Vhscroll_step;
1df7e8f0 673
e00daaa0
GM
674/* A list of symbols, one for each supported image type. */
675
676Lisp_Object Vimage_types;
677
6422c1d7 678/* The variable `resize-mini-windows'. If nil, don't resize
67526daf 679 mini-windows. If t, always resize them to fit the text they
6422c1d7
GM
680 display. If `grow-only', let mini-windows grow only until they
681 become empty. */
682
683Lisp_Object Vresize_mini_windows;
684
82a7ab23
RS
685/* Buffer being redisplayed -- for redisplay_window_error. */
686
687struct buffer *displayed_buffer;
688
5f5c8ee5
GM
689/* Value returned from text property handlers (see below). */
690
691enum prop_handled
3c6595e0 692{
5f5c8ee5
GM
693 HANDLED_NORMALLY,
694 HANDLED_RECOMPUTE_PROPS,
695 HANDLED_OVERLAY_STRING_CONSUMED,
696 HANDLED_RETURN
697};
3c6595e0 698
5f5c8ee5
GM
699/* A description of text properties that redisplay is interested
700 in. */
3c6595e0 701
5f5c8ee5
GM
702struct props
703{
704 /* The name of the property. */
705 Lisp_Object *name;
90adcf20 706
5f5c8ee5
GM
707 /* A unique index for the property. */
708 enum prop_idx idx;
709
710 /* A handler function called to set up iterator IT from the property
711 at IT's current position. Value is used to steer handle_stop. */
712 enum prop_handled (*handler) P_ ((struct it *it));
713};
714
715static enum prop_handled handle_face_prop P_ ((struct it *));
716static enum prop_handled handle_invisible_prop P_ ((struct it *));
717static enum prop_handled handle_display_prop P_ ((struct it *));
260a86a0 718static enum prop_handled handle_composition_prop P_ ((struct it *));
5f5c8ee5
GM
719static enum prop_handled handle_overlay_change P_ ((struct it *));
720static enum prop_handled handle_fontified_prop P_ ((struct it *));
df013a7f 721static enum prop_handled handle_auto_composed_prop P_ ((struct it *));
5f5c8ee5
GM
722
723/* Properties handled by iterators. */
724
725static struct props it_props[] =
5992c4f7 726{
df013a7f 727 {&Qauto_composed, AUTO_COMPOSED_PROP_IDX, handle_auto_composed_prop},
5f5c8ee5
GM
728 {&Qfontified, FONTIFIED_PROP_IDX, handle_fontified_prop},
729 /* Handle `face' before `display' because some sub-properties of
730 `display' need to know the face. */
731 {&Qface, FACE_PROP_IDX, handle_face_prop},
732 {&Qdisplay, DISPLAY_PROP_IDX, handle_display_prop},
733 {&Qinvisible, INVISIBLE_PROP_IDX, handle_invisible_prop},
260a86a0 734 {&Qcomposition, COMPOSITION_PROP_IDX, handle_composition_prop},
5f5c8ee5
GM
735 {NULL, 0, NULL}
736};
5992c4f7 737
5f5c8ee5
GM
738/* Value is the position described by X. If X is a marker, value is
739 the marker_position of X. Otherwise, value is X. */
12adba34 740
5f5c8ee5 741#define COERCE_MARKER(X) (MARKERP ((X)) ? Fmarker_position (X) : (X))
12adba34 742
5f5c8ee5 743/* Enumeration returned by some move_it_.* functions internally. */
12adba34 744
5f5c8ee5
GM
745enum move_it_result
746{
747 /* Not used. Undefined value. */
748 MOVE_UNDEFINED,
bab29e15 749
5f5c8ee5
GM
750 /* Move ended at the requested buffer position or ZV. */
751 MOVE_POS_MATCH_OR_ZV,
bab29e15 752
5f5c8ee5
GM
753 /* Move ended at the requested X pixel position. */
754 MOVE_X_REACHED,
12adba34 755
5f5c8ee5
GM
756 /* Move within a line ended at the end of a line that must be
757 continued. */
758 MOVE_LINE_CONTINUED,
2311178e 759
5f5c8ee5
GM
760 /* Move within a line ended at the end of a line that would
761 be displayed truncated. */
762 MOVE_LINE_TRUNCATED,
ff6c30e5 763
5f5c8ee5
GM
764 /* Move within a line ended at a line end. */
765 MOVE_NEWLINE_OR_CR
766};
12adba34 767
1987b083
RS
768/* This counter is used to clear the face cache every once in a while
769 in redisplay_internal. It is incremented for each redisplay.
770 Every CLEAR_FACE_CACHE_COUNT full redisplays, the face cache is
771 cleared. */
772
773#define CLEAR_FACE_CACHE_COUNT 500
774static int clear_face_cache_count;
775
776/* Record the previous terminal frame we displayed. */
777
778static struct frame *previous_terminal_frame;
779
780/* Non-zero while redisplay_internal is in progress. */
781
782int redisplaying_p;
783
26683087
RS
784/* Non-zero means don't free realized faces. Bound while freeing
785 realized faces is dangerous because glyph matrices might still
786 reference them. */
1987b083 787
26683087
RS
788int inhibit_free_realized_faces;
789Lisp_Object Qinhibit_free_realized_faces;
ff6c30e5 790
fa3c6b4d
KS
791/* If a string, XTread_socket generates an event to display that string.
792 (The display is done in read_char.) */
793
794Lisp_Object help_echo_string;
795Lisp_Object help_echo_window;
796Lisp_Object help_echo_object;
797int help_echo_pos;
798
799/* Temporary variable for XTread_socket. */
800
801Lisp_Object previous_help_echo_string;
802
803
5f5c8ee5
GM
804\f
805/* Function prototypes. */
806
5a08cbaf 807static void setup_for_ellipsis P_ ((struct it *));
43c09969 808static void mark_window_display_accurate_1 P_ ((struct window *, int));
74bd6d65
GM
809static int single_display_prop_string_p P_ ((Lisp_Object, Lisp_Object));
810static int display_prop_string_p P_ ((Lisp_Object, Lisp_Object));
cafafe0b 811static int cursor_row_p P_ ((struct window *, struct glyph_row *));
715e84c9 812static int redisplay_mode_lines P_ ((Lisp_Object, int));
2e621225 813static char *decode_mode_spec_coding P_ ((Lisp_Object, char *, int));
c0a53abb
PJ
814
815#if 0
2e621225 816static int invisible_text_between_p P_ ((struct it *, int, int));
c0a53abb
PJ
817#endif
818
2e621225
GM
819static int next_element_from_ellipsis P_ ((struct it *));
820static void pint2str P_ ((char *, int, int));
6b61353c 821static void pint2hrstr P_ ((char *, int, int));
2e621225
GM
822static struct text_pos run_window_scroll_functions P_ ((Lisp_Object,
823 struct text_pos));
824static void reconsider_clip_changes P_ ((struct window *, struct buffer *));
825static int text_outside_line_unchanged_p P_ ((struct window *, int, int));
826static void store_frame_title_char P_ ((char));
50f80c2f 827static int store_frame_title P_ ((const unsigned char *, int, int));
2e621225
GM
828static void x_consider_frame_title P_ ((Lisp_Object));
829static void handle_stop P_ ((struct it *));
830static int tool_bar_lines_needed P_ ((struct frame *));
06568bbf 831static int single_display_prop_intangible_p P_ ((Lisp_Object));
5bcfeb49 832static void ensure_echo_area_buffers P_ ((void));
c6e89d6c
GM
833static Lisp_Object unwind_with_echo_area_buffer P_ ((Lisp_Object));
834static Lisp_Object with_echo_area_buffer_unwind_data P_ ((struct window *));
23a96c77 835static int with_echo_area_buffer P_ ((struct window *, int,
23dd2d97
KR
836 int (*) (EMACS_INT, Lisp_Object, EMACS_INT, EMACS_INT),
837 EMACS_INT, Lisp_Object, EMACS_INT, EMACS_INT));
c6e89d6c 838static void clear_garbaged_frames P_ ((void));
23dd2d97
KR
839static int current_message_1 P_ ((EMACS_INT, Lisp_Object, EMACS_INT, EMACS_INT));
840static int truncate_message_1 P_ ((EMACS_INT, Lisp_Object, EMACS_INT, EMACS_INT));
841static int set_message_1 P_ ((EMACS_INT, Lisp_Object, EMACS_INT, EMACS_INT));
c6e89d6c 842static int display_echo_area P_ ((struct window *));
23dd2d97
KR
843static int display_echo_area_1 P_ ((EMACS_INT, Lisp_Object, EMACS_INT, EMACS_INT));
844static int resize_mini_window_1 P_ ((EMACS_INT, Lisp_Object, EMACS_INT, EMACS_INT));
28514cd9 845static Lisp_Object unwind_redisplay P_ ((Lisp_Object));
50f80c2f 846static int string_char_and_length P_ ((const unsigned char *, int, int *));
5f5c8ee5
GM
847static struct text_pos display_prop_end P_ ((struct it *, Lisp_Object,
848 struct text_pos));
849static int compute_window_start_on_continuation_line P_ ((struct window *));
116d6f5c 850static Lisp_Object safe_eval_handler P_ ((Lisp_Object));
5f5c8ee5 851static void insert_left_trunc_glyphs P_ ((struct it *));
6b61353c
KH
852static struct glyph_row *get_overlay_arrow_glyph_row P_ ((struct window *,
853 Lisp_Object));
5f5c8ee5 854static void extend_face_to_end_of_line P_ ((struct it *));
80c6cb1f 855static int append_space P_ ((struct it *, int));
6b61353c 856static int make_cursor_line_fully_visible P_ ((struct window *, int));
03b0a4b4 857static int try_scrolling P_ ((Lisp_Object, int, EMACS_INT, EMACS_INT, int, int));
47589c8c 858static int try_cursor_movement P_ ((Lisp_Object, struct text_pos, int *));
5f5c8ee5
GM
859static int trailing_whitespace_p P_ ((int));
860static int message_log_check_duplicate P_ ((int, int, int, int));
5f5c8ee5
GM
861static void push_it P_ ((struct it *));
862static void pop_it P_ ((struct it *));
863static void sync_frame_with_window_matrix_rows P_ ((struct window *));
6b61353c 864static void select_frame_for_redisplay P_ ((Lisp_Object));
5f5c8ee5 865static void redisplay_internal P_ ((int));
c6e89d6c 866static int echo_area_display P_ ((int));
5f5c8ee5
GM
867static void redisplay_windows P_ ((Lisp_Object));
868static void redisplay_window P_ ((Lisp_Object, int));
82a7ab23
RS
869static Lisp_Object redisplay_window_error ();
870static Lisp_Object redisplay_window_0 P_ ((Lisp_Object));
871static Lisp_Object redisplay_window_1 P_ ((Lisp_Object));
5f5c8ee5
GM
872static void update_menu_bar P_ ((struct frame *, int));
873static int try_window_reusing_current_matrix P_ ((struct window *));
874static int try_window_id P_ ((struct window *));
875static int display_line P_ ((struct it *));
715e84c9 876static int display_mode_lines P_ ((struct window *));
04612a64 877static int display_mode_line P_ ((struct window *, enum face_id, Lisp_Object));
c53a1624 878static int display_mode_element P_ ((struct it *, int, int, int, Lisp_Object, Lisp_Object, int));
fec8f23e 879static int store_mode_line_string P_ ((char *, Lisp_Object, int, int, int, Lisp_Object));
72f62cb5 880static char *decode_mode_spec P_ ((struct window *, int, int, int, int *));
5f5c8ee5
GM
881static void display_menu_bar P_ ((struct window *));
882static int display_count_lines P_ ((int, int, int, int, int *));
883static int display_string P_ ((unsigned char *, Lisp_Object, Lisp_Object,
884 int, int, struct it *, int, int, int, int));
885static void compute_line_metrics P_ ((struct it *));
886static void run_redisplay_end_trigger_hook P_ ((struct it *));
5a08cbaf 887static int get_overlay_strings P_ ((struct it *, int));
5f5c8ee5 888static void next_overlay_string P_ ((struct it *));
5f5c8ee5
GM
889static void reseat P_ ((struct it *, struct text_pos, int));
890static void reseat_1 P_ ((struct it *, struct text_pos, int));
891static void back_to_previous_visible_line_start P_ ((struct it *));
892static void reseat_at_previous_visible_line_start P_ ((struct it *));
312246d1 893static void reseat_at_next_visible_line_start P_ ((struct it *, int));
5f5c8ee5
GM
894static int next_element_from_display_vector P_ ((struct it *));
895static int next_element_from_string P_ ((struct it *));
896static int next_element_from_c_string P_ ((struct it *));
897static int next_element_from_buffer P_ ((struct it *));
260a86a0 898static int next_element_from_composition P_ ((struct it *));
5f5c8ee5
GM
899static int next_element_from_image P_ ((struct it *));
900static int next_element_from_stretch P_ ((struct it *));
5a08cbaf 901static void load_overlay_strings P_ ((struct it *, int));
47d57b22
GM
902static int init_from_display_pos P_ ((struct it *, struct window *,
903 struct display_pos *));
5f5c8ee5
GM
904static void reseat_to_string P_ ((struct it *, unsigned char *,
905 Lisp_Object, int, int, int, int));
5f5c8ee5
GM
906static enum move_it_result move_it_in_display_line_to P_ ((struct it *,
907 int, int, int));
908void move_it_vertically_backward P_ ((struct it *, int));
909static void init_to_row_start P_ ((struct it *, struct window *,
910 struct glyph_row *));
47d57b22
GM
911static int init_to_row_end P_ ((struct it *, struct window *,
912 struct glyph_row *));
5f5c8ee5 913static void back_to_previous_line_start P_ ((struct it *));
cafafe0b 914static int forward_to_next_line_start P_ ((struct it *, int *));
5f5c8ee5
GM
915static struct text_pos string_pos_nchars_ahead P_ ((struct text_pos,
916 Lisp_Object, int));
917static struct text_pos string_pos P_ ((int, Lisp_Object));
918static struct text_pos c_string_pos P_ ((int, unsigned char *, int));
919static int number_of_chars P_ ((unsigned char *, int));
920static void compute_stop_pos P_ ((struct it *));
921static void compute_string_pos P_ ((struct text_pos *, struct text_pos,
922 Lisp_Object));
923static int face_before_or_after_it_pos P_ ((struct it *, int));
924static int next_overlay_change P_ ((int));
925static int handle_single_display_prop P_ ((struct it *, Lisp_Object,
a61b7058
GM
926 Lisp_Object, struct text_pos *,
927 int));
06a12811 928static int underlying_face_id P_ ((struct it *));
4bde0ebb
GM
929static int in_ellipses_for_invisible_text_p P_ ((struct display_pos *,
930 struct window *));
5f5c8ee5
GM
931
932#define face_before_it_pos(IT) face_before_or_after_it_pos ((IT), 1)
933#define face_after_it_pos(IT) face_before_or_after_it_pos ((IT), 0)
ff6c30e5 934
5f5c8ee5 935#ifdef HAVE_WINDOW_SYSTEM
12adba34 936
e037b9ec
GM
937static void update_tool_bar P_ ((struct frame *, int));
938static void build_desired_tool_bar_string P_ ((struct frame *f));
939static int redisplay_tool_bar P_ ((struct frame *));
940static void display_tool_bar_line P_ ((struct it *));
fa3c6b4d
KS
941static void notice_overwritten_cursor P_ ((struct window *,
942 enum glyph_row_area,
943 int, int, int, int));
944
945
12adba34 946
5f5c8ee5 947#endif /* HAVE_WINDOW_SYSTEM */
12adba34 948
5f5c8ee5
GM
949\f
950/***********************************************************************
951 Window display dimensions
952 ***********************************************************************/
12adba34 953
40a301b3
RS
954/* Return the bottom boundary y-position for text lines in window W.
955 This is the first y position at which a line cannot start.
956 It is relative to the top of the window.
957
958 This is the height of W minus the height of a mode line, if any. */
5f5c8ee5
GM
959
960INLINE int
961window_text_bottom_y (w)
962 struct window *w;
963{
da8b7f4f 964 int height = WINDOW_TOTAL_HEIGHT (w);
1a578e9b 965
5f5c8ee5
GM
966 if (WINDOW_WANTS_MODELINE_P (w))
967 height -= CURRENT_MODE_LINE_HEIGHT (w);
968 return height;
f88eb0b6
KH
969}
970
5f5c8ee5 971/* Return the pixel width of display area AREA of window W. AREA < 0
b46952ae 972 means return the total width of W, not including fringes to
5f5c8ee5 973 the left and right of the window. */
ff6c30e5 974
5f5c8ee5
GM
975INLINE int
976window_box_width (w, area)
977 struct window *w;
978 int area;
979{
da8b7f4f
KS
980 int cols = XFASTINT (w->total_cols);
981 int pixels = 0;
2311178e 982
5f5c8ee5 983 if (!w->pseudo_window_p)
ff6c30e5 984 {
da8b7f4f 985 cols -= WINDOW_SCROLL_BAR_COLS (w);
2311178e 986
5f5c8ee5
GM
987 if (area == TEXT_AREA)
988 {
da8b7f4f
KS
989 if (INTEGERP (w->left_margin_cols))
990 cols -= XFASTINT (w->left_margin_cols);
991 if (INTEGERP (w->right_margin_cols))
992 cols -= XFASTINT (w->right_margin_cols);
993 pixels = -WINDOW_TOTAL_FRINGE_WIDTH (w);
5f5c8ee5
GM
994 }
995 else if (area == LEFT_MARGIN_AREA)
da8b7f4f
KS
996 {
997 cols = (INTEGERP (w->left_margin_cols)
998 ? XFASTINT (w->left_margin_cols) : 0);
999 pixels = 0;
1000 }
5f5c8ee5 1001 else if (area == RIGHT_MARGIN_AREA)
da8b7f4f
KS
1002 {
1003 cols = (INTEGERP (w->right_margin_cols)
1004 ? XFASTINT (w->right_margin_cols) : 0);
1005 pixels = 0;
1006 }
ff6c30e5 1007 }
5f5c8ee5 1008
da8b7f4f 1009 return cols * WINDOW_FRAME_COLUMN_WIDTH (w) + pixels;
ff6c30e5 1010}
1adc55de 1011
1adc55de 1012
5f5c8ee5 1013/* Return the pixel height of the display area of window W, not
4b41cebb 1014 including mode lines of W, if any. */
f88eb0b6 1015
5f5c8ee5
GM
1016INLINE int
1017window_box_height (w)
1018 struct window *w;
f88eb0b6 1019{
5f5c8ee5 1020 struct frame *f = XFRAME (w->frame);
da8b7f4f 1021 int height = WINDOW_TOTAL_HEIGHT (w);
7ecd4937
GM
1022
1023 xassert (height >= 0);
2311178e 1024
d9c9e99c
MB
1025 /* Note: the code below that determines the mode-line/header-line
1026 height is essentially the same as that contained in the macro
1027 CURRENT_{MODE,HEADER}_LINE_HEIGHT, except that it checks whether
1028 the appropriate glyph row has its `mode_line_p' flag set,
1029 and if it doesn't, uses estimate_mode_line_height instead. */
1030
5f5c8ee5 1031 if (WINDOW_WANTS_MODELINE_P (w))
97dff879
MB
1032 {
1033 struct glyph_row *ml_row
1034 = (w->current_matrix && w->current_matrix->rows
1035 ? MATRIX_MODE_LINE_ROW (w->current_matrix)
1036 : 0);
1037 if (ml_row && ml_row->mode_line_p)
1038 height -= ml_row->height;
1039 else
96d2320f 1040 height -= estimate_mode_line_height (f, CURRENT_MODE_LINE_FACE_ID (w));
97dff879 1041 }
5f5c8ee5 1042
045dee35 1043 if (WINDOW_WANTS_HEADER_LINE_P (w))
97dff879
MB
1044 {
1045 struct glyph_row *hl_row
1046 = (w->current_matrix && w->current_matrix->rows
1047 ? MATRIX_HEADER_LINE_ROW (w->current_matrix)
1048 : 0);
1049 if (hl_row && hl_row->mode_line_p)
1050 height -= hl_row->height;
1051 else
1052 height -= estimate_mode_line_height (f, HEADER_LINE_FACE_ID);
1053 }
5f5c8ee5 1054
7c75be36
PJ
1055 /* With a very small font and a mode-line that's taller than
1056 default, we might end up with a negative height. */
1057 return max (0, height);
5992c4f7
KH
1058}
1059
da8b7f4f
KS
1060/* Return the window-relative coordinate of the left edge of display
1061 area AREA of window W. AREA < 0 means return the left edge of the
1062 whole window, to the right of the left fringe of W. */
1063
1064INLINE int
1065window_box_left_offset (w, area)
1066 struct window *w;
1067 int area;
1068{
1069 int x;
1070
1071 if (w->pseudo_window_p)
1072 return 0;
1073
1074 x = WINDOW_LEFT_SCROLL_BAR_AREA_WIDTH (w);
1075
1076 if (area == TEXT_AREA)
1077 x += (WINDOW_LEFT_FRINGE_WIDTH (w)
1078 + window_box_width (w, LEFT_MARGIN_AREA));
1079 else if (area == RIGHT_MARGIN_AREA)
1080 x += (WINDOW_LEFT_FRINGE_WIDTH (w)
1081 + window_box_width (w, LEFT_MARGIN_AREA)
1082 + window_box_width (w, TEXT_AREA)
1083 + (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
1084 ? 0
1085 : WINDOW_RIGHT_FRINGE_WIDTH (w)));
1086 else if (area == LEFT_MARGIN_AREA
1087 && WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w))
1088 x += WINDOW_LEFT_FRINGE_WIDTH (w);
1089
1090 return x;
1091}
1092
1093
1094/* Return the window-relative coordinate of the right edge of display
1095 area AREA of window W. AREA < 0 means return the left edge of the
1096 whole window, to the left of the right fringe of W. */
1097
1098INLINE int
1099window_box_right_offset (w, area)
1100 struct window *w;
1101 int area;
1102{
1103 return window_box_left_offset (w, area) + window_box_width (w, area);
1104}
5992c4f7 1105
5f5c8ee5
GM
1106/* Return the frame-relative coordinate of the left edge of display
1107 area AREA of window W. AREA < 0 means return the left edge of the
b46952ae 1108 whole window, to the right of the left fringe of W. */
5992c4f7 1109
5f5c8ee5
GM
1110INLINE int
1111window_box_left (w, area)
1112 struct window *w;
1113 int area;
90adcf20 1114{
5f5c8ee5 1115 struct frame *f = XFRAME (w->frame);
da8b7f4f 1116 int x;
a3788d53 1117
da8b7f4f
KS
1118 if (w->pseudo_window_p)
1119 return FRAME_INTERNAL_BORDER_WIDTH (f);
2311178e 1120
da8b7f4f
KS
1121 x = (WINDOW_LEFT_EDGE_X (w)
1122 + window_box_left_offset (w, area));
73af359d 1123
5f5c8ee5 1124 return x;
2311178e 1125}
90adcf20 1126
b6436d4e 1127
5f5c8ee5
GM
1128/* Return the frame-relative coordinate of the right edge of display
1129 area AREA of window W. AREA < 0 means return the left edge of the
b46952ae 1130 whole window, to the left of the right fringe of W. */
ded34426 1131
5f5c8ee5
GM
1132INLINE int
1133window_box_right (w, area)
1134 struct window *w;
1135 int area;
1136{
1137 return window_box_left (w, area) + window_box_width (w, area);
2311178e
TTN
1138}
1139
5f5c8ee5
GM
1140/* Get the bounding box of the display area AREA of window W, without
1141 mode lines, in frame-relative coordinates. AREA < 0 means the
b46952ae 1142 whole window, not including the left and right fringes of
5f5c8ee5
GM
1143 the window. Return in *BOX_X and *BOX_Y the frame-relative pixel
1144 coordinates of the upper-left corner of the box. Return in
1145 *BOX_WIDTH, and *BOX_HEIGHT the pixel width and height of the box. */
1146
1147INLINE void
1148window_box (w, area, box_x, box_y, box_width, box_height)
1149 struct window *w;
1150 int area;
1151 int *box_x, *box_y, *box_width, *box_height;
1152{
da8b7f4f
KS
1153 if (box_width)
1154 *box_width = window_box_width (w, area);
1155 if (box_height)
1156 *box_height = window_box_height (w);
1157 if (box_x)
1158 *box_x = window_box_left (w, area);
1159 if (box_y)
1160 {
1161 *box_y = WINDOW_TOP_EDGE_Y (w);
1162 if (WINDOW_WANTS_HEADER_LINE_P (w))
1163 *box_y += CURRENT_HEADER_LINE_HEIGHT (w);
1164 }
ded34426 1165}
1adc55de 1166
1adc55de 1167
5f5c8ee5 1168/* Get the bounding box of the display area AREA of window W, without
b46952ae
KS
1169 mode lines. AREA < 0 means the whole window, not including the
1170 left and right fringe of the window. Return in *TOP_LEFT_X
5f5c8ee5
GM
1171 and TOP_LEFT_Y the frame-relative pixel coordinates of the
1172 upper-left corner of the box. Return in *BOTTOM_RIGHT_X, and
1173 *BOTTOM_RIGHT_Y the coordinates of the bottom-right corner of the
1174 box. */
ded34426 1175
5f5c8ee5
GM
1176INLINE void
1177window_box_edges (w, area, top_left_x, top_left_y,
1178 bottom_right_x, bottom_right_y)
1179 struct window *w;
1180 int area;
1181 int *top_left_x, *top_left_y, *bottom_right_x, *bottom_right_y;
48ae5f0a 1182{
5f5c8ee5
GM
1183 window_box (w, area, top_left_x, top_left_y, bottom_right_x,
1184 bottom_right_y);
1185 *bottom_right_x += *top_left_x;
1186 *bottom_right_y += *top_left_y;
48ae5f0a
KH
1187}
1188
5f5c8ee5
GM
1189
1190\f
1191/***********************************************************************
1192 Utilities
1193 ***********************************************************************/
1194
8b6ea97f
GM
1195/* Return the bottom y-position of the line the iterator IT is in.
1196 This can modify IT's settings. */
1197
1198int
1199line_bottom_y (it)
1200 struct it *it;
1201{
1202 int line_height = it->max_ascent + it->max_descent;
1203 int line_top_y = it->current_y;
2311178e 1204
8b6ea97f
GM
1205 if (line_height == 0)
1206 {
1207 if (last_height)
1208 line_height = last_height;
1209 else if (IT_CHARPOS (*it) < ZV)
1210 {
1211 move_it_by_lines (it, 1, 1);
1212 line_height = (it->max_ascent || it->max_descent
1213 ? it->max_ascent + it->max_descent
1214 : last_height);
1215 }
1216 else
1217 {
1218 struct glyph_row *row = it->glyph_row;
2311178e 1219
8b6ea97f
GM
1220 /* Use the default character height. */
1221 it->glyph_row = NULL;
1222 it->what = IT_CHARACTER;
1223 it->c = ' ';
1224 it->len = 1;
1225 PRODUCE_GLYPHS (it);
1226 line_height = it->ascent + it->descent;
1227 it->glyph_row = row;
1228 }
1229 }
1230
1231 return line_top_y + line_height;
1232}
1233
1234
0db95684
GM
1235/* Return 1 if position CHARPOS is visible in window W. Set *FULLY to
1236 1 if POS is visible and the line containing POS is fully visible.
1237 EXACT_MODE_LINE_HEIGHTS_P non-zero means compute exact mode-line
1238 and header-lines heights. */
3a641a69
GM
1239
1240int
04612a64 1241pos_visible_p (w, charpos, fully, exact_mode_line_heights_p)
3a641a69 1242 struct window *w;
04612a64 1243 int charpos, *fully, exact_mode_line_heights_p;
3a641a69
GM
1244{
1245 struct it it;
1246 struct text_pos top;
fcab1954
GM
1247 int visible_p;
1248 struct buffer *old_buffer = NULL;
1249
1250 if (XBUFFER (w->buffer) != current_buffer)
1251 {
1252 old_buffer = current_buffer;
1253 set_buffer_internal_1 (XBUFFER (w->buffer));
1254 }
3a641a69
GM
1255
1256 *fully = visible_p = 0;
1257 SET_TEXT_POS_FROM_MARKER (top, w->start);
2311178e 1258
04612a64
GM
1259 /* Compute exact mode line heights, if requested. */
1260 if (exact_mode_line_heights_p)
1261 {
1262 if (WINDOW_WANTS_MODELINE_P (w))
1263 current_mode_line_height
96d2320f 1264 = display_mode_line (w, CURRENT_MODE_LINE_FACE_ID (w),
04612a64 1265 current_buffer->mode_line_format);
2311178e 1266
04612a64
GM
1267 if (WINDOW_WANTS_HEADER_LINE_P (w))
1268 current_header_line_height
1269 = display_mode_line (w, HEADER_LINE_FACE_ID,
1270 current_buffer->header_line_format);
1271 }
3a641a69 1272
04612a64 1273 start_display (&it, w, top);
3a641a69
GM
1274 move_it_to (&it, charpos, 0, it.last_visible_y, -1,
1275 MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
a13be207
GM
1276
1277 /* Note that we may overshoot because of invisible text. */
1278 if (IT_CHARPOS (it) >= charpos)
3a641a69 1279 {
8b6ea97f
GM
1280 int top_y = it.current_y;
1281 int bottom_y = line_bottom_y (&it);
da8b7f4f 1282 int window_top_y = WINDOW_HEADER_LINE_HEIGHT (w);
2311178e 1283
8b6ea97f
GM
1284 if (top_y < window_top_y)
1285 visible_p = bottom_y > window_top_y;
1286 else if (top_y < it.last_visible_y)
fcab1954
GM
1287 {
1288 visible_p = 1;
8b6ea97f 1289 *fully = bottom_y <= it.last_visible_y;
fcab1954 1290 }
3a641a69
GM
1291 }
1292 else if (it.current_y + it.max_ascent + it.max_descent > it.last_visible_y)
1293 {
1294 move_it_by_lines (&it, 1, 0);
1295 if (charpos < IT_CHARPOS (it))
1296 {
1297 visible_p = 1;
1298 *fully = 0;
1299 }
1300 }
fcab1954
GM
1301
1302 if (old_buffer)
1303 set_buffer_internal_1 (old_buffer);
04612a64
GM
1304
1305 current_header_line_height = current_mode_line_height = -1;
3a641a69
GM
1306 return visible_p;
1307}
1308
1309
4fdb80f2
GM
1310/* Return the next character from STR which is MAXLEN bytes long.
1311 Return in *LEN the length of the character. This is like
1312 STRING_CHAR_AND_LENGTH but never returns an invalid character. If
9ab8560d 1313 we find one, we return a `?', but with the length of the invalid
4fdb80f2
GM
1314 character. */
1315
1316static INLINE int
7a5b8a93 1317string_char_and_length (str, maxlen, len)
50f80c2f 1318 const unsigned char *str;
7a5b8a93 1319 int maxlen, *len;
4fdb80f2
GM
1320{
1321 int c;
1322
1323 c = STRING_CHAR_AND_LENGTH (str, maxlen, *len);
1324 if (!CHAR_VALID_P (c, 1))
1325 /* We may not change the length here because other places in Emacs
9ab8560d 1326 don't use this function, i.e. they silently accept invalid
4fdb80f2
GM
1327 characters. */
1328 c = '?';
1329
1330 return c;
1331}
1332
1333
1334
5f5c8ee5
GM
1335/* Given a position POS containing a valid character and byte position
1336 in STRING, return the position NCHARS ahead (NCHARS >= 0). */
1337
1338static struct text_pos
1339string_pos_nchars_ahead (pos, string, nchars)
1340 struct text_pos pos;
1341 Lisp_Object string;
1342 int nchars;
0b1005ef 1343{
5f5c8ee5
GM
1344 xassert (STRINGP (string) && nchars >= 0);
1345
1346 if (STRING_MULTIBYTE (string))
1347 {
2051c264 1348 int rest = SBYTES (string) - BYTEPOS (pos);
50f80c2f 1349 const unsigned char *p = SDATA (string) + BYTEPOS (pos);
5f5c8ee5
GM
1350 int len;
1351
1352 while (nchars--)
1353 {
4fdb80f2 1354 string_char_and_length (p, rest, &len);
5f5c8ee5
GM
1355 p += len, rest -= len;
1356 xassert (rest >= 0);
1357 CHARPOS (pos) += 1;
1358 BYTEPOS (pos) += len;
1359 }
1360 }
1361 else
1362 SET_TEXT_POS (pos, CHARPOS (pos) + nchars, BYTEPOS (pos) + nchars);
1363
1364 return pos;
0a9dc68b
RS
1365}
1366
0a9dc68b 1367
5f5c8ee5
GM
1368/* Value is the text position, i.e. character and byte position,
1369 for character position CHARPOS in STRING. */
1370
1371static INLINE struct text_pos
1372string_pos (charpos, string)
1373 int charpos;
0a9dc68b 1374 Lisp_Object string;
0a9dc68b 1375{
5f5c8ee5
GM
1376 struct text_pos pos;
1377 xassert (STRINGP (string));
1378 xassert (charpos >= 0);
1379 SET_TEXT_POS (pos, charpos, string_char_to_byte (string, charpos));
1380 return pos;
1381}
1382
1383
1384/* Value is a text position, i.e. character and byte position, for
1385 character position CHARPOS in C string S. MULTIBYTE_P non-zero
1386 means recognize multibyte characters. */
1387
1388static struct text_pos
1389c_string_pos (charpos, s, multibyte_p)
1390 int charpos;
1391 unsigned char *s;
1392 int multibyte_p;
1393{
1394 struct text_pos pos;
1395
1396 xassert (s != NULL);
1397 xassert (charpos >= 0);
1398
1399 if (multibyte_p)
0a9dc68b 1400 {
5f5c8ee5
GM
1401 int rest = strlen (s), len;
1402
1403 SET_TEXT_POS (pos, 0, 0);
1404 while (charpos--)
0a9dc68b 1405 {
4fdb80f2 1406 string_char_and_length (s, rest, &len);
5f5c8ee5
GM
1407 s += len, rest -= len;
1408 xassert (rest >= 0);
1409 CHARPOS (pos) += 1;
1410 BYTEPOS (pos) += len;
0a9dc68b
RS
1411 }
1412 }
5f5c8ee5
GM
1413 else
1414 SET_TEXT_POS (pos, charpos, charpos);
0a9dc68b 1415
5f5c8ee5
GM
1416 return pos;
1417}
0a9dc68b 1418
0a9dc68b 1419
5f5c8ee5
GM
1420/* Value is the number of characters in C string S. MULTIBYTE_P
1421 non-zero means recognize multibyte characters. */
0a9dc68b 1422
5f5c8ee5
GM
1423static int
1424number_of_chars (s, multibyte_p)
1425 unsigned char *s;
1426 int multibyte_p;
1427{
1428 int nchars;
2311178e 1429
5f5c8ee5
GM
1430 if (multibyte_p)
1431 {
1432 int rest = strlen (s), len;
1433 unsigned char *p = (unsigned char *) s;
0a9dc68b 1434
5f5c8ee5
GM
1435 for (nchars = 0; rest > 0; ++nchars)
1436 {
4fdb80f2 1437 string_char_and_length (p, rest, &len);
5f5c8ee5 1438 rest -= len, p += len;
0a9dc68b
RS
1439 }
1440 }
5f5c8ee5
GM
1441 else
1442 nchars = strlen (s);
1443
1444 return nchars;
0b1005ef
KH
1445}
1446
2311178e 1447
5f5c8ee5
GM
1448/* Compute byte position NEWPOS->bytepos corresponding to
1449 NEWPOS->charpos. POS is a known position in string STRING.
1450 NEWPOS->charpos must be >= POS.charpos. */
76412d64 1451
5f5c8ee5
GM
1452static void
1453compute_string_pos (newpos, pos, string)
1454 struct text_pos *newpos, pos;
1455 Lisp_Object string;
76412d64 1456{
5f5c8ee5
GM
1457 xassert (STRINGP (string));
1458 xassert (CHARPOS (*newpos) >= CHARPOS (pos));
2311178e 1459
5f5c8ee5 1460 if (STRING_MULTIBYTE (string))
6fc556fd
KR
1461 *newpos = string_pos_nchars_ahead (pos, string,
1462 CHARPOS (*newpos) - CHARPOS (pos));
5f5c8ee5
GM
1463 else
1464 BYTEPOS (*newpos) = CHARPOS (*newpos);
76412d64
RS
1465}
1466
fa3c6b4d
KS
1467/* EXPORT:
1468 Return an estimation of the pixel height of mode or top lines on
1469 frame F. FACE_ID specifies what line's height to estimate. */
1470
1471int
1472estimate_mode_line_height (f, face_id)
1473 struct frame *f;
1474 enum face_id face_id;
1475{
1476#ifdef HAVE_WINDOW_SYSTEM
1477 if (FRAME_WINDOW_P (f))
1478 {
1479 int height = FONT_HEIGHT (FRAME_FONT (f));
1480
1481 /* This function is called so early when Emacs starts that the face
1482 cache and mode line face are not yet initialized. */
1483 if (FRAME_FACE_CACHE (f))
1484 {
1485 struct face *face = FACE_FROM_ID (f, face_id);
1486 if (face)
1487 {
1488 if (face->font)
1489 height = FONT_HEIGHT (face->font);
1490 if (face->box_line_width > 0)
1491 height += 2 * face->box_line_width;
1492 }
1493 }
1494
1495 return height;
1496 }
1497#endif
1498
1499 return 1;
1500}
1501
e080d3eb
KS
1502/* Given a pixel position (PIX_X, PIX_Y) on frame F, return glyph
1503 co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle that the
1504 glyph at X, Y occupies, if BOUNDS != 0. If NOCLIP is non-zero, do
1505 not force the value into range. */
1506
1507void
1508pixel_to_glyph_coords (f, pix_x, pix_y, x, y, bounds, noclip)
1509 FRAME_PTR f;
1510 register int pix_x, pix_y;
1511 int *x, *y;
1512 NativeRectangle *bounds;
1513 int noclip;
1514{
1515
1516#ifdef HAVE_WINDOW_SYSTEM
1517 if (FRAME_WINDOW_P (f))
1518 {
da8b7f4f 1519 /* Arrange for the division in FRAME_PIXEL_X_TO_COL etc. to round down
e080d3eb
KS
1520 even for negative values. */
1521 if (pix_x < 0)
da8b7f4f 1522 pix_x -= FRAME_COLUMN_WIDTH (f) - 1;
e080d3eb 1523 if (pix_y < 0)
da8b7f4f 1524 pix_y -= FRAME_LINE_HEIGHT (f) - 1;
e080d3eb 1525
da8b7f4f
KS
1526 pix_x = FRAME_PIXEL_X_TO_COL (f, pix_x);
1527 pix_y = FRAME_PIXEL_Y_TO_LINE (f, pix_y);
e080d3eb
KS
1528
1529 if (bounds)
1530 STORE_NATIVE_RECT (*bounds,
da8b7f4f
KS
1531 FRAME_COL_TO_PIXEL_X (f, pix_x),
1532 FRAME_LINE_TO_PIXEL_Y (f, pix_y),
1533 FRAME_COLUMN_WIDTH (f) - 1,
1534 FRAME_LINE_HEIGHT (f) - 1);
e080d3eb
KS
1535
1536 if (!noclip)
1537 {
1538 if (pix_x < 0)
1539 pix_x = 0;
da8b7f4f
KS
1540 else if (pix_x > FRAME_TOTAL_COLS (f))
1541 pix_x = FRAME_TOTAL_COLS (f);
e080d3eb
KS
1542
1543 if (pix_y < 0)
1544 pix_y = 0;
da8b7f4f
KS
1545 else if (pix_y > FRAME_LINES (f))
1546 pix_y = FRAME_LINES (f);
e080d3eb
KS
1547 }
1548 }
1549#endif
1550
1551 *x = pix_x;
1552 *y = pix_y;
1553}
1554
1555
1556/* Given HPOS/VPOS in the current matrix of W, return corresponding
1557 frame-relative pixel positions in *FRAME_X and *FRAME_Y. If we
1558 can't tell the positions because W's display is not up to date,
1559 return 0. */
1560
1561int
1562glyph_to_pixel_coords (w, hpos, vpos, frame_x, frame_y)
1563 struct window *w;
1564 int hpos, vpos;
1565 int *frame_x, *frame_y;
1566{
1567#ifdef HAVE_WINDOW_SYSTEM
1568 if (FRAME_WINDOW_P (XFRAME (WINDOW_FRAME (w))))
1569 {
1570 int success_p;
1571
1572 xassert (hpos >= 0 && hpos < w->current_matrix->matrix_w);
1573 xassert (vpos >= 0 && vpos < w->current_matrix->matrix_h);
1574
1575 if (display_completed)
1576 {
1577 struct glyph_row *row = MATRIX_ROW (w->current_matrix, vpos);
1578 struct glyph *glyph = row->glyphs[TEXT_AREA];
1579 struct glyph *end = glyph + min (hpos, row->used[TEXT_AREA]);
1580
1581 hpos = row->x;
1582 vpos = row->y;
1583 while (glyph < end)
1584 {
1585 hpos += glyph->pixel_width;
1586 ++glyph;
1587 }
1588
6b61353c
KH
1589 /* If first glyph is partially visible, its first visible position is still 0. */
1590 if (hpos < 0)
1591 hpos = 0;
1592
e080d3eb
KS
1593 success_p = 1;
1594 }
1595 else
1596 {
1597 hpos = vpos = 0;
1598 success_p = 0;
1599 }
1600
1601 *frame_x = WINDOW_TO_FRAME_PIXEL_X (w, hpos);
1602 *frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, vpos);
1603 return success_p;
1604 }
1605#endif
1606
1607 *frame_x = hpos;
1608 *frame_y = vpos;
1609 return 1;
1610}
1611
1612
fa3c6b4d
KS
1613#ifdef HAVE_WINDOW_SYSTEM
1614
1615/* Find the glyph under window-relative coordinates X/Y in window W.
1616 Consider only glyphs from buffer text, i.e. no glyphs from overlay
1617 strings. Return in *HPOS and *VPOS the row and column number of
1618 the glyph found. Return in *AREA the glyph area containing X.
1619 Value is a pointer to the glyph found or null if X/Y is not on
1620 text, or we can't tell because W's current matrix is not up to
1621 date. */
1622
1623static struct glyph *
6b61353c 1624x_y_to_hpos_vpos (w, x, y, hpos, vpos, dx, dy, area)
fa3c6b4d
KS
1625 struct window *w;
1626 int x, y;
6b61353c 1627 int *hpos, *vpos, *dx, *dy, *area;
fa3c6b4d
KS
1628{
1629 struct glyph *glyph, *end;
1630 struct glyph_row *row = NULL;
da8b7f4f 1631 int x0, i;
fa3c6b4d
KS
1632
1633 /* Find row containing Y. Give up if some row is not enabled. */
1634 for (i = 0; i < w->current_matrix->nrows; ++i)
1635 {
1636 row = MATRIX_ROW (w->current_matrix, i);
1637 if (!row->enabled_p)
1638 return NULL;
1639 if (y >= row->y && y < MATRIX_ROW_BOTTOM_Y (row))
1640 break;
1641 }
1642
1643 *vpos = i;
1644 *hpos = 0;
1645
1646 /* Give up if Y is not in the window. */
1647 if (i == w->current_matrix->nrows)
1648 return NULL;
1649
1650 /* Get the glyph area containing X. */
1651 if (w->pseudo_window_p)
1652 {
1653 *area = TEXT_AREA;
1654 x0 = 0;
1655 }
1656 else
1657 {
da8b7f4f 1658 if (x < window_box_left_offset (w, TEXT_AREA))
fa3c6b4d
KS
1659 {
1660 *area = LEFT_MARGIN_AREA;
da8b7f4f 1661 x0 = window_box_left_offset (w, LEFT_MARGIN_AREA);
fa3c6b4d 1662 }
da8b7f4f 1663 else if (x < window_box_right_offset (w, TEXT_AREA))
fa3c6b4d
KS
1664 {
1665 *area = TEXT_AREA;
6b61353c 1666 x0 = window_box_left_offset (w, TEXT_AREA) + min (row->x, 0);
fa3c6b4d
KS
1667 }
1668 else
1669 {
1670 *area = RIGHT_MARGIN_AREA;
da8b7f4f 1671 x0 = window_box_left_offset (w, RIGHT_MARGIN_AREA);
fa3c6b4d
KS
1672 }
1673 }
1674
1675 /* Find glyph containing X. */
1676 glyph = row->glyphs[*area];
1677 end = glyph + row->used[*area];
6b61353c
KH
1678 x -= x0;
1679 while (glyph < end && x >= glyph->pixel_width)
fa3c6b4d 1680 {
6b61353c 1681 x -= glyph->pixel_width;
fa3c6b4d
KS
1682 ++glyph;
1683 }
1684
1685 if (glyph == end)
1686 return NULL;
1687
6b61353c
KH
1688 if (dx)
1689 {
1690 *dx = x;
1691 *dy = y - (row->y + row->ascent - glyph->ascent);
1692 }
1693
fa3c6b4d
KS
1694 *hpos = glyph - row->glyphs[*area];
1695 return glyph;
1696}
1697
1698
1699/* EXPORT:
1700 Convert frame-relative x/y to coordinates relative to window W.
1701 Takes pseudo-windows into account. */
1702
1703void
1704frame_to_window_pixel_xy (w, x, y)
1705 struct window *w;
1706 int *x, *y;
1707{
1708 if (w->pseudo_window_p)
1709 {
1710 /* A pseudo-window is always full-width, and starts at the
1711 left edge of the frame, plus a frame border. */
1712 struct frame *f = XFRAME (w->frame);
da8b7f4f 1713 *x -= FRAME_INTERNAL_BORDER_WIDTH (f);
fa3c6b4d
KS
1714 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
1715 }
1716 else
1717 {
da8b7f4f 1718 *x -= WINDOW_LEFT_EDGE_X (w);
fa3c6b4d
KS
1719 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
1720 }
1721}
1722
1723/* EXPORT:
1724 Return in *R the clipping rectangle for glyph string S. */
1725
1726void
1727get_glyph_string_clip_rect (s, nr)
1728 struct glyph_string *s;
1729 NativeRectangle *nr;
1730{
1731 XRectangle r;
1732
1733 if (s->row->full_width_p)
1734 {
da8b7f4f
KS
1735 /* Draw full-width. X coordinates are relative to S->w->left_col. */
1736 r.x = WINDOW_LEFT_EDGE_X (s->w);
1737 r.width = WINDOW_TOTAL_WIDTH (s->w);
fa3c6b4d
KS
1738
1739 /* Unless displaying a mode or menu bar line, which are always
1740 fully visible, clip to the visible part of the row. */
1741 if (s->w->pseudo_window_p)
1742 r.height = s->row->visible_height;
1743 else
1744 r.height = s->height;
1745 }
1746 else
1747 {
1748 /* This is a text line that may be partially visible. */
da8b7f4f 1749 r.x = window_box_left (s->w, s->area);
fa3c6b4d
KS
1750 r.width = window_box_width (s->w, s->area);
1751 r.height = s->row->visible_height;
1752 }
1753
1754 /* If S draws overlapping rows, it's sufficient to use the top and
1755 bottom of the window for clipping because this glyph string
1756 intentionally draws over other lines. */
1757 if (s->for_overlaps_p)
1758 {
da8b7f4f 1759 r.y = WINDOW_HEADER_LINE_HEIGHT (s->w);
fa3c6b4d
KS
1760 r.height = window_text_bottom_y (s->w) - r.y;
1761 }
1762 else
1763 {
1764 /* Don't use S->y for clipping because it doesn't take partially
1765 visible lines into account. For example, it can be negative for
1766 partially visible lines at the top of a window. */
1767 if (!s->row->full_width_p
1768 && MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (s->w, s->row))
da8b7f4f 1769 r.y = WINDOW_HEADER_LINE_HEIGHT (s->w);
fa3c6b4d
KS
1770 else
1771 r.y = max (0, s->row->y);
1772
1773 /* If drawing a tool-bar window, draw it over the internal border
1774 at the top of the window. */
1775 if (s->w == XWINDOW (s->f->tool_bar_window))
b4ebbb12 1776 r.y -= FRAME_INTERNAL_BORDER_WIDTH (s->f);
fa3c6b4d
KS
1777 }
1778
1779 r.y = WINDOW_TO_FRAME_PIXEL_Y (s->w, r.y);
1780
fa3c6b4d
KS
1781 /* If drawing the cursor, don't let glyph draw outside its
1782 advertised boundaries. Cleartype does this under some circumstances. */
1783 if (s->hl == DRAW_CURSOR)
1784 {
6b61353c
KH
1785 struct glyph *glyph = s->first_glyph;
1786 int height;
1787
fa3c6b4d
KS
1788 if (s->x > r.x)
1789 {
1790 r.width -= s->x - r.x;
1791 r.x = s->x;
1792 }
6b61353c
KH
1793 r.width = min (r.width, glyph->pixel_width);
1794
1795 /* Don't draw cursor glyph taller than our actual glyph. */
1796 height = max (FRAME_LINE_HEIGHT (s->f), glyph->ascent + glyph->descent);
1797 if (height < r.height)
1798 {
1799 int max_y = r.y + r.height;
1800 r.y = min (max_y, s->ybase + glyph->descent - height);
1801 r.height = min (max_y - r.y, height);
1802 }
fa3c6b4d 1803 }
fa3c6b4d
KS
1804
1805#ifdef CONVERT_FROM_XRECT
1806 CONVERT_FROM_XRECT (r, *nr);
1807#else
1808 *nr = r;
fd4c9408 1809#endif
fa3c6b4d
KS
1810}
1811
1812#endif /* HAVE_WINDOW_SYSTEM */
9c74a0dd 1813
5f5c8ee5
GM
1814\f
1815/***********************************************************************
1816 Lisp form evaluation
1817 ***********************************************************************/
1818
116d6f5c 1819/* Error handler for safe_eval and safe_call. */
5f5c8ee5
GM
1820
1821static Lisp_Object
116d6f5c 1822safe_eval_handler (arg)
5f5c8ee5
GM
1823 Lisp_Object arg;
1824{
0dbf9fd2 1825 add_to_log ("Error during redisplay: %s", arg, Qnil);
5f5c8ee5
GM
1826 return Qnil;
1827}
1828
1829
1830/* Evaluate SEXPR and return the result, or nil if something went
2913a9c0 1831 wrong. Prevent redisplay during the evaluation. */
5f5c8ee5 1832
71e5b1b8 1833Lisp_Object
116d6f5c 1834safe_eval (sexpr)
5f5c8ee5
GM
1835 Lisp_Object sexpr;
1836{
5f5c8ee5 1837 Lisp_Object val;
2311178e 1838
30a3f61c
GM
1839 if (inhibit_eval_during_redisplay)
1840 val = Qnil;
1841 else
1842 {
331379bf 1843 int count = SPECPDL_INDEX ();
30a3f61c 1844 struct gcpro gcpro1;
0d8b31c0 1845
30a3f61c
GM
1846 GCPRO1 (sexpr);
1847 specbind (Qinhibit_redisplay, Qt);
7033d6df
RS
1848 /* Use Qt to ensure debugger does not run,
1849 so there is no possibility of wanting to redisplay. */
1850 val = internal_condition_case_1 (Feval, sexpr, Qt,
30a3f61c
GM
1851 safe_eval_handler);
1852 UNGCPRO;
1853 val = unbind_to (count, val);
1854 }
2311178e 1855
30a3f61c 1856 return val;
0d8b31c0
GM
1857}
1858
1859
1860/* Call function ARGS[0] with arguments ARGS[1] to ARGS[NARGS - 1].
2913a9c0
GM
1861 Return the result, or nil if something went wrong. Prevent
1862 redisplay during the evaluation. */
0d8b31c0
GM
1863
1864Lisp_Object
116d6f5c 1865safe_call (nargs, args)
0d8b31c0
GM
1866 int nargs;
1867 Lisp_Object *args;
1868{
0d8b31c0 1869 Lisp_Object val;
2311178e 1870
30a3f61c
GM
1871 if (inhibit_eval_during_redisplay)
1872 val = Qnil;
1873 else
1874 {
331379bf 1875 int count = SPECPDL_INDEX ();
30a3f61c 1876 struct gcpro gcpro1;
0d8b31c0 1877
30a3f61c
GM
1878 GCPRO1 (args[0]);
1879 gcpro1.nvars = nargs;
1880 specbind (Qinhibit_redisplay, Qt);
7033d6df
RS
1881 /* Use Qt to ensure debugger does not run,
1882 so there is no possibility of wanting to redisplay. */
1883 val = internal_condition_case_2 (Ffuncall, nargs, args, Qt,
30a3f61c
GM
1884 safe_eval_handler);
1885 UNGCPRO;
1886 val = unbind_to (count, val);
1887 }
1888
1889 return val;
5f5c8ee5
GM
1890}
1891
1892
116d6f5c
GM
1893/* Call function FN with one argument ARG.
1894 Return the result, or nil if something went wrong. */
1895
1896Lisp_Object
1897safe_call1 (fn, arg)
1898 Lisp_Object fn, arg;
1899{
1900 Lisp_Object args[2];
1901 args[0] = fn;
1902 args[1] = arg;
1903 return safe_call (2, args);
1904}
1905
1906
5f5c8ee5
GM
1907\f
1908/***********************************************************************
1909 Debugging
1910 ***********************************************************************/
1911
1912#if 0
1913
1914/* Define CHECK_IT to perform sanity checks on iterators.
1915 This is for debugging. It is too slow to do unconditionally. */
1916
1917static void
1918check_it (it)
1919 struct it *it;
1920{
1921 if (it->method == next_element_from_string)
a2889657 1922 {
5f5c8ee5
GM
1923 xassert (STRINGP (it->string));
1924 xassert (IT_STRING_CHARPOS (*it) >= 0);
1925 }
6b61353c 1926 else
5f5c8ee5 1927 {
6b61353c
KH
1928 xassert (IT_STRING_CHARPOS (*it) < 0);
1929 if (it->method == next_element_from_buffer)
1930 {
1931 /* Check that character and byte positions agree. */
1932 xassert (IT_CHARPOS (*it) == BYTE_TO_CHAR (IT_BYTEPOS (*it)));
1933 }
5f5c8ee5 1934 }
73af359d 1935
5f5c8ee5
GM
1936 if (it->dpvec)
1937 xassert (it->current.dpvec_index >= 0);
1938 else
1939 xassert (it->current.dpvec_index < 0);
1940}
1f40cad2 1941
5f5c8ee5
GM
1942#define CHECK_IT(IT) check_it ((IT))
1943
1944#else /* not 0 */
1945
1946#define CHECK_IT(IT) (void) 0
1947
1948#endif /* not 0 */
1949
1950
1951#if GLYPH_DEBUG
1952
1953/* Check that the window end of window W is what we expect it
1954 to be---the last row in the current matrix displaying text. */
1955
1956static void
1957check_window_end (w)
1958 struct window *w;
1959{
1960 if (!MINI_WINDOW_P (w)
1961 && !NILP (w->window_end_valid))
1962 {
1963 struct glyph_row *row;
1964 xassert ((row = MATRIX_ROW (w->current_matrix,
1965 XFASTINT (w->window_end_vpos)),
1966 !row->enabled_p
1967 || MATRIX_ROW_DISPLAYS_TEXT_P (row)
1968 || MATRIX_ROW_VPOS (row, w->current_matrix) == 0));
1969 }
1970}
1971
1972#define CHECK_WINDOW_END(W) check_window_end ((W))
1973
1974#else /* not GLYPH_DEBUG */
1975
1976#define CHECK_WINDOW_END(W) (void) 0
1977
1978#endif /* not GLYPH_DEBUG */
1979
1980
1981\f
1982/***********************************************************************
1983 Iterator initialization
1984 ***********************************************************************/
1985
1986/* Initialize IT for displaying current_buffer in window W, starting
1987 at character position CHARPOS. CHARPOS < 0 means that no buffer
1988 position is specified which is useful when the iterator is assigned
1989 a position later. BYTEPOS is the byte position corresponding to
3ebf0ea9 1990 CHARPOS. BYTEPOS < 0 means compute it from CHARPOS.
5f5c8ee5
GM
1991
1992 If ROW is not null, calls to produce_glyphs with IT as parameter
1993 will produce glyphs in that row.
1994
1995 BASE_FACE_ID is the id of a base face to use. It must be one of
96d2320f
KS
1996 DEFAULT_FACE_ID for normal text, MODE_LINE_FACE_ID,
1997 MODE_LINE_INACTIVE_FACE_ID, or HEADER_LINE_FACE_ID for displaying
1998 mode lines, or TOOL_BAR_FACE_ID for displaying the tool-bar.
2311178e 1999
96d2320f
KS
2000 If ROW is null and BASE_FACE_ID is equal to MODE_LINE_FACE_ID,
2001 MODE_LINE_INACTIVE_FACE_ID, or HEADER_LINE_FACE_ID, the iterator
2002 will be initialized to use the corresponding mode line glyph row of
2003 the desired matrix of W. */
5f5c8ee5
GM
2004
2005void
2006init_iterator (it, w, charpos, bytepos, row, base_face_id)
2007 struct it *it;
2008 struct window *w;
2009 int charpos, bytepos;
2010 struct glyph_row *row;
2011 enum face_id base_face_id;
2012{
2013 int highlight_region_p;
5f5c8ee5
GM
2014
2015 /* Some precondition checks. */
2016 xassert (w != NULL && it != NULL);
3b6b6db7
SM
2017 xassert (charpos < 0 || (charpos >= BUF_BEG (current_buffer)
2018 && charpos <= ZV));
5f5c8ee5
GM
2019
2020 /* If face attributes have been changed since the last redisplay,
2021 free realized faces now because they depend on face definitions
7d0393cf 2022 that might have changed. Don't free faces while there might be
1987b083 2023 desired matrices pending which reference these faces. */
26683087 2024 if (face_change_count && !inhibit_free_realized_faces)
5f5c8ee5
GM
2025 {
2026 face_change_count = 0;
2027 free_all_realized_faces (Qnil);
2028 }
2029
2030 /* Use one of the mode line rows of W's desired matrix if
2031 appropriate. */
2032 if (row == NULL)
2033 {
96d2320f
KS
2034 if (base_face_id == MODE_LINE_FACE_ID
2035 || base_face_id == MODE_LINE_INACTIVE_FACE_ID)
5f5c8ee5 2036 row = MATRIX_MODE_LINE_ROW (w->desired_matrix);
045dee35
GM
2037 else if (base_face_id == HEADER_LINE_FACE_ID)
2038 row = MATRIX_HEADER_LINE_ROW (w->desired_matrix);
5f5c8ee5 2039 }
2311178e 2040
5f5c8ee5
GM
2041 /* Clear IT. */
2042 bzero (it, sizeof *it);
2043 it->current.overlay_string_index = -1;
2044 it->current.dpvec_index = -1;
5f5c8ee5 2045 it->base_face_id = base_face_id;
6b61353c
KH
2046 it->string = Qnil;
2047 IT_STRING_CHARPOS (*it) = IT_STRING_BYTEPOS (*it) = -1;
5f5c8ee5
GM
2048
2049 /* The window in which we iterate over current_buffer: */
2050 XSETWINDOW (it->window, w);
2051 it->w = w;
2052 it->f = XFRAME (w->frame);
2053
d475bcb8
GM
2054 /* Extra space between lines (on window systems only). */
2055 if (base_face_id == DEFAULT_FACE_ID
2056 && FRAME_WINDOW_P (it->f))
2057 {
2058 if (NATNUMP (current_buffer->extra_line_spacing))
2059 it->extra_line_spacing = XFASTINT (current_buffer->extra_line_spacing);
2060 else if (it->f->extra_line_spacing > 0)
2061 it->extra_line_spacing = it->f->extra_line_spacing;
2062 }
2063
5f5c8ee5 2064 /* If realized faces have been removed, e.g. because of face
62be9979
GM
2065 attribute changes of named faces, recompute them. When running
2066 in batch mode, the face cache of Vterminal_frame is null. If
2067 we happen to get called, make a dummy face cache. */
6b61353c 2068 if (noninteractive && FRAME_FACE_CACHE (it->f) == NULL)
62be9979 2069 init_frame_faces (it->f);
5f5c8ee5
GM
2070 if (FRAME_FACE_CACHE (it->f)->used == 0)
2071 recompute_basic_faces (it->f);
2072
5f5c8ee5
GM
2073 /* Current value of the `space-width', and 'height' properties. */
2074 it->space_width = Qnil;
2075 it->font_height = Qnil;
2311178e 2076
5f5c8ee5
GM
2077 /* Are control characters displayed as `^C'? */
2078 it->ctl_arrow_p = !NILP (current_buffer->ctl_arrow);
2079
2080 /* -1 means everything between a CR and the following line end
2081 is invisible. >0 means lines indented more than this value are
2082 invisible. */
2083 it->selective = (INTEGERP (current_buffer->selective_display)
2084 ? XFASTINT (current_buffer->selective_display)
2311178e 2085 : (!NILP (current_buffer->selective_display)
5f5c8ee5
GM
2086 ? -1 : 0));
2087 it->selective_display_ellipsis_p
2088 = !NILP (current_buffer->selective_display_ellipses);
2089
2090 /* Display table to use. */
2091 it->dp = window_display_table (w);
2092
2093 /* Are multibyte characters enabled in current_buffer? */
2094 it->multibyte_p = !NILP (current_buffer->enable_multibyte_characters);
2095
2096 /* Non-zero if we should highlight the region. */
2097 highlight_region_p
3ebf0ea9 2098 = (!NILP (Vtransient_mark_mode)
5f5c8ee5
GM
2099 && !NILP (current_buffer->mark_active)
2100 && XMARKER (current_buffer->mark)->buffer != 0);
2101
2102 /* Set IT->region_beg_charpos and IT->region_end_charpos to the
2103 start and end of a visible region in window IT->w. Set both to
2104 -1 to indicate no region. */
2105 if (highlight_region_p
2106 /* Maybe highlight only in selected window. */
2311178e 2107 && (/* Either show region everywhere. */
5f5c8ee5
GM
2108 highlight_nonselected_windows
2109 /* Or show region in the selected window. */
2110 || w == XWINDOW (selected_window)
2111 /* Or show the region if we are in the mini-buffer and W is
2112 the window the mini-buffer refers to. */
2113 || (MINI_WINDOW_P (XWINDOW (selected_window))
5705966b
KS
2114 && WINDOWP (minibuf_selected_window)
2115 && w == XWINDOW (minibuf_selected_window))))
5f5c8ee5
GM
2116 {
2117 int charpos = marker_position (current_buffer->mark);
2118 it->region_beg_charpos = min (PT, charpos);
2119 it->region_end_charpos = max (PT, charpos);
2120 }
2121 else
2122 it->region_beg_charpos = it->region_end_charpos = -1;
2123
2124 /* Get the position at which the redisplay_end_trigger hook should
2125 be run, if it is to be run at all. */
2126 if (MARKERP (w->redisplay_end_trigger)
2127 && XMARKER (w->redisplay_end_trigger)->buffer != 0)
2128 it->redisplay_end_trigger_charpos
2129 = marker_position (w->redisplay_end_trigger);
2130 else if (INTEGERP (w->redisplay_end_trigger))
2131 it->redisplay_end_trigger_charpos = XINT (w->redisplay_end_trigger);
2132
2133 /* Correct bogus values of tab_width. */
2134 it->tab_width = XINT (current_buffer->tab_width);
2135 if (it->tab_width <= 0 || it->tab_width > 1000)
2136 it->tab_width = 8;
2137
2138 /* Are lines in the display truncated? */
2139 it->truncate_lines_p
2140 = (base_face_id != DEFAULT_FACE_ID
2141 || XINT (it->w->hscroll)
2142 || (truncate_partial_width_windows
2143 && !WINDOW_FULL_WIDTH_P (it->w))
2144 || !NILP (current_buffer->truncate_lines));
2145
2146 /* Get dimensions of truncation and continuation glyphs. These are
b46952ae 2147 displayed as fringe bitmaps under X, so we don't need them for such
5f5c8ee5
GM
2148 frames. */
2149 if (!FRAME_WINDOW_P (it->f))
2150 {
2151 if (it->truncate_lines_p)
2152 {
2153 /* We will need the truncation glyph. */
2154 xassert (it->glyph_row == NULL);
2155 produce_special_glyphs (it, IT_TRUNCATION);
2156 it->truncation_pixel_width = it->pixel_width;
2157 }
2158 else
2159 {
2160 /* We will need the continuation glyph. */
2161 xassert (it->glyph_row == NULL);
2162 produce_special_glyphs (it, IT_CONTINUATION);
2163 it->continuation_pixel_width = it->pixel_width;
2164 }
2165
153c2160 2166 /* Reset these values to zero because the produce_special_glyphs
5f5c8ee5
GM
2167 above has changed them. */
2168 it->pixel_width = it->ascent = it->descent = 0;
312246d1 2169 it->phys_ascent = it->phys_descent = 0;
5f5c8ee5
GM
2170 }
2171
2172 /* Set this after getting the dimensions of truncation and
2173 continuation glyphs, so that we don't produce glyphs when calling
2174 produce_special_glyphs, above. */
2175 it->glyph_row = row;
2176 it->area = TEXT_AREA;
2177
2178 /* Get the dimensions of the display area. The display area
2179 consists of the visible window area plus a horizontally scrolled
2180 part to the left of the window. All x-values are relative to the
2181 start of this total display area. */
2182 if (base_face_id != DEFAULT_FACE_ID)
2183 {
2184 /* Mode lines, menu bar in terminal frames. */
2185 it->first_visible_x = 0;
da8b7f4f 2186 it->last_visible_x = WINDOW_TOTAL_WIDTH (w);
5f5c8ee5
GM
2187 }
2188 else
2189 {
2190 it->first_visible_x
da8b7f4f 2191 = XFASTINT (it->w->hscroll) * FRAME_COLUMN_WIDTH (it->f);
5f5c8ee5
GM
2192 it->last_visible_x = (it->first_visible_x
2193 + window_box_width (w, TEXT_AREA));
2194
2195 /* If we truncate lines, leave room for the truncator glyph(s) at
2196 the right margin. Otherwise, leave room for the continuation
2197 glyph(s). Truncation and continuation glyphs are not inserted
2198 for window-based redisplay. */
2199 if (!FRAME_WINDOW_P (it->f))
2200 {
2201 if (it->truncate_lines_p)
2202 it->last_visible_x -= it->truncation_pixel_width;
2203 else
2204 it->last_visible_x -= it->continuation_pixel_width;
2205 }
2206
045dee35 2207 it->header_line_p = WINDOW_WANTS_HEADER_LINE_P (w);
da8b7f4f 2208 it->current_y = WINDOW_HEADER_LINE_HEIGHT (w) + w->vscroll;
5f5c8ee5
GM
2209 }
2210
2211 /* Leave room for a border glyph. */
2212 if (!FRAME_WINDOW_P (it->f)
2213 && !WINDOW_RIGHTMOST_P (it->w))
2214 it->last_visible_x -= 1;
2215
2216 it->last_visible_y = window_text_bottom_y (w);
2217
2218 /* For mode lines and alike, arrange for the first glyph having a
2219 left box line if the face specifies a box. */
2220 if (base_face_id != DEFAULT_FACE_ID)
2221 {
2222 struct face *face;
2311178e 2223
5f5c8ee5
GM
2224 it->face_id = base_face_id;
2225
2226 /* If we have a boxed mode line, make the first character appear
2227 with a left box line. */
2228 face = FACE_FROM_ID (it->f, base_face_id);
2229 if (face->box != FACE_NO_BOX)
2230 it->start_of_box_run_p = 1;
2231 }
2232
2233 /* If a buffer position was specified, set the iterator there,
2234 getting overlays and face properties from that position. */
3ebf0ea9 2235 if (charpos >= BUF_BEG (current_buffer))
5f5c8ee5
GM
2236 {
2237 it->end_charpos = ZV;
2238 it->face_id = -1;
2239 IT_CHARPOS (*it) = charpos;
2311178e 2240
5f5c8ee5 2241 /* Compute byte position if not specified. */
3ebf0ea9 2242 if (bytepos < charpos)
5f5c8ee5
GM
2243 IT_BYTEPOS (*it) = CHAR_TO_BYTE (charpos);
2244 else
2245 IT_BYTEPOS (*it) = bytepos;
2246
6b61353c
KH
2247 it->start = it->current;
2248
5f5c8ee5
GM
2249 /* Compute faces etc. */
2250 reseat (it, it->current.pos, 1);
2251 }
2311178e 2252
5f5c8ee5
GM
2253 CHECK_IT (it);
2254}
2255
2256
2257/* Initialize IT for the display of window W with window start POS. */
2258
2259void
2260start_display (it, w, pos)
2261 struct it *it;
2262 struct window *w;
2263 struct text_pos pos;
2264{
5f5c8ee5 2265 struct glyph_row *row;
045dee35 2266 int first_vpos = WINDOW_WANTS_HEADER_LINE_P (w) ? 1 : 0;
5f5c8ee5
GM
2267
2268 row = w->desired_matrix->rows + first_vpos;
2269 init_iterator (it, w, CHARPOS (pos), BYTEPOS (pos), row, DEFAULT_FACE_ID);
6b61353c 2270 it->first_vpos = first_vpos;
17fdcfc8
GM
2271
2272 if (!it->truncate_lines_p)
5f5c8ee5 2273 {
17fdcfc8
GM
2274 int start_at_line_beg_p;
2275 int first_y = it->current_y;
2311178e 2276
17fdcfc8
GM
2277 /* If window start is not at a line start, skip forward to POS to
2278 get the correct continuation lines width. */
2279 start_at_line_beg_p = (CHARPOS (pos) == BEGV
2280 || FETCH_BYTE (BYTEPOS (pos) - 1) == '\n');
2281 if (!start_at_line_beg_p)
5f5c8ee5 2282 {
0e47bbf7
RS
2283 int new_x;
2284
17fdcfc8
GM
2285 reseat_at_previous_visible_line_start (it);
2286 move_it_to (it, CHARPOS (pos), -1, -1, -1, MOVE_TO_POS);
2287
0e47bbf7
RS
2288 new_x = it->current_x + it->pixel_width;
2289
17fdcfc8
GM
2290 /* If lines are continued, this line may end in the middle
2291 of a multi-glyph character (e.g. a control character
2292 displayed as \003, or in the middle of an overlay
2293 string). In this case move_it_to above will not have
2294 taken us to the start of the continuation line but to the
2295 end of the continued line. */
0e47bbf7
RS
2296 if (it->current_x > 0
2297 && !it->truncate_lines_p /* Lines are continued. */
2298 && (/* And glyph doesn't fit on the line. */
2299 new_x > it->last_visible_x
2300 /* Or it fits exactly and we're on a window
2301 system frame. */
2302 || (new_x == it->last_visible_x
2303 && FRAME_WINDOW_P (it->f))))
5f5c8ee5 2304 {
b28cb6ed
GM
2305 if (it->current.dpvec_index >= 0
2306 || it->current.overlay_string_index >= 0)
2307 {
cafafe0b 2308 set_iterator_to_next (it, 1);
b28cb6ed
GM
2309 move_it_in_display_line_to (it, -1, -1, 0);
2310 }
2311178e 2311
b28cb6ed 2312 it->continuation_lines_width += it->current_x;
5f5c8ee5 2313 }
b28cb6ed
GM
2314
2315 /* We're starting a new display line, not affected by the
2316 height of the continued line, so clear the appropriate
2317 fields in the iterator structure. */
2318 it->max_ascent = it->max_descent = 0;
2319 it->max_phys_ascent = it->max_phys_descent = 0;
2311178e 2320
17fdcfc8
GM
2321 it->current_y = first_y;
2322 it->vpos = 0;
2323 it->current_x = it->hpos = 0;
2324 }
5f5c8ee5
GM
2325 }
2326
2327#if 0 /* Don't assert the following because start_display is sometimes
2328 called intentionally with a window start that is not at a
2329 line start. Please leave this code in as a comment. */
2311178e 2330
5f5c8ee5
GM
2331 /* Window start should be on a line start, now. */
2332 xassert (it->continuation_lines_width
2333 || IT_CHARPOS (it) == BEGV
2334 || FETCH_BYTE (IT_BYTEPOS (it) - 1) == '\n');
2335#endif /* 0 */
2336}
2337
2338
4bde0ebb
GM
2339/* Return 1 if POS is a position in ellipses displayed for invisible
2340 text. W is the window we display, for text property lookup. */
5f5c8ee5 2341
4bde0ebb
GM
2342static int
2343in_ellipses_for_invisible_text_p (pos, w)
5f5c8ee5 2344 struct display_pos *pos;
4bde0ebb 2345 struct window *w;
5f5c8ee5 2346{
ac90c44f 2347 Lisp_Object prop, window;
4bde0ebb
GM
2348 int ellipses_p = 0;
2349 int charpos = CHARPOS (pos->pos);
2311178e 2350
ac90c44f
GM
2351 /* If POS specifies a position in a display vector, this might
2352 be for an ellipsis displayed for invisible text. We won't
2353 get the iterator set up for delivering that ellipsis unless
2354 we make sure that it gets aware of the invisible text. */
2355 if (pos->dpvec_index >= 0
2356 && pos->overlay_string_index < 0
2357 && CHARPOS (pos->string_pos) < 0
2358 && charpos > BEGV
2359 && (XSETWINDOW (window, w),
2360 prop = Fget_char_property (make_number (charpos),
2361 Qinvisible, window),
20fbd925 2362 !TEXT_PROP_MEANS_INVISIBLE (prop)))
ac90c44f
GM
2363 {
2364 prop = Fget_char_property (make_number (charpos - 1), Qinvisible,
2365 window);
8580a4e3 2366 ellipses_p = 2 == TEXT_PROP_MEANS_INVISIBLE (prop);
4bde0ebb
GM
2367 }
2368
2369 return ellipses_p;
2370}
2371
2372
2373/* Initialize IT for stepping through current_buffer in window W,
2374 starting at position POS that includes overlay string and display
47d57b22
GM
2375 vector/ control character translation position information. Value
2376 is zero if there are overlay strings with newlines at POS. */
4bde0ebb 2377
47d57b22 2378static int
4bde0ebb
GM
2379init_from_display_pos (it, w, pos)
2380 struct it *it;
2381 struct window *w;
2382 struct display_pos *pos;
2383{
2384 int charpos = CHARPOS (pos->pos), bytepos = BYTEPOS (pos->pos);
47d57b22 2385 int i, overlay_strings_with_newlines = 0;
2311178e 2386
4bde0ebb
GM
2387 /* If POS specifies a position in a display vector, this might
2388 be for an ellipsis displayed for invisible text. We won't
2389 get the iterator set up for delivering that ellipsis unless
2390 we make sure that it gets aware of the invisible text. */
2391 if (in_ellipses_for_invisible_text_p (pos, w))
2392 {
2393 --charpos;
2394 bytepos = 0;
ac90c44f 2395 }
2311178e 2396
5f5c8ee5
GM
2397 /* Keep in mind: the call to reseat in init_iterator skips invisible
2398 text, so we might end up at a position different from POS. This
2399 is only a problem when POS is a row start after a newline and an
2400 overlay starts there with an after-string, and the overlay has an
2401 invisible property. Since we don't skip invisible text in
2402 display_line and elsewhere immediately after consuming the
2403 newline before the row start, such a POS will not be in a string,
2404 but the call to init_iterator below will move us to the
2405 after-string. */
ac90c44f 2406 init_iterator (it, w, charpos, bytepos, NULL, DEFAULT_FACE_ID);
5f5c8ee5 2407
47d57b22 2408 for (i = 0; i < it->n_overlay_strings; ++i)
1e1e5daf 2409 {
50f80c2f
KR
2410 const char *s = SDATA (it->overlay_strings[i]);
2411 const char *e = s + SBYTES (it->overlay_strings[i]);
2311178e 2412
1e1e5daf
GM
2413 while (s < e && *s != '\n')
2414 ++s;
2415
2416 if (s < e)
2417 {
2418 overlay_strings_with_newlines = 1;
2419 break;
2420 }
2421 }
47d57b22 2422
75c5350a
GM
2423 /* If position is within an overlay string, set up IT to the right
2424 overlay string. */
5f5c8ee5
GM
2425 if (pos->overlay_string_index >= 0)
2426 {
2427 int relative_index;
75c5350a
GM
2428
2429 /* If the first overlay string happens to have a `display'
2430 property for an image, the iterator will be set up for that
2431 image, and we have to undo that setup first before we can
2432 correct the overlay string index. */
2433 if (it->method == next_element_from_image)
2434 pop_it (it);
2311178e 2435
5f5c8ee5
GM
2436 /* We already have the first chunk of overlay strings in
2437 IT->overlay_strings. Load more until the one for
2438 pos->overlay_string_index is in IT->overlay_strings. */
2439 if (pos->overlay_string_index >= OVERLAY_STRING_CHUNK_SIZE)
2440 {
2441 int n = pos->overlay_string_index / OVERLAY_STRING_CHUNK_SIZE;
2442 it->current.overlay_string_index = 0;
2443 while (n--)
2444 {
5a08cbaf 2445 load_overlay_strings (it, 0);
5f5c8ee5
GM
2446 it->current.overlay_string_index += OVERLAY_STRING_CHUNK_SIZE;
2447 }
2448 }
2311178e 2449
5f5c8ee5
GM
2450 it->current.overlay_string_index = pos->overlay_string_index;
2451 relative_index = (it->current.overlay_string_index
2452 % OVERLAY_STRING_CHUNK_SIZE);
2453 it->string = it->overlay_strings[relative_index];
cafafe0b 2454 xassert (STRINGP (it->string));
5f5c8ee5
GM
2455 it->current.string_pos = pos->string_pos;
2456 it->method = next_element_from_string;
2457 }
2311178e 2458
1e1e5daf
GM
2459#if 0 /* This is bogus because POS not having an overlay string
2460 position does not mean it's after the string. Example: A
2461 line starting with a before-string and initialization of IT
2462 to the previous row's end position. */
2be8f184
GM
2463 else if (it->current.overlay_string_index >= 0)
2464 {
2465 /* If POS says we're already after an overlay string ending at
2466 POS, make sure to pop the iterator because it will be in
2467 front of that overlay string. When POS is ZV, we've thereby
2468 also ``processed'' overlay strings at ZV. */
aeb2b8fc
GM
2469 while (it->sp)
2470 pop_it (it);
2be8f184
GM
2471 it->current.overlay_string_index = -1;
2472 it->method = next_element_from_buffer;
2473 if (CHARPOS (pos->pos) == ZV)
2474 it->overlay_strings_at_end_processed_p = 1;
2475 }
1e1e5daf 2476#endif /* 0 */
2311178e 2477
2be8f184 2478 if (CHARPOS (pos->string_pos) >= 0)
5f5c8ee5
GM
2479 {
2480 /* Recorded position is not in an overlay string, but in another
2481 string. This can only be a string from a `display' property.
2482 IT should already be filled with that string. */
2483 it->current.string_pos = pos->string_pos;
2484 xassert (STRINGP (it->string));
2485 }
2486
ac90c44f
GM
2487 /* Restore position in display vector translations, control
2488 character translations or ellipses. */
5f5c8ee5
GM
2489 if (pos->dpvec_index >= 0)
2490 {
ac90c44f
GM
2491 if (it->dpvec == NULL)
2492 get_next_display_element (it);
5f5c8ee5
GM
2493 xassert (it->dpvec && it->current.dpvec_index == 0);
2494 it->current.dpvec_index = pos->dpvec_index;
2495 }
2311178e 2496
5f5c8ee5 2497 CHECK_IT (it);
47d57b22 2498 return !overlay_strings_with_newlines;
5f5c8ee5
GM
2499}
2500
2501
2502/* Initialize IT for stepping through current_buffer in window W
2503 starting at ROW->start. */
2504
2505static void
2506init_to_row_start (it, w, row)
2507 struct it *it;
2508 struct window *w;
2509 struct glyph_row *row;
2510{
2511 init_from_display_pos (it, w, &row->start);
6b61353c 2512 it->start = row->start;
5f5c8ee5
GM
2513 it->continuation_lines_width = row->continuation_lines_width;
2514 CHECK_IT (it);
2515}
2516
2311178e 2517
5f5c8ee5 2518/* Initialize IT for stepping through current_buffer in window W
47d57b22
GM
2519 starting in the line following ROW, i.e. starting at ROW->end.
2520 Value is zero if there are overlay strings with newlines at ROW's
2521 end position. */
5f5c8ee5 2522
47d57b22 2523static int
5f5c8ee5
GM
2524init_to_row_end (it, w, row)
2525 struct it *it;
2526 struct window *w;
2527 struct glyph_row *row;
2528{
47d57b22 2529 int success = 0;
2311178e 2530
47d57b22
GM
2531 if (init_from_display_pos (it, w, &row->end))
2532 {
2533 if (row->continued_p)
2534 it->continuation_lines_width
2535 = row->continuation_lines_width + row->pixel_width;
2536 CHECK_IT (it);
2537 success = 1;
2538 }
2311178e 2539
47d57b22 2540 return success;
5f5c8ee5
GM
2541}
2542
2543
2544
2545\f
2546/***********************************************************************
2547 Text properties
2548 ***********************************************************************/
2549
2550/* Called when IT reaches IT->stop_charpos. Handle text property and
2551 overlay changes. Set IT->stop_charpos to the next position where
2552 to stop. */
2553
2554static void
2555handle_stop (it)
2556 struct it *it;
2557{
2558 enum prop_handled handled;
2559 int handle_overlay_change_p = 1;
2560 struct props *p;
2561
2562 it->dpvec = NULL;
2563 it->current.dpvec_index = -1;
2564
2565 do
2566 {
2567 handled = HANDLED_NORMALLY;
2311178e 2568
5f5c8ee5
GM
2569 /* Call text property handlers. */
2570 for (p = it_props; p->handler; ++p)
2571 {
2572 handled = p->handler (it);
2970b9be 2573
5f5c8ee5
GM
2574 if (handled == HANDLED_RECOMPUTE_PROPS)
2575 break;
2576 else if (handled == HANDLED_RETURN)
2577 return;
2578 else if (handled == HANDLED_OVERLAY_STRING_CONSUMED)
2579 handle_overlay_change_p = 0;
2580 }
2581
2582 if (handled != HANDLED_RECOMPUTE_PROPS)
2583 {
2584 /* Don't check for overlay strings below when set to deliver
2585 characters from a display vector. */
2586 if (it->method == next_element_from_display_vector)
2587 handle_overlay_change_p = 0;
2588
2589 /* Handle overlay changes. */
2590 if (handle_overlay_change_p)
2591 handled = handle_overlay_change (it);
2311178e 2592
5f5c8ee5
GM
2593 /* Determine where to stop next. */
2594 if (handled == HANDLED_NORMALLY)
2595 compute_stop_pos (it);
2596 }
2597 }
2598 while (handled == HANDLED_RECOMPUTE_PROPS);
2599}
2600
2601
2602/* Compute IT->stop_charpos from text property and overlay change
2603 information for IT's current position. */
2604
2605static void
2606compute_stop_pos (it)
2607 struct it *it;
2608{
2609 register INTERVAL iv, next_iv;
2610 Lisp_Object object, limit, position;
2611
2612 /* If nowhere else, stop at the end. */
2613 it->stop_charpos = it->end_charpos;
2311178e 2614
5f5c8ee5
GM
2615 if (STRINGP (it->string))
2616 {
2617 /* Strings are usually short, so don't limit the search for
2618 properties. */
2619 object = it->string;
2620 limit = Qnil;
ac90c44f 2621 position = make_number (IT_STRING_CHARPOS (*it));
5f5c8ee5
GM
2622 }
2623 else
2624 {
2625 int charpos;
2626
2627 /* If next overlay change is in front of the current stop pos
2628 (which is IT->end_charpos), stop there. Note: value of
2629 next_overlay_change is point-max if no overlay change
2630 follows. */
2631 charpos = next_overlay_change (IT_CHARPOS (*it));
2632 if (charpos < it->stop_charpos)
2633 it->stop_charpos = charpos;
2634
2635 /* If showing the region, we have to stop at the region
2636 start or end because the face might change there. */
2637 if (it->region_beg_charpos > 0)
2638 {
2639 if (IT_CHARPOS (*it) < it->region_beg_charpos)
2640 it->stop_charpos = min (it->stop_charpos, it->region_beg_charpos);
2641 else if (IT_CHARPOS (*it) < it->region_end_charpos)
2642 it->stop_charpos = min (it->stop_charpos, it->region_end_charpos);
2643 }
2311178e 2644
5f5c8ee5
GM
2645 /* Set up variables for computing the stop position from text
2646 property changes. */
2647 XSETBUFFER (object, current_buffer);
ac90c44f
GM
2648 limit = make_number (IT_CHARPOS (*it) + TEXT_PROP_DISTANCE_LIMIT);
2649 position = make_number (IT_CHARPOS (*it));
5f5c8ee5
GM
2650
2651 }
2652
2653 /* Get the interval containing IT's position. Value is a null
2654 interval if there isn't such an interval. */
2655 iv = validate_interval_range (object, &position, &position, 0);
2656 if (!NULL_INTERVAL_P (iv))
2657 {
2658 Lisp_Object values_here[LAST_PROP_IDX];
2659 struct props *p;
2660
2661 /* Get properties here. */
2662 for (p = it_props; p->handler; ++p)
2663 values_here[p->idx] = textget (iv->plist, *p->name);
2664
2665 /* Look for an interval following iv that has different
2666 properties. */
2667 for (next_iv = next_interval (iv);
2668 (!NULL_INTERVAL_P (next_iv)
2669 && (NILP (limit)
2670 || XFASTINT (limit) > next_iv->position));
2671 next_iv = next_interval (next_iv))
2672 {
2673 for (p = it_props; p->handler; ++p)
2674 {
2675 Lisp_Object new_value;
2676
2677 new_value = textget (next_iv->plist, *p->name);
2678 if (!EQ (values_here[p->idx], new_value))
2679 break;
2680 }
2311178e 2681
5f5c8ee5
GM
2682 if (p->handler)
2683 break;
2684 }
2685
2686 if (!NULL_INTERVAL_P (next_iv))
2687 {
2688 if (INTEGERP (limit)
2689 && next_iv->position >= XFASTINT (limit))
2690 /* No text property change up to limit. */
2691 it->stop_charpos = min (XFASTINT (limit), it->stop_charpos);
2692 else
2693 /* Text properties change in next_iv. */
2694 it->stop_charpos = min (it->stop_charpos, next_iv->position);
2695 }
2696 }
2697
2698 xassert (STRINGP (it->string)
2699 || (it->stop_charpos >= BEGV
2700 && it->stop_charpos >= IT_CHARPOS (*it)));
2701}
2702
2703
2704/* Return the position of the next overlay change after POS in
2705 current_buffer. Value is point-max if no overlay change
2706 follows. This is like `next-overlay-change' but doesn't use
2707 xmalloc. */
2708
2709static int
2710next_overlay_change (pos)
2711 int pos;
2712{
2713 int noverlays;
2714 int endpos;
2715 Lisp_Object *overlays;
2716 int len;
2717 int i;
2718
2719 /* Get all overlays at the given position. */
2720 len = 10;
2721 overlays = (Lisp_Object *) alloca (len * sizeof *overlays);
a0315a63 2722 noverlays = overlays_at (pos, 0, &overlays, &len, &endpos, NULL, 1);
5f5c8ee5
GM
2723 if (noverlays > len)
2724 {
2725 len = noverlays;
2726 overlays = (Lisp_Object *) alloca (len * sizeof *overlays);
a0315a63 2727 noverlays = overlays_at (pos, 0, &overlays, &len, &endpos, NULL, 1);
5f5c8ee5
GM
2728 }
2729
2730 /* If any of these overlays ends before endpos,
2731 use its ending point instead. */
2732 for (i = 0; i < noverlays; ++i)
2733 {
2734 Lisp_Object oend;
2735 int oendpos;
2736
2737 oend = OVERLAY_END (overlays[i]);
2738 oendpos = OVERLAY_POSITION (oend);
2739 endpos = min (endpos, oendpos);
2740 }
2741
2742 return endpos;
2743}
2744
2745
2746\f
2747/***********************************************************************
2748 Fontification
2749 ***********************************************************************/
2750
2751/* Handle changes in the `fontified' property of the current buffer by
2752 calling hook functions from Qfontification_functions to fontify
2753 regions of text. */
2754
2755static enum prop_handled
2756handle_fontified_prop (it)
2757 struct it *it;
2758{
2759 Lisp_Object prop, pos;
2760 enum prop_handled handled = HANDLED_NORMALLY;
2761
2762 /* Get the value of the `fontified' property at IT's current buffer
2763 position. (The `fontified' property doesn't have a special
2764 meaning in strings.) If the value is nil, call functions from
2765 Qfontification_functions. */
2766 if (!STRINGP (it->string)
2767 && it->s == NULL
2768 && !NILP (Vfontification_functions)
085536c2 2769 && !NILP (Vrun_hooks)
5f5c8ee5
GM
2770 && (pos = make_number (IT_CHARPOS (*it)),
2771 prop = Fget_char_property (pos, Qfontified, Qnil),
2772 NILP (prop)))
2773 {
331379bf 2774 int count = SPECPDL_INDEX ();
085536c2
GM
2775 Lisp_Object val;
2776
2777 val = Vfontification_functions;
2778 specbind (Qfontification_functions, Qnil);
2311178e 2779
085536c2 2780 if (!CONSP (val) || EQ (XCAR (val), Qlambda))
116d6f5c 2781 safe_call1 (val, pos);
085536c2
GM
2782 else
2783 {
2784 Lisp_Object globals, fn;
2785 struct gcpro gcpro1, gcpro2;
5f5c8ee5 2786
085536c2
GM
2787 globals = Qnil;
2788 GCPRO2 (val, globals);
2311178e 2789
085536c2
GM
2790 for (; CONSP (val); val = XCDR (val))
2791 {
2792 fn = XCAR (val);
2311178e 2793
085536c2
GM
2794 if (EQ (fn, Qt))
2795 {
2796 /* A value of t indicates this hook has a local
2797 binding; it means to run the global binding too.
2798 In a global value, t should not occur. If it
2799 does, we must ignore it to avoid an endless
2800 loop. */
2801 for (globals = Fdefault_value (Qfontification_functions);
2802 CONSP (globals);
2803 globals = XCDR (globals))
2804 {
2805 fn = XCAR (globals);
2806 if (!EQ (fn, Qt))
116d6f5c 2807 safe_call1 (fn, pos);
085536c2
GM
2808 }
2809 }
2810 else
116d6f5c 2811 safe_call1 (fn, pos);
085536c2
GM
2812 }
2813
2814 UNGCPRO;
2815 }
2816
2817 unbind_to (count, Qnil);
5f5c8ee5
GM
2818
2819 /* Return HANDLED_RECOMPUTE_PROPS only if function fontified
2820 something. This avoids an endless loop if they failed to
2821 fontify the text for which reason ever. */
2822 if (!NILP (Fget_char_property (pos, Qfontified, Qnil)))
2823 handled = HANDLED_RECOMPUTE_PROPS;
2824 }
2825
2826 return handled;
2827}
2828
2829
2830\f
2831/***********************************************************************
2832 Faces
2833 ***********************************************************************/
2834
2835/* Set up iterator IT from face properties at its current position.
2836 Called from handle_stop. */
2837
2838static enum prop_handled
2839handle_face_prop (it)
2840 struct it *it;
2841{
2842 int new_face_id, next_stop;
2311178e 2843
5f5c8ee5
GM
2844 if (!STRINGP (it->string))
2845 {
2846 new_face_id
2847 = face_at_buffer_position (it->w,
2848 IT_CHARPOS (*it),
2849 it->region_beg_charpos,
2850 it->region_end_charpos,
2851 &next_stop,
2852 (IT_CHARPOS (*it)
2853 + TEXT_PROP_DISTANCE_LIMIT),
2854 0);
2311178e 2855
5f5c8ee5
GM
2856 /* Is this a start of a run of characters with box face?
2857 Caveat: this can be called for a freshly initialized
4b41cebb 2858 iterator; face_id is -1 in this case. We know that the new
5f5c8ee5
GM
2859 face will not change until limit, i.e. if the new face has a
2860 box, all characters up to limit will have one. But, as
2861 usual, we don't know whether limit is really the end. */
2862 if (new_face_id != it->face_id)
2863 {
2864 struct face *new_face = FACE_FROM_ID (it->f, new_face_id);
2311178e 2865
5f5c8ee5
GM
2866 /* If new face has a box but old face has not, this is
2867 the start of a run of characters with box, i.e. it has
2868 a shadow on the left side. The value of face_id of the
2869 iterator will be -1 if this is the initial call that gets
2870 the face. In this case, we have to look in front of IT's
2871 position and see whether there is a face != new_face_id. */
2872 it->start_of_box_run_p
2873 = (new_face->box != FACE_NO_BOX
2874 && (it->face_id >= 0
2875 || IT_CHARPOS (*it) == BEG
2876 || new_face_id != face_before_it_pos (it)));
2877 it->face_box_p = new_face->box != FACE_NO_BOX;
2878 }
2879 }
2880 else
2881 {
06a12811
GM
2882 int base_face_id, bufpos;
2883
2884 if (it->current.overlay_string_index >= 0)
2885 bufpos = IT_CHARPOS (*it);
2886 else
2887 bufpos = 0;
2311178e 2888
06a12811
GM
2889 /* For strings from a buffer, i.e. overlay strings or strings
2890 from a `display' property, use the face at IT's current
2891 buffer position as the base face to merge with, so that
2892 overlay strings appear in the same face as surrounding
2893 text, unless they specify their own faces. */
2894 base_face_id = underlying_face_id (it);
2311178e 2895
06a12811
GM
2896 new_face_id = face_at_string_position (it->w,
2897 it->string,
2898 IT_STRING_CHARPOS (*it),
2899 bufpos,
2900 it->region_beg_charpos,
2901 it->region_end_charpos,
2902 &next_stop,
5de7c6f2 2903 base_face_id, 0);
2311178e 2904
5f5c8ee5
GM
2905#if 0 /* This shouldn't be neccessary. Let's check it. */
2906 /* If IT is used to display a mode line we would really like to
2907 use the mode line face instead of the frame's default face. */
2908 if (it->glyph_row == MATRIX_MODE_LINE_ROW (it->w->desired_matrix)
2909 && new_face_id == DEFAULT_FACE_ID)
96d2320f 2910 new_face_id = CURRENT_MODE_LINE_FACE_ID (it->w);
5f5c8ee5 2911#endif
2311178e 2912
5f5c8ee5
GM
2913 /* Is this a start of a run of characters with box? Caveat:
2914 this can be called for a freshly allocated iterator; face_id
2915 is -1 is this case. We know that the new face will not
2916 change until the next check pos, i.e. if the new face has a
2917 box, all characters up to that position will have a
2918 box. But, as usual, we don't know whether that position
2919 is really the end. */
2920 if (new_face_id != it->face_id)
2921 {
2922 struct face *new_face = FACE_FROM_ID (it->f, new_face_id);
2923 struct face *old_face = FACE_FROM_ID (it->f, it->face_id);
2311178e 2924
5f5c8ee5
GM
2925 /* If new face has a box but old face hasn't, this is the
2926 start of a run of characters with box, i.e. it has a
2927 shadow on the left side. */
2928 it->start_of_box_run_p
2929 = new_face->box && (old_face == NULL || !old_face->box);
2930 it->face_box_p = new_face->box != FACE_NO_BOX;
2931 }
2932 }
2311178e 2933
5f5c8ee5 2934 it->face_id = new_face_id;
5f5c8ee5
GM
2935 return HANDLED_NORMALLY;
2936}
2937
2938
06a12811
GM
2939/* Return the ID of the face ``underlying'' IT's current position,
2940 which is in a string. If the iterator is associated with a
2941 buffer, return the face at IT's current buffer position.
2942 Otherwise, use the iterator's base_face_id. */
2943
2944static int
2945underlying_face_id (it)
2946 struct it *it;
2947{
2948 int face_id = it->base_face_id, i;
2949
2950 xassert (STRINGP (it->string));
2951
2952 for (i = it->sp - 1; i >= 0; --i)
2953 if (NILP (it->stack[i].string))
2954 face_id = it->stack[i].face_id;
2955
2956 return face_id;
2957}
2958
2959
5f5c8ee5
GM
2960/* Compute the face one character before or after the current position
2961 of IT. BEFORE_P non-zero means get the face in front of IT's
2962 position. Value is the id of the face. */
2963
2964static int
2965face_before_or_after_it_pos (it, before_p)
2966 struct it *it;
2967 int before_p;
2968{
2969 int face_id, limit;
2970 int next_check_charpos;
2971 struct text_pos pos;
2972
2973 xassert (it->s == NULL);
2311178e 2974
5f5c8ee5
GM
2975 if (STRINGP (it->string))
2976 {
06a12811 2977 int bufpos, base_face_id;
2311178e 2978
5f5c8ee5
GM
2979 /* No face change past the end of the string (for the case
2980 we are padding with spaces). No face change before the
2981 string start. */
2051c264 2982 if (IT_STRING_CHARPOS (*it) >= SCHARS (it->string)
5f5c8ee5
GM
2983 || (IT_STRING_CHARPOS (*it) == 0 && before_p))
2984 return it->face_id;
2985
2986 /* Set pos to the position before or after IT's current position. */
2987 if (before_p)
2988 pos = string_pos (IT_STRING_CHARPOS (*it) - 1, it->string);
2989 else
260a86a0
KH
2990 /* For composition, we must check the character after the
2991 composition. */
2992 pos = (it->what == IT_COMPOSITION
2993 ? string_pos (IT_STRING_CHARPOS (*it) + it->cmp_len, it->string)
2994 : string_pos (IT_STRING_CHARPOS (*it) + 1, it->string));
5f5c8ee5 2995
06a12811
GM
2996 if (it->current.overlay_string_index >= 0)
2997 bufpos = IT_CHARPOS (*it);
2998 else
2999 bufpos = 0;
3000
3001 base_face_id = underlying_face_id (it);
3002
5f5c8ee5 3003 /* Get the face for ASCII, or unibyte. */
06a12811
GM
3004 face_id = face_at_string_position (it->w,
3005 it->string,
3006 CHARPOS (pos),
3007 bufpos,
3008 it->region_beg_charpos,
3009 it->region_end_charpos,
3010 &next_check_charpos,
5de7c6f2 3011 base_face_id, 0);
5f5c8ee5
GM
3012
3013 /* Correct the face for charsets different from ASCII. Do it
3014 for the multibyte case only. The face returned above is
3015 suitable for unibyte text if IT->string is unibyte. */
3016 if (STRING_MULTIBYTE (it->string))
3017 {
50f80c2f 3018 const unsigned char *p = SDATA (it->string) + BYTEPOS (pos);
2051c264 3019 int rest = SBYTES (it->string) - BYTEPOS (pos);
980806b6
KH
3020 int c, len;
3021 struct face *face = FACE_FROM_ID (it->f, face_id);
2311178e 3022
4fdb80f2 3023 c = string_char_and_length (p, rest, &len);
f46a4dc1 3024 face_id = FACE_FOR_CHAR (it->f, face, c, CHARPOS (pos), it->string);
5f5c8ee5
GM
3025 }
3026 }
3027 else
3028 {
70851746
GM
3029 if ((IT_CHARPOS (*it) >= ZV && !before_p)
3030 || (IT_CHARPOS (*it) <= BEGV && before_p))
3031 return it->face_id;
2311178e 3032
5f5c8ee5
GM
3033 limit = IT_CHARPOS (*it) + TEXT_PROP_DISTANCE_LIMIT;
3034 pos = it->current.pos;
2311178e 3035
5f5c8ee5 3036 if (before_p)
c1005d06 3037 DEC_TEXT_POS (pos, it->multibyte_p);
5f5c8ee5 3038 else
260a86a0
KH
3039 {
3040 if (it->what == IT_COMPOSITION)
3041 /* For composition, we must check the position after the
3042 composition. */
3043 pos.charpos += it->cmp_len, pos.bytepos += it->len;
3044 else
c1005d06 3045 INC_TEXT_POS (pos, it->multibyte_p);
260a86a0 3046 }
2311178e 3047
5f5c8ee5
GM
3048 /* Determine face for CHARSET_ASCII, or unibyte. */
3049 face_id = face_at_buffer_position (it->w,
3050 CHARPOS (pos),
3051 it->region_beg_charpos,
3052 it->region_end_charpos,
3053 &next_check_charpos,
3054 limit, 0);
3055
3056 /* Correct the face for charsets different from ASCII. Do it
3057 for the multibyte case only. The face returned above is
3058 suitable for unibyte text if current_buffer is unibyte. */
3059 if (it->multibyte_p)
3060 {
1d1b6e6a 3061 int c = FETCH_MULTIBYTE_CHAR (BYTEPOS (pos));
980806b6 3062 struct face *face = FACE_FROM_ID (it->f, face_id);
f46a4dc1 3063 face_id = FACE_FOR_CHAR (it->f, face, c, CHARPOS (pos), Qnil);
5f5c8ee5
GM
3064 }
3065 }
2311178e 3066
5f5c8ee5
GM
3067 return face_id;
3068}
3069
3070
3071\f
3072/***********************************************************************
3073 Invisible text
3074 ***********************************************************************/
3075
3076/* Set up iterator IT from invisible properties at its current
3077 position. Called from handle_stop. */
3078
3079static enum prop_handled
3080handle_invisible_prop (it)
3081 struct it *it;
3082{
3083 enum prop_handled handled = HANDLED_NORMALLY;
3084
3085 if (STRINGP (it->string))
3086 {
3087 extern Lisp_Object Qinvisible;
3088 Lisp_Object prop, end_charpos, limit, charpos;
3089
3090 /* Get the value of the invisible text property at the
3091 current position. Value will be nil if there is no such
3092 property. */
ac90c44f 3093 charpos = make_number (IT_STRING_CHARPOS (*it));
5f5c8ee5
GM
3094 prop = Fget_text_property (charpos, Qinvisible, it->string);
3095
eadc0bf8
GM
3096 if (!NILP (prop)
3097 && IT_STRING_CHARPOS (*it) < it->end_charpos)
5f5c8ee5
GM
3098 {
3099 handled = HANDLED_RECOMPUTE_PROPS;
2311178e 3100
5f5c8ee5
GM
3101 /* Get the position at which the next change of the
3102 invisible text property can be found in IT->string.
3103 Value will be nil if the property value is the same for
3104 all the rest of IT->string. */
2051c264 3105 XSETINT (limit, SCHARS (it->string));
5f5c8ee5 3106 end_charpos = Fnext_single_property_change (charpos, Qinvisible,
2051c264 3107 it->string, limit);
2311178e 3108
5f5c8ee5
GM
3109 /* Text at current position is invisible. The next
3110 change in the property is at position end_charpos.
3111 Move IT's current position to that position. */
3112 if (INTEGERP (end_charpos)
3113 && XFASTINT (end_charpos) < XFASTINT (limit))
3114 {
3115 struct text_pos old;
3116 old = it->current.string_pos;
3117 IT_STRING_CHARPOS (*it) = XFASTINT (end_charpos);
3118 compute_string_pos (&it->current.string_pos, old, it->string);
3119 }
3120 else
3121 {
3122 /* The rest of the string is invisible. If this is an
3123 overlay string, proceed with the next overlay string
3124 or whatever comes and return a character from there. */
3125 if (it->current.overlay_string_index >= 0)
3126 {
3127 next_overlay_string (it);
3128 /* Don't check for overlay strings when we just
3129 finished processing them. */
3130 handled = HANDLED_OVERLAY_STRING_CONSUMED;
3131 }
3132 else
3133 {
2051c264
GM
3134 IT_STRING_CHARPOS (*it) = SCHARS (it->string);
3135 IT_STRING_BYTEPOS (*it) = SBYTES (it->string);
5f5c8ee5
GM
3136 }
3137 }
3138 }
3139 }
3140 else
3141 {
8580a4e3 3142 int invis_p, newpos, next_stop, start_charpos;
5a08cbaf 3143 Lisp_Object pos, prop, overlay;
5f5c8ee5
GM
3144
3145 /* First of all, is there invisible text at this position? */
5a08cbaf 3146 start_charpos = IT_CHARPOS (*it);
ac90c44f 3147 pos = make_number (IT_CHARPOS (*it));
5a08cbaf
GM
3148 prop = get_char_property_and_overlay (pos, Qinvisible, it->window,
3149 &overlay);
8580a4e3
SM
3150 invis_p = TEXT_PROP_MEANS_INVISIBLE (prop);
3151
5f5c8ee5 3152 /* If we are on invisible text, skip over it. */
8580a4e3 3153 if (invis_p && IT_CHARPOS (*it) < it->end_charpos)
5f5c8ee5
GM
3154 {
3155 /* Record whether we have to display an ellipsis for the
3156 invisible text. */
8580a4e3 3157 int display_ellipsis_p = invis_p == 2;
5f5c8ee5
GM
3158
3159 handled = HANDLED_RECOMPUTE_PROPS;
2311178e 3160
5f5c8ee5
GM
3161 /* Loop skipping over invisible text. The loop is left at
3162 ZV or with IT on the first char being visible again. */
3163 do
3164 {
3165 /* Try to skip some invisible text. Return value is the
3166 position reached which can be equal to IT's position
3167 if there is nothing invisible here. This skips both
3168 over invisible text properties and overlays with
3169 invisible property. */
3170 newpos = skip_invisible (IT_CHARPOS (*it),
3171 &next_stop, ZV, it->window);
3172
3173 /* If we skipped nothing at all we weren't at invisible
3174 text in the first place. If everything to the end of
3175 the buffer was skipped, end the loop. */
3176 if (newpos == IT_CHARPOS (*it) || newpos >= ZV)
8580a4e3 3177 invis_p = 0;
5f5c8ee5
GM
3178 else
3179 {
3180 /* We skipped some characters but not necessarily
3181 all there are. Check if we ended up on visible
3182 text. Fget_char_property returns the property of
3183 the char before the given position, i.e. if we
8580a4e3 3184 get invis_p = 0, this means that the char at
5f5c8ee5 3185 newpos is visible. */
ac90c44f 3186 pos = make_number (newpos);
5f5c8ee5 3187 prop = Fget_char_property (pos, Qinvisible, it->window);
8580a4e3 3188 invis_p = TEXT_PROP_MEANS_INVISIBLE (prop);
5f5c8ee5 3189 }
2311178e 3190
5f5c8ee5
GM
3191 /* If we ended up on invisible text, proceed to
3192 skip starting with next_stop. */
8580a4e3 3193 if (invis_p)
5f5c8ee5
GM
3194 IT_CHARPOS (*it) = next_stop;
3195 }
8580a4e3 3196 while (invis_p);
5a08cbaf 3197
5f5c8ee5
GM
3198 /* The position newpos is now either ZV or on visible text. */
3199 IT_CHARPOS (*it) = newpos;
3200 IT_BYTEPOS (*it) = CHAR_TO_BYTE (newpos);
2311178e 3201
5a08cbaf
GM
3202 /* If there are before-strings at the start of invisible
3203 text, and the text is invisible because of a text
3204 property, arrange to show before-strings because 20.x did
3205 it that way. (If the text is invisible because of an
3206 overlay property instead of a text property, this is
3207 already handled in the overlay code.) */
3208 if (NILP (overlay)
3209 && get_overlay_strings (it, start_charpos))
5f5c8ee5 3210 {
5a08cbaf
GM
3211 handled = HANDLED_RECOMPUTE_PROPS;
3212 it->stack[it->sp - 1].display_ellipsis_p = display_ellipsis_p;
5f5c8ee5 3213 }
5a08cbaf
GM
3214 else if (display_ellipsis_p)
3215 setup_for_ellipsis (it);
5f5c8ee5
GM
3216 }
3217 }
3218
3219 return handled;
3220}
3221
3222
5a08cbaf
GM
3223/* Make iterator IT return `...' next. */
3224
3225static void
3226setup_for_ellipsis (it)
3227 struct it *it;
3228{
2311178e 3229 if (it->dp
5a08cbaf
GM
3230 && VECTORP (DISP_INVIS_VECTOR (it->dp)))
3231 {
3232 struct Lisp_Vector *v = XVECTOR (DISP_INVIS_VECTOR (it->dp));
3233 it->dpvec = v->contents;
3234 it->dpend = v->contents + v->size;
3235 }
2311178e 3236 else
5a08cbaf
GM
3237 {
3238 /* Default `...'. */
3239 it->dpvec = default_invis_vector;
3240 it->dpend = default_invis_vector + 3;
3241 }
2311178e 3242
5a08cbaf
GM
3243 /* The ellipsis display does not replace the display of the
3244 character at the new position. Indicate this by setting
3245 IT->dpvec_char_len to zero. */
3246 it->dpvec_char_len = 0;
2311178e 3247
5a08cbaf
GM
3248 it->current.dpvec_index = 0;
3249 it->method = next_element_from_display_vector;
3250}
3251
3252
5f5c8ee5
GM
3253\f
3254/***********************************************************************
3255 'display' property
3256 ***********************************************************************/
3257
3258/* Set up iterator IT from `display' property at its current position.
3259 Called from handle_stop. */
3260
3261static enum prop_handled
3262handle_display_prop (it)
3263 struct it *it;
3264{
3265 Lisp_Object prop, object;
3266 struct text_pos *position;
a61b7058 3267 int display_replaced_p = 0;
5f5c8ee5
GM
3268
3269 if (STRINGP (it->string))
3270 {
3271 object = it->string;
3272 position = &it->current.string_pos;
3273 }
3274 else
3275 {
221dd3e7 3276 object = it->w->buffer;
5f5c8ee5
GM
3277 position = &it->current.pos;
3278 }
3279
3280 /* Reset those iterator values set from display property values. */
3281 it->font_height = Qnil;
3282 it->space_width = Qnil;
3283 it->voffset = 0;
3284
3285 /* We don't support recursive `display' properties, i.e. string
3286 values that have a string `display' property, that have a string
3287 `display' property etc. */
3288 if (!it->string_from_display_prop_p)
3289 it->area = TEXT_AREA;
3290
3291 prop = Fget_char_property (make_number (position->charpos),
3292 Qdisplay, object);
3293 if (NILP (prop))
3294 return HANDLED_NORMALLY;
3295
f3751a65 3296 if (CONSP (prop)
12700f40
GM
3297 /* Simple properties. */
3298 && !EQ (XCAR (prop), Qimage)
3299 && !EQ (XCAR (prop), Qspace)
3300 && !EQ (XCAR (prop), Qwhen)
3301 && !EQ (XCAR (prop), Qspace_width)
3302 && !EQ (XCAR (prop), Qheight)
3303 && !EQ (XCAR (prop), Qraise)
3304 /* Marginal area specifications. */
3305 && !(CONSP (XCAR (prop)) && EQ (XCAR (XCAR (prop)), Qmargin))
6b61353c
KH
3306 && !EQ (XCAR (prop), Qleft_fringe)
3307 && !EQ (XCAR (prop), Qright_fringe)
12700f40 3308 && !NILP (XCAR (prop)))
5f5c8ee5 3309 {
a61b7058 3310 for (; CONSP (prop); prop = XCDR (prop))
5f5c8ee5 3311 {
a61b7058
GM
3312 if (handle_single_display_prop (it, XCAR (prop), object,
3313 position, display_replaced_p))
3314 display_replaced_p = 1;
5f5c8ee5
GM
3315 }
3316 }
3317 else if (VECTORP (prop))
3318 {
3319 int i;
a61b7058
GM
3320 for (i = 0; i < ASIZE (prop); ++i)
3321 if (handle_single_display_prop (it, AREF (prop, i), object,
3322 position, display_replaced_p))
3323 display_replaced_p = 1;
5f5c8ee5
GM
3324 }
3325 else
3326 {
a61b7058
GM
3327 if (handle_single_display_prop (it, prop, object, position, 0))
3328 display_replaced_p = 1;
5f5c8ee5
GM
3329 }
3330
a61b7058 3331 return display_replaced_p ? HANDLED_RETURN : HANDLED_NORMALLY;
5f5c8ee5
GM
3332}
3333
3334
6c577098 3335/* Value is the position of the end of the `display' property starting
5f5c8ee5
GM
3336 at START_POS in OBJECT. */
3337
3338static struct text_pos
3339display_prop_end (it, object, start_pos)
3340 struct it *it;
3341 Lisp_Object object;
3342 struct text_pos start_pos;
3343{
3344 Lisp_Object end;
3345 struct text_pos end_pos;
5f5c8ee5 3346
016b5642
MB
3347 end = Fnext_single_char_property_change (make_number (CHARPOS (start_pos)),
3348 Qdisplay, object, Qnil);
6c577098
GM
3349 CHARPOS (end_pos) = XFASTINT (end);
3350 if (STRINGP (object))
5f5c8ee5
GM
3351 compute_string_pos (&end_pos, start_pos, it->string);
3352 else
6c577098 3353 BYTEPOS (end_pos) = CHAR_TO_BYTE (XFASTINT (end));
5f5c8ee5
GM
3354
3355 return end_pos;
3356}
3357
3358
3359/* Set up IT from a single `display' sub-property value PROP. OBJECT
3360 is the object in which the `display' property was found. *POSITION
a61b7058
GM
3361 is the position at which it was found. DISPLAY_REPLACED_P non-zero
3362 means that we previously saw a display sub-property which already
3363 replaced text display with something else, for example an image;
3364 ignore such properties after the first one has been processed.
5f5c8ee5
GM
3365
3366 If PROP is a `space' or `image' sub-property, set *POSITION to the
3367 end position of the `display' property.
3368
4b41cebb 3369 Value is non-zero if something was found which replaces the display
a61b7058 3370 of buffer or string text. */
5f5c8ee5
GM
3371
3372static int
a61b7058
GM
3373handle_single_display_prop (it, prop, object, position,
3374 display_replaced_before_p)
5f5c8ee5
GM
3375 struct it *it;
3376 Lisp_Object prop;
3377 Lisp_Object object;
3378 struct text_pos *position;
a61b7058 3379 int display_replaced_before_p;
5f5c8ee5
GM
3380{
3381 Lisp_Object value;
a61b7058 3382 int replaces_text_display_p = 0;
5f5c8ee5
GM
3383 Lisp_Object form;
3384
d3acf96b 3385 /* If PROP is a list of the form `(when FORM . VALUE)', FORM is
4b41cebb 3386 evaluated. If the result is nil, VALUE is ignored. */
5f5c8ee5 3387 form = Qt;
d3acf96b 3388 if (CONSP (prop) && EQ (XCAR (prop), Qwhen))
5f5c8ee5
GM
3389 {
3390 prop = XCDR (prop);
3391 if (!CONSP (prop))
3392 return 0;
3393 form = XCAR (prop);
3394 prop = XCDR (prop);
5f5c8ee5
GM
3395 }
3396
3397 if (!NILP (form) && !EQ (form, Qt))
3398 {
331379bf 3399 int count = SPECPDL_INDEX ();
5f5c8ee5 3400 struct gcpro gcpro1;
5f5c8ee5 3401
b384d6f8
GM
3402 /* Bind `object' to the object having the `display' property, a
3403 buffer or string. Bind `position' to the position in the
3404 object where the property was found, and `buffer-position'
3405 to the current position in the buffer. */
3406 specbind (Qobject, object);
31ac723b
SM
3407 specbind (Qposition, make_number (CHARPOS (*position)));
3408 specbind (Qbuffer_position,
3409 make_number (STRINGP (object)
3410 ? IT_CHARPOS (*it) : CHARPOS (*position)));
b384d6f8 3411 GCPRO1 (form);
116d6f5c 3412 form = safe_eval (form);
b384d6f8
GM
3413 UNGCPRO;
3414 unbind_to (count, Qnil);
5f5c8ee5 3415 }
2311178e 3416
5f5c8ee5
GM
3417 if (NILP (form))
3418 return 0;
3419
3420 if (CONSP (prop)
3421 && EQ (XCAR (prop), Qheight)
3422 && CONSP (XCDR (prop)))
3423 {
e4093f38 3424 if (FRAME_TERMCAP_P (it->f) || FRAME_MSDOS_P (it->f))
5f5c8ee5 3425 return 0;
2311178e 3426
5f5c8ee5
GM
3427 /* `(height HEIGHT)'. */
3428 it->font_height = XCAR (XCDR (prop));
3429 if (!NILP (it->font_height))
3430 {
3431 struct face *face = FACE_FROM_ID (it->f, it->face_id);
3432 int new_height = -1;
3433
3434 if (CONSP (it->font_height)
3435 && (EQ (XCAR (it->font_height), Qplus)
3436 || EQ (XCAR (it->font_height), Qminus))
3437 && CONSP (XCDR (it->font_height))
3438 && INTEGERP (XCAR (XCDR (it->font_height))))
3439 {
3440 /* `(+ N)' or `(- N)' where N is an integer. */
3441 int steps = XINT (XCAR (XCDR (it->font_height)));
3442 if (EQ (XCAR (it->font_height), Qplus))
3443 steps = - steps;
3444 it->face_id = smaller_face (it->f, it->face_id, steps);
3445 }
0d8b31c0 3446 else if (FUNCTIONP (it->font_height))
5f5c8ee5
GM
3447 {
3448 /* Call function with current height as argument.
3449 Value is the new height. */
116d6f5c
GM
3450 Lisp_Object height;
3451 height = safe_call1 (it->font_height,
3452 face->lface[LFACE_HEIGHT_INDEX]);
5f5c8ee5
GM
3453 if (NUMBERP (height))
3454 new_height = XFLOATINT (height);
5f5c8ee5
GM
3455 }
3456 else if (NUMBERP (it->font_height))
3457 {
3458 /* Value is a multiple of the canonical char height. */
3459 struct face *face;
2311178e 3460
5f5c8ee5
GM
3461 face = FACE_FROM_ID (it->f, DEFAULT_FACE_ID);
3462 new_height = (XFLOATINT (it->font_height)
3463 * XINT (face->lface[LFACE_HEIGHT_INDEX]));
3464 }
3465 else
3466 {
3467 /* Evaluate IT->font_height with `height' bound to the
3468 current specified height to get the new height. */
3469 Lisp_Object value;
331379bf 3470 int count = SPECPDL_INDEX ();
2311178e 3471
5f5c8ee5 3472 specbind (Qheight, face->lface[LFACE_HEIGHT_INDEX]);
116d6f5c 3473 value = safe_eval (it->font_height);
5f5c8ee5 3474 unbind_to (count, Qnil);
2311178e 3475
5f5c8ee5
GM
3476 if (NUMBERP (value))
3477 new_height = XFLOATINT (value);
3478 }
2311178e 3479
5f5c8ee5
GM
3480 if (new_height > 0)
3481 it->face_id = face_with_height (it->f, it->face_id, new_height);
3482 }
3483 }
3484 else if (CONSP (prop)
3485 && EQ (XCAR (prop), Qspace_width)
3486 && CONSP (XCDR (prop)))
3487 {
3488 /* `(space_width WIDTH)'. */
e4093f38 3489 if (FRAME_TERMCAP_P (it->f) || FRAME_MSDOS_P (it->f))
bafb434c 3490 return 0;
2311178e 3491
5f5c8ee5
GM
3492 value = XCAR (XCDR (prop));
3493 if (NUMBERP (value) && XFLOATINT (value) > 0)
3494 it->space_width = value;
3495 }
3496 else if (CONSP (prop)
3497 && EQ (XCAR (prop), Qraise)
3498 && CONSP (XCDR (prop)))
3499 {
5f5c8ee5 3500 /* `(raise FACTOR)'. */
e4093f38 3501 if (FRAME_TERMCAP_P (it->f) || FRAME_MSDOS_P (it->f))
bafb434c 3502 return 0;
2311178e 3503
fb3842a8 3504#ifdef HAVE_WINDOW_SYSTEM
5f5c8ee5
GM
3505 value = XCAR (XCDR (prop));
3506 if (NUMBERP (value))
3507 {
3508 struct face *face = FACE_FROM_ID (it->f, it->face_id);
3509 it->voffset = - (XFLOATINT (value)
1ab3e082 3510 * (FONT_HEIGHT (face->font)));
5f5c8ee5
GM
3511 }
3512#endif /* HAVE_WINDOW_SYSTEM */
3513 }
3514 else if (!it->string_from_display_prop_p)
3515 {
f3751a65 3516 /* `((margin left-margin) VALUE)' or `((margin right-margin)
4b41cebb 3517 VALUE) or `((margin nil) VALUE)' or VALUE. */
5f5c8ee5
GM
3518 Lisp_Object location, value;
3519 struct text_pos start_pos;
3520 int valid_p;
3521
3522 /* Characters having this form of property are not displayed, so
3523 we have to find the end of the property. */
5f5c8ee5
GM
3524 start_pos = *position;
3525 *position = display_prop_end (it, object, start_pos);
15e26c76 3526 value = Qnil;
5f5c8ee5
GM
3527
3528 /* Let's stop at the new position and assume that all
3529 text properties change there. */
3530 it->stop_charpos = position->charpos;
3531
6b61353c
KH
3532 if (CONSP (prop)
3533 && (EQ (XCAR (prop), Qleft_fringe)
3534 || EQ (XCAR (prop), Qright_fringe))
3535 && CONSP (XCDR (prop)))
3536 {
3537 unsigned face_id = DEFAULT_FACE_ID;
3538
3539 /* Save current settings of IT so that we can restore them
3540 when we are finished with the glyph property value. */
3541
3542 /* `(left-fringe BITMAP FACE)'. */
3543 if (FRAME_TERMCAP_P (it->f) || FRAME_MSDOS_P (it->f))
3544 return 0;
3545
3546#ifdef HAVE_WINDOW_SYSTEM
3547 value = XCAR (XCDR (prop));
3548 if (!NUMBERP (value)
3549 || !valid_fringe_bitmap_id_p (XINT (value)))
3550 return 0;
3551
3552 if (CONSP (XCDR (XCDR (prop))))
3553 {
3554 Lisp_Object face_name = XCAR (XCDR (XCDR (prop)));
3555
3556 face_id = lookup_named_face (it->f, face_name);
3557 if (face_id < 0)
3558 return 0;
3559 }
3560
3561 push_it (it);
3562
3563 it->area = TEXT_AREA;
3564 it->what = IT_IMAGE;
3565 it->image_id = -1; /* no image */
3566 it->position = start_pos;
3567 it->object = NILP (object) ? it->w->buffer : object;
3568 it->method = next_element_from_image;
3569 it->face_id = face_id;
3570
3571 /* Say that we haven't consumed the characters with
3572 `display' property yet. The call to pop_it in
3573 set_iterator_to_next will clean this up. */
3574 *position = start_pos;
3575
3576 if (EQ (XCAR (prop), Qleft_fringe))
3577 {
3578 it->left_user_fringe_bitmap = XINT (value);
3579 it->left_user_fringe_face_id = face_id;
3580 }
3581 else
3582 {
3583 it->right_user_fringe_bitmap = XINT (value);
3584 it->right_user_fringe_face_id = face_id;
3585 }
3586#endif /* HAVE_WINDOW_SYSTEM */
3587 return 1;
3588 }
3589
f3751a65
GM
3590 location = Qunbound;
3591 if (CONSP (prop) && CONSP (XCAR (prop)))
5f5c8ee5 3592 {
f3751a65 3593 Lisp_Object tem;
2311178e 3594
5f5c8ee5 3595 value = XCDR (prop);
f3751a65
GM
3596 if (CONSP (value))
3597 value = XCAR (value);
3598
3599 tem = XCAR (prop);
3600 if (EQ (XCAR (tem), Qmargin)
3601 && (tem = XCDR (tem),
3602 tem = CONSP (tem) ? XCAR (tem) : Qnil,
3603 (NILP (tem)
3604 || EQ (tem, Qleft_margin)
3605 || EQ (tem, Qright_margin))))
3606 location = tem;
5f5c8ee5 3607 }
f3751a65
GM
3608
3609 if (EQ (location, Qunbound))
5f5c8ee5
GM
3610 {
3611 location = Qnil;
3612 value = prop;
3613 }
3614
6b61353c 3615 valid_p = (STRINGP (value)
5f5c8ee5 3616#ifdef HAVE_WINDOW_SYSTEM
6b61353c 3617 || (!FRAME_TERMCAP_P (it->f) && valid_image_p (value))
5f5c8ee5 3618#endif /* not HAVE_WINDOW_SYSTEM */
6b61353c 3619 || (CONSP (value) && EQ (XCAR (value), Qspace)));
2311178e 3620
5f5c8ee5
GM
3621 if ((EQ (location, Qleft_margin)
3622 || EQ (location, Qright_margin)
3623 || NILP (location))
a61b7058
GM
3624 && valid_p
3625 && !display_replaced_before_p)
5f5c8ee5 3626 {
a61b7058 3627 replaces_text_display_p = 1;
2311178e 3628
5f5c8ee5
GM
3629 /* Save current settings of IT so that we can restore them
3630 when we are finished with the glyph property value. */
3631 push_it (it);
2311178e 3632
5f5c8ee5
GM
3633 if (NILP (location))
3634 it->area = TEXT_AREA;
3635 else if (EQ (location, Qleft_margin))
3636 it->area = LEFT_MARGIN_AREA;
3637 else
3638 it->area = RIGHT_MARGIN_AREA;
2311178e 3639
5f5c8ee5
GM
3640 if (STRINGP (value))
3641 {
3642 it->string = value;
3643 it->multibyte_p = STRING_MULTIBYTE (it->string);
3644 it->current.overlay_string_index = -1;
3645 IT_STRING_CHARPOS (*it) = IT_STRING_BYTEPOS (*it) = 0;
2051c264 3646 it->end_charpos = it->string_nchars = SCHARS (it->string);
5f5c8ee5
GM
3647 it->method = next_element_from_string;
3648 it->stop_charpos = 0;
3649 it->string_from_display_prop_p = 1;
e187cf71
GM
3650 /* Say that we haven't consumed the characters with
3651 `display' property yet. The call to pop_it in
3652 set_iterator_to_next will clean this up. */
3653 *position = start_pos;
5f5c8ee5
GM
3654 }
3655 else if (CONSP (value) && EQ (XCAR (value), Qspace))
3656 {
3657 it->method = next_element_from_stretch;
3658 it->object = value;
3659 it->current.pos = it->position = start_pos;
3660 }
3661#ifdef HAVE_WINDOW_SYSTEM
3662 else
3663 {
3664 it->what = IT_IMAGE;
3665 it->image_id = lookup_image (it->f, value);
3666 it->position = start_pos;
3667 it->object = NILP (object) ? it->w->buffer : object;
3668 it->method = next_element_from_image;
2311178e 3669
02513cdd 3670 /* Say that we haven't consumed the characters with
5f5c8ee5
GM
3671 `display' property yet. The call to pop_it in
3672 set_iterator_to_next will clean this up. */
3673 *position = start_pos;
3674 }
3675#endif /* HAVE_WINDOW_SYSTEM */
3676 }
a21a3943
GM
3677 else
3678 /* Invalid property or property not supported. Restore
3679 the position to what it was before. */
3680 *position = start_pos;
5f5c8ee5
GM
3681 }
3682
a61b7058 3683 return replaces_text_display_p;
5f5c8ee5
GM
3684}
3685
3686
06568bbf
GM
3687/* Check if PROP is a display sub-property value whose text should be
3688 treated as intangible. */
3689
3690static int
3691single_display_prop_intangible_p (prop)
3692 Lisp_Object prop;
3693{
3694 /* Skip over `when FORM'. */
3695 if (CONSP (prop) && EQ (XCAR (prop), Qwhen))
3696 {
3697 prop = XCDR (prop);
3698 if (!CONSP (prop))
3699 return 0;
3700 prop = XCDR (prop);
3701 }
3702
959bc044
SM
3703 if (STRINGP (prop))
3704 return 1;
3705
06568bbf
GM
3706 if (!CONSP (prop))
3707 return 0;
3708
3709 /* Skip over `margin LOCATION'. If LOCATION is in the margins,
3710 we don't need to treat text as intangible. */
3711 if (EQ (XCAR (prop), Qmargin))
3712 {
3713 prop = XCDR (prop);
3714 if (!CONSP (prop))
3715 return 0;
3716
3717 prop = XCDR (prop);
3718 if (!CONSP (prop)
3719 || EQ (XCAR (prop), Qleft_margin)
3720 || EQ (XCAR (prop), Qright_margin))
3721 return 0;
3722 }
2311178e 3723
6cd83a9a
SM
3724 return (CONSP (prop)
3725 && (EQ (XCAR (prop), Qimage)
3726 || EQ (XCAR (prop), Qspace)));
06568bbf
GM
3727}
3728
3729
3730/* Check if PROP is a display property value whose text should be
3731 treated as intangible. */
3732
3733int
3734display_prop_intangible_p (prop)
3735 Lisp_Object prop;
3736{
3737 if (CONSP (prop)
3738 && CONSP (XCAR (prop))
3739 && !EQ (Qmargin, XCAR (XCAR (prop))))
3740 {
3741 /* A list of sub-properties. */
3742 while (CONSP (prop))
3743 {
3744 if (single_display_prop_intangible_p (XCAR (prop)))
3745 return 1;
3746 prop = XCDR (prop);
3747 }
3748 }
3749 else if (VECTORP (prop))
3750 {
3751 /* A vector of sub-properties. */
3752 int i;
a61b7058
GM
3753 for (i = 0; i < ASIZE (prop); ++i)
3754 if (single_display_prop_intangible_p (AREF (prop, i)))
06568bbf
GM
3755 return 1;
3756 }
3757 else
3758 return single_display_prop_intangible_p (prop);
3759
3760 return 0;
3761}
3762
74bd6d65
GM
3763
3764/* Return 1 if PROP is a display sub-property value containing STRING. */
3765
3766static int
3767single_display_prop_string_p (prop, string)
3768 Lisp_Object prop, string;
3769{
74bd6d65
GM
3770 if (EQ (string, prop))
3771 return 1;
2311178e 3772
74bd6d65
GM
3773 /* Skip over `when FORM'. */
3774 if (CONSP (prop) && EQ (XCAR (prop), Qwhen))
3775 {
3776 prop = XCDR (prop);
3777 if (!CONSP (prop))
3778 return 0;
3779 prop = XCDR (prop);
3780 }
3781
3782 if (CONSP (prop))
3783 /* Skip over `margin LOCATION'. */
3784 if (EQ (XCAR (prop), Qmargin))
3785 {
3786 prop = XCDR (prop);
3787 if (!CONSP (prop))
3788 return 0;
3789
3790 prop = XCDR (prop);
3791 if (!CONSP (prop))
3792 return 0;
3793 }
2311178e 3794
74bd6d65
GM
3795 return CONSP (prop) && EQ (XCAR (prop), string);
3796}
3797
3798
3799/* Return 1 if STRING appears in the `display' property PROP. */
3800
3801static int
3802display_prop_string_p (prop, string)
3803 Lisp_Object prop, string;
3804{
74bd6d65
GM
3805 if (CONSP (prop)
3806 && CONSP (XCAR (prop))
3807 && !EQ (Qmargin, XCAR (XCAR (prop))))
3808 {
3809 /* A list of sub-properties. */
3810 while (CONSP (prop))
3811 {
3812 if (single_display_prop_string_p (XCAR (prop), string))
3813 return 1;
3814 prop = XCDR (prop);
3815 }
3816 }
3817 else if (VECTORP (prop))
3818 {
3819 /* A vector of sub-properties. */
3820 int i;
3821 for (i = 0; i < ASIZE (prop); ++i)
3822 if (single_display_prop_string_p (AREF (prop, i), string))
3823 return 1;
3824 }
3825 else
3826 return single_display_prop_string_p (prop, string);
3827
3828 return 0;
3829}
3830
3831
3832/* Determine from which buffer position in W's buffer STRING comes
3833 from. AROUND_CHARPOS is an approximate position where it could
3834 be from. Value is the buffer position or 0 if it couldn't be
3835 determined.
3836
3837 W's buffer must be current.
3838
3839 This function is necessary because we don't record buffer positions
3840 in glyphs generated from strings (to keep struct glyph small).
3841 This function may only use code that doesn't eval because it is
3842 called asynchronously from note_mouse_highlight. */
3843
3844int
3845string_buffer_position (w, string, around_charpos)
3846 struct window *w;
3847 Lisp_Object string;
3848 int around_charpos;
3849{
74bd6d65
GM
3850 Lisp_Object limit, prop, pos;
3851 const int MAX_DISTANCE = 1000;
3852 int found = 0;
3853
d8731202 3854 pos = make_number (around_charpos);
74bd6d65
GM
3855 limit = make_number (min (XINT (pos) + MAX_DISTANCE, ZV));
3856 while (!found && !EQ (pos, limit))
3857 {
3858 prop = Fget_char_property (pos, Qdisplay, Qnil);
3859 if (!NILP (prop) && display_prop_string_p (prop, string))
3860 found = 1;
3861 else
134d9283 3862 pos = Fnext_single_char_property_change (pos, Qdisplay, Qnil, limit);
74bd6d65
GM
3863 }
3864
3865 if (!found)
3866 {
d8731202 3867 pos = make_number (around_charpos);
74bd6d65
GM
3868 limit = make_number (max (XINT (pos) - MAX_DISTANCE, BEGV));
3869 while (!found && !EQ (pos, limit))
3870 {
3871 prop = Fget_char_property (pos, Qdisplay, Qnil);
3872 if (!NILP (prop) && display_prop_string_p (prop, string))
3873 found = 1;
3874 else
134d9283
GM
3875 pos = Fprevious_single_char_property_change (pos, Qdisplay, Qnil,
3876 limit);
74bd6d65
GM
3877 }
3878 }
3879
3880 return found ? XINT (pos) : 0;
3881}
3882
3883
5f5c8ee5 3884\f
260a86a0
KH
3885/***********************************************************************
3886 `composition' property
3887 ***********************************************************************/
3888
df013a7f
KH
3889static enum prop_handled
3890handle_auto_composed_prop (it)
3891 struct it *it;
3892{
3893 enum prop_handled handled = HANDLED_NORMALLY;
3894
e53d2f00 3895 if (FUNCTIONP (Vauto_composition_function))
df013a7f
KH
3896 {
3897 Lisp_Object val;
e53d2f00 3898 EMACS_INT pos, this_pos;
df013a7f
KH
3899
3900 if (STRINGP (it->string))
3901 pos = IT_STRING_CHARPOS (*it);
3902 else
3903 pos = IT_CHARPOS (*it);
e53d2f00 3904 this_pos = pos;
df013a7f
KH
3905
3906 val =Fget_char_property (make_number (pos), Qauto_composed, it->string);
e53d2f00
KH
3907 if (! NILP (val))
3908 {
c0c99152
KH
3909 Lisp_Object limit = Qnil, next;
3910
3911 /* As Fnext_single_char_property_change is very slow, we
3912 limit the search to the current line. */
3b0fab0e 3913 if (STRINGP (it->string))
d834b493 3914 limit = make_number (SCHARS (it->string));
3b0fab0e 3915 else
c0c99152 3916 limit = make_number (find_next_newline_no_quit (pos, 1));
3b0fab0e 3917
e53d2f00 3918 next = (Fnext_single_property_change
c0c99152
KH
3919 (make_number (pos), Qauto_composed, it->string, limit));
3920 if (XINT (next) < XINT (limit))
e53d2f00
KH
3921 {
3922 /* The current point is auto-composed, but there exist
c0c99152 3923 characters not yet composed beyond the auto-composed
e53d2f00
KH
3924 region. There's a possiblity that the last
3925 characters in the region may be newly composed. */
3926 int charpos = XINT (next) - 1, bytepos, c;
3927
3928 if (STRINGP (it->string))
3929 {
3930 bytepos = string_char_to_byte (it->string, charpos);
3931 c = SDATA (it->string)[bytepos];
3932 }
3933 else
3934 {
3935 bytepos = CHAR_TO_BYTE (charpos);
3936 c = FETCH_BYTE (bytepos);
3937 }
3938 if (c != '\n')
3939 /* If the last character is not newline, it may be
3940 composed with the following characters. */
3941 val = Qnil, pos = charpos + 1;
3942 }
3943 }
df013a7f
KH
3944 if (NILP (val))
3945 {
8f924df7 3946 int count = SPECPDL_INDEX ();
df013a7f
KH
3947 Lisp_Object args[3];
3948
3949 args[0] = Vauto_composition_function;
3950 specbind (Qauto_composition_function, Qnil);
3951 args[1] = make_number (pos);
3952 args[2] = it->string;
3953 safe_call (3, args);
3954 unbind_to (count, Qnil);
3955
c0c99152
KH
3956 if (this_pos == pos)
3957 {
3958 val = Fget_char_property (args[1], Qauto_composed, it->string);
3959 /* Return HANDLED_RECOMPUTE_PROPS only if function composed
3960 something. This avoids an endless loop if they failed to
3961 fontify the text for which reason ever. */
3962 if (! NILP (val))
3963 handled = HANDLED_RECOMPUTE_PROPS;
3964 }
3965 else
df013a7f
KH
3966 handled = HANDLED_RECOMPUTE_PROPS;
3967 }
3968 }
3969
3970 return handled;
3971}
3972
260a86a0
KH
3973/* Set up iterator IT from `composition' property at its current
3974 position. Called from handle_stop. */
3975
3976static enum prop_handled
3977handle_composition_prop (it)
3978 struct it *it;
3979{
3980 Lisp_Object prop, string;
e53d2f00 3981 EMACS_INT pos, pos_byte, start, end;
260a86a0
KH
3982 enum prop_handled handled = HANDLED_NORMALLY;
3983
3984 if (STRINGP (it->string))
3985 {
3986 pos = IT_STRING_CHARPOS (*it);
3987 pos_byte = IT_STRING_BYTEPOS (*it);
3988 string = it->string;
3989 }
3990 else
3991 {
3992 pos = IT_CHARPOS (*it);
3993 pos_byte = IT_BYTEPOS (*it);
3994 string = Qnil;
3995 }
3996
3997 /* If there's a valid composition and point is not inside of the
3998 composition (in the case that the composition is from the current
3999 buffer), draw a glyph composed from the composition components. */
e53d2f00
KH
4000 if (find_composition (pos, -1, &start, &end, &prop, string)
4001 && COMPOSITION_VALID_P (start, end, prop)
4002 && (STRINGP (it->string) || (PT <= start || PT >= end)))
260a86a0 4003 {
e53d2f00
KH
4004 int id;
4005
4006 if (start != pos)
4007 {
4008 if (STRINGP (it->string))
4009 pos_byte = string_char_to_byte (it->string, start);
4010 else
4011 pos_byte = CHAR_TO_BYTE (start);
4012 }
4013 id = get_composition_id (start, pos_byte, end - start, prop, string);
260a86a0
KH
4014
4015 if (id >= 0)
4016 {
4017 it->method = next_element_from_composition;
4018 it->cmp_id = id;
4019 it->cmp_len = COMPOSITION_LENGTH (prop);
4020 /* For a terminal, draw only the first character of the
4021 components. */
4022 it->c = COMPOSITION_GLYPH (composition_table[id], 0);
4023 it->len = (STRINGP (it->string)
4024 ? string_char_to_byte (it->string, end)
4025 : CHAR_TO_BYTE (end)) - pos_byte;
4026 it->stop_charpos = end;
4027 handled = HANDLED_RETURN;
4028 }
4029 }
4030
4031 return handled;
4032}
4033
4034
4035\f
5f5c8ee5
GM
4036/***********************************************************************
4037 Overlay strings
4038 ***********************************************************************/
4039
4040/* The following structure is used to record overlay strings for
4041 later sorting in load_overlay_strings. */
4042
4043struct overlay_entry
4044{
2970b9be 4045 Lisp_Object overlay;
5f5c8ee5
GM
4046 Lisp_Object string;
4047 int priority;
4048 int after_string_p;
4049};
4050
4051
4052/* Set up iterator IT from overlay strings at its current position.
4053 Called from handle_stop. */
4054
4055static enum prop_handled
4056handle_overlay_change (it)
4057 struct it *it;
4058{
5a08cbaf 4059 if (!STRINGP (it->string) && get_overlay_strings (it, 0))
2970b9be 4060 return HANDLED_RECOMPUTE_PROPS;
5f5c8ee5 4061 else
2970b9be 4062 return HANDLED_NORMALLY;
5f5c8ee5
GM
4063}
4064
4065
4066/* Set up the next overlay string for delivery by IT, if there is an
4067 overlay string to deliver. Called by set_iterator_to_next when the
4068 end of the current overlay string is reached. If there are more
4069 overlay strings to display, IT->string and
4070 IT->current.overlay_string_index are set appropriately here.
4071 Otherwise IT->string is set to nil. */
2311178e 4072
5f5c8ee5
GM
4073static void
4074next_overlay_string (it)
4075 struct it *it;
4076{
4077 ++it->current.overlay_string_index;
4078 if (it->current.overlay_string_index == it->n_overlay_strings)
4079 {
4080 /* No more overlay strings. Restore IT's settings to what
4081 they were before overlay strings were processed, and
4082 continue to deliver from current_buffer. */
5a08cbaf 4083 int display_ellipsis_p = it->stack[it->sp - 1].display_ellipsis_p;
2311178e 4084
5f5c8ee5
GM
4085 pop_it (it);
4086 xassert (it->stop_charpos >= BEGV
4087 && it->stop_charpos <= it->end_charpos);
4088 it->string = Qnil;
4089 it->current.overlay_string_index = -1;
4090 SET_TEXT_POS (it->current.string_pos, -1, -1);
4091 it->n_overlay_strings = 0;
4092 it->method = next_element_from_buffer;
2970b9be
GM
4093
4094 /* If we're at the end of the buffer, record that we have
4095 processed the overlay strings there already, so that
4096 next_element_from_buffer doesn't try it again. */
4097 if (IT_CHARPOS (*it) >= it->end_charpos)
4098 it->overlay_strings_at_end_processed_p = 1;
5a08cbaf
GM
4099
4100 /* If we have to display `...' for invisible text, set
4101 the iterator up for that. */
4102 if (display_ellipsis_p)
4103 setup_for_ellipsis (it);
5f5c8ee5
GM
4104 }
4105 else
4106 {
4107 /* There are more overlay strings to process. If
4108 IT->current.overlay_string_index has advanced to a position
4109 where we must load IT->overlay_strings with more strings, do
4110 it. */
4111 int i = it->current.overlay_string_index % OVERLAY_STRING_CHUNK_SIZE;
2311178e 4112
5f5c8ee5 4113 if (it->current.overlay_string_index && i == 0)
5a08cbaf 4114 load_overlay_strings (it, 0);
5f5c8ee5
GM
4115
4116 /* Initialize IT to deliver display elements from the overlay
4117 string. */
4118 it->string = it->overlay_strings[i];
4119 it->multibyte_p = STRING_MULTIBYTE (it->string);
4120 SET_TEXT_POS (it->current.string_pos, 0, 0);
4121 it->method = next_element_from_string;
4122 it->stop_charpos = 0;
4123 }
2311178e 4124
5f5c8ee5
GM
4125 CHECK_IT (it);
4126}
4127
4128
4129/* Compare two overlay_entry structures E1 and E2. Used as a
4130 comparison function for qsort in load_overlay_strings. Overlay
4131 strings for the same position are sorted so that
4132
2970b9be
GM
4133 1. All after-strings come in front of before-strings, except
4134 when they come from the same overlay.
2311178e 4135
5f5c8ee5
GM
4136 2. Within after-strings, strings are sorted so that overlay strings
4137 from overlays with higher priorities come first.
4138
4139 2. Within before-strings, strings are sorted so that overlay
4140 strings from overlays with higher priorities come last.
4141
4142 Value is analogous to strcmp. */
4143
2311178e 4144
5f5c8ee5
GM
4145static int
4146compare_overlay_entries (e1, e2)
4147 void *e1, *e2;
4148{
4149 struct overlay_entry *entry1 = (struct overlay_entry *) e1;
4150 struct overlay_entry *entry2 = (struct overlay_entry *) e2;
4151 int result;
4152
4153 if (entry1->after_string_p != entry2->after_string_p)
2970b9be
GM
4154 {
4155 /* Let after-strings appear in front of before-strings if
4156 they come from different overlays. */
4157 if (EQ (entry1->overlay, entry2->overlay))
4158 result = entry1->after_string_p ? 1 : -1;
4159 else
4160 result = entry1->after_string_p ? -1 : 1;
4161 }
5f5c8ee5
GM
4162 else if (entry1->after_string_p)
4163 /* After-strings sorted in order of decreasing priority. */
4164 result = entry2->priority - entry1->priority;
4165 else
4166 /* Before-strings sorted in order of increasing priority. */
4167 result = entry1->priority - entry2->priority;
4168
4169 return result;
4170}
4171
4172
4173/* Load the vector IT->overlay_strings with overlay strings from IT's
5a08cbaf
GM
4174 current buffer position, or from CHARPOS if that is > 0. Set
4175 IT->n_overlays to the total number of overlay strings found.
5f5c8ee5
GM
4176
4177 Overlay strings are processed OVERLAY_STRING_CHUNK_SIZE strings at
4178 a time. On entry into load_overlay_strings,
4179 IT->current.overlay_string_index gives the number of overlay
4180 strings that have already been loaded by previous calls to this
4181 function.
4182
2970b9be
GM
4183 IT->add_overlay_start contains an additional overlay start
4184 position to consider for taking overlay strings from, if non-zero.
4185 This position comes into play when the overlay has an `invisible'
4186 property, and both before and after-strings. When we've skipped to
4187 the end of the overlay, because of its `invisible' property, we
4188 nevertheless want its before-string to appear.
4189 IT->add_overlay_start will contain the overlay start position
4190 in this case.
4191
5f5c8ee5
GM
4192 Overlay strings are sorted so that after-string strings come in
4193 front of before-string strings. Within before and after-strings,
4194 strings are sorted by overlay priority. See also function
4195 compare_overlay_entries. */
2311178e 4196
5f5c8ee5 4197static void
5a08cbaf 4198load_overlay_strings (it, charpos)
5f5c8ee5 4199 struct it *it;
5a08cbaf 4200 int charpos;
5f5c8ee5
GM
4201{
4202 extern Lisp_Object Qafter_string, Qbefore_string, Qwindow, Qpriority;
b7253a3e
SM
4203 Lisp_Object overlay, window, str, invisible;
4204 struct Lisp_Overlay *ov;
5f5c8ee5
GM
4205 int start, end;
4206 int size = 20;
cafafe0b 4207 int n = 0, i, j, invis_p;
5f5c8ee5
GM
4208 struct overlay_entry *entries
4209 = (struct overlay_entry *) alloca (size * sizeof *entries);
5a08cbaf
GM
4210
4211 if (charpos <= 0)
4212 charpos = IT_CHARPOS (*it);
5f5c8ee5
GM
4213
4214 /* Append the overlay string STRING of overlay OVERLAY to vector
4215 `entries' which has size `size' and currently contains `n'
4216 elements. AFTER_P non-zero means STRING is an after-string of
4217 OVERLAY. */
4218#define RECORD_OVERLAY_STRING(OVERLAY, STRING, AFTER_P) \
4219 do \
4220 { \
4221 Lisp_Object priority; \
4222 \
4223 if (n == size) \
4224 { \
4225 int new_size = 2 * size; \
4226 struct overlay_entry *old = entries; \
4227 entries = \
4228 (struct overlay_entry *) alloca (new_size \
4229 * sizeof *entries); \
4230 bcopy (old, entries, size * sizeof *entries); \
4231 size = new_size; \
4232 } \
4233 \
4234 entries[n].string = (STRING); \
2970b9be 4235 entries[n].overlay = (OVERLAY); \
5f5c8ee5 4236 priority = Foverlay_get ((OVERLAY), Qpriority); \
2970b9be 4237 entries[n].priority = INTEGERP (priority) ? XINT (priority) : 0; \
5f5c8ee5
GM
4238 entries[n].after_string_p = (AFTER_P); \
4239 ++n; \
4240 } \
4241 while (0)
4242
4243 /* Process overlay before the overlay center. */
b7253a3e 4244 for (ov = current_buffer->overlays_before; ov; ov = ov->next)
5f5c8ee5 4245 {
b7253a3e 4246 XSETMISC (overlay, ov);
5f5c8ee5
GM
4247 xassert (OVERLAYP (overlay));
4248 start = OVERLAY_POSITION (OVERLAY_START (overlay));
4249 end = OVERLAY_POSITION (OVERLAY_END (overlay));
2311178e 4250
cafafe0b 4251 if (end < charpos)
5f5c8ee5
GM
4252 break;
4253
4254 /* Skip this overlay if it doesn't start or end at IT's current
4255 position. */
cafafe0b 4256 if (end != charpos && start != charpos)
5f5c8ee5 4257 continue;
2311178e 4258
5f5c8ee5
GM
4259 /* Skip this overlay if it doesn't apply to IT->w. */
4260 window = Foverlay_get (overlay, Qwindow);
4261 if (WINDOWP (window) && XWINDOW (window) != it->w)
4262 continue;
4263
cafafe0b
GM
4264 /* If the text ``under'' the overlay is invisible, both before-
4265 and after-strings from this overlay are visible; start and
4266 end position are indistinguishable. */
4267 invisible = Foverlay_get (overlay, Qinvisible);
4268 invis_p = TEXT_PROP_MEANS_INVISIBLE (invisible);
4269
5f5c8ee5 4270 /* If overlay has a non-empty before-string, record it. */
cafafe0b 4271 if ((start == charpos || (end == charpos && invis_p))
5f5c8ee5 4272 && (str = Foverlay_get (overlay, Qbefore_string), STRINGP (str))
2051c264 4273 && SCHARS (str))
5f5c8ee5 4274 RECORD_OVERLAY_STRING (overlay, str, 0);
2311178e 4275
5f5c8ee5 4276 /* If overlay has a non-empty after-string, record it. */
cafafe0b 4277 if ((end == charpos || (start == charpos && invis_p))
5f5c8ee5 4278 && (str = Foverlay_get (overlay, Qafter_string), STRINGP (str))
2051c264 4279 && SCHARS (str))
5f5c8ee5
GM
4280 RECORD_OVERLAY_STRING (overlay, str, 1);
4281 }
2311178e 4282
5f5c8ee5 4283 /* Process overlays after the overlay center. */
b7253a3e 4284 for (ov = current_buffer->overlays_after; ov; ov = ov->next)
5f5c8ee5 4285 {
b7253a3e 4286 XSETMISC (overlay, ov);
5f5c8ee5
GM
4287 xassert (OVERLAYP (overlay));
4288 start = OVERLAY_POSITION (OVERLAY_START (overlay));
4289 end = OVERLAY_POSITION (OVERLAY_END (overlay));
4290
cafafe0b 4291 if (start > charpos)
5f5c8ee5 4292 break;
2311178e 4293
5f5c8ee5
GM
4294 /* Skip this overlay if it doesn't start or end at IT's current
4295 position. */
cafafe0b 4296 if (end != charpos && start != charpos)
5f5c8ee5
GM
4297 continue;
4298
4299 /* Skip this overlay if it doesn't apply to IT->w. */
4300 window = Foverlay_get (overlay, Qwindow);
4301 if (WINDOWP (window) && XWINDOW (window) != it->w)
4302 continue;
2311178e 4303
cafafe0b
GM
4304 /* If the text ``under'' the overlay is invisible, it has a zero
4305 dimension, and both before- and after-strings apply. */
4306 invisible = Foverlay_get (overlay, Qinvisible);
4307 invis_p = TEXT_PROP_MEANS_INVISIBLE (invisible);
4308
5f5c8ee5 4309 /* If overlay has a non-empty before-string, record it. */
cafafe0b 4310 if ((start == charpos || (end == charpos && invis_p))
5f5c8ee5 4311 && (str = Foverlay_get (overlay, Qbefore_string), STRINGP (str))
2051c264 4312 && SCHARS (str))
5f5c8ee5 4313 RECORD_OVERLAY_STRING (overlay, str, 0);
2311178e 4314
5f5c8ee5 4315 /* If overlay has a non-empty after-string, record it. */
cafafe0b 4316 if ((end == charpos || (start == charpos && invis_p))
5f5c8ee5 4317 && (str = Foverlay_get (overlay, Qafter_string), STRINGP (str))
2051c264 4318 && SCHARS (str))
5f5c8ee5
GM
4319 RECORD_OVERLAY_STRING (overlay, str, 1);
4320 }
4321
4322#undef RECORD_OVERLAY_STRING
2311178e 4323
5f5c8ee5 4324 /* Sort entries. */
cafafe0b 4325 if (n > 1)
2970b9be 4326 qsort (entries, n, sizeof *entries, compare_overlay_entries);
5f5c8ee5
GM
4327
4328 /* Record the total number of strings to process. */
4329 it->n_overlay_strings = n;
4330
4331 /* IT->current.overlay_string_index is the number of overlay strings
4332 that have already been consumed by IT. Copy some of the
4333 remaining overlay strings to IT->overlay_strings. */
4334 i = 0;
4335 j = it->current.overlay_string_index;
4336 while (i < OVERLAY_STRING_CHUNK_SIZE && j < n)
4337 it->overlay_strings[i++] = entries[j++].string;
2970b9be 4338
5f5c8ee5
GM
4339 CHECK_IT (it);
4340}
4341
4342
4343/* Get the first chunk of overlay strings at IT's current buffer
5a08cbaf
GM
4344 position, or at CHARPOS if that is > 0. Value is non-zero if at
4345 least one overlay string was found. */
5f5c8ee5
GM
4346
4347static int
5a08cbaf 4348get_overlay_strings (it, charpos)
5f5c8ee5 4349 struct it *it;
5a08cbaf 4350 int charpos;
5f5c8ee5
GM
4351{
4352 /* Get the first OVERLAY_STRING_CHUNK_SIZE overlay strings to
4353 process. This fills IT->overlay_strings with strings, and sets
4354 IT->n_overlay_strings to the total number of strings to process.
4355 IT->pos.overlay_string_index has to be set temporarily to zero
4356 because load_overlay_strings needs this; it must be set to -1
4357 when no overlay strings are found because a zero value would
4358 indicate a position in the first overlay string. */
4359 it->current.overlay_string_index = 0;
5a08cbaf 4360 load_overlay_strings (it, charpos);
5f5c8ee5
GM
4361
4362 /* If we found overlay strings, set up IT to deliver display
4363 elements from the first one. Otherwise set up IT to deliver
4364 from current_buffer. */
4365 if (it->n_overlay_strings)
4366 {
4367 /* Make sure we know settings in current_buffer, so that we can
4368 restore meaningful values when we're done with the overlay
4369 strings. */
4370 compute_stop_pos (it);
4371 xassert (it->face_id >= 0);
2311178e 4372
5f5c8ee5
GM
4373 /* Save IT's settings. They are restored after all overlay
4374 strings have been processed. */
4375 xassert (it->sp == 0);
4376 push_it (it);
4377
4378 /* Set up IT to deliver display elements from the first overlay
4379 string. */
4380 IT_STRING_CHARPOS (*it) = IT_STRING_BYTEPOS (*it) = 0;
5f5c8ee5 4381 it->string = it->overlay_strings[0];
b2046df8 4382 it->stop_charpos = 0;
5f5c8ee5 4383 xassert (STRINGP (it->string));
2051c264 4384 it->end_charpos = SCHARS (it->string);
d5db4077 4385 it->multibyte_p = STRING_MULTIBYTE (it->string);
5f5c8ee5
GM
4386 it->method = next_element_from_string;
4387 }
4388 else
4389 {
4390 it->string = Qnil;
4391 it->current.overlay_string_index = -1;
4392 it->method = next_element_from_buffer;
4393 }
4394
4395 CHECK_IT (it);
4396
4397 /* Value is non-zero if we found at least one overlay string. */
4398 return STRINGP (it->string);
4399}
4400
4401
4402\f
4403/***********************************************************************
4404 Saving and restoring state
4405 ***********************************************************************/
4406
4407/* Save current settings of IT on IT->stack. Called, for example,
4408 before setting up IT for an overlay string, to be able to restore
4409 IT's settings to what they were after the overlay string has been
4410 processed. */
4411
4412static void
4413push_it (it)
4414 struct it *it;
4415{
4416 struct iterator_stack_entry *p;
2311178e 4417
5f5c8ee5
GM
4418 xassert (it->sp < 2);
4419 p = it->stack + it->sp;
4420
4421 p->stop_charpos = it->stop_charpos;
4422 xassert (it->face_id >= 0);
4423 p->face_id = it->face_id;
4424 p->string = it->string;
4425 p->pos = it->current;
4426 p->end_charpos = it->end_charpos;
4427 p->string_nchars = it->string_nchars;
4428 p->area = it->area;
4429 p->multibyte_p = it->multibyte_p;
4430 p->space_width = it->space_width;
4431 p->font_height = it->font_height;
4432 p->voffset = it->voffset;
4433 p->string_from_display_prop_p = it->string_from_display_prop_p;
5a08cbaf 4434 p->display_ellipsis_p = 0;
5f5c8ee5
GM
4435 ++it->sp;
4436}
4437
4438
4439/* Restore IT's settings from IT->stack. Called, for example, when no
4440 more overlay strings must be processed, and we return to delivering
4441 display elements from a buffer, or when the end of a string from a
4442 `display' property is reached and we return to delivering display
4443 elements from an overlay string, or from a buffer. */
4444
4445static void
4446pop_it (it)
4447 struct it *it;
4448{
4449 struct iterator_stack_entry *p;
2311178e 4450
5f5c8ee5
GM
4451 xassert (it->sp > 0);
4452 --it->sp;
4453 p = it->stack + it->sp;
4454 it->stop_charpos = p->stop_charpos;
4455 it->face_id = p->face_id;
4456 it->string = p->string;
4457 it->current = p->pos;
4458 it->end_charpos = p->end_charpos;
4459 it->string_nchars = p->string_nchars;
4460 it->area = p->area;
4461 it->multibyte_p = p->multibyte_p;
4462 it->space_width = p->space_width;
4463 it->font_height = p->font_height;
4464 it->voffset = p->voffset;
4465 it->string_from_display_prop_p = p->string_from_display_prop_p;
4466}
4467
4468
4469\f
4470/***********************************************************************
4471 Moving over lines
4472 ***********************************************************************/
4473
4474/* Set IT's current position to the previous line start. */
4475
4476static void
4477back_to_previous_line_start (it)
4478 struct it *it;
4479{
4480 IT_CHARPOS (*it) = find_next_newline_no_quit (IT_CHARPOS (*it) - 1, -1);
4481 IT_BYTEPOS (*it) = CHAR_TO_BYTE (IT_CHARPOS (*it));
4482}
4483
4484
cafafe0b 4485/* Move IT to the next line start.
2311178e 4486
cafafe0b
GM
4487 Value is non-zero if a newline was found. Set *SKIPPED_P to 1 if
4488 we skipped over part of the text (as opposed to moving the iterator
4489 continuously over the text). Otherwise, don't change the value
4490 of *SKIPPED_P.
2311178e 4491
cafafe0b
GM
4492 Newlines may come from buffer text, overlay strings, or strings
4493 displayed via the `display' property. That's the reason we can't
0fd37545
GM
4494 simply use find_next_newline_no_quit.
4495
4496 Note that this function may not skip over invisible text that is so
4497 because of text properties and immediately follows a newline. If
4498 it would, function reseat_at_next_visible_line_start, when called
4499 from set_iterator_to_next, would effectively make invisible
4500 characters following a newline part of the wrong glyph row, which
4501 leads to wrong cursor motion. */
5f5c8ee5 4502
cafafe0b
GM
4503static int
4504forward_to_next_line_start (it, skipped_p)
5f5c8ee5 4505 struct it *it;
cafafe0b 4506 int *skipped_p;
5f5c8ee5 4507{
54918e2b 4508 int old_selective, newline_found_p, n;
cafafe0b
GM
4509 const int MAX_NEWLINE_DISTANCE = 500;
4510
0fd37545
GM
4511 /* If already on a newline, just consume it to avoid unintended
4512 skipping over invisible text below. */
51695746
GM
4513 if (it->what == IT_CHARACTER
4514 && it->c == '\n'
4515 && CHARPOS (it->position) == IT_CHARPOS (*it))
0fd37545
GM
4516 {
4517 set_iterator_to_next (it, 0);
a77dc1ec 4518 it->c = 0;
0fd37545
GM
4519 return 1;
4520 }
4521
54918e2b 4522 /* Don't handle selective display in the following. It's (a)
0fd37545
GM
4523 unnecessary because it's done by the caller, and (b) leads to an
4524 infinite recursion because next_element_from_ellipsis indirectly
4525 calls this function. */
54918e2b
GM
4526 old_selective = it->selective;
4527 it->selective = 0;
4528
cafafe0b
GM
4529 /* Scan for a newline within MAX_NEWLINE_DISTANCE display elements
4530 from buffer text. */
3aec8722
GM
4531 for (n = newline_found_p = 0;
4532 !newline_found_p && n < MAX_NEWLINE_DISTANCE;
4533 n += STRINGP (it->string) ? 0 : 1)
cafafe0b 4534 {
8692ca92 4535 if (!get_next_display_element (it))
d43be70c 4536 return 0;
d02f1cb8 4537 newline_found_p = it->what == IT_CHARACTER && it->c == '\n';
cafafe0b 4538 set_iterator_to_next (it, 0);
cafafe0b
GM
4539 }
4540
4541 /* If we didn't find a newline near enough, see if we can use a
4542 short-cut. */
db0bb807 4543 if (!newline_found_p)
cafafe0b
GM
4544 {
4545 int start = IT_CHARPOS (*it);
4546 int limit = find_next_newline_no_quit (start, 1);
4547 Lisp_Object pos;
4548
4549 xassert (!STRINGP (it->string));
4550
4551 /* If there isn't any `display' property in sight, and no
4552 overlays, we can just use the position of the newline in
4553 buffer text. */
4554 if (it->stop_charpos >= limit
4555 || ((pos = Fnext_single_property_change (make_number (start),
4556 Qdisplay,
4557 Qnil, make_number (limit)),
4558 NILP (pos))
4559 && next_overlay_change (start) == ZV))
4560 {
4561 IT_CHARPOS (*it) = limit;
4562 IT_BYTEPOS (*it) = CHAR_TO_BYTE (limit);
4563 *skipped_p = newline_found_p = 1;
4564 }
4565 else
4566 {
4567 while (get_next_display_element (it)
4568 && !newline_found_p)
4569 {
4570 newline_found_p = ITERATOR_AT_END_OF_LINE_P (it);
4571 set_iterator_to_next (it, 0);
4572 }
4573 }
4574 }
4575
54918e2b 4576 it->selective = old_selective;
cafafe0b 4577 return newline_found_p;
5f5c8ee5
GM
4578}
4579
4580
4581/* Set IT's current position to the previous visible line start. Skip
4582 invisible text that is so either due to text properties or due to
4583 selective display. Caution: this does not change IT->current_x and
4584 IT->hpos. */
4585
4586static void
4587back_to_previous_visible_line_start (it)
4588 struct it *it;
4589{
4590 int visible_p = 0;
4591
4592 /* Go back one newline if not on BEGV already. */
4593 if (IT_CHARPOS (*it) > BEGV)
4594 back_to_previous_line_start (it);
4595
4596 /* Move over lines that are invisible because of selective display
4597 or text properties. */
4598 while (IT_CHARPOS (*it) > BEGV
4599 && !visible_p)
4600 {
4601 visible_p = 1;
4602
4603 /* If selective > 0, then lines indented more than that values
4604 are invisible. */
4605 if (it->selective > 0
4606 && indented_beyond_p (IT_CHARPOS (*it), IT_BYTEPOS (*it),
a67e162b 4607 (double) it->selective)) /* iftc */
5f5c8ee5 4608 visible_p = 0;
2311178e 4609 else
5f5c8ee5
GM
4610 {
4611 Lisp_Object prop;
4612
6fc556fd
KR
4613 prop = Fget_char_property (make_number (IT_CHARPOS (*it)),
4614 Qinvisible, it->window);
5f5c8ee5
GM
4615 if (TEXT_PROP_MEANS_INVISIBLE (prop))
4616 visible_p = 0;
4617 }
5f5c8ee5
GM
4618
4619 /* Back one more newline if the current one is invisible. */
4620 if (!visible_p)
4621 back_to_previous_line_start (it);
4622 }
4623
4624 xassert (IT_CHARPOS (*it) >= BEGV);
4625 xassert (IT_CHARPOS (*it) == BEGV
4626 || FETCH_BYTE (IT_BYTEPOS (*it) - 1) == '\n');
4627 CHECK_IT (it);
4628}
4629
4630
4631/* Reseat iterator IT at the previous visible line start. Skip
4632 invisible text that is so either due to text properties or due to
4633 selective display. At the end, update IT's overlay information,
4634 face information etc. */
4635
4636static void
4637reseat_at_previous_visible_line_start (it)
4638 struct it *it;
4639{
4640 back_to_previous_visible_line_start (it);
4641 reseat (it, it->current.pos, 1);
4642 CHECK_IT (it);
4643}
4644
4645
4646/* Reseat iterator IT on the next visible line start in the current
312246d1
GM
4647 buffer. ON_NEWLINE_P non-zero means position IT on the newline
4648 preceding the line start. Skip over invisible text that is so
4649 because of selective display. Compute faces, overlays etc at the
4650 new position. Note that this function does not skip over text that
4651 is invisible because of text properties. */
5f5c8ee5
GM
4652
4653static void
312246d1 4654reseat_at_next_visible_line_start (it, on_newline_p)
5f5c8ee5 4655 struct it *it;
312246d1 4656 int on_newline_p;
5f5c8ee5 4657{
cafafe0b
GM
4658 int newline_found_p, skipped_p = 0;
4659
4660 newline_found_p = forward_to_next_line_start (it, &skipped_p);
4661
4662 /* Skip over lines that are invisible because they are indented
4663 more than the value of IT->selective. */
4664 if (it->selective > 0)
4665 while (IT_CHARPOS (*it) < ZV
a77dc1ec 4666 && indented_beyond_p (IT_CHARPOS (*it), IT_BYTEPOS (*it),
a67e162b 4667 (double) it->selective)) /* iftc */
a77dc1ec
GM
4668 {
4669 xassert (FETCH_BYTE (IT_BYTEPOS (*it) - 1) == '\n');
4670 newline_found_p = forward_to_next_line_start (it, &skipped_p);
4671 }
cafafe0b
GM
4672
4673 /* Position on the newline if that's what's requested. */
4674 if (on_newline_p && newline_found_p)
5f5c8ee5 4675 {
cafafe0b 4676 if (STRINGP (it->string))
5f5c8ee5 4677 {
cafafe0b
GM
4678 if (IT_STRING_CHARPOS (*it) > 0)
4679 {
4680 --IT_STRING_CHARPOS (*it);
4681 --IT_STRING_BYTEPOS (*it);
4682 }
5f5c8ee5 4683 }
cafafe0b 4684 else if (IT_CHARPOS (*it) > BEGV)
312246d1
GM
4685 {
4686 --IT_CHARPOS (*it);
cafafe0b
GM
4687 --IT_BYTEPOS (*it);
4688 reseat (it, it->current.pos, 0);
312246d1 4689 }
5f5c8ee5 4690 }
cafafe0b
GM
4691 else if (skipped_p)
4692 reseat (it, it->current.pos, 0);
2311178e 4693
5f5c8ee5
GM
4694 CHECK_IT (it);
4695}
4696
4697
4698\f
4699/***********************************************************************
4700 Changing an iterator's position
4701***********************************************************************/
4702
4703/* Change IT's current position to POS in current_buffer. If FORCE_P
4704 is non-zero, always check for text properties at the new position.
4705 Otherwise, text properties are only looked up if POS >=
4706 IT->check_charpos of a property. */
4707
4708static void
4709reseat (it, pos, force_p)
4710 struct it *it;
4711 struct text_pos pos;
4712 int force_p;
4713{
4714 int original_pos = IT_CHARPOS (*it);
4715
4716 reseat_1 (it, pos, 0);
4717
4718 /* Determine where to check text properties. Avoid doing it
4719 where possible because text property lookup is very expensive. */
4720 if (force_p
4721 || CHARPOS (pos) > it->stop_charpos
4722 || CHARPOS (pos) < original_pos)
4723 handle_stop (it);
4724
4725 CHECK_IT (it);
4726}
4727
4728
4729/* Change IT's buffer position to POS. SET_STOP_P non-zero means set
4730 IT->stop_pos to POS, also. */
4731
4732static void
4733reseat_1 (it, pos, set_stop_p)
4734 struct it *it;
4735 struct text_pos pos;
4736 int set_stop_p;
4737{
4738 /* Don't call this function when scanning a C string. */
4739 xassert (it->s == NULL);
4740
4741 /* POS must be a reasonable value. */
4742 xassert (CHARPOS (pos) >= BEGV && CHARPOS (pos) <= ZV);
4743
4744 it->current.pos = it->position = pos;
4745 XSETBUFFER (it->object, current_buffer);
78c663d8 4746 it->end_charpos = ZV;
5f5c8ee5
GM
4747 it->dpvec = NULL;
4748 it->current.dpvec_index = -1;
4749 it->current.overlay_string_index = -1;
4750 IT_STRING_CHARPOS (*it) = -1;
4751 IT_STRING_BYTEPOS (*it) = -1;
4752 it->string = Qnil;
4753 it->method = next_element_from_buffer;
5905025c
RS
4754 /* RMS: I added this to fix a bug in move_it_vertically_backward
4755 where it->area continued to relate to the starting point
4756 for the backward motion. Bug report from
4757 Nick Roberts <nick@nick.uklinux.net> on 19 May 2003.
4758 However, I am not sure whether reseat still does the right thing
4759 in general after this change. */
4760 it->area = TEXT_AREA;
06fd3792 4761 it->multibyte_p = !NILP (current_buffer->enable_multibyte_characters);
5f5c8ee5 4762 it->sp = 0;
4aad61f8 4763 it->face_before_selective_p = 0;
5f5c8ee5
GM
4764
4765 if (set_stop_p)
4766 it->stop_charpos = CHARPOS (pos);
4767}
4768
4769
4770/* Set up IT for displaying a string, starting at CHARPOS in window W.
4771 If S is non-null, it is a C string to iterate over. Otherwise,
4772 STRING gives a Lisp string to iterate over.
2311178e 4773
5f5c8ee5
GM
4774 If PRECISION > 0, don't return more then PRECISION number of
4775 characters from the string.
4776
4777 If FIELD_WIDTH > 0, return padding spaces until FIELD_WIDTH
4778 characters have been returned. FIELD_WIDTH < 0 means an infinite
4779 field width.
4780
4781 MULTIBYTE = 0 means disable processing of multibyte characters,
4782 MULTIBYTE > 0 means enable it,
4783 MULTIBYTE < 0 means use IT->multibyte_p.
4784
4785 IT must be initialized via a prior call to init_iterator before
4786 calling this function. */
4787
4788static void
4789reseat_to_string (it, s, string, charpos, precision, field_width, multibyte)
4790 struct it *it;
4791 unsigned char *s;
4792 Lisp_Object string;
4793 int charpos;
4794 int precision, field_width, multibyte;
4795{
4796 /* No region in strings. */
4797 it->region_beg_charpos = it->region_end_charpos = -1;
4798
4799 /* No text property checks performed by default, but see below. */
4800 it->stop_charpos = -1;
4801
4802 /* Set iterator position and end position. */
4803 bzero (&it->current, sizeof it->current);
4804 it->current.overlay_string_index = -1;
4805 it->current.dpvec_index = -1;
5f5c8ee5 4806 xassert (charpos >= 0);
2311178e 4807
e719f5ae
GM
4808 /* If STRING is specified, use its multibyteness, otherwise use the
4809 setting of MULTIBYTE, if specified. */
cabf45da 4810 if (multibyte >= 0)
5f5c8ee5 4811 it->multibyte_p = multibyte > 0;
2311178e 4812
5f5c8ee5
GM
4813 if (s == NULL)
4814 {
4815 xassert (STRINGP (string));
4816 it->string = string;
4817 it->s = NULL;
2051c264 4818 it->end_charpos = it->string_nchars = SCHARS (string);
5f5c8ee5
GM
4819 it->method = next_element_from_string;
4820 it->current.string_pos = string_pos (charpos, string);
4821 }
4822 else
4823 {
4824 it->s = s;
4825 it->string = Qnil;
4826
4827 /* Note that we use IT->current.pos, not it->current.string_pos,
4828 for displaying C strings. */
4829 IT_STRING_CHARPOS (*it) = IT_STRING_BYTEPOS (*it) = -1;
4830 if (it->multibyte_p)
4831 {
4832 it->current.pos = c_string_pos (charpos, s, 1);
4833 it->end_charpos = it->string_nchars = number_of_chars (s, 1);
4834 }
4835 else
4836 {
4837 IT_CHARPOS (*it) = IT_BYTEPOS (*it) = charpos;
4838 it->end_charpos = it->string_nchars = strlen (s);
4839 }
2311178e 4840
5f5c8ee5
GM
4841 it->method = next_element_from_c_string;
4842 }
4843
4844 /* PRECISION > 0 means don't return more than PRECISION characters
4845 from the string. */
4846 if (precision > 0 && it->end_charpos - charpos > precision)
4847 it->end_charpos = it->string_nchars = charpos + precision;
4848
4849 /* FIELD_WIDTH > 0 means pad with spaces until FIELD_WIDTH
4850 characters have been returned. FIELD_WIDTH == 0 means don't pad,
4851 FIELD_WIDTH < 0 means infinite field width. This is useful for
4852 padding with `-' at the end of a mode line. */
4853 if (field_width < 0)
4854 field_width = INFINITY;
4855 if (field_width > it->end_charpos - charpos)
4856 it->end_charpos = charpos + field_width;
4857
4858 /* Use the standard display table for displaying strings. */
4859 if (DISP_TABLE_P (Vstandard_display_table))
4860 it->dp = XCHAR_TABLE (Vstandard_display_table);
4861
4862 it->stop_charpos = charpos;
4863 CHECK_IT (it);
4864}
4865
4866
4867\f
4868/***********************************************************************
4869 Iteration
4870 ***********************************************************************/
4871
4872/* Load IT's display element fields with information about the next
4873 display element from the current position of IT. Value is zero if
4874 end of buffer (or C string) is reached. */
4875
4876int
4877get_next_display_element (it)
4878 struct it *it;
4879{
7d0393cf 4880 /* Non-zero means that we found a display element. Zero means that
5f5c8ee5
GM
4881 we hit the end of what we iterate over. Performance note: the
4882 function pointer `method' used here turns out to be faster than
4883 using a sequence of if-statements. */
4884 int success_p = (*it->method) (it);
5f5c8ee5
GM
4885
4886 if (it->what == IT_CHARACTER)
4887 {
4888 /* Map via display table or translate control characters.
4889 IT->c, IT->len etc. have been set to the next character by
4890 the function call above. If we have a display table, and it
4891 contains an entry for IT->c, translate it. Don't do this if
4892 IT->c itself comes from a display table, otherwise we could
4893 end up in an infinite recursion. (An alternative could be to
4894 count the recursion depth of this function and signal an
4895 error when a certain maximum depth is reached.) Is it worth
4896 it? */
4897 if (success_p && it->dpvec == NULL)
4898 {
4899 Lisp_Object dv;
4900
4901 if (it->dp
4902 && (dv = DISP_CHAR_VECTOR (it->dp, it->c),
4903 VECTORP (dv)))
4904 {
4905 struct Lisp_Vector *v = XVECTOR (dv);
4906
4907 /* Return the first character from the display table
4908 entry, if not empty. If empty, don't display the
4909 current character. */
4910 if (v->size)
4911 {
4912 it->dpvec_char_len = it->len;
4913 it->dpvec = v->contents;
4914 it->dpend = v->contents + v->size;
4915 it->current.dpvec_index = 0;
4916 it->method = next_element_from_display_vector;
7eee47cc
GM
4917 success_p = get_next_display_element (it);
4918 }
4919 else
4920 {
4921 set_iterator_to_next (it, 0);
4922 success_p = get_next_display_element (it);
5f5c8ee5 4923 }
5f5c8ee5
GM
4924 }
4925
4926 /* Translate control characters into `\003' or `^C' form.
4927 Control characters coming from a display table entry are
4928 currently not translated because we use IT->dpvec to hold
4929 the translation. This could easily be changed but I
197516c2
KH
4930 don't believe that it is worth doing.
4931
fa831cf8
KH
4932 If it->multibyte_p is nonzero, eight-bit characters and
4933 non-printable multibyte characters are also translated to
4934 octal form.
4935
4936 If it->multibyte_p is zero, eight-bit characters that
4937 don't have corresponding multibyte char code are also
4938 translated to octal form. */
ba197fe6 4939 else if ((it->c < ' '
5f5c8ee5 4940 && (it->area != TEXT_AREA
c6e89d6c 4941 || (it->c != '\n' && it->c != '\t')))
ea0ffe21 4942 || (it->c != '\n' && it->c != '\t'
790ac1c7
KH
4943 && (it->multibyte_p ? !CHAR_PRINTABLE_P (it->c)
4944 : it->c == 127)))
5f5c8ee5
GM
4945 {
4946 /* IT->c is a control character which must be displayed
4947 either as '\003' or as `^C' where the '\\' and '^'
4948 can be defined in the display table. Fill
4949 IT->ctl_chars with glyphs for what we have to
4950 display. Then, set IT->dpvec to these glyphs. */
4951 GLYPH g;
4952
54c85a23 4953 if (it->c < 128 && it->ctl_arrow_p)
5f5c8ee5
GM
4954 {
4955 /* Set IT->ctl_chars[0] to the glyph for `^'. */
4956 if (it->dp
4957 && INTEGERP (DISP_CTRL_GLYPH (it->dp))
4958 && GLYPH_CHAR_VALID_P (XINT (DISP_CTRL_GLYPH (it->dp))))
4959 g = XINT (DISP_CTRL_GLYPH (it->dp));
4960 else
4961 g = FAST_MAKE_GLYPH ('^', 0);
4962 XSETINT (it->ctl_chars[0], g);
4963
4964 g = FAST_MAKE_GLYPH (it->c ^ 0100, 0);
4965 XSETINT (it->ctl_chars[1], g);
4966
4967 /* Set up IT->dpvec and return first character from it. */
4968 it->dpvec_char_len = it->len;
4969 it->dpvec = it->ctl_chars;
4970 it->dpend = it->dpvec + 2;
4971 it->current.dpvec_index = 0;
4972 it->method = next_element_from_display_vector;
4973 get_next_display_element (it);
4974 }
4975 else
4976 {
260a86a0 4977 unsigned char str[MAX_MULTIBYTE_LENGTH];
c5924f47 4978 int len;
197516c2
KH
4979 int i;
4980 GLYPH escape_glyph;
4981
5f5c8ee5
GM
4982 /* Set IT->ctl_chars[0] to the glyph for `\\'. */
4983 if (it->dp
4984 && INTEGERP (DISP_ESCAPE_GLYPH (it->dp))
4985 && GLYPH_CHAR_VALID_P (XFASTINT (DISP_ESCAPE_GLYPH (it->dp))))
197516c2 4986 escape_glyph = XFASTINT (DISP_ESCAPE_GLYPH (it->dp));
5f5c8ee5 4987 else
197516c2
KH
4988 escape_glyph = FAST_MAKE_GLYPH ('\\', 0);
4989
ea0ffe21
KH
4990 if (CHAR_BYTE8_P (it->c))
4991 {
4992 str[0] = CHAR_TO_BYTE8 (it->c);
4993 len = 1;
4994 }
4995 else if (it->c < 256)
4996 {
4997 str[0] = it->c;
4998 len = 1;
4999 }
c5924f47 5000 else
ea9dd091 5001 {
ea0ffe21
KH
5002 /* It's an invalid character, which
5003 shouldn't happen actually, but due to
5004 bugs it may happen. Let's print the char
5005 as is, there's not much meaningful we can
5006 do with it. */
5007 str[0] = it->c;
5008 str[1] = it->c >> 8;
5009 str[2] = it->c >> 16;
5010 str[3] = it->c >> 24;
5011 len = 4;
ea9dd091 5012 }
c5924f47 5013
197516c2
KH
5014 for (i = 0; i < len; i++)
5015 {
5016 XSETINT (it->ctl_chars[i * 4], escape_glyph);
5017 /* Insert three more glyphs into IT->ctl_chars for
5018 the octal display of the character. */
2311178e 5019 g = FAST_MAKE_GLYPH (((str[i] >> 6) & 7) + '0', 0);
197516c2 5020 XSETINT (it->ctl_chars[i * 4 + 1], g);
2311178e 5021 g = FAST_MAKE_GLYPH (((str[i] >> 3) & 7) + '0', 0);
197516c2 5022 XSETINT (it->ctl_chars[i * 4 + 2], g);
2311178e 5023 g = FAST_MAKE_GLYPH ((str[i] & 7) + '0', 0);
197516c2
KH
5024 XSETINT (it->ctl_chars[i * 4 + 3], g);
5025 }
5f5c8ee5
GM
5026
5027 /* Set up IT->dpvec and return the first character
5028 from it. */
5029 it->dpvec_char_len = it->len;
5030 it->dpvec = it->ctl_chars;
197516c2 5031 it->dpend = it->dpvec + len * 4;
5f5c8ee5
GM
5032 it->current.dpvec_index = 0;
5033 it->method = next_element_from_display_vector;
5034 get_next_display_element (it);
5035 }
5036 }
5037 }
5038
980806b6
KH
5039 /* Adjust face id for a multibyte character. There are no
5040 multibyte character in unibyte text. */
5f5c8ee5
GM
5041 if (it->multibyte_p
5042 && success_p
980806b6 5043 && FRAME_WINDOW_P (it->f))
5f5c8ee5 5044 {
980806b6 5045 struct face *face = FACE_FROM_ID (it->f, it->face_id);
069315b7
KH
5046 int pos = (it->s ? -1
5047 : STRINGP (it->string) ? IT_STRING_CHARPOS (*it)
5048 : IT_CHARPOS (*it));
5049
f46a4dc1 5050 it->face_id = FACE_FOR_CHAR (it->f, face, it->c, pos, it->string);
5f5c8ee5
GM
5051 }
5052 }
5053
5054 /* Is this character the last one of a run of characters with
5055 box? If yes, set IT->end_of_box_run_p to 1. */
5056 if (it->face_box_p
5057 && it->s == NULL)
5058 {
5059 int face_id;
5060 struct face *face;
5061
5062 it->end_of_box_run_p
5063 = ((face_id = face_after_it_pos (it),
5064 face_id != it->face_id)
5065 && (face = FACE_FROM_ID (it->f, face_id),
5066 face->box == FACE_NO_BOX));
5067 }
5068
5069 /* Value is 0 if end of buffer or string reached. */
5070 return success_p;
5071}
5072
5073
5074/* Move IT to the next display element.
5075
cafafe0b
GM
5076 RESEAT_P non-zero means if called on a newline in buffer text,
5077 skip to the next visible line start.
5078
5f5c8ee5
GM
5079 Functions get_next_display_element and set_iterator_to_next are
5080 separate because I find this arrangement easier to handle than a
5081 get_next_display_element function that also increments IT's
5082 position. The way it is we can first look at an iterator's current
5083 display element, decide whether it fits on a line, and if it does,
5084 increment the iterator position. The other way around we probably
5085 would either need a flag indicating whether the iterator has to be
5086 incremented the next time, or we would have to implement a
5087 decrement position function which would not be easy to write. */
5088
5089void
cafafe0b 5090set_iterator_to_next (it, reseat_p)
5f5c8ee5 5091 struct it *it;
cafafe0b 5092 int reseat_p;
5f5c8ee5 5093{
483de32b
GM
5094 /* Reset flags indicating start and end of a sequence of characters
5095 with box. Reset them at the start of this function because
5096 moving the iterator to a new position might set them. */
5097 it->start_of_box_run_p = it->end_of_box_run_p = 0;
2311178e 5098
5f5c8ee5
GM
5099 if (it->method == next_element_from_buffer)
5100 {
5101 /* The current display element of IT is a character from
5102 current_buffer. Advance in the buffer, and maybe skip over
5103 invisible lines that are so because of selective display. */
cafafe0b 5104 if (ITERATOR_AT_END_OF_LINE_P (it) && reseat_p)
312246d1 5105 reseat_at_next_visible_line_start (it, 0);
5f5c8ee5
GM
5106 else
5107 {
5108 xassert (it->len != 0);
5109 IT_BYTEPOS (*it) += it->len;
5110 IT_CHARPOS (*it) += 1;
5111 xassert (IT_BYTEPOS (*it) == CHAR_TO_BYTE (IT_CHARPOS (*it)));
5112 }
5113 }
260a86a0
KH
5114 else if (it->method == next_element_from_composition)
5115 {
5116 xassert (it->cmp_id >= 0 && it ->cmp_id < n_compositions);
5117 if (STRINGP (it->string))
5118 {
5119 IT_STRING_BYTEPOS (*it) += it->len;
5120 IT_STRING_CHARPOS (*it) += it->cmp_len;
5121 it->method = next_element_from_string;
5122 goto consider_string_end;
5123 }
5124 else
5125 {
5126 IT_BYTEPOS (*it) += it->len;
5127 IT_CHARPOS (*it) += it->cmp_len;
5128 it->method = next_element_from_buffer;
5129 }
5130 }
5f5c8ee5
GM
5131 else if (it->method == next_element_from_c_string)
5132 {
5133 /* Current display element of IT is from a C string. */
5134 IT_BYTEPOS (*it) += it->len;
5135 IT_CHARPOS (*it) += 1;
5136 }
5137 else if (it->method == next_element_from_display_vector)
5138 {
5139 /* Current display element of IT is from a display table entry.
5140 Advance in the display table definition. Reset it to null if
5141 end reached, and continue with characters from buffers/
5142 strings. */
5143 ++it->current.dpvec_index;
286bcbc9 5144
980806b6
KH
5145 /* Restore face of the iterator to what they were before the
5146 display vector entry (these entries may contain faces). */
5f5c8ee5 5147 it->face_id = it->saved_face_id;
2311178e 5148
5f5c8ee5
GM
5149 if (it->dpvec + it->current.dpvec_index == it->dpend)
5150 {
5151 if (it->s)
5152 it->method = next_element_from_c_string;
5153 else if (STRINGP (it->string))
5154 it->method = next_element_from_string;
5155 else
5156 it->method = next_element_from_buffer;
5157
5158 it->dpvec = NULL;
5159 it->current.dpvec_index = -1;
5160
312246d1
GM
5161 /* Skip over characters which were displayed via IT->dpvec. */
5162 if (it->dpvec_char_len < 0)
5163 reseat_at_next_visible_line_start (it, 1);
5164 else if (it->dpvec_char_len > 0)
5f5c8ee5
GM
5165 {
5166 it->len = it->dpvec_char_len;
cafafe0b 5167 set_iterator_to_next (it, reseat_p);
5f5c8ee5
GM
5168 }
5169 }
5170 }
5171 else if (it->method == next_element_from_string)
5172 {
5173 /* Current display element is a character from a Lisp string. */
5174 xassert (it->s == NULL && STRINGP (it->string));
5175 IT_STRING_BYTEPOS (*it) += it->len;
5176 IT_STRING_CHARPOS (*it) += 1;
2311178e 5177
5f5c8ee5
GM
5178 consider_string_end:
5179
5180 if (it->current.overlay_string_index >= 0)
5181 {
5182 /* IT->string is an overlay string. Advance to the
5183 next, if there is one. */
2051c264 5184 if (IT_STRING_CHARPOS (*it) >= SCHARS (it->string))
5f5c8ee5
GM
5185 next_overlay_string (it);
5186 }
5187 else
5188 {
5189 /* IT->string is not an overlay string. If we reached
5190 its end, and there is something on IT->stack, proceed
5191 with what is on the stack. This can be either another
5192 string, this time an overlay string, or a buffer. */
2051c264 5193 if (IT_STRING_CHARPOS (*it) == SCHARS (it->string)
5f5c8ee5
GM
5194 && it->sp > 0)
5195 {
5196 pop_it (it);
5197 if (!STRINGP (it->string))
5198 it->method = next_element_from_buffer;
b2046df8
GM
5199 else
5200 goto consider_string_end;
5f5c8ee5
GM
5201 }
5202 }
5203 }
5204 else if (it->method == next_element_from_image
5205 || it->method == next_element_from_stretch)
5206 {
5207 /* The position etc with which we have to proceed are on
5208 the stack. The position may be at the end of a string,
5209 if the `display' property takes up the whole string. */
5210 pop_it (it);
5211 it->image_id = 0;
5212 if (STRINGP (it->string))
5213 {
5214 it->method = next_element_from_string;
5215 goto consider_string_end;
5216 }
5217 else
5218 it->method = next_element_from_buffer;
5219 }
5220 else
5221 /* There are no other methods defined, so this should be a bug. */
5222 abort ();
5223
5f5c8ee5
GM
5224 xassert (it->method != next_element_from_string
5225 || (STRINGP (it->string)
5226 && IT_STRING_CHARPOS (*it) >= 0));
5227}
5228
5229
5230/* Load IT's display element fields with information about the next
5231 display element which comes from a display table entry or from the
5232 result of translating a control character to one of the forms `^C'
5233 or `\003'. IT->dpvec holds the glyphs to return as characters. */
5234
5235static int
5236next_element_from_display_vector (it)
5237 struct it *it;
5238{
5239 /* Precondition. */
5240 xassert (it->dpvec && it->current.dpvec_index >= 0);
5241
5242 /* Remember the current face id in case glyphs specify faces.
5243 IT's face is restored in set_iterator_to_next. */
5244 it->saved_face_id = it->face_id;
2311178e 5245
5f5c8ee5
GM
5246 if (INTEGERP (*it->dpvec)
5247 && GLYPH_CHAR_VALID_P (XFASTINT (*it->dpvec)))
5248 {
5249 int lface_id;
5250 GLYPH g;
5251
5252 g = XFASTINT (it->dpvec[it->current.dpvec_index]);
5253 it->c = FAST_GLYPH_CHAR (g);
c5924f47 5254 it->len = CHAR_BYTES (it->c);
5f5c8ee5
GM
5255
5256 /* The entry may contain a face id to use. Such a face id is
5257 the id of a Lisp face, not a realized face. A face id of
969065c3 5258 zero means no face is specified. */
5f5c8ee5
GM
5259 lface_id = FAST_GLYPH_FACE (g);
5260 if (lface_id)
5261 {
969065c3 5262 /* The function returns -1 if lface_id is invalid. */
5f5c8ee5
GM
5263 int face_id = ascii_face_of_lisp_face (it->f, lface_id);
5264 if (face_id >= 0)
969065c3 5265 it->face_id = face_id;
5f5c8ee5
GM
5266 }
5267 }
5268 else
5269 /* Display table entry is invalid. Return a space. */
5270 it->c = ' ', it->len = 1;
5271
5272 /* Don't change position and object of the iterator here. They are
5273 still the values of the character that had this display table
5274 entry or was translated, and that's what we want. */
5275 it->what = IT_CHARACTER;
5276 return 1;
5277}
5278
5279
5280/* Load IT with the next display element from Lisp string IT->string.
5281 IT->current.string_pos is the current position within the string.
5282 If IT->current.overlay_string_index >= 0, the Lisp string is an
5283 overlay string. */
5284
5285static int
5286next_element_from_string (it)
5287 struct it *it;
5288{
5289 struct text_pos position;
5290
5291 xassert (STRINGP (it->string));
5292 xassert (IT_STRING_CHARPOS (*it) >= 0);
5293 position = it->current.string_pos;
5294
5295 /* Time to check for invisible text? */
5296 if (IT_STRING_CHARPOS (*it) < it->end_charpos
5297 && IT_STRING_CHARPOS (*it) == it->stop_charpos)
5298 {
5299 handle_stop (it);
5300
5301 /* Since a handler may have changed IT->method, we must
5302 recurse here. */
5303 return get_next_display_element (it);
5304 }
5305
5306 if (it->current.overlay_string_index >= 0)
5307 {
5308 /* Get the next character from an overlay string. In overlay
5309 strings, There is no field width or padding with spaces to
5310 do. */
2051c264 5311 if (IT_STRING_CHARPOS (*it) >= SCHARS (it->string))
5f5c8ee5
GM
5312 {
5313 it->what = IT_EOB;
5314 return 0;
5315 }
5316 else if (STRING_MULTIBYTE (it->string))
5317 {
2051c264 5318 int remaining = SBYTES (it->string) - IT_STRING_BYTEPOS (*it);
50f80c2f
KR
5319 const unsigned char *s = (SDATA (it->string)
5320 + IT_STRING_BYTEPOS (*it));
4fdb80f2 5321 it->c = string_char_and_length (s, remaining, &it->len);
5f5c8ee5
GM
5322 }
5323 else
5324 {
2051c264 5325 it->c = SREF (it->string, IT_STRING_BYTEPOS (*it));
5f5c8ee5
GM
5326 it->len = 1;
5327 }
5328 }
5329 else
5330 {
5331 /* Get the next character from a Lisp string that is not an
5332 overlay string. Such strings come from the mode line, for
5333 example. We may have to pad with spaces, or truncate the
5334 string. See also next_element_from_c_string. */
5335 if (IT_STRING_CHARPOS (*it) >= it->end_charpos)
5336 {
5337 it->what = IT_EOB;
5338 return 0;
5339 }
5340 else if (IT_STRING_CHARPOS (*it) >= it->string_nchars)
5341 {
5342 /* Pad with spaces. */
5343 it->c = ' ', it->len = 1;
5344 CHARPOS (position) = BYTEPOS (position) = -1;
5345 }
5346 else if (STRING_MULTIBYTE (it->string))
5347 {
2051c264 5348 int maxlen = SBYTES (it->string) - IT_STRING_BYTEPOS (*it);
50f80c2f
KR
5349 const unsigned char *s = (SDATA (it->string)
5350 + IT_STRING_BYTEPOS (*it));
4fdb80f2 5351 it->c = string_char_and_length (s, maxlen, &it->len);
5f5c8ee5
GM
5352 }
5353 else
5354 {
2051c264 5355 it->c = SREF (it->string, IT_STRING_BYTEPOS (*it));
5f5c8ee5
GM
5356 it->len = 1;
5357 }
5358 }
5359
5360 /* Record what we have and where it came from. Note that we store a
5361 buffer position in IT->position although it could arguably be a
5362 string position. */
5363 it->what = IT_CHARACTER;
5364 it->object = it->string;
5365 it->position = position;
5366 return 1;
5367}
5368
5369
5370/* Load IT with next display element from C string IT->s.
5371 IT->string_nchars is the maximum number of characters to return
5372 from the string. IT->end_charpos may be greater than
5373 IT->string_nchars when this function is called, in which case we
5374 may have to return padding spaces. Value is zero if end of string
5375 reached, including padding spaces. */
5376
5377static int
5378next_element_from_c_string (it)
5379 struct it *it;
5380{
5381 int success_p = 1;
2311178e 5382
5f5c8ee5
GM
5383 xassert (it->s);
5384 it->what = IT_CHARACTER;
5385 BYTEPOS (it->position) = CHARPOS (it->position) = 0;
5386 it->object = Qnil;
2311178e 5387
5f5c8ee5
GM
5388 /* IT's position can be greater IT->string_nchars in case a field
5389 width or precision has been specified when the iterator was
5390 initialized. */
5391 if (IT_CHARPOS (*it) >= it->end_charpos)
5392 {
5393 /* End of the game. */
5394 it->what = IT_EOB;
5395 success_p = 0;
5396 }
5397 else if (IT_CHARPOS (*it) >= it->string_nchars)
5398 {
5399 /* Pad with spaces. */
5400 it->c = ' ', it->len = 1;
5401 BYTEPOS (it->position) = CHARPOS (it->position) = -1;
5402 }
5403 else if (it->multibyte_p)
5404 {
5405 /* Implementation note: The calls to strlen apparently aren't a
5406 performance problem because there is no noticeable performance
5407 difference between Emacs running in unibyte or multibyte mode. */
5408 int maxlen = strlen (it->s) - IT_BYTEPOS (*it);
4fdb80f2
GM
5409 it->c = string_char_and_length (it->s + IT_BYTEPOS (*it),
5410 maxlen, &it->len);
5f5c8ee5
GM
5411 }
5412 else
5413 it->c = it->s[IT_BYTEPOS (*it)], it->len = 1;
2311178e 5414
5f5c8ee5
GM
5415 return success_p;
5416}
5417
5418
5419/* Set up IT to return characters from an ellipsis, if appropriate.
5420 The definition of the ellipsis glyphs may come from a display table
5421 entry. This function Fills IT with the first glyph from the
5422 ellipsis if an ellipsis is to be displayed. */
5423
13f19968 5424static int
5f5c8ee5
GM
5425next_element_from_ellipsis (it)
5426 struct it *it;
5427{
13f19968 5428 if (it->selective_display_ellipsis_p)
5f5c8ee5 5429 {
13f19968
GM
5430 if (it->dp && VECTORP (DISP_INVIS_VECTOR (it->dp)))
5431 {
5432 /* Use the display table definition for `...'. Invalid glyphs
5433 will be handled by the method returning elements from dpvec. */
5434 struct Lisp_Vector *v = XVECTOR (DISP_INVIS_VECTOR (it->dp));
5435 it->dpvec_char_len = it->len;
5436 it->dpvec = v->contents;
5437 it->dpend = v->contents + v->size;
5438 it->current.dpvec_index = 0;
5439 it->method = next_element_from_display_vector;
5440 }
5441 else
5442 {
5443 /* Use default `...' which is stored in default_invis_vector. */
5444 it->dpvec_char_len = it->len;
5445 it->dpvec = default_invis_vector;
5446 it->dpend = default_invis_vector + 3;
5447 it->current.dpvec_index = 0;
5448 it->method = next_element_from_display_vector;
5449 }
5f5c8ee5 5450 }
13f19968 5451 else
54918e2b 5452 {
4aad61f8
GM
5453 /* The face at the current position may be different from the
5454 face we find after the invisible text. Remember what it
5455 was in IT->saved_face_id, and signal that it's there by
5456 setting face_before_selective_p. */
5457 it->saved_face_id = it->face_id;
54918e2b
GM
5458 it->method = next_element_from_buffer;
5459 reseat_at_next_visible_line_start (it, 1);
4aad61f8 5460 it->face_before_selective_p = 1;
54918e2b 5461 }
2311178e 5462
13f19968 5463 return get_next_display_element (it);
5f5c8ee5
GM
5464}
5465
5466
5467/* Deliver an image display element. The iterator IT is already
5468 filled with image information (done in handle_display_prop). Value
5469 is always 1. */
2311178e 5470
5f5c8ee5
GM
5471
5472static int
5473next_element_from_image (it)
5474 struct it *it;
5475{
5476 it->what = IT_IMAGE;
5477 return 1;
5478}
5479
5480
5481/* Fill iterator IT with next display element from a stretch glyph
5482 property. IT->object is the value of the text property. Value is
5483 always 1. */
5484
5485static int
5486next_element_from_stretch (it)
5487 struct it *it;
5488{
5489 it->what = IT_STRETCH;
5490 return 1;
5491}
5492
5493
5494/* Load IT with the next display element from current_buffer. Value
5495 is zero if end of buffer reached. IT->stop_charpos is the next
5496 position at which to stop and check for text properties or buffer
5497 end. */
5498
5499static int
5500next_element_from_buffer (it)
5501 struct it *it;
5502{
5503 int success_p = 1;
5504
5505 /* Check this assumption, otherwise, we would never enter the
5506 if-statement, below. */
5507 xassert (IT_CHARPOS (*it) >= BEGV
5508 && IT_CHARPOS (*it) <= it->stop_charpos);
5509
5510 if (IT_CHARPOS (*it) >= it->stop_charpos)
5511 {
5512 if (IT_CHARPOS (*it) >= it->end_charpos)
5513 {
5514 int overlay_strings_follow_p;
2311178e 5515
5f5c8ee5
GM
5516 /* End of the game, except when overlay strings follow that
5517 haven't been returned yet. */
5518 if (it->overlay_strings_at_end_processed_p)
5519 overlay_strings_follow_p = 0;
5520 else
5521 {
5522 it->overlay_strings_at_end_processed_p = 1;
5a08cbaf 5523 overlay_strings_follow_p = get_overlay_strings (it, 0);
5f5c8ee5
GM
5524 }
5525
5526 if (overlay_strings_follow_p)
5527 success_p = get_next_display_element (it);
5528 else
5529 {
5530 it->what = IT_EOB;
5531 it->position = it->current.pos;
5532 success_p = 0;
5533 }
5534 }
5535 else
5536 {
5537 handle_stop (it);
5538 return get_next_display_element (it);
5539 }
5540 }
5541 else
5542 {
5543 /* No face changes, overlays etc. in sight, so just return a
5544 character from current_buffer. */
5545 unsigned char *p;
5546
5547 /* Maybe run the redisplay end trigger hook. Performance note:
5548 This doesn't seem to cost measurable time. */
5549 if (it->redisplay_end_trigger_charpos
5550 && it->glyph_row
5551 && IT_CHARPOS (*it) >= it->redisplay_end_trigger_charpos)
5552 run_redisplay_end_trigger_hook (it);
5553
5554 /* Get the next character, maybe multibyte. */
5555 p = BYTE_POS_ADDR (IT_BYTEPOS (*it));
260a86a0 5556 if (it->multibyte_p && !ASCII_BYTE_P (*p))
5f5c8ee5
GM
5557 {
5558 int maxlen = ((IT_BYTEPOS (*it) >= GPT_BYTE ? ZV_BYTE : GPT_BYTE)
5559 - IT_BYTEPOS (*it));
4fdb80f2 5560 it->c = string_char_and_length (p, maxlen, &it->len);
5f5c8ee5
GM
5561 }
5562 else
5563 it->c = *p, it->len = 1;
5564
5565 /* Record what we have and where it came from. */
5566 it->what = IT_CHARACTER;;
5567 it->object = it->w->buffer;
5568 it->position = it->current.pos;
5569
5570 /* Normally we return the character found above, except when we
5571 really want to return an ellipsis for selective display. */
5572 if (it->selective)
5573 {
5574 if (it->c == '\n')
5575 {
5576 /* A value of selective > 0 means hide lines indented more
5577 than that number of columns. */
5578 if (it->selective > 0
5579 && IT_CHARPOS (*it) + 1 < ZV
5580 && indented_beyond_p (IT_CHARPOS (*it) + 1,
5581 IT_BYTEPOS (*it) + 1,
a67e162b 5582 (double) it->selective)) /* iftc */
312246d1 5583 {
13f19968 5584 success_p = next_element_from_ellipsis (it);
312246d1
GM
5585 it->dpvec_char_len = -1;
5586 }
5f5c8ee5
GM
5587 }
5588 else if (it->c == '\r' && it->selective == -1)
5589 {
5590 /* A value of selective == -1 means that everything from the
5591 CR to the end of the line is invisible, with maybe an
5592 ellipsis displayed for it. */
13f19968 5593 success_p = next_element_from_ellipsis (it);
312246d1 5594 it->dpvec_char_len = -1;
5f5c8ee5
GM
5595 }
5596 }
5597 }
5598
5599 /* Value is zero if end of buffer reached. */
c880678e 5600 xassert (!success_p || it->what != IT_CHARACTER || it->len > 0);
5f5c8ee5
GM
5601 return success_p;
5602}
5603
2311178e 5604
5f5c8ee5
GM
5605/* Run the redisplay end trigger hook for IT. */
5606
5607static void
5608run_redisplay_end_trigger_hook (it)
5609 struct it *it;
5610{
5611 Lisp_Object args[3];
5612
5613 /* IT->glyph_row should be non-null, i.e. we should be actually
5614 displaying something, or otherwise we should not run the hook. */
5615 xassert (it->glyph_row);
5616
5617 /* Set up hook arguments. */
5618 args[0] = Qredisplay_end_trigger_functions;
5619 args[1] = it->window;
5620 XSETINT (args[2], it->redisplay_end_trigger_charpos);
5621 it->redisplay_end_trigger_charpos = 0;
5622
5623 /* Since we are *trying* to run these functions, don't try to run
5624 them again, even if they get an error. */
5625 it->w->redisplay_end_trigger = Qnil;
5626 Frun_hook_with_args (3, args);
2311178e 5627
5f5c8ee5
GM
5628 /* Notice if it changed the face of the character we are on. */
5629 handle_face_prop (it);
5630}
5631
5632
260a86a0
KH
5633/* Deliver a composition display element. The iterator IT is already
5634 filled with composition information (done in
5635 handle_composition_prop). Value is always 1. */
5636
5637static int
5638next_element_from_composition (it)
5639 struct it *it;
5640{
5641 it->what = IT_COMPOSITION;
5642 it->position = (STRINGP (it->string)
5643 ? it->current.string_pos
5644 : it->current.pos);
5645 return 1;
5646}
5647
5648
5f5c8ee5
GM
5649\f
5650/***********************************************************************
5651 Moving an iterator without producing glyphs
5652 ***********************************************************************/
5653
5654/* Move iterator IT to a specified buffer or X position within one
5655 line on the display without producing glyphs.
5656
c53a1624
RS
5657 OP should be a bit mask including some or all of these bits:
5658 MOVE_TO_X: Stop on reaching x-position TO_X.
5659 MOVE_TO_POS: Stop on reaching buffer or string position TO_CHARPOS.
5660 Regardless of OP's value, stop in reaching the end of the display line.
5f5c8ee5 5661
c53a1624
RS
5662 TO_X is normally a value 0 <= TO_X <= IT->last_visible_x.
5663 This means, in particular, that TO_X includes window's horizontal
5664 scroll amount.
5f5c8ee5 5665
c53a1624
RS
5666 The return value has several possible values that
5667 say what condition caused the scan to stop:
5f5c8ee5
GM
5668
5669 MOVE_POS_MATCH_OR_ZV
5670 - when TO_POS or ZV was reached.
2311178e 5671
5f5c8ee5
GM
5672 MOVE_X_REACHED
5673 -when TO_X was reached before TO_POS or ZV were reached.
2311178e 5674
5f5c8ee5
GM
5675 MOVE_LINE_CONTINUED
5676 - when we reached the end of the display area and the line must
5677 be continued.
2311178e 5678
5f5c8ee5
GM
5679 MOVE_LINE_TRUNCATED
5680 - when we reached the end of the display area and the line is
5681 truncated.
5682
5683 MOVE_NEWLINE_OR_CR
5684 - when we stopped at a line end, i.e. a newline or a CR and selective
5685 display is on. */
5686
701552dd 5687static enum move_it_result
5f5c8ee5
GM
5688move_it_in_display_line_to (it, to_charpos, to_x, op)
5689 struct it *it;
5690 int to_charpos, to_x, op;
5691{
5692 enum move_it_result result = MOVE_UNDEFINED;
5693 struct glyph_row *saved_glyph_row;
5694
5695 /* Don't produce glyphs in produce_glyphs. */
5696 saved_glyph_row = it->glyph_row;
5697 it->glyph_row = NULL;
5698
6b61353c
KH
5699#define BUFFER_POS_REACHED_P() \
5700 ((op & MOVE_TO_POS) != 0 \
5701 && BUFFERP (it->object) \
5702 && IT_CHARPOS (*it) >= to_charpos)
5703
5f5c8ee5
GM
5704 while (1)
5705 {
ae26e27d 5706 int x, i, ascent = 0, descent = 0;
2311178e 5707
5f5c8ee5
GM
5708 /* Stop when ZV or TO_CHARPOS reached. */
5709 if (!get_next_display_element (it)
6b61353c 5710 || BUFFER_POS_REACHED_P ())
5f5c8ee5
GM
5711 {
5712 result = MOVE_POS_MATCH_OR_ZV;
5713 break;
5714 }
2311178e 5715
5f5c8ee5
GM
5716 /* The call to produce_glyphs will get the metrics of the
5717 display element IT is loaded with. We record in x the
5718 x-position before this display element in case it does not
5719 fit on the line. */
5720 x = it->current_x;
2311178e 5721
47589c8c
GM
5722 /* Remember the line height so far in case the next element doesn't
5723 fit on the line. */
5724 if (!it->truncate_lines_p)
5725 {
5726 ascent = it->max_ascent;
5727 descent = it->max_descent;
5728 }
2311178e 5729
5f5c8ee5
GM
5730 PRODUCE_GLYPHS (it);
5731
5732 if (it->area != TEXT_AREA)
5733 {
cafafe0b 5734 set_iterator_to_next (it, 1);
5f5c8ee5
GM
5735 continue;
5736 }
5737
5738 /* The number of glyphs we get back in IT->nglyphs will normally
5739 be 1 except when IT->c is (i) a TAB, or (ii) a multi-glyph
5740 character on a terminal frame, or (iii) a line end. For the
5741 second case, IT->nglyphs - 1 padding glyphs will be present
5742 (on X frames, there is only one glyph produced for a
5743 composite character.
5744
5745 The behavior implemented below means, for continuation lines,
5746 that as many spaces of a TAB as fit on the current line are
5747 displayed there. For terminal frames, as many glyphs of a
5748 multi-glyph character are displayed in the current line, too.
5749 This is what the old redisplay code did, and we keep it that
5750 way. Under X, the whole shape of a complex character must
5751 fit on the line or it will be completely displayed in the
5752 next line.
5753
5754 Note that both for tabs and padding glyphs, all glyphs have
5755 the same width. */
5756 if (it->nglyphs)
5757 {
5758 /* More than one glyph or glyph doesn't fit on line. All
5759 glyphs have the same width. */
5760 int single_glyph_width = it->pixel_width / it->nglyphs;
5761 int new_x;
2311178e 5762
5f5c8ee5
GM
5763 for (i = 0; i < it->nglyphs; ++i, x = new_x)
5764 {
5765 new_x = x + single_glyph_width;
5766
5767 /* We want to leave anything reaching TO_X to the caller. */
5768 if ((op & MOVE_TO_X) && new_x > to_x)
5769 {
5770 it->current_x = x;
5771 result = MOVE_X_REACHED;
5772 break;
5773 }
5774 else if (/* Lines are continued. */
5775 !it->truncate_lines_p
5776 && (/* And glyph doesn't fit on the line. */
5777 new_x > it->last_visible_x
5778 /* Or it fits exactly and we're on a window
5779 system frame. */
5780 || (new_x == it->last_visible_x
5781 && FRAME_WINDOW_P (it->f))))
5782 {
5783 if (/* IT->hpos == 0 means the very first glyph
5784 doesn't fit on the line, e.g. a wide image. */
5785 it->hpos == 0
5786 || (new_x == it->last_visible_x
5787 && FRAME_WINDOW_P (it->f)))
5788 {
5789 ++it->hpos;
5790 it->current_x = new_x;
5791 if (i == it->nglyphs - 1)
6b61353c
KH
5792 {
5793 set_iterator_to_next (it, 1);
5794#ifdef HAVE_WINDOW_SYSTEM
5795 if (IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
5796 {
5797 if (!get_next_display_element (it)
5798 || BUFFER_POS_REACHED_P ())
5799 {
5800 result = MOVE_POS_MATCH_OR_ZV;
5801 break;
5802 }
5803 if (ITERATOR_AT_END_OF_LINE_P (it))
5804 {
5805 result = MOVE_NEWLINE_OR_CR;
5806 break;
5807 }
5808 }
5809#endif /* HAVE_WINDOW_SYSTEM */
5810 }
5f5c8ee5
GM
5811 }
5812 else
47589c8c
GM
5813 {
5814 it->current_x = x;
5815 it->max_ascent = ascent;
5816 it->max_descent = descent;
5817 }
2311178e 5818
47589c8c
GM
5819 TRACE_MOVE ((stderr, "move_it_in: continued at %d\n",
5820 IT_CHARPOS (*it)));
5f5c8ee5
GM
5821 result = MOVE_LINE_CONTINUED;
5822 break;
5823 }
5824 else if (new_x > it->first_visible_x)
5825 {
5826 /* Glyph is visible. Increment number of glyphs that
5827 would be displayed. */
5828 ++it->hpos;
5829 }
5830 else
5831 {
2311178e 5832 /* Glyph is completely off the left margin of the display
5f5c8ee5
GM
5833 area. Nothing to do. */
5834 }
5835 }
5836
5837 if (result != MOVE_UNDEFINED)
5838 break;
5839 }
5840 else if ((op & MOVE_TO_X) && it->current_x >= to_x)
5841 {
5842 /* Stop when TO_X specified and reached. This check is
5843 necessary here because of lines consisting of a line end,
5844 only. The line end will not produce any glyphs and we
5845 would never get MOVE_X_REACHED. */
5846 xassert (it->nglyphs == 0);
5847 result = MOVE_X_REACHED;
5848 break;
5849 }
2311178e 5850
5f5c8ee5
GM
5851 /* Is this a line end? If yes, we're done. */
5852 if (ITERATOR_AT_END_OF_LINE_P (it))
5853 {
5854 result = MOVE_NEWLINE_OR_CR;
5855 break;
5856 }
2311178e 5857
5f5c8ee5
GM
5858 /* The current display element has been consumed. Advance
5859 to the next. */
cafafe0b 5860 set_iterator_to_next (it, 1);
2311178e 5861
5f5c8ee5
GM
5862 /* Stop if lines are truncated and IT's current x-position is
5863 past the right edge of the window now. */
5864 if (it->truncate_lines_p
5865 && it->current_x >= it->last_visible_x)
5866 {
6b61353c
KH
5867#ifdef HAVE_WINDOW_SYSTEM
5868 if (IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
5869 {
5870 if (!get_next_display_element (it)
5871 || BUFFER_POS_REACHED_P ())
5872 {
5873 result = MOVE_POS_MATCH_OR_ZV;
5874 break;
5875 }
5876 if (ITERATOR_AT_END_OF_LINE_P (it))
5877 {
5878 result = MOVE_NEWLINE_OR_CR;
5879 break;
5880 }
5881 }
5882#endif /* HAVE_WINDOW_SYSTEM */
5f5c8ee5
GM
5883 result = MOVE_LINE_TRUNCATED;
5884 break;
5885 }
5886 }
5887
6b61353c
KH
5888#undef BUFFER_POS_REACHED_P
5889
5f5c8ee5
GM
5890 /* Restore the iterator settings altered at the beginning of this
5891 function. */
5892 it->glyph_row = saved_glyph_row;
5893 return result;
5894}
5895
5896
9b2bba76
RS
5897/* Move IT forward until it satisfies one or more of the criteria in
5898 TO_CHARPOS, TO_X, TO_Y, and TO_VPOS.
5899
5900 OP is a bit-mask that specifies where to stop, and in particular,
5901 which of those four position arguments makes a difference. See the
5902 description of enum move_operation_enum.
2311178e 5903
5f5c8ee5
GM
5904 If TO_CHARPOS is in invisible text, e.g. a truncated part of a
5905 screen line, this function will set IT to the next position >
5906 TO_CHARPOS. */
5907
5908void
5909move_it_to (it, to_charpos, to_x, to_y, to_vpos, op)
5910 struct it *it;
5911 int to_charpos, to_x, to_y, to_vpos;
5912 int op;
5913{
5914 enum move_it_result skip, skip2 = MOVE_X_REACHED;
5915 int line_height;
47589c8c 5916 int reached = 0;
5f5c8ee5 5917
47589c8c 5918 for (;;)
5f5c8ee5
GM
5919 {
5920 if (op & MOVE_TO_VPOS)
5921 {
5922 /* If no TO_CHARPOS and no TO_X specified, stop at the
5923 start of the line TO_VPOS. */
5924 if ((op & (MOVE_TO_X | MOVE_TO_POS)) == 0)
5925 {
5926 if (it->vpos == to_vpos)
47589c8c
GM
5927 {
5928 reached = 1;
5929 break;
5930 }
5931 else
5932 skip = move_it_in_display_line_to (it, -1, -1, 0);
5f5c8ee5
GM
5933 }
5934 else
5935 {
5936 /* TO_VPOS >= 0 means stop at TO_X in the line at
5937 TO_VPOS, or at TO_POS, whichever comes first. */
47589c8c
GM
5938 if (it->vpos == to_vpos)
5939 {
5940 reached = 2;
5941 break;
5942 }
2311178e 5943
5f5c8ee5
GM
5944 skip = move_it_in_display_line_to (it, to_charpos, to_x, op);
5945
5946 if (skip == MOVE_POS_MATCH_OR_ZV || it->vpos == to_vpos)
47589c8c
GM
5947 {
5948 reached = 3;
5949 break;
5950 }
5f5c8ee5
GM
5951 else if (skip == MOVE_X_REACHED && it->vpos != to_vpos)
5952 {
5953 /* We have reached TO_X but not in the line we want. */
5954 skip = move_it_in_display_line_to (it, to_charpos,
5955 -1, MOVE_TO_POS);
5956 if (skip == MOVE_POS_MATCH_OR_ZV)
47589c8c
GM
5957 {
5958 reached = 4;
5959 break;
5960 }
5f5c8ee5
GM
5961 }
5962 }
5963 }
5964 else if (op & MOVE_TO_Y)
5965 {
5966 struct it it_backup;
2311178e 5967
5f5c8ee5
GM
5968 /* TO_Y specified means stop at TO_X in the line containing
5969 TO_Y---or at TO_CHARPOS if this is reached first. The
5970 problem is that we can't really tell whether the line
5971 contains TO_Y before we have completely scanned it, and
5972 this may skip past TO_X. What we do is to first scan to
5973 TO_X.
5974
5975 If TO_X is not specified, use a TO_X of zero. The reason
5976 is to make the outcome of this function more predictable.
5977 If we didn't use TO_X == 0, we would stop at the end of
5978 the line which is probably not what a caller would expect
5979 to happen. */
5980 skip = move_it_in_display_line_to (it, to_charpos,
5981 ((op & MOVE_TO_X)
5982 ? to_x : 0),
5983 (MOVE_TO_X
5984 | (op & MOVE_TO_POS)));
5985
5986 /* If TO_CHARPOS is reached or ZV, we don't have to do more. */
5987 if (skip == MOVE_POS_MATCH_OR_ZV)
47589c8c
GM
5988 {
5989 reached = 5;
5990 break;
5991 }
2311178e 5992
5f5c8ee5
GM
5993 /* If TO_X was reached, we would like to know whether TO_Y
5994 is in the line. This can only be said if we know the
5995 total line height which requires us to scan the rest of
5996 the line. */
5f5c8ee5
GM
5997 if (skip == MOVE_X_REACHED)
5998 {
993651d1
KH
5999 /* Wait! We can conclude that TO_Y is in the line if
6000 the already scanned glyphs make the line tall enough
6001 because further scanning doesn't make it shorter. */
6002 line_height = it->max_ascent + it->max_descent;
6003 if (to_y >= it->current_y
6004 && to_y < it->current_y + line_height)
6005 {
6006 reached = 6;
6007 break;
6008 }
5f5c8ee5 6009 it_backup = *it;
47589c8c 6010 TRACE_MOVE ((stderr, "move_it: from %d\n", IT_CHARPOS (*it)));
5f5c8ee5
GM
6011 skip2 = move_it_in_display_line_to (it, to_charpos, -1,
6012 op & MOVE_TO_POS);
47589c8c 6013 TRACE_MOVE ((stderr, "move_it: to %d\n", IT_CHARPOS (*it)));
5f5c8ee5
GM
6014 }
6015
6016 /* Now, decide whether TO_Y is in this line. */
6017 line_height = it->max_ascent + it->max_descent;
47589c8c 6018 TRACE_MOVE ((stderr, "move_it: line_height = %d\n", line_height));
2311178e 6019
5f5c8ee5
GM
6020 if (to_y >= it->current_y
6021 && to_y < it->current_y + line_height)
6022 {
6023 if (skip == MOVE_X_REACHED)
6024 /* If TO_Y is in this line and TO_X was reached above,
6025 we scanned too far. We have to restore IT's settings
6026 to the ones before skipping. */
6027 *it = it_backup;
47589c8c 6028 reached = 6;
5f5c8ee5
GM
6029 }
6030 else if (skip == MOVE_X_REACHED)
6031 {
6032 skip = skip2;
6033 if (skip == MOVE_POS_MATCH_OR_ZV)
47589c8c 6034 reached = 7;
5f5c8ee5
GM
6035 }
6036
47589c8c 6037 if (reached)
5f5c8ee5
GM
6038 break;
6039 }
6040 else
6041 skip = move_it_in_display_line_to (it, to_charpos, -1, MOVE_TO_POS);
6042
6043 switch (skip)
6044 {
6045 case MOVE_POS_MATCH_OR_ZV:
47589c8c
GM
6046 reached = 8;
6047 goto out;
5f5c8ee5
GM
6048
6049 case MOVE_NEWLINE_OR_CR:
cafafe0b 6050 set_iterator_to_next (it, 1);
5f5c8ee5
GM
6051 it->continuation_lines_width = 0;
6052 break;
6053
6054 case MOVE_LINE_TRUNCATED:
6055 it->continuation_lines_width = 0;
312246d1 6056 reseat_at_next_visible_line_start (it, 0);
5f5c8ee5
GM
6057 if ((op & MOVE_TO_POS) != 0
6058 && IT_CHARPOS (*it) > to_charpos)
47589c8c
GM
6059 {
6060 reached = 9;
6061 goto out;
6062 }
5f5c8ee5
GM
6063 break;
6064
6065 case MOVE_LINE_CONTINUED:
6066 it->continuation_lines_width += it->current_x;
6067 break;
6068
6069 default:
6070 abort ();
6071 }
6072
6073 /* Reset/increment for the next run. */
6074 recenter_overlay_lists (current_buffer, IT_CHARPOS (*it));
6075 it->current_x = it->hpos = 0;
6076 it->current_y += it->max_ascent + it->max_descent;
6077 ++it->vpos;
6078 last_height = it->max_ascent + it->max_descent;
6079 last_max_ascent = it->max_ascent;
6080 it->max_ascent = it->max_descent = 0;
6081 }
2311178e 6082
47589c8c
GM
6083 out:
6084
6085 TRACE_MOVE ((stderr, "move_it_to: reached %d\n", reached));
5f5c8ee5
GM
6086}
6087
6088
6089/* Move iterator IT backward by a specified y-distance DY, DY >= 0.
6090
6091 If DY > 0, move IT backward at least that many pixels. DY = 0
6092 means move IT backward to the preceding line start or BEGV. This
6093 function may move over more than DY pixels if IT->current_y - DY
6094 ends up in the middle of a line; in this case IT->current_y will be
6095 set to the top of the line moved to. */
6096
6097void
6098move_it_vertically_backward (it, dy)
6099 struct it *it;
6100 int dy;
6101{
79ddf6f7
GM
6102 int nlines, h;
6103 struct it it2, it3;
5f5c8ee5 6104 int start_pos = IT_CHARPOS (*it);
2311178e 6105
5f5c8ee5
GM
6106 xassert (dy >= 0);
6107
6108 /* Estimate how many newlines we must move back. */
da8b7f4f 6109 nlines = max (1, dy / FRAME_LINE_HEIGHT (it->f));
5f5c8ee5
GM
6110
6111 /* Set the iterator's position that many lines back. */
6112 while (nlines-- && IT_CHARPOS (*it) > BEGV)
6113 back_to_previous_visible_line_start (it);
6114
6115 /* Reseat the iterator here. When moving backward, we don't want
6116 reseat to skip forward over invisible text, set up the iterator
6117 to deliver from overlay strings at the new position etc. So,
6118 use reseat_1 here. */
6119 reseat_1 (it, it->current.pos, 1);
6120
6121 /* We are now surely at a line start. */
6122 it->current_x = it->hpos = 0;
0e47bbf7 6123 it->continuation_lines_width = 0;
5f5c8ee5
GM
6124
6125 /* Move forward and see what y-distance we moved. First move to the
6126 start of the next line so that we get its height. We need this
6127 height to be able to tell whether we reached the specified
6128 y-distance. */
6129 it2 = *it;
6130 it2.max_ascent = it2.max_descent = 0;
6131 move_it_to (&it2, start_pos, -1, -1, it2.vpos + 1,
6132 MOVE_TO_POS | MOVE_TO_VPOS);
6133 xassert (IT_CHARPOS (*it) >= BEGV);
79ddf6f7 6134 it3 = it2;
2311178e 6135
5f5c8ee5
GM
6136 move_it_to (&it2, start_pos, -1, -1, -1, MOVE_TO_POS);
6137 xassert (IT_CHARPOS (*it) >= BEGV);
ccbb9ed2
RS
6138 /* H is the actual vertical distance from the position in *IT
6139 and the starting position. */
5f5c8ee5 6140 h = it2.current_y - it->current_y;
ccbb9ed2 6141 /* NLINES is the distance in number of lines. */
5f5c8ee5
GM
6142 nlines = it2.vpos - it->vpos;
6143
ccbb9ed2
RS
6144 /* Correct IT's y and vpos position
6145 so that they are relative to the starting point. */
5f5c8ee5
GM
6146 it->vpos -= nlines;
6147 it->current_y -= h;
2311178e 6148
5f5c8ee5
GM
6149 if (dy == 0)
6150 {
6151 /* DY == 0 means move to the start of the screen line. The
6152 value of nlines is > 0 if continuation lines were involved. */
6153 if (nlines > 0)
6154 move_it_by_lines (it, nlines, 1);
6155 xassert (IT_CHARPOS (*it) <= start_pos);
6156 }
ccbb9ed2 6157 else
5f5c8ee5 6158 {
ccbb9ed2
RS
6159 /* The y-position we try to reach, relative to *IT.
6160 Note that H has been subtracted in front of the if-statement. */
5f5c8ee5 6161 int target_y = it->current_y + h - dy;
79ddf6f7
GM
6162 int y0 = it3.current_y;
6163 int y1 = line_bottom_y (&it3);
6164 int line_height = y1 - y0;
f7ccfc8c 6165
5f5c8ee5
GM
6166 /* If we did not reach target_y, try to move further backward if
6167 we can. If we moved too far backward, try to move forward. */
6168 if (target_y < it->current_y
79ddf6f7
GM
6169 /* This is heuristic. In a window that's 3 lines high, with
6170 a line height of 13 pixels each, recentering with point
6171 on the bottom line will try to move -39/2 = 19 pixels
6172 backward. Try to avoid moving into the first line. */
798dbe1f 6173 && it->current_y - target_y > line_height / 3 * 2
5f5c8ee5
GM
6174 && IT_CHARPOS (*it) > BEGV)
6175 {
f7ccfc8c
GM
6176 TRACE_MOVE ((stderr, " not far enough -> move_vert %d\n",
6177 target_y - it->current_y));
5f5c8ee5
GM
6178 move_it_vertically (it, target_y - it->current_y);
6179 xassert (IT_CHARPOS (*it) >= BEGV);
6180 }
6181 else if (target_y >= it->current_y + line_height
6182 && IT_CHARPOS (*it) < ZV)
6183 {
55591976 6184 /* Should move forward by at least one line, maybe more.
2311178e 6185
55591976
GM
6186 Note: Calling move_it_by_lines can be expensive on
6187 terminal frames, where compute_motion is used (via
6188 vmotion) to do the job, when there are very long lines
6189 and truncate-lines is nil. That's the reason for
6190 treating terminal frames specially here. */
2311178e 6191
55591976
GM
6192 if (!FRAME_WINDOW_P (it->f))
6193 move_it_vertically (it, target_y - (it->current_y + line_height));
6194 else
f7ccfc8c 6195 {
55591976
GM
6196 do
6197 {
6198 move_it_by_lines (it, 1, 1);
6199 }
6200 while (target_y >= line_bottom_y (it) && IT_CHARPOS (*it) < ZV);
f7ccfc8c 6201 }
f7ccfc8c 6202
5f5c8ee5
GM
6203 xassert (IT_CHARPOS (*it) >= BEGV);
6204 }
6205 }
6206}
6207
6208
6209/* Move IT by a specified amount of pixel lines DY. DY negative means
6210 move backwards. DY = 0 means move to start of screen line. At the
6211 end, IT will be on the start of a screen line. */
6212
2311178e 6213void
5f5c8ee5
GM
6214move_it_vertically (it, dy)
6215 struct it *it;
6216 int dy;
6217{
6218 if (dy <= 0)
6219 move_it_vertically_backward (it, -dy);
6220 else if (dy > 0)
6221 {
47589c8c 6222 TRACE_MOVE ((stderr, "move_it_v: from %d, %d\n", IT_CHARPOS (*it), dy));
5f5c8ee5
GM
6223 move_it_to (it, ZV, -1, it->current_y + dy, -1,
6224 MOVE_TO_POS | MOVE_TO_Y);
47589c8c 6225 TRACE_MOVE ((stderr, "move_it_v: to %d\n", IT_CHARPOS (*it)));
5f5c8ee5
GM
6226
6227 /* If buffer ends in ZV without a newline, move to the start of
6228 the line to satisfy the post-condition. */
6229 if (IT_CHARPOS (*it) == ZV
6230 && FETCH_BYTE (IT_BYTEPOS (*it) - 1) != '\n')
6231 move_it_by_lines (it, 0, 0);
6232 }
6233}
6234
6235
47fc2c10
GM
6236/* Move iterator IT past the end of the text line it is in. */
6237
6238void
6239move_it_past_eol (it)
6240 struct it *it;
6241{
6242 enum move_it_result rc;
2311178e 6243
47fc2c10
GM
6244 rc = move_it_in_display_line_to (it, Z, 0, MOVE_TO_POS);
6245 if (rc == MOVE_NEWLINE_OR_CR)
6246 set_iterator_to_next (it, 0);
6247}
6248
6249
2c79b732
GM
6250#if 0 /* Currently not used. */
6251
5f5c8ee5
GM
6252/* Return non-zero if some text between buffer positions START_CHARPOS
6253 and END_CHARPOS is invisible. IT->window is the window for text
6254 property lookup. */
6255
6256static int
6257invisible_text_between_p (it, start_charpos, end_charpos)
6258 struct it *it;
6259 int start_charpos, end_charpos;
6260{
5f5c8ee5
GM
6261 Lisp_Object prop, limit;
6262 int invisible_found_p;
2311178e 6263
5f5c8ee5
GM
6264 xassert (it != NULL && start_charpos <= end_charpos);
6265
6266 /* Is text at START invisible? */
6267 prop = Fget_char_property (make_number (start_charpos), Qinvisible,
6268 it->window);
6269 if (TEXT_PROP_MEANS_INVISIBLE (prop))
6270 invisible_found_p = 1;
6271 else
6272 {
016b5642
MB
6273 limit = Fnext_single_char_property_change (make_number (start_charpos),
6274 Qinvisible, Qnil,
6275 make_number (end_charpos));
5f5c8ee5
GM
6276 invisible_found_p = XFASTINT (limit) < end_charpos;
6277 }
6278
6279 return invisible_found_p;
5f5c8ee5
GM
6280}
6281
2c79b732
GM
6282#endif /* 0 */
6283
5f5c8ee5
GM
6284
6285/* Move IT by a specified number DVPOS of screen lines down. DVPOS
6286 negative means move up. DVPOS == 0 means move to the start of the
6287 screen line. NEED_Y_P non-zero means calculate IT->current_y. If
6288 NEED_Y_P is zero, IT->current_y will be left unchanged.
6289
6290 Further optimization ideas: If we would know that IT->f doesn't use
6291 a face with proportional font, we could be faster for
6292 truncate-lines nil. */
6293
6294void
6295move_it_by_lines (it, dvpos, need_y_p)
6296 struct it *it;
6297 int dvpos, need_y_p;
6298{
6299 struct position pos;
2311178e 6300
5f5c8ee5
GM
6301 if (!FRAME_WINDOW_P (it->f))
6302 {
6303 struct text_pos textpos;
2311178e 6304
5f5c8ee5
GM
6305 /* We can use vmotion on frames without proportional fonts. */
6306 pos = *vmotion (IT_CHARPOS (*it), dvpos, it->w);
6307 SET_TEXT_POS (textpos, pos.bufpos, pos.bytepos);
6308 reseat (it, textpos, 1);
6309 it->vpos += pos.vpos;
6310 it->current_y += pos.vpos;
6311 }
6312 else if (dvpos == 0)
6313 {
6314 /* DVPOS == 0 means move to the start of the screen line. */
6315 move_it_vertically_backward (it, 0);
6316 xassert (it->current_x == 0 && it->hpos == 0);
6317 }
6318 else if (dvpos > 0)
2c79b732 6319 move_it_to (it, -1, -1, -1, it->vpos + dvpos, MOVE_TO_VPOS);
5f5c8ee5
GM
6320 else
6321 {
6322 struct it it2;
6323 int start_charpos, i;
2311178e 6324
e8660d73
GM
6325 /* Start at the beginning of the screen line containing IT's
6326 position. */
6327 move_it_vertically_backward (it, 0);
2311178e 6328
5f5c8ee5
GM
6329 /* Go back -DVPOS visible lines and reseat the iterator there. */
6330 start_charpos = IT_CHARPOS (*it);
6331 for (i = -dvpos; i && IT_CHARPOS (*it) > BEGV; --i)
6332 back_to_previous_visible_line_start (it);
6333 reseat (it, it->current.pos, 1);
6334 it->current_x = it->hpos = 0;
6335
6336 /* Above call may have moved too far if continuation lines
6337 are involved. Scan forward and see if it did. */
6338 it2 = *it;
6339 it2.vpos = it2.current_y = 0;
6340 move_it_to (&it2, start_charpos, -1, -1, -1, MOVE_TO_POS);
6341 it->vpos -= it2.vpos;
6342 it->current_y -= it2.current_y;
6343 it->current_x = it->hpos = 0;
6344
6345 /* If we moved too far, move IT some lines forward. */
6346 if (it2.vpos > -dvpos)
6347 {
6348 int delta = it2.vpos + dvpos;
6349 move_it_to (it, -1, -1, -1, it->vpos + delta, MOVE_TO_VPOS);
6350 }
6351 }
6352}
6353
3824b1a6
AS
6354/* Return 1 if IT points into the middle of a display vector. */
6355
6356int
6357in_display_vector_p (it)
6358 struct it *it;
6359{
6360 return (it->method == next_element_from_display_vector
6361 && it->current.dpvec_index > 0
6362 && it->dpvec + it->current.dpvec_index != it->dpend);
6363}
5f5c8ee5
GM
6364
6365\f
6366/***********************************************************************
6367 Messages
6368 ***********************************************************************/
6369
6370
937248bc
GM
6371/* Add a message with format string FORMAT and arguments ARG1 and ARG2
6372 to *Messages*. */
6373
6374void
6375add_to_log (format, arg1, arg2)
6376 char *format;
6377 Lisp_Object arg1, arg2;
6378{
6379 Lisp_Object args[3];
6380 Lisp_Object msg, fmt;
6381 char *buffer;
6382 int len;
6383 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
6384
ae794295
GM
6385 /* Do nothing if called asynchronously. Inserting text into
6386 a buffer may call after-change-functions and alike and
6387 that would means running Lisp asynchronously. */
6388 if (handling_signal)
6389 return;
6390
937248bc
GM
6391 fmt = msg = Qnil;
6392 GCPRO4 (fmt, msg, arg1, arg2);
2311178e 6393
937248bc
GM
6394 args[0] = fmt = build_string (format);
6395 args[1] = arg1;
6396 args[2] = arg2;
6fc556fd 6397 msg = Fformat (3, args);
937248bc 6398
2051c264 6399 len = SBYTES (msg) + 1;
937248bc 6400 buffer = (char *) alloca (len);
2051c264 6401 bcopy (SDATA (msg), buffer, len);
2311178e 6402
796184bc 6403 message_dolog (buffer, len - 1, 1, 0);
937248bc
GM
6404 UNGCPRO;
6405}
6406
6407
5f5c8ee5
GM
6408/* Output a newline in the *Messages* buffer if "needs" one. */
6409
6410void
6411message_log_maybe_newline ()
6412{
6413 if (message_log_need_newline)
6414 message_dolog ("", 0, 1, 0);
6415}
6416
6417
1e313f28 6418/* Add a string M of length NBYTES to the message log, optionally
5f5c8ee5
GM
6419 terminated with a newline when NLFLAG is non-zero. MULTIBYTE, if
6420 nonzero, means interpret the contents of M as multibyte. This
6421 function calls low-level routines in order to bypass text property
6422 hooks, etc. which might not be safe to run. */
6423
6424void
1e313f28 6425message_dolog (m, nbytes, nlflag, multibyte)
50f80c2f 6426 const char *m;
1e313f28 6427 int nbytes, nlflag, multibyte;
5f5c8ee5 6428{
a67e162b
RS
6429 if (!NILP (Vmemory_full))
6430 return;
6431
5f5c8ee5
GM
6432 if (!NILP (Vmessage_log_max))
6433 {
6434 struct buffer *oldbuf;
6435 Lisp_Object oldpoint, oldbegv, oldzv;
6436 int old_windows_or_buffers_changed = windows_or_buffers_changed;
6437 int point_at_end = 0;
6438 int zv_at_end = 0;
6439 Lisp_Object old_deactivate_mark, tem;
6052529b 6440 struct gcpro gcpro1;
5f5c8ee5
GM
6441
6442 old_deactivate_mark = Vdeactivate_mark;
6443 oldbuf = current_buffer;
6a94510a 6444 Fset_buffer (Fget_buffer_create (Vmessages_buffer_name));
5f5c8ee5
GM
6445 current_buffer->undo_list = Qt;
6446
b14bc55e
RS
6447 oldpoint = message_dolog_marker1;
6448 set_marker_restricted (oldpoint, make_number (PT), Qnil);
6449 oldbegv = message_dolog_marker2;
6450 set_marker_restricted (oldbegv, make_number (BEGV), Qnil);
6451 oldzv = message_dolog_marker3;
6452 set_marker_restricted (oldzv, make_number (ZV), Qnil);
6453 GCPRO1 (old_deactivate_mark);
5f5c8ee5
GM
6454
6455 if (PT == Z)
6456 point_at_end = 1;
6457 if (ZV == Z)
6458 zv_at_end = 1;
6459
6460 BEGV = BEG;
6461 BEGV_BYTE = BEG_BYTE;
6462 ZV = Z;
6463 ZV_BYTE = Z_BYTE;
6464 TEMP_SET_PT_BOTH (Z, Z_BYTE);
6465
6466 /* Insert the string--maybe converting multibyte to single byte
6467 or vice versa, so that all the text fits the buffer. */
6468 if (multibyte
6469 && NILP (current_buffer->enable_multibyte_characters))
6470 {
1e313f28 6471 int i, c, char_bytes;
5f5c8ee5 6472 unsigned char work[1];
2311178e 6473
5f5c8ee5
GM
6474 /* Convert a multibyte string to single-byte
6475 for the *Message* buffer. */
6e57ec5e 6476 for (i = 0; i < nbytes; i += char_bytes)
5f5c8ee5 6477 {
1e313f28 6478 c = string_char_and_length (m + i, nbytes - i, &char_bytes);
522b161c 6479 work[0] = (ASCII_CHAR_P (c)
5f5c8ee5
GM
6480 ? c
6481 : multibyte_char_to_unibyte (c, Qnil));
6482 insert_1_both (work, 1, 1, 1, 0, 0);
6483 }
6484 }
6485 else if (! multibyte
6486 && ! NILP (current_buffer->enable_multibyte_characters))
6487 {
1e313f28 6488 int i, c, char_bytes;
5f5c8ee5 6489 unsigned char *msg = (unsigned char *) m;
260a86a0 6490 unsigned char str[MAX_MULTIBYTE_LENGTH];
5f5c8ee5
GM
6491 /* Convert a single-byte string to multibyte
6492 for the *Message* buffer. */
1e313f28 6493 for (i = 0; i < nbytes; i++)
5f5c8ee5
GM
6494 {
6495 c = unibyte_char_to_multibyte (msg[i]);
1e313f28
GM
6496 char_bytes = CHAR_STRING (c, str);
6497 insert_1_both (str, 1, char_bytes, 1, 0, 0);
5f5c8ee5
GM
6498 }
6499 }
1e313f28
GM
6500 else if (nbytes)
6501 insert_1 (m, nbytes, 1, 0, 0);
5f5c8ee5
GM
6502
6503 if (nlflag)
6504 {
6505 int this_bol, this_bol_byte, prev_bol, prev_bol_byte, dup;
6506 insert_1 ("\n", 1, 1, 0, 0);
6507
6508 scan_newline (Z, Z_BYTE, BEG, BEG_BYTE, -2, 0);
6509 this_bol = PT;
6510 this_bol_byte = PT_BYTE;
6511
b14bc55e
RS
6512 /* See if this line duplicates the previous one.
6513 If so, combine duplicates. */
5f5c8ee5
GM
6514 if (this_bol > BEG)
6515 {
6516 scan_newline (PT, PT_BYTE, BEG, BEG_BYTE, -2, 0);
6517 prev_bol = PT;
6518 prev_bol_byte = PT_BYTE;
6519
6520 dup = message_log_check_duplicate (prev_bol, prev_bol_byte,
6521 this_bol, this_bol_byte);
6522 if (dup)
6523 {
6524 del_range_both (prev_bol, prev_bol_byte,
6525 this_bol, this_bol_byte, 0);
6526 if (dup > 1)
6527 {
6528 char dupstr[40];
6529 int duplen;
6530
6531 /* If you change this format, don't forget to also
6532 change message_log_check_duplicate. */
6533 sprintf (dupstr, " [%d times]", dup);
6534 duplen = strlen (dupstr);
6535 TEMP_SET_PT_BOTH (Z - 1, Z_BYTE - 1);
6536 insert_1 (dupstr, duplen, 1, 0, 1);
6537 }
6538 }
6539 }
6540
b14bc55e
RS
6541 /* If we have more than the desired maximum number of lines
6542 in the *Messages* buffer now, delete the oldest ones.
6543 This is safe because we don't have undo in this buffer. */
6544
5f5c8ee5
GM
6545 if (NATNUMP (Vmessage_log_max))
6546 {
6547 scan_newline (Z, Z_BYTE, BEG, BEG_BYTE,
6548 -XFASTINT (Vmessage_log_max) - 1, 0);
6549 del_range_both (BEG, BEG_BYTE, PT, PT_BYTE, 0);
6550 }
6551 }
6552 BEGV = XMARKER (oldbegv)->charpos;
6553 BEGV_BYTE = marker_byte_position (oldbegv);
6554
6555 if (zv_at_end)
6556 {
6557 ZV = Z;
6558 ZV_BYTE = Z_BYTE;
6559 }
6560 else
6561 {
6562 ZV = XMARKER (oldzv)->charpos;
6563 ZV_BYTE = marker_byte_position (oldzv);
6564 }
6565
6566 if (point_at_end)
6567 TEMP_SET_PT_BOTH (Z, Z_BYTE);
6568 else
6569 /* We can't do Fgoto_char (oldpoint) because it will run some
6570 Lisp code. */
6571 TEMP_SET_PT_BOTH (XMARKER (oldpoint)->charpos,
6572 XMARKER (oldpoint)->bytepos);
6573
6574 UNGCPRO;
cfea0546
SM
6575 unchain_marker (XMARKER (oldpoint));
6576 unchain_marker (XMARKER (oldbegv));
6577 unchain_marker (XMARKER (oldzv));
5f5c8ee5
GM
6578
6579 tem = Fget_buffer_window (Fcurrent_buffer (), Qt);
6580 set_buffer_internal (oldbuf);
6581 if (NILP (tem))
6582 windows_or_buffers_changed = old_windows_or_buffers_changed;
6583 message_log_need_newline = !nlflag;
6584 Vdeactivate_mark = old_deactivate_mark;
6585 }
6586}
6587
6588
6589/* We are at the end of the buffer after just having inserted a newline.
6590 (Note: We depend on the fact we won't be crossing the gap.)
6591 Check to see if the most recent message looks a lot like the previous one.
6592 Return 0 if different, 1 if the new one should just replace it, or a
6593 value N > 1 if we should also append " [N times]". */
6594
6595static int
6596message_log_check_duplicate (prev_bol, prev_bol_byte, this_bol, this_bol_byte)
6597 int prev_bol, this_bol;
6598 int prev_bol_byte, this_bol_byte;
6599{
6600 int i;
6601 int len = Z_BYTE - 1 - this_bol_byte;
6602 int seen_dots = 0;
6603 unsigned char *p1 = BUF_BYTE_ADDRESS (current_buffer, prev_bol_byte);
6604 unsigned char *p2 = BUF_BYTE_ADDRESS (current_buffer, this_bol_byte);
6605
6606 for (i = 0; i < len; i++)
6607 {
509633e3 6608 if (i >= 3 && p1[i-3] == '.' && p1[i-2] == '.' && p1[i-1] == '.')
5f5c8ee5
GM
6609 seen_dots = 1;
6610 if (p1[i] != p2[i])
6611 return seen_dots;
6612 }
6613 p1 += len;
6614 if (*p1 == '\n')
6615 return 2;
6616 if (*p1++ == ' ' && *p1++ == '[')
6617 {
6618 int n = 0;
6619 while (*p1 >= '0' && *p1 <= '9')
6620 n = n * 10 + *p1++ - '0';
6621 if (strncmp (p1, " times]\n", 8) == 0)
6622 return n+1;
6623 }
6624 return 0;
6625}
6626
6627
1e313f28
GM
6628/* Display an echo area message M with a specified length of NBYTES
6629 bytes. The string may include null characters. If M is 0, clear
6630 out any existing message, and let the mini-buffer text show
6631 through.
5f5c8ee5
GM
6632
6633 The buffer M must continue to exist until after the echo area gets
6634 cleared or some other message gets displayed there. This means do
6635 not pass text that is stored in a Lisp string; do not pass text in
6636 a buffer that was alloca'd. */
6637
6638void
1e313f28 6639message2 (m, nbytes, multibyte)
50f80c2f 6640 const char *m;
1e313f28 6641 int nbytes;
5f5c8ee5
GM
6642 int multibyte;
6643{
6644 /* First flush out any partial line written with print. */
6645 message_log_maybe_newline ();
6646 if (m)
1e313f28
GM
6647 message_dolog (m, nbytes, 1, multibyte);
6648 message2_nolog (m, nbytes, multibyte);
5f5c8ee5
GM
6649}
6650
6651
6652/* The non-logging counterpart of message2. */
6653
6654void
1e313f28 6655message2_nolog (m, nbytes, multibyte)
50f80c2f 6656 const char *m;
e3383b6f 6657 int nbytes, multibyte;
5f5c8ee5 6658{
886bd6f2 6659 struct frame *sf = SELECTED_FRAME ();
5f5c8ee5
GM
6660 message_enable_multibyte = multibyte;
6661
6662 if (noninteractive)
6663 {
6664 if (noninteractive_need_newline)
6665 putc ('\n', stderr);
6666 noninteractive_need_newline = 0;
6667 if (m)
1e313f28 6668 fwrite (m, nbytes, 1, stderr);
5f5c8ee5
GM
6669 if (cursor_in_echo_area == 0)
6670 fprintf (stderr, "\n");
6671 fflush (stderr);
6672 }
6673 /* A null message buffer means that the frame hasn't really been
6674 initialized yet. Error messages get reported properly by
6675 cmd_error, so this must be just an informative message; toss it. */
2311178e 6676 else if (INTERACTIVE
886bd6f2
GM
6677 && sf->glyphs_initialized_p
6678 && FRAME_MESSAGE_BUF (sf))
5f5c8ee5
GM
6679 {
6680 Lisp_Object mini_window;
6681 struct frame *f;
6682
6683 /* Get the frame containing the mini-buffer
6684 that the selected frame is using. */
886bd6f2 6685 mini_window = FRAME_MINIBUF_WINDOW (sf);
5f5c8ee5
GM
6686 f = XFRAME (WINDOW_FRAME (XWINDOW (mini_window)));
6687
6688 FRAME_SAMPLE_VISIBILITY (f);
886bd6f2 6689 if (FRAME_VISIBLE_P (sf)
5f5c8ee5
GM
6690 && ! FRAME_VISIBLE_P (f))
6691 Fmake_frame_visible (WINDOW_FRAME (XWINDOW (mini_window)));
6692
6693 if (m)
6694 {
1e313f28 6695 set_message (m, Qnil, nbytes, multibyte);
5f5c8ee5
GM
6696 if (minibuffer_auto_raise)
6697 Fraise_frame (WINDOW_FRAME (XWINDOW (mini_window)));
6698 }
6699 else
c6e89d6c 6700 clear_message (1, 1);
5f5c8ee5 6701
c6e89d6c 6702 do_pending_window_change (0);
5f5c8ee5 6703 echo_area_display (1);
c6e89d6c 6704 do_pending_window_change (0);
5f5c8ee5
GM
6705 if (frame_up_to_date_hook != 0 && ! gc_in_progress)
6706 (*frame_up_to_date_hook) (f);
6707 }
6708}
6709
6710
c6e89d6c
GM
6711/* Display an echo area message M with a specified length of NBYTES
6712 bytes. The string may include null characters. If M is not a
5f5c8ee5
GM
6713 string, clear out any existing message, and let the mini-buffer
6714 text show through. */
6715
6716void
c6e89d6c 6717message3 (m, nbytes, multibyte)
5f5c8ee5 6718 Lisp_Object m;
c6e89d6c 6719 int nbytes;
5f5c8ee5
GM
6720 int multibyte;
6721{
6722 struct gcpro gcpro1;
6723
6724 GCPRO1 (m);
2311178e 6725
5f5c8ee5
GM
6726 /* First flush out any partial line written with print. */
6727 message_log_maybe_newline ();
6728 if (STRINGP (m))
2051c264 6729 message_dolog (SDATA (m), nbytes, 1, multibyte);
c6e89d6c 6730 message3_nolog (m, nbytes, multibyte);
5f5c8ee5
GM
6731
6732 UNGCPRO;
6733}
6734
6735
6736/* The non-logging version of message3. */
6737
6738void
c6e89d6c 6739message3_nolog (m, nbytes, multibyte)
5f5c8ee5 6740 Lisp_Object m;
c6e89d6c 6741 int nbytes, multibyte;
5f5c8ee5 6742{
886bd6f2 6743 struct frame *sf = SELECTED_FRAME ();
5f5c8ee5
GM
6744 message_enable_multibyte = multibyte;
6745
6746 if (noninteractive)
6747 {
6748 if (noninteractive_need_newline)
6749 putc ('\n', stderr);
6750 noninteractive_need_newline = 0;
6751 if (STRINGP (m))
2051c264 6752 fwrite (SDATA (m), nbytes, 1, stderr);
5f5c8ee5
GM
6753 if (cursor_in_echo_area == 0)
6754 fprintf (stderr, "\n");
6755 fflush (stderr);
6756 }
6757 /* A null message buffer means that the frame hasn't really been
6758 initialized yet. Error messages get reported properly by
6759 cmd_error, so this must be just an informative message; toss it. */
2311178e 6760 else if (INTERACTIVE
886bd6f2
GM
6761 && sf->glyphs_initialized_p
6762 && FRAME_MESSAGE_BUF (sf))
5f5c8ee5
GM
6763 {
6764 Lisp_Object mini_window;
c6e89d6c 6765 Lisp_Object frame;
5f5c8ee5
GM
6766 struct frame *f;
6767
6768 /* Get the frame containing the mini-buffer
6769 that the selected frame is using. */
886bd6f2 6770 mini_window = FRAME_MINIBUF_WINDOW (sf);
c6e89d6c
GM
6771 frame = XWINDOW (mini_window)->frame;
6772 f = XFRAME (frame);
5f5c8ee5
GM
6773
6774 FRAME_SAMPLE_VISIBILITY (f);
886bd6f2 6775 if (FRAME_VISIBLE_P (sf)
c6e89d6c
GM
6776 && !FRAME_VISIBLE_P (f))
6777 Fmake_frame_visible (frame);
5f5c8ee5 6778
2051c264 6779 if (STRINGP (m) && SCHARS (m) > 0)
5f5c8ee5 6780 {
c6e89d6c 6781 set_message (NULL, m, nbytes, multibyte);
468155d7
GM
6782 if (minibuffer_auto_raise)
6783 Fraise_frame (frame);
5f5c8ee5
GM
6784 }
6785 else
c6e89d6c 6786 clear_message (1, 1);
5f5c8ee5 6787
c6e89d6c 6788 do_pending_window_change (0);
5f5c8ee5 6789 echo_area_display (1);
c6e89d6c 6790 do_pending_window_change (0);
5f5c8ee5
GM
6791 if (frame_up_to_date_hook != 0 && ! gc_in_progress)
6792 (*frame_up_to_date_hook) (f);
6793 }
6794}
6795
6796
6797/* Display a null-terminated echo area message M. If M is 0, clear
6798 out any existing message, and let the mini-buffer text show through.
6799
6800 The buffer M must continue to exist until after the echo area gets
6801 cleared or some other message gets displayed there. Do not pass
6802 text that is stored in a Lisp string. Do not pass text in a buffer
6803 that was alloca'd. */
6804
6805void
6806message1 (m)
6807 char *m;
6808{
6809 message2 (m, (m ? strlen (m) : 0), 0);
6810}
6811
6812
6813/* The non-logging counterpart of message1. */
6814
6815void
6816message1_nolog (m)
6817 char *m;
6818{
6819 message2_nolog (m, (m ? strlen (m) : 0), 0);
6820}
6821
6822/* Display a message M which contains a single %s
6823 which gets replaced with STRING. */
6824
6825void
6826message_with_string (m, string, log)
6827 char *m;
6828 Lisp_Object string;
6829 int log;
6830{
5b6d51b6
RS
6831 CHECK_STRING (string);
6832
5f5c8ee5
GM
6833 if (noninteractive)
6834 {
6835 if (m)
6836 {
6837 if (noninteractive_need_newline)
6838 putc ('\n', stderr);
6839 noninteractive_need_newline = 0;
2051c264 6840 fprintf (stderr, m, SDATA (string));
5f5c8ee5
GM
6841 if (cursor_in_echo_area == 0)
6842 fprintf (stderr, "\n");
6843 fflush (stderr);
6844 }
6845 }
6846 else if (INTERACTIVE)
6847 {
6848 /* The frame whose minibuffer we're going to display the message on.
6849 It may be larger than the selected frame, so we need
6850 to use its buffer, not the selected frame's buffer. */
6851 Lisp_Object mini_window;
886bd6f2 6852 struct frame *f, *sf = SELECTED_FRAME ();
5f5c8ee5
GM
6853
6854 /* Get the frame containing the minibuffer
6855 that the selected frame is using. */
886bd6f2 6856 mini_window = FRAME_MINIBUF_WINDOW (sf);
5f5c8ee5
GM
6857 f = XFRAME (WINDOW_FRAME (XWINDOW (mini_window)));
6858
6859 /* A null message buffer means that the frame hasn't really been
6860 initialized yet. Error messages get reported properly by
6861 cmd_error, so this must be just an informative message; toss it. */
6862 if (FRAME_MESSAGE_BUF (f))
6863 {
eb484132
GM
6864 Lisp_Object args[2], message;
6865 struct gcpro gcpro1, gcpro2;
5f5c8ee5 6866
eb484132
GM
6867 args[0] = build_string (m);
6868 args[1] = message = string;
78e17433 6869 GCPRO2 (args[0], message);
eb484132 6870 gcpro1.nvars = 2;
2311178e 6871
eb484132 6872 message = Fformat (2, args);
5f5c8ee5
GM
6873
6874 if (log)
d5db4077 6875 message3 (message, SBYTES (message), STRING_MULTIBYTE (message));
5f5c8ee5 6876 else
d5db4077 6877 message3_nolog (message, SBYTES (message), STRING_MULTIBYTE (message));
eb484132
GM
6878
6879 UNGCPRO;
5f5c8ee5
GM
6880
6881 /* Print should start at the beginning of the message
6882 buffer next time. */
6883 message_buf_print = 0;
6884 }
6885 }
6886}
6887
6888
5f5c8ee5
GM
6889/* Dump an informative message to the minibuf. If M is 0, clear out
6890 any existing message, and let the mini-buffer text show through. */
6891
6892/* VARARGS 1 */
6893void
6894message (m, a1, a2, a3)
6895 char *m;
6896 EMACS_INT a1, a2, a3;
6897{
6898 if (noninteractive)
6899 {
6900 if (m)
6901 {
6902 if (noninteractive_need_newline)
6903 putc ('\n', stderr);
6904 noninteractive_need_newline = 0;
6905 fprintf (stderr, m, a1, a2, a3);
6906 if (cursor_in_echo_area == 0)
6907 fprintf (stderr, "\n");
6908 fflush (stderr);
6909 }
6910 }
6911 else if (INTERACTIVE)
6912 {
6913 /* The frame whose mini-buffer we're going to display the message
6914 on. It may be larger than the selected frame, so we need to
6915 use its buffer, not the selected frame's buffer. */
6916 Lisp_Object mini_window;
886bd6f2 6917 struct frame *f, *sf = SELECTED_FRAME ();
5f5c8ee5
GM
6918
6919 /* Get the frame containing the mini-buffer
6920 that the selected frame is using. */
886bd6f2 6921 mini_window = FRAME_MINIBUF_WINDOW (sf);
5f5c8ee5
GM
6922 f = XFRAME (WINDOW_FRAME (XWINDOW (mini_window)));
6923
6924 /* A null message buffer means that the frame hasn't really been
6925 initialized yet. Error messages get reported properly by
6926 cmd_error, so this must be just an informative message; toss
6927 it. */
6928 if (FRAME_MESSAGE_BUF (f))
6929 {
6930 if (m)
6931 {
6932 int len;
6933#ifdef NO_ARG_ARRAY
6934 char *a[3];
6935 a[0] = (char *) a1;
6936 a[1] = (char *) a2;
6937 a[2] = (char *) a3;
6938
6939 len = doprnt (FRAME_MESSAGE_BUF (f),
6940 FRAME_MESSAGE_BUF_SIZE (f), m, (char *)0, 3, a);
6941#else
6942 len = doprnt (FRAME_MESSAGE_BUF (f),
6943 FRAME_MESSAGE_BUF_SIZE (f), m, (char *)0, 3,
6944 (char **) &a1);
6945#endif /* NO_ARG_ARRAY */
6946
6947 message2 (FRAME_MESSAGE_BUF (f), len, 0);
6948 }
6949 else
6950 message1 (0);
6951
6952 /* Print should start at the beginning of the message
6953 buffer next time. */
6954 message_buf_print = 0;
6955 }
6956 }
6957}
6958
6959
6960/* The non-logging version of message. */
6961
6962void
6963message_nolog (m, a1, a2, a3)
6964 char *m;
6965 EMACS_INT a1, a2, a3;
6966{
6967 Lisp_Object old_log_max;
6968 old_log_max = Vmessage_log_max;
6969 Vmessage_log_max = Qnil;
6970 message (m, a1, a2, a3);
6971 Vmessage_log_max = old_log_max;
6972}
6973
6974
c6e89d6c
GM
6975/* Display the current message in the current mini-buffer. This is
6976 only called from error handlers in process.c, and is not time
6977 critical. */
5f5c8ee5
GM
6978
6979void
6980update_echo_area ()
6981{
c6e89d6c
GM
6982 if (!NILP (echo_area_buffer[0]))
6983 {
6984 Lisp_Object string;
6985 string = Fcurrent_message ();
2311178e 6986 message3 (string, SBYTES (string),
c6e89d6c
GM
6987 !NILP (current_buffer->enable_multibyte_characters));
6988 }
6989}
6990
6991
a67e162b
RS
6992/* Make sure echo area buffers in `echo_buffers' are live.
6993 If they aren't, make new ones. */
5bcfeb49
GM
6994
6995static void
6996ensure_echo_area_buffers ()
6997{
6998 int i;
6999
7000 for (i = 0; i < 2; ++i)
7001 if (!BUFFERP (echo_buffer[i])
7002 || NILP (XBUFFER (echo_buffer[i])->name))
7003 {
7004 char name[30];
ff3d9573
GM
7005 Lisp_Object old_buffer;
7006 int j;
7007
7008 old_buffer = echo_buffer[i];
5bcfeb49
GM
7009 sprintf (name, " *Echo Area %d*", i);
7010 echo_buffer[i] = Fget_buffer_create (build_string (name));
ad4f174e 7011 XBUFFER (echo_buffer[i])->truncate_lines = Qnil;
ff3d9573
GM
7012
7013 for (j = 0; j < 2; ++j)
7014 if (EQ (old_buffer, echo_area_buffer[j]))
7015 echo_area_buffer[j] = echo_buffer[i];
5bcfeb49
GM
7016 }
7017}
7018
7019
23a96c77 7020/* Call FN with args A1..A4 with either the current or last displayed
c6e89d6c
GM
7021 echo_area_buffer as current buffer.
7022
7023 WHICH zero means use the current message buffer
7024 echo_area_buffer[0]. If that is nil, choose a suitable buffer
7025 from echo_buffer[] and clear it.
7026
7027 WHICH > 0 means use echo_area_buffer[1]. If that is nil, choose a
7028 suitable buffer from echo_buffer[] and clear it.
7029
7030 If WHICH < 0, set echo_area_buffer[1] to echo_area_buffer[0], so
7031 that the current message becomes the last displayed one, make
7032 choose a suitable buffer for echo_area_buffer[0], and clear it.
7033
4b41cebb 7034 Value is what FN returns. */
c6e89d6c
GM
7035
7036static int
23a96c77 7037with_echo_area_buffer (w, which, fn, a1, a2, a3, a4)
c6e89d6c
GM
7038 struct window *w;
7039 int which;
23dd2d97
KR
7040 int (*fn) P_ ((EMACS_INT, Lisp_Object, EMACS_INT, EMACS_INT));
7041 EMACS_INT a1;
7042 Lisp_Object a2;
7043 EMACS_INT a3, a4;
c6e89d6c
GM
7044{
7045 Lisp_Object buffer;
15e26c76 7046 int this_one, the_other, clear_buffer_p, rc;
331379bf 7047 int count = SPECPDL_INDEX ();
c6e89d6c 7048
9583b2bb 7049 /* If buffers aren't live, make new ones. */
5bcfeb49 7050 ensure_echo_area_buffers ();
c6e89d6c
GM
7051
7052 clear_buffer_p = 0;
2311178e 7053
c6e89d6c
GM
7054 if (which == 0)
7055 this_one = 0, the_other = 1;
7056 else if (which > 0)
7057 this_one = 1, the_other = 0;
5f5c8ee5 7058 else
c6e89d6c
GM
7059 {
7060 this_one = 0, the_other = 1;
7061 clear_buffer_p = 1;
2311178e 7062
c6e89d6c
GM
7063 /* We need a fresh one in case the current echo buffer equals
7064 the one containing the last displayed echo area message. */
7065 if (!NILP (echo_area_buffer[this_one])
7066 && EQ (echo_area_buffer[this_one], echo_area_buffer[the_other]))
7067 echo_area_buffer[this_one] = Qnil;
c6e89d6c
GM
7068 }
7069
7070 /* Choose a suitable buffer from echo_buffer[] is we don't
7071 have one. */
7072 if (NILP (echo_area_buffer[this_one]))
7073 {
7074 echo_area_buffer[this_one]
7075 = (EQ (echo_area_buffer[the_other], echo_buffer[this_one])
7076 ? echo_buffer[the_other]
7077 : echo_buffer[this_one]);
7078 clear_buffer_p = 1;
7079 }
7080
7081 buffer = echo_area_buffer[this_one];
7082
1013f4e3
GM
7083 /* Don't get confused by reusing the buffer used for echoing
7084 for a different purpose. */
032906b1 7085 if (echo_kboard == NULL && EQ (buffer, echo_message_buffer))
1013f4e3
GM
7086 cancel_echoing ();
7087
c6e89d6c
GM
7088 record_unwind_protect (unwind_with_echo_area_buffer,
7089 with_echo_area_buffer_unwind_data (w));
7090
7091 /* Make the echo area buffer current. Note that for display
7092 purposes, it is not necessary that the displayed window's buffer
7093 == current_buffer, except for text property lookup. So, let's
7094 only set that buffer temporarily here without doing a full
7095 Fset_window_buffer. We must also change w->pointm, though,
7096 because otherwise an assertions in unshow_buffer fails, and Emacs
7097 aborts. */
9142dd5b 7098 set_buffer_internal_1 (XBUFFER (buffer));
c6e89d6c
GM
7099 if (w)
7100 {
7101 w->buffer = buffer;
7102 set_marker_both (w->pointm, buffer, BEG, BEG_BYTE);
7103 }
ad4f174e 7104
c6e89d6c
GM
7105 current_buffer->undo_list = Qt;
7106 current_buffer->read_only = Qnil;
bbbf6d06 7107 specbind (Qinhibit_read_only, Qt);
0b04fa5f 7108 specbind (Qinhibit_modification_hooks, Qt);
c6e89d6c
GM
7109
7110 if (clear_buffer_p && Z > BEG)
7111 del_range (BEG, Z);
7112
7113 xassert (BEGV >= BEG);
7114 xassert (ZV <= Z && ZV >= BEGV);
7115
23a96c77 7116 rc = fn (a1, a2, a3, a4);
c6e89d6c
GM
7117
7118 xassert (BEGV >= BEG);
7119 xassert (ZV <= Z && ZV >= BEGV);
7120
7121 unbind_to (count, Qnil);
7122 return rc;
5f5c8ee5
GM
7123}
7124
7125
c6e89d6c
GM
7126/* Save state that should be preserved around the call to the function
7127 FN called in with_echo_area_buffer. */
5f5c8ee5 7128
c6e89d6c
GM
7129static Lisp_Object
7130with_echo_area_buffer_unwind_data (w)
7131 struct window *w;
5f5c8ee5 7132{
c6e89d6c
GM
7133 int i = 0;
7134 Lisp_Object vector;
5f5c8ee5 7135
c6e89d6c
GM
7136 /* Reduce consing by keeping one vector in
7137 Vwith_echo_area_save_vector. */
7138 vector = Vwith_echo_area_save_vector;
7139 Vwith_echo_area_save_vector = Qnil;
2311178e 7140
c6e89d6c 7141 if (NILP (vector))
9142dd5b 7142 vector = Fmake_vector (make_number (7), Qnil);
2311178e 7143
a61b7058
GM
7144 XSETBUFFER (AREF (vector, i), current_buffer); ++i;
7145 AREF (vector, i) = Vdeactivate_mark, ++i;
7146 AREF (vector, i) = make_number (windows_or_buffers_changed), ++i;
2311178e 7147
c6e89d6c
GM
7148 if (w)
7149 {
a61b7058
GM
7150 XSETWINDOW (AREF (vector, i), w); ++i;
7151 AREF (vector, i) = w->buffer; ++i;
7152 AREF (vector, i) = make_number (XMARKER (w->pointm)->charpos); ++i;
7153 AREF (vector, i) = make_number (XMARKER (w->pointm)->bytepos); ++i;
c6e89d6c
GM
7154 }
7155 else
7156 {
7157 int end = i + 4;
a61b7058
GM
7158 for (; i < end; ++i)
7159 AREF (vector, i) = Qnil;
c6e89d6c 7160 }
5f5c8ee5 7161
a61b7058 7162 xassert (i == ASIZE (vector));
c6e89d6c
GM
7163 return vector;
7164}
5f5c8ee5 7165
5f5c8ee5 7166
c6e89d6c
GM
7167/* Restore global state from VECTOR which was created by
7168 with_echo_area_buffer_unwind_data. */
7169
7170static Lisp_Object
7171unwind_with_echo_area_buffer (vector)
7172 Lisp_Object vector;
7173{
bbbf6d06
GM
7174 set_buffer_internal_1 (XBUFFER (AREF (vector, 0)));
7175 Vdeactivate_mark = AREF (vector, 1);
7176 windows_or_buffers_changed = XFASTINT (AREF (vector, 2));
c6e89d6c 7177
bbbf6d06 7178 if (WINDOWP (AREF (vector, 3)))
c6e89d6c
GM
7179 {
7180 struct window *w;
7181 Lisp_Object buffer, charpos, bytepos;
2311178e 7182
bbbf6d06
GM
7183 w = XWINDOW (AREF (vector, 3));
7184 buffer = AREF (vector, 4);
7185 charpos = AREF (vector, 5);
7186 bytepos = AREF (vector, 6);
2311178e 7187
c6e89d6c
GM
7188 w->buffer = buffer;
7189 set_marker_both (w->pointm, buffer,
7190 XFASTINT (charpos), XFASTINT (bytepos));
7191 }
7192
7193 Vwith_echo_area_save_vector = vector;
7194 return Qnil;
7195}
7196
7197
7198/* Set up the echo area for use by print functions. MULTIBYTE_P
7199 non-zero means we will print multibyte. */
7200
7201void
7202setup_echo_area_for_printing (multibyte_p)
7203 int multibyte_p;
7204{
03b0a4b4
RS
7205 /* If we can't find an echo area any more, exit. */
7206 if (! FRAME_LIVE_P (XFRAME (selected_frame)))
7207 Fkill_emacs (Qnil);
7208
5bcfeb49
GM
7209 ensure_echo_area_buffers ();
7210
c6e89d6c
GM
7211 if (!message_buf_print)
7212 {
7213 /* A message has been output since the last time we printed.
7214 Choose a fresh echo area buffer. */
7215 if (EQ (echo_area_buffer[1], echo_buffer[0]))
2311178e 7216 echo_area_buffer[0] = echo_buffer[1];
c6e89d6c
GM
7217 else
7218 echo_area_buffer[0] = echo_buffer[0];
7219
7220 /* Switch to that buffer and clear it. */
7221 set_buffer_internal (XBUFFER (echo_area_buffer[0]));
ab2c5f0a 7222 current_buffer->truncate_lines = Qnil;
2311178e 7223
c6e89d6c 7224 if (Z > BEG)
bbbf6d06 7225 {
331379bf 7226 int count = SPECPDL_INDEX ();
bbbf6d06 7227 specbind (Qinhibit_read_only, Qt);
a67e162b 7228 /* Note that undo recording is always disabled. */
bbbf6d06
GM
7229 del_range (BEG, Z);
7230 unbind_to (count, Qnil);
7231 }
c6e89d6c
GM
7232 TEMP_SET_PT_BOTH (BEG, BEG_BYTE);
7233
7234 /* Set up the buffer for the multibyteness we need. */
7235 if (multibyte_p
7236 != !NILP (current_buffer->enable_multibyte_characters))
7237 Fset_buffer_multibyte (multibyte_p ? Qt : Qnil);
7238
7239 /* Raise the frame containing the echo area. */
7240 if (minibuffer_auto_raise)
7241 {
886bd6f2 7242 struct frame *sf = SELECTED_FRAME ();
c6e89d6c 7243 Lisp_Object mini_window;
886bd6f2 7244 mini_window = FRAME_MINIBUF_WINDOW (sf);
c6e89d6c
GM
7245 Fraise_frame (WINDOW_FRAME (XWINDOW (mini_window)));
7246 }
7247
8a4e3c0c 7248 message_log_maybe_newline ();
c6e89d6c
GM
7249 message_buf_print = 1;
7250 }
fa77249f
GM
7251 else
7252 {
7253 if (NILP (echo_area_buffer[0]))
7254 {
7255 if (EQ (echo_area_buffer[1], echo_buffer[0]))
2311178e 7256 echo_area_buffer[0] = echo_buffer[1];
fa77249f
GM
7257 else
7258 echo_area_buffer[0] = echo_buffer[0];
7259 }
2311178e 7260
fa77249f 7261 if (current_buffer != XBUFFER (echo_area_buffer[0]))
ab2c5f0a
GM
7262 {
7263 /* Someone switched buffers between print requests. */
7264 set_buffer_internal (XBUFFER (echo_area_buffer[0]));
7265 current_buffer->truncate_lines = Qnil;
7266 }
fa77249f 7267 }
c6e89d6c
GM
7268}
7269
7270
dd2eb166
GM
7271/* Display an echo area message in window W. Value is non-zero if W's
7272 height is changed. If display_last_displayed_message_p is
7273 non-zero, display the message that was last displayed, otherwise
7274 display the current message. */
c6e89d6c
GM
7275
7276static int
7277display_echo_area (w)
7278 struct window *w;
7279{
25edb08f
GM
7280 int i, no_message_p, window_height_changed_p, count;
7281
7282 /* Temporarily disable garbage collections while displaying the echo
7283 area. This is done because a GC can print a message itself.
7284 That message would modify the echo area buffer's contents while a
7285 redisplay of the buffer is going on, and seriously confuse
7286 redisplay. */
7287 count = inhibit_garbage_collection ();
dd2eb166
GM
7288
7289 /* If there is no message, we must call display_echo_area_1
7290 nevertheless because it resizes the window. But we will have to
7291 reset the echo_area_buffer in question to nil at the end because
7292 with_echo_area_buffer will sets it to an empty buffer. */
7293 i = display_last_displayed_message_p ? 1 : 0;
7294 no_message_p = NILP (echo_area_buffer[i]);
2311178e 7295
dd2eb166
GM
7296 window_height_changed_p
7297 = with_echo_area_buffer (w, display_last_displayed_message_p,
23a96c77 7298 display_echo_area_1,
23dd2d97 7299 (EMACS_INT) w, Qnil, 0, 0);
dd2eb166
GM
7300
7301 if (no_message_p)
7302 echo_area_buffer[i] = Qnil;
25edb08f
GM
7303
7304 unbind_to (count, Qnil);
dd2eb166 7305 return window_height_changed_p;
c6e89d6c
GM
7306}
7307
7308
7309/* Helper for display_echo_area. Display the current buffer which
23a96c77
GM
7310 contains the current echo area message in window W, a mini-window,
7311 a pointer to which is passed in A1. A2..A4 are currently not used.
c6e89d6c
GM
7312 Change the height of W so that all of the message is displayed.
7313 Value is non-zero if height of W was changed. */
7314
7315static int
23a96c77 7316display_echo_area_1 (a1, a2, a3, a4)
23dd2d97
KR
7317 EMACS_INT a1;
7318 Lisp_Object a2;
7319 EMACS_INT a3, a4;
c6e89d6c 7320{
23a96c77 7321 struct window *w = (struct window *) a1;
c6e89d6c 7322 Lisp_Object window;
c6e89d6c
GM
7323 struct text_pos start;
7324 int window_height_changed_p = 0;
7325
7326 /* Do this before displaying, so that we have a large enough glyph
7327 matrix for the display. */
92a90e89 7328 window_height_changed_p = resize_mini_window (w, 0);
c6e89d6c
GM
7329
7330 /* Display. */
7331 clear_glyph_matrix (w->desired_matrix);
7332 XSETWINDOW (window, w);
7333 SET_TEXT_POS (start, BEG, BEG_BYTE);
7334 try_window (window, start);
7335
c6e89d6c
GM
7336 return window_height_changed_p;
7337}
7338
7339
92a90e89 7340/* Resize the echo area window to exactly the size needed for the
6d004fea
GM
7341 currently displayed message, if there is one. If a mini-buffer
7342 is active, don't shrink it. */
92a90e89
GM
7343
7344void
308a74d8 7345resize_echo_area_exactly ()
92a90e89
GM
7346{
7347 if (BUFFERP (echo_area_buffer[0])
7348 && WINDOWP (echo_area_window))
7349 {
7350 struct window *w = XWINDOW (echo_area_window);
7351 int resized_p;
6d004fea
GM
7352 Lisp_Object resize_exactly;
7353
7354 if (minibuf_level == 0)
7355 resize_exactly = Qt;
7356 else
7357 resize_exactly = Qnil;
2311178e 7358
23a96c77 7359 resized_p = with_echo_area_buffer (w, 0, resize_mini_window_1,
6d004fea 7360 (EMACS_INT) w, resize_exactly, 0, 0);
92a90e89
GM
7361 if (resized_p)
7362 {
7363 ++windows_or_buffers_changed;
7364 ++update_mode_lines;
7365 redisplay_internal (0);
7366 }
7367 }
7368}
7369
7370
23a96c77 7371/* Callback function for with_echo_area_buffer, when used from
308a74d8 7372 resize_echo_area_exactly. A1 contains a pointer to the window to
6d004fea
GM
7373 resize, EXACTLY non-nil means resize the mini-window exactly to the
7374 size of the text displayed. A3 and A4 are not used. Value is what
7375 resize_mini_window returns. */
23a96c77
GM
7376
7377static int
6d004fea 7378resize_mini_window_1 (a1, exactly, a3, a4)
23dd2d97 7379 EMACS_INT a1;
6d004fea 7380 Lisp_Object exactly;
23dd2d97 7381 EMACS_INT a3, a4;
23a96c77 7382{
6d004fea 7383 return resize_mini_window ((struct window *) a1, !NILP (exactly));
23a96c77
GM
7384}
7385
7386
92a90e89
GM
7387/* Resize mini-window W to fit the size of its contents. EXACT:P
7388 means size the window exactly to the size needed. Otherwise, it's
7389 only enlarged until W's buffer is empty. Value is non-zero if
4b41cebb 7390 the window height has been changed. */
c6e89d6c 7391
9472f927 7392int
92a90e89 7393resize_mini_window (w, exact_p)
c6e89d6c 7394 struct window *w;
92a90e89 7395 int exact_p;
c6e89d6c
GM
7396{
7397 struct frame *f = XFRAME (w->frame);
7398 int window_height_changed_p = 0;
7399
7400 xassert (MINI_WINDOW_P (w));
97cafc0f 7401
2913a9c0
GM
7402 /* Don't resize windows while redisplaying a window; it would
7403 confuse redisplay functions when the size of the window they are
7404 displaying changes from under them. Such a resizing can happen,
7405 for instance, when which-func prints a long message while
7406 we are running fontification-functions. We're running these
7407 functions with safe_call which binds inhibit-redisplay to t. */
7408 if (!NILP (Vinhibit_redisplay))
64c5be50 7409 return 0;
2311178e 7410
97cafc0f 7411 /* Nil means don't try to resize. */
6422c1d7 7412 if (NILP (Vresize_mini_windows)
fa3c6b4d 7413 || (FRAME_X_P (f) && FRAME_X_OUTPUT (f) == NULL))
97cafc0f 7414 return 0;
2311178e 7415
c6e89d6c
GM
7416 if (!FRAME_MINIBUF_ONLY_P (f))
7417 {
7418 struct it it;
dd2eb166 7419 struct window *root = XWINDOW (FRAME_ROOT_WINDOW (f));
da8b7f4f 7420 int total_height = WINDOW_TOTAL_LINES (root) + WINDOW_TOTAL_LINES (w);
dd2eb166 7421 int height, max_height;
da8b7f4f 7422 int unit = FRAME_LINE_HEIGHT (f);
dd2eb166 7423 struct text_pos start;
1bfdbe43
GM
7424 struct buffer *old_current_buffer = NULL;
7425
7426 if (current_buffer != XBUFFER (w->buffer))
7427 {
7428 old_current_buffer = current_buffer;
7429 set_buffer_internal (XBUFFER (w->buffer));
7430 }
9142dd5b 7431
c6e89d6c 7432 init_iterator (&it, w, BEGV, BEGV_BYTE, NULL, DEFAULT_FACE_ID);
c6e89d6c 7433
dd2eb166
GM
7434 /* Compute the max. number of lines specified by the user. */
7435 if (FLOATP (Vmax_mini_window_height))
da8b7f4f 7436 max_height = XFLOATINT (Vmax_mini_window_height) * FRAME_LINES (f);
dd2eb166
GM
7437 else if (INTEGERP (Vmax_mini_window_height))
7438 max_height = XINT (Vmax_mini_window_height);
97cafc0f
GM
7439 else
7440 max_height = total_height / 4;
2311178e 7441
4b41cebb 7442 /* Correct that max. height if it's bogus. */
dd2eb166
GM
7443 max_height = max (1, max_height);
7444 max_height = min (total_height, max_height);
2311178e 7445
dd2eb166 7446 /* Find out the height of the text in the window. */
ad4f174e
GM
7447 if (it.truncate_lines_p)
7448 height = 1;
55b064bd 7449 else
ad4f174e
GM
7450 {
7451 last_height = 0;
7452 move_it_to (&it, ZV, -1, -1, -1, MOVE_TO_POS);
7453 if (it.max_ascent == 0 && it.max_descent == 0)
7454 height = it.current_y + last_height;
7455 else
7456 height = it.current_y + it.max_ascent + it.max_descent;
3c4b7685 7457 height -= it.extra_line_spacing;
ad4f174e
GM
7458 height = (height + unit - 1) / unit;
7459 }
2311178e 7460
dd2eb166
GM
7461 /* Compute a suitable window start. */
7462 if (height > max_height)
7463 {
7464 height = max_height;
7465 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
7466 move_it_vertically_backward (&it, (height - 1) * unit);
7467 start = it.current.pos;
7468 }
7469 else
7470 SET_TEXT_POS (start, BEGV, BEGV_BYTE);
7471 SET_MARKER_FROM_TEXT_POS (w->start, start);
c59c668a 7472
6422c1d7 7473 if (EQ (Vresize_mini_windows, Qgrow_only))
dd2eb166 7474 {
6422c1d7
GM
7475 /* Let it grow only, until we display an empty message, in which
7476 case the window shrinks again. */
da8b7f4f 7477 if (height > WINDOW_TOTAL_LINES (w))
6422c1d7 7478 {
da8b7f4f 7479 int old_height = WINDOW_TOTAL_LINES (w);
6422c1d7 7480 freeze_window_starts (f, 1);
da8b7f4f
KS
7481 grow_mini_window (w, height - WINDOW_TOTAL_LINES (w));
7482 window_height_changed_p = WINDOW_TOTAL_LINES (w) != old_height;
6422c1d7 7483 }
da8b7f4f 7484 else if (height < WINDOW_TOTAL_LINES (w)
6422c1d7
GM
7485 && (exact_p || BEGV == ZV))
7486 {
da8b7f4f 7487 int old_height = WINDOW_TOTAL_LINES (w);
6422c1d7
GM
7488 freeze_window_starts (f, 0);
7489 shrink_mini_window (w);
da8b7f4f 7490 window_height_changed_p = WINDOW_TOTAL_LINES (w) != old_height;
6422c1d7 7491 }
da448723 7492 }
2311178e 7493 else
da448723 7494 {
6422c1d7 7495 /* Always resize to exact size needed. */
da8b7f4f 7496 if (height > WINDOW_TOTAL_LINES (w))
6422c1d7 7497 {
da8b7f4f 7498 int old_height = WINDOW_TOTAL_LINES (w);
6422c1d7 7499 freeze_window_starts (f, 1);
da8b7f4f
KS
7500 grow_mini_window (w, height - WINDOW_TOTAL_LINES (w));
7501 window_height_changed_p = WINDOW_TOTAL_LINES (w) != old_height;
6422c1d7 7502 }
da8b7f4f 7503 else if (height < WINDOW_TOTAL_LINES (w))
6422c1d7 7504 {
da8b7f4f 7505 int old_height = WINDOW_TOTAL_LINES (w);
6422c1d7
GM
7506 freeze_window_starts (f, 0);
7507 shrink_mini_window (w);
7508
7509 if (height)
7510 {
7511 freeze_window_starts (f, 1);
da8b7f4f 7512 grow_mini_window (w, height - WINDOW_TOTAL_LINES (w));
6422c1d7 7513 }
2311178e 7514
da8b7f4f 7515 window_height_changed_p = WINDOW_TOTAL_LINES (w) != old_height;
6422c1d7 7516 }
9142dd5b 7517 }
1bfdbe43
GM
7518
7519 if (old_current_buffer)
7520 set_buffer_internal (old_current_buffer);
c6e89d6c
GM
7521 }
7522
7523 return window_height_changed_p;
7524}
7525
7526
7527/* Value is the current message, a string, or nil if there is no
7528 current message. */
7529
7530Lisp_Object
7531current_message ()
7532{
7533 Lisp_Object msg;
7534
7535 if (NILP (echo_area_buffer[0]))
7536 msg = Qnil;
7537 else
7538 {
23a96c77 7539 with_echo_area_buffer (0, 0, current_message_1,
23dd2d97 7540 (EMACS_INT) &msg, Qnil, 0, 0);
c6e89d6c
GM
7541 if (NILP (msg))
7542 echo_area_buffer[0] = Qnil;
7543 }
2311178e 7544
c6e89d6c
GM
7545 return msg;
7546}
7547
7548
7549static int
23a96c77 7550current_message_1 (a1, a2, a3, a4)
23dd2d97
KR
7551 EMACS_INT a1;
7552 Lisp_Object a2;
7553 EMACS_INT a3, a4;
c6e89d6c 7554{
23a96c77 7555 Lisp_Object *msg = (Lisp_Object *) a1;
2311178e 7556
c6e89d6c
GM
7557 if (Z > BEG)
7558 *msg = make_buffer_string (BEG, Z, 1);
7559 else
7560 *msg = Qnil;
7561 return 0;
7562}
7563
7564
7565/* Push the current message on Vmessage_stack for later restauration
7566 by restore_message. Value is non-zero if the current message isn't
7567 empty. This is a relatively infrequent operation, so it's not
7568 worth optimizing. */
7569
7570int
7571push_message ()
7572{
7573 Lisp_Object msg;
7574 msg = current_message ();
7575 Vmessage_stack = Fcons (msg, Vmessage_stack);
7576 return STRINGP (msg);
7577}
7578
7579
7580/* Restore message display from the top of Vmessage_stack. */
7581
7582void
7583restore_message ()
7584{
7585 Lisp_Object msg;
2311178e 7586
c6e89d6c
GM
7587 xassert (CONSP (Vmessage_stack));
7588 msg = XCAR (Vmessage_stack);
7589 if (STRINGP (msg))
d5db4077 7590 message3_nolog (msg, SBYTES (msg), STRING_MULTIBYTE (msg));
c6e89d6c
GM
7591 else
7592 message3_nolog (msg, 0, 0);
7593}
7594
7595
37d66095
RS
7596/* Handler for record_unwind_protect calling pop_message. */
7597
7598Lisp_Object
7599pop_message_unwind (dummy)
7600 Lisp_Object dummy;
7601{
7602 pop_message ();
7603 return Qnil;
7604}
7605
c6e89d6c
GM
7606/* Pop the top-most entry off Vmessage_stack. */
7607
7608void
7609pop_message ()
7610{
7611 xassert (CONSP (Vmessage_stack));
7612 Vmessage_stack = XCDR (Vmessage_stack);
7613}
7614
7615
7616/* Check that Vmessage_stack is nil. Called from emacs.c when Emacs
7617 exits. If the stack is not empty, we have a missing pop_message
7618 somewhere. */
7619
7620void
7621check_message_stack ()
7622{
7623 if (!NILP (Vmessage_stack))
7624 abort ();
7625}
7626
7627
7628/* Truncate to NCHARS what will be displayed in the echo area the next
7629 time we display it---but don't redisplay it now. */
7630
7631void
7632truncate_echo_area (nchars)
7633 int nchars;
7634{
7635 if (nchars == 0)
7636 echo_area_buffer[0] = Qnil;
7637 /* A null message buffer means that the frame hasn't really been
7638 initialized yet. Error messages get reported properly by
7639 cmd_error, so this must be just an informative message; toss it. */
7640 else if (!noninteractive
7641 && INTERACTIVE
c6e89d6c 7642 && !NILP (echo_area_buffer[0]))
886bd6f2
GM
7643 {
7644 struct frame *sf = SELECTED_FRAME ();
7645 if (FRAME_MESSAGE_BUF (sf))
23dd2d97 7646 with_echo_area_buffer (0, 0, truncate_message_1, nchars, Qnil, 0, 0);
886bd6f2 7647 }
c6e89d6c
GM
7648}
7649
7650
7651/* Helper function for truncate_echo_area. Truncate the current
7652 message to at most NCHARS characters. */
7653
7654static int
23a96c77 7655truncate_message_1 (nchars, a2, a3, a4)
23dd2d97
KR
7656 EMACS_INT nchars;
7657 Lisp_Object a2;
7658 EMACS_INT a3, a4;
c6e89d6c
GM
7659{
7660 if (BEG + nchars < Z)
7661 del_range (BEG + nchars, Z);
7662 if (Z == BEG)
7663 echo_area_buffer[0] = Qnil;
7664 return 0;
7665}
7666
7667
7668/* Set the current message to a substring of S or STRING.
7669
7670 If STRING is a Lisp string, set the message to the first NBYTES
7671 bytes from STRING. NBYTES zero means use the whole string. If
7672 STRING is multibyte, the message will be displayed multibyte.
7673
7674 If S is not null, set the message to the first LEN bytes of S. LEN
7675 zero means use the whole string. MULTIBYTE_P non-zero means S is
7676 multibyte. Display the message multibyte in that case. */
7677
7678void
7679set_message (s, string, nbytes, multibyte_p)
50f80c2f 7680 const char *s;
c6e89d6c 7681 Lisp_Object string;
e3383b6f 7682 int nbytes, multibyte_p;
c6e89d6c
GM
7683{
7684 message_enable_multibyte
7685 = ((s && multibyte_p)
7686 || (STRINGP (string) && STRING_MULTIBYTE (string)));
2311178e 7687
23a96c77
GM
7688 with_echo_area_buffer (0, -1, set_message_1,
7689 (EMACS_INT) s, string, nbytes, multibyte_p);
c6e89d6c 7690 message_buf_print = 0;
21fdfb65 7691 help_echo_showing_p = 0;
c6e89d6c
GM
7692}
7693
7694
7695/* Helper function for set_message. Arguments have the same meaning
23a96c77
GM
7696 as there, with A1 corresponding to S and A2 corresponding to STRING
7697 This function is called with the echo area buffer being
c6e89d6c
GM
7698 current. */
7699
7700static int
23a96c77 7701set_message_1 (a1, a2, nbytes, multibyte_p)
23dd2d97
KR
7702 EMACS_INT a1;
7703 Lisp_Object a2;
7704 EMACS_INT nbytes, multibyte_p;
c6e89d6c 7705{
50f80c2f 7706 const char *s = (const char *) a1;
23dd2d97 7707 Lisp_Object string = a2;
2311178e 7708
c6e89d6c 7709 xassert (BEG == Z);
2311178e 7710
c6e89d6c
GM
7711 /* Change multibyteness of the echo buffer appropriately. */
7712 if (message_enable_multibyte
7713 != !NILP (current_buffer->enable_multibyte_characters))
7714 Fset_buffer_multibyte (message_enable_multibyte ? Qt : Qnil);
7715
ad4f174e 7716 current_buffer->truncate_lines = message_truncate_lines ? Qt : Qnil;
2311178e 7717
c6e89d6c
GM
7718 /* Insert new message at BEG. */
7719 TEMP_SET_PT_BOTH (BEG, BEG_BYTE);
7720
7721 if (STRINGP (string))
7722 {
7723 int nchars;
2311178e 7724
c6e89d6c 7725 if (nbytes == 0)
2051c264 7726 nbytes = SBYTES (string);
c6e89d6c 7727 nchars = string_byte_to_char (string, nbytes);
2311178e 7728
c6e89d6c
GM
7729 /* This function takes care of single/multibyte conversion. We
7730 just have to ensure that the echo area buffer has the right
7731 setting of enable_multibyte_characters. */
7732 insert_from_string (string, 0, 0, nchars, nbytes, 1);
7733 }
7734 else if (s)
7735 {
7736 if (nbytes == 0)
7737 nbytes = strlen (s);
2311178e 7738
c6e89d6c
GM
7739 if (multibyte_p && NILP (current_buffer->enable_multibyte_characters))
7740 {
7741 /* Convert from multi-byte to single-byte. */
7742 int i, c, n;
7743 unsigned char work[1];
2311178e 7744
c6e89d6c
GM
7745 /* Convert a multibyte string to single-byte. */
7746 for (i = 0; i < nbytes; i += n)
7747 {
7748 c = string_char_and_length (s + i, nbytes - i, &n);
522b161c 7749 work[0] = (ASCII_CHAR_P (c)
c6e89d6c
GM
7750 ? c
7751 : multibyte_char_to_unibyte (c, Qnil));
7752 insert_1_both (work, 1, 1, 1, 0, 0);
7753 }
7754 }
7755 else if (!multibyte_p
7756 && !NILP (current_buffer->enable_multibyte_characters))
7757 {
7758 /* Convert from single-byte to multi-byte. */
7759 int i, c, n;
50f80c2f 7760 const unsigned char *msg = (const unsigned char *) s;
260a86a0 7761 unsigned char str[MAX_MULTIBYTE_LENGTH];
2311178e 7762
c6e89d6c
GM
7763 /* Convert a single-byte string to multibyte. */
7764 for (i = 0; i < nbytes; i++)
7765 {
7766 c = unibyte_char_to_multibyte (msg[i]);
260a86a0
KH
7767 n = CHAR_STRING (c, str);
7768 insert_1_both (str, 1, n, 1, 0, 0);
c6e89d6c
GM
7769 }
7770 }
7771 else
7772 insert_1 (s, nbytes, 1, 0, 0);
7773 }
7774
7775 return 0;
7776}
7777
7778
7779/* Clear messages. CURRENT_P non-zero means clear the current
7780 message. LAST_DISPLAYED_P non-zero means clear the message
7781 last displayed. */
7782
7783void
7784clear_message (current_p, last_displayed_p)
7785 int current_p, last_displayed_p;
7786{
7787 if (current_p)
6e019995
GM
7788 {
7789 echo_area_buffer[0] = Qnil;
7790 message_cleared_p = 1;
7791 }
2311178e 7792
c6e89d6c
GM
7793 if (last_displayed_p)
7794 echo_area_buffer[1] = Qnil;
2311178e 7795
c6e89d6c
GM
7796 message_buf_print = 0;
7797}
7798
7799/* Clear garbaged frames.
7800
7801 This function is used where the old redisplay called
7802 redraw_garbaged_frames which in turn called redraw_frame which in
7803 turn called clear_frame. The call to clear_frame was a source of
7804 flickering. I believe a clear_frame is not necessary. It should
7805 suffice in the new redisplay to invalidate all current matrices,
7806 and ensure a complete redisplay of all windows. */
7807
7808static void
7809clear_garbaged_frames ()
7810{
5f5c8ee5
GM
7811 if (frame_garbaged)
7812 {
5f5c8ee5 7813 Lisp_Object tail, frame;
5fb96e96 7814 int changed_count = 0;
2311178e 7815
5f5c8ee5
GM
7816 FOR_EACH_FRAME (tail, frame)
7817 {
7818 struct frame *f = XFRAME (frame);
2311178e 7819
5f5c8ee5
GM
7820 if (FRAME_VISIBLE_P (f) && FRAME_GARBAGED_P (f))
7821 {
6bb95882 7822 if (f->resized_p)
6b61353c
KH
7823 {
7824 Fredraw_frame (frame);
7825 f->force_flush_display_p = 1;
7826 }
5f5c8ee5 7827 clear_current_matrices (f);
5fb96e96 7828 changed_count++;
5f5c8ee5 7829 f->garbaged = 0;
6bb95882 7830 f->resized_p = 0;
5f5c8ee5
GM
7831 }
7832 }
7833
7834 frame_garbaged = 0;
5fb96e96
RS
7835 if (changed_count)
7836 ++windows_or_buffers_changed;
5f5c8ee5 7837 }
c6e89d6c 7838}
5f5c8ee5 7839
5f5c8ee5 7840
886bd6f2
GM
7841/* Redisplay the echo area of the selected frame. If UPDATE_FRAME_P
7842 is non-zero update selected_frame. Value is non-zero if the
c6e89d6c 7843 mini-windows height has been changed. */
5f5c8ee5 7844
c6e89d6c
GM
7845static int
7846echo_area_display (update_frame_p)
7847 int update_frame_p;
7848{
7849 Lisp_Object mini_window;
7850 struct window *w;
7851 struct frame *f;
7852 int window_height_changed_p = 0;
886bd6f2 7853 struct frame *sf = SELECTED_FRAME ();
c6e89d6c 7854
886bd6f2 7855 mini_window = FRAME_MINIBUF_WINDOW (sf);
c6e89d6c
GM
7856 w = XWINDOW (mini_window);
7857 f = XFRAME (WINDOW_FRAME (w));
7858
7859 /* Don't display if frame is invisible or not yet initialized. */
7860 if (!FRAME_VISIBLE_P (f) || !f->glyphs_initialized_p)
7861 return 0;
5f5c8ee5 7862
1a578e9b 7863/* The terminal frame is used as the first Emacs frame on the Mac OS. */
e0f712ba 7864#ifndef MAC_OS8
1ab3e082 7865#ifdef HAVE_WINDOW_SYSTEM
c6e89d6c
GM
7866 /* When Emacs starts, selected_frame may be a visible terminal
7867 frame, even if we run under a window system. If we let this
7868 through, a message would be displayed on the terminal. */
2311178e 7869 if (EQ (selected_frame, Vterminal_frame)
622e3754 7870 && !NILP (Vwindow_system))
c6e89d6c 7871 return 0;
1ab3e082 7872#endif /* HAVE_WINDOW_SYSTEM */
1a578e9b 7873#endif
c6e89d6c
GM
7874
7875 /* Redraw garbaged frames. */
7876 if (frame_garbaged)
7877 clear_garbaged_frames ();
7878
7879 if (!NILP (echo_area_buffer[0]) || minibuf_level == 0)
7880 {
7881 echo_area_window = mini_window;
7882 window_height_changed_p = display_echo_area (w);
5f5c8ee5 7883 w->must_be_updated_p = 1;
c59c668a 7884
d4358b37
GM
7885 /* Update the display, unless called from redisplay_internal.
7886 Also don't update the screen during redisplay itself. The
7887 update will happen at the end of redisplay, and an update
7888 here could cause confusion. */
7889 if (update_frame_p && !redisplaying_p)
5f5c8ee5 7890 {
715e84c9 7891 int n = 0;
edc68111 7892
715e84c9
GM
7893 /* If the display update has been interrupted by pending
7894 input, update mode lines in the frame. Due to the
7895 pending input, it might have been that redisplay hasn't
7896 been called, so that mode lines above the echo area are
7897 garbaged. This looks odd, so we prevent it here. */
7898 if (!display_completed)
7899 n = redisplay_mode_lines (FRAME_ROOT_WINDOW (f), 0);
2311178e 7900
8af1308e
GM
7901 if (window_height_changed_p
7902 /* Don't do this if Emacs is shutting down. Redisplay
7903 needs to run hooks. */
7904 && !NILP (Vrun_hooks))
c59c668a 7905 {
c06017fb
GM
7906 /* Must update other windows. Likewise as in other
7907 cases, don't let this update be interrupted by
7908 pending input. */
331379bf 7909 int count = SPECPDL_INDEX ();
c06017fb 7910 specbind (Qredisplay_dont_pause, Qt);
edc68111 7911 windows_or_buffers_changed = 1;
c59c668a 7912 redisplay_internal (0);
c06017fb 7913 unbind_to (count, Qnil);
c59c668a 7914 }
715e84c9 7915 else if (FRAME_WINDOW_P (f) && n == 0)
5f5c8ee5 7916 {
edc68111 7917 /* Window configuration is the same as before.
715e84c9
GM
7918 Can do with a display update of the echo area,
7919 unless we displayed some mode lines. */
5f5c8ee5
GM
7920 update_single_window (w, 1);
7921 rif->flush_display (f);
7922 }
7923 else
7924 update_frame (f, 1, 1);
31b6671b
GM
7925
7926 /* If cursor is in the echo area, make sure that the next
7927 redisplay displays the minibuffer, so that the cursor will
7928 be replaced with what the minibuffer wants. */
7929 if (cursor_in_echo_area)
7930 ++windows_or_buffers_changed;
5f5c8ee5
GM
7931 }
7932 }
7933 else if (!EQ (mini_window, selected_window))
7934 windows_or_buffers_changed++;
c59c668a
GM
7935
7936 /* Last displayed message is now the current message. */
dd2eb166 7937 echo_area_buffer[1] = echo_area_buffer[0];
2311178e 7938
5f5c8ee5
GM
7939 /* Prevent redisplay optimization in redisplay_internal by resetting
7940 this_line_start_pos. This is done because the mini-buffer now
7941 displays the message instead of its buffer text. */
7942 if (EQ (mini_window, selected_window))
7943 CHARPOS (this_line_start_pos) = 0;
c6e89d6c
GM
7944
7945 return window_height_changed_p;
5f5c8ee5
GM
7946}
7947
7948
7949\f
7950/***********************************************************************
7951 Frame Titles
7952 ***********************************************************************/
7953
7954
8143e6ab
KS
7955/* The frame title buffering code is also used by Fformat_mode_line.
7956 So it is not conditioned by HAVE_WINDOW_SYSTEM. */
5f5c8ee5
GM
7957
7958/* A buffer for constructing frame titles in it; allocated from the
7959 heap in init_xdisp and resized as needed in store_frame_title_char. */
7960
7961static char *frame_title_buf;
7962
7963/* The buffer's end, and a current output position in it. */
7964
7965static char *frame_title_buf_end;
7966static char *frame_title_ptr;
7967
7968
7969/* Store a single character C for the frame title in frame_title_buf.
7970 Re-allocate frame_title_buf if necessary. */
7971
7972static void
5d15cc8f
DL
7973#ifdef PROTOTYPES
7974store_frame_title_char (char c)
7975#else
5f5c8ee5
GM
7976store_frame_title_char (c)
7977 char c;
5d15cc8f 7978#endif
5f5c8ee5
GM
7979{
7980 /* If output position has reached the end of the allocated buffer,
7981 double the buffer's size. */
7982 if (frame_title_ptr == frame_title_buf_end)
7983 {
7984 int len = frame_title_ptr - frame_title_buf;
7985 int new_size = 2 * len * sizeof *frame_title_buf;
7986 frame_title_buf = (char *) xrealloc (frame_title_buf, new_size);
7987 frame_title_buf_end = frame_title_buf + new_size;
7988 frame_title_ptr = frame_title_buf + len;
7989 }
7990
7991 *frame_title_ptr++ = c;
7992}
7993
7994
7995/* Store part of a frame title in frame_title_buf, beginning at
d26b89b8
KH
7996 frame_title_ptr. STR is the string to store. Do not copy
7997 characters that yield more columns than PRECISION; PRECISION <= 0
7998 means copy the whole string. Pad with spaces until FIELD_WIDTH
7999 number of characters have been copied; FIELD_WIDTH <= 0 means don't
8000 pad. Called from display_mode_element when it is used to build a
8001 frame title. */
5f5c8ee5
GM
8002
8003static int
8004store_frame_title (str, field_width, precision)
50f80c2f 8005 const unsigned char *str;
5f5c8ee5
GM
8006 int field_width, precision;
8007{
8008 int n = 0;
3b552d56 8009 int dummy, nbytes;
5f5c8ee5
GM
8010
8011 /* Copy at most PRECISION chars from STR. */
d26b89b8
KH
8012 nbytes = strlen (str);
8013 n+= c_string_width (str, nbytes, precision, &dummy, &nbytes);
8014 while (nbytes--)
8015 store_frame_title_char (*str++);
5f5c8ee5
GM
8016
8017 /* Fill up with spaces until FIELD_WIDTH reached. */
8018 while (field_width > 0
8019 && n < field_width)
8020 {
8021 store_frame_title_char (' ');
8022 ++n;
8023 }
8024
8025 return n;
8026}
8027
8143e6ab 8028#ifdef HAVE_WINDOW_SYSTEM
5f5c8ee5
GM
8029
8030/* Set the title of FRAME, if it has changed. The title format is
8031 Vicon_title_format if FRAME is iconified, otherwise it is
8032 frame_title_format. */
8033
8034static void
8035x_consider_frame_title (frame)
8036 Lisp_Object frame;
8037{
8038 struct frame *f = XFRAME (frame);
8039
8040 if (FRAME_WINDOW_P (f)
8041 || FRAME_MINIBUF_ONLY_P (f)
8042 || f->explicit_name)
8043 {
8044 /* Do we have more than one visible frame on this X display? */
8045 Lisp_Object tail;
8046 Lisp_Object fmt;
8047 struct buffer *obuf;
8048 int len;
8049 struct it it;
8050
9472f927 8051 for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
5f5c8ee5 8052 {
74779f52
JR
8053 Lisp_Object other_frame = XCAR (tail);
8054 struct frame *tf = XFRAME (other_frame);
5f5c8ee5 8055
2311178e 8056 if (tf != f
5f5c8ee5
GM
8057 && FRAME_KBOARD (tf) == FRAME_KBOARD (f)
8058 && !FRAME_MINIBUF_ONLY_P (tf)
74779f52 8059 && !EQ (other_frame, tip_frame)
5f5c8ee5
GM
8060 && (FRAME_VISIBLE_P (tf) || FRAME_ICONIFIED_P (tf)))
8061 break;
8062 }
8063
8064 /* Set global variable indicating that multiple frames exist. */
8065 multiple_frames = CONSP (tail);
8066
8067 /* Switch to the buffer of selected window of the frame. Set up
8068 frame_title_ptr so that display_mode_element will output into it;
8069 then display the title. */
8070 obuf = current_buffer;
bb336f8d 8071 set_buffer_internal_1 (XBUFFER (XWINDOW (f->selected_window)->buffer));
5f5c8ee5
GM
8072 fmt = FRAME_ICONIFIED_P (f) ? Vicon_title_format : Vframe_title_format;
8073 frame_title_ptr = frame_title_buf;
8074 init_iterator (&it, XWINDOW (f->selected_window), -1, -1,
8075 NULL, DEFAULT_FACE_ID);
c53a1624 8076 display_mode_element (&it, 0, -1, -1, fmt, Qnil, 0);
d26b89b8 8077 len = frame_title_ptr - frame_title_buf;
5f5c8ee5 8078 frame_title_ptr = NULL;
bb336f8d 8079 set_buffer_internal_1 (obuf);
5f5c8ee5
GM
8080
8081 /* Set the title only if it's changed. This avoids consing in
8082 the common case where it hasn't. (If it turns out that we've
8083 already wasted too much time by walking through the list with
8084 display_mode_element, then we might need to optimize at a
8085 higher level than this.) */
2311178e 8086 if (! STRINGP (f->name)
2051c264
GM
8087 || SBYTES (f->name) != len
8088 || bcmp (frame_title_buf, SDATA (f->name), len) != 0)
5f5c8ee5
GM
8089 x_implicitly_set_name (f, make_string (frame_title_buf, len), Qnil);
8090 }
8091}
8092
5f5c8ee5
GM
8093#endif /* not HAVE_WINDOW_SYSTEM */
8094
8095
8096
8097\f
8098/***********************************************************************
8099 Menu Bars
8100 ***********************************************************************/
8101
8102
8103/* Prepare for redisplay by updating menu-bar item lists when
8104 appropriate. This can call eval. */
8105
8106void
8107prepare_menu_bars ()
8108{
8109 int all_windows;
8110 struct gcpro gcpro1, gcpro2;
8111 struct frame *f;
6b5c4794 8112 Lisp_Object tooltip_frame;
5f5c8ee5 8113
86ffe5cd 8114#ifdef HAVE_WINDOW_SYSTEM
5f5c8ee5
GM
8115 tooltip_frame = tip_frame;
8116#else
6b5c4794 8117 tooltip_frame = Qnil;
5f5c8ee5
GM
8118#endif
8119
8120 /* Update all frame titles based on their buffer names, etc. We do
8121 this before the menu bars so that the buffer-menu will show the
8122 up-to-date frame titles. */
8123#ifdef HAVE_WINDOW_SYSTEM
8124 if (windows_or_buffers_changed || update_mode_lines)
8125 {
8126 Lisp_Object tail, frame;
8127
8128 FOR_EACH_FRAME (tail, frame)
8129 {
8130 f = XFRAME (frame);
6b5c4794 8131 if (!EQ (frame, tooltip_frame)
5f5c8ee5
GM
8132 && (FRAME_VISIBLE_P (f) || FRAME_ICONIFIED_P (f)))
8133 x_consider_frame_title (frame);
8134 }
8135 }
8136#endif /* HAVE_WINDOW_SYSTEM */
8137
8138 /* Update the menu bar item lists, if appropriate. This has to be
8139 done before any actual redisplay or generation of display lines. */
2311178e 8140 all_windows = (update_mode_lines
5f5c8ee5
GM
8141 || buffer_shared > 1
8142 || windows_or_buffers_changed);
8143 if (all_windows)
8144 {
8145 Lisp_Object tail, frame;
331379bf 8146 int count = SPECPDL_INDEX ();
5f5c8ee5
GM
8147
8148 record_unwind_protect (Fset_match_data, Fmatch_data (Qnil, Qnil));
8149
8150 FOR_EACH_FRAME (tail, frame)
8151 {
8152 f = XFRAME (frame);
8153
8154 /* Ignore tooltip frame. */
6b5c4794 8155 if (EQ (frame, tooltip_frame))
5f5c8ee5 8156 continue;
2311178e 8157
5f5c8ee5
GM
8158 /* If a window on this frame changed size, report that to
8159 the user and clear the size-change flag. */
8160 if (FRAME_WINDOW_SIZES_CHANGED (f))
8161 {
8162 Lisp_Object functions;
2311178e 8163
5f5c8ee5
GM
8164 /* Clear flag first in case we get an error below. */
8165 FRAME_WINDOW_SIZES_CHANGED (f) = 0;
8166 functions = Vwindow_size_change_functions;
8167 GCPRO2 (tail, functions);
2311178e 8168
5f5c8ee5
GM
8169 while (CONSP (functions))
8170 {
8171 call1 (XCAR (functions), frame);
8172 functions = XCDR (functions);
8173 }
8174 UNGCPRO;
8175 }
2311178e 8176
5f5c8ee5
GM
8177 GCPRO1 (tail);
8178 update_menu_bar (f, 0);
8179#ifdef HAVE_WINDOW_SYSTEM
e037b9ec 8180 update_tool_bar (f, 0);
5f5c8ee5
GM
8181#endif
8182 UNGCPRO;
8183 }
8184
8185 unbind_to (count, Qnil);
8186 }
8187 else
8188 {
886bd6f2
GM
8189 struct frame *sf = SELECTED_FRAME ();
8190 update_menu_bar (sf, 1);
5f5c8ee5 8191#ifdef HAVE_WINDOW_SYSTEM
886bd6f2 8192 update_tool_bar (sf, 1);
5f5c8ee5
GM
8193#endif
8194 }
8195
8196 /* Motif needs this. See comment in xmenu.c. Turn it off when
8197 pending_menu_activation is not defined. */
8198#ifdef USE_X_TOOLKIT
8199 pending_menu_activation = 0;
8200#endif
8201}
8202
8203
8204/* Update the menu bar item list for frame F. This has to be done
8205 before we start to fill in any display lines, because it can call
8206 eval.
8207
8208 If SAVE_MATCH_DATA is non-zero, we must save and restore it here. */
8209
8210static void
8211update_menu_bar (f, save_match_data)
8212 struct frame *f;
8213 int save_match_data;
8214{
8215 Lisp_Object window;
8216 register struct window *w;
8217
e1477f43
GM
8218 /* If called recursively during a menu update, do nothing. This can
8219 happen when, for instance, an activate-menubar-hook causes a
8220 redisplay. */
8221 if (inhibit_menubar_update)
8222 return;
8223
5f5c8ee5
GM
8224 window = FRAME_SELECTED_WINDOW (f);
8225 w = XWINDOW (window);
2311178e 8226
84f2e615 8227#if 0 /* The if statement below this if statement used to include the
a5f08374
RS
8228 condition !NILP (w->update_mode_line), rather than using
8229 update_mode_lines directly, and this if statement may have
8230 been added to make that condition work. Now the if
2311178e 8231 statement below matches its comment, this isn't needed. */
5f5c8ee5
GM
8232 if (update_mode_lines)
8233 w->update_mode_line = Qt;
a5f08374 8234#endif
5f5c8ee5
GM
8235
8236 if (FRAME_WINDOW_P (f)
8237 ?
488dd4c4
JD
8238#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (MAC_OS) \
8239 || defined (USE_GTK)
2311178e 8240 FRAME_EXTERNAL_MENU_BAR (f)
5f5c8ee5
GM
8241#else
8242 FRAME_MENU_BAR_LINES (f) > 0
8243#endif
8244 : FRAME_MENU_BAR_LINES (f) > 0)
8245 {
8246 /* If the user has switched buffers or windows, we need to
8247 recompute to reflect the new bindings. But we'll
8248 recompute when update_mode_lines is set too; that means
8249 that people can use force-mode-line-update to request
8250 that the menu bar be recomputed. The adverse effect on
8251 the rest of the redisplay algorithm is about the same as
8252 windows_or_buffers_changed anyway. */
8253 if (windows_or_buffers_changed
a5f08374
RS
8254 /* This used to test w->update_mode_line, but we believe
8255 there is no need to recompute the menu in that case. */
8256 || update_mode_lines
5f5c8ee5
GM
8257 || ((BUF_SAVE_MODIFF (XBUFFER (w->buffer))
8258 < BUF_MODIFF (XBUFFER (w->buffer)))
8259 != !NILP (w->last_had_star))
8260 || ((!NILP (Vtransient_mark_mode)
8261 && !NILP (XBUFFER (w->buffer)->mark_active))
8262 != !NILP (w->region_showing)))
8263 {
8264 struct buffer *prev = current_buffer;
331379bf 8265 int count = SPECPDL_INDEX ();
5f5c8ee5 8266
e1477f43
GM
8267 specbind (Qinhibit_menubar_update, Qt);
8268
5f5c8ee5
GM
8269 set_buffer_internal_1 (XBUFFER (w->buffer));
8270 if (save_match_data)
8271 record_unwind_protect (Fset_match_data, Fmatch_data (Qnil, Qnil));
8272 if (NILP (Voverriding_local_map_menu_flag))
8273 {
8274 specbind (Qoverriding_terminal_local_map, Qnil);
8275 specbind (Qoverriding_local_map, Qnil);
8276 }
8277
8278 /* Run the Lucid hook. */
65048e97 8279 safe_run_hooks (Qactivate_menubar_hook);
2311178e 8280
5f5c8ee5
GM
8281 /* If it has changed current-menubar from previous value,
8282 really recompute the menu-bar from the value. */
8283 if (! NILP (Vlucid_menu_bar_dirty_flag))
8284 call0 (Qrecompute_lucid_menubar);
2311178e 8285
5f5c8ee5
GM
8286 safe_run_hooks (Qmenu_bar_update_hook);
8287 FRAME_MENU_BAR_ITEMS (f) = menu_bar_items (FRAME_MENU_BAR_ITEMS (f));
2311178e 8288
5f5c8ee5 8289 /* Redisplay the menu bar in case we changed it. */
488dd4c4
JD
8290#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (MAC_OS) \
8291 || defined (USE_GTK)
1a578e9b 8292 if (FRAME_WINDOW_P (f)
e0f712ba 8293#if defined (MAC_OS)
1a578e9b
AC
8294 /* All frames on Mac OS share the same menubar. So only the
8295 selected frame should be allowed to set it. */
8296 && f == SELECTED_FRAME ()
8297#endif
8298 )
5f5c8ee5
GM
8299 set_frame_menubar (f, 0, 0);
8300 else
8301 /* On a terminal screen, the menu bar is an ordinary screen
8302 line, and this makes it get updated. */
8303 w->update_mode_line = Qt;
488dd4c4 8304#else /* ! (USE_X_TOOLKIT || HAVE_NTGUI || MAC_OS || USE_GTK) */
5f5c8ee5
GM
8305 /* In the non-toolkit version, the menu bar is an ordinary screen
8306 line, and this makes it get updated. */
8307 w->update_mode_line = Qt;
488dd4c4 8308#endif /* ! (USE_X_TOOLKIT || HAVE_NTGUI || MAC_OS || USE_GTK) */
5f5c8ee5
GM
8309
8310 unbind_to (count, Qnil);
8311 set_buffer_internal_1 (prev);
8312 }
8313 }
8314}
8315
8316
8317\f
fa3c6b4d
KS
8318/***********************************************************************
8319 Output Cursor
8320 ***********************************************************************/
8321
1dabd0cf
KS
8322#ifdef HAVE_WINDOW_SYSTEM
8323
fa3c6b4d
KS
8324/* EXPORT:
8325 Nominal cursor position -- where to draw output.
8326 HPOS and VPOS are window relative glyph matrix coordinates.
8327 X and Y are window relative pixel coordinates. */
8328
8329struct cursor_pos output_cursor;
8330
8331
8332/* EXPORT:
8333 Set the global variable output_cursor to CURSOR. All cursor
8334 positions are relative to updated_window. */
8335
8336void
8337set_output_cursor (cursor)
8338 struct cursor_pos *cursor;
8339{
8340 output_cursor.hpos = cursor->hpos;
8341 output_cursor.vpos = cursor->vpos;
8342 output_cursor.x = cursor->x;
8343 output_cursor.y = cursor->y;
8344}
8345
8346
8347/* EXPORT for RIF:
8348 Set a nominal cursor position.
8349
8350 HPOS and VPOS are column/row positions in a window glyph matrix. X
8351 and Y are window text area relative pixel positions.
8352
8353 If this is done during an update, updated_window will contain the
8354 window that is being updated and the position is the future output
8355 cursor position for that window. If updated_window is null, use
8356 selected_window and display the cursor at the given position. */
8357
8358void
8359x_cursor_to (vpos, hpos, y, x)
8360 int vpos, hpos, y, x;
8361{
8362 struct window *w;
8363
8364 /* If updated_window is not set, work on selected_window. */
8365 if (updated_window)
8366 w = updated_window;
8367 else
8368 w = XWINDOW (selected_window);
8369
8370 /* Set the output cursor. */
8371 output_cursor.hpos = hpos;
8372 output_cursor.vpos = vpos;
8373 output_cursor.x = x;
8374 output_cursor.y = y;
8375
8376 /* If not called as part of an update, really display the cursor.
8377 This will also set the cursor position of W. */
8378 if (updated_window == NULL)
8379 {
8380 BLOCK_INPUT;
8381 display_and_set_cursor (w, 1, hpos, vpos, x, y);
8382 if (rif->flush_display_optional)
8383 rif->flush_display_optional (SELECTED_FRAME ());
8384 UNBLOCK_INPUT;
8385 }
8386}
8387
1dabd0cf 8388#endif /* HAVE_WINDOW_SYSTEM */
fa3c6b4d
KS
8389
8390\f
5f5c8ee5 8391/***********************************************************************
e037b9ec 8392 Tool-bars
5f5c8ee5
GM
8393 ***********************************************************************/
8394
8395#ifdef HAVE_WINDOW_SYSTEM
8396
fa3c6b4d
KS
8397/* Where the mouse was last time we reported a mouse event. */
8398
8399FRAME_PTR last_mouse_frame;
8400
8401/* Tool-bar item index of the item on which a mouse button was pressed
8402 or -1. */
8403
8404int last_tool_bar_item;
8405
8406
e037b9ec 8407/* Update the tool-bar item list for frame F. This has to be done
5f5c8ee5
GM
8408 before we start to fill in any display lines. Called from
8409 prepare_menu_bars. If SAVE_MATCH_DATA is non-zero, we must save
8410 and restore it here. */
8411
8412static void
e037b9ec 8413update_tool_bar (f, save_match_data)
5f5c8ee5
GM
8414 struct frame *f;
8415 int save_match_data;
8416{
488dd4c4 8417#ifdef USE_GTK
6b61353c 8418 int do_update = FRAME_EXTERNAL_TOOL_BAR (f);
488dd4c4
JD
8419#else
8420 int do_update = WINDOWP (f->tool_bar_window)
da8b7f4f 8421 && WINDOW_TOTAL_LINES (XWINDOW (f->tool_bar_window)) > 0;
488dd4c4
JD
8422#endif
8423
8424 if (do_update)
5f5c8ee5
GM
8425 {
8426 Lisp_Object window;
8427 struct window *w;
8428
8429 window = FRAME_SELECTED_WINDOW (f);
8430 w = XWINDOW (window);
2311178e 8431
5f5c8ee5
GM
8432 /* If the user has switched buffers or windows, we need to
8433 recompute to reflect the new bindings. But we'll
8434 recompute when update_mode_lines is set too; that means
8435 that people can use force-mode-line-update to request
8436 that the menu bar be recomputed. The adverse effect on
8437 the rest of the redisplay algorithm is about the same as
8438 windows_or_buffers_changed anyway. */
8439 if (windows_or_buffers_changed
8440 || !NILP (w->update_mode_line)
84f2e615 8441 || update_mode_lines
5f5c8ee5
GM
8442 || ((BUF_SAVE_MODIFF (XBUFFER (w->buffer))
8443 < BUF_MODIFF (XBUFFER (w->buffer)))
8444 != !NILP (w->last_had_star))
8445 || ((!NILP (Vtransient_mark_mode)
8446 && !NILP (XBUFFER (w->buffer)->mark_active))
8447 != !NILP (w->region_showing)))
8448 {
8449 struct buffer *prev = current_buffer;
331379bf 8450 int count = SPECPDL_INDEX ();
84f2e615
RS
8451 Lisp_Object old_tool_bar;
8452 struct gcpro gcpro1;
a2889657 8453
5f5c8ee5
GM
8454 /* Set current_buffer to the buffer of the selected
8455 window of the frame, so that we get the right local
8456 keymaps. */
8457 set_buffer_internal_1 (XBUFFER (w->buffer));
1f40cad2 8458
5f5c8ee5
GM
8459 /* Save match data, if we must. */
8460 if (save_match_data)
8461 record_unwind_protect (Fset_match_data, Fmatch_data (Qnil, Qnil));
8462
8463 /* Make sure that we don't accidentally use bogus keymaps. */
8464 if (NILP (Voverriding_local_map_menu_flag))
8465 {
8466 specbind (Qoverriding_terminal_local_map, Qnil);
8467 specbind (Qoverriding_local_map, Qnil);
1f40cad2 8468 }
1f40cad2 8469
84f2e615
RS
8470 old_tool_bar = f->tool_bar_items;
8471 GCPRO1 (old_tool_bar);
8472
e037b9ec 8473 /* Build desired tool-bar items from keymaps. */
e3b2c21f 8474 BLOCK_INPUT;
7464726e
GM
8475 f->tool_bar_items
8476 = tool_bar_items (f->tool_bar_items, &f->n_tool_bar_items);
e3b2c21f 8477 UNBLOCK_INPUT;
2311178e 8478
84f2e615
RS
8479 /* Redisplay the tool-bar if we changed it. */
8480 if (! NILP (Fequal (old_tool_bar, f->tool_bar_items)))
8481 w->update_mode_line = Qt;
6b61353c 8482
1e802fb5 8483 UNGCPRO;
5f5c8ee5
GM
8484
8485 unbind_to (count, Qnil);
8486 set_buffer_internal_1 (prev);
81d478f3 8487 }
a2889657
JB
8488 }
8489}
8490
6c4429a5 8491
e037b9ec 8492/* Set F->desired_tool_bar_string to a Lisp string representing frame
7464726e 8493 F's desired tool-bar contents. F->tool_bar_items must have
5f5c8ee5
GM
8494 been set up previously by calling prepare_menu_bars. */
8495
a2889657 8496static void
e037b9ec 8497build_desired_tool_bar_string (f)
5f5c8ee5 8498 struct frame *f;
a2889657 8499{
a23887b9 8500 int i, size, size_needed;
5f5c8ee5
GM
8501 struct gcpro gcpro1, gcpro2, gcpro3;
8502 Lisp_Object image, plist, props;
a2889657 8503
5f5c8ee5
GM
8504 image = plist = props = Qnil;
8505 GCPRO3 (image, plist, props);
a2889657 8506
e037b9ec 8507 /* Prepare F->desired_tool_bar_string. If we can reuse it, do so.
5f5c8ee5 8508 Otherwise, make a new string. */
2311178e 8509
5f5c8ee5 8510 /* The size of the string we might be able to reuse. */
e037b9ec 8511 size = (STRINGP (f->desired_tool_bar_string)
2051c264 8512 ? SCHARS (f->desired_tool_bar_string)
5f5c8ee5
GM
8513 : 0);
8514
b94c0d9c 8515 /* We need one space in the string for each image. */
a23887b9 8516 size_needed = f->n_tool_bar_items;
2311178e 8517
b94c0d9c 8518 /* Reuse f->desired_tool_bar_string, if possible. */
cb2ddc53 8519 if (size < size_needed || NILP (f->desired_tool_bar_string))
6fc556fd
KR
8520 f->desired_tool_bar_string = Fmake_string (make_number (size_needed),
8521 make_number (' '));
5f5c8ee5
GM
8522 else
8523 {
8524 props = list4 (Qdisplay, Qnil, Qmenu_item, Qnil);
8525 Fremove_text_properties (make_number (0), make_number (size),
e037b9ec 8526 props, f->desired_tool_bar_string);
5f5c8ee5 8527 }
a2889657 8528
5f5c8ee5 8529 /* Put a `display' property on the string for the images to display,
e037b9ec
GM
8530 put a `menu_item' property on tool-bar items with a value that
8531 is the index of the item in F's tool-bar item vector. */
a23887b9 8532 for (i = 0; i < f->n_tool_bar_items; ++i)
a2889657 8533 {
7464726e 8534#define PROP(IDX) AREF (f->tool_bar_items, i * TOOL_BAR_ITEM_NSLOTS + (IDX))
5f5c8ee5 8535
e037b9ec
GM
8536 int enabled_p = !NILP (PROP (TOOL_BAR_ITEM_ENABLED_P));
8537 int selected_p = !NILP (PROP (TOOL_BAR_ITEM_SELECTED_P));
35a41507 8538 int hmargin, vmargin, relief, idx, end;
6b61353c 8539 extern Lisp_Object QCrelief, QCmargin, QCconversion;
5f5c8ee5
GM
8540
8541 /* If image is a vector, choose the image according to the
8542 button state. */
e037b9ec 8543 image = PROP (TOOL_BAR_ITEM_IMAGES);
5f5c8ee5
GM
8544 if (VECTORP (image))
8545 {
5f5c8ee5
GM
8546 if (enabled_p)
8547 idx = (selected_p
e037b9ec
GM
8548 ? TOOL_BAR_IMAGE_ENABLED_SELECTED
8549 : TOOL_BAR_IMAGE_ENABLED_DESELECTED);
5f5c8ee5
GM
8550 else
8551 idx = (selected_p
e037b9ec
GM
8552 ? TOOL_BAR_IMAGE_DISABLED_SELECTED
8553 : TOOL_BAR_IMAGE_DISABLED_DESELECTED);
2311178e 8554
37e4e482
GM
8555 xassert (ASIZE (image) >= idx);
8556 image = AREF (image, idx);
5f5c8ee5 8557 }
37e4e482
GM
8558 else
8559 idx = -1;
5f5c8ee5
GM
8560
8561 /* Ignore invalid image specifications. */
8562 if (!valid_image_p (image))
8563 continue;
8564
e037b9ec 8565 /* Display the tool-bar button pressed, or depressed. */
5f5c8ee5
GM
8566 plist = Fcopy_sequence (XCDR (image));
8567
8568 /* Compute margin and relief to draw. */
9f864bf9 8569 relief = (tool_bar_button_relief >= 0
c3d76173
GM
8570 ? tool_bar_button_relief
8571 : DEFAULT_TOOL_BAR_BUTTON_RELIEF);
35a41507
GM
8572 hmargin = vmargin = relief;
8573
8574 if (INTEGERP (Vtool_bar_button_margin)
8575 && XINT (Vtool_bar_button_margin) > 0)
8576 {
8577 hmargin += XFASTINT (Vtool_bar_button_margin);
8578 vmargin += XFASTINT (Vtool_bar_button_margin);
8579 }
8580 else if (CONSP (Vtool_bar_button_margin))
8581 {
8582 if (INTEGERP (XCAR (Vtool_bar_button_margin))
8583 && XINT (XCAR (Vtool_bar_button_margin)) > 0)
8584 hmargin += XFASTINT (XCAR (Vtool_bar_button_margin));
2311178e 8585
35a41507
GM
8586 if (INTEGERP (XCDR (Vtool_bar_button_margin))
8587 && XINT (XCDR (Vtool_bar_button_margin)) > 0)
8588 vmargin += XFASTINT (XCDR (Vtool_bar_button_margin));
8589 }
2311178e 8590
e037b9ec 8591 if (auto_raise_tool_bar_buttons_p)
5f5c8ee5
GM
8592 {
8593 /* Add a `:relief' property to the image spec if the item is
8594 selected. */
8595 if (selected_p)
8596 {
8597 plist = Fplist_put (plist, QCrelief, make_number (-relief));
35a41507
GM
8598 hmargin -= relief;
8599 vmargin -= relief;
5f5c8ee5
GM
8600 }
8601 }
8602 else
8603 {
8604 /* If image is selected, display it pressed, i.e. with a
8605 negative relief. If it's not selected, display it with a
8606 raised relief. */
8607 plist = Fplist_put (plist, QCrelief,
8608 (selected_p
8609 ? make_number (-relief)
8610 : make_number (relief)));
35a41507
GM
8611 hmargin -= relief;
8612 vmargin -= relief;
5f5c8ee5
GM
8613 }
8614
8615 /* Put a margin around the image. */
35a41507
GM
8616 if (hmargin || vmargin)
8617 {
8618 if (hmargin == vmargin)
8619 plist = Fplist_put (plist, QCmargin, make_number (hmargin));
8620 else
8621 plist = Fplist_put (plist, QCmargin,
8622 Fcons (make_number (hmargin),
8623 make_number (vmargin)));
8624 }
2311178e 8625
37e4e482
GM
8626 /* If button is not enabled, and we don't have special images
8627 for the disabled state, make the image appear disabled by
5f5c8ee5 8628 applying an appropriate algorithm to it. */
37e4e482 8629 if (!enabled_p && idx < 0)
ecd01a0e 8630 plist = Fplist_put (plist, QCconversion, Qdisabled);
2311178e 8631
5f5c8ee5
GM
8632 /* Put a `display' text property on the string for the image to
8633 display. Put a `menu-item' property on the string that gives
e037b9ec 8634 the start of this item's properties in the tool-bar items
5f5c8ee5
GM
8635 vector. */
8636 image = Fcons (Qimage, plist);
8637 props = list4 (Qdisplay, image,
a23887b9
GM
8638 Qmenu_item, make_number (i * TOOL_BAR_ITEM_NSLOTS));
8639
8640 /* Let the last image hide all remaining spaces in the tool bar
8641 string. The string can be longer than needed when we reuse a
8642 previous string. */
8643 if (i + 1 == f->n_tool_bar_items)
2051c264 8644 end = SCHARS (f->desired_tool_bar_string);
a23887b9
GM
8645 else
8646 end = i + 1;
8647 Fadd_text_properties (make_number (i), make_number (end),
e037b9ec 8648 props, f->desired_tool_bar_string);
5f5c8ee5 8649#undef PROP
a2889657
JB
8650 }
8651
5f5c8ee5
GM
8652 UNGCPRO;
8653}
8654
8655
e037b9ec 8656/* Display one line of the tool-bar of frame IT->f. */
5f5c8ee5
GM
8657
8658static void
e037b9ec 8659display_tool_bar_line (it)
5f5c8ee5
GM
8660 struct it *it;
8661{
8662 struct glyph_row *row = it->glyph_row;
8663 int max_x = it->last_visible_x;
8664 struct glyph *last;
2311178e 8665
5f5c8ee5
GM
8666 prepare_desired_row (row);
8667 row->y = it->current_y;
90aa2856
GM
8668
8669 /* Note that this isn't made use of if the face hasn't a box,
8670 so there's no need to check the face here. */
8671 it->start_of_box_run_p = 1;
2311178e 8672
5f5c8ee5 8673 while (it->current_x < max_x)
a2889657 8674 {
5f5c8ee5 8675 int x_before, x, n_glyphs_before, i, nglyphs;
a2f016e3 8676
5f5c8ee5
GM
8677 /* Get the next display element. */
8678 if (!get_next_display_element (it))
8679 break;
73af359d 8680
5f5c8ee5
GM
8681 /* Produce glyphs. */
8682 x_before = it->current_x;
8683 n_glyphs_before = it->glyph_row->used[TEXT_AREA];
8684 PRODUCE_GLYPHS (it);
daa37602 8685
5f5c8ee5
GM
8686 nglyphs = it->glyph_row->used[TEXT_AREA] - n_glyphs_before;
8687 i = 0;
8688 x = x_before;
8689 while (i < nglyphs)
8690 {
8691 struct glyph *glyph = row->glyphs[TEXT_AREA] + n_glyphs_before + i;
2311178e 8692
5f5c8ee5
GM
8693 if (x + glyph->pixel_width > max_x)
8694 {
8695 /* Glyph doesn't fit on line. */
8696 it->glyph_row->used[TEXT_AREA] = n_glyphs_before + i;
8697 it->current_x = x;
8698 goto out;
8699 }
daa37602 8700
5f5c8ee5
GM
8701 ++it->hpos;
8702 x += glyph->pixel_width;
8703 ++i;
8704 }
8705
8706 /* Stop at line ends. */
8707 if (ITERATOR_AT_END_OF_LINE_P (it))
8708 break;
8709
cafafe0b 8710 set_iterator_to_next (it, 1);
a2889657 8711 }
a2889657 8712
5f5c8ee5 8713 out:;
a2889657 8714
5f5c8ee5
GM
8715 row->displays_text_p = row->used[TEXT_AREA] != 0;
8716 extend_face_to_end_of_line (it);
8717 last = row->glyphs[TEXT_AREA] + row->used[TEXT_AREA] - 1;
8718 last->right_box_line_p = 1;
90aa2856
GM
8719 if (last == row->glyphs[TEXT_AREA])
8720 last->left_box_line_p = 1;
5f5c8ee5 8721 compute_line_metrics (it);
2311178e 8722
e037b9ec 8723 /* If line is empty, make it occupy the rest of the tool-bar. */
5f5c8ee5
GM
8724 if (!row->displays_text_p)
8725 {
312246d1
GM
8726 row->height = row->phys_height = it->last_visible_y - row->y;
8727 row->ascent = row->phys_ascent = 0;
5f5c8ee5 8728 }
2311178e 8729
5f5c8ee5
GM
8730 row->full_width_p = 1;
8731 row->continued_p = 0;
8732 row->truncated_on_left_p = 0;
8733 row->truncated_on_right_p = 0;
8734
8735 it->current_x = it->hpos = 0;
8736 it->current_y += row->height;
8737 ++it->vpos;
8738 ++it->glyph_row;
a2889657 8739}
96a410bc 8740
5f5c8ee5 8741
e037b9ec 8742/* Value is the number of screen lines needed to make all tool-bar
5f5c8ee5 8743 items of frame F visible. */
96a410bc 8744
d39b6696 8745static int
e037b9ec 8746tool_bar_lines_needed (f)
5f5c8ee5 8747 struct frame *f;
d39b6696 8748{
e037b9ec 8749 struct window *w = XWINDOW (f->tool_bar_window);
5f5c8ee5 8750 struct it it;
2311178e 8751
e037b9ec
GM
8752 /* Initialize an iterator for iteration over
8753 F->desired_tool_bar_string in the tool-bar window of frame F. */
8754 init_iterator (&it, w, -1, -1, w->desired_matrix->rows, TOOL_BAR_FACE_ID);
5f5c8ee5 8755 it.first_visible_x = 0;
da8b7f4f 8756 it.last_visible_x = FRAME_TOTAL_COLS (f) * FRAME_COLUMN_WIDTH (f);
e037b9ec 8757 reseat_to_string (&it, NULL, f->desired_tool_bar_string, 0, 0, 0, -1);
5f5c8ee5
GM
8758
8759 while (!ITERATOR_AT_END_P (&it))
8760 {
8761 it.glyph_row = w->desired_matrix->rows;
8762 clear_glyph_row (it.glyph_row);
e037b9ec 8763 display_tool_bar_line (&it);
5f5c8ee5
GM
8764 }
8765
da8b7f4f 8766 return (it.current_y + FRAME_LINE_HEIGHT (f) - 1) / FRAME_LINE_HEIGHT (f);
d39b6696 8767}
96a410bc 8768
5f5c8ee5 8769
57c28064
GM
8770DEFUN ("tool-bar-lines-needed", Ftool_bar_lines_needed, Stool_bar_lines_needed,
8771 0, 1, 0,
7ee72033
MB
8772 doc: /* Return the number of lines occupied by the tool bar of FRAME. */)
8773 (frame)
57c28064
GM
8774 Lisp_Object frame;
8775{
8776 struct frame *f;
8777 struct window *w;
8778 int nlines = 0;
8779
8780 if (NILP (frame))
8781 frame = selected_frame;
8782 else
b7826503 8783 CHECK_FRAME (frame);
57c28064 8784 f = XFRAME (frame);
2311178e 8785
57c28064
GM
8786 if (WINDOWP (f->tool_bar_window)
8787 || (w = XWINDOW (f->tool_bar_window),
da8b7f4f 8788 WINDOW_TOTAL_LINES (w) > 0))
57c28064
GM
8789 {
8790 update_tool_bar (f, 1);
8791 if (f->n_tool_bar_items)
8792 {
8793 build_desired_tool_bar_string (f);
8794 nlines = tool_bar_lines_needed (f);
8795 }
8796 }
8797
8798 return make_number (nlines);
8799}
8800
8801
e037b9ec 8802/* Display the tool-bar of frame F. Value is non-zero if tool-bar's
5f5c8ee5
GM
8803 height should be changed. */
8804
8805static int
e037b9ec 8806redisplay_tool_bar (f)
5f5c8ee5 8807 struct frame *f;
96a410bc 8808{
5f5c8ee5
GM
8809 struct window *w;
8810 struct it it;
8811 struct glyph_row *row;
8812 int change_height_p = 0;
177c0ea7 8813
488dd4c4 8814#ifdef USE_GTK
6b61353c 8815 if (FRAME_EXTERNAL_TOOL_BAR (f))
488dd4c4
JD
8816 update_frame_tool_bar (f);
8817 return 0;
8818#endif
2311178e 8819
e037b9ec
GM
8820 /* If frame hasn't a tool-bar window or if it is zero-height, don't
8821 do anything. This means you must start with tool-bar-lines
5f5c8ee5 8822 non-zero to get the auto-sizing effect. Or in other words, you
e037b9ec
GM
8823 can turn off tool-bars by specifying tool-bar-lines zero. */
8824 if (!WINDOWP (f->tool_bar_window)
8825 || (w = XWINDOW (f->tool_bar_window),
da8b7f4f 8826 WINDOW_TOTAL_LINES (w) == 0))
5f5c8ee5 8827 return 0;
96a410bc 8828
e037b9ec
GM
8829 /* Set up an iterator for the tool-bar window. */
8830 init_iterator (&it, w, -1, -1, w->desired_matrix->rows, TOOL_BAR_FACE_ID);
5f5c8ee5 8831 it.first_visible_x = 0;
da8b7f4f 8832 it.last_visible_x = FRAME_TOTAL_COLS (f) * FRAME_COLUMN_WIDTH (f);
5f5c8ee5 8833 row = it.glyph_row;
3450d04c 8834
e037b9ec
GM
8835 /* Build a string that represents the contents of the tool-bar. */
8836 build_desired_tool_bar_string (f);
8837 reseat_to_string (&it, NULL, f->desired_tool_bar_string, 0, 0, 0, -1);
3450d04c 8838
e037b9ec 8839 /* Display as many lines as needed to display all tool-bar items. */
5f5c8ee5 8840 while (it.current_y < it.last_visible_y)
e037b9ec 8841 display_tool_bar_line (&it);
3450d04c 8842
e037b9ec 8843 /* It doesn't make much sense to try scrolling in the tool-bar
5f5c8ee5
GM
8844 window, so don't do it. */
8845 w->desired_matrix->no_scrolling_p = 1;
8846 w->must_be_updated_p = 1;
3450d04c 8847
e037b9ec 8848 if (auto_resize_tool_bars_p)
5f5c8ee5
GM
8849 {
8850 int nlines;
6e33e6f0
GM
8851
8852 /* If we couldn't display everything, change the tool-bar's
8853 height. */
8854 if (IT_STRING_CHARPOS (it) < it.end_charpos)
8855 change_height_p = 1;
2311178e 8856
5f5c8ee5
GM
8857 /* If there are blank lines at the end, except for a partially
8858 visible blank line at the end that is smaller than
da8b7f4f 8859 FRAME_LINE_HEIGHT, change the tool-bar's height. */
5f5c8ee5
GM
8860 row = it.glyph_row - 1;
8861 if (!row->displays_text_p
da8b7f4f 8862 && row->height >= FRAME_LINE_HEIGHT (f))
5f5c8ee5
GM
8863 change_height_p = 1;
8864
e037b9ec
GM
8865 /* If row displays tool-bar items, but is partially visible,
8866 change the tool-bar's height. */
5f5c8ee5
GM
8867 if (row->displays_text_p
8868 && MATRIX_ROW_BOTTOM_Y (row) > it.last_visible_y)
8869 change_height_p = 1;
8870
e037b9ec 8871 /* Resize windows as needed by changing the `tool-bar-lines'
5f5c8ee5
GM
8872 frame parameter. */
8873 if (change_height_p
e037b9ec 8874 && (nlines = tool_bar_lines_needed (f),
da8b7f4f 8875 nlines != WINDOW_TOTAL_LINES (w)))
5f5c8ee5 8876 {
e037b9ec 8877 extern Lisp_Object Qtool_bar_lines;
5f5c8ee5 8878 Lisp_Object frame;
da8b7f4f 8879 int old_height = WINDOW_TOTAL_LINES (w);
2311178e 8880
5f5c8ee5
GM
8881 XSETFRAME (frame, f);
8882 clear_glyph_matrix (w->desired_matrix);
8883 Fmodify_frame_parameters (frame,
e037b9ec 8884 Fcons (Fcons (Qtool_bar_lines,
5f5c8ee5
GM
8885 make_number (nlines)),
8886 Qnil));
da8b7f4f 8887 if (WINDOW_TOTAL_LINES (w) != old_height)
e85ee976 8888 fonts_changed_p = 1;
5f5c8ee5
GM
8889 }
8890 }
3450d04c 8891
5f5c8ee5 8892 return change_height_p;
96a410bc 8893}
90adcf20 8894
5f5c8ee5 8895
e037b9ec
GM
8896/* Get information about the tool-bar item which is displayed in GLYPH
8897 on frame F. Return in *PROP_IDX the index where tool-bar item
7464726e 8898 properties start in F->tool_bar_items. Value is zero if
e037b9ec 8899 GLYPH doesn't display a tool-bar item. */
5f5c8ee5 8900
fa3c6b4d 8901static int
e037b9ec 8902tool_bar_item_info (f, glyph, prop_idx)
5f5c8ee5
GM
8903 struct frame *f;
8904 struct glyph *glyph;
8905 int *prop_idx;
90adcf20 8906{
5f5c8ee5
GM
8907 Lisp_Object prop;
8908 int success_p;
be676094
GM
8909 int charpos;
8910
8911 /* This function can be called asynchronously, which means we must
8912 exclude any possibility that Fget_text_property signals an
8913 error. */
2051c264 8914 charpos = min (SCHARS (f->current_tool_bar_string), glyph->charpos);
be676094 8915 charpos = max (0, charpos);
2311178e 8916
5f5c8ee5
GM
8917 /* Get the text property `menu-item' at pos. The value of that
8918 property is the start index of this item's properties in
7464726e 8919 F->tool_bar_items. */
be676094 8920 prop = Fget_text_property (make_number (charpos),
e037b9ec 8921 Qmenu_item, f->current_tool_bar_string);
5f5c8ee5
GM
8922 if (INTEGERP (prop))
8923 {
8924 *prop_idx = XINT (prop);
8925 success_p = 1;
8926 }
8927 else
8928 success_p = 0;
90adcf20 8929
5f5c8ee5
GM
8930 return success_p;
8931}
2311178e 8932
fa3c6b4d
KS
8933\f
8934/* Get information about the tool-bar item at position X/Y on frame F.
8935 Return in *GLYPH a pointer to the glyph of the tool-bar item in
8936 the current matrix of the tool-bar window of F, or NULL if not
8937 on a tool-bar item. Return in *PROP_IDX the index of the tool-bar
8938 item in F->tool_bar_items. Value is
8939
8940 -1 if X/Y is not on a tool-bar item
8941 0 if X/Y is on the same item that was highlighted before.
8942 1 otherwise. */
8943
8944static int
8945get_tool_bar_item (f, x, y, glyph, hpos, vpos, prop_idx)
8946 struct frame *f;
8947 int x, y;
8948 struct glyph **glyph;
8949 int *hpos, *vpos, *prop_idx;
8950{
8951 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
8952 struct window *w = XWINDOW (f->tool_bar_window);
8953 int area;
8954
8955 /* Find the glyph under X/Y. */
6b61353c 8956 *glyph = x_y_to_hpos_vpos (w, x, y, hpos, vpos, 0, 0, &area);
fa3c6b4d
KS
8957 if (*glyph == NULL)
8958 return -1;
8959
8960 /* Get the start of this tool-bar item's properties in
8961 f->tool_bar_items. */
8962 if (!tool_bar_item_info (f, *glyph, prop_idx))
8963 return -1;
8964
8965 /* Is mouse on the highlighted item? */
8966 if (EQ (f->tool_bar_window, dpyinfo->mouse_face_window)
8967 && *vpos >= dpyinfo->mouse_face_beg_row
8968 && *vpos <= dpyinfo->mouse_face_end_row
8969 && (*vpos > dpyinfo->mouse_face_beg_row
8970 || *hpos >= dpyinfo->mouse_face_beg_col)
8971 && (*vpos < dpyinfo->mouse_face_end_row
8972 || *hpos < dpyinfo->mouse_face_end_col
8973 || dpyinfo->mouse_face_past_end))
8974 return 0;
8975
8976 return 1;
8977}
8978
8979
8980/* EXPORT:
8981 Handle mouse button event on the tool-bar of frame F, at
8982 frame-relative coordinates X/Y. DOWN_P is 1 for a button press,
8983 0 for button release. MODIFIERS is event modifiers for button
8984 release. */
8985
8986void
8987handle_tool_bar_click (f, x, y, down_p, modifiers)
8988 struct frame *f;
8989 int x, y, down_p;
8990 unsigned int modifiers;
8991{
8992 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
8993 struct window *w = XWINDOW (f->tool_bar_window);
8994 int hpos, vpos, prop_idx;
8995 struct glyph *glyph;
8996 Lisp_Object enabled_p;
8997
8998 /* If not on the highlighted tool-bar item, return. */
8999 frame_to_window_pixel_xy (w, &x, &y);
9000 if (get_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx) != 0)
9001 return;
9002
9003 /* If item is disabled, do nothing. */
9004 enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P);
9005 if (NILP (enabled_p))
9006 return;
9007
9008 if (down_p)
9009 {
9010 /* Show item in pressed state. */
9011 show_mouse_face (dpyinfo, DRAW_IMAGE_SUNKEN);
9012 dpyinfo->mouse_face_image_state = DRAW_IMAGE_SUNKEN;
9013 last_tool_bar_item = prop_idx;
9014 }
9015 else
9016 {
9017 Lisp_Object key, frame;
9018 struct input_event event;
d86705ec 9019 EVENT_INIT (event);
fa3c6b4d
KS
9020
9021 /* Show item in released state. */
9022 show_mouse_face (dpyinfo, DRAW_IMAGE_RAISED);
9023 dpyinfo->mouse_face_image_state = DRAW_IMAGE_RAISED;
9024
9025 key = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_KEY);
9026
9027 XSETFRAME (frame, f);
9028 event.kind = TOOL_BAR_EVENT;
9029 event.frame_or_window = frame;
9030 event.arg = frame;
9031 kbd_buffer_store_event (&event);
9032
9033 event.kind = TOOL_BAR_EVENT;
9034 event.frame_or_window = frame;
9035 event.arg = key;
9036 event.modifiers = modifiers;
9037 kbd_buffer_store_event (&event);
9038 last_tool_bar_item = -1;
9039 }
9040}
9041
9042
9043/* Possibly highlight a tool-bar item on frame F when mouse moves to
9044 tool-bar window-relative coordinates X/Y. Called from
9045 note_mouse_highlight. */
9046
9047static void
9048note_tool_bar_highlight (f, x, y)
9049 struct frame *f;
9050 int x, y;
9051{
9052 Lisp_Object window = f->tool_bar_window;
9053 struct window *w = XWINDOW (window);
9054 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
9055 int hpos, vpos;
9056 struct glyph *glyph;
9057 struct glyph_row *row;
9058 int i;
9059 Lisp_Object enabled_p;
9060 int prop_idx;
9061 enum draw_glyphs_face draw = DRAW_IMAGE_RAISED;
9062 int mouse_down_p, rc;
9063
9064 /* Function note_mouse_highlight is called with negative x(y
9065 values when mouse moves outside of the frame. */
9066 if (x <= 0 || y <= 0)
9067 {
9068 clear_mouse_face (dpyinfo);
9069 return;
9070 }
9071
9072 rc = get_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx);
9073 if (rc < 0)
9074 {
9075 /* Not on tool-bar item. */
9076 clear_mouse_face (dpyinfo);
9077 return;
9078 }
9079 else if (rc == 0)
9080 /* On same tool-bar item as before. */
9081 goto set_help_echo;
9082
9083 clear_mouse_face (dpyinfo);
9084
9085 /* Mouse is down, but on different tool-bar item? */
9086 mouse_down_p = (dpyinfo->grabbed
9087 && f == last_mouse_frame
9088 && FRAME_LIVE_P (f));
9089 if (mouse_down_p
9090 && last_tool_bar_item != prop_idx)
9091 return;
9092
9093 dpyinfo->mouse_face_image_state = DRAW_NORMAL_TEXT;
9094 draw = mouse_down_p ? DRAW_IMAGE_SUNKEN : DRAW_IMAGE_RAISED;
9095
9096 /* If tool-bar item is not enabled, don't highlight it. */
9097 enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P);
9098 if (!NILP (enabled_p))
9099 {
9100 /* Compute the x-position of the glyph. In front and past the
da8b7f4f 9101 image is a space. We include this in the highlighted area. */
fa3c6b4d
KS
9102 row = MATRIX_ROW (w->current_matrix, vpos);
9103 for (i = x = 0; i < hpos; ++i)
9104 x += row->glyphs[TEXT_AREA][i].pixel_width;
9105
9106 /* Record this as the current active region. */
9107 dpyinfo->mouse_face_beg_col = hpos;
9108 dpyinfo->mouse_face_beg_row = vpos;
9109 dpyinfo->mouse_face_beg_x = x;
9110 dpyinfo->mouse_face_beg_y = row->y;
9111 dpyinfo->mouse_face_past_end = 0;
9112
9113 dpyinfo->mouse_face_end_col = hpos + 1;
9114 dpyinfo->mouse_face_end_row = vpos;
9115 dpyinfo->mouse_face_end_x = x + glyph->pixel_width;
9116 dpyinfo->mouse_face_end_y = row->y;
9117 dpyinfo->mouse_face_window = window;
9118 dpyinfo->mouse_face_face_id = TOOL_BAR_FACE_ID;
9119
9120 /* Display it as active. */
9121 show_mouse_face (dpyinfo, draw);
9122 dpyinfo->mouse_face_image_state = draw;
9123 }
9124
9125 set_help_echo:
9126
9127 /* Set help_echo_string to a help string to display for this tool-bar item.
9128 XTread_socket does the rest. */
9129 help_echo_object = help_echo_window = Qnil;
9130 help_echo_pos = -1;
9131 help_echo_string = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_HELP);
9132 if (NILP (help_echo_string))
9133 help_echo_string = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_CAPTION);
9134}
9135
5f5c8ee5 9136#endif /* HAVE_WINDOW_SYSTEM */
ffbbc941
KS
9137
9138
9139\f
5f5c8ee5
GM
9140/************************************************************************
9141 Horizontal scrolling
9142 ************************************************************************/
feb0c42f 9143
5f5c8ee5
GM
9144static int hscroll_window_tree P_ ((Lisp_Object));
9145static int hscroll_windows P_ ((Lisp_Object));
feb0c42f 9146
5f5c8ee5
GM
9147/* For all leaf windows in the window tree rooted at WINDOW, set their
9148 hscroll value so that PT is (i) visible in the window, and (ii) so
9149 that it is not within a certain margin at the window's left and
9150 right border. Value is non-zero if any window's hscroll has been
9151 changed. */
9152
9153static int
9154hscroll_window_tree (window)
9155 Lisp_Object window;
9156{
9157 int hscrolled_p = 0;
e76d28d5 9158 int hscroll_relative_p = FLOATP (Vhscroll_step);
1df7e8f0
EZ
9159 int hscroll_step_abs = 0;
9160 double hscroll_step_rel = 0;
9161
9162 if (hscroll_relative_p)
9163 {
e76d28d5 9164 hscroll_step_rel = XFLOAT_DATA (Vhscroll_step);
1df7e8f0
EZ
9165 if (hscroll_step_rel < 0)
9166 {
9167 hscroll_relative_p = 0;
9168 hscroll_step_abs = 0;
9169 }
9170 }
e76d28d5 9171 else if (INTEGERP (Vhscroll_step))
1df7e8f0 9172 {
e76d28d5 9173 hscroll_step_abs = XINT (Vhscroll_step);
1df7e8f0
EZ
9174 if (hscroll_step_abs < 0)
9175 hscroll_step_abs = 0;
9176 }
9177 else
9178 hscroll_step_abs = 0;
9179
5f5c8ee5 9180 while (WINDOWP (window))
90adcf20 9181 {
5f5c8ee5 9182 struct window *w = XWINDOW (window);
1df7e8f0 9183
5f5c8ee5
GM
9184 if (WINDOWP (w->hchild))
9185 hscrolled_p |= hscroll_window_tree (w->hchild);
9186 else if (WINDOWP (w->vchild))
9187 hscrolled_p |= hscroll_window_tree (w->vchild);
9188 else if (w->cursor.vpos >= 0)
9189 {
da8b7f4f
KS
9190 int h_margin;
9191 int text_area_width;
92a90e89
GM
9192 struct glyph_row *current_cursor_row
9193 = MATRIX_ROW (w->current_matrix, w->cursor.vpos);
9194 struct glyph_row *desired_cursor_row
9195 = MATRIX_ROW (w->desired_matrix, w->cursor.vpos);
9196 struct glyph_row *cursor_row
9197 = (desired_cursor_row->enabled_p
9198 ? desired_cursor_row
9199 : current_cursor_row);
a2725ab2 9200
da8b7f4f 9201 text_area_width = window_box_width (w, TEXT_AREA);
90adcf20 9202
5f5c8ee5 9203 /* Scroll when cursor is inside this scroll margin. */
da8b7f4f 9204 h_margin = hscroll_margin * WINDOW_FRAME_COLUMN_WIDTH (w);
1df7e8f0 9205
5f5c8ee5 9206 if ((XFASTINT (w->hscroll)
e76d28d5 9207 && w->cursor.x <= h_margin)
92a90e89
GM
9208 || (cursor_row->enabled_p
9209 && cursor_row->truncated_on_right_p
e76d28d5 9210 && (w->cursor.x >= text_area_width - h_margin)))
08b610e4 9211 {
5f5c8ee5
GM
9212 struct it it;
9213 int hscroll;
9214 struct buffer *saved_current_buffer;
9215 int pt;
1df7e8f0 9216 int wanted_x;
5f5c8ee5
GM
9217
9218 /* Find point in a display of infinite width. */
9219 saved_current_buffer = current_buffer;
9220 current_buffer = XBUFFER (w->buffer);
1df7e8f0 9221
5f5c8ee5
GM
9222 if (w == XWINDOW (selected_window))
9223 pt = BUF_PT (current_buffer);
9224 else
08b610e4 9225 {
5f5c8ee5
GM
9226 pt = marker_position (w->pointm);
9227 pt = max (BEGV, pt);
9228 pt = min (ZV, pt);
9229 }
9230
9231 /* Move iterator to pt starting at cursor_row->start in
9232 a line with infinite width. */
9233 init_to_row_start (&it, w, cursor_row);
9234 it.last_visible_x = INFINITY;
9235 move_it_in_display_line_to (&it, pt, -1, MOVE_TO_POS);
9236 current_buffer = saved_current_buffer;
9237
1df7e8f0
EZ
9238 /* Position cursor in window. */
9239 if (!hscroll_relative_p && hscroll_step_abs == 0)
6b61353c
KH
9240 hscroll = max (0, (it.current_x
9241 - (ITERATOR_AT_END_OF_LINE_P (&it)
9242 ? (text_area_width - 4 * FRAME_COLUMN_WIDTH (it.f))
9243 : (text_area_width / 2))))
da8b7f4f 9244 / FRAME_COLUMN_WIDTH (it.f);
e76d28d5 9245 else if (w->cursor.x >= text_area_width - h_margin)
1df7e8f0
EZ
9246 {
9247 if (hscroll_relative_p)
9248 wanted_x = text_area_width * (1 - hscroll_step_rel)
e76d28d5 9249 - h_margin;
1df7e8f0
EZ
9250 else
9251 wanted_x = text_area_width
da8b7f4f 9252 - hscroll_step_abs * FRAME_COLUMN_WIDTH (it.f)
e76d28d5 9253 - h_margin;
1df7e8f0 9254 hscroll
da8b7f4f 9255 = max (0, it.current_x - wanted_x) / FRAME_COLUMN_WIDTH (it.f);
1df7e8f0
EZ
9256 }
9257 else
9258 {
9259 if (hscroll_relative_p)
9260 wanted_x = text_area_width * hscroll_step_rel
e76d28d5 9261 + h_margin;
1df7e8f0 9262 else
da8b7f4f 9263 wanted_x = hscroll_step_abs * FRAME_COLUMN_WIDTH (it.f)
e76d28d5 9264 + h_margin;
1df7e8f0 9265 hscroll
da8b7f4f 9266 = max (0, it.current_x - wanted_x) / FRAME_COLUMN_WIDTH (it.f);
1df7e8f0 9267 }
3172f70b 9268 hscroll = max (hscroll, XFASTINT (w->min_hscroll));
5f5c8ee5
GM
9269
9270 /* Don't call Fset_window_hscroll if value hasn't
9271 changed because it will prevent redisplay
9272 optimizations. */
9273 if (XFASTINT (w->hscroll) != hscroll)
9274 {
3172f70b
GM
9275 XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
9276 w->hscroll = make_number (hscroll);
5f5c8ee5 9277 hscrolled_p = 1;
08b610e4 9278 }
08b610e4 9279 }
08b610e4 9280 }
a2725ab2 9281
5f5c8ee5 9282 window = w->next;
90adcf20 9283 }
cd6dfed6 9284
5f5c8ee5
GM
9285 /* Value is non-zero if hscroll of any leaf window has been changed. */
9286 return hscrolled_p;
9287}
9288
9289
9290/* Set hscroll so that cursor is visible and not inside horizontal
9291 scroll margins for all windows in the tree rooted at WINDOW. See
9292 also hscroll_window_tree above. Value is non-zero if any window's
9293 hscroll has been changed. If it has, desired matrices on the frame
9294 of WINDOW are cleared. */
9295
9296static int
9297hscroll_windows (window)
9298 Lisp_Object window;
9299{
d475bcb8 9300 int hscrolled_p;
2311178e 9301
d475bcb8
GM
9302 if (automatic_hscrolling_p)
9303 {
9304 hscrolled_p = hscroll_window_tree (window);
9305 if (hscrolled_p)
9306 clear_desired_matrices (XFRAME (WINDOW_FRAME (XWINDOW (window))));
9307 }
9308 else
9309 hscrolled_p = 0;
5f5c8ee5 9310 return hscrolled_p;
90adcf20 9311}
5f5c8ee5
GM
9312
9313
90adcf20 9314\f
5f5c8ee5
GM
9315/************************************************************************
9316 Redisplay
9317 ************************************************************************/
9318
9319/* Variables holding some state of redisplay if GLYPH_DEBUG is defined
9320 to a non-zero value. This is sometimes handy to have in a debugger
9321 session. */
9322
9323#if GLYPH_DEBUG
a2889657 9324
5f5c8ee5
GM
9325/* First and last unchanged row for try_window_id. */
9326
9327int debug_first_unchanged_at_end_vpos;
9328int debug_last_unchanged_at_beg_vpos;
9329
9330/* Delta vpos and y. */
9331
9332int debug_dvpos, debug_dy;
9333
9334/* Delta in characters and bytes for try_window_id. */
9335
9336int debug_delta, debug_delta_bytes;
9337
9338/* Values of window_end_pos and window_end_vpos at the end of
9339 try_window_id. */
9340
31ade731 9341EMACS_INT debug_end_pos, debug_end_vpos;
5f5c8ee5
GM
9342
9343/* Append a string to W->desired_matrix->method. FMT is a printf
9344 format string. A1...A9 are a supplement for a variable-length
9345 argument list. If trace_redisplay_p is non-zero also printf the
9346 resulting string to stderr. */
9347
9348static void
9349debug_method_add (w, fmt, a1, a2, a3, a4, a5, a6, a7, a8, a9)
9350 struct window *w;
9351 char *fmt;
9352 int a1, a2, a3, a4, a5, a6, a7, a8, a9;
9353{
9354 char buffer[512];
9355 char *method = w->desired_matrix->method;
9356 int len = strlen (method);
9357 int size = sizeof w->desired_matrix->method;
9358 int remaining = size - len - 1;
9359
9360 sprintf (buffer, fmt, a1, a2, a3, a4, a5, a6, a7, a8, a9);
9361 if (len && remaining)
9362 {
9363 method[len] = '|';
9364 --remaining, ++len;
9365 }
2311178e 9366
5f5c8ee5
GM
9367 strncpy (method + len, buffer, remaining);
9368
9369 if (trace_redisplay_p)
9370 fprintf (stderr, "%p (%s): %s\n",
9371 w,
9372 ((BUFFERP (w->buffer)
9373 && STRINGP (XBUFFER (w->buffer)->name))
2051c264 9374 ? (char *) SDATA (XBUFFER (w->buffer)->name)
5f5c8ee5
GM
9375 : "no buffer"),
9376 buffer);
9377}
a2889657 9378
5f5c8ee5 9379#endif /* GLYPH_DEBUG */
90adcf20 9380
a2889657 9381
5f5c8ee5
GM
9382/* Value is non-zero if all changes in window W, which displays
9383 current_buffer, are in the text between START and END. START is a
9384 buffer position, END is given as a distance from Z. Used in
9385 redisplay_internal for display optimization. */
9386
9387static INLINE int
9388text_outside_line_unchanged_p (w, start, end)
9389 struct window *w;
9390 int start, end;
9391{
9392 int unchanged_p = 1;
2311178e 9393
5f5c8ee5
GM
9394 /* If text or overlays have changed, see where. */
9395 if (XFASTINT (w->last_modified) < MODIFF
9396 || XFASTINT (w->last_overlay_modified) < OVERLAY_MODIFF)
9397 {
9398 /* Gap in the line? */
9399 if (GPT < start || Z - GPT < end)
9400 unchanged_p = 0;
9401
9402 /* Changes start in front of the line, or end after it? */
9403 if (unchanged_p
9142dd5b
GM
9404 && (BEG_UNCHANGED < start - 1
9405 || END_UNCHANGED < end))
5f5c8ee5 9406 unchanged_p = 0;
2311178e 9407
5f5c8ee5
GM
9408 /* If selective display, can't optimize if changes start at the
9409 beginning of the line. */
9410 if (unchanged_p
9411 && INTEGERP (current_buffer->selective_display)
9412 && XINT (current_buffer->selective_display) > 0
9142dd5b 9413 && (BEG_UNCHANGED < start || GPT <= start))
5f5c8ee5 9414 unchanged_p = 0;
47d57b22
GM
9415
9416 /* If there are overlays at the start or end of the line, these
9417 may have overlay strings with newlines in them. A change at
9418 START, for instance, may actually concern the display of such
9419 overlay strings as well, and they are displayed on different
9420 lines. So, quickly rule out this case. (For the future, it
9421 might be desirable to implement something more telling than
9422 just BEG/END_UNCHANGED.) */
9423 if (unchanged_p)
9424 {
9425 if (BEG + BEG_UNCHANGED == start
9426 && overlay_touches_p (start))
9427 unchanged_p = 0;
9428 if (END_UNCHANGED == end
9429 && overlay_touches_p (Z - end))
9430 unchanged_p = 0;
9431 }
5f5c8ee5
GM
9432 }
9433
9434 return unchanged_p;
9435}
9436
9437
9438/* Do a frame update, taking possible shortcuts into account. This is
9439 the main external entry point for redisplay.
9440
9441 If the last redisplay displayed an echo area message and that message
9442 is no longer requested, we clear the echo area or bring back the
9443 mini-buffer if that is in use. */
20de20dc 9444
a2889657
JB
9445void
9446redisplay ()
e9874cee
RS
9447{
9448 redisplay_internal (0);
9449}
9450
47d57b22 9451
6b61353c
KH
9452static Lisp_Object
9453overlay_arrow_string_or_property (var, pbitmap)
9454 Lisp_Object var;
9455 int *pbitmap;
9456{
9457 Lisp_Object pstr = Fget (var, Qoverlay_arrow_string);
9458 Lisp_Object bitmap;
9459
9460 if (pbitmap)
9461 {
9462 *pbitmap = 0;
9463 if (bitmap = Fget (var, Qoverlay_arrow_bitmap), INTEGERP (bitmap))
9464 *pbitmap = XINT (bitmap);
9465 }
9466
9467 if (!NILP (pstr))
9468 return pstr;
9469 return Voverlay_arrow_string;
9470}
9471
9472/* Return 1 if there are any overlay-arrows in current_buffer. */
9473static int
9474overlay_arrow_in_current_buffer_p ()
9475{
9476 Lisp_Object vlist;
9477
9478 for (vlist = Voverlay_arrow_variable_list;
9479 CONSP (vlist);
9480 vlist = XCDR (vlist))
9481 {
9482 Lisp_Object var = XCAR (vlist);
9483 Lisp_Object val;
9484
9485 if (!SYMBOLP (var))
9486 continue;
9487 val = find_symbol_value (var);
9488 if (MARKERP (val)
9489 && current_buffer == XMARKER (val)->buffer)
9490 return 1;
9491 }
9492 return 0;
9493}
9494
9495
9496/* Return 1 if any overlay_arrows have moved or overlay-arrow-string
9497 has changed. */
9498
9499static int
9500overlay_arrows_changed_p ()
9501{
9502 Lisp_Object vlist;
9503
9504 for (vlist = Voverlay_arrow_variable_list;
9505 CONSP (vlist);
9506 vlist = XCDR (vlist))
9507 {
9508 Lisp_Object var = XCAR (vlist);
9509 Lisp_Object val, pstr;
9510
9511 if (!SYMBOLP (var))
9512 continue;
9513 val = find_symbol_value (var);
9514 if (!MARKERP (val))
9515 continue;
9516 if (! EQ (COERCE_MARKER (val),
9517 Fget (var, Qlast_arrow_position))
9518 || ! (pstr = overlay_arrow_string_or_property (var, 0),
9519 EQ (pstr, Fget (var, Qlast_arrow_string))))
9520 return 1;
9521 }
9522 return 0;
9523}
9524
9525/* Mark overlay arrows to be updated on next redisplay. */
9526
9527static void
9528update_overlay_arrows (up_to_date)
9529 int up_to_date;
9530{
9531 Lisp_Object vlist;
9532
9533 for (vlist = Voverlay_arrow_variable_list;
9534 CONSP (vlist);
9535 vlist = XCDR (vlist))
9536 {
9537 Lisp_Object var = XCAR (vlist);
9538
9539 if (!SYMBOLP (var))
9540 continue;
9541
9542 if (up_to_date)
9543 {
9544 Lisp_Object val = find_symbol_value (var);
9545 Fput (var, Qlast_arrow_position,
9546 COERCE_MARKER (val));
9547 Fput (var, Qlast_arrow_string,
9548 overlay_arrow_string_or_property (var, 0));
9549 }
9550 else if (up_to_date < 0
9551 || !NILP (Fget (var, Qlast_arrow_position)))
9552 {
9553 Fput (var, Qlast_arrow_position, Qt);
9554 Fput (var, Qlast_arrow_string, Qt);
9555 }
9556 }
9557}
9558
9559
9560/* Return overlay arrow string at row, or nil. */
9561
9562static Lisp_Object
9563overlay_arrow_at_row (f, row, pbitmap)
9564 struct frame *f;
9565 struct glyph_row *row;
9566 int *pbitmap;
9567{
9568 Lisp_Object vlist;
9569
9570 for (vlist = Voverlay_arrow_variable_list;
9571 CONSP (vlist);
9572 vlist = XCDR (vlist))
9573 {
9574 Lisp_Object var = XCAR (vlist);
9575 Lisp_Object val;
9576
9577 if (!SYMBOLP (var))
9578 continue;
9579
9580 val = find_symbol_value (var);
9581
9582 if (MARKERP (val)
9583 && current_buffer == XMARKER (val)->buffer
9584 && (MATRIX_ROW_START_CHARPOS (row) == marker_position (val)))
9585 {
9586 val = overlay_arrow_string_or_property (var, pbitmap);
9587 if (FRAME_WINDOW_P (f))
9588 return Qt;
9589 else if (STRINGP (val))
9590 return val;
9591 break;
9592 }
9593 }
9594
9595 *pbitmap = 0;
9596 return Qnil;
9597}
9598
260a86a0
KH
9599/* Return 1 if point moved out of or into a composition. Otherwise
9600 return 0. PREV_BUF and PREV_PT are the last point buffer and
9601 position. BUF and PT are the current point buffer and position. */
9602
9603int
9604check_point_in_composition (prev_buf, prev_pt, buf, pt)
9605 struct buffer *prev_buf, *buf;
9606 int prev_pt, pt;
9607{
575d8075 9608 EMACS_INT start, end;
260a86a0
KH
9609 Lisp_Object prop;
9610 Lisp_Object buffer;
9611
9612 XSETBUFFER (buffer, buf);
9613 /* Check a composition at the last point if point moved within the
9614 same buffer. */
9615 if (prev_buf == buf)
9616 {
9617 if (prev_pt == pt)
9618 /* Point didn't move. */
9619 return 0;
2311178e 9620
260a86a0
KH
9621 if (prev_pt > BUF_BEGV (buf) && prev_pt < BUF_ZV (buf)
9622 && find_composition (prev_pt, -1, &start, &end, &prop, buffer)
9623 && COMPOSITION_VALID_P (start, end, prop)
9624 && start < prev_pt && end > prev_pt)
9625 /* The last point was within the composition. Return 1 iff
9626 point moved out of the composition. */
9627 return (pt <= start || pt >= end);
9628 }
9629
9630 /* Check a composition at the current point. */
9631 return (pt > BUF_BEGV (buf) && pt < BUF_ZV (buf)
9632 && find_composition (pt, -1, &start, &end, &prop, buffer)
9633 && COMPOSITION_VALID_P (start, end, prop)
9634 && start < pt && end > pt);
9635}
5f5c8ee5 9636
47d57b22 9637
9142dd5b
GM
9638/* Reconsider the setting of B->clip_changed which is displayed
9639 in window W. */
9640
9641static INLINE void
9642reconsider_clip_changes (w, b)
9643 struct window *w;
9644 struct buffer *b;
9645{
c62c1bb5 9646 if (b->clip_changed
9142dd5b
GM
9647 && !NILP (w->window_end_valid)
9648 && w->current_matrix->buffer == b
9649 && w->current_matrix->zv == BUF_ZV (b)
9650 && w->current_matrix->begv == BUF_BEGV (b))
9651 b->clip_changed = 0;
260a86a0
KH
9652
9653 /* If display wasn't paused, and W is not a tool bar window, see if
9654 point has been moved into or out of a composition. In that case,
9655 we set b->clip_changed to 1 to force updating the screen. If
9656 b->clip_changed has already been set to 1, we can skip this
9657 check. */
9658 if (!b->clip_changed
9659 && BUFFERP (w->buffer) && !NILP (w->window_end_valid))
9660 {
9661 int pt;
9662
9663 if (w == XWINDOW (selected_window))
9664 pt = BUF_PT (current_buffer);
9665 else
9666 pt = marker_position (w->pointm);
9667
9668 if ((w->current_matrix->buffer != XBUFFER (w->buffer)
6fc556fd 9669 || pt != XINT (w->last_point))
260a86a0 9670 && check_point_in_composition (w->current_matrix->buffer,
6fc556fd 9671 XINT (w->last_point),
260a86a0
KH
9672 XBUFFER (w->buffer), pt))
9673 b->clip_changed = 1;
9674 }
9142dd5b 9675}
aac2d8b2 9676\f
aac2d8b2 9677
6b61353c
KH
9678/* Select FRAME to forward the values of frame-local variables into C
9679 variables so that the redisplay routines can access those values
9680 directly. */
9142dd5b 9681
6b61353c
KH
9682static void
9683select_frame_for_redisplay (frame)
9684 Lisp_Object frame;
9685{
9686 Lisp_Object tail, sym, val;
9687 Lisp_Object old = selected_frame;
9142dd5b 9688
6b61353c
KH
9689 selected_frame = frame;
9690
9691 for (tail = XFRAME (frame)->param_alist; CONSP (tail); tail = XCDR (tail))
9692 if (CONSP (XCAR (tail))
9693 && (sym = XCAR (XCAR (tail)),
9694 SYMBOLP (sym))
9695 && (sym = indirect_variable (sym),
9696 val = SYMBOL_VALUE (sym),
9697 (BUFFER_LOCAL_VALUEP (val)
9698 || SOME_BUFFER_LOCAL_VALUEP (val)))
9699 && XBUFFER_LOCAL_VALUE (val)->check_frame)
9700 Fsymbol_value (sym);
9701
9702 for (tail = XFRAME (old)->param_alist; CONSP (tail); tail = XCDR (tail))
9703 if (CONSP (XCAR (tail))
9704 && (sym = XCAR (XCAR (tail)),
9705 SYMBOLP (sym))
9706 && (sym = indirect_variable (sym),
9707 val = SYMBOL_VALUE (sym),
9708 (BUFFER_LOCAL_VALUEP (val)
9709 || SOME_BUFFER_LOCAL_VALUEP (val)))
9710 && XBUFFER_LOCAL_VALUE (val)->check_frame)
9711 Fsymbol_value (sym);
9712}
9713
9714
9715#define STOP_POLLING \
9716do { if (! polling_stopped_here) stop_polling (); \
9717 polling_stopped_here = 1; } while (0)
9718
9719#define RESUME_POLLING \
9720do { if (polling_stopped_here) start_polling (); \
9721 polling_stopped_here = 0; } while (0)
9722
9723
9724/* If PRESERVE_ECHO_AREA is nonzero, it means this redisplay is not in
5f5c8ee5
GM
9725 response to any user action; therefore, we should preserve the echo
9726 area. (Actually, our caller does that job.) Perhaps in the future
9727 avoid recentering windows if it is not necessary; currently that
9728 causes some problems. */
e9874cee
RS
9729
9730static void
9731redisplay_internal (preserve_echo_area)
9732 int preserve_echo_area;
a2889657 9733{
5f5c8ee5
GM
9734 struct window *w = XWINDOW (selected_window);
9735 struct frame *f = XFRAME (w->frame);
9736 int pause;
a2889657 9737 int must_finish = 0;
5f5c8ee5 9738 struct text_pos tlbufpos, tlendpos;
89819bdd 9739 int number_of_visible_frames;
28514cd9 9740 int count;
886bd6f2 9741 struct frame *sf = SELECTED_FRAME ();
aac2d8b2 9742 int polling_stopped_here = 0;
a2889657 9743
5f5c8ee5
GM
9744 /* Non-zero means redisplay has to consider all windows on all
9745 frames. Zero means, only selected_window is considered. */
9746 int consider_all_windows_p;
2311178e 9747
5f5c8ee5
GM
9748 TRACE ((stderr, "redisplay_internal %d\n", redisplaying_p));
9749
9750 /* No redisplay if running in batch mode or frame is not yet fully
9751 initialized, or redisplay is explicitly turned off by setting
9752 Vinhibit_redisplay. */
9753 if (noninteractive
9754 || !NILP (Vinhibit_redisplay)
9755 || !f->glyphs_initialized_p)
a2889657
JB
9756 return;
9757
5f5c8ee5
GM
9758 /* The flag redisplay_performed_directly_p is set by
9759 direct_output_for_insert when it already did the whole screen
9760 update necessary. */
9761 if (redisplay_performed_directly_p)
9762 {
9763 redisplay_performed_directly_p = 0;
9764 if (!hscroll_windows (selected_window))
9765 return;
9766 }
9767
488dd4c4 9768#if defined (USE_X_TOOLKIT) || defined (USE_GTK)
15f0cf78
RS
9769 if (popup_activated ())
9770 return;
9771#endif
9772
28514cd9 9773 /* I don't think this happens but let's be paranoid. */
5f5c8ee5 9774 if (redisplaying_p)
735c094c
KH
9775 return;
9776
28514cd9
GM
9777 /* Record a function that resets redisplaying_p to its old value
9778 when we leave this function. */
331379bf 9779 count = SPECPDL_INDEX ();
6b61353c
KH
9780 record_unwind_protect (unwind_redisplay,
9781 Fcons (make_number (redisplaying_p), selected_frame));
28514cd9 9782 ++redisplaying_p;
26683087 9783 specbind (Qinhibit_free_realized_faces, Qnil);
2311178e 9784
8b32d885 9785 retry:
bd9d0f3f 9786 pause = 0;
9142dd5b
GM
9787 reconsider_clip_changes (w, current_buffer);
9788
5f5c8ee5
GM
9789 /* If new fonts have been loaded that make a glyph matrix adjustment
9790 necessary, do it. */
9791 if (fonts_changed_p)
9792 {
9793 adjust_glyphs (NULL);
9794 ++windows_or_buffers_changed;
9795 fonts_changed_p = 0;
9796 }
9797
6961e0c1
GM
9798 /* If face_change_count is non-zero, init_iterator will free all
9799 realized faces, which includes the faces referenced from current
9800 matrices. So, we can't reuse current matrices in this case. */
9801 if (face_change_count)
9802 ++windows_or_buffers_changed;
9803
886bd6f2
GM
9804 if (! FRAME_WINDOW_P (sf)
9805 && previous_terminal_frame != sf)
20de20dc 9806 {
5f5c8ee5
GM
9807 /* Since frames on an ASCII terminal share the same display
9808 area, displaying a different frame means redisplay the whole
9809 thing. */
20de20dc 9810 windows_or_buffers_changed++;
886bd6f2
GM
9811 SET_FRAME_GARBAGED (sf);
9812 XSETFRAME (Vterminal_frame, sf);
20de20dc 9813 }
886bd6f2 9814 previous_terminal_frame = sf;
20de20dc 9815
5f5c8ee5
GM
9816 /* Set the visible flags for all frames. Do this before checking
9817 for resized or garbaged frames; they want to know if their frames
9818 are visible. See the comment in frame.h for
9819 FRAME_SAMPLE_VISIBILITY. */
d724d989 9820 {
35f56f96 9821 Lisp_Object tail, frame;
d724d989 9822
89819bdd
RS
9823 number_of_visible_frames = 0;
9824
35f56f96 9825 FOR_EACH_FRAME (tail, frame)
f82aff7c 9826 {
5f5c8ee5 9827 struct frame *f = XFRAME (frame);
2311178e 9828
5f5c8ee5
GM
9829 FRAME_SAMPLE_VISIBILITY (f);
9830 if (FRAME_VISIBLE_P (f))
9831 ++number_of_visible_frames;
9832 clear_desired_matrices (f);
f82aff7c 9833 }
d724d989
JB
9834 }
9835
44fa5b1e 9836 /* Notice any pending interrupt request to change frame size. */
c6e89d6c 9837 do_pending_window_change (1);
a2889657 9838
5f5c8ee5 9839 /* Clear frames marked as garbaged. */
44fa5b1e 9840 if (frame_garbaged)
c6e89d6c 9841 clear_garbaged_frames ();
a2889657 9842
e037b9ec 9843 /* Build menubar and tool-bar items. */
f82aff7c
RS
9844 prepare_menu_bars ();
9845
28995e67 9846 if (windows_or_buffers_changed)
a2889657
JB
9847 update_mode_lines++;
9848
538f13d4
RS
9849 /* Detect case that we need to write or remove a star in the mode line. */
9850 if ((SAVE_MODIFF < MODIFF) != !NILP (w->last_had_star))
a2889657
JB
9851 {
9852 w->update_mode_line = Qt;
9853 if (buffer_shared > 1)
9854 update_mode_lines++;
9855 }
9856
5f5c8ee5 9857 /* If %c is in the mode line, update it if needed. */
28995e67
RS
9858 if (!NILP (w->column_number_displayed)
9859 /* This alternative quickly identifies a common case
9860 where no change is needed. */
9861 && !(PT == XFASTINT (w->last_point)
8850a573
RS
9862 && XFASTINT (w->last_modified) >= MODIFF
9863 && XFASTINT (w->last_overlay_modified) >= OVERLAY_MODIFF)
2311178e
TTN
9864 && (XFASTINT (w->column_number_displayed)
9865 != (int) current_column ())) /* iftc */
9866 w->update_mode_line = Qt;
28995e67 9867
44fa5b1e 9868 FRAME_SCROLL_BOTTOM_VPOS (XFRAME (w->frame)) = -1;
a2889657 9869
5f5c8ee5
GM
9870 /* The variable buffer_shared is set in redisplay_window and
9871 indicates that we redisplay a buffer in different windows. See
9872 there. */
5fb96e96
RS
9873 consider_all_windows_p = (update_mode_lines || buffer_shared > 1
9874 || cursor_type_changed);
a2889657
JB
9875
9876 /* If specs for an arrow have changed, do thorough redisplay
9877 to ensure we remove any arrow that should no longer exist. */
6b61353c 9878 if (overlay_arrows_changed_p ())
5f5c8ee5 9879 consider_all_windows_p = windows_or_buffers_changed = 1;
a2889657 9880
90adcf20
RS
9881 /* Normally the message* functions will have already displayed and
9882 updated the echo area, but the frame may have been trashed, or
9883 the update may have been preempted, so display the echo area
6e019995 9884 again here. Checking message_cleared_p captures the case that
c6e89d6c 9885 the echo area should be cleared. */
96d5e9a0
GM
9886 if ((!NILP (echo_area_buffer[0]) && !display_last_displayed_message_p)
9887 || (!NILP (echo_area_buffer[1]) && display_last_displayed_message_p)
3fa69ee7
GM
9888 || (message_cleared_p
9889 && minibuf_level == 0
9890 /* If the mini-window is currently selected, this means the
9891 echo-area doesn't show through. */
9892 && !MINI_WINDOW_P (XWINDOW (selected_window))))
90adcf20 9893 {
c6e89d6c 9894 int window_height_changed_p = echo_area_display (0);
90adcf20 9895 must_finish = 1;
6e019995
GM
9896
9897 /* If we don't display the current message, don't clear the
9898 message_cleared_p flag, because, if we did, we wouldn't clear
9899 the echo area in the next redisplay which doesn't preserve
9900 the echo area. */
9901 if (!display_last_displayed_message_p)
9902 message_cleared_p = 0;
2311178e 9903
c6e89d6c
GM
9904 if (fonts_changed_p)
9905 goto retry;
9906 else if (window_height_changed_p)
9907 {
9908 consider_all_windows_p = 1;
9909 ++update_mode_lines;
9910 ++windows_or_buffers_changed;
2311178e 9911
9142dd5b
GM
9912 /* If window configuration was changed, frames may have been
9913 marked garbaged. Clear them or we will experience
9914 surprises wrt scrolling. */
9915 if (frame_garbaged)
9916 clear_garbaged_frames ();
c6e89d6c 9917 }
90adcf20 9918 }
97a36635 9919 else if (EQ (selected_window, minibuf_window)
dd2eb166
GM
9920 && (current_buffer->clip_changed
9921 || XFASTINT (w->last_modified) < MODIFF
9922 || XFASTINT (w->last_overlay_modified) < OVERLAY_MODIFF)
92a90e89 9923 && resize_mini_window (w, 0))
c6e89d6c
GM
9924 {
9925 /* Resized active mini-window to fit the size of what it is
dd2eb166
GM
9926 showing if its contents might have changed. */
9927 must_finish = 1;
9928 consider_all_windows_p = 1;
c6e89d6c 9929 ++windows_or_buffers_changed;
dd2eb166 9930 ++update_mode_lines;
2311178e 9931
9142dd5b
GM
9932 /* If window configuration was changed, frames may have been
9933 marked garbaged. Clear them or we will experience
9934 surprises wrt scrolling. */
9935 if (frame_garbaged)
9936 clear_garbaged_frames ();
c6e89d6c 9937 }
2311178e 9938
90adcf20 9939
5f5c8ee5
GM
9940 /* If showing the region, and mark has changed, we must redisplay
9941 the whole window. The assignment to this_line_start_pos prevents
9942 the optimization directly below this if-statement. */
bd66d1ba
RS
9943 if (((!NILP (Vtransient_mark_mode)
9944 && !NILP (XBUFFER (w->buffer)->mark_active))
9945 != !NILP (w->region_showing))
82d04750
JB
9946 || (!NILP (w->region_showing)
9947 && !EQ (w->region_showing,
9948 Fmarker_position (XBUFFER (w->buffer)->mark))))
5f5c8ee5
GM
9949 CHARPOS (this_line_start_pos) = 0;
9950
9951 /* Optimize the case that only the line containing the cursor in the
9952 selected window has changed. Variables starting with this_ are
9953 set in display_line and record information about the line
9954 containing the cursor. */
9955 tlbufpos = this_line_start_pos;
9956 tlendpos = this_line_end_pos;
9957 if (!consider_all_windows_p
9958 && CHARPOS (tlbufpos) > 0
9959 && NILP (w->update_mode_line)
73af359d 9960 && !current_buffer->clip_changed
c62c1bb5 9961 && !current_buffer->prevent_redisplay_optimizations_p
44fa5b1e 9962 && FRAME_VISIBLE_P (XFRAME (w->frame))
f21ef775 9963 && !FRAME_OBSCURED_P (XFRAME (w->frame))
5f5c8ee5 9964 /* Make sure recorded data applies to current buffer, etc. */
a2889657
JB
9965 && this_line_buffer == current_buffer
9966 && current_buffer == XBUFFER (w->buffer)
265a9e55 9967 && NILP (w->force_start)
acda20e1 9968 && NILP (w->optional_new_start)
5f5c8ee5
GM
9969 /* Point must be on the line that we have info recorded about. */
9970 && PT >= CHARPOS (tlbufpos)
9971 && PT <= Z - CHARPOS (tlendpos)
a2889657
JB
9972 /* All text outside that line, including its final newline,
9973 must be unchanged */
5f5c8ee5
GM
9974 && text_outside_line_unchanged_p (w, CHARPOS (tlbufpos),
9975 CHARPOS (tlendpos)))
9976 {
9977 if (CHARPOS (tlbufpos) > BEGV
9978 && FETCH_BYTE (BYTEPOS (tlbufpos) - 1) != '\n'
9979 && (CHARPOS (tlbufpos) == ZV
9980 || FETCH_BYTE (BYTEPOS (tlbufpos)) == '\n'))
a2889657
JB
9981 /* Former continuation line has disappeared by becoming empty */
9982 goto cancel;
9983 else if (XFASTINT (w->last_modified) < MODIFF
8850a573 9984 || XFASTINT (w->last_overlay_modified) < OVERLAY_MODIFF
a2889657
JB
9985 || MINI_WINDOW_P (w))
9986 {
1c9241f5
KH
9987 /* We have to handle the case of continuation around a
9988 wide-column character (See the comment in indent.c around
9989 line 885).
9990
9991 For instance, in the following case:
9992
9993 -------- Insert --------
9994 K_A_N_\\ `a' K_A_N_a\ `X_' are wide-column chars.
9995 J_I_ ==> J_I_ `^^' are cursors.
9996 ^^ ^^
9997 -------- --------
9998
9999 As we have to redraw the line above, we should goto cancel. */
10000
5f5c8ee5
GM
10001 struct it it;
10002 int line_height_before = this_line_pixel_height;
10003
10004 /* Note that start_display will handle the case that the
10005 line starting at tlbufpos is a continuation lines. */
10006 start_display (&it, w, tlbufpos);
10007
10008 /* Implementation note: It this still necessary? */
10009 if (it.current_x != this_line_start_x)
1c9241f5
KH
10010 goto cancel;
10011
5f5c8ee5
GM
10012 TRACE ((stderr, "trying display optimization 1\n"));
10013 w->cursor.vpos = -1;
a2889657 10014 overlay_arrow_seen = 0;
5f5c8ee5
GM
10015 it.vpos = this_line_vpos;
10016 it.current_y = this_line_y;
10017 it.glyph_row = MATRIX_ROW (w->desired_matrix, this_line_vpos);
10018 display_line (&it);
10019
a2889657 10020 /* If line contains point, is not continued,
5f5c8ee5 10021 and ends at same distance from eob as before, we win */
2311178e 10022 if (w->cursor.vpos >= 0
5f5c8ee5
GM
10023 /* Line is not continued, otherwise this_line_start_pos
10024 would have been set to 0 in display_line. */
10025 && CHARPOS (this_line_start_pos)
10026 /* Line ends as before. */
10027 && CHARPOS (this_line_end_pos) == CHARPOS (tlendpos)
10028 /* Line has same height as before. Otherwise other lines
10029 would have to be shifted up or down. */
10030 && this_line_pixel_height == line_height_before)
a2889657 10031 {
5f5c8ee5
GM
10032 /* If this is not the window's last line, we must adjust
10033 the charstarts of the lines below. */
10034 if (it.current_y < it.last_visible_y)
10035 {
10036 struct glyph_row *row
10037 = MATRIX_ROW (w->current_matrix, this_line_vpos + 1);
10038 int delta, delta_bytes;
2311178e 10039
5f5c8ee5
GM
10040 if (Z - CHARPOS (tlendpos) == ZV)
10041 {
10042 /* This line ends at end of (accessible part of)
10043 buffer. There is no newline to count. */
10044 delta = (Z
10045 - CHARPOS (tlendpos)
10046 - MATRIX_ROW_START_CHARPOS (row));
10047 delta_bytes = (Z_BYTE
10048 - BYTEPOS (tlendpos)
10049 - MATRIX_ROW_START_BYTEPOS (row));
10050 }
10051 else
10052 {
10053 /* This line ends in a newline. Must take
10054 account of the newline and the rest of the
10055 text that follows. */
10056 delta = (Z
10057 - CHARPOS (tlendpos)
10058 - MATRIX_ROW_START_CHARPOS (row));
10059 delta_bytes = (Z_BYTE
10060 - BYTEPOS (tlendpos)
10061 - MATRIX_ROW_START_BYTEPOS (row));
10062 }
2311178e 10063
f2d86d7a
GM
10064 increment_matrix_positions (w->current_matrix,
10065 this_line_vpos + 1,
10066 w->current_matrix->nrows,
10067 delta, delta_bytes);
85bcef6c 10068 }
46db8486 10069
5f5c8ee5
GM
10070 /* If this row displays text now but previously didn't,
10071 or vice versa, w->window_end_vpos may have to be
10072 adjusted. */
10073 if ((it.glyph_row - 1)->displays_text_p)
10074 {
10075 if (XFASTINT (w->window_end_vpos) < this_line_vpos)
10076 XSETINT (w->window_end_vpos, this_line_vpos);
10077 }
10078 else if (XFASTINT (w->window_end_vpos) == this_line_vpos
10079 && this_line_vpos > 0)
10080 XSETINT (w->window_end_vpos, this_line_vpos - 1);
10081 w->window_end_valid = Qnil;
2311178e 10082
5f5c8ee5
GM
10083 /* Update hint: No need to try to scroll in update_window. */
10084 w->desired_matrix->no_scrolling_p = 1;
10085
10086#if GLYPH_DEBUG
10087 *w->desired_matrix->method = 0;
10088 debug_method_add (w, "optimization 1");
6b61353c
KH
10089#endif
10090#ifdef HAVE_WINDOW_SYSTEM
10091 update_window_fringes (w, 0);
5f5c8ee5 10092#endif
a2889657
JB
10093 goto update;
10094 }
10095 else
10096 goto cancel;
10097 }
5f5c8ee5
GM
10098 else if (/* Cursor position hasn't changed. */
10099 PT == XFASTINT (w->last_point)
b6f0fe04
RS
10100 /* Make sure the cursor was last displayed
10101 in this window. Otherwise we have to reposition it. */
5f5c8ee5 10102 && 0 <= w->cursor.vpos
da8b7f4f 10103 && WINDOW_TOTAL_LINES (w) > w->cursor.vpos)
a2889657
JB
10104 {
10105 if (!must_finish)
10106 {
c6e89d6c 10107 do_pending_window_change (1);
5f5c8ee5 10108
2311178e 10109 /* We used to always goto end_of_redisplay here, but this
5f5c8ee5
GM
10110 isn't enough if we have a blinking cursor. */
10111 if (w->cursor_off_p == w->last_cursor_off_p)
10112 goto end_of_redisplay;
a2889657
JB
10113 }
10114 goto update;
10115 }
8b51f1e3
KH
10116 /* If highlighting the region, or if the cursor is in the echo area,
10117 then we can't just move the cursor. */
bd66d1ba
RS
10118 else if (! (!NILP (Vtransient_mark_mode)
10119 && !NILP (current_buffer->mark_active))
97a36635 10120 && (EQ (selected_window, current_buffer->last_selected_window)
293a54ce 10121 || highlight_nonselected_windows)
8b51f1e3 10122 && NILP (w->region_showing)
8f897821 10123 && NILP (Vshow_trailing_whitespace)
8b51f1e3 10124 && !cursor_in_echo_area)
a2889657 10125 {
5f5c8ee5
GM
10126 struct it it;
10127 struct glyph_row *row;
10128
10129 /* Skip from tlbufpos to PT and see where it is. Note that
10130 PT may be in invisible text. If so, we will end at the
10131 next visible position. */
10132 init_iterator (&it, w, CHARPOS (tlbufpos), BYTEPOS (tlbufpos),
10133 NULL, DEFAULT_FACE_ID);
10134 it.current_x = this_line_start_x;
10135 it.current_y = this_line_y;
10136 it.vpos = this_line_vpos;
2311178e 10137
5f5c8ee5
GM
10138 /* The call to move_it_to stops in front of PT, but
10139 moves over before-strings. */
10140 move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
10141
10142 if (it.vpos == this_line_vpos
10143 && (row = MATRIX_ROW (w->current_matrix, this_line_vpos),
10144 row->enabled_p))
a2889657 10145 {
5f5c8ee5
GM
10146 xassert (this_line_vpos == it.vpos);
10147 xassert (this_line_y == it.current_y);
10148 set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0);
ade0bee1
GM
10149#if GLYPH_DEBUG
10150 *w->desired_matrix->method = 0;
10151 debug_method_add (w, "optimization 3");
10152#endif
a2889657
JB
10153 goto update;
10154 }
10155 else
10156 goto cancel;
10157 }
5f5c8ee5 10158
a2889657 10159 cancel:
5f5c8ee5
GM
10160 /* Text changed drastically or point moved off of line. */
10161 SET_MATRIX_ROW_ENABLED_P (w->desired_matrix, this_line_vpos, 0);
a2889657
JB
10162 }
10163
5f5c8ee5
GM
10164 CHARPOS (this_line_start_pos) = 0;
10165 consider_all_windows_p |= buffer_shared > 1;
10166 ++clear_face_cache_count;
a2889657 10167
2311178e 10168
bd9d0f3f
GM
10169 /* Build desired matrices, and update the display. If
10170 consider_all_windows_p is non-zero, do it for all windows on all
10171 frames. Otherwise do it for selected_window, only. */
463f6b91 10172
5f5c8ee5 10173 if (consider_all_windows_p)
a2889657 10174 {
35f56f96 10175 Lisp_Object tail, frame;
0528abe1
GM
10176 int i, n = 0, size = 50;
10177 struct frame **updated
10178 = (struct frame **) alloca (size * sizeof *updated);
a2889657 10179
5f5c8ee5
GM
10180 /* Clear the face cache eventually. */
10181 if (clear_face_cache_count > CLEAR_FACE_CACHE_COUNT)
463f6b91 10182 {
5f5c8ee5 10183 clear_face_cache (0);
463f6b91
RS
10184 clear_face_cache_count = 0;
10185 }
31b24551 10186
5f5c8ee5
GM
10187 /* Recompute # windows showing selected buffer. This will be
10188 incremented each time such a window is displayed. */
a2889657
JB
10189 buffer_shared = 0;
10190
35f56f96 10191 FOR_EACH_FRAME (tail, frame)
30c566e4 10192 {
5f5c8ee5 10193 struct frame *f = XFRAME (frame);
2311178e 10194
886bd6f2 10195 if (FRAME_WINDOW_P (f) || f == sf)
9769686d 10196 {
6b61353c
KH
10197 if (! EQ (frame, selected_frame))
10198 /* Select the frame, for the sake of frame-local
10199 variables. */
10200 select_frame_for_redisplay (frame);
10201
ae02e06a 10202#ifdef HAVE_WINDOW_SYSTEM
bb336f8d
RS
10203 if (clear_face_cache_count % 50 == 0
10204 && FRAME_WINDOW_P (f))
10205 clear_image_cache (f, 0);
ae02e06a 10206#endif /* HAVE_WINDOW_SYSTEM */
bb336f8d 10207
5f5c8ee5
GM
10208 /* Mark all the scroll bars to be removed; we'll redeem
10209 the ones we want when we redisplay their windows. */
9769686d 10210 if (condemn_scroll_bars_hook)
504454e8 10211 condemn_scroll_bars_hook (f);
30c566e4 10212
f21ef775 10213 if (FRAME_VISIBLE_P (f) && !FRAME_OBSCURED_P (f))
5f5c8ee5 10214 redisplay_windows (FRAME_ROOT_WINDOW (f));
30c566e4 10215
5f5c8ee5
GM
10216 /* Any scroll bars which redisplay_windows should have
10217 nuked should now go away. */
9769686d 10218 if (judge_scroll_bars_hook)
504454e8 10219 judge_scroll_bars_hook (f);
bd9d0f3f
GM
10220
10221 /* If fonts changed, display again. */
b60c9653
RS
10222 /* ??? rms: I suspect it is a mistake to jump all the way
10223 back to retry here. It should just retry this frame. */
bd9d0f3f
GM
10224 if (fonts_changed_p)
10225 goto retry;
2311178e 10226
bd9d0f3f
GM
10227 if (FRAME_VISIBLE_P (f) && !FRAME_OBSCURED_P (f))
10228 {
10229 /* See if we have to hscroll. */
10230 if (hscroll_windows (f->root_window))
10231 goto retry;
10232
10233 /* Prevent various kinds of signals during display
10234 update. stdio is not robust about handling
10235 signals, which can cause an apparent I/O
10236 error. */
10237 if (interrupt_input)
10238 unrequest_sigio ();
aac2d8b2 10239 STOP_POLLING;
bd9d0f3f
GM
10240
10241 /* Update the display. */
10242 set_window_update_flags (XWINDOW (f->root_window), 1);
10243 pause |= update_frame (f, 0, 0);
ccbb9ed2 10244#if 0 /* Exiting the loop can leave the wrong value for buffer_shared. */
bd9d0f3f
GM
10245 if (pause)
10246 break;
ccbb9ed2 10247#endif
bd9d0f3f 10248
0528abe1
GM
10249 if (n == size)
10250 {
10251 int nbytes = size * sizeof *updated;
10252 struct frame **p = (struct frame **) alloca (2 * nbytes);
10253 bcopy (updated, p, nbytes);
10254 size *= 2;
10255 }
2311178e 10256
0528abe1 10257 updated[n++] = f;
bd9d0f3f 10258 }
9769686d 10259 }
30c566e4 10260 }
0528abe1 10261
6b61353c 10262 if (!pause)
6f68b035 10263 {
6b61353c
KH
10264 /* Do the mark_window_display_accurate after all windows have
10265 been redisplayed because this call resets flags in buffers
10266 which are needed for proper redisplay. */
10267 for (i = 0; i < n; ++i)
10268 {
10269 struct frame *f = updated[i];
10270 mark_window_display_accurate (f->root_window, 1);
10271 if (frame_up_to_date_hook)
10272 frame_up_to_date_hook (f);
10273 }
0528abe1 10274 }
a2889657 10275 }
bd9d0f3f
GM
10276 else if (FRAME_VISIBLE_P (sf) && !FRAME_OBSCURED_P (sf))
10277 {
10278 Lisp_Object mini_window;
10279 struct frame *mini_frame;
5f5c8ee5 10280
82a7ab23 10281 displayed_buffer = XBUFFER (XWINDOW (selected_window)->buffer);
7033d6df
RS
10282 /* Use list_of_error, not Qerror, so that
10283 we catch only errors and don't run the debugger. */
10284 internal_condition_case_1 (redisplay_window_1, selected_window,
10285 list_of_error,
82a7ab23 10286 redisplay_window_error);
2311178e 10287
bd9d0f3f 10288 /* Compare desired and current matrices, perform output. */
7d0393cf 10289
26683087 10290 update:
bd9d0f3f
GM
10291 /* If fonts changed, display again. */
10292 if (fonts_changed_p)
92a90e89 10293 goto retry;
a2889657 10294
bd9d0f3f
GM
10295 /* Prevent various kinds of signals during display update.
10296 stdio is not robust about handling signals,
10297 which can cause an apparent I/O error. */
10298 if (interrupt_input)
10299 unrequest_sigio ();
aac2d8b2 10300 STOP_POLLING;
1af9f229 10301
bd9d0f3f 10302 if (FRAME_VISIBLE_P (sf) && !FRAME_OBSCURED_P (sf))
5f5c8ee5 10303 {
92a90e89
GM
10304 if (hscroll_windows (selected_window))
10305 goto retry;
2311178e 10306
5f5c8ee5 10307 XWINDOW (selected_window)->must_be_updated_p = 1;
886bd6f2 10308 pause = update_frame (sf, 0, 0);
5f5c8ee5 10309 }
d724d989 10310
8de2d90b 10311 /* We may have called echo_area_display at the top of this
44fa5b1e
JB
10312 function. If the echo area is on another frame, that may
10313 have put text on a frame other than the selected one, so the
10314 above call to update_frame would not have caught it. Catch
8de2d90b 10315 it here. */
bd9d0f3f
GM
10316 mini_window = FRAME_MINIBUF_WINDOW (sf);
10317 mini_frame = XFRAME (WINDOW_FRAME (XWINDOW (mini_window)));
2311178e 10318
bd9d0f3f
GM
10319 if (mini_frame != sf && FRAME_WINDOW_P (mini_frame))
10320 {
10321 XWINDOW (mini_window)->must_be_updated_p = 1;
10322 pause |= update_frame (mini_frame, 0, 0);
10323 if (!pause && hscroll_windows (mini_window))
10324 goto retry;
10325 }
6e8290aa 10326 }
a2889657 10327
5f5c8ee5
GM
10328 /* If display was paused because of pending input, make sure we do a
10329 thorough update the next time. */
a2889657
JB
10330 if (pause)
10331 {
5f5c8ee5
GM
10332 /* Prevent the optimization at the beginning of
10333 redisplay_internal that tries a single-line update of the
10334 line containing the cursor in the selected window. */
10335 CHARPOS (this_line_start_pos) = 0;
10336
10337 /* Let the overlay arrow be updated the next time. */
6b61353c 10338 update_overlay_arrows (0);
2311178e 10339
5f5c8ee5
GM
10340 /* If we pause after scrolling, some rows in the current
10341 matrices of some windows are not valid. */
10342 if (!WINDOW_FULL_WIDTH_P (w)
10343 && !FRAME_WINDOW_P (XFRAME (w->frame)))
a2889657
JB
10344 update_mode_lines = 1;
10345 }
43c09969 10346 else
a2889657 10347 {
43c09969 10348 if (!consider_all_windows_p)
a2889657 10349 {
43c09969
GM
10350 /* This has already been done above if
10351 consider_all_windows_p is set. */
10352 mark_window_display_accurate_1 (w, 1);
2311178e 10353
6b61353c
KH
10354 /* Say overlay arrows are up to date. */
10355 update_overlay_arrows (1);
2311178e 10356
efc63ef0 10357 if (frame_up_to_date_hook != 0)
43c09969 10358 frame_up_to_date_hook (sf);
a2889657 10359 }
15e26c76 10360
a2889657
JB
10361 update_mode_lines = 0;
10362 windows_or_buffers_changed = 0;
5fb96e96 10363 cursor_type_changed = 0;
a2889657
JB
10364 }
10365
5f5c8ee5
GM
10366 /* Start SIGIO interrupts coming again. Having them off during the
10367 code above makes it less likely one will discard output, but not
10368 impossible, since there might be stuff in the system buffer here.
a2889657 10369 But it is much hairier to try to do anything about that. */
a2889657
JB
10370 if (interrupt_input)
10371 request_sigio ();
aac2d8b2 10372 RESUME_POLLING;
a2889657 10373
5f5c8ee5
GM
10374 /* If a frame has become visible which was not before, redisplay
10375 again, so that we display it. Expose events for such a frame
10376 (which it gets when becoming visible) don't call the parts of
10377 redisplay constructing glyphs, so simply exposing a frame won't
10378 display anything in this case. So, we have to display these
10379 frames here explicitly. */
11c52c4f
RS
10380 if (!pause)
10381 {
10382 Lisp_Object tail, frame;
10383 int new_count = 0;
10384
10385 FOR_EACH_FRAME (tail, frame)
10386 {
10387 int this_is_visible = 0;
8e83f802
RS
10388
10389 if (XFRAME (frame)->visible)
10390 this_is_visible = 1;
10391 FRAME_SAMPLE_VISIBILITY (XFRAME (frame));
10392 if (XFRAME (frame)->visible)
10393 this_is_visible = 1;
11c52c4f
RS
10394
10395 if (this_is_visible)
10396 new_count++;
10397 }
10398
89819bdd 10399 if (new_count != number_of_visible_frames)
11c52c4f
RS
10400 windows_or_buffers_changed++;
10401 }
10402
44fa5b1e 10403 /* Change frame size now if a change is pending. */
c6e89d6c 10404 do_pending_window_change (1);
d8e242fd 10405
8b32d885
RS
10406 /* If we just did a pending size change, or have additional
10407 visible frames, redisplay again. */
3c8c72e0 10408 if (windows_or_buffers_changed && !pause)
8b32d885 10409 goto retry;
5f5c8ee5 10410
1987b083 10411 end_of_redisplay:
28514cd9 10412 unbind_to (count, Qnil);
aac2d8b2 10413 RESUME_POLLING;
a2889657
JB
10414}
10415
5f5c8ee5
GM
10416
10417/* Redisplay, but leave alone any recent echo area message unless
10418 another message has been requested in its place.
a2889657
JB
10419
10420 This is useful in situations where you need to redisplay but no
10421 user action has occurred, making it inappropriate for the message
10422 area to be cleared. See tracking_off and
9bf76936
GM
10423 wait_reading_process_input for examples of these situations.
10424
10425 FROM_WHERE is an integer saying from where this function was
10426 called. This is useful for debugging. */
a2889657 10427
8991bb31 10428void
9bf76936
GM
10429redisplay_preserve_echo_area (from_where)
10430 int from_where;
a2889657 10431{
9bf76936
GM
10432 TRACE ((stderr, "redisplay_preserve_echo_area (%d)\n", from_where));
10433
c6e89d6c 10434 if (!NILP (echo_area_buffer[1]))
a2889657 10435 {
c6e89d6c
GM
10436 /* We have a previously displayed message, but no current
10437 message. Redisplay the previous message. */
10438 display_last_displayed_message_p = 1;
e9874cee 10439 redisplay_internal (1);
c6e89d6c 10440 display_last_displayed_message_p = 0;
a2889657
JB
10441 }
10442 else
e9874cee 10443 redisplay_internal (1);
a2889657
JB
10444}
10445
5f5c8ee5 10446
28514cd9 10447/* Function registered with record_unwind_protect in
acfca545
RS
10448 redisplay_internal. Reset redisplaying_p to the value it had
10449 before redisplay_internal was called, and clear
6b61353c
KH
10450 prevent_freeing_realized_faces_p. It also selects the previously
10451 selected frame. */
28514cd9
GM
10452
10453static Lisp_Object
6b61353c
KH
10454unwind_redisplay (val)
10455 Lisp_Object val;
28514cd9 10456{
6b61353c
KH
10457 Lisp_Object old_redisplaying_p, old_frame;
10458
10459 old_redisplaying_p = XCAR (val);
28514cd9 10460 redisplaying_p = XFASTINT (old_redisplaying_p);
6b61353c
KH
10461 old_frame = XCDR (val);
10462 if (! EQ (old_frame, selected_frame))
10463 select_frame_for_redisplay (old_frame);
c6e89d6c 10464 return Qnil;
28514cd9
GM
10465}
10466
10467
43c09969
GM
10468/* Mark the display of window W as accurate or inaccurate. If
10469 ACCURATE_P is non-zero mark display of W as accurate. If
10470 ACCURATE_P is zero, arrange for W to be redisplayed the next time
10471 redisplay_internal is called. */
5f5c8ee5 10472
43c09969
GM
10473static void
10474mark_window_display_accurate_1 (w, accurate_p)
10475 struct window *w;
5f5c8ee5 10476 int accurate_p;
a2889657 10477{
43c09969 10478 if (BUFFERP (w->buffer))
a2889657 10479 {
43c09969 10480 struct buffer *b = XBUFFER (w->buffer);
2311178e 10481
43c09969
GM
10482 w->last_modified
10483 = make_number (accurate_p ? BUF_MODIFF (b) : 0);
10484 w->last_overlay_modified
10485 = make_number (accurate_p ? BUF_OVERLAY_MODIFF (b) : 0);
10486 w->last_had_star
10487 = BUF_MODIFF (b) > BUF_SAVE_MODIFF (b) ? Qt : Qnil;
a2889657 10488
43c09969 10489 if (accurate_p)
bd66d1ba 10490 {
43c09969
GM
10491 b->clip_changed = 0;
10492 b->prevent_redisplay_optimizations_p = 0;
10493
10494 BUF_UNCHANGED_MODIFIED (b) = BUF_MODIFF (b);
10495 BUF_OVERLAY_UNCHANGED_MODIFIED (b) = BUF_OVERLAY_MODIFF (b);
10496 BUF_BEG_UNCHANGED (b) = BUF_GPT (b) - BUF_BEG (b);
10497 BUF_END_UNCHANGED (b) = BUF_Z (b) - BUF_GPT (b);
2311178e 10498
43c09969
GM
10499 w->current_matrix->buffer = b;
10500 w->current_matrix->begv = BUF_BEGV (b);
10501 w->current_matrix->zv = BUF_ZV (b);
2311178e 10502
43c09969
GM
10503 w->last_cursor = w->cursor;
10504 w->last_cursor_off_p = w->cursor_off_p;
2311178e 10505
43c09969
GM
10506 if (w == XWINDOW (selected_window))
10507 w->last_point = make_number (BUF_PT (b));
10508 else
10509 w->last_point = make_number (XMARKER (w->pointm)->charpos);
bd66d1ba 10510 }
43c09969 10511 }
bd66d1ba 10512
43c09969
GM
10513 if (accurate_p)
10514 {
d2f84654 10515 w->window_end_valid = w->buffer;
99332eb6 10516#if 0 /* This is incorrect with variable-height lines. */
2913a9c0 10517 xassert (XINT (w->window_end_vpos)
da8b7f4f 10518 < (WINDOW_TOTAL_LINES (w)
2913a9c0 10519 - (WINDOW_WANTS_MODELINE_P (w) ? 1 : 0)));
99332eb6 10520#endif
a2889657 10521 w->update_mode_line = Qnil;
43c09969
GM
10522 }
10523}
10524
10525
10526/* Mark the display of windows in the window tree rooted at WINDOW as
10527 accurate or inaccurate. If ACCURATE_P is non-zero mark display of
10528 windows as accurate. If ACCURATE_P is zero, arrange for windows to
10529 be redisplayed the next time redisplay_internal is called. */
10530
10531void
10532mark_window_display_accurate (window, accurate_p)
10533 Lisp_Object window;
10534 int accurate_p;
10535{
10536 struct window *w;
2311178e 10537
43c09969
GM
10538 for (; !NILP (window); window = w->next)
10539 {
10540 w = XWINDOW (window);
10541 mark_window_display_accurate_1 (w, accurate_p);
a2889657 10542
265a9e55 10543 if (!NILP (w->vchild))
5f5c8ee5 10544 mark_window_display_accurate (w->vchild, accurate_p);
265a9e55 10545 if (!NILP (w->hchild))
5f5c8ee5 10546 mark_window_display_accurate (w->hchild, accurate_p);
a2889657
JB
10547 }
10548
5f5c8ee5 10549 if (accurate_p)
a2889657 10550 {
6b61353c 10551 update_overlay_arrows (1);
a2889657
JB
10552 }
10553 else
10554 {
5f5c8ee5
GM
10555 /* Force a thorough redisplay the next time by setting
10556 last_arrow_position and last_arrow_string to t, which is
4b41cebb 10557 unequal to any useful value of Voverlay_arrow_... */
6b61353c 10558 update_overlay_arrows (-1);
a2889657
JB
10559 }
10560}
5f5c8ee5
GM
10561
10562
10563/* Return value in display table DP (Lisp_Char_Table *) for character
10564 C. Since a display table doesn't have any parent, we don't have to
10565 follow parent. Do not call this function directly but use the
10566 macro DISP_CHAR_VECTOR. */
10567
10568Lisp_Object
10569disp_char_vector (dp, c)
10570 struct Lisp_Char_Table *dp;
10571 int c;
10572{
5f5c8ee5
GM
10573 Lisp_Object val;
10574
ea0ffe21 10575 if (ASCII_CHAR_P (c))
5f5c8ee5 10576 {
ea0ffe21
KH
10577 val = dp->ascii;
10578 if (SUB_CHAR_TABLE_P (val))
10579 val = XSUB_CHAR_TABLE (val)->contents[c];
5f5c8ee5 10580 }
ea0ffe21
KH
10581 else
10582 {
10583 Lisp_Object table;
2311178e 10584
ea0ffe21
KH
10585 XSETCHAR_TABLE (table, dp);
10586 val = char_table_ref (table, c);
10587 }
10588 if (NILP (val))
10589 val = dp->defalt;
10590 return val;
5f5c8ee5
GM
10591}
10592
10593
a2889657 10594\f
5f5c8ee5
GM
10595/***********************************************************************
10596 Window Redisplay
10597 ***********************************************************************/
a2725ab2 10598
5f5c8ee5 10599/* Redisplay all leaf windows in the window tree rooted at WINDOW. */
90adcf20
RS
10600
10601static void
5f5c8ee5
GM
10602redisplay_windows (window)
10603 Lisp_Object window;
90adcf20 10604{
5f5c8ee5
GM
10605 while (!NILP (window))
10606 {
10607 struct window *w = XWINDOW (window);
2311178e 10608
5f5c8ee5
GM
10609 if (!NILP (w->hchild))
10610 redisplay_windows (w->hchild);
10611 else if (!NILP (w->vchild))
10612 redisplay_windows (w->vchild);
10613 else
82a7ab23
RS
10614 {
10615 displayed_buffer = XBUFFER (w->buffer);
7033d6df
RS
10616 /* Use list_of_error, not Qerror, so that
10617 we catch only errors and don't run the debugger. */
2311178e 10618 internal_condition_case_1 (redisplay_window_0, window,
7033d6df 10619 list_of_error,
82a7ab23
RS
10620 redisplay_window_error);
10621 }
a2725ab2 10622
5f5c8ee5
GM
10623 window = w->next;
10624 }
10625}
10626
82a7ab23
RS
10627static Lisp_Object
10628redisplay_window_error ()
10629{
10630 displayed_buffer->display_error_modiff = BUF_MODIFF (displayed_buffer);
10631 return Qnil;
10632}
10633
10634static Lisp_Object
10635redisplay_window_0 (window)
10636 Lisp_Object window;
10637{
10638 if (displayed_buffer->display_error_modiff < BUF_MODIFF (displayed_buffer))
10639 redisplay_window (window, 0);
10640 return Qnil;
10641}
5f5c8ee5 10642
82a7ab23
RS
10643static Lisp_Object
10644redisplay_window_1 (window)
10645 Lisp_Object window;
10646{
10647 if (displayed_buffer->display_error_modiff < BUF_MODIFF (displayed_buffer))
10648 redisplay_window (window, 1);
10649 return Qnil;
10650}
10651\f
bc6371a6
KH
10652
10653/* Increment GLYPH until it reaches END or CONDITION fails while
10654 adding (GLYPH)->pixel_width to X. */
10655
10656#define SKIP_GLYPHS(glyph, end, x, condition) \
10657 do \
10658 { \
10659 (x) += (glyph)->pixel_width; \
10660 ++(glyph); \
10661 } \
10662 while ((glyph) < (end) && (condition))
10663
10664
5f5c8ee5
GM
10665/* Set cursor position of W. PT is assumed to be displayed in ROW.
10666 DELTA is the number of bytes by which positions recorded in ROW
10667 differ from current buffer positions. */
10668
10669void
10670set_cursor_from_row (w, row, matrix, delta, delta_bytes, dy, dvpos)
10671 struct window *w;
10672 struct glyph_row *row;
10673 struct glyph_matrix *matrix;
10674 int delta, delta_bytes, dy, dvpos;
10675{
10676 struct glyph *glyph = row->glyphs[TEXT_AREA];
10677 struct glyph *end = glyph + row->used[TEXT_AREA];
ae73dc1c
KH
10678 /* The first glyph that starts a sequence of glyphs from string. */
10679 struct glyph *string_start;
10680 /* The X coordinate of string_start. */
10681 int string_start_x;
10682 /* The last known character position. */
10683 int last_pos = MATRIX_ROW_START_CHARPOS (row) + delta;
10684 /* The last known character position before string_start. */
10685 int string_before_pos;
5f5c8ee5
GM
10686 int x = row->x;
10687 int pt_old = PT - delta;
10688
10689 /* Skip over glyphs not having an object at the start of the row.
10690 These are special glyphs like truncation marks on terminal
10691 frames. */
10692 if (row->displays_text_p)
10693 while (glyph < end
6fc556fd 10694 && INTEGERP (glyph->object)
5f5c8ee5
GM
10695 && glyph->charpos < 0)
10696 {
10697 x += glyph->pixel_width;
10698 ++glyph;
10699 }
10700
ae73dc1c 10701 string_start = NULL;
5f5c8ee5 10702 while (glyph < end
6fc556fd 10703 && !INTEGERP (glyph->object)
5f5c8ee5 10704 && (!BUFFERP (glyph->object)
ae73dc1c 10705 || (last_pos = glyph->charpos) < pt_old))
5f5c8ee5 10706 {
ae73dc1c
KH
10707 if (! STRINGP (glyph->object))
10708 {
10709 string_start = NULL;
10710 x += glyph->pixel_width;
10711 ++glyph;
10712 }
10713 else
10714 {
10715 string_before_pos = last_pos;
10716 string_start = glyph;
10717 string_start_x = x;
10718 /* Skip all glyphs from string. */
bc6371a6 10719 SKIP_GLYPHS (glyph, end, x, STRINGP (glyph->object));
ae73dc1c
KH
10720 }
10721 }
10722
10723 if (string_start
10724 && (glyph == end || !BUFFERP (glyph->object) || last_pos > pt_old))
10725 {
10726 /* We may have skipped over point because the previous glyphs
10727 are from string. As there's no easy way to know the
10728 character position of the current glyph, find the correct
10729 glyph on point by scanning from string_start again. */
bc6371a6
KH
10730 Lisp_Object limit;
10731 Lisp_Object string;
10732 int pos;
ae73dc1c 10733
bc6371a6
KH
10734 limit = make_number (pt_old + 1);
10735 end = glyph;
ae73dc1c
KH
10736 glyph = string_start;
10737 x = string_start_x;
bc6371a6
KH
10738 string = glyph->object;
10739 pos = string_buffer_position (w, string, string_before_pos);
10740 /* If STRING is from overlay, LAST_POS == 0. We skip such glyphs
10741 because we always put cursor after overlay strings. */
10742 while (pos == 0 && glyph < end)
ae73dc1c 10743 {
bc6371a6
KH
10744 string = glyph->object;
10745 SKIP_GLYPHS (glyph, end, x, EQ (glyph->object, string));
10746 if (glyph < end)
10747 pos = string_buffer_position (w, glyph->object, string_before_pos);
10748 }
10749
10750 while (glyph < end)
10751 {
10752 pos = XINT (Fnext_single_char_property_change
10753 (make_number (pos), Qdisplay, Qnil, limit));
10754 if (pos > pt_old)
10755 break;
ae73dc1c 10756 /* Skip glyphs from the same string. */
bc6371a6
KH
10757 string = glyph->object;
10758 SKIP_GLYPHS (glyph, end, x, EQ (glyph->object, string));
10759 /* Skip glyphs from an overlay. */
10760 while (glyph < end
10761 && ! string_buffer_position (w, glyph->object, pos))
ae73dc1c 10762 {
bc6371a6
KH
10763 string = glyph->object;
10764 SKIP_GLYPHS (glyph, end, x, EQ (glyph->object, string));
ae73dc1c 10765 }
ae73dc1c 10766 }
5f5c8ee5
GM
10767 }
10768
10769 w->cursor.hpos = glyph - row->glyphs[TEXT_AREA];
10770 w->cursor.x = x;
10771 w->cursor.vpos = MATRIX_ROW_VPOS (row, matrix) + dvpos;
10772 w->cursor.y = row->y + dy;
10773
10774 if (w == XWINDOW (selected_window))
10775 {
10776 if (!row->continued_p
10777 && !MATRIX_ROW_CONTINUATION_LINE_P (row)
10778 && row->x == 0)
10779 {
10780 this_line_buffer = XBUFFER (w->buffer);
2311178e 10781
5f5c8ee5
GM
10782 CHARPOS (this_line_start_pos)
10783 = MATRIX_ROW_START_CHARPOS (row) + delta;
10784 BYTEPOS (this_line_start_pos)
10785 = MATRIX_ROW_START_BYTEPOS (row) + delta_bytes;
2311178e 10786
5f5c8ee5
GM
10787 CHARPOS (this_line_end_pos)
10788 = Z - (MATRIX_ROW_END_CHARPOS (row) + delta);
10789 BYTEPOS (this_line_end_pos)
10790 = Z_BYTE - (MATRIX_ROW_END_BYTEPOS (row) + delta_bytes);
2311178e 10791
5f5c8ee5
GM
10792 this_line_y = w->cursor.y;
10793 this_line_pixel_height = row->height;
10794 this_line_vpos = w->cursor.vpos;
10795 this_line_start_x = row->x;
10796 }
10797 else
10798 CHARPOS (this_line_start_pos) = 0;
10799 }
10800}
10801
10802
10803/* Run window scroll functions, if any, for WINDOW with new window
756a3cb6
RS
10804 start STARTP. Sets the window start of WINDOW to that position.
10805
10806 We assume that the window's buffer is really current. */
5f5c8ee5
GM
10807
10808static INLINE struct text_pos
10809run_window_scroll_functions (window, startp)
10810 Lisp_Object window;
10811 struct text_pos startp;
10812{
10813 struct window *w = XWINDOW (window);
10814 SET_MARKER_FROM_TEXT_POS (w->start, startp);
756a3cb6
RS
10815
10816 if (current_buffer != XBUFFER (w->buffer))
10817 abort ();
10818
5f5c8ee5
GM
10819 if (!NILP (Vwindow_scroll_functions))
10820 {
2311178e 10821 run_hook_with_args_2 (Qwindow_scroll_functions, window,
5f5c8ee5
GM
10822 make_number (CHARPOS (startp)));
10823 SET_TEXT_POS_FROM_MARKER (startp, w->start);
756a3cb6
RS
10824 /* In case the hook functions switch buffers. */
10825 if (current_buffer != XBUFFER (w->buffer))
10826 set_buffer_internal_1 (XBUFFER (w->buffer));
5f5c8ee5 10827 }
90adcf20 10828
5f5c8ee5
GM
10829 return startp;
10830}
10831
10832
ddf6b9a3
RS
10833/* Make sure the line containing the cursor is fully visible.
10834 A value of 1 means there is nothing to be done.
10835 (Either the line is fully visible, or it cannot be made so,
10836 or we cannot tell.)
6b61353c
KH
10837
10838 If FORCE_P is non-zero, return 0 even if partial visible cursor row
10839 is higher than window.
10840
ddf6b9a3
RS
10841 A value of 0 means the caller should do scrolling
10842 as if point had gone off the screen. */
5f5c8ee5 10843
cb617e7c 10844static int
6b61353c 10845make_cursor_line_fully_visible (w, force_p)
5f5c8ee5 10846 struct window *w;
6b61353c 10847 int force_p;
5f5c8ee5
GM
10848{
10849 struct glyph_matrix *matrix;
10850 struct glyph_row *row;
478d746b 10851 int window_height;
2311178e 10852
5f5c8ee5
GM
10853 /* It's not always possible to find the cursor, e.g, when a window
10854 is full of overlay strings. Don't do anything in that case. */
10855 if (w->cursor.vpos < 0)
cb617e7c 10856 return 1;
2311178e 10857
5f5c8ee5
GM
10858 matrix = w->desired_matrix;
10859 row = MATRIX_ROW (matrix, w->cursor.vpos);
10860
acda20e1 10861 /* If the cursor row is not partially visible, there's nothing to do. */
b28cb6ed 10862 if (!MATRIX_ROW_PARTIALLY_VISIBLE_P (row))
cb617e7c 10863 return 1;
b28cb6ed 10864
6b61353c
KH
10865 if (force_p)
10866 return 0;
10867
b28cb6ed
GM
10868 /* If the row the cursor is in is taller than the window's height,
10869 it's not clear what to do, so do nothing. */
10870 window_height = window_box_height (w);
10871 if (row->height >= window_height)
cb617e7c 10872 return 1;
b28cb6ed 10873
ddf6b9a3
RS
10874 return 0;
10875
10876#if 0
10877 /* This code used to try to scroll the window just enough to make
10878 the line visible. It returned 0 to say that the caller should
10879 allocate larger glyph matrices. */
10880
b28cb6ed 10881 if (MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (w, row))
5f5c8ee5
GM
10882 {
10883 int dy = row->height - row->visible_height;
10884 w->vscroll = 0;
10885 w->cursor.y += dy;
10886 shift_glyph_matrix (w, matrix, 0, matrix->nrows, dy);
10887 }
b28cb6ed 10888 else /* MATRIX_ROW_PARTIALLY_VISIBLE_AT_BOTTOM_P (w, row)) */
5f5c8ee5
GM
10889 {
10890 int dy = - (row->height - row->visible_height);
10891 w->vscroll = dy;
10892 w->cursor.y += dy;
10893 shift_glyph_matrix (w, matrix, 0, matrix->nrows, dy);
10894 }
2311178e 10895
5f5c8ee5
GM
10896 /* When we change the cursor y-position of the selected window,
10897 change this_line_y as well so that the display optimization for
10898 the cursor line of the selected window in redisplay_internal uses
10899 the correct y-position. */
10900 if (w == XWINDOW (selected_window))
10901 this_line_y = w->cursor.y;
cb617e7c
GM
10902
10903 /* If vscrolling requires a larger glyph matrix, arrange for a fresh
10904 redisplay with larger matrices. */
10905 if (matrix->nrows < required_matrix_height (w))
10906 {
10907 fonts_changed_p = 1;
10908 return 0;
10909 }
10910
10911 return 1;
ddf6b9a3 10912#endif /* 0 */
5f5c8ee5
GM
10913}
10914
10915
10916/* Try scrolling PT into view in window WINDOW. JUST_THIS_ONE_P
10917 non-zero means only WINDOW is redisplayed in redisplay_internal.
10918 TEMP_SCROLL_STEP has the same meaning as scroll_step, and is used
10919 in redisplay_window to bring a partially visible line into view in
10920 the case that only the cursor has moved.
10921
03b0a4b4
RS
10922 LAST_LINE_MISFIT should be nonzero if we're scrolling because the
10923 last screen line's vertical height extends past the end of the screen.
10924
5f5c8ee5
GM
10925 Value is
10926
10927 1 if scrolling succeeded
2311178e 10928
5f5c8ee5 10929 0 if scrolling didn't find point.
2311178e 10930
5f5c8ee5
GM
10931 -1 if new fonts have been loaded so that we must interrupt
10932 redisplay, adjust glyph matrices, and try again. */
10933
cb617e7c
GM
10934enum
10935{
10936 SCROLLING_SUCCESS,
10937 SCROLLING_FAILED,
10938 SCROLLING_NEED_LARGER_MATRICES
10939};
10940
5f5c8ee5
GM
10941static int
10942try_scrolling (window, just_this_one_p, scroll_conservatively,
03b0a4b4 10943 scroll_step, temp_scroll_step, last_line_misfit)
5f5c8ee5
GM
10944 Lisp_Object window;
10945 int just_this_one_p;
31ade731 10946 EMACS_INT scroll_conservatively, scroll_step;
5f5c8ee5 10947 int temp_scroll_step;
03b0a4b4 10948 int last_line_misfit;
5f5c8ee5
GM
10949{
10950 struct window *w = XWINDOW (window);
10951 struct frame *f = XFRAME (w->frame);
10952 struct text_pos scroll_margin_pos;
10953 struct text_pos pos;
10954 struct text_pos startp;
10955 struct it it;
10956 Lisp_Object window_end;
10957 int this_scroll_margin;
10958 int dy = 0;
10959 int scroll_max;
b8a63ccb 10960 int rc;
5f5c8ee5
GM
10961 int amount_to_scroll = 0;
10962 Lisp_Object aggressive;
10963 int height;
6b61353c 10964 int extra_scroll_margin_lines = last_line_misfit ? 1 : 0;
5f5c8ee5
GM
10965
10966#if GLYPH_DEBUG
10967 debug_method_add (w, "try_scrolling");
78614721 10968#endif
5f5c8ee5
GM
10969
10970 SET_TEXT_POS_FROM_MARKER (startp, w->start);
2311178e 10971
5f5c8ee5
GM
10972 /* Compute scroll margin height in pixels. We scroll when point is
10973 within this distance from the top or bottom of the window. */
10974 if (scroll_margin > 0)
90adcf20 10975 {
da8b7f4f
KS
10976 this_scroll_margin = min (scroll_margin, WINDOW_TOTAL_LINES (w) / 4);
10977 this_scroll_margin *= FRAME_LINE_HEIGHT (f);
5f5c8ee5
GM
10978 }
10979 else
10980 this_scroll_margin = 0;
10981
10982 /* Compute how much we should try to scroll maximally to bring point
10983 into view. */
0894e696
SM
10984 if (scroll_step || scroll_conservatively || temp_scroll_step)
10985 scroll_max = max (scroll_step,
10986 max (scroll_conservatively, temp_scroll_step));
5f5c8ee5
GM
10987 else if (NUMBERP (current_buffer->scroll_down_aggressively)
10988 || NUMBERP (current_buffer->scroll_up_aggressively))
10989 /* We're trying to scroll because of aggressive scrolling
10990 but no scroll_step is set. Choose an arbitrary one. Maybe
10991 there should be a variable for this. */
10992 scroll_max = 10;
10993 else
10994 scroll_max = 0;
da8b7f4f 10995 scroll_max *= FRAME_LINE_HEIGHT (f);
5f5c8ee5
GM
10996
10997 /* Decide whether we have to scroll down. Start at the window end
10998 and move this_scroll_margin up to find the position of the scroll
10999 margin. */
11000 window_end = Fwindow_end (window, Qt);
03b0a4b4
RS
11001
11002 too_near_end:
11003
5f5c8ee5
GM
11004 CHARPOS (scroll_margin_pos) = XINT (window_end);
11005 BYTEPOS (scroll_margin_pos) = CHAR_TO_BYTE (CHARPOS (scroll_margin_pos));
03b0a4b4 11006
6b61353c 11007 if (this_scroll_margin || extra_scroll_margin_lines)
5f5c8ee5
GM
11008 {
11009 start_display (&it, w, scroll_margin_pos);
6b61353c
KH
11010 if (this_scroll_margin)
11011 move_it_vertically (&it, - this_scroll_margin);
11012 if (extra_scroll_margin_lines)
11013 move_it_by_lines (&it, - extra_scroll_margin_lines, 0);
5f5c8ee5
GM
11014 scroll_margin_pos = it.current.pos;
11015 }
11016
11017 if (PT >= CHARPOS (scroll_margin_pos))
11018 {
11019 int y0;
2311178e 11020
5f5c8ee5
GM
11021 /* Point is in the scroll margin at the bottom of the window, or
11022 below. Compute a new window start that makes point visible. */
47589c8c 11023
5f5c8ee5
GM
11024 /* Compute the distance from the scroll margin to PT.
11025 Give up if the distance is greater than scroll_max. */
11026 start_display (&it, w, scroll_margin_pos);
11027 y0 = it.current_y;
11028 move_it_to (&it, PT, 0, it.last_visible_y, -1,
11029 MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
539e92ad
GM
11030
11031 /* To make point visible, we have to move the window start
11032 down so that the line the cursor is in is visible, which
11033 means we have to add in the height of the cursor line. */
11034 dy = line_bottom_y (&it) - y0;
2311178e 11035
5f5c8ee5 11036 if (dy > scroll_max)
cb617e7c 11037 return SCROLLING_FAILED;
2311178e 11038
5f5c8ee5
GM
11039 /* Move the window start down. If scrolling conservatively,
11040 move it just enough down to make point visible. If
11041 scroll_step is set, move it down by scroll_step. */
11042 start_display (&it, w, startp);
11043
11044 if (scroll_conservatively)
03b0a4b4
RS
11045 /* Set AMOUNT_TO_SCROLL to at least one line,
11046 and at most scroll_conservatively lines. */
e89aaabd 11047 amount_to_scroll
da8b7f4f
KS
11048 = min (max (dy, FRAME_LINE_HEIGHT (f)),
11049 FRAME_LINE_HEIGHT (f) * scroll_conservatively);
5f5c8ee5
GM
11050 else if (scroll_step || temp_scroll_step)
11051 amount_to_scroll = scroll_max;
11052 else
90adcf20 11053 {
46226c1d 11054 aggressive = current_buffer->scroll_up_aggressively;
da8b7f4f 11055 height = WINDOW_BOX_TEXT_HEIGHT (w);
5f5c8ee5
GM
11056 if (NUMBERP (aggressive))
11057 amount_to_scroll = XFLOATINT (aggressive) * height;
11058 }
a2725ab2 11059
5f5c8ee5 11060 if (amount_to_scroll <= 0)
cb617e7c 11061 return SCROLLING_FAILED;
a2725ab2 11062
03b0a4b4
RS
11063 /* If moving by amount_to_scroll leaves STARTP unchanged,
11064 move it down one screen line. */
11065
5f5c8ee5 11066 move_it_vertically (&it, amount_to_scroll);
03b0a4b4
RS
11067 if (CHARPOS (it.current.pos) == CHARPOS (startp))
11068 move_it_by_lines (&it, 1, 1);
5f5c8ee5
GM
11069 startp = it.current.pos;
11070 }
11071 else
11072 {
11073 /* See if point is inside the scroll margin at the top of the
11074 window. */
11075 scroll_margin_pos = startp;
11076 if (this_scroll_margin)
11077 {
11078 start_display (&it, w, startp);
11079 move_it_vertically (&it, this_scroll_margin);
11080 scroll_margin_pos = it.current.pos;
11081 }
11082
11083 if (PT < CHARPOS (scroll_margin_pos))
11084 {
11085 /* Point is in the scroll margin at the top of the window or
11086 above what is displayed in the window. */
11087 int y0;
2311178e 11088
5f5c8ee5
GM
11089 /* Compute the vertical distance from PT to the scroll
11090 margin position. Give up if distance is greater than
11091 scroll_max. */
11092 SET_TEXT_POS (pos, PT, PT_BYTE);
11093 start_display (&it, w, pos);
11094 y0 = it.current_y;
11095 move_it_to (&it, CHARPOS (scroll_margin_pos), 0,
11096 it.last_visible_y, -1,
11097 MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
11098 dy = it.current_y - y0;
11099 if (dy > scroll_max)
cb617e7c 11100 return SCROLLING_FAILED;
2311178e 11101
5f5c8ee5
GM
11102 /* Compute new window start. */
11103 start_display (&it, w, startp);
2311178e 11104
5f5c8ee5 11105 if (scroll_conservatively)
0894e696 11106 amount_to_scroll =
da8b7f4f 11107 max (dy, FRAME_LINE_HEIGHT (f) * max (scroll_step, temp_scroll_step));
5f5c8ee5
GM
11108 else if (scroll_step || temp_scroll_step)
11109 amount_to_scroll = scroll_max;
538f13d4 11110 else
5f5c8ee5 11111 {
46226c1d 11112 aggressive = current_buffer->scroll_down_aggressively;
da8b7f4f 11113 height = WINDOW_BOX_TEXT_HEIGHT (w);
5f5c8ee5
GM
11114 if (NUMBERP (aggressive))
11115 amount_to_scroll = XFLOATINT (aggressive) * height;
11116 }
a2725ab2 11117
5f5c8ee5 11118 if (amount_to_scroll <= 0)
cb617e7c 11119 return SCROLLING_FAILED;
2311178e 11120
5f5c8ee5
GM
11121 move_it_vertically (&it, - amount_to_scroll);
11122 startp = it.current.pos;
90adcf20
RS
11123 }
11124 }
a2889657 11125
5f5c8ee5
GM
11126 /* Run window scroll functions. */
11127 startp = run_window_scroll_functions (window, startp);
90adcf20 11128
5f5c8ee5
GM
11129 /* Display the window. Give up if new fonts are loaded, or if point
11130 doesn't appear. */
11131 if (!try_window (window, startp))
cb617e7c 11132 rc = SCROLLING_NEED_LARGER_MATRICES;
5f5c8ee5
GM
11133 else if (w->cursor.vpos < 0)
11134 {
11135 clear_glyph_matrix (w->desired_matrix);
cb617e7c 11136 rc = SCROLLING_FAILED;
5f5c8ee5
GM
11137 }
11138 else
11139 {
11140 /* Maybe forget recorded base line for line number display. */
2311178e 11141 if (!just_this_one_p
5f5c8ee5 11142 || current_buffer->clip_changed
9142dd5b 11143 || BEG_UNCHANGED < CHARPOS (startp))
5f5c8ee5 11144 w->base_line_number = Qnil;
2311178e 11145
ddf6b9a3
RS
11146 /* If cursor ends up on a partially visible line,
11147 treat that as being off the bottom of the screen. */
6b61353c 11148 if (! make_cursor_line_fully_visible (w, extra_scroll_margin_lines <= 1))
ef3c2c73
RS
11149 {
11150 clear_glyph_matrix (w->desired_matrix);
6b61353c 11151 ++extra_scroll_margin_lines;
ef3c2c73
RS
11152 goto too_near_end;
11153 }
ddf6b9a3 11154 rc = SCROLLING_SUCCESS;
5f5c8ee5
GM
11155 }
11156
11157 return rc;
a2889657
JB
11158}
11159
5f5c8ee5
GM
11160
11161/* Compute a suitable window start for window W if display of W starts
11162 on a continuation line. Value is non-zero if a new window start
11163 was computed.
11164
11165 The new window start will be computed, based on W's width, starting
11166 from the start of the continued line. It is the start of the
11167 screen line with the minimum distance from the old start W->start. */
11168
11169static int
11170compute_window_start_on_continuation_line (w)
11171 struct window *w;
1f1ff51d 11172{
5f5c8ee5
GM
11173 struct text_pos pos, start_pos;
11174 int window_start_changed_p = 0;
1f1ff51d 11175
5f5c8ee5 11176 SET_TEXT_POS_FROM_MARKER (start_pos, w->start);
1f1ff51d 11177
5f5c8ee5 11178 /* If window start is on a continuation line... Window start may be
2311178e 11179 < BEGV in case there's invisible text at the start of the
5f5c8ee5
GM
11180 buffer (M-x rmail, for example). */
11181 if (CHARPOS (start_pos) > BEGV
11182 && FETCH_BYTE (BYTEPOS (start_pos) - 1) != '\n')
1f1ff51d 11183 {
5f5c8ee5
GM
11184 struct it it;
11185 struct glyph_row *row;
f3751a65
GM
11186
11187 /* Handle the case that the window start is out of range. */
11188 if (CHARPOS (start_pos) < BEGV)
11189 SET_TEXT_POS (start_pos, BEGV, BEGV_BYTE);
11190 else if (CHARPOS (start_pos) > ZV)
11191 SET_TEXT_POS (start_pos, ZV, ZV_BYTE);
2311178e 11192
5f5c8ee5
GM
11193 /* Find the start of the continued line. This should be fast
11194 because scan_buffer is fast (newline cache). */
045dee35 11195 row = w->desired_matrix->rows + (WINDOW_WANTS_HEADER_LINE_P (w) ? 1 : 0);
5f5c8ee5
GM
11196 init_iterator (&it, w, CHARPOS (start_pos), BYTEPOS (start_pos),
11197 row, DEFAULT_FACE_ID);
11198 reseat_at_previous_visible_line_start (&it);
11199
11200 /* If the line start is "too far" away from the window start,
11201 say it takes too much time to compute a new window start. */
11202 if (CHARPOS (start_pos) - IT_CHARPOS (it)
da8b7f4f 11203 < WINDOW_TOTAL_LINES (w) * WINDOW_TOTAL_COLS (w))
5f5c8ee5
GM
11204 {
11205 int min_distance, distance;
2311178e 11206
5f5c8ee5
GM
11207 /* Move forward by display lines to find the new window
11208 start. If window width was enlarged, the new start can
11209 be expected to be > the old start. If window width was
11210 decreased, the new window start will be < the old start.
11211 So, we're looking for the display line start with the
11212 minimum distance from the old window start. */
11213 pos = it.current.pos;
11214 min_distance = INFINITY;
11215 while ((distance = abs (CHARPOS (start_pos) - IT_CHARPOS (it))),
11216 distance < min_distance)
11217 {
11218 min_distance = distance;
11219 pos = it.current.pos;
11220 move_it_by_lines (&it, 1, 0);
11221 }
2311178e 11222
5f5c8ee5
GM
11223 /* Set the window start there. */
11224 SET_MARKER_FROM_TEXT_POS (w->start, pos);
11225 window_start_changed_p = 1;
11226 }
1f1ff51d 11227 }
2311178e 11228
5f5c8ee5 11229 return window_start_changed_p;
1f1ff51d
KH
11230}
11231
5f5c8ee5 11232
1dd5768b 11233/* Try cursor movement in case text has not changed in window WINDOW,
47589c8c
GM
11234 with window start STARTP. Value is
11235
cb617e7c 11236 CURSOR_MOVEMENT_SUCCESS if successful
2311178e 11237
cb617e7c
GM
11238 CURSOR_MOVEMENT_CANNOT_BE_USED if this method cannot be used
11239
11240 CURSOR_MOVEMENT_MUST_SCROLL if we know we have to scroll the
11241 display. *SCROLL_STEP is set to 1, under certain circumstances, if
11242 we want to scroll as if scroll-step were set to 1. See the code.
11243
11244 CURSOR_MOVEMENT_NEED_LARGER_MATRICES if we need larger matrices, in
11245 which case we have to abort this redisplay, and adjust matrices
11246 first. */
11247
2311178e 11248enum
cb617e7c
GM
11249{
11250 CURSOR_MOVEMENT_SUCCESS,
11251 CURSOR_MOVEMENT_CANNOT_BE_USED,
11252 CURSOR_MOVEMENT_MUST_SCROLL,
11253 CURSOR_MOVEMENT_NEED_LARGER_MATRICES
11254};
47589c8c
GM
11255
11256static int
11257try_cursor_movement (window, startp, scroll_step)
11258 Lisp_Object window;
11259 struct text_pos startp;
11260 int *scroll_step;
11261{
11262 struct window *w = XWINDOW (window);
11263 struct frame *f = XFRAME (w->frame);
cb617e7c 11264 int rc = CURSOR_MOVEMENT_CANNOT_BE_USED;
2311178e 11265
69d1f7c9 11266#if GLYPH_DEBUG
76cb5e06
GM
11267 if (inhibit_try_cursor_movement)
11268 return rc;
11269#endif
11270
47589c8c
GM
11271 /* Handle case where text has not changed, only point, and it has
11272 not moved off the frame. */
11273 if (/* Point may be in this window. */
11274 PT >= CHARPOS (startp)
47589c8c
GM
11275 /* Selective display hasn't changed. */
11276 && !current_buffer->clip_changed
4db87380
GM
11277 /* Function force-mode-line-update is used to force a thorough
11278 redisplay. It sets either windows_or_buffers_changed or
11279 update_mode_lines. So don't take a shortcut here for these
11280 cases. */
11281 && !update_mode_lines
11282 && !windows_or_buffers_changed
5fb96e96 11283 && !cursor_type_changed
2311178e 11284 /* Can't use this case if highlighting a region. When a
47589c8c
GM
11285 region exists, cursor movement has to do more than just
11286 set the cursor. */
11287 && !(!NILP (Vtransient_mark_mode)
11288 && !NILP (current_buffer->mark_active))
11289 && NILP (w->region_showing)
11290 && NILP (Vshow_trailing_whitespace)
11291 /* Right after splitting windows, last_point may be nil. */
11292 && INTEGERP (w->last_point)
11293 /* This code is not used for mini-buffer for the sake of the case
11294 of redisplaying to replace an echo area message; since in
11295 that case the mini-buffer contents per se are usually
11296 unchanged. This code is of no real use in the mini-buffer
11297 since the handling of this_line_start_pos, etc., in redisplay
11298 handles the same cases. */
11299 && !EQ (window, minibuf_window)
11300 /* When splitting windows or for new windows, it happens that
11301 redisplay is called with a nil window_end_vpos or one being
11302 larger than the window. This should really be fixed in
11303 window.c. I don't have this on my list, now, so we do
11304 approximately the same as the old redisplay code. --gerd. */
11305 && INTEGERP (w->window_end_vpos)
11306 && XFASTINT (w->window_end_vpos) < w->current_matrix->nrows
11307 && (FRAME_WINDOW_P (f)
6b61353c 11308 || !overlay_arrow_in_current_buffer_p ()))
47589c8c
GM
11309 {
11310 int this_scroll_margin;
8ee5b6a3 11311 struct glyph_row *row = NULL;
47589c8c
GM
11312
11313#if GLYPH_DEBUG
11314 debug_method_add (w, "cursor movement");
11315#endif
11316
11317 /* Scroll if point within this distance from the top or bottom
11318 of the window. This is a pixel value. */
11319 this_scroll_margin = max (0, scroll_margin);
da8b7f4f
KS
11320 this_scroll_margin = min (this_scroll_margin, WINDOW_TOTAL_LINES (w) / 4);
11321 this_scroll_margin *= FRAME_LINE_HEIGHT (f);
47589c8c
GM
11322
11323 /* Start with the row the cursor was displayed during the last
11324 not paused redisplay. Give up if that row is not valid. */
bd9d0f3f
GM
11325 if (w->last_cursor.vpos < 0
11326 || w->last_cursor.vpos >= w->current_matrix->nrows)
cb617e7c 11327 rc = CURSOR_MOVEMENT_MUST_SCROLL;
47589c8c
GM
11328 else
11329 {
11330 row = MATRIX_ROW (w->current_matrix, w->last_cursor.vpos);
11331 if (row->mode_line_p)
11332 ++row;
11333 if (!row->enabled_p)
cb617e7c 11334 rc = CURSOR_MOVEMENT_MUST_SCROLL;
47589c8c
GM
11335 }
11336
cb617e7c 11337 if (rc == CURSOR_MOVEMENT_CANNOT_BE_USED)
47589c8c
GM
11338 {
11339 int scroll_p = 0;
68c5d1db 11340 int last_y = window_text_bottom_y (w) - this_scroll_margin;
2311178e 11341
47589c8c
GM
11342 if (PT > XFASTINT (w->last_point))
11343 {
11344 /* Point has moved forward. */
47589c8c
GM
11345 while (MATRIX_ROW_END_CHARPOS (row) < PT
11346 && MATRIX_ROW_BOTTOM_Y (row) < last_y)
11347 {
11348 xassert (row->enabled_p);
11349 ++row;
11350 }
11351
11352 /* The end position of a row equals the start position
11353 of the next row. If PT is there, we would rather
cafafe0b
GM
11354 display it in the next line. */
11355 while (MATRIX_ROW_BOTTOM_Y (row) < last_y
11356 && MATRIX_ROW_END_CHARPOS (row) == PT
11357 && !cursor_row_p (w, row))
11358 ++row;
47589c8c
GM
11359
11360 /* If within the scroll margin, scroll. Note that
11361 MATRIX_ROW_BOTTOM_Y gives the pixel position at which
11362 the next line would be drawn, and that
11363 this_scroll_margin can be zero. */
11364 if (MATRIX_ROW_BOTTOM_Y (row) > last_y
11365 || PT > MATRIX_ROW_END_CHARPOS (row)
11366 /* Line is completely visible last line in window
11367 and PT is to be set in the next line. */
11368 || (MATRIX_ROW_BOTTOM_Y (row) == last_y
11369 && PT == MATRIX_ROW_END_CHARPOS (row)
11370 && !row->ends_at_zv_p
11371 && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row)))
11372 scroll_p = 1;
11373 }
11374 else if (PT < XFASTINT (w->last_point))
11375 {
11376 /* Cursor has to be moved backward. Note that PT >=
11377 CHARPOS (startp) because of the outer
11378 if-statement. */
11379 while (!row->mode_line_p
11380 && (MATRIX_ROW_START_CHARPOS (row) > PT
11381 || (MATRIX_ROW_START_CHARPOS (row) == PT
11382 && MATRIX_ROW_STARTS_IN_MIDDLE_OF_CHAR_P (row)))
11383 && (row->y > this_scroll_margin
11384 || CHARPOS (startp) == BEGV))
11385 {
11386 xassert (row->enabled_p);
11387 --row;
11388 }
11389
11390 /* Consider the following case: Window starts at BEGV,
11391 there is invisible, intangible text at BEGV, so that
11392 display starts at some point START > BEGV. It can
11393 happen that we are called with PT somewhere between
11394 BEGV and START. Try to handle that case. */
11395 if (row < w->current_matrix->rows
11396 || row->mode_line_p)
11397 {
11398 row = w->current_matrix->rows;
11399 if (row->mode_line_p)
11400 ++row;
11401 }
11402
11403 /* Due to newlines in overlay strings, we may have to
11404 skip forward over overlay strings. */
68c5d1db
GM
11405 while (MATRIX_ROW_BOTTOM_Y (row) < last_y
11406 && MATRIX_ROW_END_CHARPOS (row) == PT
11407 && !cursor_row_p (w, row))
47589c8c 11408 ++row;
2311178e 11409
47589c8c
GM
11410 /* If within the scroll margin, scroll. */
11411 if (row->y < this_scroll_margin
11412 && CHARPOS (startp) != BEGV)
11413 scroll_p = 1;
11414 }
11415
11416 if (PT < MATRIX_ROW_START_CHARPOS (row)
11417 || PT > MATRIX_ROW_END_CHARPOS (row))
11418 {
11419 /* if PT is not in the glyph row, give up. */
cb617e7c 11420 rc = CURSOR_MOVEMENT_MUST_SCROLL;
47589c8c 11421 }
440fc135 11422 else if (MATRIX_ROW_PARTIALLY_VISIBLE_P (row))
47589c8c 11423 {
8de4aaf8
GM
11424 if (PT == MATRIX_ROW_END_CHARPOS (row)
11425 && !row->ends_at_zv_p
11426 && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row))
cb617e7c 11427 rc = CURSOR_MOVEMENT_MUST_SCROLL;
3f7e3031 11428 else if (row->height > window_box_height (w))
440fc135 11429 {
8de4aaf8
GM
11430 /* If we end up in a partially visible line, let's
11431 make it fully visible, except when it's taller
11432 than the window, in which case we can't do much
11433 about it. */
440fc135 11434 *scroll_step = 1;
cb617e7c 11435 rc = CURSOR_MOVEMENT_MUST_SCROLL;
440fc135
GM
11436 }
11437 else
11438 {
11439 set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0);
6b61353c 11440 if (!make_cursor_line_fully_visible (w, 0))
ddf6b9a3 11441 rc = CURSOR_MOVEMENT_MUST_SCROLL;
cb617e7c
GM
11442 else
11443 rc = CURSOR_MOVEMENT_SUCCESS;
440fc135 11444 }
47589c8c
GM
11445 }
11446 else if (scroll_p)
cb617e7c 11447 rc = CURSOR_MOVEMENT_MUST_SCROLL;
47589c8c
GM
11448 else
11449 {
11450 set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0);
cb617e7c 11451 rc = CURSOR_MOVEMENT_SUCCESS;
47589c8c
GM
11452 }
11453 }
11454 }
11455
11456 return rc;
11457}
11458
9a08d928
SM
11459void
11460set_vertical_scroll_bar (w)
11461 struct window *w;
11462{
11463 int start, end, whole;
11464
11465 /* Calculate the start and end positions for the current window.
11466 At some point, it would be nice to choose between scrollbars
11467 which reflect the whole buffer size, with special markers
11468 indicating narrowing, and scrollbars which reflect only the
11469 visible region.
6b61353c 11470
9a08d928
SM
11471 Note that mini-buffers sometimes aren't displaying any text. */
11472 if (!MINI_WINDOW_P (w)
11473 || (w == XWINDOW (minibuf_window)
11474 && NILP (echo_area_buffer[0])))
11475 {
11476 struct buffer *buf = XBUFFER (w->buffer);
11477 whole = BUF_ZV (buf) - BUF_BEGV (buf);
11478 start = marker_position (w->start) - BUF_BEGV (buf);
11479 /* I don't think this is guaranteed to be right. For the
11480 moment, we'll pretend it is. */
11481 end = BUF_Z (buf) - XFASTINT (w->window_end_pos) - BUF_BEGV (buf);
6b61353c 11482
9a08d928
SM
11483 if (end < start)
11484 end = start;
11485 if (whole < (end - start))
11486 whole = end - start;
11487 }
11488 else
11489 start = end = whole = 0;
11490
11491 /* Indicate what this scroll bar ought to be displaying now. */
11492 set_vertical_scroll_bar_hook (w, end - start, whole, start);
11493}
47589c8c 11494
6b61353c 11495
5f5c8ee5 11496/* Redisplay leaf window WINDOW. JUST_THIS_ONE_P non-zero means only
b60c9653
RS
11497 selected_window is redisplayed.
11498
11499 We can return without actually redisplaying the window if
11500 fonts_changed_p is nonzero. In that case, redisplay_internal will
11501 retry. */
90adcf20 11502
a2889657 11503static void
5f5c8ee5 11504redisplay_window (window, just_this_one_p)
a2889657 11505 Lisp_Object window;
5f5c8ee5 11506 int just_this_one_p;
a2889657 11507{
5f5c8ee5
GM
11508 struct window *w = XWINDOW (window);
11509 struct frame *f = XFRAME (w->frame);
11510 struct buffer *buffer = XBUFFER (w->buffer);
a2889657 11511 struct buffer *old = current_buffer;
5f5c8ee5 11512 struct text_pos lpoint, opoint, startp;
e481f960 11513 int update_mode_line;
5f5c8ee5
GM
11514 int tem;
11515 struct it it;
11516 /* Record it now because it's overwritten. */
11517 int current_matrix_up_to_date_p = 0;
6b61353c 11518 int used_current_matrix_p = 0;
c62c1bb5
RS
11519 /* This is less strict than current_matrix_up_to_date_p.
11520 It indictes that the buffer contents and narrowing are unchanged. */
11521 int buffer_unchanged_p = 0;
5f5c8ee5 11522 int temp_scroll_step = 0;
331379bf 11523 int count = SPECPDL_INDEX ();
47589c8c 11524 int rc;
ddf6b9a3 11525 int centering_position;
03b0a4b4 11526 int last_line_misfit = 0;
a2889657 11527
5f5c8ee5
GM
11528 SET_TEXT_POS (lpoint, PT, PT_BYTE);
11529 opoint = lpoint;
a2889657 11530
5f5c8ee5
GM
11531 /* W must be a leaf window here. */
11532 xassert (!NILP (w->buffer));
11533#if GLYPH_DEBUG
11534 *w->desired_matrix->method = 0;
11535#endif
2e54982e
RS
11536
11537 specbind (Qinhibit_point_motion_hooks, Qt);
9142dd5b
GM
11538
11539 reconsider_clip_changes (w, buffer);
2311178e
TTN
11540
11541 /* Has the mode line to be updated? */
5f5c8ee5
GM
11542 update_mode_line = (!NILP (w->update_mode_line)
11543 || update_mode_lines
c62c1bb5
RS
11544 || buffer->clip_changed
11545 || buffer->prevent_redisplay_optimizations_p);
8de2d90b
JB
11546
11547 if (MINI_WINDOW_P (w))
11548 {
5f5c8ee5 11549 if (w == XWINDOW (echo_area_window)
c6e89d6c 11550 && !NILP (echo_area_buffer[0]))
5f5c8ee5
GM
11551 {
11552 if (update_mode_line)
11553 /* We may have to update a tty frame's menu bar or a
e037b9ec 11554 tool-bar. Example `M-x C-h C-h C-g'. */
5f5c8ee5
GM
11555 goto finish_menu_bars;
11556 else
11557 /* We've already displayed the echo area glyphs in this window. */
11558 goto finish_scroll_bars;
11559 }
b2b5455d
RS
11560 else if ((w != XWINDOW (minibuf_window)
11561 || minibuf_level == 0)
c0bcce6f
JPW
11562 /* When buffer is nonempty, redisplay window normally. */
11563 && BUF_Z (XBUFFER (w->buffer)) == BUF_BEG (XBUFFER (w->buffer))
3354fdcf
RS
11564 /* Quail displays non-mini buffers in minibuffer window.
11565 In that case, redisplay the window normally. */
b2b5455d 11566 && !NILP (Fmemq (w->buffer, Vminibuffer_list)))
8de2d90b 11567 {
3354fdcf
RS
11568 /* W is a mini-buffer window, but it's not active, so clear
11569 it. */
5f5c8ee5
GM
11570 int yb = window_text_bottom_y (w);
11571 struct glyph_row *row;
11572 int y;
11573
11574 for (y = 0, row = w->desired_matrix->rows;
11575 y < yb;
11576 y += row->height, ++row)
11577 blank_row (w, row, y);
88f22aff 11578 goto finish_scroll_bars;
8de2d90b 11579 }
c095a1dd
GM
11580
11581 clear_glyph_matrix (w->desired_matrix);
8de2d90b 11582 }
a2889657 11583
5f5c8ee5
GM
11584 /* Otherwise set up data on this window; select its buffer and point
11585 value. */
6a93695f
GM
11586 /* Really select the buffer, for the sake of buffer-local
11587 variables. */
11588 set_buffer_internal_1 (XBUFFER (w->buffer));
5f5c8ee5
GM
11589 SET_TEXT_POS (opoint, PT, PT_BYTE);
11590
11591 current_matrix_up_to_date_p
11592 = (!NILP (w->window_end_valid)
11593 && !current_buffer->clip_changed
c62c1bb5 11594 && !current_buffer->prevent_redisplay_optimizations_p
5f5c8ee5
GM
11595 && XFASTINT (w->last_modified) >= MODIFF
11596 && XFASTINT (w->last_overlay_modified) >= OVERLAY_MODIFF);
e481f960 11597
c62c1bb5
RS
11598 buffer_unchanged_p
11599 = (!NILP (w->window_end_valid)
11600 && !current_buffer->clip_changed
3f1258d0 11601 && XFASTINT (w->last_modified) >= MODIFF
c62c1bb5
RS
11602 && XFASTINT (w->last_overlay_modified) >= OVERLAY_MODIFF);
11603
5f5c8ee5
GM
11604 /* When windows_or_buffers_changed is non-zero, we can't rely on
11605 the window end being valid, so set it to nil there. */
11606 if (windows_or_buffers_changed)
11607 {
11608 /* If window starts on a continuation line, maybe adjust the
11609 window start in case the window's width changed. */
11610 if (XMARKER (w->start)->buffer == current_buffer)
11611 compute_window_start_on_continuation_line (w);
2311178e 11612
5f5c8ee5
GM
11613 w->window_end_valid = Qnil;
11614 }
12adba34 11615
5f5c8ee5
GM
11616 /* Some sanity checks. */
11617 CHECK_WINDOW_END (w);
11618 if (Z == Z_BYTE && CHARPOS (opoint) != BYTEPOS (opoint))
12adba34 11619 abort ();
5f5c8ee5 11620 if (BYTEPOS (opoint) < CHARPOS (opoint))
12adba34 11621 abort ();
a2889657 11622
28995e67
RS
11623 /* If %c is in mode line, update it if needed. */
11624 if (!NILP (w->column_number_displayed)
11625 /* This alternative quickly identifies a common case
11626 where no change is needed. */
11627 && !(PT == XFASTINT (w->last_point)
8850a573
RS
11628 && XFASTINT (w->last_modified) >= MODIFF
11629 && XFASTINT (w->last_overlay_modified) >= OVERLAY_MODIFF)
2311178e
TTN
11630 && (XFASTINT (w->column_number_displayed)
11631 != (int) current_column ())) /* iftc */
11632 update_mode_line = 1;
28995e67 11633
5f5c8ee5
GM
11634 /* Count number of windows showing the selected buffer. An indirect
11635 buffer counts as its base buffer. */
11636 if (!just_this_one_p)
42640f83
RS
11637 {
11638 struct buffer *current_base, *window_base;
11639 current_base = current_buffer;
11640 window_base = XBUFFER (XWINDOW (selected_window)->buffer);
11641 if (current_base->base_buffer)
11642 current_base = current_base->base_buffer;
11643 if (window_base->base_buffer)
11644 window_base = window_base->base_buffer;
11645 if (current_base == window_base)
11646 buffer_shared++;
11647 }
a2889657 11648
5f5c8ee5
GM
11649 /* Point refers normally to the selected window. For any other
11650 window, set up appropriate value. */
a2889657
JB
11651 if (!EQ (window, selected_window))
11652 {
12adba34
RS
11653 int new_pt = XMARKER (w->pointm)->charpos;
11654 int new_pt_byte = marker_byte_position (w->pointm);
f67a0f51 11655 if (new_pt < BEGV)
a2889657 11656 {
f67a0f51 11657 new_pt = BEGV;
12adba34
RS
11658 new_pt_byte = BEGV_BYTE;
11659 set_marker_both (w->pointm, Qnil, BEGV, BEGV_BYTE);
a2889657 11660 }
f67a0f51 11661 else if (new_pt > (ZV - 1))
a2889657 11662 {
f67a0f51 11663 new_pt = ZV;
12adba34
RS
11664 new_pt_byte = ZV_BYTE;
11665 set_marker_both (w->pointm, Qnil, ZV, ZV_BYTE);
a2889657 11666 }
2311178e 11667
f67a0f51 11668 /* We don't use SET_PT so that the point-motion hooks don't run. */
12adba34 11669 TEMP_SET_PT_BOTH (new_pt, new_pt_byte);
a2889657
JB
11670 }
11671
f4faa47c 11672 /* If any of the character widths specified in the display table
5f5c8ee5
GM
11673 have changed, invalidate the width run cache. It's true that
11674 this may be a bit late to catch such changes, but the rest of
f4faa47c
JB
11675 redisplay goes (non-fatally) haywire when the display table is
11676 changed, so why should we worry about doing any better? */
11677 if (current_buffer->width_run_cache)
11678 {
f908610f 11679 struct Lisp_Char_Table *disptab = buffer_display_table ();
f4faa47c
JB
11680
11681 if (! disptab_matches_widthtab (disptab,
11682 XVECTOR (current_buffer->width_table)))
11683 {
11684 invalidate_region_cache (current_buffer,
11685 current_buffer->width_run_cache,
11686 BEG, Z);
11687 recompute_width_table (current_buffer, disptab);
11688 }
11689 }
11690
a2889657 11691 /* If window-start is screwed up, choose a new one. */
a2889657
JB
11692 if (XMARKER (w->start)->buffer != current_buffer)
11693 goto recenter;
11694
5f5c8ee5 11695 SET_TEXT_POS_FROM_MARKER (startp, w->start);
a2889657 11696
cf0df6ab
RS
11697 /* If someone specified a new starting point but did not insist,
11698 check whether it can be used. */
cfad01b4
GM
11699 if (!NILP (w->optional_new_start)
11700 && CHARPOS (startp) >= BEGV
11701 && CHARPOS (startp) <= ZV)
cf0df6ab
RS
11702 {
11703 w->optional_new_start = Qnil;
5f5c8ee5
GM
11704 start_display (&it, w, startp);
11705 move_it_to (&it, PT, 0, it.last_visible_y, -1,
11706 MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
11707 if (IT_CHARPOS (it) == PT)
cf0df6ab 11708 w->force_start = Qt;
6b61353c
KH
11709 /* IT may overshoot PT if text at PT is invisible. */
11710 else if (IT_CHARPOS (it) > PT && CHARPOS (startp) <= PT)
11711 w->force_start = Qt;
11712
11713
cf0df6ab
RS
11714 }
11715
8de2d90b 11716 /* Handle case where place to start displaying has been specified,
aa6d10fa 11717 unless the specified location is outside the accessible range. */
9472f927
GM
11718 if (!NILP (w->force_start)
11719 || w->frozen_window_start_p)
a2889657 11720 {
b60c9653
RS
11721 /* We set this later on if we have to adjust point. */
11722 int new_vpos = -1;
11723
e63574d7 11724 w->force_start = Qnil;
5f5c8ee5 11725 w->vscroll = 0;
b5174a51 11726 w->window_end_valid = Qnil;
5f5c8ee5
GM
11727
11728 /* Forget any recorded base line for line number display. */
c62c1bb5 11729 if (!buffer_unchanged_p)
5f5c8ee5
GM
11730 w->base_line_number = Qnil;
11731
75c43375
RS
11732 /* Redisplay the mode line. Select the buffer properly for that.
11733 Also, run the hook window-scroll-functions
11734 because we have scrolled. */
e63574d7
RS
11735 /* Note, we do this after clearing force_start because
11736 if there's an error, it is better to forget about force_start
11737 than to get into an infinite loop calling the hook functions
11738 and having them get more errors. */
75c43375
RS
11739 if (!update_mode_line
11740 || ! NILP (Vwindow_scroll_functions))
e481f960 11741 {
e481f960
RS
11742 update_mode_line = 1;
11743 w->update_mode_line = Qt;
5f5c8ee5 11744 startp = run_window_scroll_functions (window, startp);
e481f960 11745 }
2311178e 11746
ac90c44f
GM
11747 w->last_modified = make_number (0);
11748 w->last_overlay_modified = make_number (0);
5f5c8ee5
GM
11749 if (CHARPOS (startp) < BEGV)
11750 SET_TEXT_POS (startp, BEGV, BEGV_BYTE);
11751 else if (CHARPOS (startp) > ZV)
11752 SET_TEXT_POS (startp, ZV, ZV_BYTE);
2311178e
TTN
11753
11754 /* Redisplay, then check if cursor has been set during the
5f5c8ee5
GM
11755 redisplay. Give up if new fonts were loaded. */
11756 if (!try_window (window, startp))
11757 {
11758 w->force_start = Qt;
11759 clear_glyph_matrix (w->desired_matrix);
b60c9653 11760 goto need_larger_matrices;
5f5c8ee5
GM
11761 }
11762
9472f927 11763 if (w->cursor.vpos < 0 && !w->frozen_window_start_p)
5f5c8ee5 11764 {
b28cb6ed
GM
11765 /* If point does not appear, try to move point so it does
11766 appear. The desired matrix has been built above, so we
11767 can use it here. */
b60c9653
RS
11768 new_vpos = window_box_height (w) / 2;
11769 }
11770
6b61353c 11771 if (!make_cursor_line_fully_visible (w, 0))
b60c9653
RS
11772 {
11773 /* Point does appear, but on a line partly visible at end of window.
11774 Move it back to a fully-visible line. */
11775 new_vpos = window_box_height (w);
11776 }
11777
11778 /* If we need to move point for either of the above reasons,
11779 now actually do it. */
11780 if (new_vpos >= 0)
11781 {
b28cb6ed
GM
11782 struct glyph_row *row;
11783
b28cb6ed 11784 row = MATRIX_FIRST_TEXT_ROW (w->desired_matrix);
b60c9653 11785 while (MATRIX_ROW_BOTTOM_Y (row) < new_vpos)
5f5c8ee5
GM
11786 ++row;
11787
11788 TEMP_SET_PT_BOTH (MATRIX_ROW_START_CHARPOS (row),
11789 MATRIX_ROW_START_BYTEPOS (row));
11790
90adcf20 11791 if (w != XWINDOW (selected_window))
12adba34 11792 set_marker_both (w->pointm, Qnil, PT, PT_BYTE);
5f5c8ee5
GM
11793 else if (current_buffer == old)
11794 SET_TEXT_POS (lpoint, PT, PT_BYTE);
11795
11796 set_cursor_from_row (w, row, w->desired_matrix, 0, 0, 0, 0);
2311178e 11797
5f5c8ee5
GM
11798 /* If we are highlighting the region, then we just changed
11799 the region, so redisplay to show it. */
df0b5ea1
RS
11800 if (!NILP (Vtransient_mark_mode)
11801 && !NILP (current_buffer->mark_active))
6f27fa9b 11802 {
5f5c8ee5
GM
11803 clear_glyph_matrix (w->desired_matrix);
11804 if (!try_window (window, startp))
cb617e7c 11805 goto need_larger_matrices;
6f27fa9b 11806 }
a2889657 11807 }
5f5c8ee5 11808
5f5c8ee5
GM
11809#if GLYPH_DEBUG
11810 debug_method_add (w, "forced window start");
11811#endif
a2889657
JB
11812 goto done;
11813 }
11814
5f5c8ee5 11815 /* Handle case where text has not changed, only point, and it has
3f029ea0
RS
11816 not moved off the frame, and we are not retrying after hscroll.
11817 (current_matrix_up_to_date_p is nonzero when retrying.) */
11818 if (current_matrix_up_to_date_p
47589c8c 11819 && (rc = try_cursor_movement (window, startp, &temp_scroll_step),
cb617e7c 11820 rc != CURSOR_MOVEMENT_CANNOT_BE_USED))
a2889657 11821 {
cb617e7c
GM
11822 switch (rc)
11823 {
11824 case CURSOR_MOVEMENT_SUCCESS:
6b61353c 11825 used_current_matrix_p = 1;
cb617e7c 11826 goto done;
2311178e 11827
b60c9653 11828#if 0 /* try_cursor_movement never returns this value. */
cb617e7c
GM
11829 case CURSOR_MOVEMENT_NEED_LARGER_MATRICES:
11830 goto need_larger_matrices;
b60c9653 11831#endif
2311178e 11832
cb617e7c
GM
11833 case CURSOR_MOVEMENT_MUST_SCROLL:
11834 goto try_to_scroll;
2311178e 11835
cb617e7c
GM
11836 default:
11837 abort ();
11838 }
a2889657
JB
11839 }
11840 /* If current starting point was originally the beginning of a line
11841 but no longer is, find a new starting point. */
265a9e55 11842 else if (!NILP (w->start_at_line_beg)
5f5c8ee5
GM
11843 && !(CHARPOS (startp) <= BEGV
11844 || FETCH_BYTE (BYTEPOS (startp) - 1) == '\n'))
a2889657 11845 {
5f5c8ee5
GM
11846#if GLYPH_DEBUG
11847 debug_method_add (w, "recenter 1");
11848#endif
a2889657
JB
11849 goto recenter;
11850 }
2311178e 11851
27d16f05
GM
11852 /* Try scrolling with try_window_id. Value is > 0 if update has
11853 been done, it is -1 if we know that the same window start will
11854 not work. It is 0 if unsuccessful for some other reason. */
11855 else if ((tem = try_window_id (w)) != 0)
a2889657 11856 {
5f5c8ee5 11857#if GLYPH_DEBUG
ef121659 11858 debug_method_add (w, "try_window_id %d", tem);
5f5c8ee5
GM
11859#endif
11860
11861 if (fonts_changed_p)
cb617e7c 11862 goto need_larger_matrices;
a2889657
JB
11863 if (tem > 0)
11864 goto done;
ef121659 11865
5f5c8ee5
GM
11866 /* Otherwise try_window_id has returned -1 which means that we
11867 don't want the alternative below this comment to execute. */
a2889657 11868 }
5f5c8ee5
GM
11869 else if (CHARPOS (startp) >= BEGV
11870 && CHARPOS (startp) <= ZV
11871 && PT >= CHARPOS (startp)
11872 && (CHARPOS (startp) < ZV
e9874cee 11873 /* Avoid starting at end of buffer. */
5f5c8ee5 11874 || CHARPOS (startp) == BEGV
8850a573
RS
11875 || (XFASTINT (w->last_modified) >= MODIFF
11876 && XFASTINT (w->last_overlay_modified) >= OVERLAY_MODIFF)))
a2889657 11877 {
5f5c8ee5
GM
11878#if GLYPH_DEBUG
11879 debug_method_add (w, "same window start");
11880#endif
2311178e 11881
5f5c8ee5
GM
11882 /* Try to redisplay starting at same place as before.
11883 If point has not moved off frame, accept the results. */
11884 if (!current_matrix_up_to_date_p
11885 /* Don't use try_window_reusing_current_matrix in this case
15e26c76
GM
11886 because a window scroll function can have changed the
11887 buffer. */
5f5c8ee5
GM
11888 || !NILP (Vwindow_scroll_functions)
11889 || MINI_WINDOW_P (w)
6b61353c
KH
11890 || !(used_current_matrix_p =
11891 try_window_reusing_current_matrix (w)))
5f5c8ee5
GM
11892 {
11893 IF_DEBUG (debug_method_add (w, "1"));
11894 try_window (window, startp);
11895 }
11896
11897 if (fonts_changed_p)
cb617e7c 11898 goto need_larger_matrices;
2311178e 11899
5f5c8ee5 11900 if (w->cursor.vpos >= 0)
aa6d10fa 11901 {
2311178e 11902 if (!just_this_one_p
5f5c8ee5 11903 || current_buffer->clip_changed
9142dd5b 11904 || BEG_UNCHANGED < CHARPOS (startp))
aa6d10fa
RS
11905 /* Forget any recorded base line for line number display. */
11906 w->base_line_number = Qnil;
2311178e 11907
6b61353c 11908 if (!make_cursor_line_fully_visible (w, 1))
03b0a4b4
RS
11909 {
11910 clear_glyph_matrix (w->desired_matrix);
11911 last_line_misfit = 1;
11912 }
ddf6b9a3 11913 /* Drop through and scroll. */
ef3c2c73
RS
11914 else
11915 goto done;
aa6d10fa 11916 }
a2889657 11917 else
5f5c8ee5 11918 clear_glyph_matrix (w->desired_matrix);
a2889657
JB
11919 }
11920
5f5c8ee5
GM
11921 try_to_scroll:
11922
ac90c44f
GM
11923 w->last_modified = make_number (0);
11924 w->last_overlay_modified = make_number (0);
5f5c8ee5 11925
e481f960
RS
11926 /* Redisplay the mode line. Select the buffer properly for that. */
11927 if (!update_mode_line)
11928 {
e481f960
RS
11929 update_mode_line = 1;
11930 w->update_mode_line = Qt;
11931 }
a2889657 11932
5f5c8ee5
GM
11933 /* Try to scroll by specified few lines. */
11934 if ((scroll_conservatively
11935 || scroll_step
11936 || temp_scroll_step
11937 || NUMBERP (current_buffer->scroll_up_aggressively)
11938 || NUMBERP (current_buffer->scroll_down_aggressively))
09cacf9c 11939 && !current_buffer->clip_changed
2311178e 11940 && CHARPOS (startp) >= BEGV
5f5c8ee5 11941 && CHARPOS (startp) <= ZV)
0789adb2 11942 {
5f5c8ee5
GM
11943 /* The function returns -1 if new fonts were loaded, 1 if
11944 successful, 0 if not successful. */
11945 int rc = try_scrolling (window, just_this_one_p,
11946 scroll_conservatively,
11947 scroll_step,
03b0a4b4 11948 temp_scroll_step, last_line_misfit);
cb617e7c
GM
11949 switch (rc)
11950 {
11951 case SCROLLING_SUCCESS:
11952 goto done;
2311178e 11953
cb617e7c
GM
11954 case SCROLLING_NEED_LARGER_MATRICES:
11955 goto need_larger_matrices;
2311178e 11956
cb617e7c
GM
11957 case SCROLLING_FAILED:
11958 break;
2311178e 11959
cb617e7c
GM
11960 default:
11961 abort ();
11962 }
5f5c8ee5 11963 }
f9c8af06 11964
5f5c8ee5 11965 /* Finally, just choose place to start which centers point */
5936754e 11966
5f5c8ee5 11967 recenter:
ddf6b9a3
RS
11968 centering_position = window_box_height (w) / 2;
11969
11970 point_at_top:
11971 /* Jump here with centering_position already set to 0. */
44173109 11972
5f5c8ee5
GM
11973#if GLYPH_DEBUG
11974 debug_method_add (w, "recenter");
11975#endif
0789adb2 11976
5f5c8ee5 11977 /* w->vscroll = 0; */
0789adb2 11978
5f5c8ee5 11979 /* Forget any previously recorded base line for line number display. */
c62c1bb5 11980 if (!buffer_unchanged_p)
5f5c8ee5
GM
11981 w->base_line_number = Qnil;
11982
11983 /* Move backward half the height of the window. */
11984 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
11985 it.current_y = it.last_visible_y;
ddf6b9a3 11986 move_it_vertically_backward (&it, centering_position);
5f5c8ee5
GM
11987 xassert (IT_CHARPOS (it) >= BEGV);
11988
11989 /* The function move_it_vertically_backward may move over more
11990 than the specified y-distance. If it->w is small, e.g. a
11991 mini-buffer window, we may end up in front of the window's
11992 display area. Start displaying at the start of the line
11993 containing PT in this case. */
11994 if (it.current_y <= 0)
11995 {
11996 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
11997 move_it_vertically (&it, 0);
11998 xassert (IT_CHARPOS (it) <= PT);
11999 it.current_y = 0;
0789adb2
RS
12000 }
12001
5f5c8ee5 12002 it.current_x = it.hpos = 0;
2311178e 12003
5f5c8ee5
GM
12004 /* Set startp here explicitly in case that helps avoid an infinite loop
12005 in case the window-scroll-functions functions get errors. */
12006 set_marker_both (w->start, Qnil, IT_CHARPOS (it), IT_BYTEPOS (it));
12007
12008 /* Run scroll hooks. */
12009 startp = run_window_scroll_functions (window, it.current.pos);
12010
12011 /* Redisplay the window. */
12012 if (!current_matrix_up_to_date_p
12013 || windows_or_buffers_changed
5fb96e96 12014 || cursor_type_changed
5f5c8ee5
GM
12015 /* Don't use try_window_reusing_current_matrix in this case
12016 because it can have changed the buffer. */
12017 || !NILP (Vwindow_scroll_functions)
12018 || !just_this_one_p
12019 || MINI_WINDOW_P (w)
6b61353c
KH
12020 || !(used_current_matrix_p =
12021 try_window_reusing_current_matrix (w)))
5f5c8ee5
GM
12022 try_window (window, startp);
12023
12024 /* If new fonts have been loaded (due to fontsets), give up. We
12025 have to start a new redisplay since we need to re-adjust glyph
12026 matrices. */
12027 if (fonts_changed_p)
cb617e7c 12028 goto need_larger_matrices;
5f5c8ee5
GM
12029
12030 /* If cursor did not appear assume that the middle of the window is
12031 in the first line of the window. Do it again with the next line.
12032 (Imagine a window of height 100, displaying two lines of height
12033 60. Moving back 50 from it->last_visible_y will end in the first
12034 line.) */
12035 if (w->cursor.vpos < 0)
a2889657 12036 {
5f5c8ee5
GM
12037 if (!NILP (w->window_end_valid)
12038 && PT >= Z - XFASTINT (w->window_end_pos))
a2889657 12039 {
5f5c8ee5
GM
12040 clear_glyph_matrix (w->desired_matrix);
12041 move_it_by_lines (&it, 1, 0);
12042 try_window (window, it.current.pos);
a2889657 12043 }
5f5c8ee5 12044 else if (PT < IT_CHARPOS (it))
a2889657 12045 {
5f5c8ee5
GM
12046 clear_glyph_matrix (w->desired_matrix);
12047 move_it_by_lines (&it, -1, 0);
12048 try_window (window, it.current.pos);
12049 }
12050 else
12051 {
12052 /* Not much we can do about it. */
a2889657 12053 }
a2889657 12054 }
010494d0 12055
5f5c8ee5
GM
12056 /* Consider the following case: Window starts at BEGV, there is
12057 invisible, intangible text at BEGV, so that display starts at
12058 some point START > BEGV. It can happen that we are called with
12059 PT somewhere between BEGV and START. Try to handle that case. */
12060 if (w->cursor.vpos < 0)
835766b6 12061 {
5f5c8ee5
GM
12062 struct glyph_row *row = w->current_matrix->rows;
12063 if (row->mode_line_p)
12064 ++row;
12065 set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0);
835766b6 12066 }
2311178e 12067
6b61353c 12068 if (!make_cursor_line_fully_visible (w, centering_position > 0))
ddf6b9a3 12069 {
932357b4
KS
12070 /* If vscroll is enabled, disable it and try again. */
12071 if (w->vscroll)
12072 {
12073 w->vscroll = 0;
12074 clear_glyph_matrix (w->desired_matrix);
12075 goto recenter;
12076 }
2a6d0874 12077
ddf6b9a3
RS
12078 /* If centering point failed to make the whole line visible,
12079 put point at the top instead. That has to make the whole line
12080 visible, if it can be done. */
6b61353c 12081 clear_glyph_matrix (w->desired_matrix);
ddf6b9a3
RS
12082 centering_position = 0;
12083 goto point_at_top;
12084 }
b5174a51 12085
74d481ac
GM
12086 done:
12087
5f5c8ee5
GM
12088 SET_TEXT_POS_FROM_MARKER (startp, w->start);
12089 w->start_at_line_beg = ((CHARPOS (startp) == BEGV
12090 || FETCH_BYTE (BYTEPOS (startp) - 1) == '\n')
12091 ? Qt : Qnil);
a2889657 12092
5f5c8ee5 12093 /* Display the mode line, if we must. */
e481f960 12094 if ((update_mode_line
aa6d10fa 12095 /* If window not full width, must redo its mode line
2311178e 12096 if (a) the window to its side is being redone and
5f5c8ee5
GM
12097 (b) we do a frame-based redisplay. This is a consequence
12098 of how inverted lines are drawn in frame-based redisplay. */
2311178e 12099 || (!just_this_one_p
5f5c8ee5
GM
12100 && !FRAME_WINDOW_P (f)
12101 && !WINDOW_FULL_WIDTH_P (w))
12102 /* Line number to display. */
155ef550 12103 || INTEGERP (w->base_line_pos)
5f5c8ee5 12104 /* Column number is displayed and different from the one displayed. */
155ef550 12105 || (!NILP (w->column_number_displayed)
2311178e
TTN
12106 && (XFASTINT (w->column_number_displayed)
12107 != (int) current_column ()))) /* iftc */
5f5c8ee5
GM
12108 /* This means that the window has a mode line. */
12109 && (WINDOW_WANTS_MODELINE_P (w)
045dee35 12110 || WINDOW_WANTS_HEADER_LINE_P (w)))
5ba50c51 12111 {
5f5c8ee5
GM
12112 display_mode_lines (w);
12113
12114 /* If mode line height has changed, arrange for a thorough
12115 immediate redisplay using the correct mode line height. */
12116 if (WINDOW_WANTS_MODELINE_P (w)
12117 && CURRENT_MODE_LINE_HEIGHT (w) != DESIRED_MODE_LINE_HEIGHT (w))
5ba50c51 12118 {
5f5c8ee5
GM
12119 fonts_changed_p = 1;
12120 MATRIX_MODE_LINE_ROW (w->current_matrix)->height
12121 = DESIRED_MODE_LINE_HEIGHT (w);
5ba50c51 12122 }
2311178e 12123
5f5c8ee5
GM
12124 /* If top line height has changed, arrange for a thorough
12125 immediate redisplay using the correct mode line height. */
045dee35
GM
12126 if (WINDOW_WANTS_HEADER_LINE_P (w)
12127 && CURRENT_HEADER_LINE_HEIGHT (w) != DESIRED_HEADER_LINE_HEIGHT (w))
5f5c8ee5
GM
12128 {
12129 fonts_changed_p = 1;
045dee35
GM
12130 MATRIX_HEADER_LINE_ROW (w->current_matrix)->height
12131 = DESIRED_HEADER_LINE_HEIGHT (w);
5f5c8ee5
GM
12132 }
12133
12134 if (fonts_changed_p)
cb617e7c 12135 goto need_larger_matrices;
5ba50c51 12136 }
5f5c8ee5
GM
12137
12138 if (!line_number_displayed
12139 && !BUFFERP (w->base_line_pos))
aa6d10fa
RS
12140 {
12141 w->base_line_pos = Qnil;
12142 w->base_line_number = Qnil;
12143 }
a2889657 12144
5f5c8ee5 12145 finish_menu_bars:
2311178e 12146
7ce2c095 12147 /* When we reach a frame's selected window, redo the frame's menu bar. */
e481f960 12148 if (update_mode_line
5f5c8ee5
GM
12149 && EQ (FRAME_SELECTED_WINDOW (f), window))
12150 {
12151 int redisplay_menu_p = 0;
488dd4c4 12152 int redisplay_tool_bar_p = 0;
5f5c8ee5
GM
12153
12154 if (FRAME_WINDOW_P (f))
12155 {
488dd4c4
JD
12156#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (MAC_OS) \
12157 || defined (USE_GTK)
5f5c8ee5 12158 redisplay_menu_p = FRAME_EXTERNAL_MENU_BAR (f);
76412d64 12159#else
5f5c8ee5 12160 redisplay_menu_p = FRAME_MENU_BAR_LINES (f) > 0;
76412d64 12161#endif
5f5c8ee5
GM
12162 }
12163 else
12164 redisplay_menu_p = FRAME_MENU_BAR_LINES (f) > 0;
12165
12166 if (redisplay_menu_p)
12167 display_menu_bar (w);
12168
12169#ifdef HAVE_WINDOW_SYSTEM
488dd4c4
JD
12170#ifdef USE_GTK
12171 redisplay_tool_bar_p = FRAME_EXTERNAL_TOOL_BAR (f);
12172#else
12173 redisplay_tool_bar_p = WINDOWP (f->tool_bar_window)
12174 && (FRAME_TOOL_BAR_LINES (f) > 0
12175 || auto_resize_tool_bars_p);
177c0ea7 12176
488dd4c4
JD
12177#endif
12178
12179 if (redisplay_tool_bar_p)
12180 redisplay_tool_bar (f);
5f5c8ee5
GM
12181#endif
12182 }
7ce2c095 12183
6b61353c
KH
12184#ifdef HAVE_WINDOW_SYSTEM
12185 if (update_window_fringes (w, 0)
12186 && !just_this_one_p
12187 && (used_current_matrix_p || overlay_arrow_seen)
12188 && !w->pseudo_window_p)
12189 {
12190 update_begin (f);
12191 BLOCK_INPUT;
12192 draw_window_fringes (w);
12193 UNBLOCK_INPUT;
12194 update_end (f);
12195 }
12196#endif /* HAVE_WINDOW_SYSTEM */
12197
b60c9653
RS
12198 /* We go to this label, with fonts_changed_p nonzero,
12199 if it is necessary to try again using larger glyph matrices.
12200 We have to redeem the scroll bar even in this case,
12201 because the loop in redisplay_internal expects that. */
cb617e7c
GM
12202 need_larger_matrices:
12203 ;
88f22aff 12204 finish_scroll_bars:
5f5c8ee5 12205
da8b7f4f 12206 if (WINDOW_HAS_VERTICAL_SCROLL_BAR (w))
30c566e4 12207 {
9a08d928
SM
12208 /* Set the thumb's position and size. */
12209 set_vertical_scroll_bar (w);
30c566e4 12210
5f5c8ee5
GM
12211 /* Note that we actually used the scroll bar attached to this
12212 window, so it shouldn't be deleted at the end of redisplay. */
504454e8 12213 redeem_scroll_bar_hook (w);
30c566e4 12214 }
b1d1124b 12215
5f5c8ee5
GM
12216 /* Restore current_buffer and value of point in it. */
12217 TEMP_SET_PT_BOTH (CHARPOS (opoint), BYTEPOS (opoint));
6a93695f 12218 set_buffer_internal_1 (old);
5f5c8ee5 12219 TEMP_SET_PT_BOTH (CHARPOS (lpoint), BYTEPOS (lpoint));
2e54982e
RS
12220
12221 unbind_to (count, Qnil);
a2889657 12222}
a2889657 12223
5f5c8ee5
GM
12224
12225/* Build the complete desired matrix of WINDOW with a window start
12226 buffer position POS. Value is non-zero if successful. It is zero
12227 if fonts were loaded during redisplay which makes re-adjusting
12228 glyph matrices necessary. */
12229
12230int
a2889657
JB
12231try_window (window, pos)
12232 Lisp_Object window;
5f5c8ee5
GM
12233 struct text_pos pos;
12234{
12235 struct window *w = XWINDOW (window);
12236 struct it it;
12237 struct glyph_row *last_text_row = NULL;
9cbab4ff 12238
5f5c8ee5
GM
12239 /* Make POS the new window start. */
12240 set_marker_both (w->start, Qnil, CHARPOS (pos), BYTEPOS (pos));
12adba34 12241
5f5c8ee5
GM
12242 /* Mark cursor position as unknown. No overlay arrow seen. */
12243 w->cursor.vpos = -1;
a2889657 12244 overlay_arrow_seen = 0;
642eefc6 12245
5f5c8ee5
GM
12246 /* Initialize iterator and info to start at POS. */
12247 start_display (&it, w, pos);
a2889657 12248
5f5c8ee5
GM
12249 /* Display all lines of W. */
12250 while (it.current_y < it.last_visible_y)
12251 {
12252 if (display_line (&it))
12253 last_text_row = it.glyph_row - 1;
12254 if (fonts_changed_p)
12255 return 0;
12256 }
a2889657 12257
5f5c8ee5
GM
12258 /* If bottom moved off end of frame, change mode line percentage. */
12259 if (XFASTINT (w->window_end_pos) <= 0
12260 && Z != IT_CHARPOS (it))
a2889657
JB
12261 w->update_mode_line = Qt;
12262
5f5c8ee5
GM
12263 /* Set window_end_pos to the offset of the last character displayed
12264 on the window from the end of current_buffer. Set
12265 window_end_vpos to its row number. */
12266 if (last_text_row)
12267 {
12268 xassert (MATRIX_ROW_DISPLAYS_TEXT_P (last_text_row));
12269 w->window_end_bytepos
12270 = Z_BYTE - MATRIX_ROW_END_BYTEPOS (last_text_row);
ac90c44f
GM
12271 w->window_end_pos
12272 = make_number (Z - MATRIX_ROW_END_CHARPOS (last_text_row));
12273 w->window_end_vpos
12274 = make_number (MATRIX_ROW_VPOS (last_text_row, w->desired_matrix));
5f5c8ee5
GM
12275 xassert (MATRIX_ROW (w->desired_matrix, XFASTINT (w->window_end_vpos))
12276 ->displays_text_p);
12277 }
12278 else
12279 {
86bf3faa
RS
12280 w->window_end_bytepos = Z_BYTE - ZV_BYTE;
12281 w->window_end_pos = make_number (Z - ZV);
12282 w->window_end_vpos = make_number (0);
5f5c8ee5 12283 }
2311178e 12284
a2889657
JB
12285 /* But that is not valid info until redisplay finishes. */
12286 w->window_end_valid = Qnil;
5f5c8ee5 12287 return 1;
a2889657 12288}
5f5c8ee5
GM
12289
12290
a2889657 12291\f
5f5c8ee5
GM
12292/************************************************************************
12293 Window redisplay reusing current matrix when buffer has not changed
12294 ************************************************************************/
12295
12296/* Try redisplay of window W showing an unchanged buffer with a
12297 different window start than the last time it was displayed by
12298 reusing its current matrix. Value is non-zero if successful.
12299 W->start is the new window start. */
a2889657
JB
12300
12301static int
5f5c8ee5
GM
12302try_window_reusing_current_matrix (w)
12303 struct window *w;
a2889657 12304{
5f5c8ee5
GM
12305 struct frame *f = XFRAME (w->frame);
12306 struct glyph_row *row, *bottom_row;
12307 struct it it;
12308 struct run run;
12309 struct text_pos start, new_start;
12310 int nrows_scrolled, i;
12311 struct glyph_row *last_text_row;
12312 struct glyph_row *last_reused_text_row;
12313 struct glyph_row *start_row;
12314 int start_vpos, min_y, max_y;
75c5350a 12315
69d1f7c9 12316#if GLYPH_DEBUG
76cb5e06
GM
12317 if (inhibit_try_window_reusing)
12318 return 0;
12319#endif
12320
d18354b6
GM
12321 if (/* This function doesn't handle terminal frames. */
12322 !FRAME_WINDOW_P (f)
12323 /* Don't try to reuse the display if windows have been split
12324 or such. */
5fb96e96
RS
12325 || windows_or_buffers_changed
12326 || cursor_type_changed)
5f5c8ee5 12327 return 0;
a2889657 12328
5f5c8ee5
GM
12329 /* Can't do this if region may have changed. */
12330 if ((!NILP (Vtransient_mark_mode)
12331 && !NILP (current_buffer->mark_active))
8f897821
GM
12332 || !NILP (w->region_showing)
12333 || !NILP (Vshow_trailing_whitespace))
5f5c8ee5 12334 return 0;
a2889657 12335
5f5c8ee5 12336 /* If top-line visibility has changed, give up. */
045dee35
GM
12337 if (WINDOW_WANTS_HEADER_LINE_P (w)
12338 != MATRIX_HEADER_LINE_ROW (w->current_matrix)->mode_line_p)
5f5c8ee5
GM
12339 return 0;
12340
12341 /* Give up if old or new display is scrolled vertically. We could
12342 make this function handle this, but right now it doesn't. */
12343 start_row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
12344 if (w->vscroll || MATRIX_ROW_PARTIALLY_VISIBLE_P (start_row))
12345 return 0;
12346
12347 /* The variable new_start now holds the new window start. The old
12348 start `start' can be determined from the current matrix. */
12349 SET_TEXT_POS_FROM_MARKER (new_start, w->start);
12350 start = start_row->start.pos;
12351 start_vpos = MATRIX_ROW_VPOS (start_row, w->current_matrix);
a2889657 12352
5f5c8ee5
GM
12353 /* Clear the desired matrix for the display below. */
12354 clear_glyph_matrix (w->desired_matrix);
2311178e 12355
5f5c8ee5
GM
12356 if (CHARPOS (new_start) <= CHARPOS (start))
12357 {
12358 int first_row_y;
2311178e 12359
607ec83c
GM
12360 /* Don't use this method if the display starts with an ellipsis
12361 displayed for invisible text. It's not easy to handle that case
12362 below, and it's certainly not worth the effort since this is
12363 not a frequent case. */
12364 if (in_ellipses_for_invisible_text_p (&start_row->start, w))
12365 return 0;
12366
5f5c8ee5 12367 IF_DEBUG (debug_method_add (w, "twu1"));
2311178e 12368
5f5c8ee5
GM
12369 /* Display up to a row that can be reused. The variable
12370 last_text_row is set to the last row displayed that displays
b48f74cb
GM
12371 text. Note that it.vpos == 0 if or if not there is a
12372 header-line; it's not the same as the MATRIX_ROW_VPOS! */
5f5c8ee5
GM
12373 start_display (&it, w, new_start);
12374 first_row_y = it.current_y;
12375 w->cursor.vpos = -1;
12376 last_text_row = last_reused_text_row = NULL;
2311178e 12377
5f5c8ee5
GM
12378 while (it.current_y < it.last_visible_y
12379 && IT_CHARPOS (it) < CHARPOS (start)
12380 && !fonts_changed_p)
12381 if (display_line (&it))
12382 last_text_row = it.glyph_row - 1;
12383
12384 /* A value of current_y < last_visible_y means that we stopped
12385 at the previous window start, which in turn means that we
12386 have at least one reusable row. */
12387 if (it.current_y < it.last_visible_y)
a2889657 12388 {
b48f74cb 12389 /* IT.vpos always starts from 0; it counts text lines. */
5f5c8ee5 12390 nrows_scrolled = it.vpos;
2311178e 12391
5f5c8ee5
GM
12392 /* Find PT if not already found in the lines displayed. */
12393 if (w->cursor.vpos < 0)
a2889657 12394 {
5f5c8ee5 12395 int dy = it.current_y - first_row_y;
2311178e 12396
5f5c8ee5 12397 row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
0df56f4d
GM
12398 row = row_containing_pos (w, PT, row, NULL, dy);
12399 if (row)
12400 set_cursor_from_row (w, row, w->current_matrix, 0, 0,
12401 dy, nrows_scrolled);
12402 else
5f5c8ee5
GM
12403 {
12404 clear_glyph_matrix (w->desired_matrix);
12405 return 0;
12406 }
a2889657 12407 }
5f5c8ee5
GM
12408
12409 /* Scroll the display. Do it before the current matrix is
12410 changed. The problem here is that update has not yet
12411 run, i.e. part of the current matrix is not up to date.
12412 scroll_run_hook will clear the cursor, and use the
12413 current matrix to get the height of the row the cursor is
12414 in. */
12415 run.current_y = first_row_y;
12416 run.desired_y = it.current_y;
12417 run.height = it.last_visible_y - it.current_y;
b48f74cb
GM
12418
12419 if (run.height > 0 && run.current_y != run.desired_y)
a2889657 12420 {
5f5c8ee5
GM
12421 update_begin (f);
12422 rif->update_window_begin_hook (w);
fa3c6b4d 12423 rif->clear_window_mouse_face (w);
5f5c8ee5 12424 rif->scroll_run_hook (w, &run);
64d1e7d3 12425 rif->update_window_end_hook (w, 0, 0);
5f5c8ee5 12426 update_end (f);
a2889657 12427 }
5f5c8ee5
GM
12428
12429 /* Shift current matrix down by nrows_scrolled lines. */
12430 bottom_row = MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w);
12431 rotate_matrix (w->current_matrix,
12432 start_vpos,
12433 MATRIX_ROW_VPOS (bottom_row, w->current_matrix),
12434 nrows_scrolled);
2311178e 12435
9c8b8382 12436 /* Disable lines that must be updated. */
5f5c8ee5 12437 for (i = 0; i < it.vpos; ++i)
b48f74cb 12438 (start_row + i)->enabled_p = 0;
9c8b8382 12439
5f5c8ee5 12440 /* Re-compute Y positions. */
da8b7f4f 12441 min_y = WINDOW_HEADER_LINE_HEIGHT (w);
5f5c8ee5 12442 max_y = it.last_visible_y;
b48f74cb
GM
12443 for (row = start_row + nrows_scrolled;
12444 row < bottom_row;
12445 ++row)
d2f84654 12446 {
5f5c8ee5 12447 row->y = it.current_y;
75c5350a 12448 row->visible_height = row->height;
5f5c8ee5
GM
12449
12450 if (row->y < min_y)
75c5350a
GM
12451 row->visible_height -= min_y - row->y;
12452 if (row->y + row->height > max_y)
12453 row->visible_height -= row->y + row->height - max_y;
6b61353c 12454 row->redraw_fringe_bitmaps_p = 1;
2311178e 12455
5f5c8ee5 12456 it.current_y += row->height;
5f5c8ee5
GM
12457
12458 if (MATRIX_ROW_DISPLAYS_TEXT_P (row))
12459 last_reused_text_row = row;
12460 if (MATRIX_ROW_BOTTOM_Y (row) >= it.last_visible_y)
12461 break;
d2f84654 12462 }
2311178e 12463
9c8b8382
GM
12464 /* Disable lines in the current matrix which are now
12465 below the window. */
bafb434c 12466 for (++row; row < bottom_row; ++row)
9c8b8382 12467 row->enabled_p = 0;
a2889657 12468 }
5f5c8ee5
GM
12469
12470 /* Update window_end_pos etc.; last_reused_text_row is the last
12471 reused row from the current matrix containing text, if any.
12472 The value of last_text_row is the last displayed line
12473 containing text. */
12474 if (last_reused_text_row)
a2889657 12475 {
5f5c8ee5
GM
12476 w->window_end_bytepos
12477 = Z_BYTE - MATRIX_ROW_END_BYTEPOS (last_reused_text_row);
ac90c44f
GM
12478 w->window_end_pos
12479 = make_number (Z - MATRIX_ROW_END_CHARPOS (last_reused_text_row));
12480 w->window_end_vpos
12481 = make_number (MATRIX_ROW_VPOS (last_reused_text_row,
12482 w->current_matrix));
a2889657 12483 }
5f5c8ee5
GM
12484 else if (last_text_row)
12485 {
12486 w->window_end_bytepos
12487 = Z_BYTE - MATRIX_ROW_END_BYTEPOS (last_text_row);
ac90c44f
GM
12488 w->window_end_pos
12489 = make_number (Z - MATRIX_ROW_END_CHARPOS (last_text_row));
12490 w->window_end_vpos
12491 = make_number (MATRIX_ROW_VPOS (last_text_row, w->desired_matrix));
5f5c8ee5
GM
12492 }
12493 else
12494 {
12495 /* This window must be completely empty. */
86bf3faa
RS
12496 w->window_end_bytepos = Z_BYTE - ZV_BYTE;
12497 w->window_end_pos = make_number (Z - ZV);
12498 w->window_end_vpos = make_number (0);
5f5c8ee5
GM
12499 }
12500 w->window_end_valid = Qnil;
a2889657 12501
5f5c8ee5
GM
12502 /* Update hint: don't try scrolling again in update_window. */
12503 w->desired_matrix->no_scrolling_p = 1;
2311178e 12504
5f5c8ee5
GM
12505#if GLYPH_DEBUG
12506 debug_method_add (w, "try_window_reusing_current_matrix 1");
12507#endif
12508 return 1;
a2889657 12509 }
5f5c8ee5
GM
12510 else if (CHARPOS (new_start) > CHARPOS (start))
12511 {
12512 struct glyph_row *pt_row, *row;
12513 struct glyph_row *first_reusable_row;
12514 struct glyph_row *first_row_to_display;
12515 int dy;
12516 int yb = window_text_bottom_y (w);
12517
5f5c8ee5
GM
12518 /* Find the row starting at new_start, if there is one. Don't
12519 reuse a partially visible line at the end. */
b48f74cb 12520 first_reusable_row = start_row;
5f5c8ee5
GM
12521 while (first_reusable_row->enabled_p
12522 && MATRIX_ROW_BOTTOM_Y (first_reusable_row) < yb
12523 && (MATRIX_ROW_START_CHARPOS (first_reusable_row)
12524 < CHARPOS (new_start)))
12525 ++first_reusable_row;
12526
12527 /* Give up if there is no row to reuse. */
12528 if (MATRIX_ROW_BOTTOM_Y (first_reusable_row) >= yb
28514cd9
GM
12529 || !first_reusable_row->enabled_p
12530 || (MATRIX_ROW_START_CHARPOS (first_reusable_row)
12531 != CHARPOS (new_start)))
5f5c8ee5
GM
12532 return 0;
12533
5f5c8ee5
GM
12534 /* We can reuse fully visible rows beginning with
12535 first_reusable_row to the end of the window. Set
12536 first_row_to_display to the first row that cannot be reused.
12537 Set pt_row to the row containing point, if there is any. */
5f5c8ee5 12538 pt_row = NULL;
ac90c44f
GM
12539 for (first_row_to_display = first_reusable_row;
12540 MATRIX_ROW_BOTTOM_Y (first_row_to_display) < yb;
12541 ++first_row_to_display)
5f5c8ee5 12542 {
4bde0ebb
GM
12543 if (PT >= MATRIX_ROW_START_CHARPOS (first_row_to_display)
12544 && PT < MATRIX_ROW_END_CHARPOS (first_row_to_display))
5f5c8ee5 12545 pt_row = first_row_to_display;
5f5c8ee5 12546 }
a2889657 12547
5f5c8ee5
GM
12548 /* Start displaying at the start of first_row_to_display. */
12549 xassert (first_row_to_display->y < yb);
12550 init_to_row_start (&it, w, first_row_to_display);
607ec83c 12551
b48f74cb
GM
12552 nrows_scrolled = (MATRIX_ROW_VPOS (first_reusable_row, w->current_matrix)
12553 - start_vpos);
5f5c8ee5
GM
12554 it.vpos = (MATRIX_ROW_VPOS (first_row_to_display, w->current_matrix)
12555 - nrows_scrolled);
b48f74cb 12556 it.current_y = (first_row_to_display->y - first_reusable_row->y
da8b7f4f 12557 + WINDOW_HEADER_LINE_HEIGHT (w));
5f5c8ee5
GM
12558
12559 /* Display lines beginning with first_row_to_display in the
12560 desired matrix. Set last_text_row to the last row displayed
12561 that displays text. */
12562 it.glyph_row = MATRIX_ROW (w->desired_matrix, it.vpos);
12563 if (pt_row == NULL)
12564 w->cursor.vpos = -1;
12565 last_text_row = NULL;
12566 while (it.current_y < it.last_visible_y && !fonts_changed_p)
12567 if (display_line (&it))
12568 last_text_row = it.glyph_row - 1;
12569
12570 /* Give up If point isn't in a row displayed or reused. */
12571 if (w->cursor.vpos < 0)
12572 {
12573 clear_glyph_matrix (w->desired_matrix);
12574 return 0;
12575 }
12adba34 12576
5f5c8ee5
GM
12577 /* If point is in a reused row, adjust y and vpos of the cursor
12578 position. */
12579 if (pt_row)
12580 {
12581 w->cursor.vpos -= MATRIX_ROW_VPOS (first_reusable_row,
12582 w->current_matrix);
12583 w->cursor.y -= first_reusable_row->y;
a2889657
JB
12584 }
12585
5f5c8ee5
GM
12586 /* Scroll the display. */
12587 run.current_y = first_reusable_row->y;
da8b7f4f 12588 run.desired_y = WINDOW_HEADER_LINE_HEIGHT (w);
5f5c8ee5 12589 run.height = it.last_visible_y - run.current_y;
4da61803 12590 dy = run.current_y - run.desired_y;
2311178e 12591
5f5c8ee5
GM
12592 if (run.height)
12593 {
5f5c8ee5
GM
12594 update_begin (f);
12595 rif->update_window_begin_hook (w);
fa3c6b4d 12596 rif->clear_window_mouse_face (w);
5f5c8ee5 12597 rif->scroll_run_hook (w, &run);
64d1e7d3 12598 rif->update_window_end_hook (w, 0, 0);
5f5c8ee5
GM
12599 update_end (f);
12600 }
a2889657 12601
5f5c8ee5
GM
12602 /* Adjust Y positions of reused rows. */
12603 bottom_row = MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w);
da8b7f4f 12604 min_y = WINDOW_HEADER_LINE_HEIGHT (w);
5f5c8ee5 12605 max_y = it.last_visible_y;
b48f74cb 12606 for (row = first_reusable_row; row < first_row_to_display; ++row)
5f5c8ee5
GM
12607 {
12608 row->y -= dy;
75c5350a 12609 row->visible_height = row->height;
5f5c8ee5 12610 if (row->y < min_y)
75c5350a
GM
12611 row->visible_height -= min_y - row->y;
12612 if (row->y + row->height > max_y)
12613 row->visible_height -= row->y + row->height - max_y;
6b61353c 12614 row->redraw_fringe_bitmaps_p = 1;
5f5c8ee5 12615 }
a2889657 12616
5f5c8ee5
GM
12617 /* Scroll the current matrix. */
12618 xassert (nrows_scrolled > 0);
12619 rotate_matrix (w->current_matrix,
12620 start_vpos,
12621 MATRIX_ROW_VPOS (bottom_row, w->current_matrix),
12622 -nrows_scrolled);
12623
ac90c44f
GM
12624 /* Disable rows not reused. */
12625 for (row -= nrows_scrolled; row < bottom_row; ++row)
12626 row->enabled_p = 0;
12627
5f5c8ee5
GM
12628 /* Adjust window end. A null value of last_text_row means that
12629 the window end is in reused rows which in turn means that
12630 only its vpos can have changed. */
12631 if (last_text_row)
12632 {
12633 w->window_end_bytepos
12634 = Z_BYTE - MATRIX_ROW_END_BYTEPOS (last_text_row);
ac90c44f
GM
12635 w->window_end_pos
12636 = make_number (Z - MATRIX_ROW_END_CHARPOS (last_text_row));
12637 w->window_end_vpos
12638 = make_number (MATRIX_ROW_VPOS (last_text_row, w->desired_matrix));
5f5c8ee5
GM
12639 }
12640 else
a2889657 12641 {
ac90c44f
GM
12642 w->window_end_vpos
12643 = make_number (XFASTINT (w->window_end_vpos) - nrows_scrolled);
a2889657 12644 }
2311178e 12645
5f5c8ee5
GM
12646 w->window_end_valid = Qnil;
12647 w->desired_matrix->no_scrolling_p = 1;
12648
12649#if GLYPH_DEBUG
12650 debug_method_add (w, "try_window_reusing_current_matrix 2");
12651#endif
12652 return 1;
a2889657 12653 }
2311178e 12654
5f5c8ee5
GM
12655 return 0;
12656}
a2889657 12657
a2889657 12658
5f5c8ee5
GM
12659\f
12660/************************************************************************
12661 Window redisplay reusing current matrix when buffer has changed
12662 ************************************************************************/
12663
1ec185cb
GM
12664static struct glyph_row *find_last_unchanged_at_beg_row P_ ((struct window *));
12665static struct glyph_row *find_first_unchanged_at_end_row P_ ((struct window *,
5f5c8ee5
GM
12666 int *, int *));
12667static struct glyph_row *
12668find_last_row_displaying_text P_ ((struct glyph_matrix *, struct it *,
12669 struct glyph_row *));
12670
12671
12672/* Return the last row in MATRIX displaying text. If row START is
12673 non-null, start searching with that row. IT gives the dimensions
12674 of the display. Value is null if matrix is empty; otherwise it is
12675 a pointer to the row found. */
12676
12677static struct glyph_row *
12678find_last_row_displaying_text (matrix, it, start)
12679 struct glyph_matrix *matrix;
12680 struct it *it;
12681 struct glyph_row *start;
12682{
12683 struct glyph_row *row, *row_found;
12684
12685 /* Set row_found to the last row in IT->w's current matrix
12686 displaying text. The loop looks funny but think of partially
12687 visible lines. */
12688 row_found = NULL;
12689 row = start ? start : MATRIX_FIRST_TEXT_ROW (matrix);
12690 while (MATRIX_ROW_DISPLAYS_TEXT_P (row))
12691 {
12692 xassert (row->enabled_p);
12693 row_found = row;
12694 if (MATRIX_ROW_BOTTOM_Y (row) >= it->last_visible_y)
12695 break;
12696 ++row;
a2889657 12697 }
2311178e 12698
5f5c8ee5
GM
12699 return row_found;
12700}
12701
a2889657 12702
5f5c8ee5 12703/* Return the last row in the current matrix of W that is not affected
d43fbe9d
GM
12704 by changes at the start of current_buffer that occurred since W's
12705 current matrix was built. Value is null if no such row exists.
a2889657 12706
d43fbe9d
GM
12707 BEG_UNCHANGED us the number of characters unchanged at the start of
12708 current_buffer. BEG + BEG_UNCHANGED is the buffer position of the
12709 first changed character in current_buffer. Characters at positions <
12710 BEG + BEG_UNCHANGED are at the same buffer positions as they were
12711 when the current matrix was built. */
5f5c8ee5
GM
12712
12713static struct glyph_row *
1ec185cb 12714find_last_unchanged_at_beg_row (w)
5f5c8ee5
GM
12715 struct window *w;
12716{
9142dd5b 12717 int first_changed_pos = BEG + BEG_UNCHANGED;
5f5c8ee5
GM
12718 struct glyph_row *row;
12719 struct glyph_row *row_found = NULL;
12720 int yb = window_text_bottom_y (w);
12721
12722 /* Find the last row displaying unchanged text. */
12723 row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
12724 while (MATRIX_ROW_DISPLAYS_TEXT_P (row)
12725 && MATRIX_ROW_START_CHARPOS (row) < first_changed_pos)
a2889657 12726 {
5f5c8ee5
GM
12727 if (/* If row ends before first_changed_pos, it is unchanged,
12728 except in some case. */
12729 MATRIX_ROW_END_CHARPOS (row) <= first_changed_pos
12730 /* When row ends in ZV and we write at ZV it is not
12731 unchanged. */
12732 && !row->ends_at_zv_p
12733 /* When first_changed_pos is the end of a continued line,
12734 row is not unchanged because it may be no longer
12735 continued. */
12736 && !(MATRIX_ROW_END_CHARPOS (row) == first_changed_pos
6b61353c
KH
12737 && (row->continued_p
12738 || row->exact_window_width_line_p)))
5f5c8ee5
GM
12739 row_found = row;
12740
12741 /* Stop if last visible row. */
12742 if (MATRIX_ROW_BOTTOM_Y (row) >= yb)
12743 break;
2311178e 12744
5f5c8ee5 12745 ++row;
a2889657
JB
12746 }
12747
5f5c8ee5 12748 return row_found;
a2889657 12749}
5f5c8ee5
GM
12750
12751
12752/* Find the first glyph row in the current matrix of W that is not
2311178e 12753 affected by changes at the end of current_buffer since the
d43fbe9d
GM
12754 time W's current matrix was built.
12755
12756 Return in *DELTA the number of chars by which buffer positions in
12757 unchanged text at the end of current_buffer must be adjusted.
2311178e 12758
d43fbe9d
GM
12759 Return in *DELTA_BYTES the corresponding number of bytes.
12760
12761 Value is null if no such row exists, i.e. all rows are affected by
12762 changes. */
2311178e 12763
5f5c8ee5 12764static struct glyph_row *
1ec185cb 12765find_first_unchanged_at_end_row (w, delta, delta_bytes)
5f5c8ee5
GM
12766 struct window *w;
12767 int *delta, *delta_bytes;
a2889657 12768{
5f5c8ee5
GM
12769 struct glyph_row *row;
12770 struct glyph_row *row_found = NULL;
c581d710 12771
5f5c8ee5 12772 *delta = *delta_bytes = 0;
b2a76982 12773
1ec185cb
GM
12774 /* Display must not have been paused, otherwise the current matrix
12775 is not up to date. */
12776 if (NILP (w->window_end_valid))
12777 abort ();
2311178e 12778
1ec185cb 12779 /* A value of window_end_pos >= END_UNCHANGED means that the window
5f5c8ee5
GM
12780 end is in the range of changed text. If so, there is no
12781 unchanged row at the end of W's current matrix. */
9142dd5b 12782 if (XFASTINT (w->window_end_pos) >= END_UNCHANGED)
5f5c8ee5
GM
12783 return NULL;
12784
12785 /* Set row to the last row in W's current matrix displaying text. */
12786 row = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos));
2311178e
TTN
12787
12788 /* If matrix is entirely empty, no unchanged row exists. */
5f5c8ee5
GM
12789 if (MATRIX_ROW_DISPLAYS_TEXT_P (row))
12790 {
12791 /* The value of row is the last glyph row in the matrix having a
12792 meaningful buffer position in it. The end position of row
12793 corresponds to window_end_pos. This allows us to translate
12794 buffer positions in the current matrix to current buffer
12795 positions for characters not in changed text. */
12796 int Z_old = MATRIX_ROW_END_CHARPOS (row) + XFASTINT (w->window_end_pos);
12797 int Z_BYTE_old = MATRIX_ROW_END_BYTEPOS (row) + w->window_end_bytepos;
12798 int last_unchanged_pos, last_unchanged_pos_old;
12799 struct glyph_row *first_text_row
12800 = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
12801
12802 *delta = Z - Z_old;
12803 *delta_bytes = Z_BYTE - Z_BYTE_old;
12804
12805 /* Set last_unchanged_pos to the buffer position of the last
12806 character in the buffer that has not been changed. Z is the
d43fbe9d
GM
12807 index + 1 of the last character in current_buffer, i.e. by
12808 subtracting END_UNCHANGED we get the index of the last
5f5c8ee5
GM
12809 unchanged character, and we have to add BEG to get its buffer
12810 position. */
9142dd5b 12811 last_unchanged_pos = Z - END_UNCHANGED + BEG;
5f5c8ee5 12812 last_unchanged_pos_old = last_unchanged_pos - *delta;
2311178e 12813
5f5c8ee5
GM
12814 /* Search backward from ROW for a row displaying a line that
12815 starts at a minimum position >= last_unchanged_pos_old. */
1ec185cb 12816 for (; row > first_text_row; --row)
5f5c8ee5 12817 {
1ec185cb
GM
12818 if (!row->enabled_p || !MATRIX_ROW_DISPLAYS_TEXT_P (row))
12819 abort ();
2311178e 12820
5f5c8ee5
GM
12821 if (MATRIX_ROW_START_CHARPOS (row) >= last_unchanged_pos_old)
12822 row_found = row;
5f5c8ee5
GM
12823 }
12824 }
12825
1ec185cb
GM
12826 if (row_found && !MATRIX_ROW_DISPLAYS_TEXT_P (row_found))
12827 abort ();
2311178e 12828
5f5c8ee5 12829 return row_found;
c581d710
RS
12830}
12831
c581d710 12832
5f5c8ee5
GM
12833/* Make sure that glyph rows in the current matrix of window W
12834 reference the same glyph memory as corresponding rows in the
12835 frame's frame matrix. This function is called after scrolling W's
12836 current matrix on a terminal frame in try_window_id and
12837 try_window_reusing_current_matrix. */
12838
12839static void
12840sync_frame_with_window_matrix_rows (w)
12841 struct window *w;
c581d710 12842{
5f5c8ee5
GM
12843 struct frame *f = XFRAME (w->frame);
12844 struct glyph_row *window_row, *window_row_end, *frame_row;
12845
12846 /* Preconditions: W must be a leaf window and full-width. Its frame
12847 must have a frame matrix. */
12848 xassert (NILP (w->hchild) && NILP (w->vchild));
12849 xassert (WINDOW_FULL_WIDTH_P (w));
12850 xassert (!FRAME_WINDOW_P (f));
12851
12852 /* If W is a full-width window, glyph pointers in W's current matrix
12853 have, by definition, to be the same as glyph pointers in the
7d4cc828
GM
12854 corresponding frame matrix. Note that frame matrices have no
12855 marginal areas (see build_frame_matrix). */
5f5c8ee5
GM
12856 window_row = w->current_matrix->rows;
12857 window_row_end = window_row + w->current_matrix->nrows;
da8b7f4f 12858 frame_row = f->current_matrix->rows + WINDOW_TOP_EDGE_LINE (w);
5f5c8ee5 12859 while (window_row < window_row_end)
659a218f 12860 {
7d4cc828
GM
12861 struct glyph *start = window_row->glyphs[LEFT_MARGIN_AREA];
12862 struct glyph *end = window_row->glyphs[LAST_AREA];
12863
12864 frame_row->glyphs[LEFT_MARGIN_AREA] = start;
12865 frame_row->glyphs[TEXT_AREA] = start;
12866 frame_row->glyphs[RIGHT_MARGIN_AREA] = end;
12867 frame_row->glyphs[LAST_AREA] = end;
f002db93
GM
12868
12869 /* Disable frame rows whose corresponding window rows have
12870 been disabled in try_window_id. */
12871 if (!window_row->enabled_p)
12872 frame_row->enabled_p = 0;
2311178e 12873
5f5c8ee5 12874 ++window_row, ++frame_row;
659a218f 12875 }
a2889657 12876}
5f5c8ee5
GM
12877
12878
e037b9ec
GM
12879/* Find the glyph row in window W containing CHARPOS. Consider all
12880 rows between START and END (not inclusive). END null means search
12881 all rows to the end of the display area of W. Value is the row
12882 containing CHARPOS or null. */
12883
0bef35bc 12884struct glyph_row *
0df56f4d 12885row_containing_pos (w, charpos, start, end, dy)
e037b9ec
GM
12886 struct window *w;
12887 int charpos;
12888 struct glyph_row *start, *end;
0df56f4d 12889 int dy;
e037b9ec
GM
12890{
12891 struct glyph_row *row = start;
12892 int last_y;
12893
12894 /* If we happen to start on a header-line, skip that. */
12895 if (row->mode_line_p)
12896 ++row;
2311178e 12897
e037b9ec
GM
12898 if ((end && row >= end) || !row->enabled_p)
12899 return NULL;
2311178e 12900
0df56f4d 12901 last_y = window_text_bottom_y (w) - dy;
2311178e 12902
5cce13dd
RS
12903 while (1)
12904 {
12905 /* Give up if we have gone too far. */
12906 if (end && row >= end)
12907 return NULL;
40a301b3
RS
12908 /* This formerly returned if they were equal.
12909 I think that both quantities are of a "last plus one" type;
12910 if so, when they are equal, the row is within the screen. -- rms. */
12911 if (MATRIX_ROW_BOTTOM_Y (row) > last_y)
5cce13dd
RS
12912 return NULL;
12913
12914 /* If it is in this row, return this row. */
12915 if (! (MATRIX_ROW_END_CHARPOS (row) < charpos
e037b9ec 12916 || (MATRIX_ROW_END_CHARPOS (row) == charpos
0df56f4d
GM
12917 /* The end position of a row equals the start
12918 position of the next row. If CHARPOS is there, we
12919 would rather display it in the next line, except
12920 when this line ends in ZV. */
12921 && !row->ends_at_zv_p
5cce13dd
RS
12922 && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row)))
12923 && charpos >= MATRIX_ROW_START_CHARPOS (row))
12924 return row;
12925 ++row;
12926 }
e037b9ec
GM
12927}
12928
12929
5f5c8ee5
GM
12930/* Try to redisplay window W by reusing its existing display. W's
12931 current matrix must be up to date when this function is called,
12932 i.e. window_end_valid must not be nil.
12933
12934 Value is
12935
12936 1 if display has been updated
12937 0 if otherwise unsuccessful
12938 -1 if redisplay with same window start is known not to succeed
12939
12940 The following steps are performed:
12941
12942 1. Find the last row in the current matrix of W that is not
12943 affected by changes at the start of current_buffer. If no such row
12944 is found, give up.
12945
12946 2. Find the first row in W's current matrix that is not affected by
12947 changes at the end of current_buffer. Maybe there is no such row.
12948
12949 3. Display lines beginning with the row + 1 found in step 1 to the
12950 row found in step 2 or, if step 2 didn't find a row, to the end of
12951 the window.
12952
12953 4. If cursor is not known to appear on the window, give up.
12954
12955 5. If display stopped at the row found in step 2, scroll the
12956 display and current matrix as needed.
12957
12958 6. Maybe display some lines at the end of W, if we must. This can
12959 happen under various circumstances, like a partially visible line
12960 becoming fully visible, or because newly displayed lines are displayed
12961 in smaller font sizes.
12962
12963 7. Update W's window end information. */
12964
12adba34 12965static int
5f5c8ee5 12966try_window_id (w)
12adba34 12967 struct window *w;
12adba34 12968{
5f5c8ee5
GM
12969 struct frame *f = XFRAME (w->frame);
12970 struct glyph_matrix *current_matrix = w->current_matrix;
12971 struct glyph_matrix *desired_matrix = w->desired_matrix;
12972 struct glyph_row *last_unchanged_at_beg_row;
12973 struct glyph_row *first_unchanged_at_end_row;
12974 struct glyph_row *row;
12975 struct glyph_row *bottom_row;
12976 int bottom_vpos;
12977 struct it it;
12978 int delta = 0, delta_bytes = 0, stop_pos, dvpos, dy;
12979 struct text_pos start_pos;
12980 struct run run;
12981 int first_unchanged_at_end_vpos = 0;
12982 struct glyph_row *last_text_row, *last_text_row_at_end;
12983 struct text_pos start;
27d16f05 12984 int first_changed_charpos, last_changed_charpos;
5f5c8ee5 12985
69d1f7c9 12986#if GLYPH_DEBUG
76cb5e06
GM
12987 if (inhibit_try_window_id)
12988 return 0;
12989#endif
12990
27d16f05
GM
12991 /* This is handy for debugging. */
12992#if 0
12993#define GIVE_UP(X) \
12994 do { \
12995 fprintf (stderr, "try_window_id give up %d\n", (X)); \
12996 return 0; \
12997 } while (0)
12998#else
62397849 12999#define GIVE_UP(X) return 0
27d16f05 13000#endif
2311178e 13001
5f5c8ee5
GM
13002 SET_TEXT_POS_FROM_MARKER (start, w->start);
13003
27d16f05
GM
13004 /* Don't use this for mini-windows because these can show
13005 messages and mini-buffers, and we don't handle that here. */
13006 if (MINI_WINDOW_P (w))
13007 GIVE_UP (1);
2311178e 13008
27d16f05 13009 /* This flag is used to prevent redisplay optimizations. */
5fb96e96 13010 if (windows_or_buffers_changed || cursor_type_changed)
27d16f05 13011 GIVE_UP (2);
2311178e 13012
c62c1bb5
RS
13013 /* Verify that narrowing has not changed.
13014 Also verify that we were not told to prevent redisplay optimizations.
13015 It would be nice to further
27d16f05 13016 reduce the number of cases where this prevents try_window_id. */
c62c1bb5
RS
13017 if (current_buffer->clip_changed
13018 || current_buffer->prevent_redisplay_optimizations_p)
27d16f05
GM
13019 GIVE_UP (3);
13020
13021 /* Window must either use window-based redisplay or be full width. */
13022 if (!FRAME_WINDOW_P (f)
13023 && (!line_ins_del_ok
13024 || !WINDOW_FULL_WIDTH_P (w)))
13025 GIVE_UP (4);
5f5c8ee5 13026
f5376658 13027 /* Give up if point is not known NOT to appear in W. */
27d16f05
GM
13028 if (PT < CHARPOS (start))
13029 GIVE_UP (5);
13030
13031 /* Another way to prevent redisplay optimizations. */
13032 if (XFASTINT (w->last_modified) == 0)
13033 GIVE_UP (6);
2311178e 13034
f5376658 13035 /* Verify that window is not hscrolled. */
27d16f05
GM
13036 if (XFASTINT (w->hscroll) != 0)
13037 GIVE_UP (7);
2311178e 13038
f5376658 13039 /* Verify that display wasn't paused. */
27d16f05
GM
13040 if (NILP (w->window_end_valid))
13041 GIVE_UP (8);
2311178e 13042
27d16f05
GM
13043 /* Can't use this if highlighting a region because a cursor movement
13044 will do more than just set the cursor. */
13045 if (!NILP (Vtransient_mark_mode)
13046 && !NILP (current_buffer->mark_active))
13047 GIVE_UP (9);
13048
13049 /* Likewise if highlighting trailing whitespace. */
13050 if (!NILP (Vshow_trailing_whitespace))
13051 GIVE_UP (11);
2311178e 13052
27d16f05
GM
13053 /* Likewise if showing a region. */
13054 if (!NILP (w->region_showing))
13055 GIVE_UP (10);
2311178e 13056
27d16f05 13057 /* Can use this if overlay arrow position and or string have changed. */
6b61353c 13058 if (overlay_arrows_changed_p ())
27d16f05
GM
13059 GIVE_UP (12);
13060
2311178e 13061
5f5c8ee5
GM
13062 /* Make sure beg_unchanged and end_unchanged are up to date. Do it
13063 only if buffer has really changed. The reason is that the gap is
13064 initially at Z for freshly visited files. The code below would
13065 set end_unchanged to 0 in that case. */
28ee91c0
GM
13066 if (MODIFF > SAVE_MODIFF
13067 /* This seems to happen sometimes after saving a buffer. */
13068 || BEG_UNCHANGED + END_UNCHANGED > Z_BYTE)
5f5c8ee5 13069 {
9142dd5b
GM
13070 if (GPT - BEG < BEG_UNCHANGED)
13071 BEG_UNCHANGED = GPT - BEG;
13072 if (Z - GPT < END_UNCHANGED)
13073 END_UNCHANGED = Z - GPT;
5f5c8ee5 13074 }
bf9249e3 13075
27d16f05
GM
13076 /* The position of the first and last character that has been changed. */
13077 first_changed_charpos = BEG + BEG_UNCHANGED;
13078 last_changed_charpos = Z - END_UNCHANGED;
13079
5f5c8ee5
GM
13080 /* If window starts after a line end, and the last change is in
13081 front of that newline, then changes don't affect the display.
f2d86d7a
GM
13082 This case happens with stealth-fontification. Note that although
13083 the display is unchanged, glyph positions in the matrix have to
13084 be adjusted, of course. */
5f5c8ee5 13085 row = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos));
27d16f05 13086 if (MATRIX_ROW_DISPLAYS_TEXT_P (row)
e60f4527 13087 && ((last_changed_charpos < CHARPOS (start)
27d16f05 13088 && CHARPOS (start) == BEGV)
e60f4527 13089 || (last_changed_charpos < CHARPOS (start) - 1
27d16f05
GM
13090 && FETCH_BYTE (BYTEPOS (start) - 1) == '\n')))
13091 {
13092 int Z_old, delta, Z_BYTE_old, delta_bytes;
13093 struct glyph_row *r0;
13094
13095 /* Compute how many chars/bytes have been added to or removed
13096 from the buffer. */
13097 Z_old = MATRIX_ROW_END_CHARPOS (row) + XFASTINT (w->window_end_pos);
13098 Z_BYTE_old = MATRIX_ROW_END_BYTEPOS (row) + w->window_end_bytepos;
13099 delta = Z - Z_old;
13100 delta_bytes = Z_BYTE - Z_BYTE_old;
2311178e 13101
27d16f05
GM
13102 /* Give up if PT is not in the window. Note that it already has
13103 been checked at the start of try_window_id that PT is not in
13104 front of the window start. */
13105 if (PT >= MATRIX_ROW_END_CHARPOS (row) + delta)
13106 GIVE_UP (13);
13107
13108 /* If window start is unchanged, we can reuse the whole matrix
13109 as is, after adjusting glyph positions. No need to compute
13110 the window end again, since its offset from Z hasn't changed. */
13111 r0 = MATRIX_FIRST_TEXT_ROW (current_matrix);
13112 if (CHARPOS (start) == MATRIX_ROW_START_CHARPOS (r0) + delta
2d031b89
AS
13113 && BYTEPOS (start) == MATRIX_ROW_START_BYTEPOS (r0) + delta_bytes
13114 /* PT must not be in a partially visible line. */
13115 && !(PT >= MATRIX_ROW_START_CHARPOS (row) + delta
13116 && MATRIX_ROW_BOTTOM_Y (row) > window_text_bottom_y (w)))
27d16f05
GM
13117 {
13118 /* Adjust positions in the glyph matrix. */
13119 if (delta || delta_bytes)
13120 {
13121 struct glyph_row *r1
13122 = MATRIX_BOTTOM_TEXT_ROW (current_matrix, w);
13123 increment_matrix_positions (w->current_matrix,
13124 MATRIX_ROW_VPOS (r0, current_matrix),
13125 MATRIX_ROW_VPOS (r1, current_matrix),
13126 delta, delta_bytes);
13127 }
2311178e 13128
27d16f05 13129 /* Set the cursor. */
0df56f4d 13130 row = row_containing_pos (w, PT, r0, NULL, 0);
59adf8e8
KS
13131 if (row)
13132 set_cursor_from_row (w, row, current_matrix, 0, 0, 0, 0);
40a301b3
RS
13133 else
13134 abort ();
27d16f05
GM
13135 return 1;
13136 }
5f5c8ee5
GM
13137 }
13138
27d16f05 13139 /* Handle the case that changes are all below what is displayed in
33ea6c4d 13140 the window, and that PT is in the window. This shortcut cannot
2b9c25e0
GM
13141 be taken if ZV is visible in the window, and text has been added
13142 there that is visible in the window. */
13143 if (first_changed_charpos >= MATRIX_ROW_END_CHARPOS (row)
33ea6c4d
GM
13144 /* ZV is not visible in the window, or there are no
13145 changes at ZV, actually. */
13146 && (current_matrix->zv > MATRIX_ROW_END_CHARPOS (row)
13147 || first_changed_charpos == last_changed_charpos))
5f5c8ee5 13148 {
27d16f05 13149 struct glyph_row *r0;
ef121659 13150
27d16f05
GM
13151 /* Give up if PT is not in the window. Note that it already has
13152 been checked at the start of try_window_id that PT is not in
13153 front of the window start. */
13154 if (PT >= MATRIX_ROW_END_CHARPOS (row))
13155 GIVE_UP (14);
13156
13157 /* If window start is unchanged, we can reuse the whole matrix
13158 as is, without changing glyph positions since no text has
13159 been added/removed in front of the window end. */
13160 r0 = MATRIX_FIRST_TEXT_ROW (current_matrix);
2d031b89
AS
13161 if (TEXT_POS_EQUAL_P (start, r0->start.pos)
13162 /* PT must not be in a partially visible line. */
13163 && !(PT >= MATRIX_ROW_START_CHARPOS (row)
13164 && MATRIX_ROW_BOTTOM_Y (row) > window_text_bottom_y (w)))
27d16f05
GM
13165 {
13166 /* We have to compute the window end anew since text
13167 can have been added/removed after it. */
13168 w->window_end_pos
13169 = make_number (Z - MATRIX_ROW_END_CHARPOS (row));
13170 w->window_end_bytepos
13171 = Z_BYTE - MATRIX_ROW_END_BYTEPOS (row);
13172
13173 /* Set the cursor. */
0df56f4d 13174 row = row_containing_pos (w, PT, r0, NULL, 0);
59adf8e8
KS
13175 if (row)
13176 set_cursor_from_row (w, row, current_matrix, 0, 0, 0, 0);
40a301b3
RS
13177 else
13178 abort ();
27d16f05
GM
13179 return 2;
13180 }
5f5c8ee5
GM
13181 }
13182
2b9c25e0 13183 /* Give up if window start is in the changed area.
2311178e 13184
2b9c25e0
GM
13185 The condition used to read
13186
13187 (BEG_UNCHANGED + END_UNCHANGED != Z - BEG && ...)
13188
13189 but why that was tested escapes me at the moment. */
13190 if (CHARPOS (start) >= first_changed_charpos
27d16f05
GM
13191 && CHARPOS (start) <= last_changed_charpos)
13192 GIVE_UP (15);
2311178e 13193
f5376658
RS
13194 /* Check that window start agrees with the start of the first glyph
13195 row in its current matrix. Check this after we know the window
13196 start is not in changed text, otherwise positions would not be
13197 comparable. */
27d16f05 13198 row = MATRIX_FIRST_TEXT_ROW (current_matrix);
5f5c8ee5 13199 if (!TEXT_POS_EQUAL_P (start, row->start.pos))
27d16f05 13200 GIVE_UP (16);
5f5c8ee5 13201
23e8bd86
GM
13202 /* Give up if the window ends in strings. Overlay strings
13203 at the end are difficult to handle, so don't try. */
13204 row = MATRIX_ROW (current_matrix, XFASTINT (w->window_end_vpos));
13205 if (MATRIX_ROW_START_CHARPOS (row) == MATRIX_ROW_END_CHARPOS (row))
13206 GIVE_UP (20);
13207
5f5c8ee5
GM
13208 /* Compute the position at which we have to start displaying new
13209 lines. Some of the lines at the top of the window might be
13210 reusable because they are not displaying changed text. Find the
13211 last row in W's current matrix not affected by changes at the
13212 start of current_buffer. Value is null if changes start in the
13213 first line of window. */
1ec185cb 13214 last_unchanged_at_beg_row = find_last_unchanged_at_beg_row (w);
5f5c8ee5
GM
13215 if (last_unchanged_at_beg_row)
13216 {
67f1cf4c
GM
13217 /* Avoid starting to display in the moddle of a character, a TAB
13218 for instance. This is easier than to set up the iterator
13219 exactly, and it's not a frequent case, so the additional
13220 effort wouldn't really pay off. */
e74fb0f7
GM
13221 while ((MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (last_unchanged_at_beg_row)
13222 || last_unchanged_at_beg_row->ends_in_newline_from_string_p)
67f1cf4c
GM
13223 && last_unchanged_at_beg_row > w->current_matrix->rows)
13224 --last_unchanged_at_beg_row;
13225
13226 if (MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (last_unchanged_at_beg_row))
27d16f05 13227 GIVE_UP (17);
47d57b22
GM
13228
13229 if (init_to_row_end (&it, w, last_unchanged_at_beg_row) == 0)
13230 GIVE_UP (18);
5f5c8ee5 13231 start_pos = it.current.pos;
2311178e 13232
5f5c8ee5
GM
13233 /* Start displaying new lines in the desired matrix at the same
13234 vpos we would use in the current matrix, i.e. below
13235 last_unchanged_at_beg_row. */
13236 it.vpos = 1 + MATRIX_ROW_VPOS (last_unchanged_at_beg_row,
13237 current_matrix);
13238 it.glyph_row = MATRIX_ROW (desired_matrix, it.vpos);
13239 it.current_y = MATRIX_ROW_BOTTOM_Y (last_unchanged_at_beg_row);
13240
13241 xassert (it.hpos == 0 && it.current_x == 0);
13242 }
13243 else
13244 {
13245 /* There are no reusable lines at the start of the window.
6b61353c 13246 Start displaying in the first text line. */
5f5c8ee5 13247 start_display (&it, w, start);
6b61353c 13248 it.vpos = it.first_vpos;
5f5c8ee5
GM
13249 start_pos = it.current.pos;
13250 }
13251
5f5c8ee5
GM
13252 /* Find the first row that is not affected by changes at the end of
13253 the buffer. Value will be null if there is no unchanged row, in
13254 which case we must redisplay to the end of the window. delta
13255 will be set to the value by which buffer positions beginning with
13256 first_unchanged_at_end_row have to be adjusted due to text
13257 changes. */
13258 first_unchanged_at_end_row
1ec185cb 13259 = find_first_unchanged_at_end_row (w, &delta, &delta_bytes);
5f5c8ee5
GM
13260 IF_DEBUG (debug_delta = delta);
13261 IF_DEBUG (debug_delta_bytes = delta_bytes);
2311178e 13262
5f5c8ee5
GM
13263 /* Set stop_pos to the buffer position up to which we will have to
13264 display new lines. If first_unchanged_at_end_row != NULL, this
13265 is the buffer position of the start of the line displayed in that
13266 row. For first_unchanged_at_end_row == NULL, use 0 to indicate
13267 that we don't stop at a buffer position. */
13268 stop_pos = 0;
13269 if (first_unchanged_at_end_row)
13270 {
13271 xassert (last_unchanged_at_beg_row == NULL
13272 || first_unchanged_at_end_row >= last_unchanged_at_beg_row);
2311178e 13273
5f5c8ee5
GM
13274 /* If this is a continuation line, move forward to the next one
13275 that isn't. Changes in lines above affect this line.
13276 Caution: this may move first_unchanged_at_end_row to a row
13277 not displaying text. */
13278 while (MATRIX_ROW_CONTINUATION_LINE_P (first_unchanged_at_end_row)
13279 && MATRIX_ROW_DISPLAYS_TEXT_P (first_unchanged_at_end_row)
13280 && (MATRIX_ROW_BOTTOM_Y (first_unchanged_at_end_row)
13281 < it.last_visible_y))
13282 ++first_unchanged_at_end_row;
13283
13284 if (!MATRIX_ROW_DISPLAYS_TEXT_P (first_unchanged_at_end_row)
13285 || (MATRIX_ROW_BOTTOM_Y (first_unchanged_at_end_row)
13286 >= it.last_visible_y))
13287 first_unchanged_at_end_row = NULL;
13288 else
13289 {
13290 stop_pos = (MATRIX_ROW_START_CHARPOS (first_unchanged_at_end_row)
13291 + delta);
13292 first_unchanged_at_end_vpos
13293 = MATRIX_ROW_VPOS (first_unchanged_at_end_row, current_matrix);
9142dd5b 13294 xassert (stop_pos >= Z - END_UNCHANGED);
5f5c8ee5
GM
13295 }
13296 }
13297 else if (last_unchanged_at_beg_row == NULL)
23e8bd86 13298 GIVE_UP (19);
5f5c8ee5
GM
13299
13300
13301#if GLYPH_DEBUG
2311178e 13302
5f5c8ee5
GM
13303 /* Either there is no unchanged row at the end, or the one we have
13304 now displays text. This is a necessary condition for the window
13305 end pos calculation at the end of this function. */
13306 xassert (first_unchanged_at_end_row == NULL
13307 || MATRIX_ROW_DISPLAYS_TEXT_P (first_unchanged_at_end_row));
2311178e 13308
5f5c8ee5
GM
13309 debug_last_unchanged_at_beg_vpos
13310 = (last_unchanged_at_beg_row
13311 ? MATRIX_ROW_VPOS (last_unchanged_at_beg_row, current_matrix)
13312 : -1);
13313 debug_first_unchanged_at_end_vpos = first_unchanged_at_end_vpos;
2311178e 13314
5f5c8ee5
GM
13315#endif /* GLYPH_DEBUG != 0 */
13316
2311178e 13317
5f5c8ee5
GM
13318 /* Display new lines. Set last_text_row to the last new line
13319 displayed which has text on it, i.e. might end up as being the
13320 line where the window_end_vpos is. */
13321 w->cursor.vpos = -1;
13322 last_text_row = NULL;
13323 overlay_arrow_seen = 0;
13324 while (it.current_y < it.last_visible_y
13325 && !fonts_changed_p
13326 && (first_unchanged_at_end_row == NULL
13327 || IT_CHARPOS (it) < stop_pos))
13328 {
13329 if (display_line (&it))
13330 last_text_row = it.glyph_row - 1;
13331 }
13332
13333 if (fonts_changed_p)
13334 return -1;
13335
13336
13337 /* Compute differences in buffer positions, y-positions etc. for
13338 lines reused at the bottom of the window. Compute what we can
13339 scroll. */
ca42b2e8
GM
13340 if (first_unchanged_at_end_row
13341 /* No lines reused because we displayed everything up to the
13342 bottom of the window. */
13343 && it.current_y < it.last_visible_y)
5f5c8ee5
GM
13344 {
13345 dvpos = (it.vpos
13346 - MATRIX_ROW_VPOS (first_unchanged_at_end_row,
13347 current_matrix));
13348 dy = it.current_y - first_unchanged_at_end_row->y;
13349 run.current_y = first_unchanged_at_end_row->y;
13350 run.desired_y = run.current_y + dy;
13351 run.height = it.last_visible_y - max (run.current_y, run.desired_y);
13352 }
13353 else
ca42b2e8
GM
13354 {
13355 delta = dvpos = dy = run.current_y = run.desired_y = run.height = 0;
13356 first_unchanged_at_end_row = NULL;
13357 }
5f5c8ee5
GM
13358 IF_DEBUG (debug_dvpos = dvpos; debug_dy = dy);
13359
8f8ba186 13360
5f5c8ee5
GM
13361 /* Find the cursor if not already found. We have to decide whether
13362 PT will appear on this window (it sometimes doesn't, but this is
13363 not a very frequent case.) This decision has to be made before
13364 the current matrix is altered. A value of cursor.vpos < 0 means
13365 that PT is either in one of the lines beginning at
13366 first_unchanged_at_end_row or below the window. Don't care for
13367 lines that might be displayed later at the window end; as
13368 mentioned, this is not a frequent case. */
13369 if (w->cursor.vpos < 0)
13370 {
5f5c8ee5
GM
13371 /* Cursor in unchanged rows at the top? */
13372 if (PT < CHARPOS (start_pos)
13373 && last_unchanged_at_beg_row)
13374 {
e037b9ec
GM
13375 row = row_containing_pos (w, PT,
13376 MATRIX_FIRST_TEXT_ROW (w->current_matrix),
0df56f4d 13377 last_unchanged_at_beg_row + 1, 0);
bfe0ee88
GM
13378 if (row)
13379 set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0);
5f5c8ee5
GM
13380 }
13381
13382 /* Start from first_unchanged_at_end_row looking for PT. */
13383 else if (first_unchanged_at_end_row)
13384 {
e037b9ec 13385 row = row_containing_pos (w, PT - delta,
0df56f4d 13386 first_unchanged_at_end_row, NULL, 0);
e037b9ec 13387 if (row)
468155d7
GM
13388 set_cursor_from_row (w, row, w->current_matrix, delta,
13389 delta_bytes, dy, dvpos);
5f5c8ee5
GM
13390 }
13391
13392 /* Give up if cursor was not found. */
13393 if (w->cursor.vpos < 0)
13394 {
13395 clear_glyph_matrix (w->desired_matrix);
13396 return -1;
13397 }
13398 }
2311178e 13399
5f5c8ee5
GM
13400 /* Don't let the cursor end in the scroll margins. */
13401 {
13402 int this_scroll_margin, cursor_height;
2311178e 13403
5f5c8ee5 13404 this_scroll_margin = max (0, scroll_margin);
da8b7f4f
KS
13405 this_scroll_margin = min (this_scroll_margin, WINDOW_TOTAL_LINES (w) / 4);
13406 this_scroll_margin *= FRAME_LINE_HEIGHT (it.f);
5f5c8ee5 13407 cursor_height = MATRIX_ROW (w->desired_matrix, w->cursor.vpos)->height;
2311178e 13408
5f5c8ee5
GM
13409 if ((w->cursor.y < this_scroll_margin
13410 && CHARPOS (start) > BEGV)
13411 /* Don't take scroll margin into account at the bottom because
13412 old redisplay didn't do it either. */
13413 || w->cursor.y + cursor_height > it.last_visible_y)
13414 {
13415 w->cursor.vpos = -1;
13416 clear_glyph_matrix (w->desired_matrix);
13417 return -1;
13418 }
13419 }
13420
13421 /* Scroll the display. Do it before changing the current matrix so
13422 that xterm.c doesn't get confused about where the cursor glyph is
13423 found. */
fa77249f 13424 if (dy && run.height)
5f5c8ee5
GM
13425 {
13426 update_begin (f);
2311178e 13427
5f5c8ee5
GM
13428 if (FRAME_WINDOW_P (f))
13429 {
13430 rif->update_window_begin_hook (w);
fa3c6b4d 13431 rif->clear_window_mouse_face (w);
5f5c8ee5 13432 rif->scroll_run_hook (w, &run);
64d1e7d3 13433 rif->update_window_end_hook (w, 0, 0);
5f5c8ee5
GM
13434 }
13435 else
13436 {
13437 /* Terminal frame. In this case, dvpos gives the number of
13438 lines to scroll by; dvpos < 0 means scroll up. */
13439 int first_unchanged_at_end_vpos
13440 = MATRIX_ROW_VPOS (first_unchanged_at_end_row, w->current_matrix);
da8b7f4f
KS
13441 int from = WINDOW_TOP_EDGE_LINE (w) + first_unchanged_at_end_vpos;
13442 int end = (WINDOW_TOP_EDGE_LINE (w)
522ed7fb
GM
13443 + (WINDOW_WANTS_HEADER_LINE_P (w) ? 1 : 0)
13444 + window_internal_height (w));
2311178e 13445
5f5c8ee5
GM
13446 /* Perform the operation on the screen. */
13447 if (dvpos > 0)
13448 {
13449 /* Scroll last_unchanged_at_beg_row to the end of the
13450 window down dvpos lines. */
13451 set_terminal_window (end);
13452
13453 /* On dumb terminals delete dvpos lines at the end
13454 before inserting dvpos empty lines. */
13455 if (!scroll_region_ok)
13456 ins_del_lines (end - dvpos, -dvpos);
13457
13458 /* Insert dvpos empty lines in front of
13459 last_unchanged_at_beg_row. */
13460 ins_del_lines (from, dvpos);
13461 }
13462 else if (dvpos < 0)
13463 {
13464 /* Scroll up last_unchanged_at_beg_vpos to the end of
13465 the window to last_unchanged_at_beg_vpos - |dvpos|. */
13466 set_terminal_window (end);
13467
13468 /* Delete dvpos lines in front of
13469 last_unchanged_at_beg_vpos. ins_del_lines will set
13470 the cursor to the given vpos and emit |dvpos| delete
13471 line sequences. */
13472 ins_del_lines (from + dvpos, dvpos);
13473
13474 /* On a dumb terminal insert dvpos empty lines at the
13475 end. */
13476 if (!scroll_region_ok)
13477 ins_del_lines (end + dvpos, -dvpos);
13478 }
2311178e 13479
5f5c8ee5
GM
13480 set_terminal_window (0);
13481 }
2311178e 13482
5f5c8ee5
GM
13483 update_end (f);
13484 }
13485
ca42b2e8
GM
13486 /* Shift reused rows of the current matrix to the right position.
13487 BOTTOM_ROW is the last + 1 row in the current matrix reserved for
13488 text. */
13489 bottom_row = MATRIX_BOTTOM_TEXT_ROW (current_matrix, w);
13490 bottom_vpos = MATRIX_ROW_VPOS (bottom_row, current_matrix);
5f5c8ee5
GM
13491 if (dvpos < 0)
13492 {
13493 rotate_matrix (current_matrix, first_unchanged_at_end_vpos + dvpos,
13494 bottom_vpos, dvpos);
13495 enable_glyph_matrix_rows (current_matrix, bottom_vpos + dvpos,
13496 bottom_vpos, 0);
13497 }
13498 else if (dvpos > 0)
13499 {
13500 rotate_matrix (current_matrix, first_unchanged_at_end_vpos,
13501 bottom_vpos, dvpos);
13502 enable_glyph_matrix_rows (current_matrix, first_unchanged_at_end_vpos,
13503 first_unchanged_at_end_vpos + dvpos, 0);
13504 }
13505
13506 /* For frame-based redisplay, make sure that current frame and window
13507 matrix are in sync with respect to glyph memory. */
13508 if (!FRAME_WINDOW_P (f))
13509 sync_frame_with_window_matrix_rows (w);
13510
13511 /* Adjust buffer positions in reused rows. */
13512 if (delta)
f2d86d7a
GM
13513 increment_matrix_positions (current_matrix,
13514 first_unchanged_at_end_vpos + dvpos,
13515 bottom_vpos, delta, delta_bytes);
5f5c8ee5
GM
13516
13517 /* Adjust Y positions. */
13518 if (dy)
13519 shift_glyph_matrix (w, current_matrix,
13520 first_unchanged_at_end_vpos + dvpos,
13521 bottom_vpos, dy);
13522
13523 if (first_unchanged_at_end_row)
13524 first_unchanged_at_end_row += dvpos;
13525
13526 /* If scrolling up, there may be some lines to display at the end of
13527 the window. */
13528 last_text_row_at_end = NULL;
13529 if (dy < 0)
13530 {
9c6ba6d1
GM
13531 /* Scrolling up can leave for example a partially visible line
13532 at the end of the window to be redisplayed. */
5f5c8ee5
GM
13533 /* Set last_row to the glyph row in the current matrix where the
13534 window end line is found. It has been moved up or down in
13535 the matrix by dvpos. */
13536 int last_vpos = XFASTINT (w->window_end_vpos) + dvpos;
13537 struct glyph_row *last_row = MATRIX_ROW (current_matrix, last_vpos);
13538
13539 /* If last_row is the window end line, it should display text. */
13540 xassert (last_row->displays_text_p);
13541
13542 /* If window end line was partially visible before, begin
13543 displaying at that line. Otherwise begin displaying with the
13544 line following it. */
13545 if (MATRIX_ROW_BOTTOM_Y (last_row) - dy >= it.last_visible_y)
13546 {
13547 init_to_row_start (&it, w, last_row);
13548 it.vpos = last_vpos;
13549 it.current_y = last_row->y;
13550 }
13551 else
13552 {
13553 init_to_row_end (&it, w, last_row);
13554 it.vpos = 1 + last_vpos;
13555 it.current_y = MATRIX_ROW_BOTTOM_Y (last_row);
13556 ++last_row;
13557 }
12adba34 13558
23e8bd86
GM
13559 /* We may start in a continuation line. If so, we have to
13560 get the right continuation_lines_width and current_x. */
13561 it.continuation_lines_width = last_row->continuation_lines_width;
13562 it.hpos = it.current_x = 0;
2311178e 13563
23e8bd86
GM
13564 /* Display the rest of the lines at the window end. */
13565 it.glyph_row = MATRIX_ROW (desired_matrix, it.vpos);
13566 while (it.current_y < it.last_visible_y
13567 && !fonts_changed_p)
5f5c8ee5 13568 {
23e8bd86
GM
13569 /* Is it always sure that the display agrees with lines in
13570 the current matrix? I don't think so, so we mark rows
13571 displayed invalid in the current matrix by setting their
13572 enabled_p flag to zero. */
13573 MATRIX_ROW (w->current_matrix, it.vpos)->enabled_p = 0;
13574 if (display_line (&it))
13575 last_text_row_at_end = it.glyph_row - 1;
5f5c8ee5
GM
13576 }
13577 }
12adba34 13578
5f5c8ee5
GM
13579 /* Update window_end_pos and window_end_vpos. */
13580 if (first_unchanged_at_end_row
13581 && first_unchanged_at_end_row->y < it.last_visible_y
13582 && !last_text_row_at_end)
13583 {
13584 /* Window end line if one of the preserved rows from the current
13585 matrix. Set row to the last row displaying text in current
13586 matrix starting at first_unchanged_at_end_row, after
13587 scrolling. */
13588 xassert (first_unchanged_at_end_row->displays_text_p);
13589 row = find_last_row_displaying_text (w->current_matrix, &it,
13590 first_unchanged_at_end_row);
13591 xassert (row && MATRIX_ROW_DISPLAYS_TEXT_P (row));
2311178e 13592
ac90c44f 13593 w->window_end_pos = make_number (Z - MATRIX_ROW_END_CHARPOS (row));
5f5c8ee5 13594 w->window_end_bytepos = Z_BYTE - MATRIX_ROW_END_BYTEPOS (row);
ac90c44f
GM
13595 w->window_end_vpos
13596 = make_number (MATRIX_ROW_VPOS (row, w->current_matrix));
23fca891 13597 xassert (w->window_end_bytepos >= 0);
0416532f 13598 IF_DEBUG (debug_method_add (w, "A"));
5f5c8ee5
GM
13599 }
13600 else if (last_text_row_at_end)
13601 {
ac90c44f
GM
13602 w->window_end_pos
13603 = make_number (Z - MATRIX_ROW_END_CHARPOS (last_text_row_at_end));
5f5c8ee5
GM
13604 w->window_end_bytepos
13605 = Z_BYTE - MATRIX_ROW_END_BYTEPOS (last_text_row_at_end);
ac90c44f
GM
13606 w->window_end_vpos
13607 = make_number (MATRIX_ROW_VPOS (last_text_row_at_end, desired_matrix));
23fca891 13608 xassert (w->window_end_bytepos >= 0);
0416532f 13609 IF_DEBUG (debug_method_add (w, "B"));
5f5c8ee5
GM
13610 }
13611 else if (last_text_row)
13612 {
13613 /* We have displayed either to the end of the window or at the
13614 end of the window, i.e. the last row with text is to be found
13615 in the desired matrix. */
ac90c44f
GM
13616 w->window_end_pos
13617 = make_number (Z - MATRIX_ROW_END_CHARPOS (last_text_row));
5f5c8ee5
GM
13618 w->window_end_bytepos
13619 = Z_BYTE - MATRIX_ROW_END_BYTEPOS (last_text_row);
ac90c44f
GM
13620 w->window_end_vpos
13621 = make_number (MATRIX_ROW_VPOS (last_text_row, desired_matrix));
23fca891 13622 xassert (w->window_end_bytepos >= 0);
5f5c8ee5
GM
13623 }
13624 else if (first_unchanged_at_end_row == NULL
13625 && last_text_row == NULL
13626 && last_text_row_at_end == NULL)
13627 {
13628 /* Displayed to end of window, but no line containing text was
13629 displayed. Lines were deleted at the end of the window. */
0416532f
GM
13630 int first_vpos = WINDOW_WANTS_HEADER_LINE_P (w) ? 1 : 0;
13631 int vpos = XFASTINT (w->window_end_vpos);
13632 struct glyph_row *current_row = current_matrix->rows + vpos;
13633 struct glyph_row *desired_row = desired_matrix->rows + vpos;
13634
13635 for (row = NULL;
13636 row == NULL && vpos >= first_vpos;
13637 --vpos, --current_row, --desired_row)
13638 {
13639 if (desired_row->enabled_p)
13640 {
13641 if (desired_row->displays_text_p)
13642 row = desired_row;
13643 }
13644 else if (current_row->displays_text_p)
13645 row = current_row;
13646 }
12adba34 13647
0416532f 13648 xassert (row != NULL);
d88a79d4 13649 w->window_end_vpos = make_number (vpos + 1);
8c56a983
GM
13650 w->window_end_pos = make_number (Z - MATRIX_ROW_END_CHARPOS (row));
13651 w->window_end_bytepos = Z_BYTE - MATRIX_ROW_END_BYTEPOS (row);
23fca891 13652 xassert (w->window_end_bytepos >= 0);
0416532f 13653 IF_DEBUG (debug_method_add (w, "C"));
5f5c8ee5
GM
13654 }
13655 else
13656 abort ();
ac90c44f 13657
8cdb267e
GM
13658#if 0 /* This leads to problems, for instance when the cursor is
13659 at ZV, and the cursor line displays no text. */
ac90c44f
GM
13660 /* Disable rows below what's displayed in the window. This makes
13661 debugging easier. */
13662 enable_glyph_matrix_rows (current_matrix,
13663 XFASTINT (w->window_end_vpos) + 1,
13664 bottom_vpos, 0);
8cdb267e 13665#endif
23e8bd86 13666
5f5c8ee5
GM
13667 IF_DEBUG (debug_end_pos = XFASTINT (w->window_end_pos);
13668 debug_end_vpos = XFASTINT (w->window_end_vpos));
12adba34 13669
5f5c8ee5
GM
13670 /* Record that display has not been completed. */
13671 w->window_end_valid = Qnil;
13672 w->desired_matrix->no_scrolling_p = 1;
ef121659 13673 return 3;
27d16f05
GM
13674
13675#undef GIVE_UP
12adba34 13676}
0f9c0ff0 13677
a2889657 13678
5f5c8ee5
GM
13679\f
13680/***********************************************************************
13681 More debugging support
13682 ***********************************************************************/
a2889657 13683
5f5c8ee5 13684#if GLYPH_DEBUG
a2889657 13685
eaaa65b0 13686void dump_glyph_row P_ ((struct glyph_row *, int, int));
9ab436b9 13687void dump_glyph_matrix P_ ((struct glyph_matrix *, int));
e187cf71 13688void dump_glyph P_ ((struct glyph_row *, struct glyph *, int));
1c9241f5 13689
31b24551 13690
9ab436b9 13691/* Dump the contents of glyph matrix MATRIX on stderr.
ca26e1c8 13692
9ab436b9
GM
13693 GLYPHS 0 means don't show glyph contents.
13694 GLYPHS 1 means show glyphs in short form
13695 GLYPHS > 1 means show glyphs in long form. */
13696
13697void
13698dump_glyph_matrix (matrix, glyphs)
5f5c8ee5 13699 struct glyph_matrix *matrix;
9ab436b9 13700 int glyphs;
5f5c8ee5 13701{
efc63ef0 13702 int i;
5f5c8ee5 13703 for (i = 0; i < matrix->nrows; ++i)
eaaa65b0 13704 dump_glyph_row (MATRIX_ROW (matrix, i), i, glyphs);
5f5c8ee5 13705}
31b24551 13706
68a37fa8 13707
e187cf71
GM
13708/* Dump contents of glyph GLYPH to stderr. ROW and AREA are
13709 the glyph row and area where the glyph comes from. */
13710
13711void
13712dump_glyph (row, glyph, area)
13713 struct glyph_row *row;
13714 struct glyph *glyph;
13715 int area;
13716{
13717 if (glyph->type == CHAR_GLYPH)
13718 {
13719 fprintf (stderr,
13720 " %5d %4c %6d %c %3d 0x%05x %c %4d %1.1d%1.1d\n",
13721 glyph - row->glyphs[TEXT_AREA],
13722 'C',
13723 glyph->charpos,
13724 (BUFFERP (glyph->object)
13725 ? 'B'
13726 : (STRINGP (glyph->object)
13727 ? 'S'
13728 : '-')),
13729 glyph->pixel_width,
13730 glyph->u.ch,
13731 (glyph->u.ch < 0x80 && glyph->u.ch >= ' '
13732 ? glyph->u.ch
13733 : '.'),
13734 glyph->face_id,
13735 glyph->left_box_line_p,
13736 glyph->right_box_line_p);
13737 }
13738 else if (glyph->type == STRETCH_GLYPH)
13739 {
13740 fprintf (stderr,
13741 " %5d %4c %6d %c %3d 0x%05x %c %4d %1.1d%1.1d\n",
13742 glyph - row->glyphs[TEXT_AREA],
13743 'S',
13744 glyph->charpos,
13745 (BUFFERP (glyph->object)
13746 ? 'B'
13747 : (STRINGP (glyph->object)
13748 ? 'S'
13749 : '-')),
13750 glyph->pixel_width,
13751 0,
13752 '.',
13753 glyph->face_id,
13754 glyph->left_box_line_p,
13755 glyph->right_box_line_p);
13756 }
13757 else if (glyph->type == IMAGE_GLYPH)
13758 {
13759 fprintf (stderr,
13760 " %5d %4c %6d %c %3d 0x%05x %c %4d %1.1d%1.1d\n",
13761 glyph - row->glyphs[TEXT_AREA],
13762 'I',
13763 glyph->charpos,
13764 (BUFFERP (glyph->object)
13765 ? 'B'
13766 : (STRINGP (glyph->object)
13767 ? 'S'
13768 : '-')),
13769 glyph->pixel_width,
13770 glyph->u.img_id,
13771 '.',
13772 glyph->face_id,
13773 glyph->left_box_line_p,
13774 glyph->right_box_line_p);
13775 }
13776}
13777
13778
5f5c8ee5 13779/* Dump the contents of glyph row at VPOS in MATRIX to stderr.
9ab436b9
GM
13780 GLYPHS 0 means don't show glyph contents.
13781 GLYPHS 1 means show glyphs in short form
13782 GLYPHS > 1 means show glyphs in long form. */
a2889657 13783
5f5c8ee5 13784void
eaaa65b0
GM
13785dump_glyph_row (row, vpos, glyphs)
13786 struct glyph_row *row;
9ab436b9 13787 int vpos, glyphs;
5f5c8ee5 13788{
9ab436b9
GM
13789 if (glyphs != 1)
13790 {
b94c0d9c 13791 fprintf (stderr, "Row Start End Used oEI><O\\CTZFesm X Y W H V A P\n");
9ab436b9 13792 fprintf (stderr, "=======================================================================\n");
2311178e 13793
0ad38729 13794 fprintf (stderr, "%3d %5d %5d %4d %1.1d%1.1d%1.1d%1.1d%1.1d\
33ea6c4d 13795%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 13796 vpos,
9ab436b9
GM
13797 MATRIX_ROW_START_CHARPOS (row),
13798 MATRIX_ROW_END_CHARPOS (row),
13799 row->used[TEXT_AREA],
13800 row->contains_overlapping_glyphs_p,
13801 row->enabled_p,
9ab436b9
GM
13802 row->truncated_on_left_p,
13803 row->truncated_on_right_p,
13804 row->overlay_arrow_p,
13805 row->continued_p,
13806 MATRIX_ROW_CONTINUATION_LINE_P (row),
13807 row->displays_text_p,
13808 row->ends_at_zv_p,
13809 row->fill_line_p,
13810 row->ends_in_middle_of_char_p,
13811 row->starts_in_middle_of_char_p,
b94c0d9c 13812 row->mouse_face_p,
9ab436b9
GM
13813 row->x,
13814 row->y,
13815 row->pixel_width,
13816 row->height,
13817 row->visible_height,
13818 row->ascent,
13819 row->phys_ascent);
33ea6c4d
GM
13820 fprintf (stderr, "%9d %5d\t%5d\n", row->start.overlay_string_index,
13821 row->end.overlay_string_index,
13822 row->continuation_lines_width);
9ab436b9
GM
13823 fprintf (stderr, "%9d %5d\n",
13824 CHARPOS (row->start.string_pos),
13825 CHARPOS (row->end.string_pos));
13826 fprintf (stderr, "%9d %5d\n", row->start.dpvec_index,
13827 row->end.dpvec_index);
13828 }
2311178e 13829
9ab436b9 13830 if (glyphs > 1)
bd66d1ba 13831 {
e187cf71
GM
13832 int area;
13833
13834 for (area = LEFT_MARGIN_AREA; area < LAST_AREA; ++area)
13835 {
091f8878
GM
13836 struct glyph *glyph = row->glyphs[area];
13837 struct glyph *glyph_end = glyph + row->used[area];
2311178e 13838
e187cf71 13839 /* Glyph for a line end in text. */
091f8878 13840 if (area == TEXT_AREA && glyph == glyph_end && glyph->charpos > 0)
e187cf71 13841 ++glyph_end;
2311178e 13842
e187cf71
GM
13843 if (glyph < glyph_end)
13844 fprintf (stderr, " Glyph Type Pos O W Code C Face LR\n");
2311178e 13845
e187cf71
GM
13846 for (; glyph < glyph_end; ++glyph)
13847 dump_glyph (row, glyph, area);
f7b4b63a 13848 }
f4faa47c 13849 }
9ab436b9
GM
13850 else if (glyphs == 1)
13851 {
e187cf71 13852 int area;
9ab436b9 13853
e187cf71 13854 for (area = LEFT_MARGIN_AREA; area < LAST_AREA; ++area)
9ab436b9 13855 {
e187cf71
GM
13856 char *s = (char *) alloca (row->used[area] + 1);
13857 int i;
13858
13859 for (i = 0; i < row->used[area]; ++i)
13860 {
13861 struct glyph *glyph = row->glyphs[area] + i;
13862 if (glyph->type == CHAR_GLYPH
13863 && glyph->u.ch < 0x80
13864 && glyph->u.ch >= ' ')
13865 s[i] = glyph->u.ch;
13866 else
13867 s[i] = '.';
13868 }
2311178e 13869
e187cf71
GM
13870 s[i] = '\0';
13871 fprintf (stderr, "%3d: (%d) '%s'\n", vpos, row->enabled_p, s);
13872 }
9ab436b9 13873 }
5f5c8ee5 13874}
f4faa47c 13875
a2889657 13876
5f5c8ee5
GM
13877DEFUN ("dump-glyph-matrix", Fdump_glyph_matrix,
13878 Sdump_glyph_matrix, 0, 1, "p",
7ee72033 13879 doc: /* Dump the current matrix of the selected window to stderr.
228299fa
GM
13880Shows contents of glyph row structures. With non-nil
13881parameter GLYPHS, dump glyphs as well. If GLYPHS is 1 show
7ee72033
MB
13882glyphs in short form, otherwise show glyphs in long form. */)
13883 (glyphs)
9ab436b9 13884 Lisp_Object glyphs;
5f5c8ee5
GM
13885{
13886 struct window *w = XWINDOW (selected_window);
13887 struct buffer *buffer = XBUFFER (w->buffer);
13888
13889 fprintf (stderr, "PT = %d, BEGV = %d. ZV = %d\n",
13890 BUF_PT (buffer), BUF_BEGV (buffer), BUF_ZV (buffer));
13891 fprintf (stderr, "Cursor x = %d, y = %d, hpos = %d, vpos = %d\n",
13892 w->cursor.x, w->cursor.y, w->cursor.hpos, w->cursor.vpos);
13893 fprintf (stderr, "=============================================\n");
9ab436b9
GM
13894 dump_glyph_matrix (w->current_matrix,
13895 NILP (glyphs) ? 0 : XINT (glyphs));
5f5c8ee5
GM
13896 return Qnil;
13897}
1c2250c2 13898
1fca3fae 13899
7d4cc828
GM
13900DEFUN ("dump-frame-glyph-matrix", Fdump_frame_glyph_matrix,
13901 Sdump_frame_glyph_matrix, 0, 0, "", doc: /* */)
13902 ()
13903{
13904 struct frame *f = XFRAME (selected_frame);
13905 dump_glyph_matrix (f->current_matrix, 1);
13906 return Qnil;
13907}
13908
13909
e9abc296 13910DEFUN ("dump-glyph-row", Fdump_glyph_row, Sdump_glyph_row, 1, 2, "",
7ee72033 13911 doc: /* Dump glyph row ROW to stderr.
228299fa
GM
13912GLYPH 0 means don't dump glyphs.
13913GLYPH 1 means dump glyphs in short form.
7ee72033
MB
13914GLYPH > 1 or omitted means dump glyphs in long form. */)
13915 (row, glyphs)
e9abc296 13916 Lisp_Object row, glyphs;
5f5c8ee5 13917{
eaaa65b0
GM
13918 struct glyph_matrix *matrix;
13919 int vpos;
2311178e 13920
b7826503 13921 CHECK_NUMBER (row);
eaaa65b0
GM
13922 matrix = XWINDOW (selected_window)->current_matrix;
13923 vpos = XINT (row);
13924 if (vpos >= 0 && vpos < matrix->nrows)
13925 dump_glyph_row (MATRIX_ROW (matrix, vpos),
13926 vpos,
13927 INTEGERP (glyphs) ? XINT (glyphs) : 2);
5f5c8ee5
GM
13928 return Qnil;
13929}
1fca3fae 13930
67481ae5 13931
b94c0d9c 13932DEFUN ("dump-tool-bar-row", Fdump_tool_bar_row, Sdump_tool_bar_row, 1, 2, "",
c2552f79 13933 doc: /* Dump glyph row ROW of the tool-bar of the current frame to stderr.
228299fa
GM
13934GLYPH 0 means don't dump glyphs.
13935GLYPH 1 means dump glyphs in short form.
7ee72033
MB
13936GLYPH > 1 or omitted means dump glyphs in long form. */)
13937 (row, glyphs)
b94c0d9c 13938 Lisp_Object row, glyphs;
5f5c8ee5 13939{
886bd6f2 13940 struct frame *sf = SELECTED_FRAME ();
eaaa65b0
GM
13941 struct glyph_matrix *m = XWINDOW (sf->tool_bar_window)->current_matrix;
13942 int vpos;
2311178e 13943
b7826503 13944 CHECK_NUMBER (row);
eaaa65b0
GM
13945 vpos = XINT (row);
13946 if (vpos >= 0 && vpos < m->nrows)
13947 dump_glyph_row (MATRIX_ROW (m, vpos), vpos,
13948 INTEGERP (glyphs) ? XINT (glyphs) : 2);
5f5c8ee5
GM
13949 return Qnil;
13950}
ca26e1c8 13951
0f9c0ff0 13952
62397849 13953DEFUN ("trace-redisplay", Ftrace_redisplay, Strace_redisplay, 0, 1, "P",
7ee72033
MB
13954 doc: /* Toggle tracing of redisplay.
13955With ARG, turn tracing on if and only if ARG is positive. */)
13956 (arg)
62397849 13957 Lisp_Object arg;
5f5c8ee5 13958{
62397849
GM
13959 if (NILP (arg))
13960 trace_redisplay_p = !trace_redisplay_p;
13961 else
13962 {
13963 arg = Fprefix_numeric_value (arg);
13964 trace_redisplay_p = XINT (arg) > 0;
13965 }
2311178e 13966
5f5c8ee5
GM
13967 return Qnil;
13968}
bf9249e3
GM
13969
13970
f4a374a1 13971DEFUN ("trace-to-stderr", Ftrace_to_stderr, Strace_to_stderr, 1, MANY, "",
e9757d41
SM
13972 doc: /* Like `format', but print result to stderr.
13973usage: (trace-to-stderr STRING &rest OBJECTS) */)
7ee72033 13974 (nargs, args)
f4a374a1
GM
13975 int nargs;
13976 Lisp_Object *args;
bf9249e3 13977{
f4a374a1 13978 Lisp_Object s = Fformat (nargs, args);
2051c264 13979 fprintf (stderr, "%s", SDATA (s));
bf9249e3
GM
13980 return Qnil;
13981}
2311178e 13982
5f5c8ee5 13983#endif /* GLYPH_DEBUG */
ca26e1c8 13984
ca26e1c8 13985
5f5c8ee5
GM
13986\f
13987/***********************************************************************
13988 Building Desired Matrix Rows
13989 ***********************************************************************/
a2889657 13990
5f5c8ee5
GM
13991/* Return a temporary glyph row holding the glyphs of an overlay
13992 arrow. Only used for non-window-redisplay windows. */
ca26e1c8 13993
5f5c8ee5 13994static struct glyph_row *
6b61353c 13995get_overlay_arrow_glyph_row (w, overlay_arrow_string)
5f5c8ee5 13996 struct window *w;
6b61353c 13997 Lisp_Object overlay_arrow_string;
5f5c8ee5
GM
13998{
13999 struct frame *f = XFRAME (WINDOW_FRAME (w));
14000 struct buffer *buffer = XBUFFER (w->buffer);
14001 struct buffer *old = current_buffer;
6b61353c
KH
14002 const unsigned char *arrow_string = SDATA (overlay_arrow_string);
14003 int arrow_len = SCHARS (overlay_arrow_string);
50f80c2f
KR
14004 const unsigned char *arrow_end = arrow_string + arrow_len;
14005 const unsigned char *p;
5f5c8ee5
GM
14006 struct it it;
14007 int multibyte_p;
14008 int n_glyphs_before;
14009
14010 set_buffer_temp (buffer);
14011 init_iterator (&it, w, -1, -1, &scratch_glyph_row, DEFAULT_FACE_ID);
14012 it.glyph_row->used[TEXT_AREA] = 0;
14013 SET_TEXT_POS (it.position, 0, 0);
14014
14015 multibyte_p = !NILP (buffer->enable_multibyte_characters);
14016 p = arrow_string;
14017 while (p < arrow_end)
14018 {
14019 Lisp_Object face, ilisp;
2311178e 14020
5f5c8ee5
GM
14021 /* Get the next character. */
14022 if (multibyte_p)
4fdb80f2 14023 it.c = string_char_and_length (p, arrow_len, &it.len);
5f5c8ee5
GM
14024 else
14025 it.c = *p, it.len = 1;
14026 p += it.len;
2311178e 14027
5f5c8ee5 14028 /* Get its face. */
ac90c44f 14029 ilisp = make_number (p - arrow_string);
6b61353c 14030 face = Fget_text_property (ilisp, Qface, overlay_arrow_string);
5f5c8ee5
GM
14031 it.face_id = compute_char_face (f, it.c, face);
14032
14033 /* Compute its width, get its glyphs. */
14034 n_glyphs_before = it.glyph_row->used[TEXT_AREA];
337042a9 14035 SET_TEXT_POS (it.position, -1, -1);
5f5c8ee5
GM
14036 PRODUCE_GLYPHS (&it);
14037
14038 /* If this character doesn't fit any more in the line, we have
14039 to remove some glyphs. */
14040 if (it.current_x > it.last_visible_x)
14041 {
14042 it.glyph_row->used[TEXT_AREA] = n_glyphs_before;
14043 break;
14044 }
14045 }
2311178e 14046
5f5c8ee5
GM
14047 set_buffer_temp (old);
14048 return it.glyph_row;
14049}
ca26e1c8 14050
b0a0fbda 14051
5f5c8ee5
GM
14052/* Insert truncation glyphs at the start of IT->glyph_row. Truncation
14053 glyphs are only inserted for terminal frames since we can't really
14054 win with truncation glyphs when partially visible glyphs are
14055 involved. Which glyphs to insert is determined by
14056 produce_special_glyphs. */
67481ae5 14057
5f5c8ee5
GM
14058static void
14059insert_left_trunc_glyphs (it)
14060 struct it *it;
14061{
14062 struct it truncate_it;
14063 struct glyph *from, *end, *to, *toend;
14064
14065 xassert (!FRAME_WINDOW_P (it->f));
14066
14067 /* Get the truncation glyphs. */
14068 truncate_it = *it;
5f5c8ee5
GM
14069 truncate_it.current_x = 0;
14070 truncate_it.face_id = DEFAULT_FACE_ID;
14071 truncate_it.glyph_row = &scratch_glyph_row;
14072 truncate_it.glyph_row->used[TEXT_AREA] = 0;
14073 CHARPOS (truncate_it.position) = BYTEPOS (truncate_it.position) = -1;
6fc556fd 14074 truncate_it.object = make_number (0);
5f5c8ee5 14075 produce_special_glyphs (&truncate_it, IT_TRUNCATION);
2311178e 14076
5f5c8ee5
GM
14077 /* Overwrite glyphs from IT with truncation glyphs. */
14078 from = truncate_it.glyph_row->glyphs[TEXT_AREA];
14079 end = from + truncate_it.glyph_row->used[TEXT_AREA];
14080 to = it->glyph_row->glyphs[TEXT_AREA];
14081 toend = to + it->glyph_row->used[TEXT_AREA];
14082
14083 while (from < end)
14084 *to++ = *from++;
14085
37be86f2
KH
14086 /* There may be padding glyphs left over. Overwrite them too. */
14087 while (to < toend && CHAR_GLYPH_PADDING_P (*to))
14088 {
14089 from = truncate_it.glyph_row->glyphs[TEXT_AREA];
14090 while (from < end)
14091 *to++ = *from++;
14092 }
5f5c8ee5 14093
37be86f2
KH
14094 if (to > toend)
14095 it->glyph_row->used[TEXT_AREA] = to - it->glyph_row->glyphs[TEXT_AREA];
5f5c8ee5 14096}
e0bfbde6 14097
e0bfbde6 14098
5f5c8ee5 14099/* Compute the pixel height and width of IT->glyph_row.
9c49d3d7 14100
5f5c8ee5
GM
14101 Most of the time, ascent and height of a display line will be equal
14102 to the max_ascent and max_height values of the display iterator
14103 structure. This is not the case if
67481ae5 14104
5f5c8ee5
GM
14105 1. We hit ZV without displaying anything. In this case, max_ascent
14106 and max_height will be zero.
1c9241f5 14107
5f5c8ee5
GM
14108 2. We have some glyphs that don't contribute to the line height.
14109 (The glyph row flag contributes_to_line_height_p is for future
14110 pixmap extensions).
f6fd109b 14111
5f5c8ee5
GM
14112 The first case is easily covered by using default values because in
14113 these cases, the line height does not really matter, except that it
14114 must not be zero. */
67481ae5 14115
5f5c8ee5
GM
14116static void
14117compute_line_metrics (it)
14118 struct it *it;
14119{
14120 struct glyph_row *row = it->glyph_row;
14121 int area, i;
1c2250c2 14122
5f5c8ee5
GM
14123 if (FRAME_WINDOW_P (it->f))
14124 {
75c5350a 14125 int i, min_y, max_y;
1c2250c2 14126
5f5c8ee5
GM
14127 /* The line may consist of one space only, that was added to
14128 place the cursor on it. If so, the row's height hasn't been
14129 computed yet. */
14130 if (row->height == 0)
14131 {
14132 if (it->max_ascent + it->max_descent == 0)
da8b7f4f 14133 it->max_descent = it->max_phys_descent = FRAME_LINE_HEIGHT (it->f);
5f5c8ee5
GM
14134 row->ascent = it->max_ascent;
14135 row->height = it->max_ascent + it->max_descent;
312246d1
GM
14136 row->phys_ascent = it->max_phys_ascent;
14137 row->phys_height = it->max_phys_ascent + it->max_phys_descent;
5f5c8ee5 14138 }
2311178e 14139
5f5c8ee5
GM
14140 /* Compute the width of this line. */
14141 row->pixel_width = row->x;
14142 for (i = 0; i < row->used[TEXT_AREA]; ++i)
14143 row->pixel_width += row->glyphs[TEXT_AREA][i].pixel_width;
14144
14145 xassert (row->pixel_width >= 0);
14146 xassert (row->ascent >= 0 && row->height > 0);
14147
312246d1
GM
14148 row->overlapping_p = (MATRIX_ROW_OVERLAPS_SUCC_P (row)
14149 || MATRIX_ROW_OVERLAPS_PRED_P (row));
14150
14151 /* If first line's physical ascent is larger than its logical
14152 ascent, use the physical ascent, and make the row taller.
14153 This makes accented characters fully visible. */
b28cb6ed 14154 if (row == MATRIX_FIRST_TEXT_ROW (it->w->desired_matrix)
312246d1
GM
14155 && row->phys_ascent > row->ascent)
14156 {
14157 row->height += row->phys_ascent - row->ascent;
14158 row->ascent = row->phys_ascent;
14159 }
14160
5f5c8ee5
GM
14161 /* Compute how much of the line is visible. */
14162 row->visible_height = row->height;
2311178e 14163
da8b7f4f
KS
14164 min_y = WINDOW_HEADER_LINE_HEIGHT (it->w);
14165 max_y = WINDOW_BOX_HEIGHT_NO_MODE_LINE (it->w);
75c5350a
GM
14166
14167 if (row->y < min_y)
14168 row->visible_height -= min_y - row->y;
14169 if (row->y + row->height > max_y)
14170 row->visible_height -= row->y + row->height - max_y;
5f5c8ee5
GM
14171 }
14172 else
14173 {
14174 row->pixel_width = row->used[TEXT_AREA];
33ea6c4d
GM
14175 if (row->continued_p)
14176 row->pixel_width -= it->continuation_pixel_width;
14177 else if (row->truncated_on_right_p)
14178 row->pixel_width -= it->truncation_pixel_width;
312246d1
GM
14179 row->ascent = row->phys_ascent = 0;
14180 row->height = row->phys_height = row->visible_height = 1;
5f5c8ee5 14181 }
67481ae5 14182
5f5c8ee5
GM
14183 /* Compute a hash code for this row. */
14184 row->hash = 0;
14185 for (area = LEFT_MARGIN_AREA; area < LAST_AREA; ++area)
14186 for (i = 0; i < row->used[area]; ++i)
14187 row->hash = ((((row->hash << 4) + (row->hash >> 24)) & 0x0fffffff)
14188 + row->glyphs[area][i].u.val
43d120d8
KH
14189 + row->glyphs[area][i].face_id
14190 + row->glyphs[area][i].padding_p
5f5c8ee5 14191 + (row->glyphs[area][i].type << 2));
a2889657 14192
5f5c8ee5 14193 it->max_ascent = it->max_descent = 0;
312246d1 14194 it->max_phys_ascent = it->max_phys_descent = 0;
5f5c8ee5 14195}
12adba34 14196
ca26e1c8 14197
5f5c8ee5
GM
14198/* Append one space to the glyph row of iterator IT if doing a
14199 window-based redisplay. DEFAULT_FACE_P non-zero means let the
14200 space have the default face, otherwise let it have the same face as
80c6cb1f 14201 IT->face_id. Value is non-zero if a space was added.
c6e89d6c
GM
14202
14203 This function is called to make sure that there is always one glyph
14204 at the end of a glyph row that the cursor can be set on under
14205 window-systems. (If there weren't such a glyph we would not know
14206 how wide and tall a box cursor should be displayed).
14207
14208 At the same time this space let's a nicely handle clearing to the
14209 end of the line if the row ends in italic text. */
ca26e1c8 14210
80c6cb1f 14211static int
5f5c8ee5
GM
14212append_space (it, default_face_p)
14213 struct it *it;
14214 int default_face_p;
14215{
14216 if (FRAME_WINDOW_P (it->f))
14217 {
14218 int n = it->glyph_row->used[TEXT_AREA];
ca26e1c8 14219
5f5c8ee5
GM
14220 if (it->glyph_row->glyphs[TEXT_AREA] + n
14221 < it->glyph_row->glyphs[1 + TEXT_AREA])
a2889657 14222 {
cafafe0b
GM
14223 /* Save some values that must not be changed.
14224 Must save IT->c and IT->len because otherwise
14225 ITERATOR_AT_END_P wouldn't work anymore after
14226 append_space has been called. */
478d746b 14227 enum display_element_type saved_what = it->what;
cafafe0b
GM
14228 int saved_c = it->c, saved_len = it->len;
14229 int saved_x = it->current_x;
5f5c8ee5 14230 int saved_face_id = it->face_id;
cafafe0b 14231 struct text_pos saved_pos;
5f5c8ee5 14232 Lisp_Object saved_object;
980806b6 14233 struct face *face;
5f5c8ee5
GM
14234
14235 saved_object = it->object;
14236 saved_pos = it->position;
2311178e 14237
5f5c8ee5
GM
14238 it->what = IT_CHARACTER;
14239 bzero (&it->position, sizeof it->position);
6fc556fd 14240 it->object = make_number (0);
5f5c8ee5
GM
14241 it->c = ' ';
14242 it->len = 1;
5f5c8ee5
GM
14243
14244 if (default_face_p)
14245 it->face_id = DEFAULT_FACE_ID;
4aad61f8
GM
14246 else if (it->face_before_selective_p)
14247 it->face_id = it->saved_face_id;
980806b6 14248 face = FACE_FROM_ID (it->f, it->face_id);
f46a4dc1 14249 it->face_id = FACE_FOR_CHAR (it->f, face, 0, -1, Qnil);
1842fc1a 14250
5f5c8ee5 14251 PRODUCE_GLYPHS (it);
2311178e 14252
5f5c8ee5
GM
14253 it->current_x = saved_x;
14254 it->object = saved_object;
14255 it->position = saved_pos;
14256 it->what = saved_what;
14257 it->face_id = saved_face_id;
cafafe0b
GM
14258 it->len = saved_len;
14259 it->c = saved_c;
80c6cb1f 14260 return 1;
5f5c8ee5
GM
14261 }
14262 }
80c6cb1f
GM
14263
14264 return 0;
5f5c8ee5 14265}
12adba34 14266
1842fc1a 14267
5f5c8ee5
GM
14268/* Extend the face of the last glyph in the text area of IT->glyph_row
14269 to the end of the display line. Called from display_line.
14270 If the glyph row is empty, add a space glyph to it so that we
14271 know the face to draw. Set the glyph row flag fill_line_p. */
2311178e 14272
5f5c8ee5
GM
14273static void
14274extend_face_to_end_of_line (it)
14275 struct it *it;
14276{
14277 struct face *face;
14278 struct frame *f = it->f;
1842fc1a 14279
5f5c8ee5
GM
14280 /* If line is already filled, do nothing. */
14281 if (it->current_x >= it->last_visible_x)
14282 return;
2311178e 14283
5f5c8ee5
GM
14284 /* Face extension extends the background and box of IT->face_id
14285 to the end of the line. If the background equals the background
4aad61f8
GM
14286 of the frame, we don't have to do anything. */
14287 if (it->face_before_selective_p)
14288 face = FACE_FROM_ID (it->f, it->saved_face_id);
14289 else
14290 face = FACE_FROM_ID (f, it->face_id);
2311178e 14291
5f5c8ee5
GM
14292 if (FRAME_WINDOW_P (f)
14293 && face->box == FACE_NO_BOX
14294 && face->background == FRAME_BACKGROUND_PIXEL (f)
14295 && !face->stipple)
14296 return;
1842fc1a 14297
5f5c8ee5
GM
14298 /* Set the glyph row flag indicating that the face of the last glyph
14299 in the text area has to be drawn to the end of the text area. */
14300 it->glyph_row->fill_line_p = 1;
545e04f6 14301
980806b6
KH
14302 /* If current character of IT is not ASCII, make sure we have the
14303 ASCII face. This will be automatically undone the next time
14304 get_next_display_element returns a multibyte character. Note
14305 that the character will always be single byte in unibyte text. */
522b161c 14306 if (!ASCII_CHAR_P (it->c))
5f5c8ee5 14307 {
f46a4dc1 14308 it->face_id = FACE_FOR_CHAR (f, face, 0, -1, Qnil);
5f5c8ee5 14309 }
545e04f6 14310
5f5c8ee5
GM
14311 if (FRAME_WINDOW_P (f))
14312 {
14313 /* If the row is empty, add a space with the current face of IT,
14314 so that we know which face to draw. */
14315 if (it->glyph_row->used[TEXT_AREA] == 0)
a2889657 14316 {
5f5c8ee5 14317 it->glyph_row->glyphs[TEXT_AREA][0] = space_glyph;
43d120d8 14318 it->glyph_row->glyphs[TEXT_AREA][0].face_id = it->face_id;
5f5c8ee5 14319 it->glyph_row->used[TEXT_AREA] = 1;
a2889657 14320 }
5f5c8ee5
GM
14321 }
14322 else
14323 {
14324 /* Save some values that must not be changed. */
14325 int saved_x = it->current_x;
14326 struct text_pos saved_pos;
14327 Lisp_Object saved_object;
478d746b 14328 enum display_element_type saved_what = it->what;
4aad61f8 14329 int saved_face_id = it->face_id;
5f5c8ee5
GM
14330
14331 saved_object = it->object;
14332 saved_pos = it->position;
2311178e 14333
5f5c8ee5
GM
14334 it->what = IT_CHARACTER;
14335 bzero (&it->position, sizeof it->position);
6fc556fd 14336 it->object = make_number (0);
5f5c8ee5
GM
14337 it->c = ' ';
14338 it->len = 1;
4aad61f8 14339 it->face_id = face->id;
2311178e 14340
5f5c8ee5 14341 PRODUCE_GLYPHS (it);
2311178e 14342
5f5c8ee5
GM
14343 while (it->current_x <= it->last_visible_x)
14344 PRODUCE_GLYPHS (it);
2311178e 14345
5f5c8ee5
GM
14346 /* Don't count these blanks really. It would let us insert a left
14347 truncation glyph below and make us set the cursor on them, maybe. */
14348 it->current_x = saved_x;
14349 it->object = saved_object;
14350 it->position = saved_pos;
14351 it->what = saved_what;
4aad61f8 14352 it->face_id = saved_face_id;
5f5c8ee5
GM
14353 }
14354}
12adba34 14355
545e04f6 14356
5f5c8ee5
GM
14357/* Value is non-zero if text starting at CHARPOS in current_buffer is
14358 trailing whitespace. */
1c9241f5 14359
5f5c8ee5
GM
14360static int
14361trailing_whitespace_p (charpos)
14362 int charpos;
14363{
14364 int bytepos = CHAR_TO_BYTE (charpos);
14365 int c = 0;
7bbe686f 14366
5f5c8ee5
GM
14367 while (bytepos < ZV_BYTE
14368 && (c = FETCH_CHAR (bytepos),
14369 c == ' ' || c == '\t'))
14370 ++bytepos;
0d09d1e6 14371
8f897821
GM
14372 if (bytepos >= ZV_BYTE || c == '\n' || c == '\r')
14373 {
14374 if (bytepos != PT_BYTE)
14375 return 1;
14376 }
14377 return 0;
5f5c8ee5 14378}
31b24551 14379
545e04f6 14380
5f5c8ee5 14381/* Highlight trailing whitespace, if any, in ROW. */
545e04f6 14382
5f5c8ee5
GM
14383void
14384highlight_trailing_whitespace (f, row)
14385 struct frame *f;
14386 struct glyph_row *row;
14387{
14388 int used = row->used[TEXT_AREA];
2311178e 14389
5f5c8ee5
GM
14390 if (used)
14391 {
14392 struct glyph *start = row->glyphs[TEXT_AREA];
14393 struct glyph *glyph = start + used - 1;
14394
ade0bee1
GM
14395 /* Skip over glyphs inserted to display the cursor at the
14396 end of a line, for extending the face of the last glyph
14397 to the end of the line on terminals, and for truncation
14398 and continuation glyphs. */
65008712
GM
14399 while (glyph >= start
14400 && glyph->type == CHAR_GLYPH
65008712 14401 && INTEGERP (glyph->object))
5f5c8ee5
GM
14402 --glyph;
14403
14404 /* If last glyph is a space or stretch, and it's trailing
14405 whitespace, set the face of all trailing whitespace glyphs in
14406 IT->glyph_row to `trailing-whitespace'. */
14407 if (glyph >= start
14408 && BUFFERP (glyph->object)
14409 && (glyph->type == STRETCH_GLYPH
14410 || (glyph->type == CHAR_GLYPH
43d120d8 14411 && glyph->u.ch == ' '))
5f5c8ee5 14412 && trailing_whitespace_p (glyph->charpos))
545e04f6 14413 {
522b161c 14414 int face_id = lookup_named_face (f, Qtrailing_whitespace);
2311178e 14415
5f5c8ee5
GM
14416 while (glyph >= start
14417 && BUFFERP (glyph->object)
14418 && (glyph->type == STRETCH_GLYPH
14419 || (glyph->type == CHAR_GLYPH
43d120d8
KH
14420 && glyph->u.ch == ' ')))
14421 (glyph--)->face_id = face_id;
545e04f6 14422 }
a2889657 14423 }
5f5c8ee5 14424}
a2889657 14425
5fcbb24d 14426
cafafe0b 14427/* Value is non-zero if glyph row ROW in window W should be
0fd37545 14428 used to hold the cursor. */
cafafe0b
GM
14429
14430static int
14431cursor_row_p (w, row)
14432 struct window *w;
14433 struct glyph_row *row;
14434{
9a038881 14435 int cursor_row_p = 1;
2311178e 14436
cafafe0b
GM
14437 if (PT == MATRIX_ROW_END_CHARPOS (row))
14438 {
9a038881
GM
14439 /* If the row ends with a newline from a string, we don't want
14440 the cursor there (if the row is continued it doesn't end in a
14441 newline). */
14442 if (CHARPOS (row->end.string_pos) >= 0
14443 || MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row))
14444 cursor_row_p = row->continued_p;
14445
14446 /* If the row ends at ZV, display the cursor at the end of that
14447 row instead of at the start of the row below. */
14448 else if (row->ends_at_zv_p)
14449 cursor_row_p = 1;
14450 else
14451 cursor_row_p = 0;
cafafe0b
GM
14452 }
14453
9a038881 14454 return cursor_row_p;
cafafe0b
GM
14455}
14456
14457
5f5c8ee5
GM
14458/* Construct the glyph row IT->glyph_row in the desired matrix of
14459 IT->w from text at the current position of IT. See dispextern.h
14460 for an overview of struct it. Value is non-zero if
14461 IT->glyph_row displays text, as opposed to a line displaying ZV
14462 only. */
2311178e 14463
5f5c8ee5
GM
14464static int
14465display_line (it)
14466 struct it *it;
14467{
14468 struct glyph_row *row = it->glyph_row;
6b61353c
KH
14469 int overlay_arrow_bitmap;
14470 Lisp_Object overlay_arrow_string;
5f5c8ee5
GM
14471
14472 /* We always start displaying at hpos zero even if hscrolled. */
14473 xassert (it->hpos == 0 && it->current_x == 0);
a2889657 14474
5f5c8ee5
GM
14475 /* We must not display in a row that's not a text row. */
14476 xassert (MATRIX_ROW_VPOS (row, it->w->desired_matrix)
14477 < it->w->desired_matrix->nrows);
12adba34 14478
5f5c8ee5
GM
14479 /* Is IT->w showing the region? */
14480 it->w->region_showing = it->region_beg_charpos > 0 ? Qt : Qnil;
12adba34 14481
5f5c8ee5
GM
14482 /* Clear the result glyph row and enable it. */
14483 prepare_desired_row (row);
12adba34 14484
5f5c8ee5 14485 row->y = it->current_y;
6b61353c 14486 row->start = it->start;
5f5c8ee5
GM
14487 row->continuation_lines_width = it->continuation_lines_width;
14488 row->displays_text_p = 1;
91004049
GM
14489 row->starts_in_middle_of_char_p = it->starts_in_middle_of_char_p;
14490 it->starts_in_middle_of_char_p = 0;
5f5c8ee5
GM
14491
14492 /* Arrange the overlays nicely for our purposes. Usually, we call
14493 display_line on only one line at a time, in which case this
14494 can't really hurt too much, or we call it on lines which appear
14495 one after another in the buffer, in which case all calls to
14496 recenter_overlay_lists but the first will be pretty cheap. */
14497 recenter_overlay_lists (current_buffer, IT_CHARPOS (*it));
14498
5f5c8ee5
GM
14499 /* Move over display elements that are not visible because we are
14500 hscrolled. This may stop at an x-position < IT->first_visible_x
14501 if the first glyph is partially visible or if we hit a line end. */
14502 if (it->current_x < it->first_visible_x)
14503 move_it_in_display_line_to (it, ZV, it->first_visible_x,
14504 MOVE_TO_POS | MOVE_TO_X);
14505
14506 /* Get the initial row height. This is either the height of the
14507 text hscrolled, if there is any, or zero. */
14508 row->ascent = it->max_ascent;
14509 row->height = it->max_ascent + it->max_descent;
312246d1
GM
14510 row->phys_ascent = it->max_phys_ascent;
14511 row->phys_height = it->max_phys_ascent + it->max_phys_descent;
5f5c8ee5
GM
14512
14513 /* Loop generating characters. The loop is left with IT on the next
14514 character to display. */
14515 while (1)
14516 {
14517 int n_glyphs_before, hpos_before, x_before;
14518 int x, i, nglyphs;
ae26e27d 14519 int ascent = 0, descent = 0, phys_ascent = 0, phys_descent = 0;
b28cb6ed 14520
5f5c8ee5
GM
14521 /* Retrieve the next thing to display. Value is zero if end of
14522 buffer reached. */
14523 if (!get_next_display_element (it))
14524 {
14525 /* Maybe add a space at the end of this line that is used to
1b335865
GM
14526 display the cursor there under X. Set the charpos of the
14527 first glyph of blank lines not corresponding to any text
14528 to -1. */
6b61353c
KH
14529#ifdef HAVE_WINDOW_SYSTEM
14530 if (IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
14531 row->exact_window_width_line_p = 1;
14532 else
14533#endif /* HAVE_WINDOW_SYSTEM */
1b335865
GM
14534 if ((append_space (it, 1) && row->used[TEXT_AREA] == 1)
14535 || row->used[TEXT_AREA] == 0)
a2889657 14536 {
5f5c8ee5
GM
14537 row->glyphs[TEXT_AREA]->charpos = -1;
14538 row->displays_text_p = 0;
14539
2ad551af 14540 if (!NILP (XBUFFER (it->w->buffer)->indicate_empty_lines)
e6b70fd8
GM
14541 && (!MINI_WINDOW_P (it->w)
14542 || (minibuf_level && EQ (it->window, minibuf_window))))
5f5c8ee5 14543 row->indicate_empty_line_p = 1;
a2889657 14544 }
2311178e 14545
5f5c8ee5
GM
14546 it->continuation_lines_width = 0;
14547 row->ends_at_zv_p = 1;
14548 break;
a2889657 14549 }
a2889657 14550
5f5c8ee5
GM
14551 /* Now, get the metrics of what we want to display. This also
14552 generates glyphs in `row' (which is IT->glyph_row). */
14553 n_glyphs_before = row->used[TEXT_AREA];
14554 x = it->current_x;
e6819faf
GM
14555
14556 /* Remember the line height so far in case the next element doesn't
14557 fit on the line. */
14558 if (!it->truncate_lines_p)
14559 {
14560 ascent = it->max_ascent;
14561 descent = it->max_descent;
14562 phys_ascent = it->max_phys_ascent;
14563 phys_descent = it->max_phys_descent;
14564 }
2311178e 14565
5f5c8ee5 14566 PRODUCE_GLYPHS (it);
a2889657 14567
5f5c8ee5
GM
14568 /* If this display element was in marginal areas, continue with
14569 the next one. */
14570 if (it->area != TEXT_AREA)
a2889657 14571 {
5f5c8ee5
GM
14572 row->ascent = max (row->ascent, it->max_ascent);
14573 row->height = max (row->height, it->max_ascent + it->max_descent);
312246d1
GM
14574 row->phys_ascent = max (row->phys_ascent, it->max_phys_ascent);
14575 row->phys_height = max (row->phys_height,
14576 it->max_phys_ascent + it->max_phys_descent);
cafafe0b 14577 set_iterator_to_next (it, 1);
5f5c8ee5
GM
14578 continue;
14579 }
5936754e 14580
5f5c8ee5
GM
14581 /* Does the display element fit on the line? If we truncate
14582 lines, we should draw past the right edge of the window. If
14583 we don't truncate, we want to stop so that we can display the
14584 continuation glyph before the right margin. If lines are
14585 continued, there are two possible strategies for characters
14586 resulting in more than 1 glyph (e.g. tabs): Display as many
14587 glyphs as possible in this line and leave the rest for the
14588 continuation line, or display the whole element in the next
14589 line. Original redisplay did the former, so we do it also. */
14590 nglyphs = row->used[TEXT_AREA] - n_glyphs_before;
14591 hpos_before = it->hpos;
14592 x_before = x;
4dcd74e6 14593
4b41cebb 14594 if (/* Not a newline. */
4dcd74e6 14595 nglyphs > 0
202c1b5b 14596 /* Glyphs produced fit entirely in the line. */
4dcd74e6
GM
14597 && it->current_x < it->last_visible_x)
14598 {
37be86f2 14599 it->hpos += nglyphs;
5f5c8ee5
GM
14600 row->ascent = max (row->ascent, it->max_ascent);
14601 row->height = max (row->height, it->max_ascent + it->max_descent);
312246d1
GM
14602 row->phys_ascent = max (row->phys_ascent, it->max_phys_ascent);
14603 row->phys_height = max (row->phys_height,
14604 it->max_phys_ascent + it->max_phys_descent);
5f5c8ee5
GM
14605 if (it->current_x - it->pixel_width < it->first_visible_x)
14606 row->x = x - it->first_visible_x;
14607 }
14608 else
14609 {
14610 int new_x;
14611 struct glyph *glyph;
2311178e 14612
5f5c8ee5 14613 for (i = 0; i < nglyphs; ++i, x = new_x)
b5bbc9a5 14614 {
5f5c8ee5
GM
14615 glyph = row->glyphs[TEXT_AREA] + n_glyphs_before + i;
14616 new_x = x + glyph->pixel_width;
14617
14618 if (/* Lines are continued. */
14619 !it->truncate_lines_p
14620 && (/* Glyph doesn't fit on the line. */
14621 new_x > it->last_visible_x
14622 /* Or it fits exactly on a window system frame. */
14623 || (new_x == it->last_visible_x
14624 && FRAME_WINDOW_P (it->f))))
a2889657 14625 {
5f5c8ee5 14626 /* End of a continued line. */
2311178e 14627
5f5c8ee5
GM
14628 if (it->hpos == 0
14629 || (new_x == it->last_visible_x
14630 && FRAME_WINDOW_P (it->f)))
14631 {
e6819faf
GM
14632 /* Current glyph is the only one on the line or
14633 fits exactly on the line. We must continue
14634 the line because we can't draw the cursor
14635 after the glyph. */
5f5c8ee5
GM
14636 row->continued_p = 1;
14637 it->current_x = new_x;
14638 it->continuation_lines_width += new_x;
14639 ++it->hpos;
14640 if (i == nglyphs - 1)
6b61353c
KH
14641 {
14642 set_iterator_to_next (it, 1);
14643#ifdef HAVE_WINDOW_SYSTEM
14644 if (IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
14645 {
14646 if (!get_next_display_element (it))
14647 {
14648 row->exact_window_width_line_p = 1;
14649 it->continuation_lines_width = 0;
14650 row->continued_p = 0;
14651 row->ends_at_zv_p = 1;
14652 }
14653 else if (ITERATOR_AT_END_OF_LINE_P (it))
14654 {
14655 row->continued_p = 0;
14656 row->exact_window_width_line_p = 1;
14657 }
14658 }
14659#endif /* HAVE_WINDOW_SYSTEM */
14660 }
5f5c8ee5 14661 }
3b3c4bf0
GM
14662 else if (CHAR_GLYPH_PADDING_P (*glyph)
14663 && !FRAME_WINDOW_P (it->f))
14664 {
14665 /* A padding glyph that doesn't fit on this line.
14666 This means the whole character doesn't fit
14667 on the line. */
14668 row->used[TEXT_AREA] = n_glyphs_before;
2311178e 14669
3b3c4bf0
GM
14670 /* Fill the rest of the row with continuation
14671 glyphs like in 20.x. */
14672 while (row->glyphs[TEXT_AREA] + row->used[TEXT_AREA]
14673 < row->glyphs[1 + TEXT_AREA])
14674 produce_special_glyphs (it, IT_CONTINUATION);
2311178e 14675
3b3c4bf0
GM
14676 row->continued_p = 1;
14677 it->current_x = x_before;
14678 it->continuation_lines_width += x_before;
2311178e 14679
3b3c4bf0
GM
14680 /* Restore the height to what it was before the
14681 element not fitting on the line. */
14682 it->max_ascent = ascent;
14683 it->max_descent = descent;
14684 it->max_phys_ascent = phys_ascent;
14685 it->max_phys_descent = phys_descent;
14686 }
0df56f4d
GM
14687 else if (it->c == '\t' && FRAME_WINDOW_P (it->f))
14688 {
14689 /* A TAB that extends past the right edge of the
14690 window. This produces a single glyph on
14691 window system frames. We leave the glyph in
14692 this row and let it fill the row, but don't
14693 consume the TAB. */
14694 it->continuation_lines_width += it->last_visible_x;
14695 row->ends_in_middle_of_char_p = 1;
14696 row->continued_p = 1;
14697 glyph->pixel_width = it->last_visible_x - x;
14698 it->starts_in_middle_of_char_p = 1;
14699 }
5f5c8ee5 14700 else
5936754e 14701 {
0df56f4d
GM
14702 /* Something other than a TAB that draws past
14703 the right edge of the window. Restore
14704 positions to values before the element. */
5f5c8ee5 14705 row->used[TEXT_AREA] = n_glyphs_before + i;
2311178e 14706
5f5c8ee5
GM
14707 /* Display continuation glyphs. */
14708 if (!FRAME_WINDOW_P (it->f))
14709 produce_special_glyphs (it, IT_CONTINUATION);
14710 row->continued_p = 1;
653c329b 14711
0df56f4d 14712 it->continuation_lines_width += x;
2311178e 14713
91004049
GM
14714 if (nglyphs > 1 && i > 0)
14715 {
14716 row->ends_in_middle_of_char_p = 1;
14717 it->starts_in_middle_of_char_p = 1;
14718 }
2311178e 14719
e6819faf
GM
14720 /* Restore the height to what it was before the
14721 element not fitting on the line. */
14722 it->max_ascent = ascent;
14723 it->max_descent = descent;
14724 it->max_phys_ascent = phys_ascent;
14725 it->max_phys_descent = phys_descent;
5936754e 14726 }
e6819faf 14727
5f5c8ee5
GM
14728 break;
14729 }
14730 else if (new_x > it->first_visible_x)
14731 {
14732 /* Increment number of glyphs actually displayed. */
14733 ++it->hpos;
2311178e 14734
5f5c8ee5
GM
14735 if (x < it->first_visible_x)
14736 /* Glyph is partially visible, i.e. row starts at
14737 negative X position. */
14738 row->x = x - it->first_visible_x;
14739 }
14740 else
14741 {
14742 /* Glyph is completely off the left margin of the
14743 window. This should not happen because of the
72b8c434
RS
14744 move_it_in_display_line at the start of this
14745 function, unless the text display area of the
14746 window is empty. */
14747 xassert (it->first_visible_x <= it->last_visible_x);
a2889657 14748 }
a2889657 14749 }
2311178e 14750
5f5c8ee5
GM
14751 row->ascent = max (row->ascent, it->max_ascent);
14752 row->height = max (row->height, it->max_ascent + it->max_descent);
312246d1
GM
14753 row->phys_ascent = max (row->phys_ascent, it->max_phys_ascent);
14754 row->phys_height = max (row->phys_height,
14755 it->max_phys_ascent + it->max_phys_descent);
2311178e 14756
5f5c8ee5 14757 /* End of this display line if row is continued. */
6b61353c 14758 if (row->continued_p || row->ends_at_zv_p)
5f5c8ee5 14759 break;
a2889657 14760 }
a2889657 14761
6b61353c 14762 at_end_of_line:
5f5c8ee5
GM
14763 /* Is this a line end? If yes, we're also done, after making
14764 sure that a non-default face is extended up to the right
14765 margin of the window. */
14766 if (ITERATOR_AT_END_OF_LINE_P (it))
1c9241f5 14767 {
5f5c8ee5
GM
14768 int used_before = row->used[TEXT_AREA];
14769
e74fb0f7
GM
14770 row->ends_in_newline_from_string_p = STRINGP (it->object);
14771
6b61353c 14772#ifdef HAVE_WINDOW_SYSTEM
5f5c8ee5
GM
14773 /* Add a space at the end of the line that is used to
14774 display the cursor there. */
6b61353c
KH
14775 if (!IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
14776 append_space (it, 0);
14777#endif /* HAVE_WINDOW_SYSTEM */
2311178e 14778
5f5c8ee5
GM
14779 /* Extend the face to the end of the line. */
14780 extend_face_to_end_of_line (it);
14781
14782 /* Make sure we have the position. */
14783 if (used_before == 0)
14784 row->glyphs[TEXT_AREA]->charpos = CHARPOS (it->position);
2311178e 14785
5f5c8ee5 14786 /* Consume the line end. This skips over invisible lines. */
cafafe0b 14787 set_iterator_to_next (it, 1);
5f5c8ee5
GM
14788 it->continuation_lines_width = 0;
14789 break;
1c9241f5 14790 }
a2889657 14791
2311178e 14792 /* Proceed with next display element. Note that this skips
5f5c8ee5 14793 over lines invisible because of selective display. */
cafafe0b 14794 set_iterator_to_next (it, 1);
b1d1124b 14795
5f5c8ee5
GM
14796 /* If we truncate lines, we are done when the last displayed
14797 glyphs reach past the right margin of the window. */
14798 if (it->truncate_lines_p
14799 && (FRAME_WINDOW_P (it->f)
14800 ? (it->current_x >= it->last_visible_x)
14801 : (it->current_x > it->last_visible_x)))
75d13c64 14802 {
5f5c8ee5
GM
14803 /* Maybe add truncation glyphs. */
14804 if (!FRAME_WINDOW_P (it->f))
14805 {
a98b5ed9 14806 int i, n;
2311178e 14807
a98b5ed9
GM
14808 for (i = row->used[TEXT_AREA] - 1; i > 0; --i)
14809 if (!CHAR_GLYPH_PADDING_P (row->glyphs[TEXT_AREA][i]))
14810 break;
14811
14812 for (n = row->used[TEXT_AREA]; i < n; ++i)
14813 {
14814 row->used[TEXT_AREA] = i;
14815 produce_special_glyphs (it, IT_TRUNCATION);
14816 }
5f5c8ee5 14817 }
6b61353c
KH
14818#ifdef HAVE_WINDOW_SYSTEM
14819 else
14820 {
14821 /* Don't truncate if we can overflow newline into fringe. */
14822 if (IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
14823 {
14824 if (!get_next_display_element (it))
14825 {
14826#ifdef HAVE_WINDOW_SYSTEM
14827 it->continuation_lines_width = 0;
14828 row->ends_at_zv_p = 1;
14829 row->exact_window_width_line_p = 1;
14830 break;
14831#endif /* HAVE_WINDOW_SYSTEM */
14832 }
14833 if (ITERATOR_AT_END_OF_LINE_P (it))
14834 {
14835 row->exact_window_width_line_p = 1;
14836 goto at_end_of_line;
14837 }
14838 }
14839 }
14840#endif /* HAVE_WINDOW_SYSTEM */
2311178e 14841
5f5c8ee5
GM
14842 row->truncated_on_right_p = 1;
14843 it->continuation_lines_width = 0;
312246d1 14844 reseat_at_next_visible_line_start (it, 0);
5f5c8ee5
GM
14845 row->ends_at_zv_p = FETCH_BYTE (IT_BYTEPOS (*it) - 1) != '\n';
14846 it->hpos = hpos_before;
14847 it->current_x = x_before;
14848 break;
75d13c64 14849 }
a2889657 14850 }
a2889657 14851
5f5c8ee5
GM
14852 /* If line is not empty and hscrolled, maybe insert truncation glyphs
14853 at the left window margin. */
14854 if (it->first_visible_x
14855 && IT_CHARPOS (*it) != MATRIX_ROW_START_CHARPOS (row))
14856 {
14857 if (!FRAME_WINDOW_P (it->f))
14858 insert_left_trunc_glyphs (it);
14859 row->truncated_on_left_p = 1;
14860 }
a2889657 14861
5f5c8ee5
GM
14862 /* If the start of this line is the overlay arrow-position, then
14863 mark this glyph row as the one containing the overlay arrow.
14864 This is clearly a mess with variable size fonts. It would be
14865 better to let it be displayed like cursors under X. */
6b61353c
KH
14866 if (! overlay_arrow_seen
14867 && (overlay_arrow_string
14868 = overlay_arrow_at_row (it->f, row, &overlay_arrow_bitmap),
14869 !NILP (overlay_arrow_string)))
a2889657 14870 {
b46952ae 14871 /* Overlay arrow in window redisplay is a fringe bitmap. */
5f5c8ee5 14872 if (!FRAME_WINDOW_P (it->f))
c4628384 14873 {
6b61353c
KH
14874 struct glyph_row *arrow_row
14875 = get_overlay_arrow_glyph_row (it->w, overlay_arrow_string);
5f5c8ee5
GM
14876 struct glyph *glyph = arrow_row->glyphs[TEXT_AREA];
14877 struct glyph *arrow_end = glyph + arrow_row->used[TEXT_AREA];
14878 struct glyph *p = row->glyphs[TEXT_AREA];
14879 struct glyph *p2, *end;
14880
14881 /* Copy the arrow glyphs. */
14882 while (glyph < arrow_end)
14883 *p++ = *glyph++;
14884
14885 /* Throw away padding glyphs. */
14886 p2 = p;
14887 end = row->glyphs[TEXT_AREA] + row->used[TEXT_AREA];
14888 while (p2 < end && CHAR_GLYPH_PADDING_P (*p2))
14889 ++p2;
14890 if (p2 > p)
212e4f87 14891 {
5f5c8ee5
GM
14892 while (p2 < end)
14893 *p++ = *p2++;
14894 row->used[TEXT_AREA] = p2 - row->glyphs[TEXT_AREA];
c4628384 14895 }
c4628384 14896 }
2311178e 14897
a2889657 14898 overlay_arrow_seen = 1;
6b61353c 14899 it->w->overlay_arrow_bitmap = overlay_arrow_bitmap;
5f5c8ee5 14900 row->overlay_arrow_p = 1;
a2889657
JB
14901 }
14902
5f5c8ee5
GM
14903 /* Compute pixel dimensions of this line. */
14904 compute_line_metrics (it);
14905
14906 /* Remember the position at which this line ends. */
14907 row->end = it->current;
14908
6b61353c
KH
14909 /* Save fringe bitmaps in this row. */
14910 row->left_user_fringe_bitmap = it->left_user_fringe_bitmap;
14911 row->left_user_fringe_face_id = it->left_user_fringe_face_id;
14912 row->right_user_fringe_bitmap = it->right_user_fringe_bitmap;
14913 row->right_user_fringe_face_id = it->right_user_fringe_face_id;
14914
14915 it->left_user_fringe_bitmap = 0;
14916 it->left_user_fringe_face_id = 0;
14917 it->right_user_fringe_bitmap = 0;
14918 it->right_user_fringe_face_id = 0;
14919
173cbca8 14920 /* Maybe set the cursor. */
5f5c8ee5
GM
14921 if (it->w->cursor.vpos < 0
14922 && PT >= MATRIX_ROW_START_CHARPOS (row)
cafafe0b
GM
14923 && PT <= MATRIX_ROW_END_CHARPOS (row)
14924 && cursor_row_p (it->w, row))
14925 set_cursor_from_row (it->w, row, it->w->desired_matrix, 0, 0, 0, 0);
5f5c8ee5
GM
14926
14927 /* Highlight trailing whitespace. */
8f897821 14928 if (!NILP (Vshow_trailing_whitespace))
5f5c8ee5
GM
14929 highlight_trailing_whitespace (it->f, it->glyph_row);
14930
14931 /* Prepare for the next line. This line starts horizontally at (X
14932 HPOS) = (0 0). Vertical positions are incremented. As a
14933 convenience for the caller, IT->glyph_row is set to the next
14934 row to be used. */
14935 it->current_x = it->hpos = 0;
14936 it->current_y += row->height;
14937 ++it->vpos;
14938 ++it->glyph_row;
6b61353c 14939 it->start = it->current;
5f5c8ee5 14940 return row->displays_text_p;
a2889657 14941}
5f5c8ee5
GM
14942
14943
a2889657 14944\f
5f5c8ee5
GM
14945/***********************************************************************
14946 Menu Bar
14947 ***********************************************************************/
14948
14949/* Redisplay the menu bar in the frame for window W.
14950
14951 The menu bar of X frames that don't have X toolkit support is
14952 displayed in a special window W->frame->menu_bar_window.
2311178e 14953
5f5c8ee5
GM
14954 The menu bar of terminal frames is treated specially as far as
14955 glyph matrices are concerned. Menu bar lines are not part of
14956 windows, so the update is done directly on the frame matrix rows
14957 for the menu bar. */
7ce2c095
RS
14958
14959static void
14960display_menu_bar (w)
14961 struct window *w;
14962{
5f5c8ee5
GM
14963 struct frame *f = XFRAME (WINDOW_FRAME (w));
14964 struct it it;
14965 Lisp_Object items;
8351baf2 14966 int i;
7ce2c095 14967
5f5c8ee5 14968 /* Don't do all this for graphical frames. */
dc937613 14969#ifdef HAVE_NTGUI
d129c4c2
KH
14970 if (!NILP (Vwindow_system))
14971 return;
dc937613 14972#endif
488dd4c4 14973#if defined (USE_X_TOOLKIT) || defined (USE_GTK)
d3413a53 14974 if (FRAME_X_P (f))
7ce2c095 14975 return;
5f5c8ee5 14976#endif
e0f712ba 14977#ifdef MAC_OS
1a578e9b
AC
14978 if (FRAME_MAC_P (f))
14979 return;
14980#endif
5f5c8ee5
GM
14981
14982#ifdef USE_X_TOOLKIT
14983 xassert (!FRAME_WINDOW_P (f));
52377a47 14984 init_iterator (&it, w, -1, -1, f->desired_matrix->rows, MENU_FACE_ID);
5f5c8ee5 14985 it.first_visible_x = 0;
da8b7f4f 14986 it.last_visible_x = FRAME_TOTAL_COLS (f) * FRAME_COLUMN_WIDTH (f);
5f5c8ee5
GM
14987#else /* not USE_X_TOOLKIT */
14988 if (FRAME_WINDOW_P (f))
14989 {
14990 /* Menu bar lines are displayed in the desired matrix of the
14991 dummy window menu_bar_window. */
14992 struct window *menu_w;
14993 xassert (WINDOWP (f->menu_bar_window));
14994 menu_w = XWINDOW (f->menu_bar_window);
14995 init_iterator (&it, menu_w, -1, -1, menu_w->desired_matrix->rows,
52377a47 14996 MENU_FACE_ID);
5f5c8ee5 14997 it.first_visible_x = 0;
da8b7f4f 14998 it.last_visible_x = FRAME_TOTAL_COLS (f) * FRAME_COLUMN_WIDTH (f);
5f5c8ee5
GM
14999 }
15000 else
15001 {
15002 /* This is a TTY frame, i.e. character hpos/vpos are used as
15003 pixel x/y. */
15004 init_iterator (&it, w, -1, -1, f->desired_matrix->rows,
52377a47 15005 MENU_FACE_ID);
5f5c8ee5 15006 it.first_visible_x = 0;
da8b7f4f 15007 it.last_visible_x = FRAME_COLS (f);
5f5c8ee5
GM
15008 }
15009#endif /* not USE_X_TOOLKIT */
15010
1862a24e
MB
15011 if (! mode_line_inverse_video)
15012 /* Force the menu-bar to be displayed in the default face. */
15013 it.base_face_id = it.face_id = DEFAULT_FACE_ID;
15014
5f5c8ee5
GM
15015 /* Clear all rows of the menu bar. */
15016 for (i = 0; i < FRAME_MENU_BAR_LINES (f); ++i)
15017 {
15018 struct glyph_row *row = it.glyph_row + i;
15019 clear_glyph_row (row);
15020 row->enabled_p = 1;
15021 row->full_width_p = 1;
15022 }
7ce2c095 15023
5f5c8ee5
GM
15024 /* Display all items of the menu bar. */
15025 items = FRAME_MENU_BAR_ITEMS (it.f);
469937ac 15026 for (i = 0; i < XVECTOR (items)->size; i += 4)
7ce2c095 15027 {
5f5c8ee5
GM
15028 Lisp_Object string;
15029
15030 /* Stop at nil string. */
a61b7058 15031 string = AREF (items, i + 1);
8351baf2
RS
15032 if (NILP (string))
15033 break;
2d66ad19 15034
5f5c8ee5 15035 /* Remember where item was displayed. */
a61b7058 15036 AREF (items, i + 3) = make_number (it.hpos);
7ce2c095 15037
5f5c8ee5
GM
15038 /* Display the item, pad with one space. */
15039 if (it.current_x < it.last_visible_x)
15040 display_string (NULL, string, Qnil, 0, 0, &it,
2051c264 15041 SCHARS (string) + 1, 0, 0, -1);
7ce2c095
RS
15042 }
15043
2d66ad19 15044 /* Fill out the line with spaces. */
5f5c8ee5
GM
15045 if (it.current_x < it.last_visible_x)
15046 display_string ("", Qnil, Qnil, 0, 0, &it, -1, 0, 0, -1);
db6f348c 15047
5f5c8ee5
GM
15048 /* Compute the total height of the lines. */
15049 compute_line_metrics (&it);
7ce2c095 15050}
5f5c8ee5
GM
15051
15052
7ce2c095 15053\f
5f5c8ee5
GM
15054/***********************************************************************
15055 Mode Line
15056 ***********************************************************************/
15057
715e84c9
GM
15058/* Redisplay mode lines in the window tree whose root is WINDOW. If
15059 FORCE is non-zero, redisplay mode lines unconditionally.
15060 Otherwise, redisplay only mode lines that are garbaged. Value is
15061 the number of windows whose mode lines were redisplayed. */
a2889657 15062
715e84c9
GM
15063static int
15064redisplay_mode_lines (window, force)
15065 Lisp_Object window;
15066 int force;
15067{
15068 int nwindows = 0;
2311178e 15069
715e84c9
GM
15070 while (!NILP (window))
15071 {
15072 struct window *w = XWINDOW (window);
2311178e 15073
715e84c9
GM
15074 if (WINDOWP (w->hchild))
15075 nwindows += redisplay_mode_lines (w->hchild, force);
15076 else if (WINDOWP (w->vchild))
15077 nwindows += redisplay_mode_lines (w->vchild, force);
15078 else if (force
15079 || FRAME_GARBAGED_P (XFRAME (w->frame))
15080 || !MATRIX_MODE_LINE_ROW (w->current_matrix)->enabled_p)
15081 {
715e84c9
GM
15082 struct text_pos lpoint;
15083 struct buffer *old = current_buffer;
15084
15085 /* Set the window's buffer for the mode line display. */
15086 SET_TEXT_POS (lpoint, PT, PT_BYTE);
15087 set_buffer_internal_1 (XBUFFER (w->buffer));
2311178e 15088
715e84c9
GM
15089 /* Point refers normally to the selected window. For any
15090 other window, set up appropriate value. */
15091 if (!EQ (window, selected_window))
15092 {
15093 struct text_pos pt;
2311178e 15094
715e84c9
GM
15095 SET_TEXT_POS_FROM_MARKER (pt, w->pointm);
15096 if (CHARPOS (pt) < BEGV)
15097 TEMP_SET_PT_BOTH (BEGV, BEGV_BYTE);
15098 else if (CHARPOS (pt) > (ZV - 1))
15099 TEMP_SET_PT_BOTH (ZV, ZV_BYTE);
15100 else
15101 TEMP_SET_PT_BOTH (CHARPOS (pt), BYTEPOS (pt));
15102 }
15103
715e84c9
GM
15104 /* Display mode lines. */
15105 clear_glyph_matrix (w->desired_matrix);
15106 if (display_mode_lines (w))
15107 {
15108 ++nwindows;
15109 w->must_be_updated_p = 1;
15110 }
15111
15112 /* Restore old settings. */
715e84c9
GM
15113 set_buffer_internal_1 (old);
15114 TEMP_SET_PT_BOTH (CHARPOS (lpoint), BYTEPOS (lpoint));
15115 }
15116
15117 window = w->next;
15118 }
15119
15120 return nwindows;
15121}
15122
15123
15124/* Display the mode and/or top line of window W. Value is the number
15125 of mode lines displayed. */
15126
15127static int
5f5c8ee5 15128display_mode_lines (w)
a2889657
JB
15129 struct window *w;
15130{
edd1e654 15131 Lisp_Object old_selected_window, old_selected_frame;
715e84c9 15132 int n = 0;
edd1e654
GM
15133
15134 old_selected_frame = selected_frame;
15135 selected_frame = w->frame;
15136 old_selected_window = selected_window;
15137 XSETWINDOW (selected_window, w);
2311178e 15138
5f5c8ee5 15139 /* These will be set while the mode line specs are processed. */
aa6d10fa 15140 line_number_displayed = 0;
155ef550 15141 w->column_number_displayed = Qnil;
aa6d10fa 15142
5f5c8ee5 15143 if (WINDOW_WANTS_MODELINE_P (w))
715e84c9 15144 {
c96e83bf 15145 struct window *sel_w = XWINDOW (old_selected_window);
f87c0a98 15146
96d2320f 15147 /* Select mode line face based on the real selected window. */
c96e83bf 15148 display_mode_line (w, CURRENT_MODE_LINE_FACE_ID_3 (sel_w, sel_w, w),
715e84c9
GM
15149 current_buffer->mode_line_format);
15150 ++n;
15151 }
2311178e 15152
045dee35 15153 if (WINDOW_WANTS_HEADER_LINE_P (w))
715e84c9
GM
15154 {
15155 display_mode_line (w, HEADER_LINE_FACE_ID,
15156 current_buffer->header_line_format);
15157 ++n;
15158 }
15159
edd1e654
GM
15160 selected_frame = old_selected_frame;
15161 selected_window = old_selected_window;
715e84c9 15162 return n;
5f5c8ee5 15163}
03b294dc 15164
03b294dc 15165
5f5c8ee5 15166/* Display mode or top line of window W. FACE_ID specifies which line
045dee35 15167 to display; it is either MODE_LINE_FACE_ID or HEADER_LINE_FACE_ID.
04612a64
GM
15168 FORMAT is the mode line format to display. Value is the pixel
15169 height of the mode line displayed. */
03b294dc 15170
04612a64 15171static int
5f5c8ee5
GM
15172display_mode_line (w, face_id, format)
15173 struct window *w;
15174 enum face_id face_id;
15175 Lisp_Object format;
15176{
15177 struct it it;
15178 struct face *face;
03b294dc 15179
5f5c8ee5
GM
15180 init_iterator (&it, w, -1, -1, NULL, face_id);
15181 prepare_desired_row (it.glyph_row);
15182
6b61353c
KH
15183 it.glyph_row->mode_line_p = 1;
15184
1862a24e
MB
15185 if (! mode_line_inverse_video)
15186 /* Force the mode-line to be displayed in the default face. */
15187 it.base_face_id = it.face_id = DEFAULT_FACE_ID;
15188
5f5c8ee5
GM
15189 /* Temporarily make frame's keyboard the current kboard so that
15190 kboard-local variables in the mode_line_format will get the right
15191 values. */
15192 push_frame_kboard (it.f);
c53a1624 15193 display_mode_element (&it, 0, 0, 0, format, Qnil, 0);
5f5c8ee5 15194 pop_frame_kboard ();
a2889657 15195
5f5c8ee5
GM
15196 /* Fill up with spaces. */
15197 display_string (" ", Qnil, Qnil, 0, 0, &it, 10000, -1, -1, 0);
2311178e 15198
5f5c8ee5
GM
15199 compute_line_metrics (&it);
15200 it.glyph_row->full_width_p = 1;
5f5c8ee5
GM
15201 it.glyph_row->continued_p = 0;
15202 it.glyph_row->truncated_on_left_p = 0;
15203 it.glyph_row->truncated_on_right_p = 0;
15204
15205 /* Make a 3D mode-line have a shadow at its right end. */
15206 face = FACE_FROM_ID (it.f, face_id);
15207 extend_face_to_end_of_line (&it);
15208 if (face->box != FACE_NO_BOX)
d7eb09a0 15209 {
5f5c8ee5
GM
15210 struct glyph *last = (it.glyph_row->glyphs[TEXT_AREA]
15211 + it.glyph_row->used[TEXT_AREA] - 1);
15212 last->right_box_line_p = 1;
d7eb09a0 15213 }
04612a64
GM
15214
15215 return it.glyph_row->height;
a2889657
JB
15216}
15217
0fcf414f
RS
15218/* Alist that caches the results of :propertize.
15219 Each element is (PROPERTIZED-STRING . PROPERTY-LIST). */
15220Lisp_Object mode_line_proptrans_alist;
a2889657 15221
fec8f23e
KS
15222/* List of strings making up the mode-line. */
15223Lisp_Object mode_line_string_list;
15224
15225/* Base face property when building propertized mode line string. */
15226static Lisp_Object mode_line_string_face;
15227static Lisp_Object mode_line_string_face_prop;
15228
15229
5f5c8ee5
GM
15230/* Contribute ELT to the mode line for window IT->w. How it
15231 translates into text depends on its data type.
a2889657 15232
5f5c8ee5 15233 IT describes the display environment in which we display, as usual.
a2889657
JB
15234
15235 DEPTH is the depth in recursion. It is used to prevent
15236 infinite recursion here.
15237
5f5c8ee5
GM
15238 FIELD_WIDTH is the number of characters the display of ELT should
15239 occupy in the mode line, and PRECISION is the maximum number of
15240 characters to display from ELT's representation. See
b8523839 15241 display_string for details.
a2889657 15242
c53a1624
RS
15243 Returns the hpos of the end of the text generated by ELT.
15244
15245 PROPS is a property list to add to any string we encounter.
15246
7d0393cf 15247 If RISKY is nonzero, remove (disregard) any properties in any string
93da8435
SM
15248 we encounter, and ignore :eval and :propertize.
15249
15250 If the global variable `frame_title_ptr' is non-NULL, then the output
15251 is passed to `store_frame_title' instead of `display_string'. */
a2889657
JB
15252
15253static int
c53a1624 15254display_mode_element (it, depth, field_width, precision, elt, props, risky)
5f5c8ee5 15255 struct it *it;
a2889657 15256 int depth;
5f5c8ee5 15257 int field_width, precision;
0fcf414f 15258 Lisp_Object elt, props;
c53a1624 15259 int risky;
a2889657 15260{
5f5c8ee5 15261 int n = 0, field, prec;
0fcf414f 15262 int literal = 0;
5f5c8ee5 15263
a2889657 15264 tail_recurse:
1a89be1e
SM
15265 if (depth > 100)
15266 elt = build_string ("*too-deep*");
a2889657
JB
15267
15268 depth++;
15269
0220c518 15270 switch (SWITCH_ENUM_CAST (XTYPE (elt)))
a2889657
JB
15271 {
15272 case Lisp_String:
15273 {
15274 /* A string: output it and check for %-constructs within it. */
5f5c8ee5 15275 unsigned char c;
50f80c2f 15276 const unsigned char *this, *lisp_string;
5f5c8ee5 15277
c53a1624 15278 if (!NILP (props) || risky)
0fcf414f
RS
15279 {
15280 Lisp_Object oprops, aelt;
15281 oprops = Ftext_properties_at (make_number (0), elt);
c53a1624
RS
15282
15283 if (NILP (Fequal (props, oprops)) || risky)
0fcf414f 15284 {
ae02e06a
RS
15285 /* If the starting string has properties,
15286 merge the specified ones onto the existing ones. */
c53a1624 15287 if (! NILP (oprops) && !risky)
ae02e06a
RS
15288 {
15289 Lisp_Object tem;
15290
15291 oprops = Fcopy_sequence (oprops);
15292 tem = props;
15293 while (CONSP (tem))
15294 {
15295 oprops = Fplist_put (oprops, XCAR (tem),
15296 XCAR (XCDR (tem)));
15297 tem = XCDR (XCDR (tem));
15298 }
15299 props = oprops;
15300 }
15301
0fcf414f
RS
15302 aelt = Fassoc (elt, mode_line_proptrans_alist);
15303 if (! NILP (aelt) && !NILP (Fequal (props, XCDR (aelt))))
adb63af1
RS
15304 {
15305 mode_line_proptrans_alist
15306 = Fcons (aelt, Fdelq (aelt, mode_line_proptrans_alist));
15307 elt = XCAR (aelt);
15308 }
0fcf414f
RS
15309 else
15310 {
adb63af1
RS
15311 Lisp_Object tem;
15312
0fcf414f 15313 elt = Fcopy_sequence (elt);
dc3b2c8b
SM
15314 Fset_text_properties (make_number (0), Flength (elt),
15315 props, elt);
adb63af1 15316 /* Add this item to mode_line_proptrans_alist. */
0fcf414f
RS
15317 mode_line_proptrans_alist
15318 = Fcons (Fcons (elt, props),
15319 mode_line_proptrans_alist);
adb63af1
RS
15320 /* Truncate mode_line_proptrans_alist
15321 to at most 50 elements. */
15322 tem = Fnthcdr (make_number (50),
15323 mode_line_proptrans_alist);
15324 if (! NILP (tem))
15325 XSETCDR (tem, Qnil);
0fcf414f
RS
15326 }
15327 }
15328 }
15329
2051c264 15330 this = SDATA (elt);
ae02e06a
RS
15331 lisp_string = this;
15332
0fcf414f
RS
15333 if (literal)
15334 {
15335 prec = precision - n;
15336 if (frame_title_ptr)
2051c264 15337 n += store_frame_title (SDATA (elt), -1, prec);
fec8f23e
KS
15338 else if (!NILP (mode_line_string_list))
15339 n += store_mode_line_string (NULL, elt, 1, 0, prec, Qnil);
0fcf414f
RS
15340 else
15341 n += display_string (NULL, elt, Qnil, 0, 0, it,
15342 0, prec, 0, STRING_MULTIBYTE (elt));
15343
15344 break;
15345 }
15346
5f5c8ee5
GM
15347 while ((precision <= 0 || n < precision)
15348 && *this
15349 && (frame_title_ptr
fec8f23e 15350 || !NILP (mode_line_string_list)
5f5c8ee5 15351 || it->current_x < it->last_visible_x))
a2889657 15352 {
50f80c2f 15353 const unsigned char *last = this;
5f5c8ee5
GM
15354
15355 /* Advance to end of string or next format specifier. */
a2889657
JB
15356 while ((c = *this++) != '\0' && c != '%')
15357 ;
2311178e 15358
a2889657
JB
15359 if (this - 1 != last)
15360 {
5f5c8ee5
GM
15361 /* Output to end of string or up to '%'. Field width
15362 is length of string. Don't output more than
15363 PRECISION allows us. */
d26b89b8 15364 --this;
eaaa65b0
GM
15365
15366 prec = chars_in_text (last, this - last);
5f5c8ee5
GM
15367 if (precision > 0 && prec > precision - n)
15368 prec = precision - n;
2311178e 15369
d39b6696 15370 if (frame_title_ptr)
d26b89b8 15371 n += store_frame_title (last, 0, prec);
fec8f23e
KS
15372 else if (!NILP (mode_line_string_list))
15373 {
15374 int bytepos = last - lisp_string;
15375 int charpos = string_byte_to_char (elt, bytepos);
15376 n += store_mode_line_string (NULL,
15377 Fsubstring (elt, make_number (charpos),
15378 make_number (charpos + prec)),
15379 0, 0, 0, Qnil);
15380 }
d39b6696 15381 else
eaaa65b0
GM
15382 {
15383 int bytepos = last - lisp_string;
15384 int charpos = string_byte_to_char (elt, bytepos);
15385 n += display_string (NULL, elt, Qnil, 0, charpos,
ca77144d
GM
15386 it, 0, prec, 0,
15387 STRING_MULTIBYTE (elt));
eaaa65b0 15388 }
a2889657
JB
15389 }
15390 else /* c == '%' */
15391 {
50f80c2f 15392 const unsigned char *percent_position = this;
2311178e 15393
5f5c8ee5
GM
15394 /* Get the specified minimum width. Zero means
15395 don't pad. */
15396 field = 0;
a2889657 15397 while ((c = *this++) >= '0' && c <= '9')
5f5c8ee5 15398 field = field * 10 + c - '0';
a2889657 15399
5f5c8ee5
GM
15400 /* Don't pad beyond the total padding allowed. */
15401 if (field_width - n > 0 && field > field_width - n)
15402 field = field_width - n;
a2889657 15403
5f5c8ee5
GM
15404 /* Note that either PRECISION <= 0 or N < PRECISION. */
15405 prec = precision - n;
2311178e 15406
a2889657 15407 if (c == 'M')
5f5c8ee5 15408 n += display_mode_element (it, depth, field, prec,
c53a1624
RS
15409 Vglobal_mode_string, props,
15410 risky);
a2889657 15411 else if (c != 0)
d39b6696 15412 {
72f62cb5 15413 int multibyte;
ae02e06a
RS
15414 int bytepos, charpos;
15415 unsigned char *spec;
2311178e 15416
ae02e06a
RS
15417 bytepos = percent_position - lisp_string;
15418 charpos = (STRING_MULTIBYTE (elt)
15419 ? string_byte_to_char (elt, bytepos)
15420 : bytepos);
15421
15422 spec
72f62cb5
GM
15423 = decode_mode_spec (it->w, c, field, prec, &multibyte);
15424
d39b6696 15425 if (frame_title_ptr)
5f5c8ee5 15426 n += store_frame_title (spec, field, prec);
fec8f23e
KS
15427 else if (!NILP (mode_line_string_list))
15428 {
15429 int len = strlen (spec);
15430 Lisp_Object tem = make_string (spec, len);
15431 props = Ftext_properties_at (make_number (charpos), elt);
15432 /* Should only keep face property in props */
15433 n += store_mode_line_string (NULL, tem, 0, field, prec, props);
15434 }
d39b6696 15435 else
5f5c8ee5 15436 {
ae02e06a 15437 int nglyphs_before, nwritten;
2311178e 15438
72f62cb5 15439 nglyphs_before = it->glyph_row->used[TEXT_AREA];
72f62cb5
GM
15440 nwritten = display_string (spec, Qnil, elt,
15441 charpos, 0, it,
15442 field, prec, 0,
15443 multibyte);
5f5c8ee5
GM
15444
15445 /* Assign to the glyphs written above the
15446 string where the `%x' came from, position
15447 of the `%'. */
15448 if (nwritten > 0)
15449 {
15450 struct glyph *glyph
15451 = (it->glyph_row->glyphs[TEXT_AREA]
15452 + nglyphs_before);
15453 int i;
15454
15455 for (i = 0; i < nwritten; ++i)
15456 {
15457 glyph[i].object = elt;
15458 glyph[i].charpos = charpos;
15459 }
2311178e 15460
5f5c8ee5
GM
15461 n += nwritten;
15462 }
15463 }
d39b6696 15464 }
b8523839
AS
15465 else /* c == 0 */
15466 break;
a2889657
JB
15467 }
15468 }
15469 }
15470 break;
15471
15472 case Lisp_Symbol:
15473 /* A symbol: process the value of the symbol recursively
15474 as if it appeared here directly. Avoid error if symbol void.
15475 Special case: if value of symbol is a string, output the string
15476 literally. */
15477 {
15478 register Lisp_Object tem;
c53a1624
RS
15479
15480 /* If the variable is not marked as risky to set
15481 then its contents are risky to use. */
15482 if (NILP (Fget (elt, Qrisky_local_variable)))
15483 risky = 1;
15484
a2889657 15485 tem = Fboundp (elt);
265a9e55 15486 if (!NILP (tem))
a2889657
JB
15487 {
15488 tem = Fsymbol_value (elt);
15489 /* If value is a string, output that string literally:
15490 don't check for % within it. */
e24c997d 15491 if (STRINGP (tem))
0fcf414f
RS
15492 literal = 1;
15493
15494 if (!EQ (tem, elt))
5f5c8ee5
GM
15495 {
15496 /* Give up right away for nil or t. */
15497 elt = tem;
15498 goto tail_recurse;
15499 }
a2889657
JB
15500 }
15501 }
15502 break;
15503
15504 case Lisp_Cons:
15505 {
15506 register Lisp_Object car, tem;
15507
0fcf414f
RS
15508 /* A cons cell: five distinct cases.
15509 If first element is :eval or :propertize, do something special.
a2889657
JB
15510 If first element is a string or a cons, process all the elements
15511 and effectively concatenate them.
15512 If first element is a negative number, truncate displaying cdr to
15513 at most that many characters. If positive, pad (with spaces)
15514 to at least that many characters.
15515 If first element is a symbol, process the cadr or caddr recursively
15516 according to whether the symbol's value is non-nil or nil. */
9472f927 15517 car = XCAR (elt);
0fcf414f 15518 if (EQ (car, QCeval))
5f5c8ee5
GM
15519 {
15520 /* An element of the form (:eval FORM) means evaluate FORM
15521 and use the result as mode line elements. */
0fcf414f 15522
c53a1624
RS
15523 if (risky)
15524 break;
15525
0fcf414f
RS
15526 if (CONSP (XCDR (elt)))
15527 {
15528 Lisp_Object spec;
15529 spec = safe_eval (XCAR (XCDR (elt)));
15530 n += display_mode_element (it, depth, field_width - n,
c53a1624
RS
15531 precision - n, spec, props,
15532 risky);
0fcf414f
RS
15533 }
15534 }
15535 else if (EQ (car, QCpropertize))
15536 {
c53a1624
RS
15537 /* An element of the form (:propertize ELT PROPS...)
15538 means display ELT but applying properties PROPS. */
15539
15540 if (risky)
15541 break;
15542
0fcf414f 15543 if (CONSP (XCDR (elt)))
c53a1624
RS
15544 n += display_mode_element (it, depth, field_width - n,
15545 precision - n, XCAR (XCDR (elt)),
15546 XCDR (XCDR (elt)), risky);
5f5c8ee5
GM
15547 }
15548 else if (SYMBOLP (car))
a2889657
JB
15549 {
15550 tem = Fboundp (car);
9472f927 15551 elt = XCDR (elt);
e24c997d 15552 if (!CONSP (elt))
a2889657
JB
15553 goto invalid;
15554 /* elt is now the cdr, and we know it is a cons cell.
15555 Use its car if CAR has a non-nil value. */
265a9e55 15556 if (!NILP (tem))
a2889657
JB
15557 {
15558 tem = Fsymbol_value (car);
265a9e55 15559 if (!NILP (tem))
9472f927
GM
15560 {
15561 elt = XCAR (elt);
15562 goto tail_recurse;
15563 }
a2889657
JB
15564 }
15565 /* Symbol's value is nil (or symbol is unbound)
15566 Get the cddr of the original list
15567 and if possible find the caddr and use that. */
9472f927 15568 elt = XCDR (elt);
265a9e55 15569 if (NILP (elt))
a2889657 15570 break;
e24c997d 15571 else if (!CONSP (elt))
a2889657 15572 goto invalid;
9472f927 15573 elt = XCAR (elt);
a2889657
JB
15574 goto tail_recurse;
15575 }
e24c997d 15576 else if (INTEGERP (car))
a2889657
JB
15577 {
15578 register int lim = XINT (car);
9472f927 15579 elt = XCDR (elt);
a2889657 15580 if (lim < 0)
5f5c8ee5
GM
15581 {
15582 /* Negative int means reduce maximum width. */
15583 if (precision <= 0)
15584 precision = -lim;
15585 else
15586 precision = min (precision, -lim);
15587 }
a2889657
JB
15588 else if (lim > 0)
15589 {
15590 /* Padding specified. Don't let it be more than
15591 current maximum. */
5f5c8ee5
GM
15592 if (precision > 0)
15593 lim = min (precision, lim);
15594
a2889657
JB
15595 /* If that's more padding than already wanted, queue it.
15596 But don't reduce padding already specified even if
15597 that is beyond the current truncation point. */
5f5c8ee5 15598 field_width = max (lim, field_width);
a2889657
JB
15599 }
15600 goto tail_recurse;
15601 }
e24c997d 15602 else if (STRINGP (car) || CONSP (car))
a2889657
JB
15603 {
15604 register int limit = 50;
5f5c8ee5
GM
15605 /* Limit is to protect against circular lists. */
15606 while (CONSP (elt)
15607 && --limit > 0
15608 && (precision <= 0 || n < precision))
a2889657 15609 {
5f5c8ee5 15610 n += display_mode_element (it, depth, field_width - n,
c53a1624
RS
15611 precision - n, XCAR (elt),
15612 props, risky);
9472f927 15613 elt = XCDR (elt);
a2889657
JB
15614 }
15615 }
15616 }
15617 break;
15618
15619 default:
15620 invalid:
1a89be1e
SM
15621 elt = build_string ("*invalid*");
15622 goto tail_recurse;
a2889657
JB
15623 }
15624
5f5c8ee5
GM
15625 /* Pad to FIELD_WIDTH. */
15626 if (field_width > 0 && n < field_width)
15627 {
15628 if (frame_title_ptr)
15629 n += store_frame_title ("", field_width - n, 0);
fec8f23e
KS
15630 else if (!NILP (mode_line_string_list))
15631 n += store_mode_line_string ("", Qnil, 0, field_width - n, 0, Qnil);
5f5c8ee5
GM
15632 else
15633 n += display_string ("", Qnil, Qnil, 0, 0, it, field_width - n,
15634 0, 0, 0);
15635 }
2311178e 15636
5f5c8ee5 15637 return n;
a2889657 15638}
5f5c8ee5 15639
fec8f23e
KS
15640/* Store a mode-line string element in mode_line_string_list.
15641
15642 If STRING is non-null, display that C string. Otherwise, the Lisp
15643 string LISP_STRING is displayed.
15644
15645 FIELD_WIDTH is the minimum number of output glyphs to produce.
15646 If STRING has fewer characters than FIELD_WIDTH, pad to the right
15647 with spaces. FIELD_WIDTH <= 0 means don't pad.
15648
15649 PRECISION is the maximum number of characters to output from
15650 STRING. PRECISION <= 0 means don't truncate the string.
15651
15652 If COPY_STRING is non-zero, make a copy of LISP_STRING before adding
15653 properties to the string.
15654
7d0393cf 15655 PROPS are the properties to add to the string.
fec8f23e
KS
15656 The mode_line_string_face face property is always added to the string.
15657 */
15658
15659static int store_mode_line_string (string, lisp_string, copy_string, field_width, precision, props)
15660 char *string;
15661 Lisp_Object lisp_string;
15662 int copy_string;
15663 int field_width;
15664 int precision;
15665 Lisp_Object props;
15666{
15667 int len;
15668 int n = 0;
15669
15670 if (string != NULL)
15671 {
15672 len = strlen (string);
15673 if (precision > 0 && len > precision)
15674 len = precision;
15675 lisp_string = make_string (string, len);
15676 if (NILP (props))
15677 props = mode_line_string_face_prop;
15678 else if (!NILP (mode_line_string_face))
15679 {
15680 Lisp_Object face = Fplist_get (props, Qface);
15681 props = Fcopy_sequence (props);
15682 if (NILP (face))
15683 face = mode_line_string_face;
15684 else
15685 face = Fcons (face, Fcons (mode_line_string_face, Qnil));
15686 props = Fplist_put (props, Qface, face);
15687 }
15688 Fadd_text_properties (make_number (0), make_number (len),
15689 props, lisp_string);
15690 }
7d0393cf 15691 else
fec8f23e 15692 {
c8224325 15693 len = XFASTINT (Flength (lisp_string));
fec8f23e
KS
15694 if (precision > 0 && len > precision)
15695 {
15696 len = precision;
15697 lisp_string = Fsubstring (lisp_string, make_number (0), make_number (len));
15698 precision = -1;
15699 }
15700 if (!NILP (mode_line_string_face))
15701 {
15702 Lisp_Object face;
15703 if (NILP (props))
15704 props = Ftext_properties_at (make_number (0), lisp_string);
15705 face = Fplist_get (props, Qface);
15706 if (NILP (face))
15707 face = mode_line_string_face;
15708 else
15709 face = Fcons (face, Fcons (mode_line_string_face, Qnil));
15710 props = Fcons (Qface, Fcons (face, Qnil));
15711 if (copy_string)
15712 lisp_string = Fcopy_sequence (lisp_string);
15713 }
15714 if (!NILP (props))
15715 Fadd_text_properties (make_number (0), make_number (len),
15716 props, lisp_string);
15717 }
15718
15719 if (len > 0)
15720 {
15721 mode_line_string_list = Fcons (lisp_string, mode_line_string_list);
7d0393cf 15722 n += len;
fec8f23e
KS
15723 }
15724
15725 if (field_width > len)
15726 {
15727 field_width -= len;
15728 lisp_string = Fmake_string (make_number (field_width), make_number (' '));
15729 if (!NILP (props))
15730 Fadd_text_properties (make_number (0), make_number (field_width),
15731 props, lisp_string);
15732 mode_line_string_list = Fcons (lisp_string, mode_line_string_list);
7d0393cf 15733 n += field_width;
fec8f23e
KS
15734 }
15735
15736 return n;
15737}
15738
5f5c8ee5 15739
8143e6ab 15740DEFUN ("format-mode-line", Fformat_mode_line, Sformat_mode_line,
fec8f23e 15741 0, 3, 0,
8143e6ab
KS
15742 doc: /* Return the mode-line of selected window as a string.
15743First optional arg FORMAT specifies a different format string (see
8b22c65a 15744`mode-line-format' for details) to use. If FORMAT is t, return
8143e6ab 15745the buffer's header-line. Second optional arg WINDOW specifies a
fec8f23e
KS
15746different window to use as the context for the formatting.
15747If third optional arg NO-PROPS is non-nil, string is not propertized. */)
15748 (format, window, no_props)
15749 Lisp_Object format, window, no_props;
8143e6ab
KS
15750{
15751 struct it it;
8143e6ab
KS
15752 int len;
15753 struct window *w;
15754 struct buffer *old_buffer = NULL;
fec8f23e 15755 enum face_id face_id = DEFAULT_FACE_ID;
8143e6ab
KS
15756
15757 if (NILP (window))
15758 window = selected_window;
15759 CHECK_WINDOW (window);
15760 w = XWINDOW (window);
15761 CHECK_BUFFER (w->buffer);
15762
15763 if (XBUFFER (w->buffer) != current_buffer)
15764 {
15765 old_buffer = current_buffer;
15766 set_buffer_internal_1 (XBUFFER (w->buffer));
15767 }
15768
15769 if (NILP (format) || EQ (format, Qt))
fec8f23e
KS
15770 {
15771 face_id = NILP (format)
15772 ? CURRENT_MODE_LINE_FACE_ID (w) :
15773 HEADER_LINE_FACE_ID;
15774 format = NILP (format)
15775 ? current_buffer->mode_line_format
15776 : current_buffer->header_line_format;
15777 }
15778
15779 init_iterator (&it, w, -1, -1, NULL, face_id);
8143e6ab 15780
fec8f23e
KS
15781 if (NILP (no_props))
15782 {
15783 mode_line_string_face =
15784 (face_id == MODE_LINE_FACE_ID ? Qmode_line :
15785 face_id == MODE_LINE_INACTIVE_FACE_ID ? Qmode_line_inactive :
15786 face_id == HEADER_LINE_FACE_ID ? Qheader_line : Qnil);
8143e6ab 15787
fec8f23e
KS
15788 mode_line_string_face_prop =
15789 NILP (mode_line_string_face) ? Qnil :
15790 Fcons (Qface, Fcons (mode_line_string_face, Qnil));
15791
15792 /* We need a dummy last element in mode_line_string_list to
15793 indicate we are building the propertized mode-line string.
15794 Using mode_line_string_face_prop here GC protects it. */
7d0393cf 15795 mode_line_string_list =
fec8f23e
KS
15796 Fcons (mode_line_string_face_prop, Qnil);
15797 frame_title_ptr = NULL;
15798 }
15799 else
15800 {
15801 mode_line_string_face_prop = Qnil;
15802 mode_line_string_list = Qnil;
15803 frame_title_ptr = frame_title_buf;
15804 }
8143e6ab
KS
15805
15806 push_frame_kboard (it.f);
15807 display_mode_element (&it, 0, 0, 0, format, Qnil, 0);
15808 pop_frame_kboard ();
15809
15810 if (old_buffer)
15811 set_buffer_internal_1 (old_buffer);
15812
fec8f23e
KS
15813 if (NILP (no_props))
15814 {
15815 Lisp_Object str;
15816 mode_line_string_list = Fnreverse (mode_line_string_list);
15817 str = Fmapconcat (intern ("identity"), XCDR (mode_line_string_list),
15818 make_string ("", 0));
15819 mode_line_string_face_prop = Qnil;
15820 mode_line_string_list = Qnil;
15821 return str;
15822 }
15823
8143e6ab
KS
15824 len = frame_title_ptr - frame_title_buf;
15825 if (len > 0 && frame_title_ptr[-1] == '-')
15826 {
15827 /* Mode lines typically ends with numerous dashes; reduce to two dashes. */
15828 while (frame_title_ptr > frame_title_buf && *--frame_title_ptr == '-')
15829 ;
15830 frame_title_ptr += 3; /* restore last non-dash + two dashes */
15831 if (len > frame_title_ptr - frame_title_buf)
15832 len = frame_title_ptr - frame_title_buf;
15833 }
15834
15835 frame_title_ptr = NULL;
15836 return make_string (frame_title_buf, len);
15837}
15838
766525bc
RS
15839/* Write a null-terminated, right justified decimal representation of
15840 the positive integer D to BUF using a minimal field width WIDTH. */
15841
15842static void
15843pint2str (buf, width, d)
15844 register char *buf;
15845 register int width;
15846 register int d;
15847{
15848 register char *p = buf;
2311178e 15849
766525bc 15850 if (d <= 0)
5f5c8ee5 15851 *p++ = '0';
766525bc 15852 else
5f5c8ee5 15853 {
766525bc 15854 while (d > 0)
5f5c8ee5 15855 {
766525bc
RS
15856 *p++ = d % 10 + '0';
15857 d /= 10;
5f5c8ee5
GM
15858 }
15859 }
2311178e 15860
5f5c8ee5
GM
15861 for (width -= (int) (p - buf); width > 0; --width)
15862 *p++ = ' ';
766525bc
RS
15863 *p-- = '\0';
15864 while (p > buf)
5f5c8ee5 15865 {
766525bc
RS
15866 d = *buf;
15867 *buf++ = *p;
15868 *p-- = d;
5f5c8ee5 15869 }
766525bc
RS
15870}
15871
6b61353c
KH
15872/* Write a null-terminated, right justified decimal and "human
15873 readable" representation of the nonnegative integer D to BUF using
15874 a minimal field width WIDTH. D should be smaller than 999.5e24. */
15875
15876static const char power_letter[] =
15877 {
15878 0, /* not used */
15879 'k', /* kilo */
15880 'M', /* mega */
15881 'G', /* giga */
15882 'T', /* tera */
15883 'P', /* peta */
15884 'E', /* exa */
15885 'Z', /* zetta */
15886 'Y' /* yotta */
15887 };
15888
15889static void
15890pint2hrstr (buf, width, d)
15891 char *buf;
15892 int width;
15893 int d;
15894{
15895 /* We aim to represent the nonnegative integer D as
15896 QUOTIENT.TENTHS * 10 ^ (3 * EXPONENT). */
15897 int quotient = d;
15898 int remainder = 0;
15899 /* -1 means: do not use TENTHS. */
15900 int tenths = -1;
15901 int exponent = 0;
15902
15903 /* Length of QUOTIENT.TENTHS as a string. */
15904 int length;
15905
15906 char * psuffix;
15907 char * p;
15908
15909 if (1000 <= quotient)
15910 {
15911 /* Scale to the appropriate EXPONENT. */
15912 do
15913 {
15914 remainder = quotient % 1000;
15915 quotient /= 1000;
15916 exponent++;
15917 }
15918 while (1000 <= quotient);
15919
15920 /* Round to nearest and decide whether to use TENTHS or not. */
15921 if (quotient <= 9)
15922 {
15923 tenths = remainder / 100;
15924 if (50 <= remainder % 100)
15925 if (tenths < 9)
15926 tenths++;
15927 else
15928 {
15929 quotient++;
15930 if (quotient == 10)
15931 tenths = -1;
15932 else
15933 tenths = 0;
15934 }
15935 }
15936 else
15937 if (500 <= remainder)
15938 if (quotient < 999)
15939 quotient++;
15940 else
15941 {
15942 quotient = 1;
15943 exponent++;
15944 tenths = 0;
15945 }
15946 }
15947
15948 /* Calculate the LENGTH of QUOTIENT.TENTHS as a string. */
15949 if (tenths == -1 && quotient <= 99)
15950 if (quotient <= 9)
15951 length = 1;
15952 else
15953 length = 2;
15954 else
15955 length = 3;
15956 p = psuffix = buf + max (width, length);
15957
15958 /* Print EXPONENT. */
15959 if (exponent)
15960 *psuffix++ = power_letter[exponent];
15961 *psuffix = '\0';
15962
15963 /* Print TENTHS. */
15964 if (tenths >= 0)
15965 {
15966 *--p = '0' + tenths;
15967 *--p = '.';
15968 }
15969
15970 /* Print QUOTIENT. */
15971 do
15972 {
15973 int digit = quotient % 10;
15974 *--p = '0' + digit;
15975 }
15976 while ((quotient /= 10) != 0);
15977
15978 /* Print leading spaces. */
15979 while (buf < p)
15980 *--p = ' ';
15981}
15982
5f5c8ee5 15983/* Set a mnemonic character for coding_system (Lisp symbol) in BUF.
1c9241f5
KH
15984 If EOL_FLAG is 1, set also a mnemonic character for end-of-line
15985 type of CODING_SYSTEM. Return updated pointer into BUF. */
15986
6693a99a 15987static unsigned char invalid_eol_type[] = "(*invalid*)";
d24715e8 15988
1c9241f5
KH
15989static char *
15990decode_mode_spec_coding (coding_system, buf, eol_flag)
15991 Lisp_Object coding_system;
15992 register char *buf;
15993 int eol_flag;
15994{
1e1078d6 15995 Lisp_Object val;
916848d8 15996 int multibyte = !NILP (current_buffer->enable_multibyte_characters);
50f80c2f 15997 const unsigned char *eol_str;
302f2b38
EZ
15998 int eol_str_len;
15999 /* The EOL conversion we are using. */
16000 Lisp_Object eoltype;
1e1078d6 16001
ea0ffe21 16002 val = CODING_SYSTEM_SPEC (coding_system);
085536c2 16003 eoltype = Qnil;
1c9241f5 16004
4a09dee0 16005 if (!VECTORP (val)) /* Not yet decided. */
1c9241f5 16006 {
916848d8
RS
16007 if (multibyte)
16008 *buf++ = '-';
21e989e3 16009 if (eol_flag)
302f2b38 16010 eoltype = eol_mnemonic_undecided;
1e1078d6 16011 /* Don't mention EOL conversion if it isn't decided. */
1c9241f5
KH
16012 }
16013 else
16014 {
ea0ffe21 16015 Lisp_Object attrs;
1e1078d6
RS
16016 Lisp_Object eolvalue;
16017
ea0ffe21
KH
16018 attrs = AREF (val, 0);
16019 eolvalue = AREF (val, 2);
1e1078d6 16020
916848d8 16021 if (multibyte)
ea0ffe21 16022 *buf++ = XFASTINT (CODING_ATTR_MNEMONIC (attrs));
916848d8 16023
1c9241f5
KH
16024 if (eol_flag)
16025 {
1e1078d6
RS
16026 /* The EOL conversion that is normal on this system. */
16027
16028 if (NILP (eolvalue)) /* Not yet decided. */
16029 eoltype = eol_mnemonic_undecided;
16030 else if (VECTORP (eolvalue)) /* Not yet decided. */
16031 eoltype = eol_mnemonic_undecided;
ea0ffe21
KH
16032 else /* eolvalue is Qunix, Qdos, or Qmac. */
16033 eoltype = (EQ (eolvalue, Qunix)
1e1078d6 16034 ? eol_mnemonic_unix
ea0ffe21 16035 : (EQ (eolvalue, Qdos) == 1
1e1078d6 16036 ? eol_mnemonic_dos : eol_mnemonic_mac));
302f2b38
EZ
16037 }
16038 }
2311178e 16039
302f2b38
EZ
16040 if (eol_flag)
16041 {
16042 /* Mention the EOL conversion if it is not the usual one. */
16043 if (STRINGP (eoltype))
16044 {
2051c264
GM
16045 eol_str = SDATA (eoltype);
16046 eol_str_len = SBYTES (eoltype);
302f2b38 16047 }
c732cc73 16048 else if (CHARACTERP (eoltype))
f30b3499 16049 {
50f80c2f
KR
16050 unsigned char *tmp = (unsigned char *) alloca (MAX_MULTIBYTE_LENGTH);
16051 eol_str_len = CHAR_STRING (XINT (eoltype), tmp);
16052 eol_str = tmp;
f30b3499 16053 }
302f2b38
EZ
16054 else
16055 {
16056 eol_str = invalid_eol_type;
16057 eol_str_len = sizeof (invalid_eol_type) - 1;
1c9241f5 16058 }
f30b3499 16059 bcopy (eol_str, buf, eol_str_len);
302f2b38 16060 buf += eol_str_len;
1c9241f5 16061 }
302f2b38 16062
1c9241f5
KH
16063 return buf;
16064}
16065
a2889657 16066/* Return a string for the output of a mode line %-spec for window W,
5f5c8ee5
GM
16067 generated by character C. PRECISION >= 0 means don't return a
16068 string longer than that value. FIELD_WIDTH > 0 means pad the
72f62cb5
GM
16069 string returned with spaces to that value. Return 1 in *MULTIBYTE
16070 if the result is multibyte text. */
a2889657 16071
11e82b76
JB
16072static char lots_of_dashes[] = "--------------------------------------------------------------------------------------------------------------------------------------------";
16073
a2889657 16074static char *
72f62cb5 16075decode_mode_spec (w, c, field_width, precision, multibyte)
a2889657 16076 struct window *w;
68c45bf0 16077 register int c;
5f5c8ee5 16078 int field_width, precision;
72f62cb5 16079 int *multibyte;
a2889657 16080{
0b67772d 16081 Lisp_Object obj;
5f5c8ee5
GM
16082 struct frame *f = XFRAME (WINDOW_FRAME (w));
16083 char *decode_mode_spec_buf = f->decode_mode_spec_buffer;
d39b6696 16084 struct buffer *b = XBUFFER (w->buffer);
a2889657 16085
0b67772d 16086 obj = Qnil;
72f62cb5 16087 *multibyte = 0;
a2889657
JB
16088
16089 switch (c)
16090 {
1af9f229
RS
16091 case '*':
16092 if (!NILP (b->read_only))
16093 return "%";
16094 if (BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
16095 return "*";
16096 return "-";
16097
16098 case '+':
16099 /* This differs from %* only for a modified read-only buffer. */
16100 if (BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
16101 return "*";
16102 if (!NILP (b->read_only))
16103 return "%";
16104 return "-";
16105
16106 case '&':
16107 /* This differs from %* in ignoring read-only-ness. */
16108 if (BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
16109 return "*";
16110 return "-";
16111
16112 case '%':
16113 return "%";
16114
2311178e 16115 case '[':
1af9f229
RS
16116 {
16117 int i;
16118 char *p;
16119
16120 if (command_loop_level > 5)
16121 return "[[[... ";
16122 p = decode_mode_spec_buf;
16123 for (i = 0; i < command_loop_level; i++)
16124 *p++ = '[';
16125 *p = 0;
16126 return decode_mode_spec_buf;
16127 }
16128
2311178e 16129 case ']':
1af9f229
RS
16130 {
16131 int i;
16132 char *p;
16133
16134 if (command_loop_level > 5)
16135 return " ...]]]";
16136 p = decode_mode_spec_buf;
16137 for (i = 0; i < command_loop_level; i++)
16138 *p++ = ']';
16139 *p = 0;
16140 return decode_mode_spec_buf;
16141 }
16142
16143 case '-':
16144 {
1af9f229 16145 register int i;
5f5c8ee5
GM
16146
16147 /* Let lots_of_dashes be a string of infinite length. */
fec8f23e
KS
16148 if (!NILP (mode_line_string_list))
16149 return "--";
5f5c8ee5
GM
16150 if (field_width <= 0
16151 || field_width > sizeof (lots_of_dashes))
1af9f229 16152 {
5f5c8ee5
GM
16153 for (i = 0; i < FRAME_MESSAGE_BUF_SIZE (f) - 1; ++i)
16154 decode_mode_spec_buf[i] = '-';
16155 decode_mode_spec_buf[i] = '\0';
16156 return decode_mode_spec_buf;
1af9f229 16157 }
5f5c8ee5
GM
16158 else
16159 return lots_of_dashes;
1af9f229
RS
16160 }
16161
2311178e 16162 case 'b':
d39b6696 16163 obj = b->name;
a2889657
JB
16164 break;
16165
1af9f229
RS
16166 case 'c':
16167 {
2311178e 16168 int col = (int) current_column (); /* iftc */
ac90c44f 16169 w->column_number_displayed = make_number (col);
5f5c8ee5 16170 pint2str (decode_mode_spec_buf, field_width, col);
1af9f229
RS
16171 return decode_mode_spec_buf;
16172 }
16173
16174 case 'F':
16175 /* %F displays the frame name. */
5f5c8ee5 16176 if (!NILP (f->title))
2051c264 16177 return (char *) SDATA (f->title);
fd8ff63d 16178 if (f->explicit_name || ! FRAME_WINDOW_P (f))
2051c264 16179 return (char *) SDATA (f->name);
9c6da96f 16180 return "Emacs";
1af9f229 16181
2311178e 16182 case 'f':
d39b6696 16183 obj = b->filename;
a2889657
JB
16184 break;
16185
6b61353c
KH
16186 case 'i':
16187 {
16188 int size = ZV - BEGV;
16189 pint2str (decode_mode_spec_buf, field_width, size);
16190 return decode_mode_spec_buf;
16191 }
16192
16193 case 'I':
16194 {
16195 int size = ZV - BEGV;
16196 pint2hrstr (decode_mode_spec_buf, field_width, size);
16197 return decode_mode_spec_buf;
16198 }
16199
aa6d10fa
RS
16200 case 'l':
16201 {
12adba34
RS
16202 int startpos = XMARKER (w->start)->charpos;
16203 int startpos_byte = marker_byte_position (w->start);
16204 int line, linepos, linepos_byte, topline;
aa6d10fa 16205 int nlines, junk;
da8b7f4f 16206 int height = WINDOW_TOTAL_LINES (w);
aa6d10fa 16207
2311178e 16208 /* If we decided that this buffer isn't suitable for line numbers,
aa6d10fa
RS
16209 don't forget that too fast. */
16210 if (EQ (w->base_line_pos, w->buffer))
766525bc 16211 goto no_value;
5300fd39
RS
16212 /* But do forget it, if the window shows a different buffer now. */
16213 else if (BUFFERP (w->base_line_pos))
16214 w->base_line_pos = Qnil;
aa6d10fa
RS
16215
16216 /* If the buffer is very big, don't waste time. */
37d034d3 16217 if (INTEGERP (Vline_number_display_limit)
090703f4 16218 && BUF_ZV (b) - BUF_BEGV (b) > XINT (Vline_number_display_limit))
aa6d10fa
RS
16219 {
16220 w->base_line_pos = Qnil;
16221 w->base_line_number = Qnil;
766525bc 16222 goto no_value;
aa6d10fa
RS
16223 }
16224
16225 if (!NILP (w->base_line_number)
16226 && !NILP (w->base_line_pos)
12adba34 16227 && XFASTINT (w->base_line_pos) <= startpos)
aa6d10fa
RS
16228 {
16229 line = XFASTINT (w->base_line_number);
16230 linepos = XFASTINT (w->base_line_pos);
12adba34 16231 linepos_byte = buf_charpos_to_bytepos (b, linepos);
aa6d10fa
RS
16232 }
16233 else
16234 {
16235 line = 1;
d39b6696 16236 linepos = BUF_BEGV (b);
12adba34 16237 linepos_byte = BUF_BEGV_BYTE (b);
aa6d10fa
RS
16238 }
16239
16240 /* Count lines from base line to window start position. */
12adba34
RS
16241 nlines = display_count_lines (linepos, linepos_byte,
16242 startpos_byte,
16243 startpos, &junk);
aa6d10fa
RS
16244
16245 topline = nlines + line;
16246
16247 /* Determine a new base line, if the old one is too close
16248 or too far away, or if we did not have one.
16249 "Too close" means it's plausible a scroll-down would
16250 go back past it. */
d39b6696 16251 if (startpos == BUF_BEGV (b))
aa6d10fa 16252 {
ac90c44f
GM
16253 w->base_line_number = make_number (topline);
16254 w->base_line_pos = make_number (BUF_BEGV (b));
aa6d10fa
RS
16255 }
16256 else if (nlines < height + 25 || nlines > height * 3 + 50
d39b6696 16257 || linepos == BUF_BEGV (b))
aa6d10fa 16258 {
d39b6696 16259 int limit = BUF_BEGV (b);
12adba34 16260 int limit_byte = BUF_BEGV_BYTE (b);
aa6d10fa 16261 int position;
5d121aec 16262 int distance = (height * 2 + 30) * line_number_display_limit_width;
aa6d10fa
RS
16263
16264 if (startpos - distance > limit)
12adba34
RS
16265 {
16266 limit = startpos - distance;
16267 limit_byte = CHAR_TO_BYTE (limit);
16268 }
aa6d10fa 16269
12adba34
RS
16270 nlines = display_count_lines (startpos, startpos_byte,
16271 limit_byte,
16272 - (height * 2 + 30),
aa6d10fa 16273 &position);
2311178e 16274 /* If we couldn't find the lines we wanted within
5d121aec 16275 line_number_display_limit_width chars per line,
aa6d10fa 16276 give up on line numbers for this window. */
12adba34 16277 if (position == limit_byte && limit == startpos - distance)
aa6d10fa
RS
16278 {
16279 w->base_line_pos = w->buffer;
16280 w->base_line_number = Qnil;
766525bc 16281 goto no_value;
aa6d10fa
RS
16282 }
16283
ac90c44f
GM
16284 w->base_line_number = make_number (topline - nlines);
16285 w->base_line_pos = make_number (BYTE_TO_CHAR (position));
aa6d10fa
RS
16286 }
16287
16288 /* Now count lines from the start pos to point. */
12adba34
RS
16289 nlines = display_count_lines (startpos, startpos_byte,
16290 PT_BYTE, PT, &junk);
aa6d10fa
RS
16291
16292 /* Record that we did display the line number. */
16293 line_number_displayed = 1;
16294
16295 /* Make the string to show. */
5f5c8ee5 16296 pint2str (decode_mode_spec_buf, field_width, topline + nlines);
aa6d10fa 16297 return decode_mode_spec_buf;
766525bc
RS
16298 no_value:
16299 {
16300 char* p = decode_mode_spec_buf;
5f5c8ee5
GM
16301 int pad = field_width - 2;
16302 while (pad-- > 0)
16303 *p++ = ' ';
16304 *p++ = '?';
b357b9d4
KR
16305 *p++ = '?';
16306 *p = '\0';
766525bc
RS
16307 return decode_mode_spec_buf;
16308 }
aa6d10fa
RS
16309 }
16310 break;
16311
2311178e 16312 case 'm':
d39b6696 16313 obj = b->mode_name;
a2889657
JB
16314 break;
16315
16316 case 'n':
d39b6696 16317 if (BUF_BEGV (b) > BUF_BEG (b) || BUF_ZV (b) < BUF_Z (b))
a2889657
JB
16318 return " Narrow";
16319 break;
16320
a2889657
JB
16321 case 'p':
16322 {
16323 int pos = marker_position (w->start);
d39b6696 16324 int total = BUF_ZV (b) - BUF_BEGV (b);
a2889657 16325
d39b6696 16326 if (XFASTINT (w->window_end_pos) <= BUF_Z (b) - BUF_ZV (b))
a2889657 16327 {
d39b6696 16328 if (pos <= BUF_BEGV (b))
a2889657
JB
16329 return "All";
16330 else
16331 return "Bottom";
16332 }
d39b6696 16333 else if (pos <= BUF_BEGV (b))
a2889657
JB
16334 return "Top";
16335 else
16336 {
3c7d31b9
RS
16337 if (total > 1000000)
16338 /* Do it differently for a large value, to avoid overflow. */
16339 total = ((pos - BUF_BEGV (b)) + (total / 100) - 1) / (total / 100);
16340 else
16341 total = ((pos - BUF_BEGV (b)) * 100 + total - 1) / total;
a2889657
JB
16342 /* We can't normally display a 3-digit number,
16343 so get us a 2-digit number that is close. */
16344 if (total == 100)
16345 total = 99;
16346 sprintf (decode_mode_spec_buf, "%2d%%", total);
16347 return decode_mode_spec_buf;
16348 }
16349 }
16350
8ffcb79f
RS
16351 /* Display percentage of size above the bottom of the screen. */
16352 case 'P':
16353 {
16354 int toppos = marker_position (w->start);
d39b6696
KH
16355 int botpos = BUF_Z (b) - XFASTINT (w->window_end_pos);
16356 int total = BUF_ZV (b) - BUF_BEGV (b);
8ffcb79f 16357
d39b6696 16358 if (botpos >= BUF_ZV (b))
8ffcb79f 16359 {
d39b6696 16360 if (toppos <= BUF_BEGV (b))
8ffcb79f
RS
16361 return "All";
16362 else
16363 return "Bottom";
16364 }
16365 else
16366 {
3c7d31b9
RS
16367 if (total > 1000000)
16368 /* Do it differently for a large value, to avoid overflow. */
16369 total = ((botpos - BUF_BEGV (b)) + (total / 100) - 1) / (total / 100);
16370 else
16371 total = ((botpos - BUF_BEGV (b)) * 100 + total - 1) / total;
8ffcb79f
RS
16372 /* We can't normally display a 3-digit number,
16373 so get us a 2-digit number that is close. */
16374 if (total == 100)
16375 total = 99;
d39b6696 16376 if (toppos <= BUF_BEGV (b))
8ffcb79f
RS
16377 sprintf (decode_mode_spec_buf, "Top%2d%%", total);
16378 else
16379 sprintf (decode_mode_spec_buf, "%2d%%", total);
16380 return decode_mode_spec_buf;
16381 }
16382 }
16383
1af9f229
RS
16384 case 's':
16385 /* status of process */
16386 obj = Fget_buffer_process (w->buffer);
16387 if (NILP (obj))
16388 return "no process";
16389#ifdef subprocesses
16390 obj = Fsymbol_name (Fprocess_status (obj));
16391#endif
16392 break;
d39b6696 16393
1af9f229
RS
16394 case 't': /* indicate TEXT or BINARY */
16395#ifdef MODE_LINE_BINARY_TEXT
16396 return MODE_LINE_BINARY_TEXT (b);
16397#else
16398 return "T";
16399#endif
1c9241f5
KH
16400
16401 case 'z':
16402 /* coding-system (not including end-of-line format) */
16403 case 'Z':
16404 /* coding-system (including end-of-line type) */
16405 {
16406 int eol_flag = (c == 'Z');
539b4d41 16407 char *p = decode_mode_spec_buf;
1c9241f5 16408
d30e754b 16409 if (! FRAME_WINDOW_P (f))
1c9241f5 16410 {
11c52c4f
RS
16411 /* No need to mention EOL here--the terminal never needs
16412 to do EOL conversion. */
ea0ffe21
KH
16413 p = decode_mode_spec_coding (CODING_ID_NAME (keyboard_coding.id),
16414 p, 0);
16415 p = decode_mode_spec_coding (CODING_ID_NAME (terminal_coding.id),
16416 p, 0);
1c9241f5 16417 }
f13c925f 16418 p = decode_mode_spec_coding (b->buffer_file_coding_system,
539b4d41 16419 p, eol_flag);
f13c925f 16420
11c52c4f 16421#if 0 /* This proves to be annoying; I think we can do without. -- rms. */
1c9241f5
KH
16422#ifdef subprocesses
16423 obj = Fget_buffer_process (Fcurrent_buffer ());
16424 if (PROCESSP (obj))
16425 {
16426 p = decode_mode_spec_coding (XPROCESS (obj)->decode_coding_system,
16427 p, eol_flag);
16428 p = decode_mode_spec_coding (XPROCESS (obj)->encode_coding_system,
16429 p, eol_flag);
16430 }
16431#endif /* subprocesses */
11c52c4f 16432#endif /* 0 */
1c9241f5
KH
16433 *p = 0;
16434 return decode_mode_spec_buf;
16435 }
a2889657 16436 }
d39b6696 16437
e24c997d 16438 if (STRINGP (obj))
72f62cb5
GM
16439 {
16440 *multibyte = STRING_MULTIBYTE (obj);
2051c264 16441 return (char *) SDATA (obj);
72f62cb5 16442 }
a2889657
JB
16443 else
16444 return "";
16445}
5f5c8ee5
GM
16446
16447
12adba34
RS
16448/* Count up to COUNT lines starting from START / START_BYTE.
16449 But don't go beyond LIMIT_BYTE.
16450 Return the number of lines thus found (always nonnegative).
59b49f63 16451
12adba34 16452 Set *BYTE_POS_PTR to 1 if we found COUNT lines, 0 if we hit LIMIT. */
59b49f63
RS
16453
16454static int
12adba34
RS
16455display_count_lines (start, start_byte, limit_byte, count, byte_pos_ptr)
16456 int start, start_byte, limit_byte, count;
16457 int *byte_pos_ptr;
59b49f63 16458{
59b49f63
RS
16459 register unsigned char *cursor;
16460 unsigned char *base;
16461
16462 register int ceiling;
16463 register unsigned char *ceiling_addr;
12adba34 16464 int orig_count = count;
59b49f63
RS
16465
16466 /* If we are not in selective display mode,
16467 check only for newlines. */
12adba34
RS
16468 int selective_display = (!NILP (current_buffer->selective_display)
16469 && !INTEGERP (current_buffer->selective_display));
59b49f63
RS
16470
16471 if (count > 0)
12adba34
RS
16472 {
16473 while (start_byte < limit_byte)
16474 {
16475 ceiling = BUFFER_CEILING_OF (start_byte);
16476 ceiling = min (limit_byte - 1, ceiling);
16477 ceiling_addr = BYTE_POS_ADDR (ceiling) + 1;
16478 base = (cursor = BYTE_POS_ADDR (start_byte));
16479 while (1)
16480 {
16481 if (selective_display)
16482 while (*cursor != '\n' && *cursor != 015 && ++cursor != ceiling_addr)
16483 ;
16484 else
16485 while (*cursor != '\n' && ++cursor != ceiling_addr)
16486 ;
16487
16488 if (cursor != ceiling_addr)
16489 {
16490 if (--count == 0)
16491 {
16492 start_byte += cursor - base + 1;
16493 *byte_pos_ptr = start_byte;
16494 return orig_count;
16495 }
16496 else
16497 if (++cursor == ceiling_addr)
16498 break;
16499 }
16500 else
16501 break;
16502 }
16503 start_byte += cursor - base;
16504 }
16505 }
59b49f63
RS
16506 else
16507 {
12adba34
RS
16508 while (start_byte > limit_byte)
16509 {
16510 ceiling = BUFFER_FLOOR_OF (start_byte - 1);
16511 ceiling = max (limit_byte, ceiling);
16512 ceiling_addr = BYTE_POS_ADDR (ceiling) - 1;
16513 base = (cursor = BYTE_POS_ADDR (start_byte - 1) + 1);
59b49f63
RS
16514 while (1)
16515 {
12adba34
RS
16516 if (selective_display)
16517 while (--cursor != ceiling_addr
16518 && *cursor != '\n' && *cursor != 015)
16519 ;
16520 else
16521 while (--cursor != ceiling_addr && *cursor != '\n')
16522 ;
16523
59b49f63
RS
16524 if (cursor != ceiling_addr)
16525 {
16526 if (++count == 0)
16527 {
12adba34
RS
16528 start_byte += cursor - base + 1;
16529 *byte_pos_ptr = start_byte;
16530 /* When scanning backwards, we should
16531 not count the newline posterior to which we stop. */
16532 return - orig_count - 1;
59b49f63
RS
16533 }
16534 }
16535 else
16536 break;
16537 }
12adba34
RS
16538 /* Here we add 1 to compensate for the last decrement
16539 of CURSOR, which took it past the valid range. */
16540 start_byte += cursor - base + 1;
59b49f63
RS
16541 }
16542 }
16543
12adba34 16544 *byte_pos_ptr = limit_byte;
aa6d10fa 16545
12adba34
RS
16546 if (count < 0)
16547 return - orig_count + count;
16548 return orig_count - count;
aa6d10fa 16549
12adba34 16550}
a2889657 16551
a2889657 16552
5f5c8ee5
GM
16553\f
16554/***********************************************************************
16555 Displaying strings
16556 ***********************************************************************/
278feba9 16557
5f5c8ee5 16558/* Display a NUL-terminated string, starting with index START.
a3788d53 16559
5f5c8ee5
GM
16560 If STRING is non-null, display that C string. Otherwise, the Lisp
16561 string LISP_STRING is displayed.
a2889657 16562
5f5c8ee5
GM
16563 If FACE_STRING is not nil, FACE_STRING_POS is a position in
16564 FACE_STRING. Display STRING or LISP_STRING with the face at
16565 FACE_STRING_POS in FACE_STRING:
a2889657 16566
5f5c8ee5
GM
16567 Display the string in the environment given by IT, but use the
16568 standard display table, temporarily.
a3788d53 16569
5f5c8ee5
GM
16570 FIELD_WIDTH is the minimum number of output glyphs to produce.
16571 If STRING has fewer characters than FIELD_WIDTH, pad to the right
16572 with spaces. If STRING has more characters, more than FIELD_WIDTH
16573 glyphs will be produced. FIELD_WIDTH <= 0 means don't pad.
2311178e 16574
5f5c8ee5
GM
16575 PRECISION is the maximum number of characters to output from
16576 STRING. PRECISION < 0 means don't truncate the string.
a2889657 16577
5f5c8ee5 16578 This is roughly equivalent to printf format specifiers:
a2889657 16579
5f5c8ee5
GM
16580 FIELD_WIDTH PRECISION PRINTF
16581 ----------------------------------------
16582 -1 -1 %s
16583 -1 10 %.10s
16584 10 -1 %10s
16585 20 10 %20.10s
a2889657 16586
5f5c8ee5
GM
16587 MULTIBYTE zero means do not display multibyte chars, > 0 means do
16588 display them, and < 0 means obey the current buffer's value of
16589 enable_multibyte_characters.
278feba9 16590
5f5c8ee5 16591 Value is the number of glyphs produced. */
b1d1124b 16592
5f5c8ee5
GM
16593static int
16594display_string (string, lisp_string, face_string, face_string_pos,
16595 start, it, field_width, precision, max_x, multibyte)
16596 unsigned char *string;
16597 Lisp_Object lisp_string;
68c45bf0
PE
16598 Lisp_Object face_string;
16599 int face_string_pos;
5f5c8ee5
GM
16600 int start;
16601 struct it *it;
16602 int field_width, precision, max_x;
16603 int multibyte;
16604{
16605 int hpos_at_start = it->hpos;
16606 int saved_face_id = it->face_id;
16607 struct glyph_row *row = it->glyph_row;
16608
16609 /* Initialize the iterator IT for iteration over STRING beginning
e719f5ae 16610 with index START. */
5f5c8ee5
GM
16611 reseat_to_string (it, string, lisp_string, start,
16612 precision, field_width, multibyte);
16613
16614 /* If displaying STRING, set up the face of the iterator
16615 from LISP_STRING, if that's given. */
16616 if (STRINGP (face_string))
16617 {
16618 int endptr;
16619 struct face *face;
2311178e 16620
5f5c8ee5
GM
16621 it->face_id
16622 = face_at_string_position (it->w, face_string, face_string_pos,
16623 0, it->region_beg_charpos,
16624 it->region_end_charpos,
5de7c6f2 16625 &endptr, it->base_face_id, 0);
5f5c8ee5
GM
16626 face = FACE_FROM_ID (it->f, it->face_id);
16627 it->face_box_p = face->box != FACE_NO_BOX;
b1d1124b 16628 }
a2889657 16629
5f5c8ee5
GM
16630 /* Set max_x to the maximum allowed X position. Don't let it go
16631 beyond the right edge of the window. */
16632 if (max_x <= 0)
16633 max_x = it->last_visible_x;
16634 else
16635 max_x = min (max_x, it->last_visible_x);
efc63ef0 16636
5f5c8ee5
GM
16637 /* Skip over display elements that are not visible. because IT->w is
16638 hscrolled. */
16639 if (it->current_x < it->first_visible_x)
16640 move_it_in_display_line_to (it, 100000, it->first_visible_x,
16641 MOVE_TO_POS | MOVE_TO_X);
a2889657 16642
5f5c8ee5
GM
16643 row->ascent = it->max_ascent;
16644 row->height = it->max_ascent + it->max_descent;
312246d1
GM
16645 row->phys_ascent = it->max_phys_ascent;
16646 row->phys_height = it->max_phys_ascent + it->max_phys_descent;
1c9241f5 16647
5f5c8ee5
GM
16648 /* This condition is for the case that we are called with current_x
16649 past last_visible_x. */
16650 while (it->current_x < max_x)
a2889657 16651 {
5f5c8ee5 16652 int x_before, x, n_glyphs_before, i, nglyphs;
1c9241f5 16653
5f5c8ee5
GM
16654 /* Get the next display element. */
16655 if (!get_next_display_element (it))
90adcf20 16656 break;
1c9241f5 16657
5f5c8ee5
GM
16658 /* Produce glyphs. */
16659 x_before = it->current_x;
16660 n_glyphs_before = it->glyph_row->used[TEXT_AREA];
16661 PRODUCE_GLYPHS (it);
90adcf20 16662
5f5c8ee5
GM
16663 nglyphs = it->glyph_row->used[TEXT_AREA] - n_glyphs_before;
16664 i = 0;
16665 x = x_before;
16666 while (i < nglyphs)
a2889657 16667 {
5f5c8ee5 16668 struct glyph *glyph = row->glyphs[TEXT_AREA] + n_glyphs_before + i;
2311178e 16669
5f5c8ee5
GM
16670 if (!it->truncate_lines_p
16671 && x + glyph->pixel_width > max_x)
16672 {
16673 /* End of continued line or max_x reached. */
37be86f2
KH
16674 if (CHAR_GLYPH_PADDING_P (*glyph))
16675 {
16676 /* A wide character is unbreakable. */
16677 it->glyph_row->used[TEXT_AREA] = n_glyphs_before;
16678 it->current_x = x_before;
16679 }
16680 else
16681 {
16682 it->glyph_row->used[TEXT_AREA] = n_glyphs_before + i;
16683 it->current_x = x;
16684 }
5f5c8ee5
GM
16685 break;
16686 }
587cb9a7 16687 else if (x + glyph->pixel_width >= it->first_visible_x)
5f5c8ee5
GM
16688 {
16689 /* Glyph is at least partially visible. */
16690 ++it->hpos;
16691 if (x < it->first_visible_x)
16692 it->glyph_row->x = x - it->first_visible_x;
16693 }
16694 else
a2889657 16695 {
5f5c8ee5
GM
16696 /* Glyph is off the left margin of the display area.
16697 Should not happen. */
16698 abort ();
a2889657 16699 }
5f5c8ee5
GM
16700
16701 row->ascent = max (row->ascent, it->max_ascent);
16702 row->height = max (row->height, it->max_ascent + it->max_descent);
312246d1
GM
16703 row->phys_ascent = max (row->phys_ascent, it->max_phys_ascent);
16704 row->phys_height = max (row->phys_height,
16705 it->max_phys_ascent + it->max_phys_descent);
5f5c8ee5
GM
16706 x += glyph->pixel_width;
16707 ++i;
a2889657 16708 }
5f5c8ee5
GM
16709
16710 /* Stop if max_x reached. */
16711 if (i < nglyphs)
16712 break;
16713
16714 /* Stop at line ends. */
16715 if (ITERATOR_AT_END_OF_LINE_P (it))
a2889657 16716 {
5f5c8ee5
GM
16717 it->continuation_lines_width = 0;
16718 break;
a2889657 16719 }
1c9241f5 16720
cafafe0b 16721 set_iterator_to_next (it, 1);
a688bb24 16722
5f5c8ee5
GM
16723 /* Stop if truncating at the right edge. */
16724 if (it->truncate_lines_p
16725 && it->current_x >= it->last_visible_x)
16726 {
16727 /* Add truncation mark, but don't do it if the line is
16728 truncated at a padding space. */
16729 if (IT_CHARPOS (*it) < it->string_nchars)
1c9241f5 16730 {
5f5c8ee5 16731 if (!FRAME_WINDOW_P (it->f))
37be86f2
KH
16732 {
16733 int i, n;
16734
9299cb15 16735 if (it->current_x > it->last_visible_x)
37be86f2 16736 {
9299cb15
KH
16737 for (i = row->used[TEXT_AREA] - 1; i > 0; --i)
16738 if (!CHAR_GLYPH_PADDING_P (row->glyphs[TEXT_AREA][i]))
16739 break;
16740 for (n = row->used[TEXT_AREA]; i < n; ++i)
16741 {
16742 row->used[TEXT_AREA] = i;
16743 produce_special_glyphs (it, IT_TRUNCATION);
16744 }
37be86f2 16745 }
9299cb15 16746 produce_special_glyphs (it, IT_TRUNCATION);
37be86f2 16747 }
5f5c8ee5 16748 it->glyph_row->truncated_on_right_p = 1;
1c9241f5 16749 }
5f5c8ee5 16750 break;
1c9241f5 16751 }
a2889657
JB
16752 }
16753
5f5c8ee5
GM
16754 /* Maybe insert a truncation at the left. */
16755 if (it->first_visible_x
16756 && IT_CHARPOS (*it) > 0)
a2889657 16757 {
5f5c8ee5
GM
16758 if (!FRAME_WINDOW_P (it->f))
16759 insert_left_trunc_glyphs (it);
16760 it->glyph_row->truncated_on_left_p = 1;
a2889657
JB
16761 }
16762
5f5c8ee5 16763 it->face_id = saved_face_id;
2311178e 16764
5f5c8ee5
GM
16765 /* Value is number of columns displayed. */
16766 return it->hpos - hpos_at_start;
16767}
a2889657 16768
a2889657 16769
a2889657 16770\f
3b6b6db7 16771/* This is like a combination of memq and assq. Return 1/2 if PROPVAL
5f5c8ee5
GM
16772 appears as an element of LIST or as the car of an element of LIST.
16773 If PROPVAL is a list, compare each element against LIST in that
3b6b6db7
SM
16774 way, and return 1/2 if any element of PROPVAL is found in LIST.
16775 Otherwise return 0. This function cannot quit.
16776 The return value is 2 if the text is invisible but with an ellipsis
16777 and 1 if it's invisible and without an ellipsis. */
642eefc6
RS
16778
16779int
16780invisible_p (propval, list)
16781 register Lisp_Object propval;
16782 Lisp_Object list;
16783{
3b6b6db7 16784 register Lisp_Object tail, proptail;
2311178e 16785
3b6b6db7
SM
16786 for (tail = list; CONSP (tail); tail = XCDR (tail))
16787 {
16788 register Lisp_Object tem;
16789 tem = XCAR (tail);
16790 if (EQ (propval, tem))
16791 return 1;
16792 if (CONSP (tem) && EQ (propval, XCAR (tem)))
16793 return NILP (XCDR (tem)) ? 1 : 2;
16794 }
2311178e 16795
3b6b6db7
SM
16796 if (CONSP (propval))
16797 {
16798 for (proptail = propval; CONSP (proptail); proptail = XCDR (proptail))
16799 {
16800 Lisp_Object propelt;
16801 propelt = XCAR (proptail);
16802 for (tail = list; CONSP (tail); tail = XCDR (tail))
16803 {
16804 register Lisp_Object tem;
16805 tem = XCAR (tail);
16806 if (EQ (propelt, tem))
16807 return 1;
16808 if (CONSP (tem) && EQ (propelt, XCAR (tem)))
16809 return NILP (XCDR (tem)) ? 1 : 2;
16810 }
16811 }
16812 }
2311178e 16813
3b6b6db7 16814 return 0;
642eefc6 16815}
5f5c8ee5 16816
6b61353c
KH
16817/* Calculate a width or height in pixels from a specification using
16818 the following elements:
16819
16820 SPEC ::=
16821 NUM - a (fractional) multiple of the default font width/height
16822 (NUM) - specifies exactly NUM pixels
16823 UNIT - a fixed number of pixels, see below.
16824 ELEMENT - size of a display element in pixels, see below.
16825 (NUM . SPEC) - equals NUM * SPEC
16826 (+ SPEC SPEC ...) - add pixel values
16827 (- SPEC SPEC ...) - subtract pixel values
16828 (- SPEC) - negate pixel value
16829
16830 NUM ::=
16831 INT or FLOAT - a number constant
16832 SYMBOL - use symbol's (buffer local) variable binding.
16833
16834 UNIT ::=
16835 in - pixels per inch *)
16836 mm - pixels per 1/1000 meter *)
16837 cm - pixels per 1/100 meter *)
16838 width - width of current font in pixels.
16839 height - height of current font in pixels.
16840
16841 *) using the ratio(s) defined in display-pixels-per-inch.
16842
16843 ELEMENT ::=
16844
16845 left-fringe - left fringe width in pixels
16846 right-fringe - right fringe width in pixels
16847
16848 left-margin - left margin width in pixels
16849 right-margin - right margin width in pixels
16850
16851 scroll-bar - scroll-bar area width in pixels
16852
16853 Examples:
16854
16855 Pixels corresponding to 5 inches:
16856 (5 . in)
16857
16858 Total width of non-text areas on left side of window (if scroll-bar is on left):
16859 '(space :width (+ left-fringe left-margin scroll-bar))
16860
16861 Align to first text column (in header line):
16862 '(space :align-to 0)
16863
16864 Align to middle of text area minus half the width of variable `my-image'
16865 containing a loaded image:
16866 '(space :align-to (0.5 . (- text my-image)))
16867
16868 Width of left margin minus width of 1 character in the default font:
16869 '(space :width (- left-margin 1))
16870
16871 Width of left margin minus width of 2 characters in the current font:
16872 '(space :width (- left-margin (2 . width)))
16873
16874 Center 1 character over left-margin (in header line):
16875 '(space :align-to (+ left-margin (0.5 . left-margin) -0.5))
16876
16877 Different ways to express width of left fringe plus left margin minus one pixel:
16878 '(space :width (- (+ left-fringe left-margin) (1)))
16879 '(space :width (+ left-fringe left-margin (- (1))))
16880 '(space :width (+ left-fringe left-margin (-1)))
16881
16882*/
16883
16884#define NUMVAL(X) \
16885 ((INTEGERP (X) || FLOATP (X)) \
16886 ? XFLOATINT (X) \
16887 : - 1)
16888
16889int
16890calc_pixel_width_or_height (res, it, prop, font, width_p, align_to)
16891 double *res;
16892 struct it *it;
16893 Lisp_Object prop;
16894 void *font;
16895 int width_p, *align_to;
16896{
16897 double pixels;
16898
16899#define OK_PIXELS(val) ((*res = (double)(val)), 1)
16900#define OK_ALIGN_TO(val) ((*align_to = (int)(val)), 1)
16901
16902 if (NILP (prop))
16903 return OK_PIXELS (0);
16904
16905 if (SYMBOLP (prop))
16906 {
16907 if (SCHARS (SYMBOL_NAME (prop)) == 2)
16908 {
16909 char *unit = SDATA (SYMBOL_NAME (prop));
16910
16911 if (unit[0] == 'i' && unit[1] == 'n')
16912 pixels = 1.0;
16913 else if (unit[0] == 'm' && unit[1] == 'm')
16914 pixels = 25.4;
16915 else if (unit[0] == 'c' && unit[1] == 'm')
16916 pixels = 2.54;
16917 else
16918 pixels = 0;
16919 if (pixels > 0)
16920 {
16921 double ppi;
16922 if ((ppi = NUMVAL (Vdisplay_pixels_per_inch), ppi > 0)
16923 || (CONSP (Vdisplay_pixels_per_inch)
16924 && (ppi = (width_p
16925 ? NUMVAL (XCAR (Vdisplay_pixels_per_inch))
16926 : NUMVAL (XCDR (Vdisplay_pixels_per_inch))),
16927 ppi > 0)))
16928 return OK_PIXELS (ppi / pixels);
16929
16930 return 0;
16931 }
16932 }
16933
16934#ifdef HAVE_WINDOW_SYSTEM
16935 if (EQ (prop, Qheight))
16936 return OK_PIXELS (font ? FONT_HEIGHT ((XFontStruct *)font) : FRAME_LINE_HEIGHT (it->f));
16937 if (EQ (prop, Qwidth))
16938 return OK_PIXELS (font ? FONT_WIDTH ((XFontStruct *)font) : FRAME_COLUMN_WIDTH (it->f));
16939#else
16940 if (EQ (prop, Qheight) || EQ (prop, Qwidth))
16941 return OK_PIXELS (1);
16942#endif
16943
16944 if (EQ (prop, Qtext))
16945 return OK_PIXELS (width_p
16946 ? window_box_width (it->w, TEXT_AREA)
16947 : WINDOW_BOX_HEIGHT_NO_MODE_LINE (it->w));
16948
16949 if (align_to && *align_to < 0)
16950 {
16951 *res = 0;
16952 if (EQ (prop, Qleft))
16953 return OK_ALIGN_TO (window_box_left_offset (it->w, TEXT_AREA));
16954 if (EQ (prop, Qright))
16955 return OK_ALIGN_TO (window_box_right_offset (it->w, TEXT_AREA));
16956 if (EQ (prop, Qcenter))
16957 return OK_ALIGN_TO (window_box_left_offset (it->w, TEXT_AREA)
16958 + window_box_width (it->w, TEXT_AREA) / 2);
16959 if (EQ (prop, Qleft_fringe))
16960 return OK_ALIGN_TO (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (it->w)
16961 ? WINDOW_LEFT_SCROLL_BAR_AREA_WIDTH (it->w)
16962 : window_box_right_offset (it->w, LEFT_MARGIN_AREA));
16963 if (EQ (prop, Qright_fringe))
16964 return OK_ALIGN_TO (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (it->w)
16965 ? window_box_right_offset (it->w, RIGHT_MARGIN_AREA)
16966 : window_box_right_offset (it->w, TEXT_AREA));
16967 if (EQ (prop, Qleft_margin))
16968 return OK_ALIGN_TO (window_box_left_offset (it->w, LEFT_MARGIN_AREA));
16969 if (EQ (prop, Qright_margin))
16970 return OK_ALIGN_TO (window_box_left_offset (it->w, RIGHT_MARGIN_AREA));
16971 if (EQ (prop, Qscroll_bar))
16972 return OK_ALIGN_TO (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (it->w)
16973 ? 0
16974 : (window_box_right_offset (it->w, RIGHT_MARGIN_AREA)
16975 + (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (it->w)
16976 ? WINDOW_RIGHT_FRINGE_WIDTH (it->w)
16977 : 0)));
16978 }
16979 else
16980 {
16981 if (EQ (prop, Qleft_fringe))
16982 return OK_PIXELS (WINDOW_LEFT_FRINGE_WIDTH (it->w));
16983 if (EQ (prop, Qright_fringe))
16984 return OK_PIXELS (WINDOW_RIGHT_FRINGE_WIDTH (it->w));
16985 if (EQ (prop, Qleft_margin))
16986 return OK_PIXELS (WINDOW_LEFT_MARGIN_WIDTH (it->w));
16987 if (EQ (prop, Qright_margin))
16988 return OK_PIXELS (WINDOW_RIGHT_MARGIN_WIDTH (it->w));
16989 if (EQ (prop, Qscroll_bar))
16990 return OK_PIXELS (WINDOW_SCROLL_BAR_AREA_WIDTH (it->w));
16991 }
16992
16993 prop = Fbuffer_local_value (prop, it->w->buffer);
16994 }
16995
16996 if (INTEGERP (prop) || FLOATP (prop))
16997 {
16998 int base_unit = (width_p
16999 ? FRAME_COLUMN_WIDTH (it->f)
17000 : FRAME_LINE_HEIGHT (it->f));
17001 return OK_PIXELS (XFLOATINT (prop) * base_unit);
17002 }
17003
17004 if (CONSP (prop))
17005 {
17006 Lisp_Object car = XCAR (prop);
17007 Lisp_Object cdr = XCDR (prop);
17008
17009 if (SYMBOLP (car))
17010 {
17011#ifdef HAVE_WINDOW_SYSTEM
17012 if (valid_image_p (prop))
17013 {
17014 int id = lookup_image (it->f, prop);
17015 struct image *img = IMAGE_FROM_ID (it->f, id);
17016
17017 return OK_PIXELS (width_p ? img->width : img->height);
17018 }
17019#endif
17020 if (EQ (car, Qplus) || EQ (car, Qminus))
17021 {
17022 int first = 1;
17023 double px;
17024
17025 pixels = 0;
17026 while (CONSP (cdr))
17027 {
17028 if (!calc_pixel_width_or_height (&px, it, XCAR (cdr),
17029 font, width_p, align_to))
17030 return 0;
17031 if (first)
17032 pixels = (EQ (car, Qplus) ? px : -px), first = 0;
17033 else
17034 pixels += px;
17035 cdr = XCDR (cdr);
17036 }
17037 if (EQ (car, Qminus))
17038 pixels = -pixels;
17039 return OK_PIXELS (pixels);
17040 }
17041
17042 car = Fbuffer_local_value (car, it->w->buffer);
17043 }
17044
17045 if (INTEGERP (car) || FLOATP (car))
17046 {
17047 double fact;
17048 pixels = XFLOATINT (car);
17049 if (NILP (cdr))
17050 return OK_PIXELS (pixels);
17051 if (calc_pixel_width_or_height (&fact, it, cdr,
17052 font, width_p, align_to))
17053 return OK_PIXELS (pixels * fact);
17054 return 0;
17055 }
17056
17057 return 0;
17058 }
17059
17060 return 0;
17061}
17062
642eefc6 17063\f
133c764e
KS
17064/***********************************************************************
17065 Glyph Display
17066 ***********************************************************************/
17067
79fa9e0f
KS
17068#ifdef HAVE_WINDOW_SYSTEM
17069
133c764e
KS
17070#if GLYPH_DEBUG
17071
17072void
17073dump_glyph_string (s)
17074 struct glyph_string *s;
17075{
17076 fprintf (stderr, "glyph string\n");
17077 fprintf (stderr, " x, y, w, h = %d, %d, %d, %d\n",
17078 s->x, s->y, s->width, s->height);
17079 fprintf (stderr, " ybase = %d\n", s->ybase);
17080 fprintf (stderr, " hl = %d\n", s->hl);
17081 fprintf (stderr, " left overhang = %d, right = %d\n",
17082 s->left_overhang, s->right_overhang);
17083 fprintf (stderr, " nchars = %d\n", s->nchars);
17084 fprintf (stderr, " extends to end of line = %d\n",
17085 s->extends_to_end_of_line_p);
17086 fprintf (stderr, " font height = %d\n", FONT_HEIGHT (s->font));
17087 fprintf (stderr, " bg width = %d\n", s->background_width);
17088}
17089
17090#endif /* GLYPH_DEBUG */
17091
17092/* Initialize glyph string S. CHAR2B is a suitably allocated vector
17093 of XChar2b structures for S; it can't be allocated in
17094 init_glyph_string because it must be allocated via `alloca'. W
17095 is the window on which S is drawn. ROW and AREA are the glyph row
17096 and area within the row from which S is constructed. START is the
17097 index of the first glyph structure covered by S. HL is a
17098 face-override for drawing S. */
17099
17100#ifdef HAVE_NTGUI
17101#define OPTIONAL_HDC(hdc) hdc,
17102#define DECLARE_HDC(hdc) HDC hdc;
17103#define ALLOCATE_HDC(hdc, f) hdc = get_frame_dc ((f))
17104#define RELEASE_HDC(hdc, f) release_frame_dc ((f), (hdc))
17105#endif
17106
17107#ifndef OPTIONAL_HDC
17108#define OPTIONAL_HDC(hdc)
17109#define DECLARE_HDC(hdc)
17110#define ALLOCATE_HDC(hdc, f)
17111#define RELEASE_HDC(hdc, f)
17112#endif
17113
17114static void
17115init_glyph_string (s, OPTIONAL_HDC (hdc) char2b, w, row, area, start, hl)
17116 struct glyph_string *s;
17117 DECLARE_HDC (hdc)
17118 XChar2b *char2b;
17119 struct window *w;
17120 struct glyph_row *row;
17121 enum glyph_row_area area;
17122 int start;
17123 enum draw_glyphs_face hl;
17124{
17125 bzero (s, sizeof *s);
17126 s->w = w;
17127 s->f = XFRAME (w->frame);
17128#ifdef HAVE_NTGUI
17129 s->hdc = hdc;
17130#endif
17131 s->display = FRAME_X_DISPLAY (s->f);
17132 s->window = FRAME_X_WINDOW (s->f);
17133 s->char2b = char2b;
17134 s->hl = hl;
17135 s->row = row;
17136 s->area = area;
17137 s->first_glyph = row->glyphs[area] + start;
17138 s->height = row->height;
17139 s->y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
17140
17141 /* Display the internal border below the tool-bar window. */
17142 if (s->w == XWINDOW (s->f->tool_bar_window))
17143 s->y -= FRAME_INTERNAL_BORDER_WIDTH (s->f);
17144
17145 s->ybase = s->y + row->ascent;
17146}
17147
17148
17149/* Append the list of glyph strings with head H and tail T to the list
17150 with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the result. */
17151
17152static INLINE void
17153append_glyph_string_lists (head, tail, h, t)
17154 struct glyph_string **head, **tail;
17155 struct glyph_string *h, *t;
17156{
17157 if (h)
17158 {
17159 if (*head)
17160 (*tail)->next = h;
17161 else
17162 *head = h;
17163 h->prev = *tail;
17164 *tail = t;
17165 }
17166}
17167
17168
17169/* Prepend the list of glyph strings with head H and tail T to the
17170 list with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the
17171 result. */
17172
17173static INLINE void
17174prepend_glyph_string_lists (head, tail, h, t)
17175 struct glyph_string **head, **tail;
17176 struct glyph_string *h, *t;
17177{
17178 if (h)
17179 {
17180 if (*head)
17181 (*head)->prev = t;
17182 else
17183 *tail = t;
17184 t->next = *head;
17185 *head = h;
17186 }
17187}
17188
17189
17190/* Append glyph string S to the list with head *HEAD and tail *TAIL.
17191 Set *HEAD and *TAIL to the resulting list. */
17192
17193static INLINE void
17194append_glyph_string (head, tail, s)
17195 struct glyph_string **head, **tail;
17196 struct glyph_string *s;
17197{
17198 s->next = s->prev = NULL;
17199 append_glyph_string_lists (head, tail, s, s);
17200}
17201
17202
17203/* Get face and two-byte form of character glyph GLYPH on frame F.
17204 The encoding of GLYPH->u.ch is returned in *CHAR2B. Value is
17205 a pointer to a realized face that is ready for display. */
17206
17207static INLINE struct face *
17208get_glyph_face_and_encoding (f, glyph, char2b, two_byte_p)
17209 struct frame *f;
17210 struct glyph *glyph;
17211 XChar2b *char2b;
17212 int *two_byte_p;
17213{
17214 struct face *face;
17215
17216 xassert (glyph->type == CHAR_GLYPH);
17217 face = FACE_FROM_ID (f, glyph->face_id);
17218
17219 if (two_byte_p)
17220 *two_byte_p = 0;
17221
17222 if (!glyph->multibyte_p)
17223 {
17224 /* Unibyte case. We don't have to encode, but we have to make
17225 sure to use a face suitable for unibyte. */
17226 STORE_XCHAR2B (char2b, 0, glyph->u.ch);
17227 }
17228 else if (glyph->u.ch < 128
17229 && glyph->face_id < BASIC_FACE_ID_SENTINEL)
17230 {
17231 /* Case of ASCII in a face known to fit ASCII. */
17232 STORE_XCHAR2B (char2b, 0, glyph->u.ch);
17233 }
17234 else
17235 {
8f924df7
KH
17236 struct font_info *font_info
17237 = FONT_INFO_FROM_ID (f, face->font_info_id);
17238 if (font_info)
17239 {
17240 struct charset *charset = CHARSET_FROM_ID (font_info->charset);
17241 unsigned code = ENCODE_CHAR (charset, glyph->u.ch);
133c764e 17242
8f924df7
KH
17243 if (CHARSET_DIMENSION (charset) == 1)
17244 STORE_XCHAR2B (char2b, 0, code);
17245 else
17246 STORE_XCHAR2B (char2b, (code >> 8), (code & 0xFF));
133c764e 17247
8f924df7
KH
17248 /* Maybe encode the character in *CHAR2B. */
17249 if (CHARSET_ID (charset) != charset_ascii)
17250 {
17251 glyph->font_type
17252 = rif->encode_char (glyph->u.ch, char2b, font_info, charset,
17253 two_byte_p);
17254 }
133c764e
KS
17255 }
17256 }
17257
17258 /* Make sure X resources of the face are allocated. */
17259 xassert (face != NULL);
17260 PREPARE_FACE_FOR_DISPLAY (f, face);
17261 return face;
17262}
17263
17264
17265/* Fill glyph string S with composition components specified by S->cmp.
17266
17267 FACES is an array of faces for all components of this composition.
17268 S->gidx is the index of the first component for S.
17269 OVERLAPS_P non-zero means S should draw the foreground only, and
17270 use its physical height for clipping.
17271
17272 Value is the index of a component not in S. */
17273
17274static int
17275fill_composite_glyph_string (s, faces, overlaps_p)
17276 struct glyph_string *s;
17277 struct face **faces;
17278 int overlaps_p;
17279{
17280 int i;
17281
17282 xassert (s);
17283
17284 s->for_overlaps_p = overlaps_p;
17285
17286 s->face = faces[s->gidx];
17287 s->font = s->face->font;
17288 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
17289
17290 /* For all glyphs of this composition, starting at the offset
17291 S->gidx, until we reach the end of the definition or encounter a
17292 glyph that requires the different face, add it to S. */
17293 ++s->nchars;
17294 for (i = s->gidx + 1; i < s->cmp->glyph_len && faces[i] == s->face; ++i)
17295 ++s->nchars;
17296
17297 /* All glyph strings for the same composition has the same width,
17298 i.e. the width set for the first component of the composition. */
17299
17300 s->width = s->first_glyph->pixel_width;
17301
17302 /* If the specified font could not be loaded, use the frame's
17303 default font, but record the fact that we couldn't load it in
17304 the glyph string so that we can draw rectangles for the
17305 characters of the glyph string. */
17306 if (s->font == NULL)
17307 {
17308 s->font_not_found_p = 1;
17309 s->font = FRAME_FONT (s->f);
17310 }
17311
17312 /* Adjust base line for subscript/superscript text. */
17313 s->ybase += s->first_glyph->voffset;
17314
17315 xassert (s->face && s->face->gc);
17316
17317 /* This glyph string must always be drawn with 16-bit functions. */
17318 s->two_byte_p = 1;
17319
17320 return s->gidx + s->nchars;
17321}
17322
17323
17324/* Fill glyph string S from a sequence of character glyphs.
17325
17326 FACE_ID is the face id of the string. START is the index of the
17327 first glyph to consider, END is the index of the last + 1.
17328 OVERLAPS_P non-zero means S should draw the foreground only, and
17329 use its physical height for clipping.
17330
17331 Value is the index of the first glyph not in S. */
17332
17333static int
17334fill_glyph_string (s, face_id, start, end, overlaps_p)
17335 struct glyph_string *s;
17336 int face_id;
17337 int start, end, overlaps_p;
17338{
17339 struct glyph *glyph, *last;
17340 int voffset;
17341 int glyph_not_available_p;
17342
17343 xassert (s->f == XFRAME (s->w->frame));
17344 xassert (s->nchars == 0);
17345 xassert (start >= 0 && end > start);
17346
17347 s->for_overlaps_p = overlaps_p,
17348 glyph = s->row->glyphs[s->area] + start;
17349 last = s->row->glyphs[s->area] + end;
17350 voffset = glyph->voffset;
17351
17352 glyph_not_available_p = glyph->glyph_not_available_p;
17353
17354 while (glyph < last
17355 && glyph->type == CHAR_GLYPH
17356 && glyph->voffset == voffset
17357 /* Same face id implies same font, nowadays. */
17358 && glyph->face_id == face_id
17359 && glyph->glyph_not_available_p == glyph_not_available_p)
17360 {
17361 int two_byte_p;
17362
17363 s->face = get_glyph_face_and_encoding (s->f, glyph,
17364 s->char2b + s->nchars,
17365 &two_byte_p);
17366 s->two_byte_p = two_byte_p;
17367 ++s->nchars;
17368 xassert (s->nchars <= end - start);
17369 s->width += glyph->pixel_width;
17370 ++glyph;
17371 }
17372
17373 s->font = s->face->font;
17374 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
17375
17376 /* If the specified font could not be loaded, use the frame's font,
17377 but record the fact that we couldn't load it in
17378 S->font_not_found_p so that we can draw rectangles for the
17379 characters of the glyph string. */
17380 if (s->font == NULL || glyph_not_available_p)
17381 {
17382 s->font_not_found_p = 1;
17383 s->font = FRAME_FONT (s->f);
17384 }
17385
17386 /* Adjust base line for subscript/superscript text. */
17387 s->ybase += voffset;
17388
17389 xassert (s->face && s->face->gc);
17390 return glyph - s->row->glyphs[s->area];
17391}
17392
17393
17394/* Fill glyph string S from image glyph S->first_glyph. */
17395
17396static void
17397fill_image_glyph_string (s)
17398 struct glyph_string *s;
17399{
17400 xassert (s->first_glyph->type == IMAGE_GLYPH);
17401 s->img = IMAGE_FROM_ID (s->f, s->first_glyph->u.img_id);
17402 xassert (s->img);
17403 s->face = FACE_FROM_ID (s->f, s->first_glyph->face_id);
17404 s->font = s->face->font;
17405 s->width = s->first_glyph->pixel_width;
17406
17407 /* Adjust base line for subscript/superscript text. */
17408 s->ybase += s->first_glyph->voffset;
17409}
17410
17411
17412/* Fill glyph string S from a sequence of stretch glyphs.
17413
17414 ROW is the glyph row in which the glyphs are found, AREA is the
17415 area within the row. START is the index of the first glyph to
17416 consider, END is the index of the last + 1.
17417
17418 Value is the index of the first glyph not in S. */
17419
17420static int
17421fill_stretch_glyph_string (s, row, area, start, end)
17422 struct glyph_string *s;
17423 struct glyph_row *row;
17424 enum glyph_row_area area;
17425 int start, end;
17426{
17427 struct glyph *glyph, *last;
17428 int voffset, face_id;
17429
17430 xassert (s->first_glyph->type == STRETCH_GLYPH);
17431
17432 glyph = s->row->glyphs[s->area] + start;
17433 last = s->row->glyphs[s->area] + end;
17434 face_id = glyph->face_id;
17435 s->face = FACE_FROM_ID (s->f, face_id);
17436 s->font = s->face->font;
17437 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
17438 s->width = glyph->pixel_width;
17439 voffset = glyph->voffset;
17440
17441 for (++glyph;
17442 (glyph < last
17443 && glyph->type == STRETCH_GLYPH
17444 && glyph->voffset == voffset
17445 && glyph->face_id == face_id);
17446 ++glyph)
17447 s->width += glyph->pixel_width;
17448
17449 /* Adjust base line for subscript/superscript text. */
17450 s->ybase += voffset;
17451
17452 /* The case that face->gc == 0 is handled when drawing the glyph
17453 string by calling PREPARE_FACE_FOR_DISPLAY. */
17454 xassert (s->face);
17455 return glyph - s->row->glyphs[s->area];
17456}
17457
17458
17459/* EXPORT for RIF:
17460 Set *LEFT and *RIGHT to the left and right overhang of GLYPH on
17461 frame F. Overhangs of glyphs other than type CHAR_GLYPH are
17462 assumed to be zero. */
17463
17464void
17465x_get_glyph_overhangs (glyph, f, left, right)
17466 struct glyph *glyph;
17467 struct frame *f;
17468 int *left, *right;
17469{
17470 *left = *right = 0;
17471
17472 if (glyph->type == CHAR_GLYPH)
17473 {
17474 XFontStruct *font;
17475 struct face *face;
17476 struct font_info *font_info;
17477 XChar2b char2b;
17478 XCharStruct *pcm;
17479
17480 face = get_glyph_face_and_encoding (f, glyph, &char2b, NULL);
17481 font = face->font;
17482 font_info = FONT_INFO_FROM_ID (f, face->font_info_id);
17483 if (font /* ++KFS: Should this be font_info ? */
17484 && (pcm = rif->per_char_metric (font, &char2b, glyph->font_type)))
17485 {
17486 if (pcm->rbearing > pcm->width)
17487 *right = pcm->rbearing - pcm->width;
17488 if (pcm->lbearing < 0)
17489 *left = -pcm->lbearing;
17490 }
17491 }
993651d1
KH
17492 else if (glyph->type == COMPOSITE_GLYPH)
17493 {
17494 struct composition *cmp = composition_table[glyph->u.cmp_id];
17495
17496 *right = cmp->rbearing - cmp->pixel_width;
17497 *left = - cmp->lbearing;
17498 }
133c764e
KS
17499}
17500
17501
17502/* Return the index of the first glyph preceding glyph string S that
17503 is overwritten by S because of S's left overhang. Value is -1
17504 if no glyphs are overwritten. */
17505
17506static int
17507left_overwritten (s)
17508 struct glyph_string *s;
17509{
17510 int k;
17511
17512 if (s->left_overhang)
17513 {
17514 int x = 0, i;
17515 struct glyph *glyphs = s->row->glyphs[s->area];
17516 int first = s->first_glyph - glyphs;
17517
17518 for (i = first - 1; i >= 0 && x > -s->left_overhang; --i)
17519 x -= glyphs[i].pixel_width;
17520
17521 k = i + 1;
17522 }
17523 else
17524 k = -1;
17525
17526 return k;
17527}
17528
17529
17530/* Return the index of the first glyph preceding glyph string S that
17531 is overwriting S because of its right overhang. Value is -1 if no
17532 glyph in front of S overwrites S. */
17533
17534static int
17535left_overwriting (s)
17536 struct glyph_string *s;
17537{
17538 int i, k, x;
17539 struct glyph *glyphs = s->row->glyphs[s->area];
17540 int first = s->first_glyph - glyphs;
17541
17542 k = -1;
17543 x = 0;
17544 for (i = first - 1; i >= 0; --i)
17545 {
17546 int left, right;
17547 x_get_glyph_overhangs (glyphs + i, s->f, &left, &right);
17548 if (x + right > 0)
17549 k = i;
17550 x -= glyphs[i].pixel_width;
17551 }
17552
17553 return k;
17554}
17555
17556
17557/* Return the index of the last glyph following glyph string S that is
17558 not overwritten by S because of S's right overhang. Value is -1 if
17559 no such glyph is found. */
17560
17561static int
17562right_overwritten (s)
17563 struct glyph_string *s;
17564{
17565 int k = -1;
17566
17567 if (s->right_overhang)
17568 {
17569 int x = 0, i;
17570 struct glyph *glyphs = s->row->glyphs[s->area];
17571 int first = (s->first_glyph - glyphs) + (s->cmp ? 1 : s->nchars);
17572 int end = s->row->used[s->area];
17573
17574 for (i = first; i < end && s->right_overhang > x; ++i)
17575 x += glyphs[i].pixel_width;
17576
17577 k = i;
17578 }
17579
17580 return k;
17581}
17582
17583
17584/* Return the index of the last glyph following glyph string S that
17585 overwrites S because of its left overhang. Value is negative
17586 if no such glyph is found. */
17587
17588static int
17589right_overwriting (s)
17590 struct glyph_string *s;
17591{
17592 int i, k, x;
17593 int end = s->row->used[s->area];
17594 struct glyph *glyphs = s->row->glyphs[s->area];
17595 int first = (s->first_glyph - glyphs) + (s->cmp ? 1 : s->nchars);
17596
17597 k = -1;
17598 x = 0;
17599 for (i = first; i < end; ++i)
17600 {
17601 int left, right;
17602 x_get_glyph_overhangs (glyphs + i, s->f, &left, &right);
17603 if (x - left < 0)
17604 k = i;
17605 x += glyphs[i].pixel_width;
17606 }
17607
17608 return k;
17609}
17610
17611
17612/* Get face and two-byte form of character C in face FACE_ID on frame
17613 F. The encoding of C is returned in *CHAR2B. MULTIBYTE_P non-zero
17614 means we want to display multibyte text. DISPLAY_P non-zero means
17615 make sure that X resources for the face returned are allocated.
17616 Value is a pointer to a realized face that is ready for display if
17617 DISPLAY_P is non-zero. */
17618
17619static INLINE struct face *
17620get_char_face_and_encoding (f, c, face_id, char2b, multibyte_p, display_p)
17621 struct frame *f;
17622 int c, face_id;
17623 XChar2b *char2b;
17624 int multibyte_p, display_p;
17625{
17626 struct face *face = FACE_FROM_ID (f, face_id);
17627
17628 if (!multibyte_p)
17629 {
17630 /* Unibyte case. We don't have to encode, but we have to make
17631 sure to use a face suitable for unibyte. */
17632 STORE_XCHAR2B (char2b, 0, c);
f46a4dc1 17633 face_id = FACE_FOR_CHAR (f, face, c, -1, Qnil);
133c764e
KS
17634 face = FACE_FROM_ID (f, face_id);
17635 }
17636 else if (c < 128 && face_id < BASIC_FACE_ID_SENTINEL)
17637 {
17638 /* Case of ASCII in a face known to fit ASCII. */
17639 STORE_XCHAR2B (char2b, 0, c);
17640 }
8f924df7 17641 else if (face->font != NULL)
133c764e 17642 {
8f924df7
KH
17643 struct font_info *font_info
17644 = FONT_INFO_FROM_ID (f, face->font_info_id);
17645 struct charset *charset = CHARSET_FROM_ID (font_info->charset);
17646 unsigned code = ENCODE_CHAR (charset, c);
133c764e 17647
8f924df7
KH
17648 if (CHARSET_DIMENSION (charset) == 1)
17649 STORE_XCHAR2B (char2b, 0, code);
133c764e 17650 else
8f924df7
KH
17651 STORE_XCHAR2B (char2b, (code >> 8), (code & 0xFF));
17652 /* Maybe encode the character in *CHAR2B. */
17653 rif->encode_char (c, char2b, font_info, charset, NULL);
133c764e
KS
17654 }
17655
17656 /* Make sure X resources of the face are allocated. */
17657#ifdef HAVE_X_WINDOWS
17658 if (display_p)
17659#endif
17660 {
17661 xassert (face != NULL);
17662 PREPARE_FACE_FOR_DISPLAY (f, face);
17663 }
17664
17665 return face;
17666}
17667
17668
17669/* Set background width of glyph string S. START is the index of the
17670 first glyph following S. LAST_X is the right-most x-position + 1
17671 in the drawing area. */
17672
17673static INLINE void
17674set_glyph_string_background_width (s, start, last_x)
17675 struct glyph_string *s;
17676 int start;
17677 int last_x;
17678{
17679 /* If the face of this glyph string has to be drawn to the end of
17680 the drawing area, set S->extends_to_end_of_line_p. */
17681 struct face *default_face = FACE_FROM_ID (s->f, DEFAULT_FACE_ID);
17682
17683 if (start == s->row->used[s->area]
17684 && s->area == TEXT_AREA
17685 && ((s->hl == DRAW_NORMAL_TEXT
17686 && (s->row->fill_line_p
17687 || s->face->background != default_face->background
17688 || s->face->stipple != default_face->stipple
17689 || s->row->mouse_face_p))
17690 || s->hl == DRAW_MOUSE_FACE
17691 || ((s->hl == DRAW_IMAGE_RAISED || s->hl == DRAW_IMAGE_SUNKEN)
17692 && s->row->fill_line_p)))
17693 s->extends_to_end_of_line_p = 1;
17694
17695 /* If S extends its face to the end of the line, set its
17696 background_width to the distance to the right edge of the drawing
17697 area. */
17698 if (s->extends_to_end_of_line_p)
17699 s->background_width = last_x - s->x + 1;
17700 else
17701 s->background_width = s->width;
17702}
17703
17704
17705/* Compute overhangs and x-positions for glyph string S and its
17706 predecessors, or successors. X is the starting x-position for S.
17707 BACKWARD_P non-zero means process predecessors. */
17708
17709static void
17710compute_overhangs_and_x (s, x, backward_p)
17711 struct glyph_string *s;
17712 int x;
17713 int backward_p;
17714{
17715 if (backward_p)
17716 {
17717 while (s)
17718 {
17719 if (rif->compute_glyph_string_overhangs)
17720 rif->compute_glyph_string_overhangs (s);
17721 x -= s->width;
17722 s->x = x;
17723 s = s->prev;
17724 }
17725 }
17726 else
17727 {
17728 while (s)
17729 {
17730 if (rif->compute_glyph_string_overhangs)
17731 rif->compute_glyph_string_overhangs (s);
17732 s->x = x;
17733 x += s->width;
17734 s = s->next;
17735 }
17736 }
17737}
17738
17739
17740
fa3c6b4d 17741/* The following macros are only called from draw_glyphs below.
133c764e
KS
17742 They reference the following parameters of that function directly:
17743 `w', `row', `area', and `overlap_p'
17744 as well as the following local variables:
17745 `s', `f', and `hdc' (in W32) */
17746
17747#ifdef HAVE_NTGUI
17748/* On W32, silently add local `hdc' variable to argument list of
17749 init_glyph_string. */
17750#define INIT_GLYPH_STRING(s, char2b, w, row, area, start, hl) \
17751 init_glyph_string (s, hdc, char2b, w, row, area, start, hl)
17752#else
17753#define INIT_GLYPH_STRING(s, char2b, w, row, area, start, hl) \
17754 init_glyph_string (s, char2b, w, row, area, start, hl)
17755#endif
17756
17757/* Add a glyph string for a stretch glyph to the list of strings
17758 between HEAD and TAIL. START is the index of the stretch glyph in
17759 row area AREA of glyph row ROW. END is the index of the last glyph
17760 in that glyph row area. X is the current output position assigned
17761 to the new glyph string constructed. HL overrides that face of the
17762 glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X
17763 is the right-most x-position of the drawing area. */
17764
17765/* SunOS 4 bundled cc, barfed on continuations in the arg lists here
17766 and below -- keep them on one line. */
17767#define BUILD_STRETCH_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \
17768 do \
17769 { \
17770 s = (struct glyph_string *) alloca (sizeof *s); \
17771 INIT_GLYPH_STRING (s, NULL, w, row, area, START, HL); \
17772 START = fill_stretch_glyph_string (s, row, area, START, END); \
17773 append_glyph_string (&HEAD, &TAIL, s); \
17774 s->x = (X); \
17775 } \
17776 while (0)
17777
17778
17779/* Add a glyph string for an image glyph to the list of strings
17780 between HEAD and TAIL. START is the index of the image glyph in
17781 row area AREA of glyph row ROW. END is the index of the last glyph
17782 in that glyph row area. X is the current output position assigned
17783 to the new glyph string constructed. HL overrides that face of the
17784 glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X
17785 is the right-most x-position of the drawing area. */
17786
17787#define BUILD_IMAGE_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \
17788 do \
17789 { \
17790 s = (struct glyph_string *) alloca (sizeof *s); \
17791 INIT_GLYPH_STRING (s, NULL, w, row, area, START, HL); \
17792 fill_image_glyph_string (s); \
17793 append_glyph_string (&HEAD, &TAIL, s); \
17794 ++START; \
17795 s->x = (X); \
17796 } \
17797 while (0)
17798
17799
17800/* Add a glyph string for a sequence of character glyphs to the list
17801 of strings between HEAD and TAIL. START is the index of the first
17802 glyph in row area AREA of glyph row ROW that is part of the new
17803 glyph string. END is the index of the last glyph in that glyph row
17804 area. X is the current output position assigned to the new glyph
17805 string constructed. HL overrides that face of the glyph; e.g. it
17806 is DRAW_CURSOR if a cursor has to be drawn. LAST_X is the
17807 right-most x-position of the drawing area. */
17808
17809#define BUILD_CHAR_GLYPH_STRINGS(START, END, HEAD, TAIL, HL, X, LAST_X) \
17810 do \
17811 { \
cbb6a48a 17812 int face_id; \
133c764e
KS
17813 XChar2b *char2b; \
17814 \
133c764e
KS
17815 face_id = (row)->glyphs[area][START].face_id; \
17816 \
17817 s = (struct glyph_string *) alloca (sizeof *s); \
17818 char2b = (XChar2b *) alloca ((END - START) * sizeof *char2b); \
17819 INIT_GLYPH_STRING (s, char2b, w, row, area, START, HL); \
17820 append_glyph_string (&HEAD, &TAIL, s); \
17821 s->x = (X); \
17822 START = fill_glyph_string (s, face_id, START, END, overlaps_p); \
17823 } \
17824 while (0)
17825
17826
17827/* Add a glyph string for a composite sequence to the list of strings
17828 between HEAD and TAIL. START is the index of the first glyph in
17829 row area AREA of glyph row ROW that is part of the new glyph
17830 string. END is the index of the last glyph in that glyph row area.
17831 X is the current output position assigned to the new glyph string
17832 constructed. HL overrides that face of the glyph; e.g. it is
17833 DRAW_CURSOR if a cursor has to be drawn. LAST_X is the right-most
17834 x-position of the drawing area. */
17835
17836#define BUILD_COMPOSITE_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \
17837 do { \
17838 int cmp_id = (row)->glyphs[area][START].u.cmp_id; \
17839 int face_id = (row)->glyphs[area][START].face_id; \
17840 struct face *base_face = FACE_FROM_ID (f, face_id); \
17841 struct composition *cmp = composition_table[cmp_id]; \
17842 int glyph_len = cmp->glyph_len; \
17843 XChar2b *char2b; \
17844 struct face **faces; \
17845 struct glyph_string *first_s = NULL; \
17846 int n; \
17847 \
17848 base_face = base_face->ascii_face; \
17849 char2b = (XChar2b *) alloca ((sizeof *char2b) * glyph_len); \
17850 faces = (struct face **) alloca ((sizeof *faces) * glyph_len); \
17851 /* At first, fill in `char2b' and `faces'. */ \
17852 for (n = 0; n < glyph_len; n++) \
17853 { \
17854 int c = COMPOSITION_GLYPH (cmp, n); \
f46a4dc1 17855 int this_face_id = FACE_FOR_CHAR (f, base_face, c, -1, Qnil); \
133c764e
KS
17856 faces[n] = FACE_FROM_ID (f, this_face_id); \
17857 get_char_face_and_encoding (f, c, this_face_id, \
17858 char2b + n, 1, 1); \
17859 } \
17860 \
17861 /* Make glyph_strings for each glyph sequence that is drawable by \
17862 the same face, and append them to HEAD/TAIL. */ \
17863 for (n = 0; n < cmp->glyph_len;) \
17864 { \
17865 s = (struct glyph_string *) alloca (sizeof *s); \
17866 INIT_GLYPH_STRING (s, char2b + n, w, row, area, START, HL); \
17867 append_glyph_string (&(HEAD), &(TAIL), s); \
17868 s->cmp = cmp; \
17869 s->gidx = n; \
17870 s->x = (X); \
17871 \
17872 if (n == 0) \
17873 first_s = s; \
17874 \
17875 n = fill_composite_glyph_string (s, faces, overlaps_p); \
17876 } \
17877 \
17878 ++START; \
17879 s = first_s; \
17880 } while (0)
17881
17882
17883/* Build a list of glyph strings between HEAD and TAIL for the glyphs
17884 of AREA of glyph row ROW on window W between indices START and END.
17885 HL overrides the face for drawing glyph strings, e.g. it is
17886 DRAW_CURSOR to draw a cursor. X and LAST_X are start and end
17887 x-positions of the drawing area.
17888
17889 This is an ugly monster macro construct because we must use alloca
fa3c6b4d 17890 to allocate glyph strings (because draw_glyphs can be called
133c764e
KS
17891 asynchronously). */
17892
17893#define BUILD_GLYPH_STRINGS(START, END, HEAD, TAIL, HL, X, LAST_X) \
17894 do \
17895 { \
17896 HEAD = TAIL = NULL; \
17897 while (START < END) \
17898 { \
17899 struct glyph *first_glyph = (row)->glyphs[area] + START; \
17900 switch (first_glyph->type) \
17901 { \
17902 case CHAR_GLYPH: \
17903 BUILD_CHAR_GLYPH_STRINGS (START, END, HEAD, TAIL, \
17904 HL, X, LAST_X); \
17905 break; \
17906 \
17907 case COMPOSITE_GLYPH: \
17908 BUILD_COMPOSITE_GLYPH_STRING (START, END, HEAD, TAIL, \
17909 HL, X, LAST_X); \
17910 break; \
17911 \
17912 case STRETCH_GLYPH: \
17913 BUILD_STRETCH_GLYPH_STRING (START, END, HEAD, TAIL, \
17914 HL, X, LAST_X); \
17915 break; \
17916 \
17917 case IMAGE_GLYPH: \
17918 BUILD_IMAGE_GLYPH_STRING (START, END, HEAD, TAIL, \
17919 HL, X, LAST_X); \
17920 break; \
17921 \
17922 default: \
17923 abort (); \
17924 } \
17925 \
17926 set_glyph_string_background_width (s, START, LAST_X); \
17927 (X) += s->width; \
17928 } \
17929 } \
17930 while (0)
17931
17932
17933/* Draw glyphs between START and END in AREA of ROW on window W,
17934 starting at x-position X. X is relative to AREA in W. HL is a
17935 face-override with the following meaning:
17936
17937 DRAW_NORMAL_TEXT draw normally
17938 DRAW_CURSOR draw in cursor face
17939 DRAW_MOUSE_FACE draw in mouse face.
17940 DRAW_INVERSE_VIDEO draw in mode line face
17941 DRAW_IMAGE_SUNKEN draw an image with a sunken relief around it
17942 DRAW_IMAGE_RAISED draw an image with a raised relief around it
17943
17944 If OVERLAPS_P is non-zero, draw only the foreground of characters
17945 and clip to the physical height of ROW.
17946
17947 Value is the x-position reached, relative to AREA of W. */
17948
fa3c6b4d
KS
17949static int
17950draw_glyphs (w, x, row, area, start, end, hl, overlaps_p)
133c764e
KS
17951 struct window *w;
17952 int x;
17953 struct glyph_row *row;
17954 enum glyph_row_area area;
cbb6a48a 17955 EMACS_INT start, end;
133c764e
KS
17956 enum draw_glyphs_face hl;
17957 int overlaps_p;
17958{
17959 struct glyph_string *head, *tail;
17960 struct glyph_string *s;
17961 int last_x, area_width;
17962 int x_reached;
17963 int i, j;
17964 struct frame *f = XFRAME (WINDOW_FRAME (w));
17965 DECLARE_HDC (hdc);
17966
17967 ALLOCATE_HDC (hdc, f);
17968
17969 /* Let's rather be paranoid than getting a SEGV. */
17970 end = min (end, row->used[area]);
17971 start = max (0, start);
17972 start = min (end, start);
17973
17974 /* Translate X to frame coordinates. Set last_x to the right
17975 end of the drawing area. */
17976 if (row->full_width_p)
17977 {
17978 /* X is relative to the left edge of W, without scroll bars
17979 or fringes. */
da8b7f4f
KS
17980 x += WINDOW_LEFT_EDGE_X (w);
17981 last_x = WINDOW_LEFT_EDGE_X (w) + WINDOW_TOTAL_WIDTH (w);
133c764e
KS
17982 }
17983 else
17984 {
da8b7f4f
KS
17985 int area_left = window_box_left (w, area);
17986 x += area_left;
133c764e 17987 area_width = window_box_width (w, area);
da8b7f4f 17988 last_x = area_left + area_width;
133c764e
KS
17989 }
17990
17991 /* Build a doubly-linked list of glyph_string structures between
17992 head and tail from what we have to draw. Note that the macro
17993 BUILD_GLYPH_STRINGS will modify its start parameter. That's
17994 the reason we use a separate variable `i'. */
17995 i = start;
17996 BUILD_GLYPH_STRINGS (i, end, head, tail, hl, x, last_x);
17997 if (tail)
17998 x_reached = tail->x + tail->background_width;
17999 else
18000 x_reached = x;
18001
18002 /* If there are any glyphs with lbearing < 0 or rbearing > width in
18003 the row, redraw some glyphs in front or following the glyph
18004 strings built above. */
18005 if (head && !overlaps_p && row->contains_overlapping_glyphs_p)
18006 {
18007 int dummy_x = 0;
18008 struct glyph_string *h, *t;
18009
18010 /* Compute overhangs for all glyph strings. */
18011 if (rif->compute_glyph_string_overhangs)
18012 for (s = head; s; s = s->next)
18013 rif->compute_glyph_string_overhangs (s);
18014
18015 /* Prepend glyph strings for glyphs in front of the first glyph
18016 string that are overwritten because of the first glyph
18017 string's left overhang. The background of all strings
18018 prepended must be drawn because the first glyph string
18019 draws over it. */
18020 i = left_overwritten (head);
18021 if (i >= 0)
18022 {
18023 j = i;
18024 BUILD_GLYPH_STRINGS (j, start, h, t,
18025 DRAW_NORMAL_TEXT, dummy_x, last_x);
18026 start = i;
18027 compute_overhangs_and_x (t, head->x, 1);
18028 prepend_glyph_string_lists (&head, &tail, h, t);
18029 }
18030
18031 /* Prepend glyph strings for glyphs in front of the first glyph
18032 string that overwrite that glyph string because of their
18033 right overhang. For these strings, only the foreground must
18034 be drawn, because it draws over the glyph string at `head'.
18035 The background must not be drawn because this would overwrite
18036 right overhangs of preceding glyphs for which no glyph
18037 strings exist. */
18038 i = left_overwriting (head);
18039 if (i >= 0)
18040 {
18041 BUILD_GLYPH_STRINGS (i, start, h, t,
18042 DRAW_NORMAL_TEXT, dummy_x, last_x);
18043 for (s = h; s; s = s->next)
18044 s->background_filled_p = 1;
18045 compute_overhangs_and_x (t, head->x, 1);
18046 prepend_glyph_string_lists (&head, &tail, h, t);
18047 }
18048
18049 /* Append glyphs strings for glyphs following the last glyph
18050 string tail that are overwritten by tail. The background of
18051 these strings has to be drawn because tail's foreground draws
18052 over it. */
18053 i = right_overwritten (tail);
18054 if (i >= 0)
18055 {
18056 BUILD_GLYPH_STRINGS (end, i, h, t,
18057 DRAW_NORMAL_TEXT, x, last_x);
18058 compute_overhangs_and_x (h, tail->x + tail->width, 0);
18059 append_glyph_string_lists (&head, &tail, h, t);
18060 }
18061
18062 /* Append glyph strings for glyphs following the last glyph
18063 string tail that overwrite tail. The foreground of such
18064 glyphs has to be drawn because it writes into the background
18065 of tail. The background must not be drawn because it could
18066 paint over the foreground of following glyphs. */
18067 i = right_overwriting (tail);
18068 if (i >= 0)
18069 {
18070 BUILD_GLYPH_STRINGS (end, i, h, t,
18071 DRAW_NORMAL_TEXT, x, last_x);
18072 for (s = h; s; s = s->next)
18073 s->background_filled_p = 1;
18074 compute_overhangs_and_x (h, tail->x + tail->width, 0);
18075 append_glyph_string_lists (&head, &tail, h, t);
18076 }
18077 }
18078
18079 /* Draw all strings. */
18080 for (s = head; s; s = s->next)
18081 rif->draw_glyph_string (s);
18082
18083 if (area == TEXT_AREA
18084 && !row->full_width_p
18085 /* When drawing overlapping rows, only the glyph strings'
18086 foreground is drawn, which doesn't erase a cursor
18087 completely. */
18088 && !overlaps_p)
18089 {
18090 int x0 = head ? head->x : x;
18091 int x1 = tail ? tail->x + tail->background_width : x;
18092
da8b7f4f
KS
18093 int text_left = window_box_left (w, TEXT_AREA);
18094 x0 -= text_left;
18095 x1 -= text_left;
133c764e 18096
da8b7f4f 18097 notice_overwritten_cursor (w, TEXT_AREA, x0, x1,
133c764e
KS
18098 row->y, MATRIX_ROW_BOTTOM_Y (row));
18099 }
18100
18101 /* Value is the x-position up to which drawn, relative to AREA of W.
18102 This doesn't include parts drawn because of overhangs. */
da8b7f4f
KS
18103 if (row->full_width_p)
18104 x_reached = FRAME_TO_WINDOW_PIXEL_X (w, x_reached);
18105 else
18106 x_reached -= window_box_left (w, area);
133c764e
KS
18107
18108 RELEASE_HDC (hdc, f);
18109
18110 return x_reached;
18111}
18112
18113
18114/* Store one glyph for IT->char_to_display in IT->glyph_row.
18115 Called from x_produce_glyphs when IT->glyph_row is non-null. */
18116
18117static INLINE void
18118append_glyph (it)
18119 struct it *it;
18120{
18121 struct glyph *glyph;
18122 enum glyph_row_area area = it->area;
18123
18124 xassert (it->glyph_row);
18125 xassert (it->char_to_display != '\n' && it->char_to_display != '\t');
18126
18127 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
18128 if (glyph < it->glyph_row->glyphs[area + 1])
18129 {
18130 glyph->charpos = CHARPOS (it->position);
18131 glyph->object = it->object;
18132 glyph->pixel_width = it->pixel_width;
6b61353c
KH
18133 glyph->ascent = it->ascent;
18134 glyph->descent = it->descent;
133c764e
KS
18135 glyph->voffset = it->voffset;
18136 glyph->type = CHAR_GLYPH;
18137 glyph->multibyte_p = it->multibyte_p;
18138 glyph->left_box_line_p = it->start_of_box_run_p;
18139 glyph->right_box_line_p = it->end_of_box_run_p;
18140 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
18141 || it->phys_descent > it->descent);
18142 glyph->padding_p = 0;
18143 glyph->glyph_not_available_p = it->glyph_not_available_p;
18144 glyph->face_id = it->face_id;
18145 glyph->u.ch = it->char_to_display;
18146 glyph->font_type = FONT_TYPE_UNKNOWN;
18147 ++it->glyph_row->used[area];
18148 }
18149}
18150
18151/* Store one glyph for the composition IT->cmp_id in IT->glyph_row.
18152 Called from x_produce_glyphs when IT->glyph_row is non-null. */
18153
18154static INLINE void
18155append_composite_glyph (it)
18156 struct it *it;
18157{
18158 struct glyph *glyph;
18159 enum glyph_row_area area = it->area;
18160
18161 xassert (it->glyph_row);
18162
18163 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
18164 if (glyph < it->glyph_row->glyphs[area + 1])
18165 {
18166 glyph->charpos = CHARPOS (it->position);
18167 glyph->object = it->object;
18168 glyph->pixel_width = it->pixel_width;
6b61353c
KH
18169 glyph->ascent = it->ascent;
18170 glyph->descent = it->descent;
133c764e
KS
18171 glyph->voffset = it->voffset;
18172 glyph->type = COMPOSITE_GLYPH;
18173 glyph->multibyte_p = it->multibyte_p;
18174 glyph->left_box_line_p = it->start_of_box_run_p;
18175 glyph->right_box_line_p = it->end_of_box_run_p;
18176 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
18177 || it->phys_descent > it->descent);
18178 glyph->padding_p = 0;
18179 glyph->glyph_not_available_p = 0;
18180 glyph->face_id = it->face_id;
18181 glyph->u.cmp_id = it->cmp_id;
18182 glyph->font_type = FONT_TYPE_UNKNOWN;
18183 ++it->glyph_row->used[area];
18184 }
18185}
18186
18187
18188/* Change IT->ascent and IT->height according to the setting of
18189 IT->voffset. */
18190
18191static INLINE void
18192take_vertical_position_into_account (it)
18193 struct it *it;
18194{
18195 if (it->voffset)
18196 {
18197 if (it->voffset < 0)
18198 /* Increase the ascent so that we can display the text higher
18199 in the line. */
18200 it->ascent += abs (it->voffset);
18201 else
18202 /* Increase the descent so that we can display the text lower
18203 in the line. */
18204 it->descent += it->voffset;
18205 }
18206}
18207
18208
18209/* Produce glyphs/get display metrics for the image IT is loaded with.
18210 See the description of struct display_iterator in dispextern.h for
18211 an overview of struct display_iterator. */
18212
18213static void
18214produce_image_glyph (it)
18215 struct it *it;
18216{
18217 struct image *img;
18218 struct face *face;
6b61353c 18219 int face_ascent, glyph_ascent;
133c764e
KS
18220
18221 xassert (it->what == IT_IMAGE);
18222
18223 face = FACE_FROM_ID (it->f, it->face_id);
6b61353c
KH
18224 xassert (face);
18225 /* Make sure X resources of the face is loaded. */
18226 PREPARE_FACE_FOR_DISPLAY (it->f, face);
18227
18228 if (it->image_id < 0)
18229 {
18230 /* Fringe bitmap. */
18231 it->ascent = it->phys_ascent = 0;
18232 it->descent = it->phys_descent = 0;
18233 it->pixel_width = 0;
18234 it->nglyphs = 0;
18235 return;
18236 }
18237
133c764e
KS
18238 img = IMAGE_FROM_ID (it->f, it->image_id);
18239 xassert (img);
6b61353c 18240 /* Make sure X resources of the image is loaded. */
133c764e
KS
18241 prepare_image_for_display (it->f, img);
18242
6b61353c 18243 it->ascent = it->phys_ascent = glyph_ascent = image_ascent (img, face);
133c764e
KS
18244 it->descent = it->phys_descent = img->height + 2 * img->vmargin - it->ascent;
18245 it->pixel_width = img->width + 2 * img->hmargin;
18246
6b61353c
KH
18247 /* It's quite possible for images to have an ascent greater than
18248 their height, so don't get confused in that case. */
18249 if (it->descent < 0)
18250 it->descent = 0;
18251
18252 /* If this glyph is alone on the last line, adjust it.ascent to minimum row ascent. */
18253 face_ascent = face->font ? FONT_BASE (face->font) : FRAME_BASELINE_OFFSET (it->f);
18254 if (face_ascent > it->ascent)
18255 it->ascent = it->phys_ascent = face_ascent;
18256
133c764e
KS
18257 it->nglyphs = 1;
18258
18259 if (face->box != FACE_NO_BOX)
18260 {
18261 if (face->box_line_width > 0)
18262 {
18263 it->ascent += face->box_line_width;
18264 it->descent += face->box_line_width;
18265 }
18266
18267 if (it->start_of_box_run_p)
18268 it->pixel_width += abs (face->box_line_width);
18269 if (it->end_of_box_run_p)
18270 it->pixel_width += abs (face->box_line_width);
18271 }
18272
18273 take_vertical_position_into_account (it);
18274
18275 if (it->glyph_row)
18276 {
18277 struct glyph *glyph;
18278 enum glyph_row_area area = it->area;
18279
18280 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
18281 if (glyph < it->glyph_row->glyphs[area + 1])
18282 {
18283 glyph->charpos = CHARPOS (it->position);
18284 glyph->object = it->object;
18285 glyph->pixel_width = it->pixel_width;
6b61353c
KH
18286 glyph->ascent = glyph_ascent;
18287 glyph->descent = it->descent;
133c764e
KS
18288 glyph->voffset = it->voffset;
18289 glyph->type = IMAGE_GLYPH;
18290 glyph->multibyte_p = it->multibyte_p;
18291 glyph->left_box_line_p = it->start_of_box_run_p;
18292 glyph->right_box_line_p = it->end_of_box_run_p;
18293 glyph->overlaps_vertically_p = 0;
18294 glyph->padding_p = 0;
18295 glyph->glyph_not_available_p = 0;
18296 glyph->face_id = it->face_id;
18297 glyph->u.img_id = img->id;
18298 glyph->font_type = FONT_TYPE_UNKNOWN;
18299 ++it->glyph_row->used[area];
18300 }
18301 }
18302}
18303
18304
18305/* Append a stretch glyph to IT->glyph_row. OBJECT is the source
18306 of the glyph, WIDTH and HEIGHT are the width and height of the
6b61353c 18307 stretch. ASCENT is the ascent of the glyph (0 <= ASCENT <= HEIGHT). */
133c764e
KS
18308
18309static void
18310append_stretch_glyph (it, object, width, height, ascent)
18311 struct it *it;
18312 Lisp_Object object;
18313 int width, height;
6b61353c 18314 int ascent;
133c764e
KS
18315{
18316 struct glyph *glyph;
18317 enum glyph_row_area area = it->area;
18318
6b61353c 18319 xassert (ascent >= 0 && ascent <= height);
133c764e
KS
18320
18321 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
18322 if (glyph < it->glyph_row->glyphs[area + 1])
18323 {
18324 glyph->charpos = CHARPOS (it->position);
18325 glyph->object = object;
18326 glyph->pixel_width = width;
6b61353c
KH
18327 glyph->ascent = ascent;
18328 glyph->descent = height - ascent;
133c764e
KS
18329 glyph->voffset = it->voffset;
18330 glyph->type = STRETCH_GLYPH;
18331 glyph->multibyte_p = it->multibyte_p;
18332 glyph->left_box_line_p = it->start_of_box_run_p;
18333 glyph->right_box_line_p = it->end_of_box_run_p;
18334 glyph->overlaps_vertically_p = 0;
18335 glyph->padding_p = 0;
18336 glyph->glyph_not_available_p = 0;
18337 glyph->face_id = it->face_id;
6b61353c 18338 glyph->u.stretch.ascent = ascent;
133c764e
KS
18339 glyph->u.stretch.height = height;
18340 glyph->font_type = FONT_TYPE_UNKNOWN;
18341 ++it->glyph_row->used[area];
18342 }
18343}
18344
18345
18346/* Produce a stretch glyph for iterator IT. IT->object is the value
18347 of the glyph property displayed. The value must be a list
18348 `(space KEYWORD VALUE ...)' with the following KEYWORD/VALUE pairs
18349 being recognized:
18350
18351 1. `:width WIDTH' specifies that the space should be WIDTH *
18352 canonical char width wide. WIDTH may be an integer or floating
18353 point number.
18354
18355 2. `:relative-width FACTOR' specifies that the width of the stretch
18356 should be computed from the width of the first character having the
18357 `glyph' property, and should be FACTOR times that width.
18358
18359 3. `:align-to HPOS' specifies that the space should be wide enough
18360 to reach HPOS, a value in canonical character units.
18361
18362 Exactly one of the above pairs must be present.
18363
18364 4. `:height HEIGHT' specifies that the height of the stretch produced
18365 should be HEIGHT, measured in canonical character units.
18366
18367 5. `:relative-height FACTOR' specifies that the height of the
18368 stretch should be FACTOR times the height of the characters having
18369 the glyph property.
18370
18371 Either none or exactly one of 4 or 5 must be present.
18372
18373 6. `:ascent ASCENT' specifies that ASCENT percent of the height
18374 of the stretch should be used for the ascent of the stretch.
18375 ASCENT must be in the range 0 <= ASCENT <= 100. */
18376
133c764e
KS
18377static void
18378produce_stretch_glyph (it)
18379 struct it *it;
18380{
6b61353c 18381 /* (space :width WIDTH :height HEIGHT ...) */
133c764e 18382 Lisp_Object prop, plist;
6b61353c
KH
18383 int width = 0, height = 0, align_to = -1;
18384 int zero_width_ok_p = 0, zero_height_ok_p = 0;
18385 int ascent = 0;
18386 double tem;
133c764e
KS
18387 struct face *face = FACE_FROM_ID (it->f, it->face_id);
18388 XFontStruct *font = face->font ? face->font : FRAME_FONT (it->f);
18389
18390 PREPARE_FACE_FOR_DISPLAY (it->f, face);
18391
18392 /* List should start with `space'. */
18393 xassert (CONSP (it->object) && EQ (XCAR (it->object), Qspace));
18394 plist = XCDR (it->object);
18395
18396 /* Compute the width of the stretch. */
6b61353c
KH
18397 if ((prop = Fplist_get (plist, QCwidth), !NILP (prop))
18398 && calc_pixel_width_or_height (&tem, it, prop, font, 1, 0))
18399 {
18400 /* Absolute width `:width WIDTH' specified and valid. */
18401 zero_width_ok_p = 1;
18402 width = (int)tem;
18403 }
133c764e
KS
18404 else if (prop = Fplist_get (plist, QCrelative_width),
18405 NUMVAL (prop) > 0)
18406 {
18407 /* Relative width `:relative-width FACTOR' specified and valid.
18408 Compute the width of the characters having the `glyph'
18409 property. */
18410 struct it it2;
18411 unsigned char *p = BYTE_POS_ADDR (IT_BYTEPOS (*it));
18412
18413 it2 = *it;
18414 if (it->multibyte_p)
18415 {
18416 int maxlen = ((IT_BYTEPOS (*it) >= GPT ? ZV : GPT)
18417 - IT_BYTEPOS (*it));
18418 it2.c = STRING_CHAR_AND_LENGTH (p, maxlen, it2.len);
18419 }
18420 else
18421 it2.c = *p, it2.len = 1;
18422
18423 it2.glyph_row = NULL;
18424 it2.what = IT_CHARACTER;
18425 x_produce_glyphs (&it2);
18426 width = NUMVAL (prop) * it2.pixel_width;
18427 }
6b61353c
KH
18428 else if ((prop = Fplist_get (plist, QCalign_to), !NILP (prop))
18429 && calc_pixel_width_or_height (&tem, it, prop, font, 1, &align_to))
18430 {
18431 if (it->glyph_row == NULL || !it->glyph_row->mode_line_p)
18432 align_to = (align_to < 0
18433 ? 0
18434 : align_to - window_box_left_offset (it->w, TEXT_AREA));
18435 else if (align_to < 0)
18436 align_to = window_box_left_offset (it->w, TEXT_AREA);
18437 width = max (0, (int)tem + align_to - it->current_x);
18438 zero_width_ok_p = 1;
18439 }
133c764e
KS
18440 else
18441 /* Nothing specified -> width defaults to canonical char width. */
da8b7f4f 18442 width = FRAME_COLUMN_WIDTH (it->f);
133c764e 18443
6b61353c
KH
18444 if (width <= 0 && (width < 0 || !zero_width_ok_p))
18445 width = 1;
18446
133c764e 18447 /* Compute height. */
6b61353c
KH
18448 if ((prop = Fplist_get (plist, QCheight), !NILP (prop))
18449 && calc_pixel_width_or_height (&tem, it, prop, font, 0, 0))
18450 {
18451 height = (int)tem;
18452 zero_height_ok_p = 1;
18453 }
133c764e
KS
18454 else if (prop = Fplist_get (plist, QCrelative_height),
18455 NUMVAL (prop) > 0)
18456 height = FONT_HEIGHT (font) * NUMVAL (prop);
18457 else
18458 height = FONT_HEIGHT (font);
18459
6b61353c
KH
18460 if (height <= 0 && (height < 0 || !zero_height_ok_p))
18461 height = 1;
18462
133c764e
KS
18463 /* Compute percentage of height used for ascent. If
18464 `:ascent ASCENT' is present and valid, use that. Otherwise,
18465 derive the ascent from the font in use. */
18466 if (prop = Fplist_get (plist, QCascent),
18467 NUMVAL (prop) > 0 && NUMVAL (prop) <= 100)
6b61353c
KH
18468 ascent = height * NUMVAL (prop) / 100.0;
18469 else if (!NILP (prop)
18470 && calc_pixel_width_or_height (&tem, it, prop, font, 0, 0))
18471 ascent = min (max (0, (int)tem), height);
133c764e 18472 else
6b61353c 18473 ascent = (height * FONT_BASE (font)) / FONT_HEIGHT (font);
133c764e 18474
6b61353c 18475 if (width > 0 && height > 0 && it->glyph_row)
133c764e
KS
18476 {
18477 Lisp_Object object = it->stack[it->sp - 1].string;
18478 if (!STRINGP (object))
18479 object = it->w->buffer;
18480 append_stretch_glyph (it, object, width, height, ascent);
18481 }
18482
18483 it->pixel_width = width;
6b61353c 18484 it->ascent = it->phys_ascent = ascent;
133c764e 18485 it->descent = it->phys_descent = height - it->ascent;
6b61353c 18486 it->nglyphs = width > 0 && height > 0 ? 1 : 0;
133c764e 18487
6b61353c 18488 if (width > 0 && height > 0 && face->box != FACE_NO_BOX)
133c764e
KS
18489 {
18490 if (face->box_line_width > 0)
18491 {
18492 it->ascent += face->box_line_width;
18493 it->descent += face->box_line_width;
18494 }
18495
18496 if (it->start_of_box_run_p)
18497 it->pixel_width += abs (face->box_line_width);
18498 if (it->end_of_box_run_p)
18499 it->pixel_width += abs (face->box_line_width);
18500 }
18501
18502 take_vertical_position_into_account (it);
18503}
18504
18505/* RIF:
18506 Produce glyphs/get display metrics for the display element IT is
18507 loaded with. See the description of struct display_iterator in
18508 dispextern.h for an overview of struct display_iterator. */
18509
18510void
18511x_produce_glyphs (it)
18512 struct it *it;
18513{
18514 it->glyph_not_available_p = 0;
18515
18516 if (it->what == IT_CHARACTER)
18517 {
18518 XChar2b char2b;
18519 XFontStruct *font;
18520 struct face *face = FACE_FROM_ID (it->f, it->face_id);
18521 XCharStruct *pcm;
18522 int font_not_found_p;
18523 struct font_info *font_info;
18524 int boff; /* baseline offset */
18525 /* We may change it->multibyte_p upon unibyte<->multibyte
18526 conversion. So, save the current value now and restore it
18527 later.
18528
18529 Note: It seems that we don't have to record multibyte_p in
18530 struct glyph because the character code itself tells if or
18531 not the character is multibyte. Thus, in the future, we must
18532 consider eliminating the field `multibyte_p' in the struct
18533 glyph. */
18534 int saved_multibyte_p = it->multibyte_p;
18535
18536 /* Maybe translate single-byte characters to multibyte, or the
18537 other way. */
18538 it->char_to_display = it->c;
8f924df7
KH
18539 if (!ASCII_BYTE_P (it->c)
18540 && ! it->multibyte_p)
133c764e 18541 {
8f924df7
KH
18542 if (SINGLE_BYTE_CHAR_P (it->c)
18543 && unibyte_display_via_language_environment)
18544 it->char_to_display = unibyte_char_to_multibyte (it->c);
18545 if (! SINGLE_BYTE_CHAR_P (it->c))
133c764e
KS
18546 {
18547 it->multibyte_p = 1;
f46a4dc1
KH
18548 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display,
18549 -1, Qnil);
133c764e
KS
18550 face = FACE_FROM_ID (it->f, it->face_id);
18551 }
18552 }
18553
18554 /* Get font to use. Encode IT->char_to_display. */
18555 get_char_face_and_encoding (it->f, it->char_to_display, it->face_id,
18556 &char2b, it->multibyte_p, 0);
18557 font = face->font;
18558
18559 /* When no suitable font found, use the default font. */
18560 font_not_found_p = font == NULL;
18561 if (font_not_found_p)
18562 {
18563 font = FRAME_FONT (it->f);
18564 boff = FRAME_BASELINE_OFFSET (it->f);
18565 font_info = NULL;
18566 }
18567 else
18568 {
18569 font_info = FONT_INFO_FROM_ID (it->f, face->font_info_id);
18570 boff = font_info->baseline_offset;
18571 if (font_info->vertical_centering)
18572 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
18573 }
18574
18575 if (it->char_to_display >= ' '
18576 && (!it->multibyte_p || it->char_to_display < 128))
18577 {
18578 /* Either unibyte or ASCII. */
18579 int stretched_p;
18580
18581 it->nglyphs = 1;
18582
18583 pcm = rif->per_char_metric (font, &char2b,
18584 FONT_TYPE_FOR_UNIBYTE (font, it->char_to_display));
18585 it->ascent = FONT_BASE (font) + boff;
18586 it->descent = FONT_DESCENT (font) - boff;
18587
18588 if (pcm)
18589 {
18590 it->phys_ascent = pcm->ascent + boff;
18591 it->phys_descent = pcm->descent - boff;
18592 it->pixel_width = pcm->width;
18593 }
18594 else
18595 {
18596 it->glyph_not_available_p = 1;
18597 it->phys_ascent = FONT_BASE (font) + boff;
18598 it->phys_descent = FONT_DESCENT (font) - boff;
18599 it->pixel_width = FONT_WIDTH (font);
18600 }
18601
18602 /* If this is a space inside a region of text with
18603 `space-width' property, change its width. */
18604 stretched_p = it->char_to_display == ' ' && !NILP (it->space_width);
18605 if (stretched_p)
18606 it->pixel_width *= XFLOATINT (it->space_width);
18607
18608 /* If face has a box, add the box thickness to the character
18609 height. If character has a box line to the left and/or
18610 right, add the box line width to the character's width. */
18611 if (face->box != FACE_NO_BOX)
18612 {
18613 int thick = face->box_line_width;
18614
18615 if (thick > 0)
18616 {
18617 it->ascent += thick;
18618 it->descent += thick;
18619 }
18620 else
18621 thick = -thick;
18622
18623 if (it->start_of_box_run_p)
18624 it->pixel_width += thick;
18625 if (it->end_of_box_run_p)
18626 it->pixel_width += thick;
18627 }
18628
18629 /* If face has an overline, add the height of the overline
18630 (1 pixel) and a 1 pixel margin to the character height. */
18631 if (face->overline_p)
18632 it->ascent += 2;
18633
18634 take_vertical_position_into_account (it);
18635
18636 /* If we have to actually produce glyphs, do it. */
18637 if (it->glyph_row)
18638 {
18639 if (stretched_p)
18640 {
18641 /* Translate a space with a `space-width' property
18642 into a stretch glyph. */
6b61353c
KH
18643 int ascent = (((it->ascent + it->descent) * FONT_BASE (font))
18644 / FONT_HEIGHT (font));
133c764e
KS
18645 append_stretch_glyph (it, it->object, it->pixel_width,
18646 it->ascent + it->descent, ascent);
18647 }
18648 else
18649 append_glyph (it);
18650
18651 /* If characters with lbearing or rbearing are displayed
18652 in this line, record that fact in a flag of the
18653 glyph row. This is used to optimize X output code. */
18654 if (pcm && (pcm->lbearing < 0 || pcm->rbearing > pcm->width))
18655 it->glyph_row->contains_overlapping_glyphs_p = 1;
18656 }
18657 }
18658 else if (it->char_to_display == '\n')
18659 {
18660 /* A newline has no width but we need the height of the line. */
18661 it->pixel_width = 0;
18662 it->nglyphs = 0;
18663 it->ascent = it->phys_ascent = FONT_BASE (font) + boff;
18664 it->descent = it->phys_descent = FONT_DESCENT (font) - boff;
18665
18666 if (face->box != FACE_NO_BOX
18667 && face->box_line_width > 0)
18668 {
18669 it->ascent += face->box_line_width;
18670 it->descent += face->box_line_width;
18671 }
18672 }
18673 else if (it->char_to_display == '\t')
18674 {
da8b7f4f 18675 int tab_width = it->tab_width * FRAME_COLUMN_WIDTH (it->f);
133c764e
KS
18676 int x = it->current_x + it->continuation_lines_width;
18677 int next_tab_x = ((1 + x + tab_width - 1) / tab_width) * tab_width;
18678
18679 /* If the distance from the current position to the next tab
18680 stop is less than a canonical character width, use the
18681 tab stop after that. */
da8b7f4f 18682 if (next_tab_x - x < FRAME_COLUMN_WIDTH (it->f))
133c764e
KS
18683 next_tab_x += tab_width;
18684
18685 it->pixel_width = next_tab_x - x;
18686 it->nglyphs = 1;
18687 it->ascent = it->phys_ascent = FONT_BASE (font) + boff;
18688 it->descent = it->phys_descent = FONT_DESCENT (font) - boff;
18689
18690 if (it->glyph_row)
18691 {
133c764e 18692 append_stretch_glyph (it, it->object, it->pixel_width,
6b61353c 18693 it->ascent + it->descent, it->ascent);
133c764e
KS
18694 }
18695 }
18696 else
18697 {
18698 /* A multi-byte character. Assume that the display width of the
18699 character is the width of the character multiplied by the
18700 width of the font. */
18701
18702 /* If we found a font, this font should give us the right
18703 metrics. If we didn't find a font, use the frame's
8f924df7
KH
18704 default font and calculate the width of the character by
18705 multiplying the width of font by the width of the
18706 character. */
133c764e
KS
18707
18708 pcm = rif->per_char_metric (font, &char2b,
18709 FONT_TYPE_FOR_MULTIBYTE (font, it->c));
18710
18711 if (font_not_found_p || !pcm)
18712 {
133c764e 18713 it->glyph_not_available_p = 1;
da8b7f4f 18714 it->pixel_width = (FRAME_COLUMN_WIDTH (it->f)
8f924df7 18715 * CHAR_WIDTH (it->char_to_display));
133c764e
KS
18716 it->phys_ascent = FONT_BASE (font) + boff;
18717 it->phys_descent = FONT_DESCENT (font) - boff;
18718 }
18719 else
18720 {
18721 it->pixel_width = pcm->width;
18722 it->phys_ascent = pcm->ascent + boff;
18723 it->phys_descent = pcm->descent - boff;
18724 if (it->glyph_row
18725 && (pcm->lbearing < 0
18726 || pcm->rbearing > pcm->width))
18727 it->glyph_row->contains_overlapping_glyphs_p = 1;
18728 }
18729 it->nglyphs = 1;
18730 it->ascent = FONT_BASE (font) + boff;
18731 it->descent = FONT_DESCENT (font) - boff;
18732 if (face->box != FACE_NO_BOX)
18733 {
18734 int thick = face->box_line_width;
18735
18736 if (thick > 0)
18737 {
18738 it->ascent += thick;
18739 it->descent += thick;
18740 }
18741 else
18742 thick = - thick;
18743
18744 if (it->start_of_box_run_p)
18745 it->pixel_width += thick;
18746 if (it->end_of_box_run_p)
18747 it->pixel_width += thick;
18748 }
18749
18750 /* If face has an overline, add the height of the overline
18751 (1 pixel) and a 1 pixel margin to the character height. */
18752 if (face->overline_p)
18753 it->ascent += 2;
18754
18755 take_vertical_position_into_account (it);
18756
18757 if (it->glyph_row)
18758 append_glyph (it);
18759 }
18760 it->multibyte_p = saved_multibyte_p;
18761 }
18762 else if (it->what == IT_COMPOSITION)
18763 {
18764 /* Note: A composition is represented as one glyph in the
18765 glyph matrix. There are no padding glyphs. */
18766 XChar2b char2b;
18767 XFontStruct *font;
18768 struct face *face = FACE_FROM_ID (it->f, it->face_id);
18769 XCharStruct *pcm;
18770 int font_not_found_p;
18771 struct font_info *font_info;
18772 int boff; /* baseline offset */
18773 struct composition *cmp = composition_table[it->cmp_id];
032ed801 18774 int pos;
133c764e
KS
18775
18776 /* Maybe translate single-byte characters to multibyte. */
18777 it->char_to_display = it->c;
18778 if (unibyte_display_via_language_environment
8f924df7 18779 && it->c >= 0200)
133c764e
KS
18780 {
18781 it->char_to_display = unibyte_char_to_multibyte (it->c);
18782 }
18783
18784 /* Get face and font to use. Encode IT->char_to_display. */
032ed801
KH
18785 pos = STRINGP (it->string) ? IT_STRING_CHARPOS (*it) : IT_CHARPOS (*it);
18786 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display,
18787 pos, it->string);
133c764e
KS
18788 face = FACE_FROM_ID (it->f, it->face_id);
18789 get_char_face_and_encoding (it->f, it->char_to_display, it->face_id,
18790 &char2b, it->multibyte_p, 0);
18791 font = face->font;
18792
18793 /* When no suitable font found, use the default font. */
18794 font_not_found_p = font == NULL;
18795 if (font_not_found_p)
18796 {
18797 font = FRAME_FONT (it->f);
18798 boff = FRAME_BASELINE_OFFSET (it->f);
18799 font_info = NULL;
18800 }
18801 else
18802 {
18803 font_info = FONT_INFO_FROM_ID (it->f, face->font_info_id);
18804 boff = font_info->baseline_offset;
18805 if (font_info->vertical_centering)
18806 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
18807 }
18808
18809 /* There are no padding glyphs, so there is only one glyph to
18810 produce for the composition. Important is that pixel_width,
18811 ascent and descent are the values of what is drawn by
18812 draw_glyphs (i.e. the values of the overall glyphs composed). */
18813 it->nglyphs = 1;
18814
18815 /* If we have not yet calculated pixel size data of glyphs of
18816 the composition for the current face font, calculate them
18817 now. Theoretically, we have to check all fonts for the
18818 glyphs, but that requires much time and memory space. So,
18819 here we check only the font of the first glyph. This leads
993651d1
KH
18820 to incorrect display, but it's very rare, and C-l (recenter)
18821 can correct the display anyway. */
133c764e
KS
18822 if (cmp->font != (void *) font)
18823 {
18824 /* Ascent and descent of the font of the first character of
18825 this composition (adjusted by baseline offset). Ascent
18826 and descent of overall glyphs should not be less than
18827 them respectively. */
18828 int font_ascent = FONT_BASE (font) + boff;
18829 int font_descent = FONT_DESCENT (font) - boff;
993651d1 18830 int font_height = FONT_HEIGHT (font);
133c764e
KS
18831 /* Bounding box of the overall glyphs. */
18832 int leftmost, rightmost, lowest, highest;
993651d1 18833 int lbearing, rbearing;
133c764e
KS
18834 int i, width, ascent, descent;
18835
18836 cmp->font = (void *) font;
18837
18838 /* Initialize the bounding box. */
18839 if (font_info
18840 && (pcm = rif->per_char_metric (font, &char2b,
18841 FONT_TYPE_FOR_MULTIBYTE (font, it->c))))
18842 {
18843 width = pcm->width;
18844 ascent = pcm->ascent;
18845 descent = pcm->descent;
993651d1
KH
18846 lbearing = pcm->lbearing;
18847 if (lbearing > 0)
18848 lbearing = 0;
18849 rbearing = pcm->rbearing;
18850 if (rbearing < width)
18851 rbearing = width;
133c764e
KS
18852 }
18853 else
18854 {
18855 width = FONT_WIDTH (font);
18856 ascent = FONT_BASE (font);
18857 descent = FONT_DESCENT (font);
993651d1
KH
18858 lbearing = 0;
18859 rbearing = width;
133c764e
KS
18860 }
18861
18862 rightmost = width;
18863 lowest = - descent + boff;
18864 highest = ascent + boff;
18865 leftmost = 0;
18866
18867 if (font_info
18868 && font_info->default_ascent
18869 && CHAR_TABLE_P (Vuse_default_ascent)
18870 && !NILP (Faref (Vuse_default_ascent,
18871 make_number (it->char_to_display))))
18872 highest = font_info->default_ascent + boff;
18873
18874 /* Draw the first glyph at the normal position. It may be
18875 shifted to right later if some other glyphs are drawn at
18876 the left. */
18877 cmp->offsets[0] = 0;
18878 cmp->offsets[1] = boff;
993651d1
KH
18879 cmp->lbearing = lbearing;
18880 cmp->rbearing = rbearing;
133c764e
KS
18881
18882 /* Set cmp->offsets for the remaining glyphs. */
18883 for (i = 1; i < cmp->glyph_len; i++)
18884 {
18885 int left, right, btm, top;
18886 int ch = COMPOSITION_GLYPH (cmp, i);
032ed801 18887 int face_id = FACE_FOR_CHAR (it->f, face, ch, pos, it->string);
133c764e
KS
18888
18889 face = FACE_FROM_ID (it->f, face_id);
18890 get_char_face_and_encoding (it->f, ch, face->id,
18891 &char2b, it->multibyte_p, 0);
18892 font = face->font;
18893 if (font == NULL)
18894 {
18895 font = FRAME_FONT (it->f);
2a6d0874 18896 boff = FRAME_BASELINE_OFFSET (it->f);
133c764e
KS
18897 font_info = NULL;
18898 }
18899 else
18900 {
18901 font_info
18902 = FONT_INFO_FROM_ID (it->f, face->font_info_id);
18903 boff = font_info->baseline_offset;
18904 if (font_info->vertical_centering)
18905 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
18906 }
18907
18908 if (font_info
2a6d0874 18909 && (pcm = rif->per_char_metric (font, &char2b,
133c764e
KS
18910 FONT_TYPE_FOR_MULTIBYTE (font, ch))))
18911 {
18912 width = pcm->width;
18913 ascent = pcm->ascent;
18914 descent = pcm->descent;
993651d1
KH
18915 lbearing = pcm->lbearing;
18916 if (lbearing > 0)
18917 lbearing = 0;
18918 rbearing = pcm->rbearing;
18919 if (rbearing < width)
18920 rbearing = width;
133c764e
KS
18921 }
18922 else
18923 {
18924 width = FONT_WIDTH (font);
18925 ascent = 1;
18926 descent = 0;
993651d1
KH
18927 lbearing = 0;
18928 rbearing = width;
133c764e
KS
18929 }
18930
18931 if (cmp->method != COMPOSITION_WITH_RULE_ALTCHARS)
18932 {
18933 /* Relative composition with or without
18934 alternate chars. */
18935 left = (leftmost + rightmost - width) / 2;
18936 btm = - descent + boff;
18937 if (font_info && font_info->relative_compose
18938 && (! CHAR_TABLE_P (Vignore_relative_composition)
18939 || NILP (Faref (Vignore_relative_composition,
18940 make_number (ch)))))
18941 {
18942
18943 if (- descent >= font_info->relative_compose)
18944 /* One extra pixel between two glyphs. */
18945 btm = highest + 1;
18946 else if (ascent <= 0)
18947 /* One extra pixel between two glyphs. */
18948 btm = lowest - 1 - ascent - descent;
18949 }
18950 }
18951 else
18952 {
18953 /* A composition rule is specified by an integer
18954 value that encodes global and new reference
18955 points (GREF and NREF). GREF and NREF are
18956 specified by numbers as below:
18957
18958 0---1---2 -- ascent
18959 | |
18960 | |
18961 | |
18962 9--10--11 -- center
18963 | |
18964 ---3---4---5--- baseline
18965 | |
18966 6---7---8 -- descent
18967 */
18968 int rule = COMPOSITION_RULE (cmp, i);
993651d1 18969 int gref, nref, grefx, grefy, nrefx, nrefy, xoff, yoff;
133c764e 18970
993651d1 18971 COMPOSITION_DECODE_RULE (rule, gref, nref, xoff, yoff);
133c764e
KS
18972 grefx = gref % 3, nrefx = nref % 3;
18973 grefy = gref / 3, nrefy = nref / 3;
993651d1
KH
18974 if (xoff)
18975 xoff = font_height * (xoff - 128) / 256;
18976 if (yoff)
18977 yoff = font_height * (yoff - 128) / 256;
133c764e
KS
18978
18979 left = (leftmost
18980 + grefx * (rightmost - leftmost) / 2
993651d1
KH
18981 - nrefx * width / 2
18982 + xoff);
18983
133c764e
KS
18984 btm = ((grefy == 0 ? highest
18985 : grefy == 1 ? 0
18986 : grefy == 2 ? lowest
18987 : (highest + lowest) / 2)
18988 - (nrefy == 0 ? ascent + descent
18989 : nrefy == 1 ? descent - boff
18990 : nrefy == 2 ? 0
993651d1
KH
18991 : (ascent + descent) / 2)
18992 + yoff);
133c764e
KS
18993 }
18994
18995 cmp->offsets[i * 2] = left;
18996 cmp->offsets[i * 2 + 1] = btm + descent;
18997
18998 /* Update the bounding box of the overall glyphs. */
993651d1
KH
18999 if (width > 0)
19000 {
19001 right = left + width;
19002 if (left < leftmost)
19003 leftmost = left;
19004 if (right > rightmost)
19005 rightmost = right;
19006 }
133c764e 19007 top = btm + descent + ascent;
133c764e
KS
19008 if (top > highest)
19009 highest = top;
19010 if (btm < lowest)
19011 lowest = btm;
993651d1
KH
19012
19013 if (cmp->lbearing > left + lbearing)
19014 cmp->lbearing = left + lbearing;
19015 if (cmp->rbearing < left + rbearing)
19016 cmp->rbearing = left + rbearing;
133c764e
KS
19017 }
19018
19019 /* If there are glyphs whose x-offsets are negative,
19020 shift all glyphs to the right and make all x-offsets
19021 non-negative. */
19022 if (leftmost < 0)
19023 {
19024 for (i = 0; i < cmp->glyph_len; i++)
19025 cmp->offsets[i * 2] -= leftmost;
19026 rightmost -= leftmost;
993651d1
KH
19027 cmp->lbearing -= leftmost;
19028 cmp->rbearing -= leftmost;
133c764e
KS
19029 }
19030
19031 cmp->pixel_width = rightmost;
19032 cmp->ascent = highest;
19033 cmp->descent = - lowest;
19034 if (cmp->ascent < font_ascent)
19035 cmp->ascent = font_ascent;
19036 if (cmp->descent < font_descent)
19037 cmp->descent = font_descent;
19038 }
19039
993651d1
KH
19040 if (it->glyph_row
19041 && (cmp->lbearing < 0
19042 || cmp->rbearing > cmp->pixel_width))
19043 it->glyph_row->contains_overlapping_glyphs_p = 1;
19044
133c764e
KS
19045 it->pixel_width = cmp->pixel_width;
19046 it->ascent = it->phys_ascent = cmp->ascent;
19047 it->descent = it->phys_descent = cmp->descent;
19048
19049 if (face->box != FACE_NO_BOX)
19050 {
19051 int thick = face->box_line_width;
19052
19053 if (thick > 0)
19054 {
19055 it->ascent += thick;
19056 it->descent += thick;
19057 }
19058 else
19059 thick = - thick;
19060
19061 if (it->start_of_box_run_p)
19062 it->pixel_width += thick;
19063 if (it->end_of_box_run_p)
19064 it->pixel_width += thick;
19065 }
19066
19067 /* If face has an overline, add the height of the overline
19068 (1 pixel) and a 1 pixel margin to the character height. */
19069 if (face->overline_p)
19070 it->ascent += 2;
19071
19072 take_vertical_position_into_account (it);
19073
19074 if (it->glyph_row)
19075 append_composite_glyph (it);
19076 }
19077 else if (it->what == IT_IMAGE)
19078 produce_image_glyph (it);
19079 else if (it->what == IT_STRETCH)
19080 produce_stretch_glyph (it);
19081
19082 /* Accumulate dimensions. Note: can't assume that it->descent > 0
19083 because this isn't true for images with `:ascent 100'. */
19084 xassert (it->ascent >= 0 && it->descent >= 0);
19085 if (it->area == TEXT_AREA)
19086 it->current_x += it->pixel_width;
19087
19088 it->descent += it->extra_line_spacing;
19089
19090 it->max_ascent = max (it->max_ascent, it->ascent);
19091 it->max_descent = max (it->max_descent, it->descent);
19092 it->max_phys_ascent = max (it->max_phys_ascent, it->phys_ascent);
19093 it->max_phys_descent = max (it->max_phys_descent, it->phys_descent);
19094}
19095
fa3c6b4d
KS
19096/* EXPORT for RIF:
19097 Output LEN glyphs starting at START at the nominal cursor position.
19098 Advance the nominal cursor over the text. The global variable
19099 updated_window contains the window being updated, updated_row is
19100 the glyph row being updated, and updated_area is the area of that
19101 row being updated. */
133c764e 19102
fa3c6b4d
KS
19103void
19104x_write_glyphs (start, len)
19105 struct glyph *start;
19106 int len;
19107{
19108 int x, hpos;
133c764e 19109
fa3c6b4d
KS
19110 xassert (updated_window && updated_row);
19111 BLOCK_INPUT;
133c764e 19112
fa3c6b4d 19113 /* Write glyphs. */
cfe03a41 19114
fa3c6b4d
KS
19115 hpos = start - updated_row->glyphs[updated_area];
19116 x = draw_glyphs (updated_window, output_cursor.x,
19117 updated_row, updated_area,
19118 hpos, hpos + len,
19119 DRAW_NORMAL_TEXT, 0);
cfe03a41 19120
fa3c6b4d
KS
19121 /* Invalidate old phys cursor if the glyph at its hpos is redrawn. */
19122 if (updated_area == TEXT_AREA
19123 && updated_window->phys_cursor_on_p
19124 && updated_window->phys_cursor.vpos == output_cursor.vpos
19125 && updated_window->phys_cursor.hpos >= hpos
19126 && updated_window->phys_cursor.hpos < hpos + len)
19127 updated_window->phys_cursor_on_p = 0;
cfe03a41 19128
fa3c6b4d 19129 UNBLOCK_INPUT;
cfe03a41 19130
fa3c6b4d
KS
19131 /* Advance the output cursor. */
19132 output_cursor.hpos += len;
19133 output_cursor.x = x;
19134}
cfe03a41 19135
cfe03a41 19136
fa3c6b4d
KS
19137/* EXPORT for RIF:
19138 Insert LEN glyphs from START at the nominal cursor position. */
19139
19140void
19141x_insert_glyphs (start, len)
19142 struct glyph *start;
19143 int len;
19144{
19145 struct frame *f;
19146 struct window *w;
19147 int line_height, shift_by_width, shifted_region_width;
19148 struct glyph_row *row;
19149 struct glyph *glyph;
cbb6a48a
DL
19150 int frame_x, frame_y;
19151 EMACS_INT hpos;
fa3c6b4d
KS
19152
19153 xassert (updated_window && updated_row);
19154 BLOCK_INPUT;
19155 w = updated_window;
19156 f = XFRAME (WINDOW_FRAME (w));
19157
19158 /* Get the height of the line we are in. */
19159 row = updated_row;
19160 line_height = row->height;
19161
19162 /* Get the width of the glyphs to insert. */
19163 shift_by_width = 0;
19164 for (glyph = start; glyph < start + len; ++glyph)
19165 shift_by_width += glyph->pixel_width;
19166
19167 /* Get the width of the region to shift right. */
19168 shifted_region_width = (window_box_width (w, updated_area)
19169 - output_cursor.x
19170 - shift_by_width);
19171
19172 /* Shift right. */
19173 frame_x = window_box_left (w, updated_area) + output_cursor.x;
19174 frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, output_cursor.y);
19175
7b7b454e
AS
19176 rif->shift_glyphs_for_insert (f, frame_x, frame_y, shifted_region_width,
19177 line_height, shift_by_width);
fa3c6b4d
KS
19178
19179 /* Write the glyphs. */
19180 hpos = start - row->glyphs[updated_area];
19181 draw_glyphs (w, output_cursor.x, row, updated_area,
19182 hpos, hpos + len,
19183 DRAW_NORMAL_TEXT, 0);
19184
19185 /* Advance the output cursor. */
19186 output_cursor.hpos += len;
19187 output_cursor.x += shift_by_width;
19188 UNBLOCK_INPUT;
19189}
19190
19191
19192/* EXPORT for RIF:
19193 Erase the current text line from the nominal cursor position
19194 (inclusive) to pixel column TO_X (exclusive). The idea is that
19195 everything from TO_X onward is already erased.
19196
19197 TO_X is a pixel position relative to updated_area of
19198 updated_window. TO_X == -1 means clear to the end of this area. */
19199
19200void
19201x_clear_end_of_line (to_x)
19202 int to_x;
19203{
19204 struct frame *f;
19205 struct window *w = updated_window;
19206 int max_x, min_y, max_y;
19207 int from_x, from_y, to_y;
19208
19209 xassert (updated_window && updated_row);
19210 f = XFRAME (w->frame);
19211
19212 if (updated_row->full_width_p)
da8b7f4f 19213 max_x = WINDOW_TOTAL_WIDTH (w);
fa3c6b4d
KS
19214 else
19215 max_x = window_box_width (w, updated_area);
19216 max_y = window_text_bottom_y (w);
19217
19218 /* TO_X == 0 means don't do anything. TO_X < 0 means clear to end
19219 of window. For TO_X > 0, truncate to end of drawing area. */
19220 if (to_x == 0)
19221 return;
19222 else if (to_x < 0)
19223 to_x = max_x;
19224 else
19225 to_x = min (to_x, max_x);
19226
19227 to_y = min (max_y, output_cursor.y + updated_row->height);
19228
19229 /* Notice if the cursor will be cleared by this operation. */
19230 if (!updated_row->full_width_p)
19231 notice_overwritten_cursor (w, updated_area,
19232 output_cursor.x, -1,
19233 updated_row->y,
19234 MATRIX_ROW_BOTTOM_Y (updated_row));
19235
19236 from_x = output_cursor.x;
19237
19238 /* Translate to frame coordinates. */
19239 if (updated_row->full_width_p)
19240 {
19241 from_x = WINDOW_TO_FRAME_PIXEL_X (w, from_x);
19242 to_x = WINDOW_TO_FRAME_PIXEL_X (w, to_x);
19243 }
19244 else
19245 {
da8b7f4f
KS
19246 int area_left = window_box_left (w, updated_area);
19247 from_x += area_left;
19248 to_x += area_left;
fa3c6b4d
KS
19249 }
19250
da8b7f4f 19251 min_y = WINDOW_HEADER_LINE_HEIGHT (w);
fa3c6b4d
KS
19252 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, max (min_y, output_cursor.y));
19253 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, to_y);
19254
19255 /* Prevent inadvertently clearing to end of the X window. */
19256 if (to_x > from_x && to_y > from_y)
19257 {
19258 BLOCK_INPUT;
19259 rif->clear_frame_area (f, from_x, from_y,
19260 to_x - from_x, to_y - from_y);
19261 UNBLOCK_INPUT;
19262 }
19263}
19264
19265#endif /* HAVE_WINDOW_SYSTEM */
19266
19267
19268\f
19269/***********************************************************************
19270 Cursor types
19271 ***********************************************************************/
19272
19273/* Value is the internal representation of the specified cursor type
19274 ARG. If type is BAR_CURSOR, return in *WIDTH the specified width
19275 of the bar cursor. */
19276
6b61353c 19277static enum text_cursor_kinds
fa3c6b4d
KS
19278get_specified_cursor_type (arg, width)
19279 Lisp_Object arg;
19280 int *width;
19281{
19282 enum text_cursor_kinds type;
19283
19284 if (NILP (arg))
19285 return NO_CURSOR;
19286
19287 if (EQ (arg, Qbox))
19288 return FILLED_BOX_CURSOR;
19289
19290 if (EQ (arg, Qhollow))
19291 return HOLLOW_BOX_CURSOR;
19292
19293 if (EQ (arg, Qbar))
19294 {
19295 *width = 2;
19296 return BAR_CURSOR;
19297 }
19298
19299 if (CONSP (arg)
19300 && EQ (XCAR (arg), Qbar)
19301 && INTEGERP (XCDR (arg))
19302 && XINT (XCDR (arg)) >= 0)
19303 {
19304 *width = XINT (XCDR (arg));
19305 return BAR_CURSOR;
19306 }
19307
19308 if (EQ (arg, Qhbar))
19309 {
19310 *width = 2;
19311 return HBAR_CURSOR;
19312 }
19313
19314 if (CONSP (arg)
19315 && EQ (XCAR (arg), Qhbar)
19316 && INTEGERP (XCDR (arg))
19317 && XINT (XCDR (arg)) >= 0)
19318 {
19319 *width = XINT (XCDR (arg));
19320 return HBAR_CURSOR;
19321 }
19322
19323 /* Treat anything unknown as "hollow box cursor".
19324 It was bad to signal an error; people have trouble fixing
19325 .Xdefaults with Emacs, when it has something bad in it. */
19326 type = HOLLOW_BOX_CURSOR;
19327
19328 return type;
19329}
19330
19331/* Set the default cursor types for specified frame. */
19332void
19333set_frame_cursor_types (f, arg)
19334 struct frame *f;
19335 Lisp_Object arg;
19336{
19337 int width;
19338 Lisp_Object tem;
19339
19340 FRAME_DESIRED_CURSOR (f) = get_specified_cursor_type (arg, &width);
19341 FRAME_CURSOR_WIDTH (f) = width;
19342
19343 /* By default, set up the blink-off state depending on the on-state. */
19344
19345 tem = Fassoc (arg, Vblink_cursor_alist);
19346 if (!NILP (tem))
19347 {
19348 FRAME_BLINK_OFF_CURSOR (f)
19349 = get_specified_cursor_type (XCDR (tem), &width);
19350 FRAME_BLINK_OFF_CURSOR_WIDTH (f) = width;
19351 }
19352 else
19353 FRAME_BLINK_OFF_CURSOR (f) = DEFAULT_CURSOR;
19354}
19355
19356
19357/* Return the cursor we want to be displayed in window W. Return
19358 width of bar/hbar cursor through WIDTH arg. Return with
19359 ACTIVE_CURSOR arg set to 1 if cursor in window W is `active'
19360 (i.e. if the `system caret' should track this cursor).
19361
19362 In a mini-buffer window, we want the cursor only to appear if we
19363 are reading input from this window. For the selected window, we
19364 want the cursor type given by the frame parameter or buffer local
19365 setting of cursor-type. If explicitly marked off, draw no cursor.
19366 In all other cases, we want a hollow box cursor. */
19367
6b61353c
KH
19368static enum text_cursor_kinds
19369get_window_cursor_type (w, glyph, width, active_cursor)
fa3c6b4d 19370 struct window *w;
6b61353c 19371 struct glyph *glyph;
fa3c6b4d
KS
19372 int *width;
19373 int *active_cursor;
19374{
19375 struct frame *f = XFRAME (w->frame);
19376 struct buffer *b = XBUFFER (w->buffer);
19377 int cursor_type = DEFAULT_CURSOR;
19378 Lisp_Object alt_cursor;
19379 int non_selected = 0;
19380
19381 *active_cursor = 1;
19382
19383 /* Echo area */
19384 if (cursor_in_echo_area
19385 && FRAME_HAS_MINIBUF_P (f)
19386 && EQ (FRAME_MINIBUF_WINDOW (f), echo_area_window))
19387 {
19388 if (w == XWINDOW (echo_area_window))
19389 {
19390 *width = FRAME_CURSOR_WIDTH (f);
19391 return FRAME_DESIRED_CURSOR (f);
19392 }
19393
19394 *active_cursor = 0;
19395 non_selected = 1;
19396 }
19397
19398 /* Nonselected window or nonselected frame. */
19399 else if (w != XWINDOW (f->selected_window)
19400#ifdef HAVE_WINDOW_SYSTEM
19401 || f != FRAME_X_DISPLAY_INFO (f)->x_highlight_frame
19402#endif
19403 )
19404 {
19405 *active_cursor = 0;
19406
19407 if (MINI_WINDOW_P (w) && minibuf_level == 0)
19408 return NO_CURSOR;
19409
19410 non_selected = 1;
19411 }
19412
19413 /* Never display a cursor in a window in which cursor-type is nil. */
19414 if (NILP (b->cursor_type))
19415 return NO_CURSOR;
19416
19417 /* Use cursor-in-non-selected-windows for non-selected window or frame. */
19418 if (non_selected)
19419 {
19420 alt_cursor = Fbuffer_local_value (Qcursor_in_non_selected_windows, w->buffer);
19421 return get_specified_cursor_type (alt_cursor, width);
19422 }
19423
19424 /* Get the normal cursor type for this window. */
19425 if (EQ (b->cursor_type, Qt))
19426 {
19427 cursor_type = FRAME_DESIRED_CURSOR (f);
19428 *width = FRAME_CURSOR_WIDTH (f);
19429 }
19430 else
19431 cursor_type = get_specified_cursor_type (b->cursor_type, width);
19432
19433 /* Use normal cursor if not blinked off. */
19434 if (!w->cursor_off_p)
6b61353c
KH
19435 {
19436 if (glyph != NULL && glyph->type == IMAGE_GLYPH) {
19437 if (cursor_type == FILLED_BOX_CURSOR)
19438 cursor_type = HOLLOW_BOX_CURSOR;
19439 }
19440 return cursor_type;
19441 }
fa3c6b4d
KS
19442
19443 /* Cursor is blinked off, so determine how to "toggle" it. */
19444
19445 /* First look for an entry matching the buffer's cursor-type in blink-cursor-alist. */
19446 if ((alt_cursor = Fassoc (b->cursor_type, Vblink_cursor_alist), !NILP (alt_cursor)))
19447 return get_specified_cursor_type (XCDR (alt_cursor), width);
19448
19449 /* Then see if frame has specified a specific blink off cursor type. */
19450 if (FRAME_BLINK_OFF_CURSOR (f) != DEFAULT_CURSOR)
19451 {
19452 *width = FRAME_BLINK_OFF_CURSOR_WIDTH (f);
19453 return FRAME_BLINK_OFF_CURSOR (f);
19454 }
19455
6b61353c
KH
19456#if 0
19457 /* Some people liked having a permanently visible blinking cursor,
19458 while others had very strong opinions against it. So it was
19459 decided to remove it. KFS 2003-09-03 */
19460
fa3c6b4d
KS
19461 /* Finally perform built-in cursor blinking:
19462 filled box <-> hollow box
19463 wide [h]bar <-> narrow [h]bar
19464 narrow [h]bar <-> no cursor
19465 other type <-> no cursor */
19466
19467 if (cursor_type == FILLED_BOX_CURSOR)
19468 return HOLLOW_BOX_CURSOR;
19469
19470 if ((cursor_type == BAR_CURSOR || cursor_type == HBAR_CURSOR) && *width > 1)
19471 {
19472 *width = 1;
19473 return cursor_type;
19474 }
6b61353c 19475#endif
fa3c6b4d
KS
19476
19477 return NO_CURSOR;
19478}
19479
19480
19481#ifdef HAVE_WINDOW_SYSTEM
19482
19483/* Notice when the text cursor of window W has been completely
19484 overwritten by a drawing operation that outputs glyphs in AREA
19485 starting at X0 and ending at X1 in the line starting at Y0 and
19486 ending at Y1. X coordinates are area-relative. X1 < 0 means all
19487 the rest of the line after X0 has been written. Y coordinates
19488 are window-relative. */
19489
19490static void
19491notice_overwritten_cursor (w, area, x0, x1, y0, y1)
19492 struct window *w;
19493 enum glyph_row_area area;
19494 int x0, y0, x1, y1;
19495{
6b61353c
KH
19496 int cx0, cx1, cy0, cy1;
19497 struct glyph_row *row;
fa3c6b4d 19498
6b61353c
KH
19499 if (!w->phys_cursor_on_p)
19500 return;
19501 if (area != TEXT_AREA)
19502 return;
fa3c6b4d 19503
6b61353c
KH
19504 row = w->current_matrix->rows + w->phys_cursor.vpos;
19505 if (!row->displays_text_p)
19506 return;
fa3c6b4d 19507
6b61353c
KH
19508 if (row->cursor_in_fringe_p)
19509 {
19510 row->cursor_in_fringe_p = 0;
19511 draw_fringe_bitmap (w, row, 0);
19512 w->phys_cursor_on_p = 0;
19513 return;
fa3c6b4d 19514 }
6b61353c
KH
19515
19516 cx0 = w->phys_cursor.x;
19517 cx1 = cx0 + w->phys_cursor_width;
19518 if (x0 > cx0 || (x1 >= 0 && x1 < cx1))
19519 return;
19520
19521 /* The cursor image will be completely removed from the
19522 screen if the output area intersects the cursor area in
19523 y-direction. When we draw in [y0 y1[, and some part of
19524 the cursor is at y < y0, that part must have been drawn
19525 before. When scrolling, the cursor is erased before
19526 actually scrolling, so we don't come here. When not
19527 scrolling, the rows above the old cursor row must have
19528 changed, and in this case these rows must have written
19529 over the cursor image.
19530
19531 Likewise if part of the cursor is below y1, with the
19532 exception of the cursor being in the first blank row at
19533 the buffer and window end because update_text_area
19534 doesn't draw that row. (Except when it does, but
19535 that's handled in update_text_area.) */
19536
19537 cy0 = w->phys_cursor.y;
19538 cy1 = cy0 + w->phys_cursor_height;
19539 if ((y0 < cy0 || y0 >= cy1) && (y1 <= cy0 || y1 >= cy1))
19540 return;
19541
19542 w->phys_cursor_on_p = 0;
fa3c6b4d
KS
19543}
19544
19545#endif /* HAVE_WINDOW_SYSTEM */
19546
19547\f
19548/************************************************************************
19549 Mouse Face
19550 ************************************************************************/
19551
19552#ifdef HAVE_WINDOW_SYSTEM
19553
19554/* EXPORT for RIF:
19555 Fix the display of area AREA of overlapping row ROW in window W. */
19556
19557void
19558x_fix_overlapping_area (w, row, area)
19559 struct window *w;
19560 struct glyph_row *row;
19561 enum glyph_row_area area;
19562{
19563 int i, x;
19564
19565 BLOCK_INPUT;
19566
57dd22f4 19567 x = 0;
fa3c6b4d
KS
19568 for (i = 0; i < row->used[area];)
19569 {
19570 if (row->glyphs[area][i].overlaps_vertically_p)
19571 {
19572 int start = i, start_x = x;
19573
19574 do
19575 {
19576 x += row->glyphs[area][i].pixel_width;
19577 ++i;
19578 }
19579 while (i < row->used[area]
19580 && row->glyphs[area][i].overlaps_vertically_p);
19581
19582 draw_glyphs (w, start_x, row, area,
19583 start, i,
19584 DRAW_NORMAL_TEXT, 1);
19585 }
19586 else
19587 {
19588 x += row->glyphs[area][i].pixel_width;
19589 ++i;
19590 }
19591 }
19592
19593 UNBLOCK_INPUT;
19594}
19595
19596
19597/* EXPORT:
19598 Draw the cursor glyph of window W in glyph row ROW. See the
19599 comment of draw_glyphs for the meaning of HL. */
19600
19601void
19602draw_phys_cursor_glyph (w, row, hl)
19603 struct window *w;
19604 struct glyph_row *row;
19605 enum draw_glyphs_face hl;
19606{
19607 /* If cursor hpos is out of bounds, don't draw garbage. This can
19608 happen in mini-buffer windows when switching between echo area
19609 glyphs and mini-buffer. */
19610 if (w->phys_cursor.hpos < row->used[TEXT_AREA])
19611 {
19612 int on_p = w->phys_cursor_on_p;
19613 int x1;
19614 x1 = draw_glyphs (w, w->phys_cursor.x, row, TEXT_AREA,
19615 w->phys_cursor.hpos, w->phys_cursor.hpos + 1,
19616 hl, 0);
19617 w->phys_cursor_on_p = on_p;
19618
fa3c6b4d
KS
19619 if (hl == DRAW_CURSOR)
19620 w->phys_cursor_width = x1 - w->phys_cursor.x;
fa3c6b4d
KS
19621 /* When we erase the cursor, and ROW is overlapped by other
19622 rows, make sure that these overlapping parts of other rows
19623 are redrawn. */
365fa1b3 19624 else if (hl == DRAW_NORMAL_TEXT && row->overlapped_p)
fa3c6b4d
KS
19625 {
19626 if (row > w->current_matrix->rows
19627 && MATRIX_ROW_OVERLAPS_SUCC_P (row - 1))
19628 x_fix_overlapping_area (w, row - 1, TEXT_AREA);
19629
19630 if (MATRIX_ROW_BOTTOM_Y (row) < window_text_bottom_y (w)
19631 && MATRIX_ROW_OVERLAPS_PRED_P (row + 1))
19632 x_fix_overlapping_area (w, row + 1, TEXT_AREA);
19633 }
19634 }
19635}
19636
19637
19638/* EXPORT:
19639 Erase the image of a cursor of window W from the screen. */
19640
19641void
19642erase_phys_cursor (w)
19643 struct window *w;
19644{
19645 struct frame *f = XFRAME (w->frame);
19646 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
19647 int hpos = w->phys_cursor.hpos;
19648 int vpos = w->phys_cursor.vpos;
19649 int mouse_face_here_p = 0;
19650 struct glyph_matrix *active_glyphs = w->current_matrix;
19651 struct glyph_row *cursor_row;
19652 struct glyph *cursor_glyph;
19653 enum draw_glyphs_face hl;
19654
19655 /* No cursor displayed or row invalidated => nothing to do on the
19656 screen. */
19657 if (w->phys_cursor_type == NO_CURSOR)
19658 goto mark_cursor_off;
19659
19660 /* VPOS >= active_glyphs->nrows means that window has been resized.
19661 Don't bother to erase the cursor. */
19662 if (vpos >= active_glyphs->nrows)
19663 goto mark_cursor_off;
19664
19665 /* If row containing cursor is marked invalid, there is nothing we
19666 can do. */
19667 cursor_row = MATRIX_ROW (active_glyphs, vpos);
19668 if (!cursor_row->enabled_p)
19669 goto mark_cursor_off;
19670
19671 /* If row is completely invisible, don't attempt to delete a cursor which
19672 isn't there. This can happen if cursor is at top of a window, and
19673 we switch to a buffer with a header line in that window. */
19674 if (cursor_row->visible_height <= 0)
19675 goto mark_cursor_off;
19676
6b61353c
KH
19677 /* If cursor is in the fringe, erase by drawing actual bitmap there. */
19678 if (cursor_row->cursor_in_fringe_p)
19679 {
19680 cursor_row->cursor_in_fringe_p = 0;
19681 draw_fringe_bitmap (w, cursor_row, 0);
19682 goto mark_cursor_off;
19683 }
19684
fa3c6b4d
KS
19685 /* This can happen when the new row is shorter than the old one.
19686 In this case, either draw_glyphs or clear_end_of_line
19687 should have cleared the cursor. Note that we wouldn't be
19688 able to erase the cursor in this case because we don't have a
19689 cursor glyph at hand. */
19690 if (w->phys_cursor.hpos >= cursor_row->used[TEXT_AREA])
19691 goto mark_cursor_off;
19692
19693 /* If the cursor is in the mouse face area, redisplay that when
19694 we clear the cursor. */
19695 if (! NILP (dpyinfo->mouse_face_window)
19696 && w == XWINDOW (dpyinfo->mouse_face_window)
19697 && (vpos > dpyinfo->mouse_face_beg_row
19698 || (vpos == dpyinfo->mouse_face_beg_row
19699 && hpos >= dpyinfo->mouse_face_beg_col))
19700 && (vpos < dpyinfo->mouse_face_end_row
19701 || (vpos == dpyinfo->mouse_face_end_row
19702 && hpos < dpyinfo->mouse_face_end_col))
19703 /* Don't redraw the cursor's spot in mouse face if it is at the
19704 end of a line (on a newline). The cursor appears there, but
19705 mouse highlighting does not. */
19706 && cursor_row->used[TEXT_AREA] > hpos)
19707 mouse_face_here_p = 1;
19708
19709 /* Maybe clear the display under the cursor. */
19710 if (w->phys_cursor_type == HOLLOW_BOX_CURSOR)
19711 {
19712 int x, y;
da8b7f4f 19713 int header_line_height = WINDOW_HEADER_LINE_HEIGHT (w);
fa3c6b4d
KS
19714
19715 cursor_glyph = get_phys_cursor_glyph (w);
19716 if (cursor_glyph == NULL)
19717 goto mark_cursor_off;
19718
19719 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
19720 y = WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height, cursor_row->y));
19721
19722 rif->clear_frame_area (f, x, y,
19723 cursor_glyph->pixel_width, cursor_row->visible_height);
19724 }
19725
19726 /* Erase the cursor by redrawing the character underneath it. */
19727 if (mouse_face_here_p)
19728 hl = DRAW_MOUSE_FACE;
19729 else
19730 hl = DRAW_NORMAL_TEXT;
19731 draw_phys_cursor_glyph (w, cursor_row, hl);
19732
19733 mark_cursor_off:
19734 w->phys_cursor_on_p = 0;
19735 w->phys_cursor_type = NO_CURSOR;
19736}
19737
19738
19739/* EXPORT:
19740 Display or clear cursor of window W. If ON is zero, clear the
19741 cursor. If it is non-zero, display the cursor. If ON is nonzero,
19742 where to put the cursor is specified by HPOS, VPOS, X and Y. */
19743
19744void
19745display_and_set_cursor (w, on, hpos, vpos, x, y)
19746 struct window *w;
19747 int on, hpos, vpos, x, y;
19748{
19749 struct frame *f = XFRAME (w->frame);
19750 int new_cursor_type;
19751 int new_cursor_width;
19752 int active_cursor;
fa3c6b4d 19753 struct glyph_row *glyph_row;
6b61353c 19754 struct glyph *glyph;
fa3c6b4d
KS
19755
19756 /* This is pointless on invisible frames, and dangerous on garbaged
19757 windows and frames; in the latter case, the frame or window may
19758 be in the midst of changing its size, and x and y may be off the
19759 window. */
19760 if (! FRAME_VISIBLE_P (f)
19761 || FRAME_GARBAGED_P (f)
19762 || vpos >= w->current_matrix->nrows
19763 || hpos >= w->current_matrix->matrix_w)
19764 return;
19765
19766 /* If cursor is off and we want it off, return quickly. */
19767 if (!on && !w->phys_cursor_on_p)
19768 return;
19769
6b61353c 19770 glyph_row = MATRIX_ROW (w->current_matrix, vpos);
fa3c6b4d
KS
19771 /* If cursor row is not enabled, we don't really know where to
19772 display the cursor. */
19773 if (!glyph_row->enabled_p)
19774 {
19775 w->phys_cursor_on_p = 0;
19776 return;
19777 }
19778
6b61353c
KH
19779 glyph = NULL;
19780 if (!glyph_row->exact_window_width_line_p
19781 || hpos < glyph_row->used[TEXT_AREA])
19782 glyph = glyph_row->glyphs[TEXT_AREA] + hpos;
19783
fa3c6b4d
KS
19784 xassert (interrupt_input_blocked);
19785
19786 /* Set new_cursor_type to the cursor we want to be displayed. */
6b61353c
KH
19787 new_cursor_type = get_window_cursor_type (w, glyph,
19788 &new_cursor_width, &active_cursor);
fa3c6b4d
KS
19789
19790 /* If cursor is currently being shown and we don't want it to be or
19791 it is in the wrong place, or the cursor type is not what we want,
19792 erase it. */
19793 if (w->phys_cursor_on_p
19794 && (!on
19795 || w->phys_cursor.x != x
19796 || w->phys_cursor.y != y
19797 || new_cursor_type != w->phys_cursor_type
19798 || ((new_cursor_type == BAR_CURSOR || new_cursor_type == HBAR_CURSOR)
19799 && new_cursor_width != w->phys_cursor_width)))
19800 erase_phys_cursor (w);
19801
19802 /* Don't check phys_cursor_on_p here because that flag is only set
19803 to zero in some cases where we know that the cursor has been
19804 completely erased, to avoid the extra work of erasing the cursor
19805 twice. In other words, phys_cursor_on_p can be 1 and the cursor
19806 still not be visible, or it has only been partly erased. */
19807 if (on)
19808 {
19809 w->phys_cursor_ascent = glyph_row->ascent;
19810 w->phys_cursor_height = glyph_row->height;
19811
19812 /* Set phys_cursor_.* before x_draw_.* is called because some
19813 of them may need the information. */
19814 w->phys_cursor.x = x;
19815 w->phys_cursor.y = glyph_row->y;
19816 w->phys_cursor.hpos = hpos;
19817 w->phys_cursor.vpos = vpos;
19818 }
19819
b4ebbb12
KS
19820 rif->draw_window_cursor (w, glyph_row, x, y,
19821 new_cursor_type, new_cursor_width,
19822 on, active_cursor);
fa3c6b4d
KS
19823}
19824
19825
19826/* Switch the display of W's cursor on or off, according to the value
19827 of ON. */
19828
19829static void
19830update_window_cursor (w, on)
19831 struct window *w;
19832 int on;
19833{
19834 /* Don't update cursor in windows whose frame is in the process
19835 of being deleted. */
19836 if (w->current_matrix)
19837 {
19838 BLOCK_INPUT;
19839 display_and_set_cursor (w, on, w->phys_cursor.hpos, w->phys_cursor.vpos,
19840 w->phys_cursor.x, w->phys_cursor.y);
19841 UNBLOCK_INPUT;
19842 }
19843}
19844
19845
19846/* Call update_window_cursor with parameter ON_P on all leaf windows
19847 in the window tree rooted at W. */
19848
19849static void
19850update_cursor_in_window_tree (w, on_p)
19851 struct window *w;
19852 int on_p;
19853{
19854 while (w)
19855 {
19856 if (!NILP (w->hchild))
19857 update_cursor_in_window_tree (XWINDOW (w->hchild), on_p);
19858 else if (!NILP (w->vchild))
19859 update_cursor_in_window_tree (XWINDOW (w->vchild), on_p);
19860 else
19861 update_window_cursor (w, on_p);
19862
19863 w = NILP (w->next) ? 0 : XWINDOW (w->next);
19864 }
19865}
19866
19867
19868/* EXPORT:
19869 Display the cursor on window W, or clear it, according to ON_P.
19870 Don't change the cursor's position. */
19871
19872void
19873x_update_cursor (f, on_p)
19874 struct frame *f;
19875 int on_p;
19876{
19877 update_cursor_in_window_tree (XWINDOW (f->root_window), on_p);
19878}
19879
19880
19881/* EXPORT:
19882 Clear the cursor of window W to background color, and mark the
19883 cursor as not shown. This is used when the text where the cursor
19884 is is about to be rewritten. */
19885
19886void
19887x_clear_cursor (w)
19888 struct window *w;
19889{
19890 if (FRAME_VISIBLE_P (XFRAME (w->frame)) && w->phys_cursor_on_p)
19891 update_window_cursor (w, 0);
19892}
19893
19894
19895/* EXPORT:
19896 Display the active region described by mouse_face_* according to DRAW. */
19897
19898void
19899show_mouse_face (dpyinfo, draw)
19900 Display_Info *dpyinfo;
19901 enum draw_glyphs_face draw;
19902{
19903 struct window *w = XWINDOW (dpyinfo->mouse_face_window);
19904 struct frame *f = XFRAME (WINDOW_FRAME (w));
19905
19906 if (/* If window is in the process of being destroyed, don't bother
19907 to do anything. */
19908 w->current_matrix != NULL
19909 /* Don't update mouse highlight if hidden */
19910 && (draw != DRAW_MOUSE_FACE || !dpyinfo->mouse_face_hidden)
19911 /* Recognize when we are called to operate on rows that don't exist
19912 anymore. This can happen when a window is split. */
19913 && dpyinfo->mouse_face_end_row < w->current_matrix->nrows)
19914 {
19915 int phys_cursor_on_p = w->phys_cursor_on_p;
19916 struct glyph_row *row, *first, *last;
19917
19918 first = MATRIX_ROW (w->current_matrix, dpyinfo->mouse_face_beg_row);
19919 last = MATRIX_ROW (w->current_matrix, dpyinfo->mouse_face_end_row);
19920
19921 for (row = first; row <= last && row->enabled_p; ++row)
19922 {
19923 int start_hpos, end_hpos, start_x;
19924
19925 /* For all but the first row, the highlight starts at column 0. */
19926 if (row == first)
19927 {
19928 start_hpos = dpyinfo->mouse_face_beg_col;
19929 start_x = dpyinfo->mouse_face_beg_x;
19930 }
19931 else
19932 {
19933 start_hpos = 0;
19934 start_x = 0;
19935 }
19936
19937 if (row == last)
19938 end_hpos = dpyinfo->mouse_face_end_col;
19939 else
19940 end_hpos = row->used[TEXT_AREA];
19941
19942 if (end_hpos > start_hpos)
19943 {
19944 draw_glyphs (w, start_x, row, TEXT_AREA,
19945 start_hpos, end_hpos,
19946 draw, 0);
19947
19948 row->mouse_face_p
19949 = draw == DRAW_MOUSE_FACE || draw == DRAW_IMAGE_RAISED;
19950 }
19951 }
19952
19953 /* When we've written over the cursor, arrange for it to
19954 be displayed again. */
19955 if (phys_cursor_on_p && !w->phys_cursor_on_p)
19956 {
19957 BLOCK_INPUT;
19958 display_and_set_cursor (w, 1,
19959 w->phys_cursor.hpos, w->phys_cursor.vpos,
19960 w->phys_cursor.x, w->phys_cursor.y);
19961 UNBLOCK_INPUT;
19962 }
19963 }
19964
19965 /* Change the mouse cursor. */
19966 if (draw == DRAW_NORMAL_TEXT)
19967 rif->define_frame_cursor (f, FRAME_X_OUTPUT (f)->text_cursor);
19968 else if (draw == DRAW_MOUSE_FACE)
19969 rif->define_frame_cursor (f, FRAME_X_OUTPUT (f)->hand_cursor);
19970 else
19971 rif->define_frame_cursor (f, FRAME_X_OUTPUT (f)->nontext_cursor);
19972}
19973
19974/* EXPORT:
19975 Clear out the mouse-highlighted active region.
19976 Redraw it un-highlighted first. Value is non-zero if mouse
19977 face was actually drawn unhighlighted. */
19978
19979int
19980clear_mouse_face (dpyinfo)
19981 Display_Info *dpyinfo;
19982{
19983 int cleared = 0;
19984
6b61353c 19985 if (!dpyinfo->mouse_face_hidden && !NILP (dpyinfo->mouse_face_window))
fa3c6b4d
KS
19986 {
19987 show_mouse_face (dpyinfo, DRAW_NORMAL_TEXT);
19988 cleared = 1;
19989 }
19990
19991 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
19992 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
19993 dpyinfo->mouse_face_window = Qnil;
19994 dpyinfo->mouse_face_overlay = Qnil;
19995 return cleared;
19996}
19997
19998
19999/* EXPORT:
20000 Non-zero if physical cursor of window W is within mouse face. */
20001
20002int
20003cursor_in_mouse_face_p (w)
20004 struct window *w;
20005{
20006 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (XFRAME (w->frame));
20007 int in_mouse_face = 0;
20008
20009 if (WINDOWP (dpyinfo->mouse_face_window)
20010 && XWINDOW (dpyinfo->mouse_face_window) == w)
20011 {
20012 int hpos = w->phys_cursor.hpos;
20013 int vpos = w->phys_cursor.vpos;
20014
20015 if (vpos >= dpyinfo->mouse_face_beg_row
20016 && vpos <= dpyinfo->mouse_face_end_row
20017 && (vpos > dpyinfo->mouse_face_beg_row
20018 || hpos >= dpyinfo->mouse_face_beg_col)
20019 && (vpos < dpyinfo->mouse_face_end_row
20020 || hpos < dpyinfo->mouse_face_end_col
20021 || dpyinfo->mouse_face_past_end))
20022 in_mouse_face = 1;
20023 }
20024
20025 return in_mouse_face;
20026}
20027
20028
20029
20030\f
20031/* Find the glyph matrix position of buffer position CHARPOS in window
20032 *W. HPOS, *VPOS, *X, and *Y are set to the positions found. W's
20033 current glyphs must be up to date. If CHARPOS is above window
20034 start return (0, 0, 0, 0). If CHARPOS is after end of W, return end
20035 of last line in W. In the row containing CHARPOS, stop before glyphs
20036 having STOP as object. */
20037
9c3521e0 20038#if 1 /* This is a version of fast_find_position that's more correct
fa3c6b4d
KS
20039 in the presence of hscrolling, for example. I didn't install
20040 it right away because the problem fixed is minor, it failed
20041 in 20.x as well, and I think it's too risky to install
20042 so near the release of 21.1. 2001-09-25 gerd. */
20043
20044static int
20045fast_find_position (w, charpos, hpos, vpos, x, y, stop)
20046 struct window *w;
cbb6a48a 20047 EMACS_INT charpos;
fa3c6b4d
KS
20048 int *hpos, *vpos, *x, *y;
20049 Lisp_Object stop;
20050{
20051 struct glyph_row *row, *first;
20052 struct glyph *glyph, *end;
b19a5b64 20053 int past_end = 0;
fa3c6b4d
KS
20054
20055 first = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
20056 row = row_containing_pos (w, charpos, first, NULL, 0);
20057 if (row == NULL)
20058 {
20059 if (charpos < MATRIX_ROW_START_CHARPOS (first))
20060 {
20061 *x = *y = *hpos = *vpos = 0;
6b61353c 20062 return 1;
fa3c6b4d
KS
20063 }
20064 else
20065 {
20066 row = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos));
20067 past_end = 1;
20068 }
20069 }
20070
20071 *x = row->x;
20072 *y = row->y;
20073 *vpos = MATRIX_ROW_VPOS (row, w->current_matrix);
20074
20075 glyph = row->glyphs[TEXT_AREA];
20076 end = glyph + row->used[TEXT_AREA];
20077
20078 /* Skip over glyphs not having an object at the start of the row.
20079 These are special glyphs like truncation marks on terminal
20080 frames. */
20081 if (row->displays_text_p)
20082 while (glyph < end
20083 && INTEGERP (glyph->object)
20084 && !EQ (stop, glyph->object)
20085 && glyph->charpos < 0)
20086 {
20087 *x += glyph->pixel_width;
20088 ++glyph;
20089 }
20090
20091 while (glyph < end
20092 && !INTEGERP (glyph->object)
20093 && !EQ (stop, glyph->object)
20094 && (!BUFFERP (glyph->object)
20095 || glyph->charpos < charpos))
20096 {
20097 *x += glyph->pixel_width;
20098 ++glyph;
20099 }
20100
20101 *hpos = glyph - row->glyphs[TEXT_AREA];
6b61353c 20102 return !past_end;
fa3c6b4d
KS
20103}
20104
9c3521e0 20105#else /* not 1 */
fa3c6b4d
KS
20106
20107static int
20108fast_find_position (w, pos, hpos, vpos, x, y, stop)
20109 struct window *w;
cbb6a48a 20110 EMACS_INT pos;
fa3c6b4d
KS
20111 int *hpos, *vpos, *x, *y;
20112 Lisp_Object stop;
20113{
20114 int i;
20115 int lastcol;
20116 int maybe_next_line_p = 0;
20117 int line_start_position;
20118 int yb = window_text_bottom_y (w);
20119 struct glyph_row *row, *best_row;
20120 int row_vpos, best_row_vpos;
20121 int current_x;
20122
20123 row = best_row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
20124 row_vpos = best_row_vpos = MATRIX_ROW_VPOS (row, w->current_matrix);
20125
20126 while (row->y < yb)
20127 {
20128 if (row->used[TEXT_AREA])
20129 line_start_position = row->glyphs[TEXT_AREA]->charpos;
20130 else
20131 line_start_position = 0;
20132
20133 if (line_start_position > pos)
20134 break;
20135 /* If the position sought is the end of the buffer,
20136 don't include the blank lines at the bottom of the window. */
20137 else if (line_start_position == pos
20138 && pos == BUF_ZV (XBUFFER (w->buffer)))
20139 {
20140 maybe_next_line_p = 1;
20141 break;
20142 }
20143 else if (line_start_position > 0)
20144 {
20145 best_row = row;
20146 best_row_vpos = row_vpos;
20147 }
20148
20149 if (row->y + row->height >= yb)
20150 break;
20151
20152 ++row;
20153 ++row_vpos;
20154 }
20155
20156 /* Find the right column within BEST_ROW. */
20157 lastcol = 0;
20158 current_x = best_row->x;
20159 for (i = 0; i < best_row->used[TEXT_AREA]; i++)
20160 {
20161 struct glyph *glyph = best_row->glyphs[TEXT_AREA] + i;
20162 int charpos = glyph->charpos;
20163
20164 if (BUFFERP (glyph->object))
20165 {
20166 if (charpos == pos)
20167 {
20168 *hpos = i;
20169 *vpos = best_row_vpos;
20170 *x = current_x;
20171 *y = best_row->y;
20172 return 1;
20173 }
20174 else if (charpos > pos)
20175 break;
20176 }
20177 else if (EQ (glyph->object, stop))
20178 break;
20179
20180 if (charpos > 0)
20181 lastcol = i;
20182 current_x += glyph->pixel_width;
20183 }
20184
20185 /* If we're looking for the end of the buffer,
20186 and we didn't find it in the line we scanned,
20187 use the start of the following line. */
20188 if (maybe_next_line_p)
20189 {
20190 ++best_row;
20191 ++best_row_vpos;
20192 lastcol = 0;
20193 current_x = best_row->x;
20194 }
20195
20196 *vpos = best_row_vpos;
20197 *hpos = lastcol + 1;
20198 *x = current_x;
20199 *y = best_row->y;
20200 return 0;
20201}
20202
9c3521e0 20203#endif /* not 1 */
fa3c6b4d
KS
20204
20205
20206/* Find the position of the glyph for position POS in OBJECT in
20207 window W's current matrix, and return in *X, *Y the pixel
20208 coordinates, and return in *HPOS, *VPOS the column/row of the glyph.
20209
20210 RIGHT_P non-zero means return the position of the right edge of the
20211 glyph, RIGHT_P zero means return the left edge position.
20212
20213 If no glyph for POS exists in the matrix, return the position of
20214 the glyph with the next smaller position that is in the matrix, if
20215 RIGHT_P is zero. If RIGHT_P is non-zero, and no glyph for POS
20216 exists in the matrix, return the position of the glyph with the
20217 next larger position in OBJECT.
20218
20219 Value is non-zero if a glyph was found. */
20220
20221static int
20222fast_find_string_pos (w, pos, object, hpos, vpos, x, y, right_p)
20223 struct window *w;
cbb6a48a 20224 EMACS_INT pos;
fa3c6b4d
KS
20225 Lisp_Object object;
20226 int *hpos, *vpos, *x, *y;
20227 int right_p;
20228{
20229 int yb = window_text_bottom_y (w);
20230 struct glyph_row *r;
20231 struct glyph *best_glyph = NULL;
20232 struct glyph_row *best_row = NULL;
20233 int best_x = 0;
20234
20235 for (r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
20236 r->enabled_p && r->y < yb;
20237 ++r)
20238 {
20239 struct glyph *g = r->glyphs[TEXT_AREA];
20240 struct glyph *e = g + r->used[TEXT_AREA];
20241 int gx;
20242
20243 for (gx = r->x; g < e; gx += g->pixel_width, ++g)
20244 if (EQ (g->object, object))
20245 {
20246 if (g->charpos == pos)
20247 {
20248 best_glyph = g;
20249 best_x = gx;
20250 best_row = r;
20251 goto found;
20252 }
20253 else if (best_glyph == NULL
20254 || ((abs (g->charpos - pos)
20255 < abs (best_glyph->charpos - pos))
20256 && (right_p
20257 ? g->charpos < pos
20258 : g->charpos > pos)))
20259 {
20260 best_glyph = g;
20261 best_x = gx;
20262 best_row = r;
20263 }
20264 }
20265 }
20266
20267 found:
20268
20269 if (best_glyph)
20270 {
20271 *x = best_x;
20272 *hpos = best_glyph - best_row->glyphs[TEXT_AREA];
20273
20274 if (right_p)
20275 {
20276 *x += best_glyph->pixel_width;
20277 ++*hpos;
20278 }
20279
20280 *y = best_row->y;
20281 *vpos = best_row - w->current_matrix->rows;
20282 }
20283
20284 return best_glyph != NULL;
20285}
20286
20287
6b61353c
KH
20288/* See if position X, Y is within a hot-spot of an image. */
20289
20290static int
20291on_hot_spot_p (hot_spot, x, y)
20292 Lisp_Object hot_spot;
20293 int x, y;
20294{
20295 if (!CONSP (hot_spot))
20296 return 0;
20297
20298 if (EQ (XCAR (hot_spot), Qrect))
20299 {
20300 /* CDR is (Top-Left . Bottom-Right) = ((x0 . y0) . (x1 . y1)) */
20301 Lisp_Object rect = XCDR (hot_spot);
20302 Lisp_Object tem;
20303 if (!CONSP (rect))
20304 return 0;
20305 if (!CONSP (XCAR (rect)))
20306 return 0;
20307 if (!CONSP (XCDR (rect)))
20308 return 0;
20309 if (!(tem = XCAR (XCAR (rect)), INTEGERP (tem) && x >= XINT (tem)))
20310 return 0;
20311 if (!(tem = XCDR (XCAR (rect)), INTEGERP (tem) && y >= XINT (tem)))
20312 return 0;
20313 if (!(tem = XCAR (XCDR (rect)), INTEGERP (tem) && x <= XINT (tem)))
20314 return 0;
20315 if (!(tem = XCDR (XCDR (rect)), INTEGERP (tem) && y <= XINT (tem)))
20316 return 0;
20317 return 1;
20318 }
20319 else if (EQ (XCAR (hot_spot), Qcircle))
20320 {
20321 /* CDR is (Center . Radius) = ((x0 . y0) . r) */
20322 Lisp_Object circ = XCDR (hot_spot);
20323 Lisp_Object lr, lx0, ly0;
20324 if (CONSP (circ)
20325 && CONSP (XCAR (circ))
20326 && (lr = XCDR (circ), INTEGERP (lr) || FLOATP (lr))
20327 && (lx0 = XCAR (XCAR (circ)), INTEGERP (lx0))
20328 && (ly0 = XCDR (XCAR (circ)), INTEGERP (ly0)))
20329 {
20330 double r = XFLOATINT (lr);
20331 double dx = XINT (lx0) - x;
20332 double dy = XINT (ly0) - y;
20333 return (dx * dx + dy * dy <= r * r);
20334 }
20335 }
20336 else if (EQ (XCAR (hot_spot), Qpoly))
20337 {
20338 /* CDR is [x0 y0 x1 y1 x2 y2 ...x(n-1) y(n-1)] */
20339 if (VECTORP (XCDR (hot_spot)))
20340 {
20341 struct Lisp_Vector *v = XVECTOR (XCDR (hot_spot));
20342 Lisp_Object *poly = v->contents;
20343 int n = v->size;
20344 int i;
20345 int inside = 0;
20346 Lisp_Object lx, ly;
20347 int x0, y0;
20348
20349 /* Need an even number of coordinates, and at least 3 edges. */
20350 if (n < 6 || n & 1)
20351 return 0;
20352
20353 /* Count edge segments intersecting line from (X,Y) to (X,infinity).
20354 If count is odd, we are inside polygon. Pixels on edges
20355 may or may not be included depending on actual geometry of the
20356 polygon. */
20357 if ((lx = poly[n-2], !INTEGERP (lx))
20358 || (ly = poly[n-1], !INTEGERP (lx)))
20359 return 0;
20360 x0 = XINT (lx), y0 = XINT (ly);
20361 for (i = 0; i < n; i += 2)
20362 {
20363 int x1 = x0, y1 = y0;
20364 if ((lx = poly[i], !INTEGERP (lx))
20365 || (ly = poly[i+1], !INTEGERP (ly)))
20366 return 0;
20367 x0 = XINT (lx), y0 = XINT (ly);
20368
20369 /* Does this segment cross the X line? */
20370 if (x0 >= x)
20371 {
20372 if (x1 >= x)
20373 continue;
20374 }
20375 else if (x1 < x)
20376 continue;
20377 if (y > y0 && y > y1)
20378 continue;
20379 if (y < y0 + ((y1 - y0) * (x - x0)) / (x1 - x0))
20380 inside = !inside;
20381 }
20382 return inside;
20383 }
20384 }
20385 else
20386 return 0;
20387}
20388
20389Lisp_Object
20390find_hot_spot (map, x, y)
20391 Lisp_Object map;
20392 int x, y;
20393{
20394 while (CONSP (map))
20395 {
20396 if (CONSP (XCAR (map))
20397 && on_hot_spot_p (XCAR (XCAR (map)), x, y))
20398 return XCAR (map);
20399 map = XCDR (map);
20400 }
20401
20402 return Qnil;
20403}
20404
20405DEFUN ("lookup-image-map", Flookup_image_map, Slookup_image_map,
20406 3, 3, 0,
20407 doc: /* Lookup in image map MAP coordinates X and Y.
20408An image map is an alist where each element has the format (AREA ID PLIST).
20409An AREA is specified as either a rectangle, a circle, or a polygon:
20410A rectangle is a cons (rect . ((x0 . y0) . (x1 . y1))) specifying the
20411pixel coordinates of the upper left and bottom right corners.
20412A circle is a cons (circle . ((x0 . y0) . r)) specifying the center
20413and the radius of the circle; r may be a float or integer.
20414A polygon is a cons (poly . [x0 y0 x1 y1 ...]) where each pair in the
20415vector describes one corner in the polygon.
20416Returns the alist element for the first matching AREA in MAP. */)
20417 (map, x, y)
20418 Lisp_Object map;
20419 Lisp_Object x, y;
20420{
20421 int ix, iy;
20422 if (NILP (map))
20423 return Qnil;
20424
20425 CHECK_NUMBER (x);
20426 CHECK_NUMBER (y);
20427
20428 return find_hot_spot (map, XINT (x), XINT (y));
20429}
20430
20431
20432/* Display frame CURSOR, optionally using shape defined by POINTER. */
20433static void
20434define_frame_cursor1 (f, cursor, pointer)
20435 struct frame *f;
20436 Cursor cursor;
20437 Lisp_Object pointer;
20438{
20439 if (!NILP (pointer))
20440 {
20441 if (EQ (pointer, Qarrow))
20442 cursor = FRAME_X_OUTPUT (f)->nontext_cursor;
20443 else if (EQ (pointer, Qhand))
20444 cursor = FRAME_X_OUTPUT (f)->hand_cursor;
20445 else if (EQ (pointer, Qtext))
20446 cursor = FRAME_X_OUTPUT (f)->text_cursor;
20447 else if (EQ (pointer, intern ("hdrag")))
20448 cursor = FRAME_X_OUTPUT (f)->horizontal_drag_cursor;
20449#ifdef HAVE_X_WINDOWS
20450 else if (EQ (pointer, intern ("vdrag")))
20451 cursor = FRAME_X_DISPLAY_INFO (f)->vertical_scroll_bar_cursor;
20452#endif
20453 else if (EQ (pointer, intern ("hourglass")))
20454 cursor = FRAME_X_OUTPUT (f)->hourglass_cursor;
20455 else if (EQ (pointer, Qmodeline))
20456 cursor = FRAME_X_OUTPUT (f)->modeline_cursor;
20457 else
20458 cursor = FRAME_X_OUTPUT (f)->nontext_cursor;
20459 }
20460
20461#ifndef HAVE_CARBON
20462 if (cursor != No_Cursor)
20463#else
20464 if (bcmp (&cursor, &No_Cursor, sizeof (Cursor)))
20465#endif
20466 rif->define_frame_cursor (f, cursor);
20467}
20468
fa3c6b4d
KS
20469/* Take proper action when mouse has moved to the mode or header line
20470 or marginal area AREA of window W, x-position X and y-position Y.
20471 X is relative to the start of the text display area of W, so the
20472 width of bitmap areas and scroll bars must be subtracted to get a
20473 position relative to the start of the mode line. */
20474
20475static void
20476note_mode_line_or_margin_highlight (w, x, y, area)
20477 struct window *w;
20478 int x, y;
20479 enum window_part area;
20480{
20481 struct frame *f = XFRAME (w->frame);
20482 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
6b61353c
KH
20483 Cursor cursor = FRAME_X_OUTPUT (f)->nontext_cursor;
20484 Lisp_Object pointer = Qnil;
20485 int charpos, dx, dy, width, height;
20486 Lisp_Object string, object = Qnil;
20487 Lisp_Object pos, help, image;
fa3c6b4d
KS
20488
20489 if (area == ON_MODE_LINE || area == ON_HEADER_LINE)
6b61353c
KH
20490 string = mode_line_string (w, area, &x, &y, &charpos,
20491 &object, &dx, &dy, &width, &height);
fa3c6b4d 20492 else
6b61353c
KH
20493 {
20494 x -= WINDOW_LEFT_SCROLL_BAR_AREA_WIDTH (w);
20495 string = marginal_area_string (w, area, &x, &y, &charpos,
20496 &object, &dx, &dy, &width, &height);
20497 }
20498
20499 help = Qnil;
20500
20501 if (IMAGEP (object))
20502 {
20503 Lisp_Object image_map, hotspot;
20504 if ((image_map = Fplist_get (XCDR (object), QCmap),
20505 !NILP (image_map))
20506 && (hotspot = find_hot_spot (image_map, dx, dy),
20507 CONSP (hotspot))
20508 && (hotspot = XCDR (hotspot), CONSP (hotspot)))
20509 {
20510 Lisp_Object area_id, plist;
20511
20512 area_id = XCAR (hotspot);
20513 /* Could check AREA_ID to see if we enter/leave this hot-spot.
20514 If so, we could look for mouse-enter, mouse-leave
20515 properties in PLIST (and do something...). */
20516 if ((plist = XCDR (hotspot), CONSP (plist)))
20517 {
20518 pointer = Fplist_get (plist, Qpointer);
20519 if (NILP (pointer))
20520 pointer = Qhand;
20521 help = Fplist_get (plist, Qhelp_echo);
20522 if (!NILP (help))
20523 {
20524 help_echo_string = help;
20525 /* Is this correct? ++kfs */
20526 XSETWINDOW (help_echo_window, w);
20527 help_echo_object = w->buffer;
20528 help_echo_pos = charpos;
20529 }
20530 }
20531 if (NILP (pointer))
20532 pointer = Fplist_get (XCDR (object), QCpointer);
20533 }
20534 }
fa3c6b4d
KS
20535
20536 if (STRINGP (string))
20537 {
20538 pos = make_number (charpos);
fa3c6b4d
KS
20539 /* If we're on a string with `help-echo' text property, arrange
20540 for the help to be displayed. This is done by setting the
20541 global variable help_echo_string to the help string. */
20542 help = Fget_text_property (pos, Qhelp_echo, string);
20543 if (!NILP (help))
20544 {
20545 help_echo_string = help;
20546 XSETWINDOW (help_echo_window, w);
20547 help_echo_object = string;
20548 help_echo_pos = charpos;
20549 }
20550
6b61353c
KH
20551 if (NILP (pointer))
20552 pointer = Fget_text_property (pos, Qpointer, string);
20553
fa3c6b4d 20554 /* Change the mouse pointer according to what is under X/Y. */
6b61353c
KH
20555 if (NILP (pointer) && ((area == ON_MODE_LINE) || (area == ON_HEADER_LINE)))
20556 {
20557 Lisp_Object map;
20558 map = Fget_text_property (pos, Qlocal_map, string);
20559 if (!KEYMAPP (map))
20560 map = Fget_text_property (pos, Qkeymap, string);
20561 if (!KEYMAPP (map))
20562 cursor = dpyinfo->vertical_scroll_bar_cursor;
20563 }
fa3c6b4d
KS
20564 }
20565
6b61353c 20566 define_frame_cursor1 (f, cursor, pointer);
fa3c6b4d
KS
20567}
20568
fa3c6b4d
KS
20569
20570/* EXPORT:
20571 Take proper action when the mouse has moved to position X, Y on
20572 frame F as regards highlighting characters that have mouse-face
20573 properties. Also de-highlighting chars where the mouse was before.
20574 X and Y can be negative or out of range. */
20575
20576void
20577note_mouse_highlight (f, x, y)
20578 struct frame *f;
20579 int x, y;
20580{
20581 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
20582 enum window_part part;
20583 Lisp_Object window;
20584 struct window *w;
20585 Cursor cursor = No_Cursor;
6b61353c 20586 Lisp_Object pointer = Qnil; /* Takes precedence over cursor! */
fa3c6b4d
KS
20587 struct buffer *b;
20588
20589 /* When a menu is active, don't highlight because this looks odd. */
20590#if defined (USE_X_TOOLKIT) || defined (USE_GTK) || defined (HAVE_NTGUI)
20591 if (popup_activated ())
20592 return;
20593#endif
20594
20595 if (NILP (Vmouse_highlight)
20596 || !f->glyphs_initialized_p)
20597 return;
20598
20599 dpyinfo->mouse_face_mouse_x = x;
20600 dpyinfo->mouse_face_mouse_y = y;
20601 dpyinfo->mouse_face_mouse_frame = f;
20602
20603 if (dpyinfo->mouse_face_defer)
20604 return;
20605
20606 if (gc_in_progress)
20607 {
20608 dpyinfo->mouse_face_deferred_gc = 1;
20609 return;
20610 }
20611
20612 /* Which window is that in? */
da8b7f4f 20613 window = window_from_coordinates (f, x, y, &part, 0, 0, 1);
fa3c6b4d
KS
20614
20615 /* If we were displaying active text in another window, clear that. */
20616 if (! EQ (window, dpyinfo->mouse_face_window))
20617 clear_mouse_face (dpyinfo);
20618
20619 /* Not on a window -> return. */
20620 if (!WINDOWP (window))
20621 return;
20622
20623 /* Reset help_echo_string. It will get recomputed below. */
fa3c6b4d
KS
20624 help_echo_string = Qnil;
20625
20626 /* Convert to window-relative pixel coordinates. */
20627 w = XWINDOW (window);
20628 frame_to_window_pixel_xy (w, &x, &y);
20629
20630 /* Handle tool-bar window differently since it doesn't display a
20631 buffer. */
20632 if (EQ (window, f->tool_bar_window))
20633 {
20634 note_tool_bar_highlight (f, x, y);
20635 return;
20636 }
20637
fa3c6b4d
KS
20638 /* Mouse is on the mode, header line or margin? */
20639 if (part == ON_MODE_LINE || part == ON_HEADER_LINE
20640 || part == ON_LEFT_MARGIN || part == ON_RIGHT_MARGIN)
20641 {
20642 note_mode_line_or_margin_highlight (w, x, y, part);
20643 return;
20644 }
fa3c6b4d
KS
20645
20646 if (part == ON_VERTICAL_BORDER)
20647 cursor = FRAME_X_OUTPUT (f)->horizontal_drag_cursor;
6b61353c
KH
20648 else if (part == ON_LEFT_FRINGE || part == ON_RIGHT_FRINGE)
20649 cursor = FRAME_X_OUTPUT (f)->nontext_cursor;
fa3c6b4d
KS
20650 else
20651 cursor = FRAME_X_OUTPUT (f)->text_cursor;
20652
20653 /* Are we in a window whose display is up to date?
20654 And verify the buffer's text has not changed. */
20655 b = XBUFFER (w->buffer);
20656 if (part == ON_TEXT
20657 && EQ (w->window_end_valid, w->buffer)
20658 && XFASTINT (w->last_modified) == BUF_MODIFF (b)
20659 && XFASTINT (w->last_overlay_modified) == BUF_OVERLAY_MODIFF (b))
20660 {
6b61353c 20661 int hpos, vpos, pos, i, dx, dy, area;
fa3c6b4d
KS
20662 struct glyph *glyph;
20663 Lisp_Object object;
20664 Lisp_Object mouse_face = Qnil, overlay = Qnil, position;
20665 Lisp_Object *overlay_vec = NULL;
20666 int len, noverlays;
20667 struct buffer *obuf;
20668 int obegv, ozv, same_region;
20669
20670 /* Find the glyph under X/Y. */
6b61353c
KH
20671 glyph = x_y_to_hpos_vpos (w, x, y, &hpos, &vpos, &dx, &dy, &area);
20672
20673 /* Look for :pointer property on image. */
20674 if (glyph != NULL && glyph->type == IMAGE_GLYPH)
20675 {
20676 struct image *img = IMAGE_FROM_ID (f, glyph->u.img_id);
20677 if (img != NULL && IMAGEP (img->spec))
20678 {
20679 Lisp_Object image_map, hotspot;
20680 if ((image_map = Fplist_get (XCDR (img->spec), QCmap),
20681 !NILP (image_map))
20682 && (hotspot = find_hot_spot (image_map, dx, dy),
20683 CONSP (hotspot))
20684 && (hotspot = XCDR (hotspot), CONSP (hotspot)))
20685 {
20686 Lisp_Object area_id, plist;
20687
20688 area_id = XCAR (hotspot);
20689 /* Could check AREA_ID to see if we enter/leave this hot-spot.
20690 If so, we could look for mouse-enter, mouse-leave
20691 properties in PLIST (and do something...). */
20692 if ((plist = XCDR (hotspot), CONSP (plist)))
20693 {
20694 pointer = Fplist_get (plist, Qpointer);
20695 if (NILP (pointer))
20696 pointer = Qhand;
20697 help_echo_string = Fplist_get (plist, Qhelp_echo);
20698 if (!NILP (help_echo_string))
20699 {
20700 help_echo_window = window;
20701 help_echo_object = glyph->object;
20702 help_echo_pos = glyph->charpos;
20703 }
20704 }
20705 }
20706 if (NILP (pointer))
20707 pointer = Fplist_get (XCDR (img->spec), QCpointer);
20708 }
20709 }
fa3c6b4d
KS
20710
20711 /* Clear mouse face if X/Y not over text. */
20712 if (glyph == NULL
20713 || area != TEXT_AREA
20714 || !MATRIX_ROW (w->current_matrix, vpos)->displays_text_p)
20715 {
fa3c6b4d
KS
20716 if (clear_mouse_face (dpyinfo))
20717 cursor = No_Cursor;
6b61353c
KH
20718 if (NILP (pointer))
20719 {
20720 if (area != TEXT_AREA)
20721 cursor = FRAME_X_OUTPUT (f)->nontext_cursor;
20722 else
20723 pointer = Vvoid_text_area_pointer;
20724 }
fa3c6b4d
KS
20725 goto set_cursor;
20726 }
20727
20728 pos = glyph->charpos;
20729 object = glyph->object;
20730 if (!STRINGP (object) && !BUFFERP (object))
20731 goto set_cursor;
20732
20733 /* If we get an out-of-range value, return now; avoid an error. */
20734 if (BUFFERP (object) && pos > BUF_Z (b))
20735 goto set_cursor;
20736
20737 /* Make the window's buffer temporarily current for
20738 overlays_at and compute_char_face. */
20739 obuf = current_buffer;
20740 current_buffer = b;
20741 obegv = BEGV;
20742 ozv = ZV;
20743 BEGV = BEG;
20744 ZV = Z;
20745
20746 /* Is this char mouse-active or does it have help-echo? */
20747 position = make_number (pos);
20748
20749 if (BUFFERP (object))
20750 {
20751 /* Put all the overlays we want in a vector in overlay_vec.
20752 Store the length in len. If there are more than 10, make
20753 enough space for all, and try again. */
20754 len = 10;
20755 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
20756 noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL, 0);
20757 if (noverlays > len)
20758 {
20759 len = noverlays;
20760 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
20761 noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL,0);
20762 }
20763
20764 /* Sort overlays into increasing priority order. */
20765 noverlays = sort_overlays (overlay_vec, noverlays, w);
20766 }
20767 else
20768 noverlays = 0;
20769
20770 same_region = (EQ (window, dpyinfo->mouse_face_window)
20771 && vpos >= dpyinfo->mouse_face_beg_row
20772 && vpos <= dpyinfo->mouse_face_end_row
20773 && (vpos > dpyinfo->mouse_face_beg_row
20774 || hpos >= dpyinfo->mouse_face_beg_col)
20775 && (vpos < dpyinfo->mouse_face_end_row
20776 || hpos < dpyinfo->mouse_face_end_col
20777 || dpyinfo->mouse_face_past_end));
20778
20779 if (same_region)
20780 cursor = No_Cursor;
20781
20782 /* Check mouse-face highlighting. */
20783 if (! same_region
20784 /* If there exists an overlay with mouse-face overlapping
20785 the one we are currently highlighting, we have to
20786 check if we enter the overlapping overlay, and then
20787 highlight only that. */
20788 || (OVERLAYP (dpyinfo->mouse_face_overlay)
20789 && mouse_face_overlay_overlaps (dpyinfo->mouse_face_overlay)))
20790 {
20791 /* Find the highest priority overlay that has a mouse-face
20792 property. */
20793 overlay = Qnil;
20794 for (i = noverlays - 1; i >= 0 && NILP (overlay); --i)
20795 {
20796 mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face);
20797 if (!NILP (mouse_face))
20798 overlay = overlay_vec[i];
20799 }
20800
20801 /* If we're actually highlighting the same overlay as
20802 before, there's no need to do that again. */
20803 if (!NILP (overlay)
20804 && EQ (overlay, dpyinfo->mouse_face_overlay))
20805 goto check_help_echo;
20806
20807 dpyinfo->mouse_face_overlay = overlay;
20808
20809 /* Clear the display of the old active region, if any. */
20810 if (clear_mouse_face (dpyinfo))
20811 cursor = No_Cursor;
20812
20813 /* If no overlay applies, get a text property. */
20814 if (NILP (overlay))
20815 mouse_face = Fget_text_property (position, Qmouse_face, object);
20816
20817 /* Handle the overlay case. */
20818 if (!NILP (overlay))
20819 {
20820 /* Find the range of text around this char that
20821 should be active. */
20822 Lisp_Object before, after;
20823 int ignore;
20824
20825 before = Foverlay_start (overlay);
20826 after = Foverlay_end (overlay);
20827 /* Record this as the current active region. */
20828 fast_find_position (w, XFASTINT (before),
20829 &dpyinfo->mouse_face_beg_col,
20830 &dpyinfo->mouse_face_beg_row,
20831 &dpyinfo->mouse_face_beg_x,
20832 &dpyinfo->mouse_face_beg_y, Qnil);
20833
20834 dpyinfo->mouse_face_past_end
20835 = !fast_find_position (w, XFASTINT (after),
20836 &dpyinfo->mouse_face_end_col,
20837 &dpyinfo->mouse_face_end_row,
20838 &dpyinfo->mouse_face_end_x,
20839 &dpyinfo->mouse_face_end_y, Qnil);
20840 dpyinfo->mouse_face_window = window;
20841
20842 dpyinfo->mouse_face_face_id
20843 = face_at_buffer_position (w, pos, 0, 0,
20844 &ignore, pos + 1,
20845 !dpyinfo->mouse_face_hidden);
20846
20847 /* Display it as active. */
20848 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
20849 cursor = No_Cursor;
20850 }
20851 /* Handle the text property case. */
20852 else if (!NILP (mouse_face) && BUFFERP (object))
20853 {
20854 /* Find the range of text around this char that
20855 should be active. */
20856 Lisp_Object before, after, beginning, end;
20857 int ignore;
20858
20859 beginning = Fmarker_position (w->start);
20860 end = make_number (BUF_Z (XBUFFER (object))
20861 - XFASTINT (w->window_end_pos));
20862 before
20863 = Fprevious_single_property_change (make_number (pos + 1),
20864 Qmouse_face,
20865 object, beginning);
20866 after
20867 = Fnext_single_property_change (position, Qmouse_face,
20868 object, end);
20869
20870 /* Record this as the current active region. */
20871 fast_find_position (w, XFASTINT (before),
20872 &dpyinfo->mouse_face_beg_col,
20873 &dpyinfo->mouse_face_beg_row,
20874 &dpyinfo->mouse_face_beg_x,
20875 &dpyinfo->mouse_face_beg_y, Qnil);
20876 dpyinfo->mouse_face_past_end
20877 = !fast_find_position (w, XFASTINT (after),
20878 &dpyinfo->mouse_face_end_col,
20879 &dpyinfo->mouse_face_end_row,
20880 &dpyinfo->mouse_face_end_x,
20881 &dpyinfo->mouse_face_end_y, Qnil);
20882 dpyinfo->mouse_face_window = window;
20883
20884 if (BUFFERP (object))
20885 dpyinfo->mouse_face_face_id
20886 = face_at_buffer_position (w, pos, 0, 0,
20887 &ignore, pos + 1,
20888 !dpyinfo->mouse_face_hidden);
20889
20890 /* Display it as active. */
20891 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
20892 cursor = No_Cursor;
20893 }
20894 else if (!NILP (mouse_face) && STRINGP (object))
20895 {
20896 Lisp_Object b, e;
20897 int ignore;
20898
20899 b = Fprevious_single_property_change (make_number (pos + 1),
20900 Qmouse_face,
20901 object, Qnil);
20902 e = Fnext_single_property_change (position, Qmouse_face,
20903 object, Qnil);
20904 if (NILP (b))
20905 b = make_number (0);
20906 if (NILP (e))
20907 e = make_number (SCHARS (object) - 1);
20908 fast_find_string_pos (w, XINT (b), object,
20909 &dpyinfo->mouse_face_beg_col,
20910 &dpyinfo->mouse_face_beg_row,
20911 &dpyinfo->mouse_face_beg_x,
20912 &dpyinfo->mouse_face_beg_y, 0);
20913 fast_find_string_pos (w, XINT (e), object,
20914 &dpyinfo->mouse_face_end_col,
20915 &dpyinfo->mouse_face_end_row,
20916 &dpyinfo->mouse_face_end_x,
20917 &dpyinfo->mouse_face_end_y, 1);
20918 dpyinfo->mouse_face_past_end = 0;
20919 dpyinfo->mouse_face_window = window;
20920 dpyinfo->mouse_face_face_id
20921 = face_at_string_position (w, object, pos, 0, 0, 0, &ignore,
20922 glyph->face_id, 1);
20923 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
20924 cursor = No_Cursor;
20925 }
20926 else if (STRINGP (object) && NILP (mouse_face))
20927 {
20928 /* A string which doesn't have mouse-face, but
20929 the text ``under'' it might have. */
20930 struct glyph_row *r = MATRIX_ROW (w->current_matrix, vpos);
20931 int start = MATRIX_ROW_START_CHARPOS (r);
20932
20933 pos = string_buffer_position (w, object, start);
20934 if (pos > 0)
20935 mouse_face = get_char_property_and_overlay (make_number (pos),
20936 Qmouse_face,
20937 w->buffer,
20938 &overlay);
20939 if (!NILP (mouse_face) && !NILP (overlay))
20940 {
20941 Lisp_Object before = Foverlay_start (overlay);
20942 Lisp_Object after = Foverlay_end (overlay);
20943 int ignore;
20944
20945 /* Note that we might not be able to find position
20946 BEFORE in the glyph matrix if the overlay is
20947 entirely covered by a `display' property. In
20948 this case, we overshoot. So let's stop in
20949 the glyph matrix before glyphs for OBJECT. */
20950 fast_find_position (w, XFASTINT (before),
20951 &dpyinfo->mouse_face_beg_col,
20952 &dpyinfo->mouse_face_beg_row,
20953 &dpyinfo->mouse_face_beg_x,
20954 &dpyinfo->mouse_face_beg_y,
20955 object);
20956
20957 dpyinfo->mouse_face_past_end
20958 = !fast_find_position (w, XFASTINT (after),
20959 &dpyinfo->mouse_face_end_col,
20960 &dpyinfo->mouse_face_end_row,
20961 &dpyinfo->mouse_face_end_x,
20962 &dpyinfo->mouse_face_end_y,
20963 Qnil);
20964 dpyinfo->mouse_face_window = window;
20965 dpyinfo->mouse_face_face_id
20966 = face_at_buffer_position (w, pos, 0, 0,
20967 &ignore, pos + 1,
20968 !dpyinfo->mouse_face_hidden);
20969
20970 /* Display it as active. */
20971 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
20972 cursor = No_Cursor;
20973 }
20974 }
20975 }
20976
20977 check_help_echo:
20978
20979 /* Look for a `help-echo' property. */
6b61353c 20980 if (NILP (help_echo_string)) {
fa3c6b4d
KS
20981 Lisp_Object help, overlay;
20982
20983 /* Check overlays first. */
20984 help = overlay = Qnil;
20985 for (i = noverlays - 1; i >= 0 && NILP (help); --i)
20986 {
20987 overlay = overlay_vec[i];
20988 help = Foverlay_get (overlay, Qhelp_echo);
20989 }
20990
20991 if (!NILP (help))
20992 {
20993 help_echo_string = help;
20994 help_echo_window = window;
20995 help_echo_object = overlay;
20996 help_echo_pos = pos;
20997 }
20998 else
20999 {
21000 Lisp_Object object = glyph->object;
21001 int charpos = glyph->charpos;
21002
21003 /* Try text properties. */
21004 if (STRINGP (object)
21005 && charpos >= 0
21006 && charpos < SCHARS (object))
21007 {
21008 help = Fget_text_property (make_number (charpos),
21009 Qhelp_echo, object);
21010 if (NILP (help))
21011 {
21012 /* If the string itself doesn't specify a help-echo,
21013 see if the buffer text ``under'' it does. */
21014 struct glyph_row *r
21015 = MATRIX_ROW (w->current_matrix, vpos);
21016 int start = MATRIX_ROW_START_CHARPOS (r);
21017 int pos = string_buffer_position (w, object, start);
21018 if (pos > 0)
21019 {
21020 help = Fget_char_property (make_number (pos),
21021 Qhelp_echo, w->buffer);
21022 if (!NILP (help))
21023 {
21024 charpos = pos;
21025 object = w->buffer;
21026 }
21027 }
21028 }
21029 }
21030 else if (BUFFERP (object)
21031 && charpos >= BEGV
21032 && charpos < ZV)
21033 help = Fget_text_property (make_number (charpos), Qhelp_echo,
21034 object);
21035
21036 if (!NILP (help))
21037 {
21038 help_echo_string = help;
21039 help_echo_window = window;
21040 help_echo_object = object;
21041 help_echo_pos = charpos;
21042 }
21043 }
21044 }
21045
6b61353c
KH
21046 /* Look for a `pointer' property. */
21047 if (NILP (pointer))
21048 {
21049 /* Check overlays first. */
21050 for (i = noverlays - 1; i >= 0 && NILP (pointer); --i)
21051 pointer = Foverlay_get (overlay_vec[i], Qpointer);
21052
21053 if (NILP (pointer))
21054 {
21055 Lisp_Object object = glyph->object;
21056 int charpos = glyph->charpos;
21057
21058 /* Try text properties. */
21059 if (STRINGP (object)
21060 && charpos >= 0
21061 && charpos < SCHARS (object))
21062 {
21063 pointer = Fget_text_property (make_number (charpos),
21064 Qpointer, object);
21065 if (NILP (pointer))
21066 {
21067 /* If the string itself doesn't specify a pointer,
21068 see if the buffer text ``under'' it does. */
21069 struct glyph_row *r
21070 = MATRIX_ROW (w->current_matrix, vpos);
21071 int start = MATRIX_ROW_START_CHARPOS (r);
21072 int pos = string_buffer_position (w, object, start);
21073 if (pos > 0)
21074 pointer = Fget_char_property (make_number (pos),
21075 Qpointer, w->buffer);
21076 }
21077 }
21078 else if (BUFFERP (object)
21079 && charpos >= BEGV
21080 && charpos < ZV)
21081 pointer = Fget_text_property (make_number (charpos),
21082 Qpointer, object);
21083 }
21084 }
21085
fa3c6b4d
KS
21086 BEGV = obegv;
21087 ZV = ozv;
21088 current_buffer = obuf;
21089 }
21090
21091 set_cursor:
21092
6b61353c 21093 define_frame_cursor1 (f, cursor, pointer);
fa3c6b4d
KS
21094}
21095
21096
21097/* EXPORT for RIF:
21098 Clear any mouse-face on window W. This function is part of the
21099 redisplay interface, and is called from try_window_id and similar
21100 functions to ensure the mouse-highlight is off. */
21101
21102void
21103x_clear_window_mouse_face (w)
21104 struct window *w;
21105{
21106 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (XFRAME (w->frame));
21107 Lisp_Object window;
21108
21109 BLOCK_INPUT;
21110 XSETWINDOW (window, w);
21111 if (EQ (window, dpyinfo->mouse_face_window))
21112 clear_mouse_face (dpyinfo);
21113 UNBLOCK_INPUT;
21114}
21115
21116
21117/* EXPORT:
21118 Just discard the mouse face information for frame F, if any.
21119 This is used when the size of F is changed. */
21120
21121void
21122cancel_mouse_face (f)
21123 struct frame *f;
21124{
21125 Lisp_Object window;
21126 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
21127
21128 window = dpyinfo->mouse_face_window;
21129 if (! NILP (window) && XFRAME (XWINDOW (window)->frame) == f)
21130 {
21131 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
21132 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
21133 dpyinfo->mouse_face_window = Qnil;
21134 }
21135}
21136
21137
21138#endif /* HAVE_WINDOW_SYSTEM */
21139
21140\f
21141/***********************************************************************
21142 Exposure Events
21143 ***********************************************************************/
21144
21145#ifdef HAVE_WINDOW_SYSTEM
21146
21147/* Redraw the part of glyph row area AREA of glyph row ROW on window W
21148 which intersects rectangle R. R is in window-relative coordinates. */
21149
21150static void
21151expose_area (w, row, r, area)
21152 struct window *w;
21153 struct glyph_row *row;
21154 XRectangle *r;
21155 enum glyph_row_area area;
21156{
21157 struct glyph *first = row->glyphs[area];
21158 struct glyph *end = row->glyphs[area] + row->used[area];
21159 struct glyph *last;
21160 int first_x, start_x, x;
21161
21162 if (area == TEXT_AREA && row->fill_line_p)
21163 /* If row extends face to end of line write the whole line. */
21164 draw_glyphs (w, 0, row, area,
21165 0, row->used[area],
21166 DRAW_NORMAL_TEXT, 0);
21167 else
21168 {
21169 /* Set START_X to the window-relative start position for drawing glyphs of
21170 AREA. The first glyph of the text area can be partially visible.
21171 The first glyphs of other areas cannot. */
da8b7f4f 21172 start_x = window_box_left_offset (w, area);
fa3c6b4d 21173 x = start_x;
6b61353c
KH
21174 if (area == TEXT_AREA)
21175 x += row->x;
fa3c6b4d
KS
21176
21177 /* Find the first glyph that must be redrawn. */
21178 while (first < end
21179 && x + first->pixel_width < r->x)
21180 {
21181 x += first->pixel_width;
21182 ++first;
21183 }
21184
21185 /* Find the last one. */
21186 last = first;
21187 first_x = x;
21188 while (last < end
21189 && x < r->x + r->width)
21190 {
21191 x += last->pixel_width;
21192 ++last;
21193 }
21194
21195 /* Repaint. */
21196 if (last > first)
21197 draw_glyphs (w, first_x - start_x, row, area,
21198 first - row->glyphs[area], last - row->glyphs[area],
21199 DRAW_NORMAL_TEXT, 0);
21200 }
21201}
21202
21203
21204/* Redraw the parts of the glyph row ROW on window W intersecting
21205 rectangle R. R is in window-relative coordinates. Value is
21206 non-zero if mouse-face was overwritten. */
21207
21208static int
21209expose_line (w, row, r)
21210 struct window *w;
21211 struct glyph_row *row;
21212 XRectangle *r;
21213{
21214 xassert (row->enabled_p);
21215
21216 if (row->mode_line_p || w->pseudo_window_p)
21217 draw_glyphs (w, 0, row, TEXT_AREA,
21218 0, row->used[TEXT_AREA],
21219 DRAW_NORMAL_TEXT, 0);
21220 else
21221 {
21222 if (row->used[LEFT_MARGIN_AREA])
21223 expose_area (w, row, r, LEFT_MARGIN_AREA);
21224 if (row->used[TEXT_AREA])
21225 expose_area (w, row, r, TEXT_AREA);
21226 if (row->used[RIGHT_MARGIN_AREA])
21227 expose_area (w, row, r, RIGHT_MARGIN_AREA);
21228 draw_row_fringe_bitmaps (w, row);
cfe03a41
KS
21229 }
21230
fa3c6b4d
KS
21231 return row->mouse_face_p;
21232}
21233
21234
21235/* Redraw those parts of glyphs rows during expose event handling that
21236 overlap other rows. Redrawing of an exposed line writes over parts
21237 of lines overlapping that exposed line; this function fixes that.
21238
21239 W is the window being exposed. FIRST_OVERLAPPING_ROW is the first
21240 row in W's current matrix that is exposed and overlaps other rows.
21241 LAST_OVERLAPPING_ROW is the last such row. */
21242
21243static void
21244expose_overlaps (w, first_overlapping_row, last_overlapping_row)
21245 struct window *w;
21246 struct glyph_row *first_overlapping_row;
21247 struct glyph_row *last_overlapping_row;
21248{
21249 struct glyph_row *row;
21250
21251 for (row = first_overlapping_row; row <= last_overlapping_row; ++row)
21252 if (row->overlapping_p)
21253 {
21254 xassert (row->enabled_p && !row->mode_line_p);
21255
21256 if (row->used[LEFT_MARGIN_AREA])
21257 x_fix_overlapping_area (w, row, LEFT_MARGIN_AREA);
cfe03a41 21258
fa3c6b4d
KS
21259 if (row->used[TEXT_AREA])
21260 x_fix_overlapping_area (w, row, TEXT_AREA);
21261
21262 if (row->used[RIGHT_MARGIN_AREA])
21263 x_fix_overlapping_area (w, row, RIGHT_MARGIN_AREA);
21264 }
21265}
21266
21267
21268/* Return non-zero if W's cursor intersects rectangle R. */
21269
21270static int
21271phys_cursor_in_rect_p (w, r)
21272 struct window *w;
21273 XRectangle *r;
21274{
21275 XRectangle cr, result;
21276 struct glyph *cursor_glyph;
21277
21278 cursor_glyph = get_phys_cursor_glyph (w);
21279 if (cursor_glyph)
cfe03a41 21280 {
6b61353c 21281 /* r is relative to W's box, but w->phys_cursor.x is relative
aecf50d2
KS
21282 to left edge of W's TEXT area. Adjust it. */
21283 cr.x = window_box_left_offset (w, TEXT_AREA) + w->phys_cursor.x;
fa3c6b4d
KS
21284 cr.y = w->phys_cursor.y;
21285 cr.width = cursor_glyph->pixel_width;
21286 cr.height = w->phys_cursor_height;
6b61353c 21287 /* ++KFS: W32 version used W32-specific IntersectRect here, but
fa3c6b4d
KS
21288 I assume the effect is the same -- and this is portable. */
21289 return x_intersect_rectangles (&cr, r, &result);
cfe03a41 21290 }
fa3c6b4d
KS
21291 else
21292 return 0;
21293}
cfe03a41 21294
cfe03a41 21295
fa3c6b4d
KS
21296/* EXPORT:
21297 Draw a vertical window border to the right of window W if W doesn't
21298 have vertical scroll bars. */
cfe03a41 21299
cfe03a41 21300void
fa3c6b4d
KS
21301x_draw_vertical_border (w)
21302 struct window *w;
cfe03a41 21303{
da8b7f4f 21304 /* We could do better, if we knew what type of scroll-bar the adjacent
6b61353c 21305 windows (on either side) have... But we don't :-(
da8b7f4f
KS
21306 However, I think this works ok. ++KFS 2003-04-25 */
21307
fa3c6b4d
KS
21308 /* Redraw borders between horizontally adjacent windows. Don't
21309 do it for frames with vertical scroll bars because either the
21310 right scroll bar of a window, or the left scroll bar of its
21311 neighbor will suffice as a border. */
21312 if (!WINDOW_RIGHTMOST_P (w)
da8b7f4f 21313 && !WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w))
fa3c6b4d
KS
21314 {
21315 int x0, x1, y0, y1;
cfe03a41 21316
fa3c6b4d 21317 window_box_edges (w, -1, &x0, &y0, &x1, &y1);
fa3c6b4d 21318 y1 -= 1;
cfe03a41 21319
fa3c6b4d 21320 rif->draw_vertical_window_border (w, x1, y0, y1);
cfe03a41 21321 }
da8b7f4f
KS
21322 else if (!WINDOW_LEFTMOST_P (w)
21323 && !WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w))
21324 {
21325 int x0, x1, y0, y1;
21326
21327 window_box_edges (w, -1, &x0, &y0, &x1, &y1);
21328 y1 -= 1;
21329
21330 rif->draw_vertical_window_border (w, x0, y0, y1);
21331 }
cfe03a41
KS
21332}
21333
21334
fa3c6b4d
KS
21335/* Redraw the part of window W intersection rectangle FR. Pixel
21336 coordinates in FR are frame-relative. Call this function with
21337 input blocked. Value is non-zero if the exposure overwrites
21338 mouse-face. */
cfe03a41 21339
fa3c6b4d
KS
21340static int
21341expose_window (w, fr)
cfe03a41 21342 struct window *w;
fa3c6b4d 21343 XRectangle *fr;
cfe03a41
KS
21344{
21345 struct frame *f = XFRAME (w->frame);
fa3c6b4d
KS
21346 XRectangle wr, r;
21347 int mouse_face_overwritten_p = 0;
21348
21349 /* If window is not yet fully initialized, do nothing. This can
21350 happen when toolkit scroll bars are used and a window is split.
21351 Reconfiguring the scroll bar will generate an expose for a newly
21352 created window. */
21353 if (w->current_matrix == NULL)
21354 return 0;
cfe03a41 21355
fa3c6b4d
KS
21356 /* When we're currently updating the window, display and current
21357 matrix usually don't agree. Arrange for a thorough display
21358 later. */
21359 if (w == updated_window)
21360 {
21361 SET_FRAME_GARBAGED (f);
21362 return 0;
21363 }
e9c99027 21364
fa3c6b4d 21365 /* Frame-relative pixel rectangle of W. */
da8b7f4f
KS
21366 wr.x = WINDOW_LEFT_EDGE_X (w);
21367 wr.y = WINDOW_TOP_EDGE_Y (w);
21368 wr.width = WINDOW_TOTAL_WIDTH (w);
21369 wr.height = WINDOW_TOTAL_HEIGHT (w);
fa3c6b4d
KS
21370
21371 if (x_intersect_rectangles (fr, &wr, &r))
cfe03a41 21372 {
fa3c6b4d
KS
21373 int yb = window_text_bottom_y (w);
21374 struct glyph_row *row;
21375 int cursor_cleared_p;
21376 struct glyph_row *first_overlapping_row, *last_overlapping_row;
21377
21378 TRACE ((stderr, "expose_window (%d, %d, %d, %d)\n",
21379 r.x, r.y, r.width, r.height));
21380
21381 /* Convert to window coordinates. */
cc8549df
KS
21382 r.x -= WINDOW_LEFT_EDGE_X (w);
21383 r.y -= WINDOW_TOP_EDGE_Y (w);
fa3c6b4d
KS
21384
21385 /* Turn off the cursor. */
21386 if (!w->pseudo_window_p
21387 && phys_cursor_in_rect_p (w, &r))
cfe03a41 21388 {
fa3c6b4d
KS
21389 x_clear_cursor (w);
21390 cursor_cleared_p = 1;
cfe03a41 21391 }
fa3c6b4d
KS
21392 else
21393 cursor_cleared_p = 0;
cfe03a41 21394
fa3c6b4d
KS
21395 /* Update lines intersecting rectangle R. */
21396 first_overlapping_row = last_overlapping_row = NULL;
21397 for (row = w->current_matrix->rows;
21398 row->enabled_p;
21399 ++row)
21400 {
21401 int y0 = row->y;
21402 int y1 = MATRIX_ROW_BOTTOM_Y (row);
cfe03a41 21403
fa3c6b4d
KS
21404 if ((y0 >= r.y && y0 < r.y + r.height)
21405 || (y1 > r.y && y1 < r.y + r.height)
21406 || (r.y >= y0 && r.y < y1)
21407 || (r.y + r.height > y0 && r.y + r.height < y1))
21408 {
21409 if (row->overlapping_p)
21410 {
21411 if (first_overlapping_row == NULL)
21412 first_overlapping_row = row;
21413 last_overlapping_row = row;
21414 }
e9c99027 21415
fa3c6b4d
KS
21416 if (expose_line (w, row, &r))
21417 mouse_face_overwritten_p = 1;
21418 }
cfe03a41 21419
fa3c6b4d
KS
21420 if (y1 >= yb)
21421 break;
21422 }
cfe03a41 21423
fa3c6b4d
KS
21424 /* Display the mode line if there is one. */
21425 if (WINDOW_WANTS_MODELINE_P (w)
21426 && (row = MATRIX_MODE_LINE_ROW (w->current_matrix),
21427 row->enabled_p)
21428 && row->y < r.y + r.height)
21429 {
21430 if (expose_line (w, row, &r))
21431 mouse_face_overwritten_p = 1;
21432 }
cfe03a41 21433
fa3c6b4d
KS
21434 if (!w->pseudo_window_p)
21435 {
21436 /* Fix the display of overlapping rows. */
21437 if (first_overlapping_row)
21438 expose_overlaps (w, first_overlapping_row, last_overlapping_row);
21439
21440 /* Draw border between windows. */
21441 x_draw_vertical_border (w);
21442
21443 /* Turn the cursor on again. */
21444 if (cursor_cleared_p)
21445 update_window_cursor (w, 1);
21446 }
21447 }
21448
21449#ifdef HAVE_CARBON
21450 /* Display scroll bar for this window. */
21451 if (!NILP (w->vertical_scroll_bar))
cfe03a41 21452 {
fa3c6b4d
KS
21453 /* ++KFS:
21454 If this doesn't work here (maybe some header files are missing),
21455 make a function in macterm.c and call it to do the job! */
21456 ControlHandle ch
21457 = SCROLL_BAR_CONTROL_HANDLE (XSCROLL_BAR (w->vertical_scroll_bar));
21458
21459 Draw1Control (ch);
cfe03a41 21460 }
fa3c6b4d 21461#endif
cfe03a41 21462
fa3c6b4d
KS
21463 return mouse_face_overwritten_p;
21464}
21465
21466
21467
21468/* Redraw (parts) of all windows in the window tree rooted at W that
21469 intersect R. R contains frame pixel coordinates. Value is
21470 non-zero if the exposure overwrites mouse-face. */
21471
21472static int
21473expose_window_tree (w, r)
21474 struct window *w;
21475 XRectangle *r;
21476{
21477 struct frame *f = XFRAME (w->frame);
21478 int mouse_face_overwritten_p = 0;
21479
21480 while (w && !FRAME_GARBAGED_P (f))
cfe03a41 21481 {
fa3c6b4d
KS
21482 if (!NILP (w->hchild))
21483 mouse_face_overwritten_p
21484 |= expose_window_tree (XWINDOW (w->hchild), r);
21485 else if (!NILP (w->vchild))
21486 mouse_face_overwritten_p
21487 |= expose_window_tree (XWINDOW (w->vchild), r);
21488 else
21489 mouse_face_overwritten_p |= expose_window (w, r);
21490
21491 w = NILP (w->next) ? NULL : XWINDOW (w->next);
cfe03a41 21492 }
cfe03a41 21493
fa3c6b4d
KS
21494 return mouse_face_overwritten_p;
21495}
cfe03a41 21496
cfe03a41 21497
fa3c6b4d
KS
21498/* EXPORT:
21499 Redisplay an exposed area of frame F. X and Y are the upper-left
21500 corner of the exposed rectangle. W and H are width and height of
21501 the exposed area. All are pixel values. W or H zero means redraw
21502 the entire frame. */
cfe03a41 21503
fa3c6b4d
KS
21504void
21505expose_frame (f, x, y, w, h)
21506 struct frame *f;
21507 int x, y, w, h;
21508{
21509 XRectangle r;
21510 int mouse_face_overwritten_p = 0;
21511
21512 TRACE ((stderr, "expose_frame "));
21513
21514 /* No need to redraw if frame will be redrawn soon. */
21515 if (FRAME_GARBAGED_P (f))
cfe03a41 21516 {
fa3c6b4d
KS
21517 TRACE ((stderr, " garbaged\n"));
21518 return;
cfe03a41 21519 }
7d0393cf 21520
fa3c6b4d
KS
21521#ifdef HAVE_CARBON
21522 /* MAC_TODO: this is a kludge, but if scroll bars are not activated
21523 or deactivated here, for unknown reasons, activated scroll bars
21524 are shown in deactivated frames in some instances. */
21525 if (f == FRAME_MAC_DISPLAY_INFO (f)->x_focus_frame)
21526 activate_scroll_bars (f);
21527 else
21528 deactivate_scroll_bars (f);
21529#endif
cfe03a41 21530
fa3c6b4d
KS
21531 /* If basic faces haven't been realized yet, there is no point in
21532 trying to redraw anything. This can happen when we get an expose
21533 event while Emacs is starting, e.g. by moving another window. */
21534 if (FRAME_FACE_CACHE (f) == NULL
21535 || FRAME_FACE_CACHE (f)->used < BASIC_FACE_ID_SENTINEL)
21536 {
21537 TRACE ((stderr, " no faces\n"));
21538 return;
21539 }
cfe03a41 21540
fa3c6b4d 21541 if (w == 0 || h == 0)
cfe03a41 21542 {
fa3c6b4d 21543 r.x = r.y = 0;
da8b7f4f
KS
21544 r.width = FRAME_COLUMN_WIDTH (f) * FRAME_COLS (f);
21545 r.height = FRAME_LINE_HEIGHT (f) * FRAME_LINES (f);
fa3c6b4d
KS
21546 }
21547 else
21548 {
21549 r.x = x;
21550 r.y = y;
21551 r.width = w;
21552 r.height = h;
cfe03a41
KS
21553 }
21554
fa3c6b4d
KS
21555 TRACE ((stderr, "(%d, %d, %d, %d)\n", r.x, r.y, r.width, r.height));
21556 mouse_face_overwritten_p = expose_window_tree (XWINDOW (f->root_window), &r);
21557
21558 if (WINDOWP (f->tool_bar_window))
21559 mouse_face_overwritten_p
21560 |= expose_window (XWINDOW (f->tool_bar_window), &r);
21561
21562#ifdef HAVE_X_WINDOWS
21563#ifndef MSDOS
21564#ifndef USE_X_TOOLKIT
21565 if (WINDOWP (f->menu_bar_window))
21566 mouse_face_overwritten_p
21567 |= expose_window (XWINDOW (f->menu_bar_window), &r);
21568#endif /* not USE_X_TOOLKIT */
21569#endif
21570#endif
21571
21572 /* Some window managers support a focus-follows-mouse style with
21573 delayed raising of frames. Imagine a partially obscured frame,
21574 and moving the mouse into partially obscured mouse-face on that
21575 frame. The visible part of the mouse-face will be highlighted,
21576 then the WM raises the obscured frame. With at least one WM, KDE
21577 2.1, Emacs is not getting any event for the raising of the frame
21578 (even tried with SubstructureRedirectMask), only Expose events.
21579 These expose events will draw text normally, i.e. not
21580 highlighted. Which means we must redo the highlight here.
21581 Subsume it under ``we love X''. --gerd 2001-08-15 */
21582 /* Included in Windows version because Windows most likely does not
21583 do the right thing if any third party tool offers
21584 focus-follows-mouse with delayed raise. --jason 2001-10-12 */
21585 if (mouse_face_overwritten_p && !FRAME_GARBAGED_P (f))
21586 {
21587 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
21588 if (f == dpyinfo->mouse_face_mouse_frame)
21589 {
21590 int x = dpyinfo->mouse_face_mouse_x;
21591 int y = dpyinfo->mouse_face_mouse_y;
21592 clear_mouse_face (dpyinfo);
21593 note_mouse_highlight (f, x, y);
21594 }
21595 }
cfe03a41
KS
21596}
21597
133c764e 21598
fa3c6b4d
KS
21599/* EXPORT:
21600 Determine the intersection of two rectangles R1 and R2. Return
21601 the intersection in *RESULT. Value is non-zero if RESULT is not
21602 empty. */
133c764e 21603
fa3c6b4d
KS
21604int
21605x_intersect_rectangles (r1, r2, result)
21606 XRectangle *r1, *r2, *result;
133c764e 21607{
fa3c6b4d
KS
21608 XRectangle *left, *right;
21609 XRectangle *upper, *lower;
21610 int intersection_p = 0;
21611
21612 /* Rearrange so that R1 is the left-most rectangle. */
21613 if (r1->x < r2->x)
21614 left = r1, right = r2;
21615 else
21616 left = r2, right = r1;
21617
21618 /* X0 of the intersection is right.x0, if this is inside R1,
21619 otherwise there is no intersection. */
21620 if (right->x <= left->x + left->width)
133c764e 21621 {
fa3c6b4d 21622 result->x = right->x;
133c764e 21623
fa3c6b4d
KS
21624 /* The right end of the intersection is the minimum of the
21625 the right ends of left and right. */
21626 result->width = (min (left->x + left->width, right->x + right->width)
21627 - result->x);
133c764e 21628
fa3c6b4d
KS
21629 /* Same game for Y. */
21630 if (r1->y < r2->y)
21631 upper = r1, lower = r2;
21632 else
21633 upper = r2, lower = r1;
133c764e 21634
fa3c6b4d
KS
21635 /* The upper end of the intersection is lower.y0, if this is inside
21636 of upper. Otherwise, there is no intersection. */
21637 if (lower->y <= upper->y + upper->height)
21638 {
21639 result->y = lower->y;
21640
21641 /* The lower end of the intersection is the minimum of the lower
21642 ends of upper and lower. */
21643 result->height = (min (lower->y + lower->height,
21644 upper->y + upper->height)
21645 - result->y);
21646 intersection_p = 1;
133c764e
KS
21647 }
21648 }
fa3c6b4d
KS
21649
21650 return intersection_p;
133c764e
KS
21651}
21652
fa3c6b4d
KS
21653#endif /* HAVE_WINDOW_SYSTEM */
21654
cfe03a41 21655\f
5f5c8ee5
GM
21656/***********************************************************************
21657 Initialization
21658 ***********************************************************************/
21659
a2889657
JB
21660void
21661syms_of_xdisp ()
21662{
c6e89d6c
GM
21663 Vwith_echo_area_save_vector = Qnil;
21664 staticpro (&Vwith_echo_area_save_vector);
5f5c8ee5 21665
c6e89d6c
GM
21666 Vmessage_stack = Qnil;
21667 staticpro (&Vmessage_stack);
2311178e 21668
735c094c 21669 Qinhibit_redisplay = intern ("inhibit-redisplay");
c6e89d6c 21670 staticpro (&Qinhibit_redisplay);
735c094c 21671
b14bc55e
RS
21672 message_dolog_marker1 = Fmake_marker ();
21673 staticpro (&message_dolog_marker1);
21674 message_dolog_marker2 = Fmake_marker ();
21675 staticpro (&message_dolog_marker2);
21676 message_dolog_marker3 = Fmake_marker ();
21677 staticpro (&message_dolog_marker3);
21678
5f5c8ee5 21679#if GLYPH_DEBUG
7d4cc828 21680 defsubr (&Sdump_frame_glyph_matrix);
5f5c8ee5
GM
21681 defsubr (&Sdump_glyph_matrix);
21682 defsubr (&Sdump_glyph_row);
e037b9ec 21683 defsubr (&Sdump_tool_bar_row);
62397849 21684 defsubr (&Strace_redisplay);
bf9249e3 21685 defsubr (&Strace_to_stderr);
5f5c8ee5 21686#endif
99a5de87 21687#ifdef HAVE_WINDOW_SYSTEM
57c28064 21688 defsubr (&Stool_bar_lines_needed);
6b61353c 21689 defsubr (&Slookup_image_map);
99a5de87 21690#endif
8143e6ab 21691 defsubr (&Sformat_mode_line);
5f5c8ee5 21692
cf074754
RS
21693 staticpro (&Qmenu_bar_update_hook);
21694 Qmenu_bar_update_hook = intern ("menu-bar-update-hook");
21695
d46fb96a 21696 staticpro (&Qoverriding_terminal_local_map);
7079aefa 21697 Qoverriding_terminal_local_map = intern ("overriding-terminal-local-map");
d46fb96a 21698
399164b4
KH
21699 staticpro (&Qoverriding_local_map);
21700 Qoverriding_local_map = intern ("overriding-local-map");
21701
75c43375
RS
21702 staticpro (&Qwindow_scroll_functions);
21703 Qwindow_scroll_functions = intern ("window-scroll-functions");
21704
e0bfbde6
RS
21705 staticpro (&Qredisplay_end_trigger_functions);
21706 Qredisplay_end_trigger_functions = intern ("redisplay-end-trigger-functions");
2311178e 21707
2e54982e
RS
21708 staticpro (&Qinhibit_point_motion_hooks);
21709 Qinhibit_point_motion_hooks = intern ("inhibit-point-motion-hooks");
21710
9499d71b
GM
21711 QCdata = intern (":data");
21712 staticpro (&QCdata);
5f5c8ee5 21713 Qdisplay = intern ("display");
f3751a65 21714 staticpro (&Qdisplay);
5f5c8ee5
GM
21715 Qspace_width = intern ("space-width");
21716 staticpro (&Qspace_width);
5f5c8ee5
GM
21717 Qraise = intern ("raise");
21718 staticpro (&Qraise);
21719 Qspace = intern ("space");
21720 staticpro (&Qspace);
f3751a65
GM
21721 Qmargin = intern ("margin");
21722 staticpro (&Qmargin);
6b61353c
KH
21723 Qpointer = intern ("pointer");
21724 staticpro (&Qpointer);
5f5c8ee5 21725 Qleft_margin = intern ("left-margin");
f3751a65 21726 staticpro (&Qleft_margin);
5f5c8ee5 21727 Qright_margin = intern ("right-margin");
f3751a65 21728 staticpro (&Qright_margin);
6b61353c
KH
21729 Qcenter = intern ("center");
21730 staticpro (&Qcenter);
5f5c8ee5
GM
21731 QCalign_to = intern (":align-to");
21732 staticpro (&QCalign_to);
5f5c8ee5
GM
21733 QCrelative_width = intern (":relative-width");
21734 staticpro (&QCrelative_width);
21735 QCrelative_height = intern (":relative-height");
21736 staticpro (&QCrelative_height);
21737 QCeval = intern (":eval");
21738 staticpro (&QCeval);
0fcf414f
RS
21739 QCpropertize = intern (":propertize");
21740 staticpro (&QCpropertize);
886bd6f2
GM
21741 QCfile = intern (":file");
21742 staticpro (&QCfile);
5f5c8ee5
GM
21743 Qfontified = intern ("fontified");
21744 staticpro (&Qfontified);
21745 Qfontification_functions = intern ("fontification-functions");
21746 staticpro (&Qfontification_functions);
5f5c8ee5
GM
21747 Qtrailing_whitespace = intern ("trailing-whitespace");
21748 staticpro (&Qtrailing_whitespace);
21749 Qimage = intern ("image");
21750 staticpro (&Qimage);
6b61353c
KH
21751 QCmap = intern (":map");
21752 staticpro (&QCmap);
21753 QCpointer = intern (":pointer");
21754 staticpro (&QCpointer);
21755 Qrect = intern ("rect");
21756 staticpro (&Qrect);
21757 Qcircle = intern ("circle");
21758 staticpro (&Qcircle);
21759 Qpoly = intern ("poly");
21760 staticpro (&Qpoly);
ad4f174e
GM
21761 Qmessage_truncate_lines = intern ("message-truncate-lines");
21762 staticpro (&Qmessage_truncate_lines);
af79bccb
RS
21763 Qcursor_in_non_selected_windows = intern ("cursor-in-non-selected-windows");
21764 staticpro (&Qcursor_in_non_selected_windows);
6422c1d7
GM
21765 Qgrow_only = intern ("grow-only");
21766 staticpro (&Qgrow_only);
e1477f43
GM
21767 Qinhibit_menubar_update = intern ("inhibit-menubar-update");
21768 staticpro (&Qinhibit_menubar_update);
30a3f61c
GM
21769 Qinhibit_eval_during_redisplay = intern ("inhibit-eval-during-redisplay");
21770 staticpro (&Qinhibit_eval_during_redisplay);
b384d6f8
GM
21771 Qposition = intern ("position");
21772 staticpro (&Qposition);
21773 Qbuffer_position = intern ("buffer-position");
21774 staticpro (&Qbuffer_position);
21775 Qobject = intern ("object");
21776 staticpro (&Qobject);
cfe03a41
KS
21777 Qbar = intern ("bar");
21778 staticpro (&Qbar);
21779 Qhbar = intern ("hbar");
21780 staticpro (&Qhbar);
21781 Qbox = intern ("box");
21782 staticpro (&Qbox);
21783 Qhollow = intern ("hollow");
21784 staticpro (&Qhollow);
6b61353c
KH
21785 Qhand = intern ("hand");
21786 staticpro (&Qhand);
21787 Qarrow = intern ("arrow");
21788 staticpro (&Qarrow);
21789 Qtext = intern ("text");
21790 staticpro (&Qtext);
c53a1624
RS
21791 Qrisky_local_variable = intern ("risky-local-variable");
21792 staticpro (&Qrisky_local_variable);
26683087
RS
21793 Qinhibit_free_realized_faces = intern ("inhibit-free-realized-faces");
21794 staticpro (&Qinhibit_free_realized_faces);
5f5c8ee5 21795
6b61353c
KH
21796 list_of_error = Fcons (Fcons (intern ("error"),
21797 Fcons (intern ("void-variable"), Qnil)),
21798 Qnil);
7033d6df
RS
21799 staticpro (&list_of_error);
21800
6b61353c
KH
21801 Qlast_arrow_position = intern ("last-arrow-position");
21802 staticpro (&Qlast_arrow_position);
21803 Qlast_arrow_string = intern ("last-arrow-string");
21804 staticpro (&Qlast_arrow_string);
21805
21806 Qoverlay_arrow_string = intern ("overlay-arrow-string");
21807 staticpro (&Qoverlay_arrow_string);
21808 Qoverlay_arrow_bitmap = intern ("overlay-arrow-bitmap");
21809 staticpro (&Qoverlay_arrow_bitmap);
2311178e 21810
c6e89d6c
GM
21811 echo_buffer[0] = echo_buffer[1] = Qnil;
21812 staticpro (&echo_buffer[0]);
21813 staticpro (&echo_buffer[1]);
21814
21815 echo_area_buffer[0] = echo_area_buffer[1] = Qnil;
21816 staticpro (&echo_area_buffer[0]);
21817 staticpro (&echo_area_buffer[1]);
a2889657 21818
6a94510a
GM
21819 Vmessages_buffer_name = build_string ("*Messages*");
21820 staticpro (&Vmessages_buffer_name);
0fcf414f
RS
21821
21822 mode_line_proptrans_alist = Qnil;
21823 staticpro (&mode_line_proptrans_alist);
2311178e 21824
fec8f23e
KS
21825 mode_line_string_list = Qnil;
21826 staticpro (&mode_line_string_list);
21827
fa3c6b4d
KS
21828 help_echo_string = Qnil;
21829 staticpro (&help_echo_string);
21830 help_echo_object = Qnil;
21831 staticpro (&help_echo_object);
21832 help_echo_window = Qnil;
21833 staticpro (&help_echo_window);
21834 previous_help_echo_string = Qnil;
21835 staticpro (&previous_help_echo_string);
21836 help_echo_pos = -1;
21837
21838#ifdef HAVE_WINDOW_SYSTEM
21839 DEFVAR_BOOL ("x-stretch-cursor", &x_stretch_cursor_p,
21840 doc: /* *Non-nil means draw block cursor as wide as the glyph under it.
21841For example, if a block cursor is over a tab, it will be drawn as
21842wide as that tab on the display. */);
21843 x_stretch_cursor_p = 0;
21844#endif
21845
7ee72033 21846 DEFVAR_LISP ("show-trailing-whitespace", &Vshow_trailing_whitespace,
6b61353c 21847 doc: /* *Non-nil means highlight trailing whitespace.
228299fa 21848The face used for trailing whitespace is `trailing-whitespace'. */);
8f897821
GM
21849 Vshow_trailing_whitespace = Qnil;
21850
6b61353c
KH
21851 DEFVAR_LISP ("void-text-area-pointer", &Vvoid_text_area_pointer,
21852 doc: /* *The pointer shape to show in void text areas.
21853Nil means to show the text pointer. Other options are `arrow', `text',
21854`hand', `vdrag', `hdrag', `modeline', and `hourglass'. */);
21855 Vvoid_text_area_pointer = Qarrow;
21856
7ee72033
MB
21857 DEFVAR_LISP ("inhibit-redisplay", &Vinhibit_redisplay,
21858 doc: /* Non-nil means don't actually do any redisplay.
228299fa 21859This is used for internal purposes. */);
735c094c
KH
21860 Vinhibit_redisplay = Qnil;
21861
7ee72033
MB
21862 DEFVAR_LISP ("global-mode-string", &Vglobal_mode_string,
21863 doc: /* String (or mode line construct) included (normally) in `mode-line-format'. */);
a2889657
JB
21864 Vglobal_mode_string = Qnil;
21865
7ee72033
MB
21866 DEFVAR_LISP ("overlay-arrow-position", &Voverlay_arrow_position,
21867 doc: /* Marker for where to display an arrow on top of the buffer text.
228299fa
GM
21868This must be the beginning of a line in order to work.
21869See also `overlay-arrow-string'. */);
a2889657
JB
21870 Voverlay_arrow_position = Qnil;
21871
7ee72033 21872 DEFVAR_LISP ("overlay-arrow-string", &Voverlay_arrow_string,
6b61353c
KH
21873 doc: /* String to display as an arrow in non-window frames.
21874See also `overlay-arrow-position'. */);
a2889657
JB
21875 Voverlay_arrow_string = Qnil;
21876
6b61353c
KH
21877 DEFVAR_LISP ("overlay-arrow-variable-list", &Voverlay_arrow_variable_list,
21878 doc: /* List of variables (symbols) which hold markers for overlay arrows.
21879The symbols on this list are examined during redisplay to determine
21880where to display overlay arrows. */);
21881 Voverlay_arrow_variable_list
21882 = Fcons (intern ("overlay-arrow-position"), Qnil);
21883
7ee72033
MB
21884 DEFVAR_INT ("scroll-step", &scroll_step,
21885 doc: /* *The number of lines to try scrolling a window by when point moves out.
228299fa
GM
21886If that fails to bring point back on frame, point is centered instead.
21887If this is zero, point is always centered after it moves off frame.
21888If you want scrolling to always be a line at a time, you should set
21889`scroll-conservatively' to a large value rather than set this to 1. */);
21890
7ee72033
MB
21891 DEFVAR_INT ("scroll-conservatively", &scroll_conservatively,
21892 doc: /* *Scroll up to this many lines, to bring point back on screen.
228299fa
GM
21893A value of zero means to scroll the text to center point vertically
21894in the window. */);
0789adb2
RS
21895 scroll_conservatively = 0;
21896
7ee72033
MB
21897 DEFVAR_INT ("scroll-margin", &scroll_margin,
21898 doc: /* *Number of lines of margin at the top and bottom of a window.
228299fa
GM
21899Recenter the window whenever point gets within this many lines
21900of the top or bottom of the window. */);
9afd2168
RS
21901 scroll_margin = 0;
21902
6b61353c
KH
21903 DEFVAR_LISP ("display-pixels-per-inch", &Vdisplay_pixels_per_inch,
21904 doc: /* Pixels per inch on current display.
21905Value is a number or a cons (WIDTH-DPI . HEIGHT-DPI). */);
21906 Vdisplay_pixels_per_inch = make_float (72.0);
21907
5f5c8ee5 21908#if GLYPH_DEBUG
7ee72033 21909 DEFVAR_INT ("debug-end-pos", &debug_end_pos, doc: /* Don't ask. */);
5f5c8ee5 21910#endif
a2889657
JB
21911
21912 DEFVAR_BOOL ("truncate-partial-width-windows",
7ee72033
MB
21913 &truncate_partial_width_windows,
21914 doc: /* *Non-nil means truncate lines in all windows less than full frame wide. */);
a2889657
JB
21915 truncate_partial_width_windows = 1;
21916
7ee72033
MB
21917 DEFVAR_BOOL ("mode-line-inverse-video", &mode_line_inverse_video,
21918 doc: /* nil means display the mode-line/header-line/menu-bar in the default face.
228299fa 21919Any other value means to use the appropriate face, `mode-line',
ccfe8f57 21920`header-line', or `menu' respectively. */);
1862a24e 21921 mode_line_inverse_video = 1;
aa6d10fa 21922
7ee72033
MB
21923 DEFVAR_LISP ("line-number-display-limit", &Vline_number_display_limit,
21924 doc: /* *Maximum buffer size for which line number should be displayed.
228299fa
GM
21925If the buffer is bigger than this, the line number does not appear
21926in the mode line. A value of nil means no limit. */);
090703f4 21927 Vline_number_display_limit = Qnil;
fba9ce76 21928
090703f4 21929 DEFVAR_INT ("line-number-display-limit-width",
7ee72033
MB
21930 &line_number_display_limit_width,
21931 doc: /* *Maximum line width (in characters) for line number display.
228299fa
GM
21932If the average length of the lines near point is bigger than this, then the
21933line number may be omitted from the mode line. */);
5d121aec
KH
21934 line_number_display_limit_width = 200;
21935
7ee72033
MB
21936 DEFVAR_BOOL ("highlight-nonselected-windows", &highlight_nonselected_windows,
21937 doc: /* *Non-nil means highlight region even in nonselected windows. */);
293a54ce 21938 highlight_nonselected_windows = 0;
d39b6696 21939
7ee72033
MB
21940 DEFVAR_BOOL ("multiple-frames", &multiple_frames,
21941 doc: /* Non-nil if more than one frame is visible on this display.
228299fa
GM
21942Minibuffer-only frames don't count, but iconified frames do.
21943This variable is not guaranteed to be accurate except while processing
21944`frame-title-format' and `icon-title-format'. */);
21945
7ee72033
MB
21946 DEFVAR_LISP ("frame-title-format", &Vframe_title_format,
21947 doc: /* Template for displaying the title bar of visible frames.
228299fa
GM
21948\(Assuming the window manager supports this feature.)
21949This variable has the same structure as `mode-line-format' (which see),
21950and is used only on frames for which no explicit name has been set
21951\(see `modify-frame-parameters'). */);
6b61353c 21952
7ee72033
MB
21953 DEFVAR_LISP ("icon-title-format", &Vicon_title_format,
21954 doc: /* Template for displaying the title bar of an iconified frame.
228299fa
GM
21955\(Assuming the window manager supports this feature.)
21956This variable has the same structure as `mode-line-format' (which see),
21957and is used only on frames for which no explicit name has been set
21958\(see `modify-frame-parameters'). */);
d39b6696
KH
21959 Vicon_title_format
21960 = Vframe_title_format
21961 = Fcons (intern ("multiple-frames"),
21962 Fcons (build_string ("%b"),
3ebf0ea9 21963 Fcons (Fcons (empty_string,
d39b6696
KH
21964 Fcons (intern ("invocation-name"),
21965 Fcons (build_string ("@"),
21966 Fcons (intern ("system-name"),
21967 Qnil)))),
21968 Qnil)));
5992c4f7 21969
7ee72033
MB
21970 DEFVAR_LISP ("message-log-max", &Vmessage_log_max,
21971 doc: /* Maximum number of lines to keep in the message log buffer.
228299fa
GM
21972If nil, disable message logging. If t, log messages but don't truncate
21973the buffer when it becomes large. */);
ac90c44f 21974 Vmessage_log_max = make_number (50);
08b610e4 21975
7ee72033
MB
21976 DEFVAR_LISP ("window-size-change-functions", &Vwindow_size_change_functions,
21977 doc: /* Functions called before redisplay, if window sizes have changed.
228299fa
GM
21978The value should be a list of functions that take one argument.
21979Just before redisplay, for each frame, if any of its windows have changed
21980size since the last redisplay, or have been split or deleted,
21981all the functions in the list are called, with the frame as argument. */);
08b610e4 21982 Vwindow_size_change_functions = Qnil;
75c43375 21983
7ee72033
MB
21984 DEFVAR_LISP ("window-scroll-functions", &Vwindow_scroll_functions,
21985 doc: /* List of Functions to call before redisplaying a window with scrolling.
228299fa
GM
21986Each function is called with two arguments, the window
21987and its new display-start position. Note that the value of `window-end'
21988is not valid when these functions are called. */);
75c43375 21989 Vwindow_scroll_functions = Qnil;
2311178e 21990
fa3c6b4d
KS
21991 DEFVAR_BOOL ("mouse-autoselect-window", &mouse_autoselect_window,
21992 doc: /* *Non-nil means autoselect window with mouse pointer. */);
21993 mouse_autoselect_window = 0;
21994
7ee72033
MB
21995 DEFVAR_BOOL ("auto-resize-tool-bars", &auto_resize_tool_bars_p,
21996 doc: /* *Non-nil means automatically resize tool-bars.
228299fa
GM
21997This increases a tool-bar's height if not all tool-bar items are visible.
21998It decreases a tool-bar's height when it would display blank lines
21999otherwise. */);
e037b9ec 22000 auto_resize_tool_bars_p = 1;
2311178e 22001
7ee72033
MB
22002 DEFVAR_BOOL ("auto-raise-tool-bar-buttons", &auto_raise_tool_bar_buttons_p,
22003 doc: /* *Non-nil means raise tool-bar buttons when the mouse moves over them. */);
e037b9ec 22004 auto_raise_tool_bar_buttons_p = 1;
5f5c8ee5 22005
7ee72033
MB
22006 DEFVAR_LISP ("tool-bar-button-margin", &Vtool_bar_button_margin,
22007 doc: /* *Margin around tool-bar buttons in pixels.
228299fa 22008If an integer, use that for both horizontal and vertical margins.
f6c89f27 22009Otherwise, value should be a pair of integers `(HORZ . VERT)' with
228299fa
GM
22010HORZ specifying the horizontal margin, and VERT specifying the
22011vertical margin. */);
c3d76173 22012 Vtool_bar_button_margin = make_number (DEFAULT_TOOL_BAR_BUTTON_MARGIN);
5f5c8ee5 22013
7ee72033 22014 DEFVAR_INT ("tool-bar-button-relief", &tool_bar_button_relief,
6da3c85b 22015 doc: /* *Relief thickness of tool-bar buttons. */);
c3d76173 22016 tool_bar_button_relief = DEFAULT_TOOL_BAR_BUTTON_RELIEF;
5f5c8ee5 22017
7ee72033
MB
22018 DEFVAR_LISP ("fontification-functions", &Vfontification_functions,
22019 doc: /* List of functions to call to fontify regions of text.
228299fa
GM
22020Each function is called with one argument POS. Functions must
22021fontify a region starting at POS in the current buffer, and give
22022fontified regions the property `fontified'. */);
5f5c8ee5 22023 Vfontification_functions = Qnil;
6b9f0906 22024 Fmake_variable_buffer_local (Qfontification_functions);
7bbe686f
AI
22025
22026 DEFVAR_BOOL ("unibyte-display-via-language-environment",
7ee72033
MB
22027 &unibyte_display_via_language_environment,
22028 doc: /* *Non-nil means display unibyte text according to language environment.
228299fa
GM
22029Specifically this means that unibyte non-ASCII characters
22030are displayed by converting them to the equivalent multibyte characters
22031according to the current language environment. As a result, they are
22032displayed according to the current fontset. */);
7bbe686f 22033 unibyte_display_via_language_environment = 0;
c6e89d6c 22034
7ee72033
MB
22035 DEFVAR_LISP ("max-mini-window-height", &Vmax_mini_window_height,
22036 doc: /* *Maximum height for resizing mini-windows.
228299fa
GM
22037If a float, it specifies a fraction of the mini-window frame's height.
22038If an integer, it specifies a number of lines. */);
c6e89d6c 22039 Vmax_mini_window_height = make_float (0.25);
6422c1d7 22040
7ee72033
MB
22041 DEFVAR_LISP ("resize-mini-windows", &Vresize_mini_windows,
22042 doc: /* *How to resize mini-windows.
228299fa
GM
22043A value of nil means don't automatically resize mini-windows.
22044A value of t means resize them to fit the text displayed in them.
22045A value of `grow-only', the default, means let mini-windows grow
22046only, until their display becomes empty, at which point the windows
22047go back to their normal size. */);
6422c1d7
GM
22048 Vresize_mini_windows = Qgrow_only;
22049
cfe03a41
KS
22050 DEFVAR_LISP ("cursor-in-non-selected-windows",
22051 &Vcursor_in_non_selected_windows,
22052 doc: /* *Cursor type to display in non-selected windows.
22053t means to use hollow box cursor. See `cursor-type' for other values. */);
22054 Vcursor_in_non_selected_windows = Qt;
22055
cfe03a41
KS
22056 DEFVAR_LISP ("blink-cursor-alist", &Vblink_cursor_alist,
22057 doc: /* Alist specifying how to blink the cursor off.
22058Each element has the form (ON-STATE . OFF-STATE). Whenever the
22059`cursor-type' frame-parameter or variable equals ON-STATE,
22060comparing using `equal', Emacs uses OFF-STATE to specify
22061how to blink it off. */);
22062 Vblink_cursor_alist = Qnil;
2311178e 22063
e76d28d5 22064 DEFVAR_BOOL ("auto-hscroll-mode", &automatic_hscrolling_p,
7ee72033 22065 doc: /* *Non-nil means scroll the display automatically to make point visible. */);
d475bcb8 22066 automatic_hscrolling_p = 1;
1df7e8f0 22067
e76d28d5 22068 DEFVAR_INT ("hscroll-margin", &hscroll_margin,
1df7e8f0
EZ
22069 doc: /* *How many columns away from the window edge point is allowed to get
22070before automatic hscrolling will horizontally scroll the window. */);
e76d28d5 22071 hscroll_margin = 5;
1df7e8f0 22072
e76d28d5 22073 DEFVAR_LISP ("hscroll-step", &Vhscroll_step,
1df7e8f0
EZ
22074 doc: /* *How many columns to scroll the window when point gets too close to the edge.
22075When point is less than `automatic-hscroll-margin' columns from the window
22076edge, automatic hscrolling will scroll the window by the amount of columns
22077determined by this variable. If its value is a positive integer, scroll that
22078many columns. If it's a positive floating-point number, it specifies the
22079fraction of the window's width to scroll. If it's nil or zero, point will be
22080centered horizontally after the scroll. Any other value, including negative
22081numbers, are treated as if the value were zero.
22082
22083Automatic hscrolling always moves point outside the scroll margin, so if
22084point was more than scroll step columns inside the margin, the window will
22085scroll more than the value given by the scroll step.
22086
22087Note that the lower bound for automatic hscrolling specified by `scroll-left'
22088and `scroll-right' overrides this variable's effect. */);
e76d28d5 22089 Vhscroll_step = make_number (0);
2311178e 22090
7ee72033
MB
22091 DEFVAR_LISP ("image-types", &Vimage_types,
22092 doc: /* List of supported image types.
228299fa 22093Each element of the list is a symbol for a supported image type. */);
e00daaa0 22094 Vimage_types = Qnil;
2311178e 22095
7ee72033
MB
22096 DEFVAR_BOOL ("message-truncate-lines", &message_truncate_lines,
22097 doc: /* If non-nil, messages are truncated instead of resizing the echo area.
228299fa 22098Bind this around calls to `message' to let it take effect. */);
ad4f174e 22099 message_truncate_lines = 0;
0bca8940 22100
7ee72033
MB
22101 DEFVAR_LISP ("menu-bar-update-hook", &Vmenu_bar_update_hook,
22102 doc: /* Normal hook run for clicks on menu bar, before displaying a submenu.
228299fa 22103Can be used to update submenus whose contents should vary. */);
6422c1d7 22104 Vmenu_bar_update_hook = Qnil;
2311178e 22105
7ee72033
MB
22106 DEFVAR_BOOL ("inhibit-menubar-update", &inhibit_menubar_update,
22107 doc: /* Non-nil means don't update menu bars. Internal use only. */);
e1477f43 22108 inhibit_menubar_update = 0;
30a3f61c 22109
7ee72033
MB
22110 DEFVAR_BOOL ("inhibit-eval-during-redisplay", &inhibit_eval_during_redisplay,
22111 doc: /* Non-nil means don't eval Lisp during redisplay. */);
30a3f61c 22112 inhibit_eval_during_redisplay = 0;
76cb5e06 22113
26683087
RS
22114 DEFVAR_BOOL ("inhibit-free-realized-faces", &inhibit_free_realized_faces,
22115 doc: /* Non-nil means don't free realized faces. Internal use only. */);
22116 inhibit_free_realized_faces = 0;
22117
69d1f7c9 22118#if GLYPH_DEBUG
76cb5e06
GM
22119 DEFVAR_BOOL ("inhibit-try-window-id", &inhibit_try_window_id,
22120 doc: /* Inhibit try_window_id display optimization. */);
22121 inhibit_try_window_id = 0;
22122
22123 DEFVAR_BOOL ("inhibit-try-window-reusing", &inhibit_try_window_reusing,
22124 doc: /* Inhibit try_window_reusing display optimization. */);
22125 inhibit_try_window_reusing = 0;
22126
22127 DEFVAR_BOOL ("inhibit-try-cursor-movement", &inhibit_try_cursor_movement,
22128 doc: /* Inhibit try_cursor_movement display optimization. */);
22129 inhibit_try_cursor_movement = 0;
22130#endif /* GLYPH_DEBUG */
a2889657
JB
22131}
22132
5f5c8ee5
GM
22133
22134/* Initialize this module when Emacs starts. */
22135
dfcf069d 22136void
a2889657
JB
22137init_xdisp ()
22138{
22139 Lisp_Object root_window;
5f5c8ee5 22140 struct window *mini_w;
a2889657 22141
04612a64
GM
22142 current_header_line_height = current_mode_line_height = -1;
22143
5f5c8ee5 22144 CHARPOS (this_line_start_pos) = 0;
a2889657
JB
22145
22146 mini_w = XWINDOW (minibuf_window);
11e82b76 22147 root_window = FRAME_ROOT_WINDOW (XFRAME (WINDOW_FRAME (mini_w)));
a2889657 22148
a2889657
JB
22149 if (!noninteractive)
22150 {
5f5c8ee5
GM
22151 struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (root_window)));
22152 int i;
22153
da8b7f4f 22154 XWINDOW (root_window)->top_line = make_number (FRAME_TOP_MARGIN (f));
12c226c5 22155 set_window_height (root_window,
da8b7f4f 22156 FRAME_LINES (f) - 1 - FRAME_TOP_MARGIN (f),
12c226c5 22157 0);
da8b7f4f 22158 mini_w->top_line = make_number (FRAME_LINES (f) - 1);
a2889657
JB
22159 set_window_height (minibuf_window, 1, 0);
22160
da8b7f4f
KS
22161 XWINDOW (root_window)->total_cols = make_number (FRAME_COLS (f));
22162 mini_w->total_cols = make_number (FRAME_COLS (f));
5f5c8ee5
GM
22163
22164 scratch_glyph_row.glyphs[TEXT_AREA] = scratch_glyphs;
22165 scratch_glyph_row.glyphs[TEXT_AREA + 1]
22166 = scratch_glyphs + MAX_SCRATCH_GLYPHS;
22167
2311178e 22168 /* The default ellipsis glyphs `...'. */
5f5c8ee5 22169 for (i = 0; i < 3; ++i)
ac90c44f 22170 default_invis_vector[i] = make_number ('.');
a2889657 22171 }
5f5c8ee5 22172
5f5c8ee5 22173 {
93da8435
SM
22174 /* Allocate the buffer for frame titles.
22175 Also used for `format-mode-line'. */
5f5c8ee5
GM
22176 int size = 100;
22177 frame_title_buf = (char *) xmalloc (size);
22178 frame_title_buf_end = frame_title_buf + size;
22179 frame_title_ptr = NULL;
22180 }
2311178e 22181
21fdfb65 22182 help_echo_showing_p = 0;
a2889657 22183}
5f5c8ee5
GM
22184
22185
6b61353c
KH
22186/* arch-tag: eacc864d-bb6a-4b74-894a-1a4399a1358b
22187 (do not change this comment) */