Fix an off by one error in c-guess-basic-syntax CASE 5B.1.
[bpt/emacs.git] / src / dispnew.c
CommitLineData
4588ec20 1/* Updating of data structures for redisplay.
acaf905b 2 Copyright (C) 1985-1988, 1993-1995, 1997-2012 Free Software Foundation, Inc.
4588ec20
JB
3
4This file is part of GNU Emacs.
5
9ec0b715 6GNU Emacs is free software: you can redistribute it and/or modify
4588ec20 7it under the terms of the GNU General Public License as published by
9ec0b715
GM
8the Free Software Foundation, either version 3 of the License, or
9(at your option) any later version.
4588ec20
JB
10
11GNU Emacs is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
9ec0b715 17along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
4588ec20 18
18160b98 19#include <config.h>
68c45bf0 20#include <signal.h>
565620a5 21#include <stdio.h>
4588ec20 22#include <ctype.h>
d7306fe6 23#include <setjmp.h>
dfcf069d 24#include <unistd.h>
dfcf069d 25
47099d6f 26#include "lisp.h"
4588ec20
JB
27#include "termchar.h"
28#include "termopts.h"
a0879520 29/* cm.h must come after dispextern.h on Windows. */
fd2e066a
GV
30#include "dispextern.h"
31#include "cm.h"
4588ec20 32#include "buffer.h"
83be827a 33#include "character.h"
d43721a2 34#include "keyboard.h"
502b9b64 35#include "frame.h"
428a555e 36#include "termhooks.h"
4588ec20
JB
37#include "window.h"
38#include "commands.h"
39#include "disptab.h"
40#include "indent.h"
d169fe39 41#include "intervals.h"
97cf50e7 42#include "blockinput.h"
dfcf069d 43#include "process.h"
4588ec20 44
58b2bb63 45#include "syssignal.h"
a41f8bed 46
4588ec20
JB
47#ifdef HAVE_X_WINDOWS
48#include "xterm.h"
5f5c8ee5 49#endif /* HAVE_X_WINDOWS */
4588ec20 50
fd2e066a
GV
51#ifdef HAVE_NTGUI
52#include "w32term.h"
53#endif /* HAVE_NTGUI */
54
edfda783
AR
55#ifdef HAVE_NS
56#include "nsterm.h"
57#endif
58
5f5c8ee5 59/* Include systime.h after xterm.h to avoid double inclusion of time.h. */
6cbd1643 60
5f5c8ee5 61#include "systime.h"
3883a901
RS
62#include <errno.h>
63
4588ec20 64/* Get number of chars of output now in the buffer of a stdio stream.
5a5fa834 65 This ought to be built in stdio, but it isn't. Some s- files
5f5c8ee5
GM
66 override this because their stdio internals differ. */
67
e3271ae5 68#ifdef __GNU_LIBRARY__
5f5c8ee5
GM
69
70/* The s- file might have overridden the definition with one that
71 works for the system's C library. But we are using the GNU C
72 library, so this is the right definition for every system. */
73
3883a901
RS
74#ifdef GNU_LIBRARY_PENDING_OUTPUT_COUNT
75#define PENDING_OUTPUT_COUNT GNU_LIBRARY_PENDING_OUTPUT_COUNT
76#else
cb5558ff 77#undef PENDING_OUTPUT_COUNT
e3271ae5 78#define PENDING_OUTPUT_COUNT(FILE) ((FILE)->__bufp - (FILE)->__buffer)
3883a901
RS
79#endif
80#else /* not __GNU_LIBRARY__ */
68c45bf0
PE
81#if !defined (PENDING_OUTPUT_COUNT) && HAVE_STDIO_EXT_H && HAVE___FPENDING
82#include <stdio_ext.h>
83#define PENDING_OUTPUT_COUNT(FILE) __fpending (FILE)
84#endif
cb5558ff 85#ifndef PENDING_OUTPUT_COUNT
4588ec20
JB
86#define PENDING_OUTPUT_COUNT(FILE) ((FILE)->_ptr - (FILE)->_base)
87#endif
5f5c8ee5
GM
88#endif /* not __GNU_LIBRARY__ */
89
5e617bc2 90#if defined (HAVE_TERM_H) && defined (GNU_LINUX) && defined (HAVE_LIBNCURSES)
fa0ec9f4
DL
91#include <term.h> /* for tgetent */
92#endif
5f5c8ee5
GM
93\f
94/* Structure to pass dimensions around. Used for character bounding
95 boxes, glyph matrix dimensions and alike. */
96
97struct dim
98{
99 int width;
100 int height;
101};
102
103\f
104/* Function prototypes. */
105
f57e2426 106static void update_frame_line (struct frame *, int);
2f7c71a1
AS
107static int required_matrix_height (struct window *);
108static int required_matrix_width (struct window *);
f57e2426 109static void adjust_frame_glyphs (struct frame *);
f57e2426 110static void change_frame_size_1 (struct frame *, int, int, int, int, int);
5bf46f05 111static void increment_row_positions (struct glyph_row *, EMACS_INT, EMACS_INT);
f57e2426
J
112static void fill_up_frame_row_with_spaces (struct glyph_row *, int);
113static void build_frame_matrix_from_window_tree (struct glyph_matrix *,
114 struct window *);
115static void build_frame_matrix_from_leaf_window (struct glyph_matrix *,
116 struct window *);
f57e2426
J
117static void adjust_frame_message_buffer (struct frame *);
118static void adjust_decode_mode_spec_buffer (struct frame *);
119static void fill_up_glyph_row_with_spaces (struct glyph_row *);
f57e2426
J
120static void clear_window_matrices (struct window *, int);
121static void fill_up_glyph_row_area_with_spaces (struct glyph_row *, int);
122static int scrolling_window (struct window *, int);
123static int update_window_line (struct window *, int, int *);
f57e2426 124static void mirror_make_current (struct window *, int);
b96fd3e8 125#if GLYPH_DEBUG
f57e2426
J
126static void check_matrix_pointers (struct glyph_matrix *,
127 struct glyph_matrix *);
b96fd3e8 128#endif
f57e2426
J
129static void mirror_line_dance (struct window *, int, int, int *, char *);
130static int update_window_tree (struct window *, int);
131static int update_window (struct window *, int);
132static int update_frame_1 (struct frame *, int, int);
5bf46f05 133static int scrolling (struct frame *);
f57e2426 134static void set_window_cursor_after_update (struct window *);
f57e2426
J
135static void adjust_frame_glyphs_for_window_redisplay (struct frame *);
136static void adjust_frame_glyphs_for_frame_redisplay (struct frame *);
5f5c8ee5 137
5f5c8ee5 138\f
d012c62b
KS
139/* Define PERIODIC_PREEMPTION_CHECKING to 1, if micro-second timers
140 are supported, so we can check for input during redisplay at
141 regular intervals. */
142#ifdef EMACS_HAS_USECS
143#define PERIODIC_PREEMPTION_CHECKING 1
144#else
145#define PERIODIC_PREEMPTION_CHECKING 0
146#endif
147
148#if PERIODIC_PREEMPTION_CHECKING
149
d012c62b
KS
150/* Redisplay preemption timers. */
151
152static EMACS_TIME preemption_period;
153static EMACS_TIME preemption_next_check;
154
155#endif
156
a41f8bed 157/* Nonzero upon entry to redisplay means do not assume anything about
502b9b64 158 current contents of actual terminal frame; clear and redraw it. */
4588ec20 159
502b9b64 160int frame_garbaged;
4588ec20 161
5f5c8ee5 162/* Nonzero means last display completed. Zero means it was preempted. */
4588ec20
JB
163
164int display_completed;
165
e7067d00 166Lisp_Object Qdisplay_table, Qredisplay_dont_pause;
5f5c8ee5 167
4588ec20 168\f
5f5c8ee5 169/* The currently selected frame. In a single-frame version, this
91fb7e1b 170 variable always equals the_only_frame. */
4588ec20 171
91fb7e1b 172Lisp_Object selected_frame;
4588ec20 173
5f5c8ee5 174/* A frame which is not just a mini-buffer, or 0 if there are no such
502b9b64 175 frames. This is usually the most recent such frame that was
87485d6f
MW
176 selected. In a single-frame version, this variable always holds
177 the address of the_only_frame. */
4588ec20 178
5f5c8ee5 179struct frame *last_nonminibuf_frame;
d52bad65 180
5f5c8ee5 181/* 1 means SIGWINCH happened when not safe. */
4588ec20 182
5bf46f05 183static int delayed_size_change;
4588ec20 184
5f5c8ee5 185/* 1 means glyph initialization has been completed at startup. */
4588ec20 186
5f5c8ee5 187static int glyphs_initialized_initially_p;
4588ec20 188
5f5c8ee5 189/* Updated window if != 0. Set by update_window. */
4588ec20 190
5f5c8ee5 191struct window *updated_window;
4588ec20 192
5f5c8ee5 193/* Glyph row updated in update_window_line, and area that is updated. */
4588ec20 194
5f5c8ee5
GM
195struct glyph_row *updated_row;
196int updated_area;
4588ec20 197
5f5c8ee5 198/* A glyph for a space. */
4588ec20 199
5f5c8ee5 200struct glyph space_glyph;
4588ec20 201
5f5c8ee5
GM
202/* Counts of allocated structures. These counts serve to diagnose
203 memory leaks and double frees. */
4588ec20 204
5bf46f05
PE
205static int glyph_matrix_count;
206static int glyph_pool_count;
4588ec20 207
5f5c8ee5
GM
208/* If non-null, the frame whose frame matrices are manipulated. If
209 null, window matrices are worked on. */
4588ec20 210
5f5c8ee5 211static struct frame *frame_matrix_frame;
4588ec20 212
5f5c8ee5
GM
213/* Non-zero means that fonts have been loaded since the last glyph
214 matrix adjustments. Redisplay must stop, and glyph matrices must
215 be adjusted when this flag becomes non-zero during display. The
216 reason fonts can be loaded so late is that fonts of fontsets are
3aa9f0c4
KH
217 loaded on demand. Another reason is that a line contains many
218 characters displayed by zero width or very narrow glyphs of
219 variable-width fonts. */
836d2cde 220
5f5c8ee5 221int fonts_changed_p;
836d2cde 222
177c0ea7 223/* Convert vpos and hpos from frame to window and vice versa.
5f5c8ee5 224 This may only be used for terminal frames. */
836d2cde 225
5f5c8ee5 226#if GLYPH_DEBUG
4588ec20 227
f57e2426
J
228static int window_to_frame_vpos (struct window *, int);
229static int window_to_frame_hpos (struct window *, int);
5f5c8ee5
GM
230#define WINDOW_TO_FRAME_VPOS(W, VPOS) window_to_frame_vpos ((W), (VPOS))
231#define WINDOW_TO_FRAME_HPOS(W, HPOS) window_to_frame_hpos ((W), (HPOS))
4588ec20 232
9b0e97aa
GM
233/* One element of the ring buffer containing redisplay history
234 information. */
235
236struct redisplay_history
237{
238 char trace[512 + 100];
239};
240
241/* The size of the history buffer. */
242
243#define REDISPLAY_HISTORY_SIZE 30
244
245/* The redisplay history buffer. */
246
247static struct redisplay_history redisplay_history[REDISPLAY_HISTORY_SIZE];
248
249/* Next free entry in redisplay_history. */
250
251static int history_idx;
252
253/* A tick that's incremented each time something is added to the
254 history. */
255
dfd153ae 256static uprintmax_t history_tick;
9b0e97aa 257
f57e2426 258static void add_frame_display_history (struct frame *, int);
6a8aec41 259\f
9b0e97aa
GM
260/* Add to the redisplay history how window W has been displayed.
261 MSG is a trace containing the information how W's glyph matrix
153a073c 262 has been constructed. PAUSED_P non-zero means that the update
9b0e97aa
GM
263 has been interrupted for pending input. */
264
265static void
c56e0fd5 266add_window_display_history (struct window *w, const char *msg, int paused_p)
9b0e97aa
GM
267{
268 char *buf;
177c0ea7 269
9b0e97aa
GM
270 if (history_idx >= REDISPLAY_HISTORY_SIZE)
271 history_idx = 0;
272 buf = redisplay_history[history_idx].trace;
273 ++history_idx;
177c0ea7 274
8666506e
PE
275 snprintf (buf, sizeof redisplay_history[0].trace,
276 "%"pMu": window %p (`%s')%s\n%s",
277 history_tick++,
278 w,
279 ((BUFFERP (w->buffer)
280 && STRINGP (BVAR (XBUFFER (w->buffer), name)))
281 ? SSDATA (BVAR (XBUFFER (w->buffer), name))
282 : "???"),
283 paused_p ? " ***paused***" : "",
284 msg);
9b0e97aa
GM
285}
286
287
288/* Add to the redisplay history that frame F has been displayed.
289 PAUSED_P non-zero means that the update has been interrupted for
290 pending input. */
291
292static void
59fc5cf9 293add_frame_display_history (struct frame *f, int paused_p)
9b0e97aa
GM
294{
295 char *buf;
177c0ea7 296
9b0e97aa
GM
297 if (history_idx >= REDISPLAY_HISTORY_SIZE)
298 history_idx = 0;
299 buf = redisplay_history[history_idx].trace;
300 ++history_idx;
177c0ea7 301
dfd153ae 302 sprintf (buf, "%"pMu": update frame %p%s",
9b0e97aa
GM
303 history_tick++,
304 f, paused_p ? " ***paused***" : "");
305}
306
307
a7ca3326 308DEFUN ("dump-redisplay-history", Fdump_redisplay_history,
9b0e97aa 309 Sdump_redisplay_history, 0, 0, "",
7ee72033 310 doc: /* Dump redisplay history to stderr. */)
5842a27b 311 (void)
9b0e97aa
GM
312{
313 int i;
314
315 for (i = history_idx - 1; i != history_idx; --i)
316 {
317 if (i < 0)
318 i = REDISPLAY_HISTORY_SIZE - 1;
319 fprintf (stderr, "%s\n", redisplay_history[i].trace);
320 }
321
322 return Qnil;
323}
324
325
5f5c8ee5 326#else /* GLYPH_DEBUG == 0 */
4588ec20 327
7df02016
KS
328#define WINDOW_TO_FRAME_VPOS(W, VPOS) ((VPOS) + WINDOW_TOP_EDGE_LINE (W))
329#define WINDOW_TO_FRAME_HPOS(W, HPOS) ((HPOS) + WINDOW_LEFT_EDGE_COL (W))
4588ec20 330
5f5c8ee5 331#endif /* GLYPH_DEBUG == 0 */
4588ec20 332
4588ec20 333
dcc19aac 334#if defined PROFILING && !HAVE___EXECUTABLE_START
72af86bd 335/* FIXME: only used to find text start for profiling. */
4588ec20
JB
336
337void
971de7fb 338safe_bcopy (const char *from, char *to, int size)
4588ec20 339{
72af86bd 340 abort ();
177c0ea7 341}
72af86bd 342#endif
5f5c8ee5
GM
343\f
344/***********************************************************************
345 Glyph Matrices
346 ***********************************************************************/
347
348/* Allocate and return a glyph_matrix structure. POOL is the glyph
349 pool from which memory for the matrix should be allocated, or null
350 for window-based redisplay where no glyph pools are used. The
351 member `pool' of the glyph matrix structure returned is set to
352 POOL, the structure is otherwise zeroed. */
353
5bf46f05 354static struct glyph_matrix *
971de7fb 355new_glyph_matrix (struct glyph_pool *pool)
4588ec20 356{
5f5c8ee5
GM
357 struct glyph_matrix *result;
358
359 /* Allocate and clear. */
360 result = (struct glyph_matrix *) xmalloc (sizeof *result);
72af86bd 361 memset (result, 0, sizeof *result);
4588ec20 362
5f5c8ee5
GM
363 /* Increment number of allocated matrices. This count is used
364 to detect memory leaks. */
365 ++glyph_matrix_count;
4588ec20 366
5f5c8ee5
GM
367 /* Set pool and return. */
368 result->pool = pool;
369 return result;
4588ec20
JB
370}
371
4588ec20 372
5f5c8ee5
GM
373/* Free glyph matrix MATRIX. Passing in a null MATRIX is allowed.
374
375 The global counter glyph_matrix_count is decremented when a matrix
376 is freed. If the count gets negative, more structures were freed
377 than allocated, i.e. one matrix was freed more than once or a bogus
378 pointer was passed to this function.
177c0ea7 379
5f5c8ee5
GM
380 If MATRIX->pool is null, this means that the matrix manages its own
381 glyph memory---this is done for matrices on X frames. Freeing the
382 matrix also frees the glyph memory in this case. */
383
384static void
971de7fb 385free_glyph_matrix (struct glyph_matrix *matrix)
4588ec20 386{
5f5c8ee5
GM
387 if (matrix)
388 {
389 int i;
390
391 /* Detect the case that more matrices are freed than were
392 allocated. */
393 if (--glyph_matrix_count < 0)
394 abort ();
395
396 /* Free glyph memory if MATRIX owns it. */
397 if (matrix->pool == NULL)
398 for (i = 0; i < matrix->rows_allocated; ++i)
399 xfree (matrix->rows[i].glyphs[LEFT_MARGIN_AREA]);
177c0ea7 400
5f5c8ee5
GM
401 /* Free row structures and the matrix itself. */
402 xfree (matrix->rows);
403 xfree (matrix);
404 }
405}
4588ec20 406
4588ec20 407
5f5c8ee5
GM
408/* Return the number of glyphs to reserve for a marginal area of
409 window W. TOTAL_GLYPHS is the number of glyphs in a complete
410 display line of window W. MARGIN gives the width of the marginal
411 area in canonical character units. MARGIN should be an integer
412 or a float. */
413
414static int
971de7fb 415margin_glyphs_to_reserve (struct window *w, int total_glyphs, Lisp_Object margin)
5f5c8ee5
GM
416{
417 int n;
4588ec20 418
5f5c8ee5 419 if (NUMBERP (margin))
4588ec20 420 {
7df02016 421 int width = XFASTINT (w->total_cols);
5f5c8ee5
GM
422 double d = max (0, XFLOATINT (margin));
423 d = min (width / 2 - 1, d);
35ec832e 424 n = (int) ((double) total_glyphs / width * d);
5f5c8ee5
GM
425 }
426 else
427 n = 0;
428
429 return n;
430}
431
7a7270dd
EZ
432#if XASSERTS
433/* Return non-zero if ROW's hash value is correct, zero if not. */
7430c2a1 434int
7a7270dd
EZ
435verify_row_hash (struct glyph_row *row)
436{
015137db 437 return row->hash == row_hash (row);
7a7270dd
EZ
438}
439#endif
4588ec20 440
5f5c8ee5
GM
441/* Adjust glyph matrix MATRIX on window W or on a frame to changed
442 window sizes.
4588ec20 443
5f5c8ee5
GM
444 W is null if the function is called for a frame glyph matrix.
445 Otherwise it is the window MATRIX is a member of. X and Y are the
446 indices of the first column and row of MATRIX within the frame
447 matrix, if such a matrix exists. They are zero for purely
448 window-based redisplay. DIM is the needed size of the matrix.
d52bad65 449
5f5c8ee5
GM
450 In window-based redisplay, where no frame matrices exist, glyph
451 matrices manage their own glyph storage. Otherwise, they allocate
452 storage from a common frame glyph pool which can be found in
453 MATRIX->pool.
23b0200c 454
5f5c8ee5
GM
455 The reason for this memory management strategy is to avoid complete
456 frame redraws if possible. When we allocate from a common pool, a
457 change of the location or size of a sub-matrix within the pool
458 requires a complete redisplay of the frame because we cannot easily
459 make sure that the current matrices of all windows still agree with
460 what is displayed on the screen. While this is usually fast, it
461 leads to screen flickering. */
23b0200c 462
5f5c8ee5 463static void
971de7fb 464adjust_glyph_matrix (struct window *w, struct glyph_matrix *matrix, int x, int y, struct dim dim)
5f5c8ee5
GM
465{
466 int i;
467 int new_rows;
468 int marginal_areas_changed_p = 0;
045dee35
GM
469 int header_line_changed_p = 0;
470 int header_line_p = 0;
5f5c8ee5 471 int left = -1, right = -1;
ca8a12a7 472 int window_width = -1, window_height = -1;
5f5c8ee5 473
6b61353c
KH
474 /* See if W had a header line that has disappeared now, or vice versa.
475 Get W's size. */
5f5c8ee5
GM
476 if (w)
477 {
6b61353c
KH
478 window_box (w, -1, 0, 0, &window_width, &window_height);
479
045dee35
GM
480 header_line_p = WINDOW_WANTS_HEADER_LINE_P (w);
481 header_line_changed_p = header_line_p != matrix->header_line_p;
5f5c8ee5 482 }
045dee35 483 matrix->header_line_p = header_line_p;
23b0200c 484
6b61353c
KH
485 /* If POOL is null, MATRIX is a window matrix for window-based redisplay.
486 Do nothing if MATRIX' size, position, vscroll, and marginal areas
5f5c8ee5
GM
487 haven't changed. This optimization is important because preserving
488 the matrix means preventing redisplay. */
489 if (matrix->pool == NULL)
490 {
7df02016
KS
491 left = margin_glyphs_to_reserve (w, dim.width, w->left_margin_cols);
492 right = margin_glyphs_to_reserve (w, dim.width, w->right_margin_cols);
5f5c8ee5
GM
493 xassert (left >= 0 && right >= 0);
494 marginal_areas_changed_p = (left != matrix->left_margin_glyphs
495 || right != matrix->right_margin_glyphs);
496
497 if (!marginal_areas_changed_p
498 && !fonts_changed_p
045dee35 499 && !header_line_changed_p
7df02016
KS
500 && matrix->window_left_col == WINDOW_LEFT_EDGE_COL (w)
501 && matrix->window_top_line == WINDOW_TOP_EDGE_LINE (w)
5f5c8ee5
GM
502 && matrix->window_height == window_height
503 && matrix->window_vscroll == w->vscroll
504 && matrix->window_width == window_width)
505 return;
506 }
177c0ea7 507
5f5c8ee5
GM
508 /* Enlarge MATRIX->rows if necessary. New rows are cleared. */
509 if (matrix->rows_allocated < dim.height)
510 {
0065d054 511 int old_alloc = matrix->rows_allocated;
5f5c8ee5 512 new_rows = dim.height - matrix->rows_allocated;
0065d054
PE
513 matrix->rows = xpalloc (matrix->rows, &matrix->rows_allocated,
514 new_rows, INT_MAX, sizeof *matrix->rows);
515 memset (matrix->rows + old_alloc, 0,
516 (matrix->rows_allocated - old_alloc) * sizeof *matrix->rows);
5f5c8ee5
GM
517 }
518 else
519 new_rows = 0;
60a8948a 520
5f5c8ee5
GM
521 /* If POOL is not null, MATRIX is a frame matrix or a window matrix
522 on a frame not using window-based redisplay. Set up pointers for
523 each row into the glyph pool. */
524 if (matrix->pool)
525 {
526 xassert (matrix->pool->glyphs);
177c0ea7 527
5f5c8ee5 528 if (w)
60a8948a 529 {
5f5c8ee5 530 left = margin_glyphs_to_reserve (w, dim.width,
7df02016 531 w->left_margin_cols);
5f5c8ee5 532 right = margin_glyphs_to_reserve (w, dim.width,
7df02016 533 w->right_margin_cols);
60a8948a 534 }
5f5c8ee5
GM
535 else
536 left = right = 0;
177c0ea7 537
5f5c8ee5 538 for (i = 0; i < dim.height; ++i)
60a8948a 539 {
5f5c8ee5 540 struct glyph_row *row = &matrix->rows[i];
177c0ea7
JB
541
542 row->glyphs[LEFT_MARGIN_AREA]
5f5c8ee5
GM
543 = (matrix->pool->glyphs
544 + (y + i) * matrix->pool->ncolumns
545 + x);
177c0ea7 546
5f5c8ee5
GM
547 if (w == NULL
548 || row == matrix->rows + dim.height - 1
045dee35 549 || (row == matrix->rows && matrix->header_line_p))
5f5c8ee5
GM
550 {
551 row->glyphs[TEXT_AREA]
552 = row->glyphs[LEFT_MARGIN_AREA];
553 row->glyphs[RIGHT_MARGIN_AREA]
554 = row->glyphs[TEXT_AREA] + dim.width;
555 row->glyphs[LAST_AREA]
556 = row->glyphs[RIGHT_MARGIN_AREA];
557 }
558 else
559 {
560 row->glyphs[TEXT_AREA]
561 = row->glyphs[LEFT_MARGIN_AREA] + left;
562 row->glyphs[RIGHT_MARGIN_AREA]
563 = row->glyphs[TEXT_AREA] + dim.width - left - right;
564 row->glyphs[LAST_AREA]
565 = row->glyphs[LEFT_MARGIN_AREA] + dim.width;
566 }
60a8948a 567 }
177c0ea7 568
5f5c8ee5
GM
569 matrix->left_margin_glyphs = left;
570 matrix->right_margin_glyphs = right;
571 }
572 else
573 {
574 /* If MATRIX->pool is null, MATRIX is responsible for managing
6b61353c
KH
575 its own memory. It is a window matrix for window-based redisplay.
576 Allocate glyph memory from the heap. */
5f5c8ee5
GM
577 if (dim.width > matrix->matrix_w
578 || new_rows
045dee35 579 || header_line_changed_p
5f5c8ee5 580 || marginal_areas_changed_p)
4588ec20 581 {
5f5c8ee5
GM
582 struct glyph_row *row = matrix->rows;
583 struct glyph_row *end = row + matrix->rows_allocated;
177c0ea7 584
5f5c8ee5
GM
585 while (row < end)
586 {
587 row->glyphs[LEFT_MARGIN_AREA]
0065d054
PE
588 = xnrealloc (row->glyphs[LEFT_MARGIN_AREA],
589 dim.width, sizeof (struct glyph));
177c0ea7 590
5f5c8ee5
GM
591 /* The mode line never has marginal areas. */
592 if (row == matrix->rows + dim.height - 1
045dee35 593 || (row == matrix->rows && matrix->header_line_p))
5f5c8ee5
GM
594 {
595 row->glyphs[TEXT_AREA]
596 = row->glyphs[LEFT_MARGIN_AREA];
597 row->glyphs[RIGHT_MARGIN_AREA]
598 = row->glyphs[TEXT_AREA] + dim.width;
599 row->glyphs[LAST_AREA]
600 = row->glyphs[RIGHT_MARGIN_AREA];
601 }
602 else
603 {
604 row->glyphs[TEXT_AREA]
605 = row->glyphs[LEFT_MARGIN_AREA] + left;
606 row->glyphs[RIGHT_MARGIN_AREA]
607 = row->glyphs[TEXT_AREA] + dim.width - left - right;
608 row->glyphs[LAST_AREA]
609 = row->glyphs[LEFT_MARGIN_AREA] + dim.width;
610 }
611 ++row;
612 }
4588ec20
JB
613 }
614
5f5c8ee5
GM
615 xassert (left >= 0 && right >= 0);
616 matrix->left_margin_glyphs = left;
617 matrix->right_margin_glyphs = right;
618 }
177c0ea7 619
5f5c8ee5
GM
620 /* Number of rows to be used by MATRIX. */
621 matrix->nrows = dim.height;
3ed36514 622 xassert (matrix->nrows >= 0);
5f5c8ee5 623
b7b20fbd 624 if (w)
5f5c8ee5 625 {
b7b20fbd 626 if (matrix == w->current_matrix)
4588ec20 627 {
b7b20fbd
GM
628 /* Mark rows in a current matrix of a window as not having
629 valid contents. It's important to not do this for
630 desired matrices. When Emacs starts, it may already be
631 building desired matrices when this function runs. */
632 if (window_width < 0)
633 window_width = window_box_width (w, -1);
177c0ea7 634
b7b20fbd
GM
635 /* Optimize the case that only the height has changed (C-x 2,
636 upper window). Invalidate all rows that are no longer part
637 of the window. */
638 if (!marginal_areas_changed_p
73d75a62
GM
639 && !header_line_changed_p
640 && new_rows == 0
641 && dim.width == matrix->matrix_w
7df02016
KS
642 && matrix->window_left_col == WINDOW_LEFT_EDGE_COL (w)
643 && matrix->window_top_line == WINDOW_TOP_EDGE_LINE (w)
73d75a62 644 && matrix->window_width == window_width)
b7b20fbd 645 {
dd42b31a
GM
646 /* Find the last row in the window. */
647 for (i = 0; i < matrix->nrows && matrix->rows[i].enabled_p; ++i)
648 if (MATRIX_ROW_BOTTOM_Y (matrix->rows + i) >= window_height)
649 {
26447967 650 ++i;
dd42b31a
GM
651 break;
652 }
b7b20fbd
GM
653
654 /* Window end is invalid, if inside of the rows that
dd42b31a 655 are invalidated below. */
b7b20fbd
GM
656 if (INTEGERP (w->window_end_vpos)
657 && XFASTINT (w->window_end_vpos) >= i)
658 w->window_end_valid = Qnil;
177c0ea7 659
b7b20fbd
GM
660 while (i < matrix->nrows)
661 matrix->rows[i++].enabled_p = 0;
662 }
663 else
664 {
665 for (i = 0; i < matrix->nrows; ++i)
666 matrix->rows[i].enabled_p = 0;
667 }
5f5c8ee5 668 }
b7b20fbd 669 else if (matrix == w->desired_matrix)
5f5c8ee5 670 {
b7b20fbd
GM
671 /* Rows in desired matrices always have to be cleared;
672 redisplay expects this is the case when it runs, so it
673 had better be the case when we adjust matrices between
674 redisplays. */
5f5c8ee5
GM
675 for (i = 0; i < matrix->nrows; ++i)
676 matrix->rows[i].enabled_p = 0;
4588ec20 677 }
4588ec20 678 }
177c0ea7
JB
679
680
5f5c8ee5
GM
681 /* Remember last values to be able to optimize frame redraws. */
682 matrix->matrix_x = x;
683 matrix->matrix_y = y;
684 matrix->matrix_w = dim.width;
685 matrix->matrix_h = dim.height;
686
687 /* Record the top y location and height of W at the time the matrix
688 was last adjusted. This is used to optimize redisplay above. */
689 if (w)
4588ec20 690 {
7df02016
KS
691 matrix->window_left_col = WINDOW_LEFT_EDGE_COL (w);
692 matrix->window_top_line = WINDOW_TOP_EDGE_LINE (w);
5f5c8ee5
GM
693 matrix->window_height = window_height;
694 matrix->window_width = window_width;
695 matrix->window_vscroll = w->vscroll;
696 }
697}
4588ec20 698
4588ec20 699
5f5c8ee5
GM
700/* Reverse the contents of rows in MATRIX between START and END. The
701 contents of the row at END - 1 end up at START, END - 2 at START +
702 1 etc. This is part of the implementation of rotate_matrix (see
703 below). */
d52bad65 704
5f5c8ee5 705static void
971de7fb 706reverse_rows (struct glyph_matrix *matrix, int start, int end)
5f5c8ee5
GM
707{
708 int i, j;
23b0200c 709
5f5c8ee5
GM
710 for (i = start, j = end - 1; i < j; ++i, --j)
711 {
712 /* Non-ISO HP/UX compiler doesn't like auto struct
713 initialization. */
714 struct glyph_row temp;
715 temp = matrix->rows[i];
716 matrix->rows[i] = matrix->rows[j];
717 matrix->rows[j] = temp;
718 }
719}
23b0200c 720
23b0200c 721
5f5c8ee5
GM
722/* Rotate the contents of rows in MATRIX in the range FIRST .. LAST -
723 1 by BY positions. BY < 0 means rotate left, i.e. towards lower
724 indices. (Note: this does not copy glyphs, only glyph pointers in
725 row structures are moved around).
60a8948a 726
5f5c8ee5
GM
727 The algorithm used for rotating the vector was, I believe, first
728 described by Kernighan. See the vector R as consisting of two
729 sub-vectors AB, where A has length BY for BY >= 0. The result
730 after rotating is then BA. Reverse both sub-vectors to get ArBr
731 and reverse the result to get (ArBr)r which is BA. Similar for
732 rotating right. */
733
734void
971de7fb 735rotate_matrix (struct glyph_matrix *matrix, int first, int last, int by)
5f5c8ee5
GM
736{
737 if (by < 0)
738 {
739 /* Up (rotate left, i.e. towards lower indices). */
740 by = -by;
741 reverse_rows (matrix, first, first + by);
742 reverse_rows (matrix, first + by, last);
743 reverse_rows (matrix, first, last);
744 }
745 else if (by > 0)
746 {
747 /* Down (rotate right, i.e. towards higher indices). */
748 reverse_rows (matrix, last - by, last);
749 reverse_rows (matrix, first, last - by);
750 reverse_rows (matrix, first, last);
751 }
752}
753
754
755/* Increment buffer positions in glyph rows of MATRIX. Do it for rows
756 with indices START <= index < END. Increment positions by DELTA/
757 DELTA_BYTES. */
758
759void
ace1712c
EZ
760increment_matrix_positions (struct glyph_matrix *matrix, int start, int end,
761 EMACS_INT delta, EMACS_INT delta_bytes)
5f5c8ee5
GM
762{
763 /* Check that START and END are reasonable values. */
764 xassert (start >= 0 && start <= matrix->nrows);
765 xassert (end >= 0 && end <= matrix->nrows);
766 xassert (start <= end);
767
768 for (; start < end; ++start)
86c11ba1 769 increment_row_positions (matrix->rows + start, delta, delta_bytes);
5f5c8ee5
GM
770}
771
772
773/* Enable a range of rows in glyph matrix MATRIX. START and END are
774 the row indices of the first and last + 1 row to enable. If
775 ENABLED_P is non-zero, enabled_p flags in rows will be set to 1. */
776
777void
971de7fb 778enable_glyph_matrix_rows (struct glyph_matrix *matrix, int start, int end, int enabled_p)
5f5c8ee5 779{
3ed36514
GM
780 xassert (start <= end);
781 xassert (start >= 0 && start < matrix->nrows);
782 xassert (end >= 0 && end <= matrix->nrows);
177c0ea7 783
5f5c8ee5
GM
784 for (; start < end; ++start)
785 matrix->rows[start].enabled_p = enabled_p != 0;
786}
787
788
789/* Clear MATRIX.
790
791 This empties all rows in MATRIX by setting the enabled_p flag for
792 all rows of the matrix to zero. The function prepare_desired_row
793 will eventually really clear a row when it sees one with a zero
794 enabled_p flag.
795
796 Resets update hints to defaults value. The only update hint
797 currently present is the flag MATRIX->no_scrolling_p. */
798
799void
971de7fb 800clear_glyph_matrix (struct glyph_matrix *matrix)
5f5c8ee5
GM
801{
802 if (matrix)
803 {
804 enable_glyph_matrix_rows (matrix, 0, matrix->nrows, 0);
805 matrix->no_scrolling_p = 0;
806 }
807}
177c0ea7 808
5f5c8ee5
GM
809
810/* Shift part of the glyph matrix MATRIX of window W up or down.
811 Increment y-positions in glyph rows between START and END by DY,
812 and recompute their visible height. */
813
814void
971de7fb 815shift_glyph_matrix (struct window *w, struct glyph_matrix *matrix, int start, int end, int dy)
5f5c8ee5
GM
816{
817 int min_y, max_y;
177c0ea7 818
5f5c8ee5
GM
819 xassert (start <= end);
820 xassert (start >= 0 && start < matrix->nrows);
821 xassert (end >= 0 && end <= matrix->nrows);
177c0ea7 822
7df02016
KS
823 min_y = WINDOW_HEADER_LINE_HEIGHT (w);
824 max_y = WINDOW_BOX_HEIGHT_NO_MODE_LINE (w);
177c0ea7 825
5f5c8ee5
GM
826 for (; start < end; ++start)
827 {
828 struct glyph_row *row = &matrix->rows[start];
177c0ea7 829
5f5c8ee5 830 row->y += dy;
d6c747a4 831 row->visible_height = row->height;
177c0ea7 832
5f5c8ee5 833 if (row->y < min_y)
d6c747a4
GM
834 row->visible_height -= min_y - row->y;
835 if (row->y + row->height > max_y)
836 row->visible_height -= row->y + row->height - max_y;
e61124cd
YM
837 if (row->fringe_bitmap_periodic_p)
838 row->redraw_fringe_bitmaps_p = 1;
5f5c8ee5
GM
839 }
840}
841
842
843/* Mark all rows in current matrices of frame F as invalid. Marking
844 invalid is done by setting enabled_p to zero for all rows in a
845 current matrix. */
846
847void
971de7fb 848clear_current_matrices (register struct frame *f)
5f5c8ee5
GM
849{
850 /* Clear frame current matrix, if we have one. */
851 if (f->current_matrix)
852 clear_glyph_matrix (f->current_matrix);
853
854 /* Clear the matrix of the menu bar window, if such a window exists.
855 The menu bar window is currently used to display menus on X when
856 no toolkit support is compiled in. */
857 if (WINDOWP (f->menu_bar_window))
858 clear_glyph_matrix (XWINDOW (f->menu_bar_window)->current_matrix);
859
9ea173e8
GM
860 /* Clear the matrix of the tool-bar window, if any. */
861 if (WINDOWP (f->tool_bar_window))
862 clear_glyph_matrix (XWINDOW (f->tool_bar_window)->current_matrix);
5f5c8ee5
GM
863
864 /* Clear current window matrices. */
865 xassert (WINDOWP (FRAME_ROOT_WINDOW (f)));
866 clear_window_matrices (XWINDOW (FRAME_ROOT_WINDOW (f)), 0);
867}
868
869
870/* Clear out all display lines of F for a coming redisplay. */
871
872void
971de7fb 873clear_desired_matrices (register struct frame *f)
5f5c8ee5
GM
874{
875 if (f->desired_matrix)
876 clear_glyph_matrix (f->desired_matrix);
177c0ea7 877
5f5c8ee5
GM
878 if (WINDOWP (f->menu_bar_window))
879 clear_glyph_matrix (XWINDOW (f->menu_bar_window)->desired_matrix);
880
9ea173e8
GM
881 if (WINDOWP (f->tool_bar_window))
882 clear_glyph_matrix (XWINDOW (f->tool_bar_window)->desired_matrix);
5f5c8ee5
GM
883
884 /* Do it for window matrices. */
885 xassert (WINDOWP (FRAME_ROOT_WINDOW (f)));
886 clear_window_matrices (XWINDOW (FRAME_ROOT_WINDOW (f)), 1);
887}
888
889
890/* Clear matrices in window tree rooted in W. If DESIRED_P is
891 non-zero clear desired matrices, otherwise clear current matrices. */
892
893static void
971de7fb 894clear_window_matrices (struct window *w, int desired_p)
5f5c8ee5
GM
895{
896 while (w)
897 {
898 if (!NILP (w->hchild))
899 {
900 xassert (WINDOWP (w->hchild));
901 clear_window_matrices (XWINDOW (w->hchild), desired_p);
902 }
903 else if (!NILP (w->vchild))
904 {
905 xassert (WINDOWP (w->vchild));
906 clear_window_matrices (XWINDOW (w->vchild), desired_p);
907 }
908 else
909 {
910 if (desired_p)
911 clear_glyph_matrix (w->desired_matrix);
912 else
913 {
914 clear_glyph_matrix (w->current_matrix);
915 w->window_end_valid = Qnil;
916 }
917 }
918
919 w = NILP (w->next) ? 0 : XWINDOW (w->next);
920 }
921}
922
923
924\f
925/***********************************************************************
926 Glyph Rows
927
928 See dispextern.h for an overall explanation of glyph rows.
929 ***********************************************************************/
930
931/* Clear glyph row ROW. Do it in a way that makes it robust against
932 changes in the glyph_row structure, i.e. addition or removal of
933 structure members. */
934
2cca872d
KH
935static struct glyph_row null_row;
936
5f5c8ee5 937void
971de7fb 938clear_glyph_row (struct glyph_row *row)
5f5c8ee5
GM
939{
940 struct glyph *p[1 + LAST_AREA];
5f5c8ee5
GM
941
942 /* Save pointers. */
943 p[LEFT_MARGIN_AREA] = row->glyphs[LEFT_MARGIN_AREA];
944 p[TEXT_AREA] = row->glyphs[TEXT_AREA];
945 p[RIGHT_MARGIN_AREA] = row->glyphs[RIGHT_MARGIN_AREA];
946 p[LAST_AREA] = row->glyphs[LAST_AREA];
947
948 /* Clear. */
949 *row = null_row;
950
951 /* Restore pointers. */
952 row->glyphs[LEFT_MARGIN_AREA] = p[LEFT_MARGIN_AREA];
953 row->glyphs[TEXT_AREA] = p[TEXT_AREA];
954 row->glyphs[RIGHT_MARGIN_AREA] = p[RIGHT_MARGIN_AREA];
955 row->glyphs[LAST_AREA] = p[LAST_AREA];
45560b1a
GM
956
957#if 0 /* At some point, some bit-fields of struct glyph were not set,
958 which made glyphs unequal when compared with GLYPH_EQUAL_P.
959 Redisplay outputs such glyphs, and flickering effects were
960 the result. This also depended on the contents of memory
961 returned by xmalloc. If flickering happens again, activate
153a073c 962 the code below. If the flickering is gone with that, chances
45560b1a 963 are that the flickering has the same reason as here. */
72af86bd 964 memset (p[0], 0, (char *) p[LAST_AREA] - (char *) p[0]);
45560b1a 965#endif
5f5c8ee5
GM
966}
967
968
969/* Make ROW an empty, enabled row of canonical character height,
970 in window W starting at y-position Y. */
971
972void
971de7fb 973blank_row (struct window *w, struct glyph_row *row, int y)
5f5c8ee5
GM
974{
975 int min_y, max_y;
177c0ea7 976
7df02016
KS
977 min_y = WINDOW_HEADER_LINE_HEIGHT (w);
978 max_y = WINDOW_BOX_HEIGHT_NO_MODE_LINE (w);
177c0ea7 979
5f5c8ee5
GM
980 clear_glyph_row (row);
981 row->y = y;
408f5064 982 row->ascent = row->phys_ascent = 0;
7df02016 983 row->height = row->phys_height = FRAME_LINE_HEIGHT (XFRAME (w->frame));
d6c747a4 984 row->visible_height = row->height;
177c0ea7 985
5f5c8ee5 986 if (row->y < min_y)
d6c747a4
GM
987 row->visible_height -= min_y - row->y;
988 if (row->y + row->height > max_y)
989 row->visible_height -= row->y + row->height - max_y;
5f5c8ee5
GM
990
991 row->enabled_p = 1;
992}
993
994
995/* Increment buffer positions in glyph row ROW. DELTA and DELTA_BYTES
996 are the amounts by which to change positions. Note that the first
997 glyph of the text area of a row can have a buffer position even if
998 the used count of the text area is zero. Such rows display line
999 ends. */
1000
5bf46f05 1001static void
ace1712c
EZ
1002increment_row_positions (struct glyph_row *row,
1003 EMACS_INT delta, EMACS_INT delta_bytes)
5f5c8ee5
GM
1004{
1005 int area, i;
1006
1007 /* Increment start and end positions. */
1008 MATRIX_ROW_START_CHARPOS (row) += delta;
1009 MATRIX_ROW_START_BYTEPOS (row) += delta_bytes;
1010 MATRIX_ROW_END_CHARPOS (row) += delta;
1011 MATRIX_ROW_END_BYTEPOS (row) += delta_bytes;
d36fe237
EZ
1012 CHARPOS (row->start.pos) += delta;
1013 BYTEPOS (row->start.pos) += delta_bytes;
1014 CHARPOS (row->end.pos) += delta;
1015 BYTEPOS (row->end.pos) += delta_bytes;
5f5c8ee5 1016
5cacdcfd
KS
1017 if (!row->enabled_p)
1018 return;
1019
5f5c8ee5
GM
1020 /* Increment positions in glyphs. */
1021 for (area = 0; area < LAST_AREA; ++area)
1022 for (i = 0; i < row->used[area]; ++i)
1023 if (BUFFERP (row->glyphs[area][i].object)
1024 && row->glyphs[area][i].charpos > 0)
1025 row->glyphs[area][i].charpos += delta;
1026
1027 /* Capture the case of rows displaying a line end. */
1028 if (row->used[TEXT_AREA] == 0
1029 && MATRIX_ROW_DISPLAYS_TEXT_P (row))
1030 row->glyphs[TEXT_AREA]->charpos += delta;
1031}
1032
1033
9af3e742 1034#if 0
5f5c8ee5
GM
1035/* Swap glyphs between two glyph rows A and B. This exchanges glyph
1036 contents, i.e. glyph structure contents are exchanged between A and
1037 B without changing glyph pointers in A and B. */
1038
1039static void
1dae0f0a 1040swap_glyphs_in_rows (struct glyph_row *a, struct glyph_row *b)
5f5c8ee5
GM
1041{
1042 int area;
1043
1044 for (area = 0; area < LAST_AREA; ++area)
1045 {
1046 /* Number of glyphs to swap. */
1047 int max_used = max (a->used[area], b->used[area]);
1048
1049 /* Start of glyphs in area of row A. */
1050 struct glyph *glyph_a = a->glyphs[area];
1051
1052 /* End + 1 of glyphs in area of row A. */
1053 struct glyph *glyph_a_end = a->glyphs[max_used];
1054
1055 /* Start of glyphs in area of row B. */
1056 struct glyph *glyph_b = b->glyphs[area];
1057
1058 while (glyph_a < glyph_a_end)
1059 {
1060 /* Non-ISO HP/UX compiler doesn't like auto struct
1061 initialization. */
1062 struct glyph temp;
1063 temp = *glyph_a;
1064 *glyph_a = *glyph_b;
1065 *glyph_b = temp;
1066 ++glyph_a;
1067 ++glyph_b;
1068 }
1069 }
1070}
1071
9af3e742 1072#endif /* 0 */
5f5c8ee5 1073
015137db
EZ
1074/* Exchange pointers to glyph memory between glyph rows A and B. Also
1075 exchange the used[] array and the hash values of the rows, because
1076 these should all go together for the row's hash value to be
1077 correct. */
5f5c8ee5 1078
55d4c1b2 1079static inline void
971de7fb 1080swap_glyph_pointers (struct glyph_row *a, struct glyph_row *b)
5f5c8ee5
GM
1081{
1082 int i;
015137db
EZ
1083 unsigned hash_tem = a->hash;
1084
5f5c8ee5
GM
1085 for (i = 0; i < LAST_AREA + 1; ++i)
1086 {
1087 struct glyph *temp = a->glyphs[i];
015137db
EZ
1088 short used_tem = a->used[i];
1089
5f5c8ee5
GM
1090 a->glyphs[i] = b->glyphs[i];
1091 b->glyphs[i] = temp;
015137db
EZ
1092 a->used[i] = b->used[i];
1093 b->used[i] = used_tem;
5f5c8ee5 1094 }
015137db
EZ
1095 a->hash = b->hash;
1096 b->hash = hash_tem;
5f5c8ee5
GM
1097}
1098
1099
1100/* Copy glyph row structure FROM to glyph row structure TO, except
015137db
EZ
1101 that glyph pointers, the `used' counts, and the hash values in the
1102 structures are left unchanged. */
5f5c8ee5 1103
55d4c1b2 1104static inline void
971de7fb 1105copy_row_except_pointers (struct glyph_row *to, struct glyph_row *from)
5f5c8ee5
GM
1106{
1107 struct glyph *pointers[1 + LAST_AREA];
015137db
EZ
1108 short used[1 + LAST_AREA];
1109 unsigned hashval;
5f5c8ee5
GM
1110
1111 /* Save glyph pointers of TO. */
72af86bd 1112 memcpy (pointers, to->glyphs, sizeof to->glyphs);
015137db
EZ
1113 memcpy (used, to->used, sizeof to->used);
1114 hashval = to->hash;
5f5c8ee5
GM
1115
1116 /* Do a structure assignment. */
1117 *to = *from;
1118
1119 /* Restore original pointers of TO. */
72af86bd 1120 memcpy (to->glyphs, pointers, sizeof to->glyphs);
015137db
EZ
1121 memcpy (to->used, used, sizeof to->used);
1122 to->hash = hashval;
5f5c8ee5
GM
1123}
1124
1125
5f5c8ee5
GM
1126/* Assign glyph row FROM to glyph row TO. This works like a structure
1127 assignment TO = FROM, except that glyph pointers are not copied but
1128 exchanged between TO and FROM. Pointers must be exchanged to avoid
1129 a memory leak. */
1130
55d4c1b2 1131static inline void
971de7fb 1132assign_row (struct glyph_row *to, struct glyph_row *from)
5f5c8ee5
GM
1133{
1134 swap_glyph_pointers (to, from);
1135 copy_row_except_pointers (to, from);
1136}
1137
1138
1139/* Test whether the glyph memory of the glyph row WINDOW_ROW, which is
1140 a row in a window matrix, is a slice of the glyph memory of the
1141 glyph row FRAME_ROW which is a row in a frame glyph matrix. Value
1142 is non-zero if the glyph memory of WINDOW_ROW is part of the glyph
1143 memory of FRAME_ROW. */
1144
2d5912c1 1145#if GLYPH_DEBUG
9339e87f 1146
5f5c8ee5 1147static int
59fc5cf9 1148glyph_row_slice_p (struct glyph_row *window_row, struct glyph_row *frame_row)
5f5c8ee5
GM
1149{
1150 struct glyph *window_glyph_start = window_row->glyphs[0];
1151 struct glyph *frame_glyph_start = frame_row->glyphs[0];
1152 struct glyph *frame_glyph_end = frame_row->glyphs[LAST_AREA];
1153
1154 return (frame_glyph_start <= window_glyph_start
1155 && window_glyph_start < frame_glyph_end);
1156}
1157
9339e87f 1158#endif /* GLYPH_DEBUG */
5f5c8ee5 1159
9af3e742
GM
1160#if 0
1161
5f5c8ee5
GM
1162/* Find the row in the window glyph matrix WINDOW_MATRIX being a slice
1163 of ROW in the frame matrix FRAME_MATRIX. Value is null if no row
1164 in WINDOW_MATRIX is found satisfying the condition. */
1165
1166static struct glyph_row *
59fc5cf9
AS
1167find_glyph_row_slice (struct glyph_matrix *window_matrix,
1168 struct glyph_matrix *frame_matrix, int row)
5f5c8ee5
GM
1169{
1170 int i;
1171
1172 xassert (row >= 0 && row < frame_matrix->nrows);
1173
1174 for (i = 0; i < window_matrix->nrows; ++i)
1175 if (glyph_row_slice_p (window_matrix->rows + i,
1176 frame_matrix->rows + row))
1177 break;
1178
1179 return i < window_matrix->nrows ? window_matrix->rows + i : 0;
1180}
1181
9af3e742 1182#endif /* 0 */
5f5c8ee5
GM
1183
1184/* Prepare ROW for display. Desired rows are cleared lazily,
1185 i.e. they are only marked as to be cleared by setting their
1186 enabled_p flag to zero. When a row is to be displayed, a prior
1187 call to this function really clears it. */
1188
1189void
971de7fb 1190prepare_desired_row (struct glyph_row *row)
5f5c8ee5
GM
1191{
1192 if (!row->enabled_p)
1193 {
dfd153ae 1194 int rp = row->reversed_p;
5009f85e 1195
5f5c8ee5
GM
1196 clear_glyph_row (row);
1197 row->enabled_p = 1;
5009f85e 1198 row->reversed_p = rp;
5f5c8ee5
GM
1199 }
1200}
1201
1202
1203/* Return a hash code for glyph row ROW. */
1204
2f7c71a1 1205static int
971de7fb 1206line_hash_code (struct glyph_row *row)
5f5c8ee5
GM
1207{
1208 int hash = 0;
177c0ea7 1209
5f5c8ee5
GM
1210 if (row->enabled_p)
1211 {
4cecaab8
MB
1212 struct glyph *glyph = row->glyphs[TEXT_AREA];
1213 struct glyph *end = glyph + row->used[TEXT_AREA];
1214
1215 while (glyph < end)
1216 {
1217 int c = glyph->u.ch;
1218 int face_id = glyph->face_id;
daf01701 1219 if (FRAME_MUST_WRITE_SPACES (SELECTED_FRAME ())) /* XXX Is SELECTED_FRAME OK here? */
4cecaab8
MB
1220 c -= SPACEGLYPH;
1221 hash = (((hash << 4) + (hash >> 24)) & 0x0fffffff) + c;
1222 hash = (((hash << 4) + (hash >> 24)) & 0x0fffffff) + face_id;
1223 ++glyph;
1224 }
5f5c8ee5 1225
4cecaab8
MB
1226 if (hash == 0)
1227 hash = 1;
5f5c8ee5
GM
1228 }
1229
1230 return hash;
1231}
1232
1233
153a073c 1234/* Return the cost of drawing line VPOS in MATRIX. The cost equals
5f5c8ee5
GM
1235 the number of characters in the line. If must_write_spaces is
1236 zero, leading and trailing spaces are ignored. */
1237
dfd153ae 1238static int
971de7fb 1239line_draw_cost (struct glyph_matrix *matrix, int vpos)
5f5c8ee5
GM
1240{
1241 struct glyph_row *row = matrix->rows + vpos;
1242 struct glyph *beg = row->glyphs[TEXT_AREA];
1243 struct glyph *end = beg + row->used[TEXT_AREA];
1244 int len;
1245 Lisp_Object *glyph_table_base = GLYPH_TABLE_BASE;
ca9ce8f2 1246 ptrdiff_t glyph_table_len = GLYPH_TABLE_LENGTH;
5f5c8ee5
GM
1247
1248 /* Ignore trailing and leading spaces if we can. */
daf01701 1249 if (!FRAME_MUST_WRITE_SPACES (SELECTED_FRAME ())) /* XXX Is SELECTED_FRAME OK here? */
5f5c8ee5
GM
1250 {
1251 /* Skip from the end over trailing spaces. */
2b4ec4d7 1252 while (end > beg && CHAR_GLYPH_SPACE_P (*(end - 1)))
5f5c8ee5
GM
1253 --end;
1254
177c0ea7 1255 /* All blank line. */
5f5c8ee5
GM
1256 if (end == beg)
1257 return 0;
1258
1259 /* Skip over leading spaces. */
1260 while (CHAR_GLYPH_SPACE_P (*beg))
1261 ++beg;
1262 }
1263
1264 /* If we don't have a glyph-table, each glyph is one character,
1265 so return the number of glyphs. */
1266 if (glyph_table_base == 0)
1267 len = end - beg;
1268 else
1269 {
1270 /* Otherwise, scan the glyphs and accumulate their total length
1271 in LEN. */
1272 len = 0;
1273 while (beg < end)
1274 {
3fc809e2 1275 GLYPH g;
177c0ea7 1276
3fc809e2
KS
1277 SET_GLYPH_FROM_CHAR_GLYPH (g, *beg);
1278
565b39a8 1279 if (GLYPH_INVALID_P (g)
42186983 1280 || GLYPH_SIMPLE_P (glyph_table_base, glyph_table_len, g))
5f5c8ee5
GM
1281 len += 1;
1282 else
1283 len += GLYPH_LENGTH (glyph_table_base, g);
177c0ea7 1284
5f5c8ee5
GM
1285 ++beg;
1286 }
1287 }
177c0ea7 1288
5f5c8ee5
GM
1289 return len;
1290}
1291
1292
1293/* Test two glyph rows A and B for equality. Value is non-zero if A
6b1f9ba4
JB
1294 and B have equal contents. MOUSE_FACE_P non-zero means compare the
1295 mouse_face_p flags of A and B, too. */
5f5c8ee5 1296
55d4c1b2 1297static inline int
6b1f9ba4 1298row_equal_p (struct glyph_row *a, struct glyph_row *b, int mouse_face_p)
5f5c8ee5 1299{
7a7270dd
EZ
1300 xassert (verify_row_hash (a));
1301 xassert (verify_row_hash (b));
1302
5f5c8ee5
GM
1303 if (a == b)
1304 return 1;
1305 else if (a->hash != b->hash)
1306 return 0;
1307 else
1308 {
1309 struct glyph *a_glyph, *b_glyph, *a_end;
1310 int area;
1311
e4e0bee9
GM
1312 if (mouse_face_p && a->mouse_face_p != b->mouse_face_p)
1313 return 0;
1314
5f5c8ee5
GM
1315 /* Compare glyphs. */
1316 for (area = LEFT_MARGIN_AREA; area < LAST_AREA; ++area)
1317 {
1318 if (a->used[area] != b->used[area])
1319 return 0;
177c0ea7 1320
5f5c8ee5
GM
1321 a_glyph = a->glyphs[area];
1322 a_end = a_glyph + a->used[area];
1323 b_glyph = b->glyphs[area];
177c0ea7 1324
5f5c8ee5
GM
1325 while (a_glyph < a_end
1326 && GLYPH_EQUAL_P (a_glyph, b_glyph))
1327 ++a_glyph, ++b_glyph;
177c0ea7 1328
5f5c8ee5
GM
1329 if (a_glyph != a_end)
1330 return 0;
1331 }
1332
6b61353c
KH
1333 if (a->fill_line_p != b->fill_line_p
1334 || a->cursor_in_fringe_p != b->cursor_in_fringe_p
1335 || a->left_fringe_bitmap != b->left_fringe_bitmap
1336 || a->left_fringe_face_id != b->left_fringe_face_id
e61124cd 1337 || a->left_fringe_offset != b->left_fringe_offset
6b61353c
KH
1338 || a->right_fringe_bitmap != b->right_fringe_bitmap
1339 || a->right_fringe_face_id != b->right_fringe_face_id
e61124cd
YM
1340 || a->right_fringe_offset != b->right_fringe_offset
1341 || a->fringe_bitmap_periodic_p != b->fringe_bitmap_periodic_p
3d4a365f 1342 || a->overlay_arrow_bitmap != b->overlay_arrow_bitmap
6b61353c 1343 || a->exact_window_width_line_p != b->exact_window_width_line_p
408f5064 1344 || a->overlapped_p != b->overlapped_p
5f5c8ee5
GM
1345 || (MATRIX_ROW_CONTINUATION_LINE_P (a)
1346 != MATRIX_ROW_CONTINUATION_LINE_P (b))
918f4159 1347 || a->reversed_p != b->reversed_p
5f5c8ee5
GM
1348 /* Different partially visible characters on left margin. */
1349 || a->x != b->x
1350 /* Different height. */
1351 || a->ascent != b->ascent
408f5064
GM
1352 || a->phys_ascent != b->phys_ascent
1353 || a->phys_height != b->phys_height
5f5c8ee5
GM
1354 || a->visible_height != b->visible_height)
1355 return 0;
1356 }
1357
1358 return 1;
1359}
1360
1361
1362\f
1363/***********************************************************************
1364 Glyph Pool
1365
1366 See dispextern.h for an overall explanation of glyph pools.
1367 ***********************************************************************/
1368
1369/* Allocate a glyph_pool structure. The structure returned is
1370 initialized with zeros. The global variable glyph_pool_count is
1371 incremented for each pool allocated. */
1372
1373static struct glyph_pool *
971de7fb 1374new_glyph_pool (void)
5f5c8ee5
GM
1375{
1376 struct glyph_pool *result;
1377
1378 /* Allocate a new glyph_pool and clear it. */
1379 result = (struct glyph_pool *) xmalloc (sizeof *result);
72af86bd 1380 memset (result, 0, sizeof *result);
177c0ea7 1381
5f5c8ee5
GM
1382 /* For memory leak and double deletion checking. */
1383 ++glyph_pool_count;
177c0ea7 1384
5f5c8ee5
GM
1385 return result;
1386}
1387
1388
1389/* Free a glyph_pool structure POOL. The function may be called with
1390 a null POOL pointer. The global variable glyph_pool_count is
1391 decremented with every pool structure freed. If this count gets
1392 negative, more structures were freed than allocated, i.e. one
1393 structure must have been freed more than once or a bogus pointer
1394 was passed to free_glyph_pool. */
1395
1396static void
971de7fb 1397free_glyph_pool (struct glyph_pool *pool)
5f5c8ee5
GM
1398{
1399 if (pool)
1400 {
153a073c 1401 /* More freed than allocated? */
5f5c8ee5
GM
1402 --glyph_pool_count;
1403 xassert (glyph_pool_count >= 0);
1404
1405 xfree (pool->glyphs);
1406 xfree (pool);
1407 }
1408}
1409
1410
1411/* Enlarge a glyph pool POOL. MATRIX_DIM gives the number of rows and
1412 columns we need. This function never shrinks a pool. The only
1413 case in which this would make sense, would be when a frame's size
1414 is changed from a large value to a smaller one. But, if someone
1415 does it once, we can expect that he will do it again.
1416
1417 Value is non-zero if the pool changed in a way which makes
1418 re-adjusting window glyph matrices necessary. */
1419
1420static int
971de7fb 1421realloc_glyph_pool (struct glyph_pool *pool, struct dim matrix_dim)
5f5c8ee5 1422{
ca9ce8f2 1423 ptrdiff_t needed;
5f5c8ee5
GM
1424 int changed_p;
1425
1426 changed_p = (pool->glyphs == 0
1427 || matrix_dim.height != pool->nrows
1428 || matrix_dim.width != pool->ncolumns);
1429
1430 /* Enlarge the glyph pool. */
ca9ce8f2 1431 needed = matrix_dim.width;
0065d054
PE
1432 if (INT_MULTIPLY_OVERFLOW (needed, matrix_dim.height))
1433 memory_full (SIZE_MAX);
ca9ce8f2 1434 needed *= matrix_dim.height;
5f5c8ee5
GM
1435 if (needed > pool->nglyphs)
1436 {
0065d054
PE
1437 ptrdiff_t old_nglyphs = pool->nglyphs;
1438 pool->glyphs = xpalloc (pool->glyphs, &pool->nglyphs,
1439 needed - old_nglyphs, -1, sizeof *pool->glyphs);
1440 memset (pool->glyphs + old_nglyphs, 0,
1441 (pool->nglyphs - old_nglyphs) * sizeof *pool->glyphs);
5f5c8ee5
GM
1442 }
1443
153a073c 1444 /* Remember the number of rows and columns because (a) we use them
5f5c8ee5
GM
1445 to do sanity checks, and (b) the number of columns determines
1446 where rows in the frame matrix start---this must be available to
1447 determine pointers to rows of window sub-matrices. */
1448 pool->nrows = matrix_dim.height;
1449 pool->ncolumns = matrix_dim.width;
177c0ea7 1450
5f5c8ee5
GM
1451 return changed_p;
1452}
1453
1454
1455\f
1456/***********************************************************************
1457 Debug Code
1458 ***********************************************************************/
1459
1460#if GLYPH_DEBUG
1461
a13396c9 1462
28d440ab
KL
1463/* Flush standard output. This is sometimes useful to call from the debugger.
1464 XXX Maybe this should be changed to flush the current terminal instead of
1465 stdout.
1466*/
a13396c9 1467
85fece3e
PE
1468void flush_stdout (void) EXTERNALLY_VISIBLE;
1469
a13396c9 1470void
59fc5cf9 1471flush_stdout (void)
a13396c9
GM
1472{
1473 fflush (stdout);
1474}
1475
1476
5f5c8ee5
GM
1477/* Check that no glyph pointers have been lost in MATRIX. If a
1478 pointer has been lost, e.g. by using a structure assignment between
1479 rows, at least one pointer must occur more than once in the rows of
1480 MATRIX. */
1481
1482void
59fc5cf9 1483check_matrix_pointer_lossage (struct glyph_matrix *matrix)
5f5c8ee5
GM
1484{
1485 int i, j;
177c0ea7 1486
5f5c8ee5
GM
1487 for (i = 0; i < matrix->nrows; ++i)
1488 for (j = 0; j < matrix->nrows; ++j)
1489 xassert (i == j
1490 || (matrix->rows[i].glyphs[TEXT_AREA]
1491 != matrix->rows[j].glyphs[TEXT_AREA]));
1492}
1493
1494
1495/* Get a pointer to glyph row ROW in MATRIX, with bounds checks. */
1496
1497struct glyph_row *
59fc5cf9 1498matrix_row (struct glyph_matrix *matrix, int row)
5f5c8ee5
GM
1499{
1500 xassert (matrix && matrix->rows);
1501 xassert (row >= 0 && row < matrix->nrows);
1502
1503 /* That's really too slow for normal testing because this function
1504 is called almost everywhere. Although---it's still astonishingly
1505 fast, so it is valuable to have for debugging purposes. */
1506#if 0
1507 check_matrix_pointer_lossage (matrix);
1508#endif
177c0ea7 1509
5f5c8ee5
GM
1510 return matrix->rows + row;
1511}
1512
1513
1514#if 0 /* This function makes invalid assumptions when text is
1515 partially invisible. But it might come handy for debugging
1516 nevertheless. */
1517
1518/* Check invariants that must hold for an up to date current matrix of
1519 window W. */
1520
1521static void
59fc5cf9 1522check_matrix_invariants (struct window *w)
5f5c8ee5
GM
1523{
1524 struct glyph_matrix *matrix = w->current_matrix;
1525 int yb = window_text_bottom_y (w);
1526 struct glyph_row *row = matrix->rows;
1527 struct glyph_row *last_text_row = NULL;
1528 struct buffer *saved = current_buffer;
1529 struct buffer *buffer = XBUFFER (w->buffer);
1530 int c;
177c0ea7 1531
5f5c8ee5
GM
1532 /* This can sometimes happen for a fresh window. */
1533 if (matrix->nrows < 2)
1534 return;
1535
1536 set_buffer_temp (buffer);
1537
1538 /* Note: last row is always reserved for the mode line. */
1539 while (MATRIX_ROW_DISPLAYS_TEXT_P (row)
1540 && MATRIX_ROW_BOTTOM_Y (row) < yb)
1541 {
1542 struct glyph_row *next = row + 1;
1543
1544 if (MATRIX_ROW_DISPLAYS_TEXT_P (row))
1545 last_text_row = row;
1546
1547 /* Check that character and byte positions are in sync. */
1548 xassert (MATRIX_ROW_START_BYTEPOS (row)
1549 == CHAR_TO_BYTE (MATRIX_ROW_START_CHARPOS (row)));
d36fe237
EZ
1550 xassert (BYTEPOS (row->start.pos)
1551 == CHAR_TO_BYTE (CHARPOS (row->start.pos)));
5f5c8ee5
GM
1552
1553 /* CHAR_TO_BYTE aborts when invoked for a position > Z. We can
1554 have such a position temporarily in case of a minibuffer
1555 displaying something like `[Sole completion]' at its end. */
1556 if (MATRIX_ROW_END_CHARPOS (row) < BUF_ZV (current_buffer))
d36fe237
EZ
1557 {
1558 xassert (MATRIX_ROW_END_BYTEPOS (row)
1559 == CHAR_TO_BYTE (MATRIX_ROW_END_CHARPOS (row)));
1560 xassert (BYTEPOS (row->end.pos)
1561 == CHAR_TO_BYTE (CHARPOS (row->end.pos)));
1562 }
5f5c8ee5
GM
1563
1564 /* Check that end position of `row' is equal to start position
1565 of next row. */
1566 if (next->enabled_p && MATRIX_ROW_DISPLAYS_TEXT_P (next))
1567 {
1568 xassert (MATRIX_ROW_END_CHARPOS (row)
1569 == MATRIX_ROW_START_CHARPOS (next));
1570 xassert (MATRIX_ROW_END_BYTEPOS (row)
1571 == MATRIX_ROW_START_BYTEPOS (next));
d36fe237
EZ
1572 xassert (CHARPOS (row->end.pos) == CHARPOS (next->start.pos));
1573 xassert (BYTEPOS (row->end.pos) == BYTEPOS (next->start.pos));
5f5c8ee5
GM
1574 }
1575 row = next;
1576 }
1577
1578 xassert (w->current_matrix->nrows == w->desired_matrix->nrows);
1579 xassert (w->desired_matrix->rows != NULL);
1580 set_buffer_temp (saved);
1581}
1582
1583#endif /* 0 */
1584
1585#endif /* GLYPH_DEBUG != 0 */
1586
1587
1588\f
1589/**********************************************************************
1590 Allocating/ Adjusting Glyph Matrices
1591 **********************************************************************/
1592
1593/* Allocate glyph matrices over a window tree for a frame-based
1594 redisplay
1595
1596 X and Y are column/row within the frame glyph matrix where
1597 sub-matrices for the window tree rooted at WINDOW must be
8ce2650d
YM
1598 allocated. DIM_ONLY_P non-zero means that the caller of this
1599 function is only interested in the result matrix dimension, and
1600 matrix adjustments should not be performed.
5f5c8ee5
GM
1601
1602 The function returns the total width/height of the sub-matrices of
1603 the window tree. If called on a frame root window, the computation
1604 will take the mini-buffer window into account.
1605
1606 *WINDOW_CHANGE_FLAGS is set to a bit mask with bits
1607
1608 NEW_LEAF_MATRIX set if any window in the tree did not have a
1609 glyph matrices yet, and
1610
1611 CHANGED_LEAF_MATRIX set if the dimension or location of a matrix of
1612 any window in the tree will be changed or have been changed (see
153a073c 1613 DIM_ONLY_P)
5f5c8ee5
GM
1614
1615 *WINDOW_CHANGE_FLAGS must be initialized by the caller of this
1616 function.
1617
1618 Windows are arranged into chains of windows on the same level
1619 through the next fields of window structures. Such a level can be
1620 either a sequence of horizontally adjacent windows from left to
1621 right, or a sequence of vertically adjacent windows from top to
1622 bottom. Each window in a horizontal sequence can be either a leaf
1623 window or a vertical sequence; a window in a vertical sequence can
1624 be either a leaf or a horizontal sequence. All windows in a
1625 horizontal sequence have the same height, and all windows in a
1626 vertical sequence have the same width.
1627
1628 This function uses, for historical reasons, a more general
1629 algorithm to determine glyph matrix dimensions that would be
1630 necessary.
1631
1632 The matrix height of a horizontal sequence is determined by the
1633 maximum height of any matrix in the sequence. The matrix width of
1634 a horizontal sequence is computed by adding up matrix widths of
1635 windows in the sequence.
1636
1637 |<------- result width ------->|
1638 +---------+----------+---------+ ---
1639 | | | | |
1640 | | | |
1641 +---------+ | | result height
1642 | +---------+
1643 | | |
1644 +----------+ ---
1645
1646 The matrix width of a vertical sequence is the maximum matrix width
1647 of any window in the sequence. Its height is computed by adding up
1648 matrix heights of windows in the sequence.
1649
1650 |<---- result width -->|
1651 +---------+ ---
1652 | | |
1653 | | |
1654 +---------+--+ |
1655 | | |
1656 | | result height
1657 | |
1658 +------------+---------+ |
1659 | | |
1660 | | |
1661 +------------+---------+ --- */
1662
1663/* Bit indicating that a new matrix will be allocated or has been
1664 allocated. */
1665
1666#define NEW_LEAF_MATRIX (1 << 0)
1667
1668/* Bit indicating that a matrix will or has changed its location or
1669 size. */
1670
1671#define CHANGED_LEAF_MATRIX (1 << 1)
1672
1673static struct dim
6f704c76
DN
1674allocate_matrices_for_frame_redisplay (Lisp_Object window, int x, int y,
1675 int dim_only_p, int *window_change_flags)
5f5c8ee5
GM
1676{
1677 struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (window)));
1678 int x0 = x, y0 = y;
1679 int wmax = 0, hmax = 0;
1680 struct dim total;
1681 struct dim dim;
1682 struct window *w;
1683 int in_horz_combination_p;
1684
1685 /* What combination is WINDOW part of? Compute this once since the
1686 result is the same for all windows in the `next' chain. The
1687 special case of a root window (parent equal to nil) is treated
1688 like a vertical combination because a root window's `next'
1689 points to the mini-buffer window, if any, which is arranged
1690 vertically below other windows. */
1691 in_horz_combination_p
1692 = (!NILP (XWINDOW (window)->parent)
1693 && !NILP (XWINDOW (XWINDOW (window)->parent)->hchild));
1694
1695 /* For WINDOW and all windows on the same level. */
177c0ea7 1696 do
5f5c8ee5
GM
1697 {
1698 w = XWINDOW (window);
1699
1700 /* Get the dimension of the window sub-matrix for W, depending
153a073c 1701 on whether this is a combination or a leaf window. */
5f5c8ee5 1702 if (!NILP (w->hchild))
177c0ea7 1703 dim = allocate_matrices_for_frame_redisplay (w->hchild, x, y,
5f5c8ee5
GM
1704 dim_only_p,
1705 window_change_flags);
1706 else if (!NILP (w->vchild))
177c0ea7 1707 dim = allocate_matrices_for_frame_redisplay (w->vchild, x, y,
5f5c8ee5
GM
1708 dim_only_p,
1709 window_change_flags);
1710 else
1711 {
1712 /* If not already done, allocate sub-matrix structures. */
1713 if (w->desired_matrix == NULL)
1714 {
1715 w->desired_matrix = new_glyph_matrix (f->desired_pool);
1716 w->current_matrix = new_glyph_matrix (f->current_pool);
1717 *window_change_flags |= NEW_LEAF_MATRIX;
1718 }
177c0ea7 1719
5f5c8ee5
GM
1720 /* Width and height MUST be chosen so that there are no
1721 holes in the frame matrix. */
5d3cc43c
GM
1722 dim.width = required_matrix_width (w);
1723 dim.height = required_matrix_height (w);
5f5c8ee5
GM
1724
1725 /* Will matrix be re-allocated? */
1726 if (x != w->desired_matrix->matrix_x
1727 || y != w->desired_matrix->matrix_y
1728 || dim.width != w->desired_matrix->matrix_w
1729 || dim.height != w->desired_matrix->matrix_h
1730 || (margin_glyphs_to_reserve (w, dim.width,
cc834cf9 1731 w->left_margin_cols)
5f5c8ee5
GM
1732 != w->desired_matrix->left_margin_glyphs)
1733 || (margin_glyphs_to_reserve (w, dim.width,
cc834cf9 1734 w->right_margin_cols)
5f5c8ee5
GM
1735 != w->desired_matrix->right_margin_glyphs))
1736 *window_change_flags |= CHANGED_LEAF_MATRIX;
1737
1738 /* Actually change matrices, if allowed. Do not consider
1739 CHANGED_LEAF_MATRIX computed above here because the pool
1740 may have been changed which we don't now here. We trust
1741 that we only will be called with DIM_ONLY_P != 0 when
1742 necessary. */
1743 if (!dim_only_p)
1744 {
1745 adjust_glyph_matrix (w, w->desired_matrix, x, y, dim);
1746 adjust_glyph_matrix (w, w->current_matrix, x, y, dim);
1747 }
1748 }
1749
1750 /* If we are part of a horizontal combination, advance x for
1751 windows to the right of W; otherwise advance y for windows
1752 below W. */
1753 if (in_horz_combination_p)
1754 x += dim.width;
177c0ea7 1755 else
5f5c8ee5
GM
1756 y += dim.height;
1757
1758 /* Remember maximum glyph matrix dimensions. */
1759 wmax = max (wmax, dim.width);
1760 hmax = max (hmax, dim.height);
1761
1762 /* Next window on same level. */
1763 window = w->next;
1764 }
1765 while (!NILP (window));
1766
1767 /* Set `total' to the total glyph matrix dimension of this window
1768 level. In a vertical combination, the width is the width of the
1769 widest window; the height is the y we finally reached, corrected
1770 by the y we started with. In a horizontal combination, the total
1771 height is the height of the tallest window, and the width is the
1772 x we finally reached, corrected by the x we started with. */
1773 if (in_horz_combination_p)
1774 {
1775 total.width = x - x0;
1776 total.height = hmax;
1777 }
177c0ea7 1778 else
5f5c8ee5
GM
1779 {
1780 total.width = wmax;
1781 total.height = y - y0;
1782 }
1783
1784 return total;
1785}
1786
1787
5d3cc43c
GM
1788/* Return the required height of glyph matrices for window W. */
1789
2f7c71a1 1790static int
971de7fb 1791required_matrix_height (struct window *w)
5d3cc43c
GM
1792{
1793#ifdef HAVE_WINDOW_SYSTEM
1794 struct frame *f = XFRAME (w->frame);
177c0ea7 1795
5d3cc43c
GM
1796 if (FRAME_WINDOW_P (f))
1797 {
1798 int ch_height = FRAME_SMALLEST_FONT_HEIGHT (f);
1ea40aa2 1799 int window_pixel_height = window_box_height (w) + eabs (w->vscroll);
5d3cc43c 1800 return (((window_pixel_height + ch_height - 1)
cc834cf9 1801 / ch_height) * w->nrows_scale_factor
5d3cc43c
GM
1802 /* One partially visible line at the top and
1803 bottom of the window. */
1804 + 2
153a073c 1805 /* 2 for header and mode line. */
5d3cc43c
GM
1806 + 2);
1807 }
1808#endif /* HAVE_WINDOW_SYSTEM */
177c0ea7 1809
7df02016 1810 return WINDOW_TOTAL_LINES (w);
5d3cc43c
GM
1811}
1812
1813
1814/* Return the required width of glyph matrices for window W. */
1815
2f7c71a1 1816static int
971de7fb 1817required_matrix_width (struct window *w)
5d3cc43c
GM
1818{
1819#ifdef HAVE_WINDOW_SYSTEM
1820 struct frame *f = XFRAME (w->frame);
1821 if (FRAME_WINDOW_P (f))
1822 {
1823 int ch_width = FRAME_SMALLEST_CHAR_WIDTH (f);
7df02016 1824 int window_pixel_width = WINDOW_TOTAL_WIDTH (w);
177c0ea7 1825
5d3cc43c
GM
1826 /* Compute number of glyphs needed in a glyph row. */
1827 return (((window_pixel_width + ch_width - 1)
cc834cf9 1828 / ch_width) * w->ncols_scale_factor
5d3cc43c
GM
1829 /* 2 partially visible columns in the text area. */
1830 + 2
1831 /* One partially visible column at the right
1832 edge of each marginal area. */
1833 + 1 + 1);
1834 }
1835#endif /* HAVE_WINDOW_SYSTEM */
1836
7df02016 1837 return XINT (w->total_cols);
5d3cc43c
GM
1838}
1839
1840
5f5c8ee5 1841/* Allocate window matrices for window-based redisplay. W is the
8ce2650d 1842 window whose matrices must be allocated/reallocated. */
177c0ea7 1843
5f5c8ee5 1844static void
971de7fb 1845allocate_matrices_for_window_redisplay (struct window *w)
5f5c8ee5 1846{
5f5c8ee5
GM
1847 while (w)
1848 {
1849 if (!NILP (w->vchild))
5d3cc43c 1850 allocate_matrices_for_window_redisplay (XWINDOW (w->vchild));
5f5c8ee5 1851 else if (!NILP (w->hchild))
5d3cc43c 1852 allocate_matrices_for_window_redisplay (XWINDOW (w->hchild));
5f5c8ee5
GM
1853 else
1854 {
1855 /* W is a leaf window. */
5f5c8ee5
GM
1856 struct dim dim;
1857
1858 /* If matrices are not yet allocated, allocate them now. */
1859 if (w->desired_matrix == NULL)
1860 {
1861 w->desired_matrix = new_glyph_matrix (NULL);
1862 w->current_matrix = new_glyph_matrix (NULL);
1863 }
1864
5d3cc43c
GM
1865 dim.width = required_matrix_width (w);
1866 dim.height = required_matrix_height (w);
5f5c8ee5
GM
1867 adjust_glyph_matrix (w, w->desired_matrix, 0, 0, dim);
1868 adjust_glyph_matrix (w, w->current_matrix, 0, 0, dim);
1869 }
177c0ea7 1870
5f5c8ee5
GM
1871 w = NILP (w->next) ? NULL : XWINDOW (w->next);
1872 }
1873}
1874
1875
1876/* Re-allocate/ re-compute glyph matrices on frame F. If F is null,
1877 do it for all frames; otherwise do it just for the given frame.
1878 This function must be called when a new frame is created, its size
1879 changes, or its window configuration changes. */
1880
1881void
971de7fb 1882adjust_glyphs (struct frame *f)
5f5c8ee5 1883{
408f5064
GM
1884 /* Block input so that expose events and other events that access
1885 glyph matrices are not processed while we are changing them. */
1886 BLOCK_INPUT;
1887
5f5c8ee5
GM
1888 if (f)
1889 adjust_frame_glyphs (f);
1890 else
1891 {
1892 Lisp_Object tail, lisp_frame;
177c0ea7 1893
5f5c8ee5
GM
1894 FOR_EACH_FRAME (tail, lisp_frame)
1895 adjust_frame_glyphs (XFRAME (lisp_frame));
1896 }
408f5064
GM
1897
1898 UNBLOCK_INPUT;
5f5c8ee5
GM
1899}
1900
1901
1902/* Adjust frame glyphs when Emacs is initialized.
177c0ea7
JB
1903
1904 To be called from init_display.
1905
5f5c8ee5
GM
1906 We need a glyph matrix because redraw will happen soon.
1907 Unfortunately, window sizes on selected_frame are not yet set to
1908 meaningful values. I believe we can assume that there are only two
1909 windows on the frame---the mini-buffer and the root window. Frame
1910 height and width seem to be correct so far. So, set the sizes of
1911 windows to estimated values. */
1912
1913static void
971de7fb 1914adjust_frame_glyphs_initially (void)
5f5c8ee5 1915{
91fb7e1b
GM
1916 struct frame *sf = SELECTED_FRAME ();
1917 struct window *root = XWINDOW (sf->root_window);
5f5c8ee5 1918 struct window *mini = XWINDOW (root->next);
7df02016
KS
1919 int frame_lines = FRAME_LINES (sf);
1920 int frame_cols = FRAME_COLS (sf);
91fb7e1b 1921 int top_margin = FRAME_TOP_MARGIN (sf);
5f5c8ee5
GM
1922
1923 /* Do it for the root window. */
7df02016 1924 XSETFASTINT (root->top_line, top_margin);
562dd5e9 1925 XSETFASTINT (root->total_lines, frame_lines - 1 - top_margin);
7df02016 1926 XSETFASTINT (root->total_cols, frame_cols);
5f5c8ee5
GM
1927
1928 /* Do it for the mini-buffer window. */
7df02016 1929 XSETFASTINT (mini->top_line, frame_lines - 1);
562dd5e9 1930 XSETFASTINT (mini->total_lines, 1);
7df02016 1931 XSETFASTINT (mini->total_cols, frame_cols);
5f5c8ee5 1932
91fb7e1b 1933 adjust_frame_glyphs (sf);
5f5c8ee5
GM
1934 glyphs_initialized_initially_p = 1;
1935}
177c0ea7 1936
5f5c8ee5
GM
1937
1938/* Allocate/reallocate glyph matrices of a single frame F. */
1939
1940static void
971de7fb 1941adjust_frame_glyphs (struct frame *f)
5f5c8ee5
GM
1942{
1943 if (FRAME_WINDOW_P (f))
1944 adjust_frame_glyphs_for_window_redisplay (f);
1945 else
1946 adjust_frame_glyphs_for_frame_redisplay (f);
177c0ea7 1947
5f5c8ee5
GM
1948 /* Don't forget the message buffer and the buffer for
1949 decode_mode_spec. */
1950 adjust_frame_message_buffer (f);
1951 adjust_decode_mode_spec_buffer (f);
1952
1953 f->glyphs_initialized_p = 1;
1954}
1955
075757cc
CY
1956/* Return 1 if any window in the tree has nonzero window margins. See
1957 the hack at the end of adjust_frame_glyphs_for_frame_redisplay. */
1958static int
971de7fb 1959showing_window_margins_p (struct window *w)
075757cc
CY
1960{
1961 while (w)
1962 {
1963 if (!NILP (w->hchild))
1964 {
1965 if (showing_window_margins_p (XWINDOW (w->hchild)))
1966 return 1;
1967 }
1968 else if (!NILP (w->vchild))
1969 {
1970 if (showing_window_margins_p (XWINDOW (w->vchild)))
1971 return 1;
1972 }
1973 else if (!NILP (w->left_margin_cols)
1974 || !NILP (w->right_margin_cols))
1975 return 1;
3fc809e2 1976
075757cc
CY
1977 w = NILP (w->next) ? 0 : XWINDOW (w->next);
1978 }
1979 return 0;
1980}
1981
5f5c8ee5 1982
c9f00270
GM
1983/* In the window tree with root W, build current matrices of leaf
1984 windows from the frame's current matrix. */
1985
1986static void
971de7fb 1987fake_current_matrices (Lisp_Object window)
c9f00270
GM
1988{
1989 struct window *w;
177c0ea7 1990
c9f00270
GM
1991 for (; !NILP (window); window = w->next)
1992 {
1993 w = XWINDOW (window);
177c0ea7 1994
c9f00270
GM
1995 if (!NILP (w->hchild))
1996 fake_current_matrices (w->hchild);
1997 else if (!NILP (w->vchild))
1998 fake_current_matrices (w->vchild);
1999 else
2000 {
2001 int i;
2002 struct frame *f = XFRAME (w->frame);
2003 struct glyph_matrix *m = w->current_matrix;
2004 struct glyph_matrix *fm = f->current_matrix;
2005
7df02016
KS
2006 xassert (m->matrix_h == WINDOW_TOTAL_LINES (w));
2007 xassert (m->matrix_w == WINDOW_TOTAL_COLS (w));
177c0ea7 2008
c9f00270
GM
2009 for (i = 0; i < m->matrix_h; ++i)
2010 {
2011 struct glyph_row *r = m->rows + i;
7df02016 2012 struct glyph_row *fr = fm->rows + i + WINDOW_TOP_EDGE_LINE (w);
c9f00270
GM
2013
2014 xassert (r->glyphs[TEXT_AREA] >= fr->glyphs[TEXT_AREA]
2015 && r->glyphs[LAST_AREA] <= fr->glyphs[LAST_AREA]);
2016
2017 r->enabled_p = fr->enabled_p;
2018 if (r->enabled_p)
2019 {
2020 r->used[LEFT_MARGIN_AREA] = m->left_margin_glyphs;
2021 r->used[RIGHT_MARGIN_AREA] = m->right_margin_glyphs;
2022 r->used[TEXT_AREA] = (m->matrix_w
2023 - r->used[LEFT_MARGIN_AREA]
2024 - r->used[RIGHT_MARGIN_AREA]);
2025 r->mode_line_p = 0;
c9f00270
GM
2026 }
2027 }
2028 }
2029 }
2030}
2031
2032
bccee4f2 2033/* Save away the contents of frame F's current frame matrix. Value is
153a073c 2034 a glyph matrix holding the contents of F's current frame matrix. */
c9f00270 2035
bccee4f2 2036static struct glyph_matrix *
971de7fb 2037save_current_matrix (struct frame *f)
c9f00270 2038{
bccee4f2
GM
2039 int i;
2040 struct glyph_matrix *saved;
e797dea6 2041
bccee4f2 2042 saved = (struct glyph_matrix *) xmalloc (sizeof *saved);
72af86bd 2043 memset (saved, 0, sizeof *saved);
bccee4f2
GM
2044 saved->nrows = f->current_matrix->nrows;
2045 saved->rows = (struct glyph_row *) xmalloc (saved->nrows
2046 * sizeof *saved->rows);
72af86bd 2047 memset (saved->rows, 0, saved->nrows * sizeof *saved->rows);
bccee4f2
GM
2048
2049 for (i = 0; i < saved->nrows; ++i)
31798cfe 2050 {
bccee4f2
GM
2051 struct glyph_row *from = f->current_matrix->rows + i;
2052 struct glyph_row *to = saved->rows + i;
dfd153ae 2053 ptrdiff_t nbytes = from->used[TEXT_AREA] * sizeof (struct glyph);
bccee4f2 2054 to->glyphs[TEXT_AREA] = (struct glyph *) xmalloc (nbytes);
72af86bd 2055 memcpy (to->glyphs[TEXT_AREA], from->glyphs[TEXT_AREA], nbytes);
bccee4f2 2056 to->used[TEXT_AREA] = from->used[TEXT_AREA];
e797dea6 2057 }
bccee4f2
GM
2058
2059 return saved;
2060}
2061
2062
2063/* Restore the contents of frame F's current frame matrix from SAVED,
2064 and free memory associated with SAVED. */
2065
2066static void
971de7fb 2067restore_current_matrix (struct frame *f, struct glyph_matrix *saved)
bccee4f2
GM
2068{
2069 int i;
2070
2071 for (i = 0; i < saved->nrows; ++i)
e797dea6 2072 {
bccee4f2
GM
2073 struct glyph_row *from = saved->rows + i;
2074 struct glyph_row *to = f->current_matrix->rows + i;
dfd153ae 2075 ptrdiff_t nbytes = from->used[TEXT_AREA] * sizeof (struct glyph);
72af86bd 2076 memcpy (to->glyphs[TEXT_AREA], from->glyphs[TEXT_AREA], nbytes);
e797dea6 2077 to->used[TEXT_AREA] = from->used[TEXT_AREA];
bccee4f2 2078 xfree (from->glyphs[TEXT_AREA]);
e797dea6 2079 }
177c0ea7 2080
bccee4f2
GM
2081 xfree (saved->rows);
2082 xfree (saved);
c9f00270
GM
2083}
2084
2085
bccee4f2 2086
5f5c8ee5
GM
2087/* Allocate/reallocate glyph matrices of a single frame F for
2088 frame-based redisplay. */
2089
2090static void
971de7fb 2091adjust_frame_glyphs_for_frame_redisplay (struct frame *f)
5f5c8ee5 2092{
5f5c8ee5
GM
2093 struct dim matrix_dim;
2094 int pool_changed_p;
2095 int window_change_flags;
2096 int top_window_y;
2097
2098 if (!FRAME_LIVE_P (f))
2099 return;
2100
5f5c8ee5
GM
2101 top_window_y = FRAME_TOP_MARGIN (f);
2102
2103 /* Allocate glyph pool structures if not already done. */
2104 if (f->desired_pool == NULL)
2105 {
2106 f->desired_pool = new_glyph_pool ();
2107 f->current_pool = new_glyph_pool ();
2108 }
2109
2110 /* Allocate frames matrix structures if needed. */
2111 if (f->desired_matrix == NULL)
2112 {
2113 f->desired_matrix = new_glyph_matrix (f->desired_pool);
2114 f->current_matrix = new_glyph_matrix (f->current_pool);
2115 }
177c0ea7 2116
5f5c8ee5
GM
2117 /* Compute window glyph matrices. (This takes the mini-buffer
2118 window into account). The result is the size of the frame glyph
2119 matrix needed. The variable window_change_flags is set to a bit
2120 mask indicating whether new matrices will be allocated or
2121 existing matrices change their size or location within the frame
2122 matrix. */
2123 window_change_flags = 0;
2124 matrix_dim
2125 = allocate_matrices_for_frame_redisplay (FRAME_ROOT_WINDOW (f),
2126 0, top_window_y,
5d3cc43c 2127 1,
5f5c8ee5
GM
2128 &window_change_flags);
2129
2130 /* Add in menu bar lines, if any. */
2131 matrix_dim.height += top_window_y;
2132
2133 /* Enlarge pools as necessary. */
2134 pool_changed_p = realloc_glyph_pool (f->desired_pool, matrix_dim);
2135 realloc_glyph_pool (f->current_pool, matrix_dim);
2136
177c0ea7 2137 /* Set up glyph pointers within window matrices. Do this only if
5f5c8ee5
GM
2138 absolutely necessary since it requires a frame redraw. */
2139 if (pool_changed_p || window_change_flags)
2140 {
2141 /* Do it for window matrices. */
2142 allocate_matrices_for_frame_redisplay (FRAME_ROOT_WINDOW (f),
5d3cc43c 2143 0, top_window_y, 0,
5f5c8ee5
GM
2144 &window_change_flags);
2145
2146 /* Size of frame matrices must equal size of frame. Note
2147 that we are called for X frames with window widths NOT equal
2148 to the frame width (from CHANGE_FRAME_SIZE_1). */
7df02016
KS
2149 xassert (matrix_dim.width == FRAME_COLS (f)
2150 && matrix_dim.height == FRAME_LINES (f));
177c0ea7 2151
e797dea6
GM
2152 /* Pointers to glyph memory in glyph rows are exchanged during
2153 the update phase of redisplay, which means in general that a
2154 frame's current matrix consists of pointers into both the
2155 desired and current glyph pool of the frame. Adjusting a
2156 matrix sets the frame matrix up so that pointers are all into
2157 the same pool. If we want to preserve glyph contents of the
2158 current matrix over a call to adjust_glyph_matrix, we must
2159 make a copy of the current glyphs, and restore the current
2160 matrix' contents from that copy. */
2161 if (display_completed
2162 && !FRAME_GARBAGED_P (f)
2163 && matrix_dim.width == f->current_matrix->matrix_w
075757cc
CY
2164 && matrix_dim.height == f->current_matrix->matrix_h
2165 /* For some reason, the frame glyph matrix gets corrupted if
2166 any of the windows contain margins. I haven't been able
2167 to hunt down the reason, but for the moment this prevents
2168 the problem from manifesting. -- cyd */
2169 && !showing_window_margins_p (XWINDOW (FRAME_ROOT_WINDOW (f))))
e797dea6 2170 {
bccee4f2
GM
2171 struct glyph_matrix *copy = save_current_matrix (f);
2172 adjust_glyph_matrix (NULL, f->desired_matrix, 0, 0, matrix_dim);
e797dea6 2173 adjust_glyph_matrix (NULL, f->current_matrix, 0, 0, matrix_dim);
bccee4f2 2174 restore_current_matrix (f, copy);
e797dea6
GM
2175 fake_current_matrices (FRAME_ROOT_WINDOW (f));
2176 }
c9f00270 2177 else
e797dea6 2178 {
bccee4f2 2179 adjust_glyph_matrix (NULL, f->desired_matrix, 0, 0, matrix_dim);
e797dea6
GM
2180 adjust_glyph_matrix (NULL, f->current_matrix, 0, 0, matrix_dim);
2181 SET_FRAME_GARBAGED (f);
2182 }
5f5c8ee5
GM
2183 }
2184}
2185
2186
2187/* Allocate/reallocate glyph matrices of a single frame F for
2188 window-based redisplay. */
2189
2190static void
971de7fb 2191adjust_frame_glyphs_for_window_redisplay (struct frame *f)
5f5c8ee5 2192{
5f5c8ee5 2193 xassert (FRAME_WINDOW_P (f) && FRAME_LIVE_P (f));
177c0ea7 2194
5f5c8ee5 2195 /* Allocate/reallocate window matrices. */
5d3cc43c 2196 allocate_matrices_for_window_redisplay (XWINDOW (FRAME_ROOT_WINDOW (f)));
5f5c8ee5 2197
8ce2650d 2198#ifdef HAVE_X_WINDOWS
5f5c8ee5
GM
2199 /* Allocate/ reallocate matrices of the dummy window used to display
2200 the menu bar under X when no X toolkit support is available. */
488dd4c4 2201#if ! defined (USE_X_TOOLKIT) && ! defined (USE_GTK)
5f5c8ee5
GM
2202 {
2203 /* Allocate a dummy window if not already done. */
d2d37ddc 2204 struct window *w;
5f5c8ee5
GM
2205 if (NILP (f->menu_bar_window))
2206 {
2207 f->menu_bar_window = make_window ();
2208 w = XWINDOW (f->menu_bar_window);
2209 XSETFRAME (w->frame, f);
2210 w->pseudo_window_p = 1;
2211 }
2212 else
2213 w = XWINDOW (f->menu_bar_window);
2214
2215 /* Set window dimensions to frame dimensions and allocate or
2216 adjust glyph matrices of W. */
7df02016
KS
2217 XSETFASTINT (w->top_line, 0);
2218 XSETFASTINT (w->left_col, 0);
2219 XSETFASTINT (w->total_lines, FRAME_MENU_BAR_LINES (f));
2220 XSETFASTINT (w->total_cols, FRAME_TOTAL_COLS (f));
5d3cc43c 2221 allocate_matrices_for_window_redisplay (w);
5f5c8ee5 2222 }
57714a86
YM
2223#endif /* not USE_X_TOOLKIT && not USE_GTK */
2224#endif /* HAVE_X_WINDOWS */
5f5c8ee5 2225
488dd4c4 2226#ifndef USE_GTK
d2d37ddc
PE
2227 {
2228 /* Allocate/ reallocate matrices of the tool bar window. If we
2229 don't have a tool bar window yet, make one. */
2230 struct window *w;
2231 if (NILP (f->tool_bar_window))
2232 {
2233 f->tool_bar_window = make_window ();
2234 w = XWINDOW (f->tool_bar_window);
2235 XSETFRAME (w->frame, f);
2236 w->pseudo_window_p = 1;
2237 }
2238 else
9ea173e8 2239 w = XWINDOW (f->tool_bar_window);
5f5c8ee5 2240
d2d37ddc
PE
2241 XSETFASTINT (w->top_line, FRAME_MENU_BAR_LINES (f));
2242 XSETFASTINT (w->left_col, 0);
2243 XSETFASTINT (w->total_lines, FRAME_TOOL_BAR_LINES (f));
2244 XSETFASTINT (w->total_cols, FRAME_TOTAL_COLS (f));
2245 allocate_matrices_for_window_redisplay (w);
2246 }
488dd4c4 2247#endif
5f5c8ee5
GM
2248}
2249
2250
177c0ea7 2251/* Adjust/ allocate message buffer of frame F.
5f5c8ee5 2252
5f5c8ee5
GM
2253 Note that the message buffer is never freed. Since I could not
2254 find a free in 19.34, I assume that freeing it would be
2255 problematic in some way and don't do it either.
2256
2257 (Implementation note: It should be checked if we can free it
2258 eventually without causing trouble). */
2259
2260static void
971de7fb 2261adjust_frame_message_buffer (struct frame *f)
5f5c8ee5 2262{
dfd153ae 2263 ptrdiff_t size = FRAME_MESSAGE_BUF_SIZE (f) + 1;
5f5c8ee5
GM
2264
2265 if (FRAME_MESSAGE_BUF (f))
2266 {
2267 char *buffer = FRAME_MESSAGE_BUF (f);
2268 char *new_buffer = (char *) xrealloc (buffer, size);
5f5c8ee5
GM
2269 FRAME_MESSAGE_BUF (f) = new_buffer;
2270 }
2271 else
2272 FRAME_MESSAGE_BUF (f) = (char *) xmalloc (size);
2273}
2274
2275
2276/* Re-allocate buffer for decode_mode_spec on frame F. */
2277
2278static void
971de7fb 2279adjust_decode_mode_spec_buffer (struct frame *f)
5f5c8ee5
GM
2280{
2281 f->decode_mode_spec_buffer
2282 = (char *) xrealloc (f->decode_mode_spec_buffer,
2283 FRAME_MESSAGE_BUF_SIZE (f) + 1);
2284}
2285
2286
2287\f
2288/**********************************************************************
2289 Freeing Glyph Matrices
2290 **********************************************************************/
2291
2292/* Free glyph memory for a frame F. F may be null. This function can
2293 be called for the same frame more than once. The root window of
2294 F may be nil when this function is called. This is the case when
2295 the function is called when F is destroyed. */
2296
2297void
971de7fb 2298free_glyphs (struct frame *f)
5f5c8ee5
GM
2299{
2300 if (f && f->glyphs_initialized_p)
2301 {
42f55fe0
GM
2302 /* Block interrupt input so that we don't get surprised by an X
2303 event while we're in an inconsistent state. */
2304 BLOCK_INPUT;
5f5c8ee5 2305 f->glyphs_initialized_p = 0;
177c0ea7 2306
5f5c8ee5
GM
2307 /* Release window sub-matrices. */
2308 if (!NILP (f->root_window))
2309 free_window_matrices (XWINDOW (f->root_window));
2310
2311 /* Free the dummy window for menu bars without X toolkit and its
2312 glyph matrices. */
2313 if (!NILP (f->menu_bar_window))
2314 {
2315 struct window *w = XWINDOW (f->menu_bar_window);
2316 free_glyph_matrix (w->desired_matrix);
2317 free_glyph_matrix (w->current_matrix);
2318 w->desired_matrix = w->current_matrix = NULL;
2319 f->menu_bar_window = Qnil;
2320 }
2321
9ea173e8
GM
2322 /* Free the tool bar window and its glyph matrices. */
2323 if (!NILP (f->tool_bar_window))
5f5c8ee5 2324 {
9ea173e8 2325 struct window *w = XWINDOW (f->tool_bar_window);
5f5c8ee5
GM
2326 free_glyph_matrix (w->desired_matrix);
2327 free_glyph_matrix (w->current_matrix);
2328 w->desired_matrix = w->current_matrix = NULL;
9ea173e8 2329 f->tool_bar_window = Qnil;
5f5c8ee5
GM
2330 }
2331
2332 /* Release frame glyph matrices. Reset fields to zero in
2333 case we are called a second time. */
2334 if (f->desired_matrix)
2335 {
2336 free_glyph_matrix (f->desired_matrix);
2337 free_glyph_matrix (f->current_matrix);
2338 f->desired_matrix = f->current_matrix = NULL;
2339 }
2340
2341 /* Release glyph pools. */
2342 if (f->desired_pool)
2343 {
2344 free_glyph_pool (f->desired_pool);
2345 free_glyph_pool (f->current_pool);
2346 f->desired_pool = f->current_pool = NULL;
2347 }
177c0ea7 2348
42f55fe0 2349 UNBLOCK_INPUT;
5f5c8ee5
GM
2350 }
2351}
2352
2353
2354/* Free glyph sub-matrices in the window tree rooted at W. This
2355 function may be called with a null pointer, and it may be called on
2356 the same tree more than once. */
2357
2358void
971de7fb 2359free_window_matrices (struct window *w)
5f5c8ee5
GM
2360{
2361 while (w)
2362 {
2363 if (!NILP (w->hchild))
2364 free_window_matrices (XWINDOW (w->hchild));
2365 else if (!NILP (w->vchild))
2366 free_window_matrices (XWINDOW (w->vchild));
177c0ea7 2367 else
5f5c8ee5
GM
2368 {
2369 /* This is a leaf window. Free its memory and reset fields
2370 to zero in case this function is called a second time for
2371 W. */
2372 free_glyph_matrix (w->current_matrix);
2373 free_glyph_matrix (w->desired_matrix);
2374 w->current_matrix = w->desired_matrix = NULL;
2375 }
2376
2377 /* Next window on same level. */
2378 w = NILP (w->next) ? 0 : XWINDOW (w->next);
2379 }
2380}
2381
2382
2383/* Check glyph memory leaks. This function is called from
2384 shut_down_emacs. Note that frames are not destroyed when Emacs
2385 exits. We therefore free all glyph memory for all active frames
2386 explicitly and check that nothing is left allocated. */
2387
2388void
971de7fb 2389check_glyph_memory (void)
5f5c8ee5
GM
2390{
2391 Lisp_Object tail, frame;
2392
2393 /* Free glyph memory for all frames. */
2394 FOR_EACH_FRAME (tail, frame)
2395 free_glyphs (XFRAME (frame));
2396
2397 /* Check that nothing is left allocated. */
2398 if (glyph_matrix_count)
2399 abort ();
2400 if (glyph_pool_count)
2401 abort ();
2402}
2403
2404
2405\f
2406/**********************************************************************
2407 Building a Frame Matrix
2408 **********************************************************************/
2409
2410/* Most of the redisplay code works on glyph matrices attached to
2411 windows. This is a good solution most of the time, but it is not
2412 suitable for terminal code. Terminal output functions cannot rely
2413 on being able to set an arbitrary terminal window. Instead they
2414 must be provided with a view of the whole frame, i.e. the whole
2415 screen. We build such a view by constructing a frame matrix from
2416 window matrices in this section.
2417
2418 Windows that must be updated have their must_be_update_p flag set.
2419 For all such windows, their desired matrix is made part of the
2420 desired frame matrix. For other windows, their current matrix is
2421 made part of the desired frame matrix.
2422
2423 +-----------------+----------------+
2424 | desired | desired |
2425 | | |
2426 +-----------------+----------------+
2427 | current |
2428 | |
2429 +----------------------------------+
2430
2431 Desired window matrices can be made part of the frame matrix in a
2432 cheap way: We exploit the fact that the desired frame matrix and
2433 desired window matrices share their glyph memory. This is not
2434 possible for current window matrices. Their glyphs are copied to
2435 the desired frame matrix. The latter is equivalent to
2436 preserve_other_columns in the old redisplay.
2437
2438 Used glyphs counters for frame matrix rows are the result of adding
2439 up glyph lengths of the window matrices. A line in the frame
2440 matrix is enabled, if a corresponding line in a window matrix is
2441 enabled.
177c0ea7 2442
5f5c8ee5
GM
2443 After building the desired frame matrix, it will be passed to
2444 terminal code, which will manipulate both the desired and current
2445 frame matrix. Changes applied to the frame's current matrix have
2446 to be visible in current window matrices afterwards, of course.
2447
2448 This problem is solved like this:
2449
2450 1. Window and frame matrices share glyphs. Window matrices are
2451 constructed in a way that their glyph contents ARE the glyph
2452 contents needed in a frame matrix. Thus, any modification of
2453 glyphs done in terminal code will be reflected in window matrices
2454 automatically.
177c0ea7 2455
5f5c8ee5
GM
2456 2. Exchanges of rows in a frame matrix done by terminal code are
2457 intercepted by hook functions so that corresponding row operations
2458 on window matrices can be performed. This is necessary because we
2459 use pointers to glyphs in glyph row structures. To satisfy the
2460 assumption of point 1 above that glyphs are updated implicitly in
2461 window matrices when they are manipulated via the frame matrix,
2462 window and frame matrix must of course agree where to find the
2463 glyphs for their rows. Possible manipulations that must be
2464 mirrored are assignments of rows of the desired frame matrix to the
2465 current frame matrix and scrolling the current frame matrix. */
2466
2467/* Build frame F's desired matrix from window matrices. Only windows
2468 which have the flag must_be_updated_p set have to be updated. Menu
2469 bar lines of a frame are not covered by window matrices, so make
2470 sure not to touch them in this function. */
2471
2472static void
971de7fb 2473build_frame_matrix (struct frame *f)
5f5c8ee5
GM
2474{
2475 int i;
2476
2477 /* F must have a frame matrix when this function is called. */
2478 xassert (!FRAME_WINDOW_P (f));
177c0ea7 2479
5f5c8ee5
GM
2480 /* Clear all rows in the frame matrix covered by window matrices.
2481 Menu bar lines are not covered by windows. */
2482 for (i = FRAME_TOP_MARGIN (f); i < f->desired_matrix->nrows; ++i)
2483 clear_glyph_row (MATRIX_ROW (f->desired_matrix, i));
2484
2485 /* Build the matrix by walking the window tree. */
2486 build_frame_matrix_from_window_tree (f->desired_matrix,
2487 XWINDOW (FRAME_ROOT_WINDOW (f)));
2488}
2489
2490
2491/* Walk a window tree, building a frame matrix MATRIX from window
2492 matrices. W is the root of a window tree. */
2493
2494static void
971de7fb 2495build_frame_matrix_from_window_tree (struct glyph_matrix *matrix, struct window *w)
5f5c8ee5
GM
2496{
2497 while (w)
2498 {
2499 if (!NILP (w->hchild))
2500 build_frame_matrix_from_window_tree (matrix, XWINDOW (w->hchild));
2501 else if (!NILP (w->vchild))
2502 build_frame_matrix_from_window_tree (matrix, XWINDOW (w->vchild));
2503 else
2504 build_frame_matrix_from_leaf_window (matrix, w);
2505
2506 w = NILP (w->next) ? 0 : XWINDOW (w->next);
2507 }
2508}
2509
2510
2511/* Add a window's matrix to a frame matrix. FRAME_MATRIX is the
2512 desired frame matrix built. W is a leaf window whose desired or
2513 current matrix is to be added to FRAME_MATRIX. W's flag
2514 must_be_updated_p determines which matrix it contributes to
2515 FRAME_MATRIX. If must_be_updated_p is non-zero, W's desired matrix
2516 is added to FRAME_MATRIX, otherwise W's current matrix is added.
2517 Adding a desired matrix means setting up used counters and such in
2518 frame rows, while adding a current window matrix to FRAME_MATRIX
2519 means copying glyphs. The latter case corresponds to
2520 preserve_other_columns in the old redisplay. */
2521
2522static void
971de7fb 2523build_frame_matrix_from_leaf_window (struct glyph_matrix *frame_matrix, struct window *w)
5f5c8ee5
GM
2524{
2525 struct glyph_matrix *window_matrix;
2526 int window_y, frame_y;
2527 /* If non-zero, a glyph to insert at the right border of W. */
3fc809e2
KS
2528 GLYPH right_border_glyph;
2529
2530 SET_GLYPH_FROM_CHAR (right_border_glyph, 0);
5f5c8ee5
GM
2531
2532 /* Set window_matrix to the matrix we have to add to FRAME_MATRIX. */
2533 if (w->must_be_updated_p)
2534 {
2535 window_matrix = w->desired_matrix;
2536
2537 /* Decide whether we want to add a vertical border glyph. */
2538 if (!WINDOW_RIGHTMOST_P (w))
2539 {
2540 struct Lisp_Char_Table *dp = window_display_table (w);
3fc809e2 2541 Lisp_Object gc;
b4e49aee 2542
3fc809e2
KS
2543 SET_GLYPH_FROM_CHAR (right_border_glyph, '|');
2544 if (dp
2545 && (gc = DISP_BORDER_GLYPH (dp), GLYPH_CODE_P (gc))
2546 && GLYPH_CODE_CHAR_VALID_P (gc))
2547 {
2548 SET_GLYPH_FROM_GLYPH_CODE (right_border_glyph, gc);
2549 spec_glyph_lookup_face (w, &right_border_glyph);
2550 }
b4e49aee 2551
3fc809e2
KS
2552 if (GLYPH_FACE (right_border_glyph) <= 0)
2553 SET_GLYPH_FACE (right_border_glyph, VERTICAL_BORDER_FACE_ID);
5f5c8ee5
GM
2554 }
2555 }
2556 else
2557 window_matrix = w->current_matrix;
2558
2559 /* For all rows in the window matrix and corresponding rows in the
2560 frame matrix. */
2561 window_y = 0;
2562 frame_y = window_matrix->matrix_y;
2563 while (window_y < window_matrix->nrows)
2564 {
2565 struct glyph_row *frame_row = frame_matrix->rows + frame_y;
2566 struct glyph_row *window_row = window_matrix->rows + window_y;
2a8bd25f 2567 int current_row_p = window_matrix == w->current_matrix;
5f5c8ee5
GM
2568
2569 /* Fill up the frame row with spaces up to the left margin of the
2570 window row. */
2571 fill_up_frame_row_with_spaces (frame_row, window_matrix->matrix_x);
2572
2573 /* Fill up areas in the window matrix row with spaces. */
2574 fill_up_glyph_row_with_spaces (window_row);
2a8bd25f
GM
2575
2576 /* If only part of W's desired matrix has been built, and
2577 window_row wasn't displayed, use the corresponding current
2578 row instead. */
2579 if (window_matrix == w->desired_matrix
2580 && !window_row->enabled_p)
2581 {
2582 window_row = w->current_matrix->rows + window_y;
2583 current_row_p = 1;
2584 }
177c0ea7 2585
2a8bd25f 2586 if (current_row_p)
5f5c8ee5 2587 {
2a8bd25f 2588 /* Copy window row to frame row. */
72af86bd
AS
2589 memcpy (frame_row->glyphs[TEXT_AREA] + window_matrix->matrix_x,
2590 window_row->glyphs[0],
2591 window_matrix->matrix_w * sizeof (struct glyph));
5f5c8ee5
GM
2592 }
2593 else
2594 {
2a8bd25f 2595 xassert (window_row->enabled_p);
177c0ea7 2596
2a8bd25f
GM
2597 /* Only when a desired row has been displayed, we want
2598 the corresponding frame row to be updated. */
2599 frame_row->enabled_p = 1;
177c0ea7 2600
5f5c8ee5
GM
2601 /* Maybe insert a vertical border between horizontally adjacent
2602 windows. */
3fc809e2 2603 if (GLYPH_CHAR (right_border_glyph) != 0)
5f5c8ee5
GM
2604 {
2605 struct glyph *border = window_row->glyphs[LAST_AREA] - 1;
2606 SET_CHAR_GLYPH_FROM_GLYPH (*border, right_border_glyph);
2607 }
2608
498c08ea 2609#if GLYPH_DEBUG
a13396c9
GM
2610 /* Window row window_y must be a slice of frame row
2611 frame_y. */
5f5c8ee5 2612 xassert (glyph_row_slice_p (window_row, frame_row));
177c0ea7 2613
5f5c8ee5
GM
2614 /* If rows are in sync, we don't have to copy glyphs because
2615 frame and window share glyphs. */
177c0ea7 2616
a38634ff 2617 strcpy (w->current_matrix->method, w->desired_matrix->method);
9b0e97aa 2618 add_window_display_history (w, w->current_matrix->method, 0);
a38634ff 2619#endif
5f5c8ee5
GM
2620 }
2621
2622 /* Set number of used glyphs in the frame matrix. Since we fill
2623 up with spaces, and visit leaf windows from left to right it
2624 can be done simply. */
177c0ea7 2625 frame_row->used[TEXT_AREA]
5f5c8ee5
GM
2626 = window_matrix->matrix_x + window_matrix->matrix_w;
2627
5f5c8ee5
GM
2628 /* Next row. */
2629 ++window_y;
2630 ++frame_y;
2631 }
2632}
2633
5f81871e
RS
2634/* Given a user-specified glyph, possibly including a Lisp-level face
2635 ID, return a glyph that has a realized face ID.
2636 This is used for glyphs displayed specially and not part of the text;
2637 for instance, vertical separators, truncation markers, etc. */
2638
3fc809e2 2639void
971de7fb 2640spec_glyph_lookup_face (struct window *w, GLYPH *glyph)
5f81871e 2641{
3fc809e2 2642 int lface_id = GLYPH_FACE (*glyph);
5f81871e
RS
2643 /* Convert the glyph's specified face to a realized (cache) face. */
2644 if (lface_id > 0)
2645 {
2646 int face_id = merge_faces (XFRAME (w->frame),
2647 Qt, lface_id, DEFAULT_FACE_ID);
3fc809e2 2648 SET_GLYPH_FACE (*glyph, face_id);
5f81871e 2649 }
5f81871e 2650}
5f5c8ee5
GM
2651
2652/* Add spaces to a glyph row ROW in a window matrix.
2653
2654 Each row has the form:
2655
2656 +---------+-----------------------------+------------+
2657 | left | text | right |
2658 +---------+-----------------------------+------------+
2659
2660 Left and right marginal areas are optional. This function adds
2661 spaces to areas so that there are no empty holes between areas.
2662 In other words: If the right area is not empty, the text area
2663 is filled up with spaces up to the right area. If the text area
2664 is not empty, the left area is filled up.
2665
2666 To be called for frame-based redisplay, only. */
2667
2668static void
971de7fb 2669fill_up_glyph_row_with_spaces (struct glyph_row *row)
5f5c8ee5
GM
2670{
2671 fill_up_glyph_row_area_with_spaces (row, LEFT_MARGIN_AREA);
2672 fill_up_glyph_row_area_with_spaces (row, TEXT_AREA);
2673 fill_up_glyph_row_area_with_spaces (row, RIGHT_MARGIN_AREA);
2674}
2675
2676
2677/* Fill area AREA of glyph row ROW with spaces. To be called for
2678 frame-based redisplay only. */
2679
2680static void
971de7fb 2681fill_up_glyph_row_area_with_spaces (struct glyph_row *row, int area)
5f5c8ee5
GM
2682{
2683 if (row->glyphs[area] < row->glyphs[area + 1])
2684 {
2685 struct glyph *end = row->glyphs[area + 1];
2686 struct glyph *text = row->glyphs[area] + row->used[area];
2687
2688 while (text < end)
2689 *text++ = space_glyph;
2690 row->used[area] = text - row->glyphs[area];
2691 }
2692}
2693
2694
2695/* Add spaces to the end of ROW in a frame matrix until index UPTO is
2696 reached. In frame matrices only one area, TEXT_AREA, is used. */
2697
2698static void
971de7fb 2699fill_up_frame_row_with_spaces (struct glyph_row *row, int upto)
5f5c8ee5
GM
2700{
2701 int i = row->used[TEXT_AREA];
2702 struct glyph *glyph = row->glyphs[TEXT_AREA];
177c0ea7 2703
5f5c8ee5
GM
2704 while (i < upto)
2705 glyph[i++] = space_glyph;
2706
2707 row->used[TEXT_AREA] = i;
2708}
2709
2710
2711\f
2712/**********************************************************************
2713 Mirroring operations on frame matrices in window matrices
2714 **********************************************************************/
2715
2716/* Set frame being updated via frame-based redisplay to F. This
2717 function must be called before updates to make explicit that we are
2718 working on frame matrices or not. */
2719
55d4c1b2 2720static inline void
971de7fb 2721set_frame_matrix_frame (struct frame *f)
5f5c8ee5
GM
2722{
2723 frame_matrix_frame = f;
2724}
2725
2726
2727/* Make sure glyph row ROW in CURRENT_MATRIX is up to date.
2728 DESIRED_MATRIX is the desired matrix corresponding to
2729 CURRENT_MATRIX. The update is done by exchanging glyph pointers
2730 between rows in CURRENT_MATRIX and DESIRED_MATRIX. If
2731 frame_matrix_frame is non-null, this indicates that the exchange is
2732 done in frame matrices, and that we have to perform analogous
2733 operations in window matrices of frame_matrix_frame. */
2734
55d4c1b2 2735static inline void
971de7fb 2736make_current (struct glyph_matrix *desired_matrix, struct glyph_matrix *current_matrix, int row)
5f5c8ee5
GM
2737{
2738 struct glyph_row *current_row = MATRIX_ROW (current_matrix, row);
2739 struct glyph_row *desired_row = MATRIX_ROW (desired_matrix, row);
e876ff42 2740 int mouse_face_p = current_row->mouse_face_p;
5f5c8ee5
GM
2741
2742 /* Do current_row = desired_row. This exchanges glyph pointers
2743 between both rows, and does a structure assignment otherwise. */
2744 assign_row (current_row, desired_row);
2745
2746 /* Enable current_row to mark it as valid. */
2747 current_row->enabled_p = 1;
e876ff42 2748 current_row->mouse_face_p = mouse_face_p;
5f5c8ee5
GM
2749
2750 /* If we are called on frame matrices, perform analogous operations
2751 for window matrices. */
2752 if (frame_matrix_frame)
2753 mirror_make_current (XWINDOW (frame_matrix_frame->root_window), row);
2754}
2755
2756
2757/* W is the root of a window tree. FRAME_ROW is the index of a row in
2758 W's frame which has been made current (by swapping pointers between
2759 current and desired matrix). Perform analogous operations in the
2760 matrices of leaf windows in the window tree rooted at W. */
2761
2762static void
971de7fb 2763mirror_make_current (struct window *w, int frame_row)
5f5c8ee5
GM
2764{
2765 while (w)
2766 {
2767 if (!NILP (w->hchild))
2768 mirror_make_current (XWINDOW (w->hchild), frame_row);
2769 else if (!NILP (w->vchild))
2770 mirror_make_current (XWINDOW (w->vchild), frame_row);
2771 else
2772 {
2773 /* Row relative to window W. Don't use FRAME_TO_WINDOW_VPOS
2774 here because the checks performed in debug mode there
2775 will not allow the conversion. */
2776 int row = frame_row - w->desired_matrix->matrix_y;
2777
2778 /* If FRAME_ROW is within W, assign the desired row to the
2779 current row (exchanging glyph pointers). */
2780 if (row >= 0 && row < w->desired_matrix->matrix_h)
2781 {
2782 struct glyph_row *current_row
2783 = MATRIX_ROW (w->current_matrix, row);
2784 struct glyph_row *desired_row
2785 = MATRIX_ROW (w->desired_matrix, row);
a38634ff
GM
2786
2787 if (desired_row->enabled_p)
2788 assign_row (current_row, desired_row);
2789 else
2790 swap_glyph_pointers (desired_row, current_row);
5f5c8ee5 2791 current_row->enabled_p = 1;
d009ae66
EZ
2792
2793 /* Set the Y coordinate of the mode/header line's row.
2794 It is needed in draw_row_with_mouse_face to find the
2795 screen coordinates. (Window-based redisplay sets
2796 this in update_window, but no one seems to do that
2797 for frame-based redisplay.) */
2798 if (current_row->mode_line_p)
2799 current_row->y = row;
5f5c8ee5
GM
2800 }
2801 }
177c0ea7 2802
5f5c8ee5
GM
2803 w = NILP (w->next) ? 0 : XWINDOW (w->next);
2804 }
2805}
2806
2807
2808/* Perform row dance after scrolling. We are working on the range of
2809 lines UNCHANGED_AT_TOP + 1 to UNCHANGED_AT_TOP + NLINES (not
2810 including) in MATRIX. COPY_FROM is a vector containing, for each
2811 row I in the range 0 <= I < NLINES, the index of the original line
2812 to move to I. This index is relative to the row range, i.e. 0 <=
2813 index < NLINES. RETAINED_P is a vector containing zero for each
2814 row 0 <= I < NLINES which is empty.
2815
2816 This function is called from do_scrolling and do_direct_scrolling. */
177c0ea7 2817
5f5c8ee5 2818void
6f704c76
DN
2819mirrored_line_dance (struct glyph_matrix *matrix, int unchanged_at_top, int nlines,
2820 int *copy_from, char *retained_p)
5f5c8ee5
GM
2821{
2822 /* A copy of original rows. */
2823 struct glyph_row *old_rows;
2824
2825 /* Rows to assign to. */
2826 struct glyph_row *new_rows = MATRIX_ROW (matrix, unchanged_at_top);
177c0ea7 2827
5f5c8ee5
GM
2828 int i;
2829
2830 /* Make a copy of the original rows. */
2831 old_rows = (struct glyph_row *) alloca (nlines * sizeof *old_rows);
72af86bd 2832 memcpy (old_rows, new_rows, nlines * sizeof *old_rows);
5f5c8ee5
GM
2833
2834 /* Assign new rows, maybe clear lines. */
2835 for (i = 0; i < nlines; ++i)
2836 {
2837 int enabled_before_p = new_rows[i].enabled_p;
2838
2839 xassert (i + unchanged_at_top < matrix->nrows);
2840 xassert (unchanged_at_top + copy_from[i] < matrix->nrows);
2841 new_rows[i] = old_rows[copy_from[i]];
2842 new_rows[i].enabled_p = enabled_before_p;
2843
2844 /* RETAINED_P is zero for empty lines. */
2845 if (!retained_p[copy_from[i]])
2846 new_rows[i].enabled_p = 0;
2847 }
2848
153a073c 2849 /* Do the same for window matrices, if MATRIX is a frame matrix. */
5f5c8ee5
GM
2850 if (frame_matrix_frame)
2851 mirror_line_dance (XWINDOW (frame_matrix_frame->root_window),
2852 unchanged_at_top, nlines, copy_from, retained_p);
2853}
2854
2855
a13396c9 2856/* Synchronize glyph pointers in the current matrix of window W with
5cb88111 2857 the current frame matrix. */
a13396c9
GM
2858
2859static void
971de7fb 2860sync_window_with_frame_matrix_rows (struct window *w)
a13396c9
GM
2861{
2862 struct frame *f = XFRAME (w->frame);
2863 struct glyph_row *window_row, *window_row_end, *frame_row;
075c507b 2864 int left, right, x, width;
a13396c9 2865
5cb88111 2866 /* Preconditions: W must be a leaf window on a tty frame. */
a13396c9 2867 xassert (NILP (w->hchild) && NILP (w->vchild));
a13396c9
GM
2868 xassert (!FRAME_WINDOW_P (f));
2869
7df02016
KS
2870 left = margin_glyphs_to_reserve (w, 1, w->left_margin_cols);
2871 right = margin_glyphs_to_reserve (w, 1, w->right_margin_cols);
5cb88111
GM
2872 x = w->current_matrix->matrix_x;
2873 width = w->current_matrix->matrix_w;
2874
a13396c9
GM
2875 window_row = w->current_matrix->rows;
2876 window_row_end = window_row + w->current_matrix->nrows;
7df02016 2877 frame_row = f->current_matrix->rows + WINDOW_TOP_EDGE_LINE (w);
177c0ea7 2878
5cb88111 2879 for (; window_row < window_row_end; ++window_row, ++frame_row)
a13396c9 2880 {
5cb88111
GM
2881 window_row->glyphs[LEFT_MARGIN_AREA]
2882 = frame_row->glyphs[0] + x;
2883 window_row->glyphs[TEXT_AREA]
2884 = window_row->glyphs[LEFT_MARGIN_AREA] + left;
2885 window_row->glyphs[LAST_AREA]
2886 = window_row->glyphs[LEFT_MARGIN_AREA] + width;
2887 window_row->glyphs[RIGHT_MARGIN_AREA]
2888 = window_row->glyphs[LAST_AREA] - right;
a13396c9
GM
2889 }
2890}
2891
2892
2893/* Return the window in the window tree rooted in W containing frame
2894 row ROW. Value is null if none is found. */
2895
09ad5a91 2896static struct window *
971de7fb 2897frame_row_to_window (struct window *w, int row)
a13396c9
GM
2898{
2899 struct window *found = NULL;
177c0ea7 2900
a13396c9
GM
2901 while (w && !found)
2902 {
2903 if (!NILP (w->hchild))
2904 found = frame_row_to_window (XWINDOW (w->hchild), row);
2905 else if (!NILP (w->vchild))
2906 found = frame_row_to_window (XWINDOW (w->vchild), row);
7df02016
KS
2907 else if (row >= WINDOW_TOP_EDGE_LINE (w)
2908 && row < WINDOW_BOTTOM_EDGE_LINE (w))
a13396c9 2909 found = w;
177c0ea7 2910
a13396c9
GM
2911 w = NILP (w->next) ? 0 : XWINDOW (w->next);
2912 }
2913
2914 return found;
2915}
2916
2917
5f5c8ee5
GM
2918/* Perform a line dance in the window tree rooted at W, after
2919 scrolling a frame matrix in mirrored_line_dance.
2920
2921 We are working on the range of lines UNCHANGED_AT_TOP + 1 to
2922 UNCHANGED_AT_TOP + NLINES (not including) in W's frame matrix.
2923 COPY_FROM is a vector containing, for each row I in the range 0 <=
2924 I < NLINES, the index of the original line to move to I. This
2925 index is relative to the row range, i.e. 0 <= index < NLINES.
2926 RETAINED_P is a vector containing zero for each row 0 <= I < NLINES
2927 which is empty. */
2928
2929static void
971de7fb 2930mirror_line_dance (struct window *w, int unchanged_at_top, int nlines, int *copy_from, char *retained_p)
5f5c8ee5
GM
2931{
2932 while (w)
2933 {
2934 if (!NILP (w->hchild))
2935 mirror_line_dance (XWINDOW (w->hchild), unchanged_at_top,
2936 nlines, copy_from, retained_p);
2937 else if (!NILP (w->vchild))
2938 mirror_line_dance (XWINDOW (w->vchild), unchanged_at_top,
2939 nlines, copy_from, retained_p);
2940 else
2941 {
2942 /* W is a leaf window, and we are working on its current
2943 matrix m. */
2944 struct glyph_matrix *m = w->current_matrix;
a13396c9 2945 int i, sync_p = 0;
5f5c8ee5
GM
2946 struct glyph_row *old_rows;
2947
2948 /* Make a copy of the original rows of matrix m. */
2949 old_rows = (struct glyph_row *) alloca (m->nrows * sizeof *old_rows);
72af86bd 2950 memcpy (old_rows, m->rows, m->nrows * sizeof *old_rows);
5f5c8ee5
GM
2951
2952 for (i = 0; i < nlines; ++i)
2953 {
2954 /* Frame relative line assigned to. */
2955 int frame_to = i + unchanged_at_top;
177c0ea7 2956
5f5c8ee5
GM
2957 /* Frame relative line assigned. */
2958 int frame_from = copy_from[i] + unchanged_at_top;
177c0ea7 2959
5f5c8ee5
GM
2960 /* Window relative line assigned to. */
2961 int window_to = frame_to - m->matrix_y;
177c0ea7 2962
5f5c8ee5
GM
2963 /* Window relative line assigned. */
2964 int window_from = frame_from - m->matrix_y;
177c0ea7 2965
5f5c8ee5
GM
2966 /* Is assigned line inside window? */
2967 int from_inside_window_p
2968 = window_from >= 0 && window_from < m->matrix_h;
177c0ea7 2969
a13396c9
GM
2970 /* Is assigned to line inside window? */
2971 int to_inside_window_p
2972 = window_to >= 0 && window_to < m->matrix_h;
177c0ea7 2973
a13396c9 2974 if (from_inside_window_p && to_inside_window_p)
5f5c8ee5 2975 {
5f5c8ee5
GM
2976 /* Enabled setting before assignment. */
2977 int enabled_before_p;
177c0ea7 2978
5f5c8ee5
GM
2979 /* Do the assignment. The enabled_p flag is saved
2980 over the assignment because the old redisplay did
2981 that. */
2982 enabled_before_p = m->rows[window_to].enabled_p;
2983 m->rows[window_to] = old_rows[window_from];
2984 m->rows[window_to].enabled_p = enabled_before_p;
177c0ea7 2985
5f5c8ee5
GM
2986 /* If frame line is empty, window line is empty, too. */
2987 if (!retained_p[copy_from[i]])
2988 m->rows[window_to].enabled_p = 0;
2989 }
a13396c9
GM
2990 else if (to_inside_window_p)
2991 {
2992 /* A copy between windows. This is an infrequent
2993 case not worth optimizing. */
2994 struct frame *f = XFRAME (w->frame);
2995 struct window *root = XWINDOW (FRAME_ROOT_WINDOW (f));
2996 struct window *w2;
2997 struct glyph_matrix *m2;
2998 int m2_from;
2999
fe8b8401 3000 w2 = frame_row_to_window (root, frame_from);
6183d842
RS
3001 /* ttn@surf.glug.org: when enabling menu bar using `emacs
3002 -nw', FROM_FRAME sometimes has no associated window.
3003 This check avoids a segfault if W2 is null. */
3004 if (w2)
3005 {
3006 m2 = w2->current_matrix;
3007 m2_from = frame_from - m2->matrix_y;
3008 copy_row_except_pointers (m->rows + window_to,
3009 m2->rows + m2_from);
3010
3011 /* If frame line is empty, window line is empty, too. */
3012 if (!retained_p[copy_from[i]])
3013 m->rows[window_to].enabled_p = 0;
3014 }
a13396c9
GM
3015 sync_p = 1;
3016 }
3017 else if (from_inside_window_p)
3018 sync_p = 1;
5f5c8ee5 3019 }
a13396c9
GM
3020
3021 /* If there was a copy between windows, make sure glyph
3022 pointers are in sync with the frame matrix. */
3023 if (sync_p)
3024 sync_window_with_frame_matrix_rows (w);
177c0ea7 3025
5f5c8ee5
GM
3026 /* Check that no pointers are lost. */
3027 CHECK_MATRIX (m);
3028 }
3029
3030 /* Next window on same level. */
3031 w = NILP (w->next) ? 0 : XWINDOW (w->next);
3032 }
3033}
3034
3035
3036#if GLYPH_DEBUG
3037
3038/* Check that window and frame matrices agree about their
3039 understanding where glyphs of the rows are to find. For each
3040 window in the window tree rooted at W, check that rows in the
3041 matrices of leaf window agree with their frame matrices about
3042 glyph pointers. */
3043
85fece3e 3044static void
59fc5cf9 3045check_window_matrix_pointers (struct window *w)
5f5c8ee5
GM
3046{
3047 while (w)
3048 {
3049 if (!NILP (w->hchild))
3050 check_window_matrix_pointers (XWINDOW (w->hchild));
3051 else if (!NILP (w->vchild))
3052 check_window_matrix_pointers (XWINDOW (w->vchild));
3053 else
60a8948a 3054 {
5f5c8ee5
GM
3055 struct frame *f = XFRAME (w->frame);
3056 check_matrix_pointers (w->desired_matrix, f->desired_matrix);
3057 check_matrix_pointers (w->current_matrix, f->current_matrix);
60a8948a 3058 }
177c0ea7 3059
5f5c8ee5
GM
3060 w = NILP (w->next) ? 0 : XWINDOW (w->next);
3061 }
3062}
3063
3064
3065/* Check that window rows are slices of frame rows. WINDOW_MATRIX is
3066 a window and FRAME_MATRIX is the corresponding frame matrix. For
3067 each row in WINDOW_MATRIX check that it's a slice of the
3068 corresponding frame row. If it isn't, abort. */
3069
3070static void
59fc5cf9
AS
3071check_matrix_pointers (struct glyph_matrix *window_matrix,
3072 struct glyph_matrix *frame_matrix)
5f5c8ee5
GM
3073{
3074 /* Row number in WINDOW_MATRIX. */
3075 int i = 0;
3076
3077 /* Row number corresponding to I in FRAME_MATRIX. */
3078 int j = window_matrix->matrix_y;
3079
177c0ea7 3080 /* For all rows check that the row in the window matrix is a
5f5c8ee5
GM
3081 slice of the row in the frame matrix. If it isn't we didn't
3082 mirror an operation on the frame matrix correctly. */
3083 while (i < window_matrix->nrows)
3084 {
3085 if (!glyph_row_slice_p (window_matrix->rows + i,
3086 frame_matrix->rows + j))
3087 abort ();
3088 ++i, ++j;
3089 }
3090}
3091
3092#endif /* GLYPH_DEBUG != 0 */
3093
3094
3095\f
3096/**********************************************************************
3097 VPOS and HPOS translations
3098 **********************************************************************/
3099
3100#if GLYPH_DEBUG
3101
3102/* Translate vertical position VPOS which is relative to window W to a
3103 vertical position relative to W's frame. */
3104
3105static int
59fc5cf9 3106window_to_frame_vpos (struct window *w, int vpos)
5f5c8ee5 3107{
85fece3e 3108 xassert (!FRAME_WINDOW_P (XFRAME (w->frame)));
5f5c8ee5 3109 xassert (vpos >= 0 && vpos <= w->desired_matrix->nrows);
7df02016 3110 vpos += WINDOW_TOP_EDGE_LINE (w);
85fece3e 3111 xassert (vpos >= 0 && vpos <= FRAME_LINES (XFRAME (w->frame)));
5f5c8ee5
GM
3112 return vpos;
3113}
3114
3115
3116/* Translate horizontal position HPOS which is relative to window W to
153a073c 3117 a horizontal position relative to W's frame. */
5f5c8ee5
GM
3118
3119static int
59fc5cf9 3120window_to_frame_hpos (struct window *w, int hpos)
5f5c8ee5 3121{
82f4a138 3122 xassert (!FRAME_WINDOW_P (XFRAME (w->frame)));
7df02016 3123 hpos += WINDOW_LEFT_EDGE_COL (w);
5f5c8ee5
GM
3124 return hpos;
3125}
177c0ea7 3126
5f5c8ee5
GM
3127#endif /* GLYPH_DEBUG */
3128
3129
3130\f
3131/**********************************************************************
3132 Redrawing Frames
3133 **********************************************************************/
3134
a7ca3326 3135DEFUN ("redraw-frame", Fredraw_frame, Sredraw_frame, 1, 1, 0,
7ee72033 3136 doc: /* Clear frame FRAME and output again what is supposed to appear on it. */)
5842a27b 3137 (Lisp_Object frame)
5f5c8ee5
GM
3138{
3139 struct frame *f;
3140
b7826503 3141 CHECK_LIVE_FRAME (frame);
5f5c8ee5
GM
3142 f = XFRAME (frame);
3143
3144 /* Ignore redraw requests, if frame has no glyphs yet.
3145 (Implementation note: It still has to be checked why we are
3146 called so early here). */
3147 if (!glyphs_initialized_initially_p)
3148 return Qnil;
3149
3150 update_begin (f);
3224dac1 3151#ifdef MSDOS
f2adda5e 3152 if (FRAME_MSDOS_P (f))
79d39b69 3153 FRAME_TERMINAL (f)->set_terminal_modes_hook (FRAME_TERMINAL (f));
3224dac1 3154#endif
385ed61f 3155 clear_frame (f);
5f5c8ee5
GM
3156 clear_current_matrices (f);
3157 update_end (f);
daf01701 3158 if (FRAME_TERMCAP_P (f))
0b0d3e0b 3159 fflush (FRAME_TTY (f)->output);
5f5c8ee5
GM
3160 windows_or_buffers_changed++;
3161 /* Mark all windows as inaccurate, so that every window will have
3162 its redisplay done. */
3163 mark_window_display_accurate (FRAME_ROOT_WINDOW (f), 0);
3164 set_window_update_flags (XWINDOW (FRAME_ROOT_WINDOW (f)), 1);
3165 f->garbaged = 0;
3166 return Qnil;
3167}
3168
3169
3170/* Redraw frame F. This is nothing more than a call to the Lisp
3171 function redraw-frame. */
3172
3173void
971de7fb 3174redraw_frame (struct frame *f)
5f5c8ee5
GM
3175{
3176 Lisp_Object frame;
3177 XSETFRAME (frame, f);
3178 Fredraw_frame (frame);
3179}
3180
3181
3182DEFUN ("redraw-display", Fredraw_display, Sredraw_display, 0, 0, "",
7ee72033 3183 doc: /* Clear and redisplay all visible frames. */)
5842a27b 3184 (void)
5f5c8ee5
GM
3185{
3186 Lisp_Object tail, frame;
3187
3188 FOR_EACH_FRAME (tail, frame)
3189 if (FRAME_VISIBLE_P (XFRAME (frame)))
3190 Fredraw_frame (frame);
3191
3192 return Qnil;
3193}
3194
3195
5f5c8ee5 3196\f
5f5c8ee5
GM
3197/***********************************************************************
3198 Frame Update
3199 ***********************************************************************/
4588ec20 3200
5f5c8ee5 3201/* Update frame F based on the data in desired matrices.
4588ec20 3202
5f5c8ee5
GM
3203 If FORCE_P is non-zero, don't let redisplay be stopped by detecting
3204 pending input. If INHIBIT_HAIRY_ID_P is non-zero, don't try
3205 scrolling.
177c0ea7 3206
5f5c8ee5 3207 Value is non-zero if redisplay was stopped due to pending input. */
4588ec20 3208
5f5c8ee5 3209int
971de7fb 3210update_frame (struct frame *f, int force_p, int inhibit_hairy_id_p)
5f5c8ee5
GM
3211{
3212 /* 1 means display has been paused because of pending input. */
3213 int paused_p;
3214 struct window *root_window = XWINDOW (f->root_window);
3215
a2130dbb
KS
3216 if (redisplay_dont_pause)
3217 force_p = 1;
d012c62b 3218#if PERIODIC_PREEMPTION_CHECKING
a2130dbb
KS
3219 else if (NILP (Vredisplay_preemption_period))
3220 force_p = 1;
3221 else if (!force_p && NUMBERP (Vredisplay_preemption_period))
d012c62b
KS
3222 {
3223 EMACS_TIME tm;
3224 double p = XFLOATINT (Vredisplay_preemption_period);
3225 int sec, usec;
3226
993d4ab6
KS
3227 if (detect_input_pending_ignore_squeezables ())
3228 {
3229 paused_p = 1;
3230 goto do_pause;
3231 }
3232
d012c62b
KS
3233 sec = (int) p;
3234 usec = (p - sec) * 1000000;
3235
3236 EMACS_GET_TIME (tm);
3237 EMACS_SET_SECS_USECS (preemption_period, sec, usec);
3238 EMACS_ADD_TIME (preemption_next_check, tm, preemption_period);
3239 }
3240#endif
3241
5f5c8ee5 3242 if (FRAME_WINDOW_P (f))
4588ec20 3243 {
5f5c8ee5
GM
3244 /* We are working on window matrix basis. All windows whose
3245 flag must_be_updated_p is set have to be updated. */
3246
3247 /* Record that we are not working on frame matrices. */
3248 set_frame_matrix_frame (NULL);
3249
3250 /* Update all windows in the window tree of F, maybe stopping
3251 when pending input is detected. */
3252 update_begin (f);
3253
3254 /* Update the menu bar on X frames that don't have toolkit
3255 support. */
3256 if (WINDOWP (f->menu_bar_window))
3257 update_window (XWINDOW (f->menu_bar_window), 1);
3258
3259 /* Update the tool-bar window, if present. */
9ea173e8 3260 if (WINDOWP (f->tool_bar_window))
4588ec20 3261 {
9ea173e8 3262 struct window *w = XWINDOW (f->tool_bar_window);
5f5c8ee5
GM
3263
3264 /* Update tool-bar window. */
3265 if (w->must_be_updated_p)
4588ec20 3266 {
153a073c
PJ
3267 Lisp_Object tem;
3268
5f5c8ee5
GM
3269 update_window (w, 1);
3270 w->must_be_updated_p = 0;
3271
3272 /* Swap tool-bar strings. We swap because we want to
3273 reuse strings. */
9ea173e8
GM
3274 tem = f->current_tool_bar_string;
3275 f->current_tool_bar_string = f->desired_tool_bar_string;
3276 f->desired_tool_bar_string = tem;
4588ec20
JB
3277 }
3278 }
177c0ea7 3279
5f5c8ee5
GM
3280
3281 /* Update windows. */
3282 paused_p = update_window_tree (root_window, force_p);
3283 update_end (f);
177c0ea7 3284
6b61353c 3285 /* This flush is a performance bottleneck under X,
e581a466 3286 and it doesn't seem to be necessary anyway (in general).
6b61353c 3287 It is necessary when resizing the window with the mouse, or
e581a466 3288 at least the fringes are not redrawn in a timely manner. ++kfs */
6b61353c 3289 if (f->force_flush_display_p)
e581a466
KL
3290 {
3291 FRAME_RIF (f)->flush_display (f);
3292 f->force_flush_display_p = 0;
3293 }
4588ec20 3294 }
5f5c8ee5
GM
3295 else
3296 {
3297 /* We are working on frame matrix basis. Set the frame on whose
3298 frame matrix we operate. */
3299 set_frame_matrix_frame (f);
3300
868dd24b 3301 /* Build F's desired matrix from window matrices. */
5f5c8ee5 3302 build_frame_matrix (f);
177c0ea7 3303
868dd24b
GM
3304 /* Update the display */
3305 update_begin (f);
5f5c8ee5 3306 paused_p = update_frame_1 (f, force_p, inhibit_hairy_id_p);
868dd24b
GM
3307 update_end (f);
3308
7d2f1216 3309 if (FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f))
3224dac1 3310 {
0b0d3e0b
KL
3311 if (FRAME_TTY (f)->termscript)
3312 fflush (FRAME_TTY (f)->termscript);
7d2f1216
EZ
3313 if (FRAME_TERMCAP_P (f))
3314 fflush (FRAME_TTY (f)->output);
3224dac1 3315 }
868dd24b 3316
5f5c8ee5 3317 /* Check window matrices for lost pointers. */
2d5912c1 3318#if GLYPH_DEBUG
9b0e97aa
GM
3319 check_window_matrix_pointers (root_window);
3320 add_frame_display_history (f, paused_p);
3321#endif
5f5c8ee5
GM
3322 }
3323
ef1b0ba7 3324#if PERIODIC_PREEMPTION_CHECKING
993d4ab6 3325 do_pause:
ef1b0ba7 3326#endif
5f5c8ee5
GM
3327 /* Reset flags indicating that a window should be updated. */
3328 set_window_update_flags (root_window, 0);
177c0ea7 3329
868dd24b 3330 display_completed = !paused_p;
5f5c8ee5 3331 return paused_p;
4588ec20 3332}
5f5c8ee5
GM
3333
3334
4588ec20 3335\f
5f5c8ee5
GM
3336/************************************************************************
3337 Window-based updates
3338 ************************************************************************/
3339
3340/* Perform updates in window tree rooted at W. FORCE_P non-zero means
3341 don't stop updating when input is pending. */
3342
3343static int
971de7fb 3344update_window_tree (struct window *w, int force_p)
5f5c8ee5
GM
3345{
3346 int paused_p = 0;
177c0ea7 3347
5f5c8ee5
GM
3348 while (w && !paused_p)
3349 {
3350 if (!NILP (w->hchild))
3351 paused_p |= update_window_tree (XWINDOW (w->hchild), force_p);
3352 else if (!NILP (w->vchild))
3353 paused_p |= update_window_tree (XWINDOW (w->vchild), force_p);
3354 else if (w->must_be_updated_p)
3355 paused_p |= update_window (w, force_p);
3356
3357 w = NILP (w->next) ? 0 : XWINDOW (w->next);
3358 }
3359
3360 return paused_p;
3361}
3362
3363
3364/* Update window W if its flag must_be_updated_p is non-zero. If
3365 FORCE_P is non-zero, don't stop updating if input is pending. */
3366
3367void
971de7fb 3368update_single_window (struct window *w, int force_p)
5f5c8ee5
GM
3369{
3370 if (w->must_be_updated_p)
3371 {
3372 struct frame *f = XFRAME (WINDOW_FRAME (w));
3373
3374 /* Record that this is not a frame-based redisplay. */
3375 set_frame_matrix_frame (NULL);
3376
a2130dbb
KS
3377 if (redisplay_dont_pause)
3378 force_p = 1;
d012c62b 3379#if PERIODIC_PREEMPTION_CHECKING
a2130dbb
KS
3380 else if (NILP (Vredisplay_preemption_period))
3381 force_p = 1;
3382 else if (!force_p && NUMBERP (Vredisplay_preemption_period))
d012c62b
KS
3383 {
3384 EMACS_TIME tm;
3385 double p = XFLOATINT (Vredisplay_preemption_period);
3386 int sec, usec;
3387
3388 sec = (int) p;
3389 usec = (p - sec) * 1000000;
3390
3391 EMACS_GET_TIME (tm);
3392 EMACS_SET_SECS_USECS (preemption_period, sec, usec);
3393 EMACS_ADD_TIME (preemption_next_check, tm, preemption_period);
3394 }
3395#endif
3396
5f5c8ee5
GM
3397 /* Update W. */
3398 update_begin (f);
3399 update_window (w, force_p);
3400 update_end (f);
4588ec20 3401
5f5c8ee5
GM
3402 /* Reset flag in W. */
3403 w->must_be_updated_p = 0;
3404 }
3405}
4588ec20 3406
93e023fc 3407#ifdef HAVE_WINDOW_SYSTEM
4588ec20 3408
408f5064
GM
3409/* Redraw lines from the current matrix of window W that are
3410 overlapped by other rows. YB is bottom-most y-position in W. */
3411
3412static void
971de7fb 3413redraw_overlapped_rows (struct window *w, int yb)
408f5064 3414{
d8ee7803 3415 int i;
fa971ac3 3416 struct frame *f = XFRAME (WINDOW_FRAME (w));
3fc809e2 3417
408f5064
GM
3418 /* If rows overlapping others have been changed, the rows being
3419 overlapped have to be redrawn. This won't draw lines that have
3420 already been drawn in update_window_line because overlapped_p in
3421 desired rows is 0, so after row assignment overlapped_p in
3422 current rows is 0. */
3423 for (i = 0; i < w->current_matrix->nrows; ++i)
3424 {
e876ff42 3425 struct glyph_row *row = w->current_matrix->rows + i;
408f5064
GM
3426
3427 if (!row->enabled_p)
3428 break;
3429 else if (row->mode_line_p)
3430 continue;
177c0ea7 3431
408f5064
GM
3432 if (row->overlapped_p)
3433 {
3434 enum glyph_row_area area;
177c0ea7 3435
408f5064
GM
3436 for (area = LEFT_MARGIN_AREA; area < LAST_AREA; ++area)
3437 {
3438 updated_row = row;
3439 updated_area = area;
fa971ac3
KL
3440 FRAME_RIF (f)->cursor_to (i, 0, row->y,
3441 area == TEXT_AREA ? row->x : 0);
408f5064 3442 if (row->used[area])
fa971ac3
KL
3443 FRAME_RIF (f)->write_glyphs (row->glyphs[area],
3444 row->used[area]);
3445 FRAME_RIF (f)->clear_end_of_line (-1);
408f5064 3446 }
177c0ea7 3447
408f5064
GM
3448 row->overlapped_p = 0;
3449 }
3450
e876ff42 3451 if (MATRIX_ROW_BOTTOM_Y (row) >= yb)
408f5064
GM
3452 break;
3453 }
3454}
3455
3456
3457/* Redraw lines from the current matrix of window W that overlap
3458 others. YB is bottom-most y-position in W. */
3459
3460static void
971de7fb 3461redraw_overlapping_rows (struct window *w, int yb)
408f5064
GM
3462{
3463 int i, bottom_y;
3464 struct glyph_row *row;
fa971ac3 3465 struct redisplay_interface *rif = FRAME_RIF (XFRAME (WINDOW_FRAME (w)));
3fc809e2 3466
408f5064
GM
3467 for (i = 0; i < w->current_matrix->nrows; ++i)
3468 {
3469 row = w->current_matrix->rows + i;
3470
3471 if (!row->enabled_p)
3472 break;
3473 else if (row->mode_line_p)
3474 continue;
177c0ea7 3475
408f5064
GM
3476 bottom_y = MATRIX_ROW_BOTTOM_Y (row);
3477
b4b2c2ca 3478 if (row->overlapping_p)
408f5064 3479 {
41124e06
YM
3480 int overlaps = 0;
3481
b4b2c2ca 3482 if (MATRIX_ROW_OVERLAPS_PRED_P (row) && i > 0
41124e06
YM
3483 && !MATRIX_ROW (w->current_matrix, i - 1)->overlapped_p)
3484 overlaps |= OVERLAPS_PRED;
b4b2c2ca 3485 if (MATRIX_ROW_OVERLAPS_SUCC_P (row) && bottom_y < yb
41124e06
YM
3486 && !MATRIX_ROW (w->current_matrix, i + 1)->overlapped_p)
3487 overlaps |= OVERLAPS_SUCC;
3488
3489 if (overlaps)
3490 {
3491 if (row->used[LEFT_MARGIN_AREA])
3492 rif->fix_overlapping_area (w, row, LEFT_MARGIN_AREA, overlaps);
3493
3494 if (row->used[TEXT_AREA])
3495 rif->fix_overlapping_area (w, row, TEXT_AREA, overlaps);
3496
3497 if (row->used[RIGHT_MARGIN_AREA])
3498 rif->fix_overlapping_area (w, row, RIGHT_MARGIN_AREA, overlaps);
3499
c5e87d10 3500 /* Record in neighbor rows that ROW overwrites part of
41124e06
YM
3501 their display. */
3502 if (overlaps & OVERLAPS_PRED)
3503 MATRIX_ROW (w->current_matrix, i - 1)->overlapped_p = 1;
3504 if (overlaps & OVERLAPS_SUCC)
3505 MATRIX_ROW (w->current_matrix, i + 1)->overlapped_p = 1;
3506 }
408f5064
GM
3507 }
3508
3509 if (bottom_y >= yb)
3510 break;
3511 }
3512}
3513
93e023fc
KS
3514#endif /* HAVE_WINDOW_SYSTEM */
3515
408f5064 3516
09ad5a91 3517#if defined GLYPH_DEBUG && 0
93962bfa
GM
3518
3519/* Check that no row in the current matrix of window W is enabled
3520 which is below what's displayed in the window. */
3521
09ad5a91 3522static void
971de7fb 3523check_current_matrix_flags (struct window *w)
93962bfa
GM
3524{
3525 int last_seen_p = 0;
3526 int i, yb = window_text_bottom_y (w);
3527
3528 for (i = 0; i < w->current_matrix->nrows - 1; ++i)
3529 {
3530 struct glyph_row *row = MATRIX_ROW (w->current_matrix, i);
3531 if (!last_seen_p && MATRIX_ROW_BOTTOM_Y (row) >= yb)
3532 last_seen_p = 1;
3533 else if (last_seen_p && row->enabled_p)
3534 abort ();
3535 }
3536}
3537
3538#endif /* GLYPH_DEBUG */
3539
3540
5f5c8ee5
GM
3541/* Update display of window W. FORCE_P non-zero means that we should
3542 not stop when detecting pending input. */
3543
3544static int
971de7fb 3545update_window (struct window *w, int force_p)
4588ec20 3546{
5f5c8ee5
GM
3547 struct glyph_matrix *desired_matrix = w->desired_matrix;
3548 int paused_p;
d012c62b 3549#if !PERIODIC_PREEMPTION_CHECKING
5f5c8ee5 3550 int preempt_count = baud_rate / 2400 + 1;
d012c62b 3551#endif
597cfb3f 3552 struct redisplay_interface *rif = FRAME_RIF (XFRAME (WINDOW_FRAME (w)));
b96fd3e8 3553#if GLYPH_DEBUG
5f5c8ee5 3554 /* Check that W's frame doesn't have glyph matrices. */
82f4a138 3555 xassert (FRAME_WINDOW_P (XFRAME (WINDOW_FRAME (w))));
4a34b529 3556#endif
5f5c8ee5
GM
3557
3558 /* Check pending input the first time so that we can quickly return. */
a2130dbb
KS
3559#if !PERIODIC_PREEMPTION_CHECKING
3560 if (!force_p)
a2d5fca0 3561 detect_input_pending_ignore_squeezables ();
d012c62b 3562#endif
4588ec20 3563
5f5c8ee5
GM
3564 /* If forced to complete the update, or if no input is pending, do
3565 the update. */
8fd9a666 3566 if (force_p || !input_pending || !NILP (do_mouse_tracking))
4588ec20 3567 {
5f5c8ee5
GM
3568 struct glyph_row *row, *end;
3569 struct glyph_row *mode_line_row;
56974e03 3570 struct glyph_row *header_line_row;
0bc32927
PE
3571 int yb, changed_p = 0, mouse_face_overwritten_p = 0;
3572#if ! PERIODIC_PREEMPTION_CHECKING
3573 int n_updated = 0;
3574#endif
5f5c8ee5
GM
3575
3576 rif->update_window_begin_hook (w);
3577 yb = window_text_bottom_y (w);
5f5c8ee5
GM
3578 row = desired_matrix->rows;
3579 end = row + desired_matrix->nrows - 1;
177c0ea7 3580
394305db
EZ
3581 /* Take note of the header line, if there is one. We will
3582 update it below, after updating all of the window's lines. */
5f5c8ee5 3583 if (row->mode_line_p)
56974e03
GM
3584 {
3585 header_line_row = row;
3586 ++row;
3587 }
3588 else
3589 header_line_row = NULL;
5f5c8ee5
GM
3590
3591 /* Update the mode line, if necessary. */
3592 mode_line_row = MATRIX_MODE_LINE_ROW (desired_matrix);
3593 if (mode_line_row->mode_line_p && mode_line_row->enabled_p)
3594 {
3595 mode_line_row->y = yb;
3596 update_window_line (w, MATRIX_ROW_VPOS (mode_line_row,
e876ff42
GM
3597 desired_matrix),
3598 &mouse_face_overwritten_p);
5f5c8ee5
GM
3599 }
3600
3601 /* Find first enabled row. Optimizations in redisplay_internal
3602 may lead to an update with only one row enabled. There may
3603 be also completely empty matrices. */
3604 while (row < end && !row->enabled_p)
3605 ++row;
177c0ea7 3606
bfdcafe1 3607 /* Try reusing part of the display by copying. */
5f5c8ee5 3608 if (row < end && !desired_matrix->no_scrolling_p)
56974e03
GM
3609 {
3610 int rc = scrolling_window (w, header_line_row != NULL);
3611 if (rc < 0)
3612 {
3613 /* All rows were found to be equal. */
3614 paused_p = 0;
3615 goto set_cursor;
3616 }
3617 else if (rc > 0)
6b61353c
KH
3618 {
3619 /* We've scrolled the display. */
3620 force_p = 1;
3621 changed_p = 1;
3622 }
5f5c8ee5
GM
3623 }
3624
3625 /* Update the rest of the lines. */
0bc32927 3626 for (; row < end && (force_p || !input_pending); ++row)
394305db
EZ
3627 /* scrolling_window resets the enabled_p flag of the rows it
3628 reuses from current_matrix. */
b7412313 3629 if (row->enabled_p)
5f5c8ee5
GM
3630 {
3631 int vpos = MATRIX_ROW_VPOS (row, desired_matrix);
3632 int i;
177c0ea7 3633
153a073c 3634 /* We'll have to play a little bit with when to
5f5c8ee5
GM
3635 detect_input_pending. If it's done too often,
3636 scrolling large windows with repeated scroll-up
3637 commands will too quickly pause redisplay. */
d012c62b
KS
3638#if PERIODIC_PREEMPTION_CHECKING
3639 if (!force_p)
3640 {
3641 EMACS_TIME tm, dif;
3642 EMACS_GET_TIME (tm);
3643 EMACS_SUB_TIME (dif, preemption_next_check, tm);
3644 if (EMACS_TIME_NEG_P (dif))
3645 {
3646 EMACS_ADD_TIME (preemption_next_check, tm, preemption_period);
993d4ab6
KS
3647 if (detect_input_pending_ignore_squeezables ())
3648 break;
d012c62b
KS
3649 }
3650 }
3651#else
e87b8809 3652 if (!force_p && ++n_updated % preempt_count == 0)
a2d5fca0 3653 detect_input_pending_ignore_squeezables ();
d012c62b 3654#endif
e876ff42
GM
3655 changed_p |= update_window_line (w, vpos,
3656 &mouse_face_overwritten_p);
5f5c8ee5
GM
3657
3658 /* Mark all rows below the last visible one in the current
3659 matrix as invalid. This is necessary because of
3660 variable line heights. Consider the case of three
3661 successive redisplays, where the first displays 5
3662 lines, the second 3 lines, and the third 5 lines again.
3663 If the second redisplay wouldn't mark rows in the
3664 current matrix invalid, the third redisplay might be
3665 tempted to optimize redisplay based on lines displayed
3666 in the first redisplay. */
3667 if (MATRIX_ROW_BOTTOM_Y (row) >= yb)
3668 for (i = vpos + 1; i < w->current_matrix->nrows - 1; ++i)
3669 MATRIX_ROW (w->current_matrix, i)->enabled_p = 0;
3670 }
3671
3672 /* Was display preempted? */
3673 paused_p = row < end;
177c0ea7 3674
56974e03 3675 set_cursor:
177c0ea7 3676
6b61353c
KH
3677 /* Update the header line after scrolling because a new header
3678 line would otherwise overwrite lines at the top of the window
3679 that can be scrolled. */
3680 if (header_line_row && header_line_row->enabled_p)
3681 {
3682 header_line_row->y = 0;
3683 update_window_line (w, 0, &mouse_face_overwritten_p);
6b61353c
KH
3684 }
3685
153a073c 3686 /* Fix the appearance of overlapping/overlapped rows. */
5f5c8ee5
GM
3687 if (!paused_p && !w->pseudo_window_p)
3688 {
93e023fc 3689#ifdef HAVE_WINDOW_SYSTEM
e876ff42
GM
3690 if (changed_p && rif->fix_overlapping_area)
3691 {
3692 redraw_overlapped_rows (w, yb);
3693 redraw_overlapping_rows (w, yb);
3694 }
93e023fc 3695#endif
177c0ea7 3696
5f5c8ee5
GM
3697 /* Make cursor visible at cursor position of W. */
3698 set_window_cursor_after_update (w);
3699
e876ff42
GM
3700#if 0 /* Check that current matrix invariants are satisfied. This is
3701 for debugging only. See the comment of check_matrix_invariants. */
5f5c8ee5
GM
3702 IF_DEBUG (check_matrix_invariants (w));
3703#endif
4588ec20 3704 }
5f5c8ee5
GM
3705
3706#if GLYPH_DEBUG
3707 /* Remember the redisplay method used to display the matrix. */
3708 strcpy (w->current_matrix->method, w->desired_matrix->method);
3709#endif
408f5064 3710
6b61353c
KH
3711#ifdef HAVE_WINDOW_SYSTEM
3712 update_window_fringes (w, 0);
3713#endif
3714
56974e03
GM
3715 /* End the update of window W. Don't set the cursor if we
3716 paused updating the display because in this case,
3717 set_window_cursor_after_update hasn't been called, and
3718 output_cursor doesn't contain the cursor location. */
3719 rif->update_window_end_hook (w, !paused_p, mouse_face_overwritten_p);
4588ec20 3720 }
5f5c8ee5
GM
3721 else
3722 paused_p = 1;
3723
2d5912c1 3724#if GLYPH_DEBUG
0cffd9d8 3725 /* check_current_matrix_flags (w); */
9b0e97aa
GM
3726 add_window_display_history (w, w->current_matrix->method, paused_p);
3727#endif
177c0ea7 3728
5f5c8ee5 3729 clear_glyph_matrix (desired_matrix);
408f5064 3730
5f5c8ee5 3731 return paused_p;
4588ec20
JB
3732}
3733
b64b3980 3734
5f5c8ee5
GM
3735/* Update the display of area AREA in window W, row number VPOS.
3736 AREA can be either LEFT_MARGIN_AREA or RIGHT_MARGIN_AREA. */
3737
3738static void
971de7fb 3739update_marginal_area (struct window *w, int area, int vpos)
b64b3980 3740{
5f5c8ee5 3741 struct glyph_row *desired_row = MATRIX_ROW (w->desired_matrix, vpos);
fa971ac3 3742 struct redisplay_interface *rif = FRAME_RIF (XFRAME (WINDOW_FRAME (w)));
5f5c8ee5
GM
3743
3744 /* Let functions in xterm.c know what area subsequent X positions
3745 will be relative to. */
3746 updated_area = area;
3747
3748 /* Set cursor to start of glyphs, write them, and clear to the end
3749 of the area. I don't think that something more sophisticated is
3750 necessary here, since marginal areas will not be the default. */
3751 rif->cursor_to (vpos, 0, desired_row->y, 0);
3752 if (desired_row->used[area])
3753 rif->write_glyphs (desired_row->glyphs[area], desired_row->used[area]);
3754 rif->clear_end_of_line (-1);
b64b3980 3755}
23b0200c 3756
352f1545 3757
408f5064
GM
3758/* Update the display of the text area of row VPOS in window W.
3759 Value is non-zero if display has changed. */
5f5c8ee5 3760
408f5064 3761static int
971de7fb 3762update_text_area (struct window *w, int vpos)
23b0200c 3763{
5f5c8ee5
GM
3764 struct glyph_row *current_row = MATRIX_ROW (w->current_matrix, vpos);
3765 struct glyph_row *desired_row = MATRIX_ROW (w->desired_matrix, vpos);
fa971ac3 3766 struct redisplay_interface *rif = FRAME_RIF (XFRAME (WINDOW_FRAME (w)));
408f5064 3767 int changed_p = 0;
5f5c8ee5
GM
3768
3769 /* Let functions in xterm.c know what area subsequent X positions
3770 will be relative to. */
3771 updated_area = TEXT_AREA;
177c0ea7 3772
5f5c8ee5
GM
3773 /* If rows are at different X or Y, or rows have different height,
3774 or the current row is marked invalid, write the entire line. */
3775 if (!current_row->enabled_p
3776 || desired_row->y != current_row->y
3777 || desired_row->ascent != current_row->ascent
408f5064
GM
3778 || desired_row->phys_ascent != current_row->phys_ascent
3779 || desired_row->phys_height != current_row->phys_height
5f5c8ee5 3780 || desired_row->visible_height != current_row->visible_height
408f5064 3781 || current_row->overlapped_p
fee8b690
CY
3782 /* This next line is necessary for correctly redrawing
3783 mouse-face areas after scrolling and other operations.
3784 However, it causes excessive flickering when mouse is moved
3785 across the mode line. Luckily, turning it off for the mode
a75b65c4
KS
3786 line doesn't seem to hurt anything. -- cyd.
3787 But it is still needed for the header line. -- kfs. */
3788 || (current_row->mouse_face_p
3789 && !(current_row->mode_line_p && vpos > 0))
5f5c8ee5
GM
3790 || current_row->x != desired_row->x)
3791 {
3792 rif->cursor_to (vpos, 0, desired_row->y, desired_row->x);
177c0ea7 3793
5f5c8ee5
GM
3794 if (desired_row->used[TEXT_AREA])
3795 rif->write_glyphs (desired_row->glyphs[TEXT_AREA],
3796 desired_row->used[TEXT_AREA]);
177c0ea7 3797
5f5c8ee5
GM
3798 /* Clear to end of window. */
3799 rif->clear_end_of_line (-1);
408f5064 3800 changed_p = 1;
60f2f3f1
GM
3801
3802 /* This erases the cursor. We do this here because
3803 notice_overwritten_cursor cannot easily check this, which
3804 might indicate that the whole functionality of
3805 notice_overwritten_cursor would better be implemented here.
3806 On the other hand, we need notice_overwritten_cursor as long
3807 as mouse highlighting is done asynchronously outside of
3808 redisplay. */
3809 if (vpos == w->phys_cursor.vpos)
3810 w->phys_cursor_on_p = 0;
5f5c8ee5
GM
3811 }
3812 else
3813 {
3814 int stop, i, x;
3815 struct glyph *current_glyph = current_row->glyphs[TEXT_AREA];
3816 struct glyph *desired_glyph = desired_row->glyphs[TEXT_AREA];
e47306e6 3817 int overlapping_glyphs_p = current_row->contains_overlapping_glyphs_p;
074b781a 3818 int desired_stop_pos = desired_row->used[TEXT_AREA];
91d227d9 3819 int abort_skipping = 0;
5f5c8ee5 3820
78897758
YM
3821 /* If the desired row extends its face to the text area end, and
3822 unless the current row also does so at the same position,
5f5c8ee5
GM
3823 make sure we write at least one glyph, so that the face
3824 extension actually takes place. */
78897758
YM
3825 if (MATRIX_ROW_EXTENDS_FACE_P (desired_row)
3826 && (desired_stop_pos < current_row->used[TEXT_AREA]
3827 || (desired_stop_pos == current_row->used[TEXT_AREA]
3828 && !MATRIX_ROW_EXTENDS_FACE_P (current_row))))
074b781a 3829 --desired_stop_pos;
177c0ea7 3830
5f5c8ee5
GM
3831 stop = min (current_row->used[TEXT_AREA], desired_stop_pos);
3832 i = 0;
3833 x = desired_row->x;
8399f8a0
GM
3834
3835 /* Loop over glyphs that current and desired row may have
3836 in common. */
5f5c8ee5 3837 while (i < stop)
352f1545 3838 {
91d227d9 3839 int can_skip_p = !abort_skipping;
177c0ea7 3840
5f5c8ee5 3841 /* Skip over glyphs that both rows have in common. These
e47306e6
GM
3842 don't have to be written. We can't skip if the last
3843 current glyph overlaps the glyph to its right. For
3844 example, consider a current row of `if ' with the `f' in
3845 Courier bold so that it overlaps the ` ' to its right.
3846 If the desired row is ` ', we would skip over the space
3847 after the `if' and there would remain a pixel from the
3848 `f' on the screen. */
3849 if (overlapping_glyphs_p && i > 0)
352f1545 3850 {
e47306e6
GM
3851 struct glyph *glyph = &current_row->glyphs[TEXT_AREA][i - 1];
3852 int left, right;
177c0ea7 3853
e47306e6
GM
3854 rif->get_glyph_overhangs (glyph, XFRAME (w->frame),
3855 &left, &right);
91d227d9 3856 can_skip_p = (right == 0 && !abort_skipping);
352f1545 3857 }
177c0ea7 3858
6d950f4c 3859 if (can_skip_p)
352f1545 3860 {
91d227d9
CY
3861 int start_hpos = i;
3862
6d950f4c
GM
3863 while (i < stop
3864 && GLYPH_EQUAL_P (desired_glyph, current_glyph))
3865 {
3866 x += desired_glyph->pixel_width;
3867 ++desired_glyph, ++current_glyph, ++i;
3868 }
3869
3870 /* Consider the case that the current row contains "xxx
3871 ppp ggg" in italic Courier font, and the desired row
3872 is "xxx ggg". The character `p' has lbearing, `g'
3873 has not. The loop above will stop in front of the
3874 first `p' in the current row. If we would start
3875 writing glyphs there, we wouldn't erase the lbearing
3876 of the `p'. The rest of the lbearing problem is then
641bdbf3 3877 taken care of by draw_glyphs. */
6d950f4c
GM
3878 if (overlapping_glyphs_p
3879 && i > 0
3880 && i < current_row->used[TEXT_AREA]
3881 && (current_row->used[TEXT_AREA]
3882 != desired_row->used[TEXT_AREA]))
5f5c8ee5 3883 {
6d950f4c 3884 int left, right;
177c0ea7 3885
6d950f4c
GM
3886 rif->get_glyph_overhangs (current_glyph, XFRAME (w->frame),
3887 &left, &right);
3888 while (left > 0 && i > 0)
3889 {
3890 --i, --desired_glyph, --current_glyph;
3891 x -= desired_glyph->pixel_width;
3892 left -= desired_glyph->pixel_width;
3893 }
91d227d9
CY
3894
3895 /* Abort the skipping algorithm if we end up before
3896 our starting point, to avoid looping (bug#1070).
3897 This can happen when the lbearing is larger than
3898 the pixel width. */
3899 abort_skipping = (i < start_hpos);
5f5c8ee5 3900 }
352f1545 3901 }
177c0ea7 3902
5f5c8ee5
GM
3903 /* Try to avoid writing the entire rest of the desired row
3904 by looking for a resync point. This mainly prevents
3905 mode line flickering in the case the mode line is in
3906 fixed-pitch font, which it usually will be. */
3907 if (i < desired_row->used[TEXT_AREA])
3908 {
3909 int start_x = x, start_hpos = i;
3910 struct glyph *start = desired_glyph;
3911 int current_x = x;
6d950f4c
GM
3912 int skip_first_p = !can_skip_p;
3913
5f5c8ee5
GM
3914 /* Find the next glyph that's equal again. */
3915 while (i < stop
6d950f4c
GM
3916 && (skip_first_p
3917 || !GLYPH_EQUAL_P (desired_glyph, current_glyph))
5f5c8ee5
GM
3918 && x == current_x)
3919 {
3920 x += desired_glyph->pixel_width;
3921 current_x += current_glyph->pixel_width;
3922 ++desired_glyph, ++current_glyph, ++i;
6d950f4c 3923 skip_first_p = 0;
5f5c8ee5 3924 }
23b0200c 3925
5f5c8ee5
GM
3926 if (i == start_hpos || x != current_x)
3927 {
3928 i = start_hpos;
3929 x = start_x;
3930 desired_glyph = start;
3931 break;
3932 }
e47306e6 3933
5f5c8ee5
GM
3934 rif->cursor_to (vpos, start_hpos, desired_row->y, start_x);
3935 rif->write_glyphs (start, i - start_hpos);
408f5064 3936 changed_p = 1;
5f5c8ee5
GM
3937 }
3938 }
177c0ea7 3939
5f5c8ee5
GM
3940 /* Write the rest. */
3941 if (i < desired_row->used[TEXT_AREA])
3942 {
3943 rif->cursor_to (vpos, i, desired_row->y, x);
3944 rif->write_glyphs (desired_glyph, desired_row->used[TEXT_AREA] - i);
408f5064 3945 changed_p = 1;
5f5c8ee5 3946 }
177c0ea7 3947
5f5c8ee5
GM
3948 /* Maybe clear to end of line. */
3949 if (MATRIX_ROW_EXTENDS_FACE_P (desired_row))
3950 {
3951 /* If new row extends to the end of the text area, nothing
3952 has to be cleared, if and only if we did a write_glyphs
3953 above. This is made sure by setting desired_stop_pos
3954 appropriately above. */
78897758
YM
3955 xassert (i < desired_row->used[TEXT_AREA]
3956 || ((desired_row->used[TEXT_AREA]
3957 == current_row->used[TEXT_AREA])
3958 && MATRIX_ROW_EXTENDS_FACE_P (current_row)));
5f5c8ee5
GM
3959 }
3960 else if (MATRIX_ROW_EXTENDS_FACE_P (current_row))
3961 {
3962 /* If old row extends to the end of the text area, clear. */
3963 if (i >= desired_row->used[TEXT_AREA])
3964 rif->cursor_to (vpos, i, desired_row->y,
6b61353c 3965 desired_row->pixel_width);
5f5c8ee5 3966 rif->clear_end_of_line (-1);
408f5064 3967 changed_p = 1;
5f5c8ee5
GM
3968 }
3969 else if (desired_row->pixel_width < current_row->pixel_width)
2e8907d3 3970 {
5f5c8ee5
GM
3971 /* Otherwise clear to the end of the old row. Everything
3972 after that position should be clear already. */
27786b2f 3973 int xlim;
177c0ea7 3974
5f5c8ee5
GM
3975 if (i >= desired_row->used[TEXT_AREA])
3976 rif->cursor_to (vpos, i, desired_row->y,
6b61353c 3977 desired_row->pixel_width);
5f5c8ee5
GM
3978
3979 /* If cursor is displayed at the end of the line, make sure
3980 it's cleared. Nowadays we don't have a phys_cursor_glyph
3981 with which to erase the cursor (because this method
3982 doesn't work with lbearing/rbearing), so we must do it
3983 this way. */
3984 if (vpos == w->phys_cursor.vpos
f951a506
EZ
3985 && (desired_row->reversed_p
3986 ? (w->phys_cursor.hpos < 0)
3987 : (w->phys_cursor.hpos >= desired_row->used[TEXT_AREA])))
5f5c8ee5
GM
3988 {
3989 w->phys_cursor_on_p = 0;
27786b2f 3990 xlim = -1;
5f5c8ee5
GM
3991 }
3992 else
27786b2f
PE
3993 xlim = current_row->pixel_width;
3994 rif->clear_end_of_line (xlim);
408f5064 3995 changed_p = 1;
2e8907d3 3996 }
23b0200c 3997 }
408f5064
GM
3998
3999 return changed_p;
23b0200c 4000}
4588ec20 4001
5f5c8ee5 4002
408f5064
GM
4003/* Update row VPOS in window W. Value is non-zero if display has been
4004 changed. */
5f5c8ee5 4005
408f5064 4006static int
971de7fb 4007update_window_line (struct window *w, int vpos, int *mouse_face_overwritten_p)
5f5c8ee5
GM
4008{
4009 struct glyph_row *current_row = MATRIX_ROW (w->current_matrix, vpos);
4010 struct glyph_row *desired_row = MATRIX_ROW (w->desired_matrix, vpos);
fa971ac3 4011 struct redisplay_interface *rif = FRAME_RIF (XFRAME (WINDOW_FRAME (w)));
408f5064 4012 int changed_p = 0;
5f5c8ee5 4013
5f5c8ee5
GM
4014 /* Set the row being updated. This is important to let xterm.c
4015 know what line height values are in effect. */
4016 updated_row = desired_row;
4017
177c0ea7
JB
4018 /* A row can be completely invisible in case a desired matrix was
4019 built with a vscroll and then make_cursor_line_fully_visible shifts
504805ac
GM
4020 the matrix. Make sure to make such rows current anyway, since
4021 we need the correct y-position, for example, in the current matrix. */
001f93f3
GM
4022 if (desired_row->mode_line_p
4023 || desired_row->visible_height > 0)
408f5064 4024 {
504805ac
GM
4025 xassert (desired_row->enabled_p);
4026
4027 /* Update display of the left margin area, if there is one. */
4028 if (!desired_row->full_width_p
7df02016 4029 && !NILP (w->left_margin_cols))
504805ac
GM
4030 {
4031 changed_p = 1;
4032 update_marginal_area (w, LEFT_MARGIN_AREA, vpos);
4033 }
177c0ea7 4034
504805ac
GM
4035 /* Update the display of the text area. */
4036 if (update_text_area (w, vpos))
4037 {
4038 changed_p = 1;
4039 if (current_row->mouse_face_p)
4040 *mouse_face_overwritten_p = 1;
4041 }
177c0ea7 4042
504805ac
GM
4043 /* Update display of the right margin area, if there is one. */
4044 if (!desired_row->full_width_p
7df02016 4045 && !NILP (w->right_margin_cols))
504805ac
GM
4046 {
4047 changed_p = 1;
4048 update_marginal_area (w, RIGHT_MARGIN_AREA, vpos);
4049 }
177c0ea7 4050
504805ac
GM
4051 /* Draw truncation marks etc. */
4052 if (!current_row->enabled_p
4053 || desired_row->y != current_row->y
4054 || desired_row->visible_height != current_row->visible_height
6b61353c 4055 || desired_row->cursor_in_fringe_p != current_row->cursor_in_fringe_p
3d4a365f 4056 || desired_row->overlay_arrow_bitmap != current_row->overlay_arrow_bitmap
6b61353c 4057 || current_row->redraw_fringe_bitmaps_p
504805ac 4058 || desired_row->mode_line_p != current_row->mode_line_p
6b61353c 4059 || desired_row->exact_window_width_line_p != current_row->exact_window_width_line_p
504805ac
GM
4060 || (MATRIX_ROW_CONTINUATION_LINE_P (desired_row)
4061 != MATRIX_ROW_CONTINUATION_LINE_P (current_row)))
4062 rif->after_update_window_line_hook (desired_row);
408f5064 4063 }
177c0ea7 4064
5f5c8ee5
GM
4065 /* Update current_row from desired_row. */
4066 make_current (w->desired_matrix, w->current_matrix, vpos);
4067 updated_row = NULL;
408f5064 4068 return changed_p;
5f5c8ee5
GM
4069}
4070
4071
4072/* Set the cursor after an update of window W. This function may only
4073 be called from update_window. */
4074
4075static void
971de7fb 4076set_window_cursor_after_update (struct window *w)
4588ec20 4077{
5f5c8ee5 4078 struct frame *f = XFRAME (w->frame);
fa971ac3 4079 struct redisplay_interface *rif = FRAME_RIF (f);
5f5c8ee5
GM
4080 int cx, cy, vpos, hpos;
4081
4082 /* Not intended for frame matrix updates. */
4083 xassert (FRAME_WINDOW_P (f));
177c0ea7 4084
b96fd3e8
GM
4085 if (cursor_in_echo_area
4086 && !NILP (echo_area_buffer[0])
4087 /* If we are showing a message instead of the mini-buffer,
4088 show the cursor for the message instead. */
4089 && XWINDOW (minibuf_window) == w
4090 && EQ (minibuf_window, echo_area_window)
5f5c8ee5
GM
4091 /* These cases apply only to the frame that contains
4092 the active mini-buffer window. */
4093 && FRAME_HAS_MINIBUF_P (f)
4094 && EQ (FRAME_MINIBUF_WINDOW (f), echo_area_window))
4095 {
4096 cx = cy = vpos = hpos = 0;
4097
4098 if (cursor_in_echo_area >= 0)
4099 {
4100 /* If the mini-buffer is several lines high, find the last
4101 line that has any text on it. Note: either all lines
4102 are enabled or none. Otherwise we wouldn't be able to
4103 determine Y. */
862b4790
GM
4104 struct glyph_row *row, *last_row;
4105 struct glyph *glyph;
4106 int yb = window_text_bottom_y (w);
5f5c8ee5 4107
862b4790 4108 last_row = NULL;
6206f8ce
GM
4109 row = w->current_matrix->rows;
4110 while (row->enabled_p
4111 && (last_row == NULL
4112 || MATRIX_ROW_BOTTOM_Y (row) <= yb))
5f5c8ee5 4113 {
862b4790
GM
4114 if (row->used[TEXT_AREA]
4115 && row->glyphs[TEXT_AREA][0].charpos >= 0)
4116 last_row = row;
6206f8ce 4117 ++row;
862b4790 4118 }
177c0ea7 4119
5f5c8ee5
GM
4120 if (last_row)
4121 {
6206f8ce
GM
4122 struct glyph *start = last_row->glyphs[TEXT_AREA];
4123 struct glyph *last = start + last_row->used[TEXT_AREA] - 1;
862b4790 4124
b96fd3e8 4125 while (last > start && last->charpos < 0)
862b4790 4126 --last;
177c0ea7 4127
862b4790
GM
4128 for (glyph = start; glyph < last; ++glyph)
4129 {
4130 cx += glyph->pixel_width;
4131 ++hpos;
4132 }
4133
5f5c8ee5 4134 cy = last_row->y;
862b4790 4135 vpos = MATRIX_ROW_VPOS (last_row, w->current_matrix);
5f5c8ee5
GM
4136 }
4137 }
4138 }
4139 else
4140 {
4141 cx = w->cursor.x;
4142 cy = w->cursor.y;
4143 hpos = w->cursor.hpos;
4144 vpos = w->cursor.vpos;
4145 }
4588ec20 4146
5f5c8ee5 4147 /* Window cursor can be out of sync for horizontally split windows. */
f951a506 4148 hpos = max (-1, hpos); /* -1 is for when cursor is on the left fringe */
5f5c8ee5
GM
4149 hpos = min (w->current_matrix->matrix_w - 1, hpos);
4150 vpos = max (0, vpos);
4151 vpos = min (w->current_matrix->nrows - 1, vpos);
4152 rif->cursor_to (vpos, hpos, cy, cx);
4588ec20 4153}
4588ec20 4154
5f5c8ee5 4155
6df5d75f
GM
4156/* Set WINDOW->must_be_updated_p to ON_P for all windows in the window
4157 tree rooted at W. */
4158
4159void
971de7fb 4160set_window_update_flags (struct window *w, int on_p)
6df5d75f
GM
4161{
4162 while (w)
4163 {
4164 if (!NILP (w->hchild))
4165 set_window_update_flags (XWINDOW (w->hchild), on_p);
4166 else if (!NILP (w->vchild))
4167 set_window_update_flags (XWINDOW (w->vchild), on_p);
4168 else
4169 w->must_be_updated_p = on_p;
4170
4171 w = NILP (w->next) ? 0 : XWINDOW (w->next);
4172 }
177c0ea7 4173}
6df5d75f
GM
4174
4175
4176\f
4177/***********************************************************************
4178 Window-Based Scrolling
4179 ***********************************************************************/
4180
4181/* Structure describing rows in scrolling_window. */
4182
4183struct row_entry
4184{
4185 /* Number of occurrences of this row in desired and current matrix. */
4186 int old_uses, new_uses;
177c0ea7 4187
6df5d75f
GM
4188 /* Vpos of row in new matrix. */
4189 int new_line_number;
4190
4191 /* Bucket index of this row_entry in the hash table row_table. */
ca9ce8f2 4192 ptrdiff_t bucket;
177c0ea7 4193
6df5d75f
GM
4194 /* The row described by this entry. */
4195 struct glyph_row *row;
177c0ea7 4196
6df5d75f
GM
4197 /* Hash collision chain. */
4198 struct row_entry *next;
4199};
4200
4201/* A pool to allocate row_entry structures from, and the size of the
4202 pool. The pool is reallocated in scrolling_window when we find
4203 that we need a larger one. */
4204
4205static struct row_entry *row_entry_pool;
ca9ce8f2 4206static ptrdiff_t row_entry_pool_size;
6df5d75f
GM
4207
4208/* Index of next free entry in row_entry_pool. */
4209
ca9ce8f2 4210static ptrdiff_t row_entry_idx;
6df5d75f
GM
4211
4212/* The hash table used during scrolling, and the table's size. This
4213 table is used to quickly identify equal rows in the desired and
4214 current matrix. */
4215
4216static struct row_entry **row_table;
ca9ce8f2 4217static ptrdiff_t row_table_size;
6df5d75f
GM
4218
4219/* Vectors of pointers to row_entry structures belonging to the
4220 current and desired matrix, and the size of the vectors. */
4221
4222static struct row_entry **old_lines, **new_lines;
0065d054 4223static ptrdiff_t old_lines_size, new_lines_size;
6df5d75f
GM
4224
4225/* A pool to allocate run structures from, and its size. */
4226
4227static struct run *run_pool;
0065d054 4228static ptrdiff_t runs_size;
6df5d75f
GM
4229
4230/* A vector of runs of lines found during scrolling. */
4231
4232static struct run **runs;
4233
6b1f9ba4 4234/* Add glyph row ROW to the scrolling hash table. */
6df5d75f 4235
55d4c1b2 4236static inline struct row_entry *
6b1f9ba4 4237add_row_entry (struct glyph_row *row)
6df5d75f
GM
4238{
4239 struct row_entry *entry;
ca9ce8f2 4240 ptrdiff_t i = row->hash % row_table_size;
177c0ea7 4241
6df5d75f 4242 entry = row_table[i];
68c95424 4243 xassert (entry || verify_row_hash (row));
6b1f9ba4 4244 while (entry && !row_equal_p (entry->row, row, 1))
6df5d75f 4245 entry = entry->next;
177c0ea7 4246
6df5d75f
GM
4247 if (entry == NULL)
4248 {
4249 entry = row_entry_pool + row_entry_idx++;
4250 entry->row = row;
4251 entry->old_uses = entry->new_uses = 0;
4252 entry->new_line_number = 0;
4253 entry->bucket = i;
4254 entry->next = row_table[i];
4255 row_table[i] = entry;
4256 }
4257
4258 return entry;
4259}
4260
4261
5f5c8ee5 4262/* Try to reuse part of the current display of W by scrolling lines.
153a073c 4263 HEADER_LINE_P non-zero means W has a header line.
5f5c8ee5
GM
4264
4265 The algorithm is taken from Communications of the ACM, Apr78 "A
4266 Technique for Isolating Differences Between Files." It should take
4267 O(N) time.
4268
4269 A short outline of the steps of the algorithm
4270
4271 1. Skip lines equal at the start and end of both matrices.
4272
4273 2. Enter rows in the current and desired matrix into a symbol
4274 table, counting how often they appear in both matrices.
4275
4276 3. Rows that appear exactly once in both matrices serve as anchors,
4277 i.e. we assume that such lines are likely to have been moved.
4278
4279 4. Starting from anchor lines, extend regions to be scrolled both
4280 forward and backward.
4281
4282 Value is
4283
4284 -1 if all rows were found to be equal.
4285 0 to indicate that we did not scroll the display, or
4286 1 if we did scroll. */
4287
4288static int
971de7fb 4289scrolling_window (struct window *w, int header_line_p)
4588ec20 4290{
5f5c8ee5
GM
4291 struct glyph_matrix *desired_matrix = w->desired_matrix;
4292 struct glyph_matrix *current_matrix = w->current_matrix;
4293 int yb = window_text_bottom_y (w);
ca9ce8f2
PE
4294 ptrdiff_t i;
4295 int j, first_old, first_new, last_old, last_new;
4296 int nruns, run_idx;
0065d054 4297 ptrdiff_t n;
6df5d75f 4298 struct row_entry *entry;
fa971ac3 4299 struct redisplay_interface *rif = FRAME_RIF (XFRAME (WINDOW_FRAME (w)));
5f5c8ee5
GM
4300
4301 /* Skip over rows equal at the start. */
bfdcafe1 4302 for (i = header_line_p ? 1 : 0; i < current_matrix->nrows - 1; ++i)
5f5c8ee5 4303 {
bfdcafe1
GM
4304 struct glyph_row *d = MATRIX_ROW (desired_matrix, i);
4305 struct glyph_row *c = MATRIX_ROW (current_matrix, i);
4306
4307 if (c->enabled_p
4308 && d->enabled_p
6b61353c 4309 && !d->redraw_fringe_bitmaps_p
bfdcafe1
GM
4310 && c->y == d->y
4311 && MATRIX_ROW_BOTTOM_Y (c) <= yb
4312 && MATRIX_ROW_BOTTOM_Y (d) <= yb
6b1f9ba4 4313 && row_equal_p (c, d, 1))
bfdcafe1
GM
4314 {
4315 assign_row (c, d);
4316 d->enabled_p = 0;
4317 }
4318 else
4319 break;
5f5c8ee5 4320 }
4588ec20 4321
5f5c8ee5
GM
4322 /* Give up if some rows in the desired matrix are not enabled. */
4323 if (!MATRIX_ROW (desired_matrix, i)->enabled_p)
4324 return -1;
177c0ea7 4325
5f5c8ee5
GM
4326 first_old = first_new = i;
4327
4d8ade89
YM
4328 /* Set last_new to the index + 1 of the row that reaches the
4329 bottom boundary in the desired matrix. Give up if we find a
4330 disabled row before we reach the bottom boundary. */
5f5c8ee5 4331 i = first_new + 1;
4d8ade89
YM
4332 while (i < desired_matrix->nrows - 1)
4333 {
4334 int bottom;
5f5c8ee5 4335
4d8ade89
YM
4336 if (!MATRIX_ROW (desired_matrix, i)->enabled_p)
4337 return 0;
4338 bottom = MATRIX_ROW_BOTTOM_Y (MATRIX_ROW (desired_matrix, i));
4339 if (bottom <= yb)
4340 ++i;
4341 if (bottom >= yb)
4342 break;
4343 }
5f5c8ee5
GM
4344
4345 last_new = i;
4346
4d8ade89
YM
4347 /* Set last_old to the index + 1 of the row that reaches the bottom
4348 boundary in the current matrix. We don't look at the enabled
4349 flag here because we plan to reuse part of the display even if
4350 other parts are disabled. */
5f5c8ee5 4351 i = first_old + 1;
93962bfa
GM
4352 while (i < current_matrix->nrows - 1)
4353 {
4354 int bottom = MATRIX_ROW_BOTTOM_Y (MATRIX_ROW (current_matrix, i));
4355 if (bottom <= yb)
4356 ++i;
4357 if (bottom >= yb)
4358 break;
4359 }
4360
5f5c8ee5
GM
4361 last_old = i;
4362
4363 /* Skip over rows equal at the bottom. */
4364 i = last_new;
4365 j = last_old;
4366 while (i - 1 > first_new
4367 && j - 1 > first_old
1e5b2111
EZ
4368 && MATRIX_ROW (current_matrix, j - 1)->enabled_p
4369 && (MATRIX_ROW (current_matrix, j - 1)->y
4370 == MATRIX_ROW (desired_matrix, i - 1)->y)
4371 && !MATRIX_ROW (desired_matrix, i - 1)->redraw_fringe_bitmaps_p
6b1f9ba4 4372 && row_equal_p (MATRIX_ROW (desired_matrix, i - 1),
e4e0bee9 4373 MATRIX_ROW (current_matrix, j - 1), 1))
5f5c8ee5
GM
4374 --i, --j;
4375 last_new = i;
4376 last_old = j;
4377
4378 /* Nothing to do if all rows are equal. */
4379 if (last_new == first_new)
4380 return 0;
4381
0065d054 4382 /* Check for integer overflow in size calculation.
ca9ce8f2
PE
4383
4384 If next_almost_prime checks (N) for divisibility by 2..10, then
4385 it can return at most N + 10, e.g., next_almost_prime (1) == 11.
4386 So, set next_almost_prime_increment_max to 10.
4387
4388 It's just a coincidence that next_almost_prime_increment_max ==
4389 NEXT_ALMOST_PRIME_LIMIT - 1. If NEXT_ALMOST_PRIME_LIMIT were
4390 13, then next_almost_prime_increment_max would be 14, e.g.,
4391 because next_almost_prime (113) would be 127. */
4392 {
4393 verify (NEXT_ALMOST_PRIME_LIMIT == 11);
4394 enum { next_almost_prime_increment_max = 10 };
ca9ce8f2 4395 ptrdiff_t row_table_max =
0065d054
PE
4396 (min (PTRDIFF_MAX, SIZE_MAX) / (3 * sizeof *row_table)
4397 - next_almost_prime_increment_max);
4398 ptrdiff_t current_nrows_max = row_table_max - desired_matrix->nrows;
4399 if (current_nrows_max < current_matrix->nrows)
ca9ce8f2
PE
4400 memory_full (SIZE_MAX);
4401 }
4402
6df5d75f 4403 /* Reallocate vectors, tables etc. if necessary. */
177c0ea7 4404
6df5d75f 4405 if (current_matrix->nrows > old_lines_size)
0065d054
PE
4406 old_lines = xpalloc (old_lines, &old_lines_size,
4407 current_matrix->nrows - old_lines_size,
4408 INT_MAX, sizeof *old_lines);
177c0ea7 4409
6df5d75f 4410 if (desired_matrix->nrows > new_lines_size)
0065d054
PE
4411 new_lines = xpalloc (new_lines, &new_lines_size,
4412 desired_matrix->nrows - new_lines_size,
4413 INT_MAX, sizeof *new_lines);
6df5d75f 4414
ca9ce8f2
PE
4415 n = desired_matrix->nrows;
4416 n += current_matrix->nrows;
0065d054 4417 if (row_table_size < 3 * n)
6df5d75f 4418 {
ca9ce8f2 4419 ptrdiff_t size = next_almost_prime (3 * n);
0065d054 4420 row_table = xnrealloc (row_table, size, sizeof *row_table);
ca9ce8f2 4421 row_table_size = size;
0065d054 4422 memset (row_table, 0, size * sizeof *row_table);
6df5d75f
GM
4423 }
4424
4425 if (n > row_entry_pool_size)
0065d054
PE
4426 row_entry_pool = xpalloc (row_entry_pool, &row_entry_pool_size,
4427 n - row_entry_pool_size,
4428 -1, sizeof *row_entry_pool);
6df5d75f
GM
4429
4430 if (desired_matrix->nrows > runs_size)
4431 {
0065d054
PE
4432 runs = xnrealloc (runs, desired_matrix->nrows, sizeof *runs);
4433 run_pool = xnrealloc (run_pool, desired_matrix->nrows, sizeof *run_pool);
ca9ce8f2 4434 runs_size = desired_matrix->nrows;
6df5d75f
GM
4435 }
4436
4437 nruns = run_idx = 0;
4438 row_entry_idx = 0;
4439
4440 /* Add rows from the current and desired matrix to the hash table
4441 row_hash_table to be able to find equal ones quickly. */
177c0ea7 4442
5f5c8ee5
GM
4443 for (i = first_old; i < last_old; ++i)
4444 {
4445 if (MATRIX_ROW (current_matrix, i)->enabled_p)
4446 {
6b1f9ba4 4447 entry = add_row_entry (MATRIX_ROW (current_matrix, i));
6df5d75f
GM
4448 old_lines[i] = entry;
4449 ++entry->old_uses;
5f5c8ee5
GM
4450 }
4451 else
6df5d75f 4452 old_lines[i] = NULL;
5f5c8ee5
GM
4453 }
4454
5f5c8ee5
GM
4455 for (i = first_new; i < last_new; ++i)
4456 {
4457 xassert (MATRIX_ROW_ENABLED_P (desired_matrix, i));
6b1f9ba4 4458 entry = add_row_entry (MATRIX_ROW (desired_matrix, i));
6df5d75f
GM
4459 ++entry->new_uses;
4460 entry->new_line_number = i;
4461 new_lines[i] = entry;
5f5c8ee5 4462 }
4588ec20 4463
5f5c8ee5
GM
4464 /* Identify moves based on lines that are unique and equal
4465 in both matrices. */
4466 for (i = first_old; i < last_old;)
6df5d75f
GM
4467 if (old_lines[i]
4468 && old_lines[i]->old_uses == 1
4469 && old_lines[i]->new_uses == 1)
5f5c8ee5 4470 {
27786b2f 4471 int p, q;
6df5d75f
GM
4472 int new_line = old_lines[i]->new_line_number;
4473 struct run *run = run_pool + run_idx++;
5f5c8ee5
GM
4474
4475 /* Record move. */
4476 run->current_vpos = i;
4477 run->current_y = MATRIX_ROW (current_matrix, i)->y;
4478 run->desired_vpos = new_line;
4479 run->desired_y = MATRIX_ROW (desired_matrix, new_line)->y;
4480 run->nrows = 1;
4481 run->height = MATRIX_ROW (current_matrix, i)->height;
4482
4483 /* Extend backward. */
27786b2f
PE
4484 p = i - 1;
4485 q = new_line - 1;
4486 while (p > first_old
4487 && q > first_new
4488 && old_lines[p] == new_lines[q])
5f5c8ee5 4489 {
27786b2f 4490 int h = MATRIX_ROW (current_matrix, p)->height;
177c0ea7
JB
4491 --run->current_vpos;
4492 --run->desired_vpos;
5f5c8ee5
GM
4493 ++run->nrows;
4494 run->height += h;
4495 run->desired_y -= h;
4496 run->current_y -= h;
27786b2f 4497 --p, --q;
5f5c8ee5 4498 }
4588ec20 4499
5f5c8ee5 4500 /* Extend forward. */
27786b2f
PE
4501 p = i + 1;
4502 q = new_line + 1;
4503 while (p < last_old
4504 && q < last_new
4505 && old_lines[p] == new_lines[q])
5f5c8ee5 4506 {
27786b2f 4507 int h = MATRIX_ROW (current_matrix, p)->height;
177c0ea7 4508 ++run->nrows;
5f5c8ee5 4509 run->height += h;
27786b2f 4510 ++p, ++q;
5f5c8ee5 4511 }
19dff8dc 4512
5f5c8ee5
GM
4513 /* Insert run into list of all runs. Order runs by copied
4514 pixel lines. Note that we record runs that don't have to
4515 be copied because they are already in place. This is done
4516 because we can avoid calling update_window_line in this
4517 case. */
27786b2f 4518 for (p = 0; p < nruns && runs[p]->height > run->height; ++p)
5f5c8ee5 4519 ;
27786b2f
PE
4520 for (q = nruns; q > p; --q)
4521 runs[q] = runs[q - 1];
4522 runs[p] = run;
5f5c8ee5
GM
4523 ++nruns;
4524
4525 i += run->nrows;
4526 }
4527 else
4528 ++i;
4588ec20 4529
5f5c8ee5
GM
4530 /* Do the moves. Do it in a way that we don't overwrite something
4531 we want to copy later on. This is not solvable in general
4532 because there is only one display and we don't have a way to
4533 exchange areas on this display. Example:
4588ec20 4534
5f5c8ee5
GM
4535 +-----------+ +-----------+
4536 | A | | B |
4537 +-----------+ --> +-----------+
4538 | B | | A |
4539 +-----------+ +-----------+
4588ec20 4540
5f5c8ee5
GM
4541 Instead, prefer bigger moves, and invalidate moves that would
4542 copy from where we copied to. */
ea0d86af 4543
5f5c8ee5
GM
4544 for (i = 0; i < nruns; ++i)
4545 if (runs[i]->nrows > 0)
4546 {
4547 struct run *r = runs[i];
24e86043 4548
5f5c8ee5
GM
4549 /* Copy on the display. */
4550 if (r->current_y != r->desired_y)
4551 {
989b42d2 4552 rif->clear_window_mouse_face (w);
5f5c8ee5 4553 rif->scroll_run_hook (w, r);
1305621b
YM
4554 }
4555
4556 /* Truncate runs that copy to where we copied to, and
4557 invalidate runs that copy from where we copied to. */
4558 for (j = nruns - 1; j > i; --j)
4559 {
4560 struct run *p = runs[j];
4561 int truncated_p = 0;
5f5c8ee5 4562
1305621b
YM
4563 if (p->nrows > 0
4564 && p->desired_y < r->desired_y + r->height
4565 && p->desired_y + p->height > r->desired_y)
5f5c8ee5 4566 {
1305621b
YM
4567 if (p->desired_y < r->desired_y)
4568 {
4569 p->nrows = r->desired_vpos - p->desired_vpos;
4570 p->height = r->desired_y - p->desired_y;
4571 truncated_p = 1;
4572 }
4573 else
4574 {
4575 int nrows_copied = (r->desired_vpos + r->nrows
4576 - p->desired_vpos);
4577
4578 if (p->nrows <= nrows_copied)
4579 p->nrows = 0;
4580 else
4581 {
4582 int height_copied = (r->desired_y + r->height
4583 - p->desired_y);
4584
4585 p->current_vpos += nrows_copied;
4586 p->desired_vpos += nrows_copied;
4587 p->nrows -= nrows_copied;
4588 p->current_y += height_copied;
4589 p->desired_y += height_copied;
4590 p->height -= height_copied;
4591 truncated_p = 1;
4592 }
4593 }
4594 }
177c0ea7 4595
1305621b
YM
4596 if (r->current_y != r->desired_y
4597 /* The condition below is equivalent to
4598 ((p->current_y >= r->desired_y
5f5c8ee5 4599 && p->current_y < r->desired_y + r->height)
1305621b 4600 || (p->current_y + p->height > r->desired_y
5f5c8ee5 4601 && (p->current_y + p->height
1305621b
YM
4602 <= r->desired_y + r->height)))
4603 because we have 0 < p->height <= r->height. */
4604 && p->current_y < r->desired_y + r->height
4605 && p->current_y + p->height > r->desired_y)
4606 p->nrows = 0;
4607
4608 /* Reorder runs by copied pixel lines if truncated. */
4609 if (truncated_p && p->nrows > 0)
4610 {
4611 int k = nruns - 1;
4612
4613 while (runs[k]->nrows == 0 || runs[k]->height < p->height)
4614 k--;
4615 memmove (runs + j, runs + j + 1, (k - j) * sizeof (*runs));
4616 runs[k] = p;
5f5c8ee5
GM
4617 }
4618 }
ea0d86af 4619
5f5c8ee5
GM
4620 /* Assign matrix rows. */
4621 for (j = 0; j < r->nrows; ++j)
4622 {
4623 struct glyph_row *from, *to;
408f5064 4624 int to_overlapped_p;
e876ff42 4625
5f5c8ee5
GM
4626 to = MATRIX_ROW (current_matrix, r->desired_vpos + j);
4627 from = MATRIX_ROW (desired_matrix, r->desired_vpos + j);
e876ff42 4628 to_overlapped_p = to->overlapped_p;
e61124cd 4629 from->redraw_fringe_bitmaps_p = from->fringe_bitmap_periodic_p;
5f5c8ee5 4630 assign_row (to, from);
1305621b
YM
4631 /* The above `assign_row' actually does swap, so if we had
4632 an overlap in the copy destination of two runs, then
4633 the second run would assign a previously disabled bogus
4634 row. But thanks to the truncation code in the
4635 preceding for-loop, we no longer have such an overlap,
4636 and thus the assigned row should always be enabled. */
4637 xassert (to->enabled_p);
4638 from->enabled_p = 0;
408f5064 4639 to->overlapped_p = to_overlapped_p;
5f5c8ee5
GM
4640 }
4641 }
15874c59 4642
6df5d75f
GM
4643 /* Clear the hash table, for the next time. */
4644 for (i = 0; i < row_entry_idx; ++i)
4645 row_table[row_entry_pool[i].bucket] = NULL;
4646
aec1708a
PE
4647 /* Value is 1 to indicate that we scrolled the display. */
4648 return 0 < nruns;
5f5c8ee5 4649}
de83c314 4650
15874c59 4651
4588ec20 4652\f
5f5c8ee5
GM
4653/************************************************************************
4654 Frame-Based Updates
4655 ************************************************************************/
4588ec20 4656
5f5c8ee5 4657/* Update the desired frame matrix of frame F.
4588ec20 4658
5f5c8ee5
GM
4659 FORCE_P non-zero means that the update should not be stopped by
4660 pending input. INHIBIT_HAIRY_ID_P non-zero means that scrolling
4661 should not be tried.
4662
4663 Value is non-zero if update was stopped due to pending input. */
4664
4665static int
971de7fb 4666update_frame_1 (struct frame *f, int force_p, int inhibit_id_p)
4588ec20 4667{
5f5c8ee5
GM
4668 /* Frame matrices to work on. */
4669 struct glyph_matrix *current_matrix = f->current_matrix;
4670 struct glyph_matrix *desired_matrix = f->desired_matrix;
4671 int i;
27786b2f 4672 int pause_p;
4588ec20 4673 int preempt_count = baud_rate / 2400 + 1;
5f5c8ee5
GM
4674
4675 xassert (current_matrix && desired_matrix);
4588ec20 4676
c37e4889
RS
4677 if (baud_rate != FRAME_COST_BAUD_RATE (f))
4678 calculate_costs (f);
4679
d88c2b9e
RS
4680 if (preempt_count <= 0)
4681 preempt_count = 1;
4682
a2130dbb
KS
4683#if !PERIODIC_PREEMPTION_CHECKING
4684 if (!force_p && detect_input_pending_ignore_squeezables ())
4588ec20 4685 {
27786b2f 4686 pause_p = 1;
4588ec20
JB
4687 goto do_pause;
4688 }
d012c62b 4689#endif
4588ec20 4690
5f5c8ee5 4691 /* If we cannot insert/delete lines, it's no use trying it. */
daf01701 4692 if (!FRAME_LINE_INS_DEL_OK (f))
5f5c8ee5 4693 inhibit_id_p = 1;
7098a0fa 4694
efb859b4 4695 /* See if any of the desired lines are enabled; don't compute for
5f5c8ee5
GM
4696 i/d line if just want cursor motion. */
4697 for (i = 0; i < desired_matrix->nrows; i++)
4698 if (MATRIX_ROW_ENABLED_P (desired_matrix, i))
4588ec20
JB
4699 break;
4700
4701 /* Try doing i/d line, if not yet inhibited. */
5f5c8ee5
GM
4702 if (!inhibit_id_p && i < desired_matrix->nrows)
4703 force_p |= scrolling (f);
4588ec20
JB
4704
4705 /* Update the individual lines as needed. Do bottom line first. */
5f5c8ee5
GM
4706 if (MATRIX_ROW_ENABLED_P (desired_matrix, desired_matrix->nrows - 1))
4707 update_frame_line (f, desired_matrix->nrows - 1);
4588ec20 4708
5f5c8ee5
GM
4709 /* Now update the rest of the lines. */
4710 for (i = 0; i < desired_matrix->nrows - 1 && (force_p || !input_pending); i++)
4588ec20 4711 {
5f5c8ee5 4712 if (MATRIX_ROW_ENABLED_P (desired_matrix, i))
4588ec20 4713 {
b6a65ac2 4714 if (FRAME_TERMCAP_P (f))
4588ec20
JB
4715 {
4716 /* Flush out every so many lines.
4717 Also flush out if likely to have more than 1k buffered
4718 otherwise. I'm told that some telnet connections get
4719 really screwed by more than 1k output at once. */
fced92f1
CY
4720 FILE *display_output = FRAME_TTY (f)->output;
4721 if (display_output)
4588ec20 4722 {
fced92f1
CY
4723 int outq = PENDING_OUTPUT_COUNT (display_output);
4724 if (outq > 900
4725 || (outq > 20 && ((i - 1) % preempt_count == 0)))
4588ec20 4726 {
fced92f1
CY
4727 fflush (display_output);
4728 if (preempt_count == 1)
4729 {
a41f8bed 4730#ifdef EMACS_OUTQSIZE
fced92f1
CY
4731 if (EMACS_OUTQSIZE (0, &outq) < 0)
4732 /* Probably not a tty. Ignore the error and reset
4733 the outq count. */
4734 outq = PENDING_OUTPUT_COUNT (FRAME_TTY (f->output));
4588ec20 4735#endif
fced92f1
CY
4736 outq *= 10;
4737 if (baud_rate <= outq && baud_rate > 0)
4738 sleep (outq / baud_rate);
4739 }
4588ec20
JB
4740 }
4741 }
4588ec20
JB
4742 }
4743
d012c62b
KS
4744#if PERIODIC_PREEMPTION_CHECKING
4745 if (!force_p)
4746 {
4747 EMACS_TIME tm, dif;
4748 EMACS_GET_TIME (tm);
4749 EMACS_SUB_TIME (dif, preemption_next_check, tm);
4750 if (EMACS_TIME_NEG_P (dif))
4751 {
4752 EMACS_ADD_TIME (preemption_next_check, tm, preemption_period);
993d4ab6
KS
4753 if (detect_input_pending_ignore_squeezables ())
4754 break;
d012c62b
KS
4755 }
4756 }
4757#else
4758 if (!force_p && (i - 1) % preempt_count == 0)
a2d5fca0 4759 detect_input_pending_ignore_squeezables ();
d012c62b 4760#endif
a2960116 4761
5f5c8ee5 4762 update_frame_line (f, i);
4588ec20 4763 }
4588ec20 4764 }
177c0ea7 4765
27786b2f 4766 pause_p = (i < FRAME_LINES (f) - 1) ? i : 0;
4588ec20
JB
4767
4768 /* Now just clean up termcap drivers and set cursor, etc. */
27786b2f 4769 if (!pause_p)
4588ec20 4770 {
48cf7030 4771 if ((cursor_in_echo_area
5f5c8ee5 4772 /* If we are showing a message instead of the mini-buffer,
2577053b 4773 show the cursor for the message instead of for the
5f5c8ee5 4774 (now hidden) mini-buffer contents. */
2577053b
RS
4775 || (EQ (minibuf_window, selected_window)
4776 && EQ (minibuf_window, echo_area_window)
b96fd3e8 4777 && !NILP (echo_area_buffer[0])))
2577053b 4778 /* These cases apply only to the frame that contains
5f5c8ee5 4779 the active mini-buffer window. */
2577053b 4780 && FRAME_HAS_MINIBUF_P (f)
140f8645 4781 && EQ (FRAME_MINIBUF_WINDOW (f), echo_area_window))
1113d9db 4782 {
7df02016 4783 int top = WINDOW_TOP_EDGE_LINE (XWINDOW (FRAME_MINIBUF_WINDOW (f)));
648fa17d
JB
4784 int row, col;
4785
4786 if (cursor_in_echo_area < 0)
4787 {
5f5c8ee5
GM
4788 /* Negative value of cursor_in_echo_area means put
4789 cursor at beginning of line. */
648fa17d
JB
4790 row = top;
4791 col = 0;
4792 }
1113d9db 4793 else
648fa17d 4794 {
5f5c8ee5
GM
4795 /* Positive value of cursor_in_echo_area means put
4796 cursor at the end of the prompt. If the mini-buffer
4797 is several lines high, find the last line that has
4798 any text on it. */
7df02016 4799 row = FRAME_LINES (f);
177c0ea7 4800 do
648fa17d 4801 {
5f5c8ee5
GM
4802 --row;
4803 col = 0;
177c0ea7 4804
5f5c8ee5
GM
4805 if (MATRIX_ROW_ENABLED_P (current_matrix, row))
4806 {
4807 /* Frame rows are filled up with spaces that
4808 must be ignored here. */
5f5c8ee5
GM
4809 struct glyph_row *r = MATRIX_ROW (current_matrix,
4810 row);
4811 struct glyph *start = r->glyphs[TEXT_AREA];
4812 struct glyph *last = start + r->used[TEXT_AREA];
4813
4814 while (last > start
4815 && (last - 1)->charpos < 0)
4816 --last;
177c0ea7 4817
5f5c8ee5
GM
4818 col = last - start;
4819 }
648fa17d
JB
4820 }
4821 while (row > top && col == 0);
4822
6395da5c 4823 /* Make sure COL is not out of range. */
868e640e 4824 if (col >= FRAME_CURSOR_X_LIMIT (f))
648fa17d 4825 {
6395da5c 4826 /* If we have another row, advance cursor into it. */
7df02016 4827 if (row < FRAME_LINES (f) - 1)
6395da5c 4828 {
7df02016 4829 col = FRAME_LEFT_SCROLL_BAR_COLS (f);
6395da5c
RS
4830 row++;
4831 }
4832 /* Otherwise move it back in range. */
4833 else
868e640e 4834 col = FRAME_CURSOR_X_LIMIT (f) - 1;
648fa17d
JB
4835 }
4836 }
4837
385ed61f 4838 cursor_to (f, row, col);
1113d9db 4839 }
4588ec20 4840 else
5f5c8ee5
GM
4841 {
4842 /* We have only one cursor on terminal frames. Use it to
4843 display the cursor of the selected window. */
4844 struct window *w = XWINDOW (FRAME_SELECTED_WINDOW (f));
a871441d
GM
4845 if (w->cursor.vpos >= 0
4846 /* The cursor vpos may be temporarily out of bounds
4847 in the following situation: There is one window,
4848 with the cursor in the lower half of it. The window
4849 is split, and a message causes a redisplay before
4850 a new cursor position has been computed. */
7df02016 4851 && w->cursor.vpos < WINDOW_TOTAL_LINES (w))
5f5c8ee5
GM
4852 {
4853 int x = WINDOW_TO_FRAME_HPOS (w, w->cursor.hpos);
4854 int y = WINDOW_TO_FRAME_VPOS (w, w->cursor.vpos);
4855
7df02016
KS
4856 if (INTEGERP (w->left_margin_cols))
4857 x += XFASTINT (w->left_margin_cols);
177c0ea7 4858
7df02016 4859 /* x = max (min (x, FRAME_TOTAL_COLS (f) - 1), 0); */
385ed61f 4860 cursor_to (f, y, x);
5f5c8ee5
GM
4861 }
4862 }
4588ec20
JB
4863 }
4864
ef1b0ba7 4865#if !PERIODIC_PREEMPTION_CHECKING
4588ec20 4866 do_pause:
ef1b0ba7 4867#endif
4588ec20 4868
5f5c8ee5 4869 clear_desired_matrices (f);
27786b2f 4870 return pause_p;
4588ec20
JB
4871}
4872
4588ec20 4873
5f5c8ee5 4874/* Do line insertions/deletions on frame F for frame-based redisplay. */
4588ec20 4875
5bf46f05 4876static int
971de7fb 4877scrolling (struct frame *frame)
4588ec20
JB
4878{
4879 int unchanged_at_top, unchanged_at_bottom;
4880 int window_size;
4881 int changed_lines;
7df02016
KS
4882 int *old_hash = (int *) alloca (FRAME_LINES (frame) * sizeof (int));
4883 int *new_hash = (int *) alloca (FRAME_LINES (frame) * sizeof (int));
4884 int *draw_cost = (int *) alloca (FRAME_LINES (frame) * sizeof (int));
4885 int *old_draw_cost = (int *) alloca (FRAME_LINES (frame) * sizeof (int));
4588ec20 4886 register int i;
7df02016 4887 int free_at_end_vpos = FRAME_LINES (frame);
5f5c8ee5
GM
4888 struct glyph_matrix *current_matrix = frame->current_matrix;
4889 struct glyph_matrix *desired_matrix = frame->desired_matrix;
4588ec20 4890
5f5c8ee5
GM
4891 if (!current_matrix)
4892 abort ();
4588ec20 4893
5f5c8ee5
GM
4894 /* Compute hash codes of all the lines. Also calculate number of
4895 changed lines, number of unchanged lines at the beginning, and
4896 number of unchanged lines at the end. */
4588ec20
JB
4897 changed_lines = 0;
4898 unchanged_at_top = 0;
7df02016
KS
4899 unchanged_at_bottom = FRAME_LINES (frame);
4900 for (i = 0; i < FRAME_LINES (frame); i++)
4588ec20
JB
4901 {
4902 /* Give up on this scrolling if some old lines are not enabled. */
5f5c8ee5 4903 if (!MATRIX_ROW_ENABLED_P (current_matrix, i))
4588ec20 4904 return 0;
5f5c8ee5
GM
4905 old_hash[i] = line_hash_code (MATRIX_ROW (current_matrix, i));
4906 if (! MATRIX_ROW_ENABLED_P (desired_matrix, i))
f188b3c4
RS
4907 {
4908 /* This line cannot be redrawn, so don't let scrolling mess it. */
4909 new_hash[i] = old_hash[i];
4910#define INFINITY 1000000 /* Taken from scroll.c */
4911 draw_cost[i] = INFINITY;
4912 }
4588ec20 4913 else
f188b3c4 4914 {
5f5c8ee5
GM
4915 new_hash[i] = line_hash_code (MATRIX_ROW (desired_matrix, i));
4916 draw_cost[i] = line_draw_cost (desired_matrix, i);
f188b3c4 4917 }
4588ec20
JB
4918
4919 if (old_hash[i] != new_hash[i])
4920 {
4921 changed_lines++;
7df02016 4922 unchanged_at_bottom = FRAME_LINES (frame) - i - 1;
4588ec20
JB
4923 }
4924 else if (i == unchanged_at_top)
4925 unchanged_at_top++;
5f5c8ee5 4926 old_draw_cost[i] = line_draw_cost (current_matrix, i);
4588ec20
JB
4927 }
4928
4929 /* If changed lines are few, don't allow preemption, don't scroll. */
daf01701 4930 if ((!FRAME_SCROLL_REGION_OK (frame)
8a56675d 4931 && changed_lines < baud_rate / 2400)
7df02016 4932 || unchanged_at_bottom == FRAME_LINES (frame))
4588ec20
JB
4933 return 1;
4934
7df02016 4935 window_size = (FRAME_LINES (frame) - unchanged_at_top
4588ec20
JB
4936 - unchanged_at_bottom);
4937
daf01701 4938 if (FRAME_SCROLL_REGION_OK (frame))
4588ec20 4939 free_at_end_vpos -= unchanged_at_bottom;
daf01701 4940 else if (FRAME_MEMORY_BELOW_FRAME (frame))
4588ec20
JB
4941 free_at_end_vpos = -1;
4942
4943 /* If large window, fast terminal and few lines in common between
5f5c8ee5 4944 current frame and desired frame, don't bother with i/d calc. */
daf01701 4945 if (!FRAME_SCROLL_REGION_OK (frame)
8a56675d 4946 && window_size >= 18 && baud_rate > 2400
4588ec20
JB
4947 && (window_size >=
4948 10 * scrolling_max_lines_saved (unchanged_at_top,
7df02016 4949 FRAME_LINES (frame) - unchanged_at_bottom,
4588ec20
JB
4950 old_hash, new_hash, draw_cost)))
4951 return 0;
4952
5f5c8ee5
GM
4953 if (window_size < 2)
4954 return 0;
4955
502b9b64 4956 scrolling_1 (frame, window_size, unchanged_at_top, unchanged_at_bottom,
4588ec20 4957 draw_cost + unchanged_at_top - 1,
190bb91a 4958 old_draw_cost + unchanged_at_top - 1,
4588ec20
JB
4959 old_hash + unchanged_at_top - 1,
4960 new_hash + unchanged_at_top - 1,
4961 free_at_end_vpos - unchanged_at_top);
4962
4963 return 0;
4964}
4588ec20 4965
4588ec20 4966
5f5c8ee5
GM
4967/* Count the number of blanks at the start of the vector of glyphs R
4968 which is LEN glyphs long. */
4588ec20 4969
4588ec20 4970static int
971de7fb 4971count_blanks (struct glyph *r, int len)
4588ec20 4972{
5f5c8ee5 4973 int i;
177c0ea7 4974
5f5c8ee5
GM
4975 for (i = 0; i < len; ++i)
4976 if (!CHAR_GLYPH_SPACE_P (r[i]))
4977 break;
4978
4979 return i;
4588ec20
JB
4980}
4981
5f5c8ee5
GM
4982
4983/* Count the number of glyphs in common at the start of the glyph
4984 vectors STR1 and STR2. END1 is the end of STR1 and END2 is the end
4985 of STR2. Value is the number of equal glyphs equal at the start. */
4986
4588ec20 4987static int
971de7fb 4988count_match (struct glyph *str1, struct glyph *end1, struct glyph *str2, struct glyph *end2)
4588ec20 4989{
5f5c8ee5
GM
4990 struct glyph *p1 = str1;
4991 struct glyph *p2 = str2;
177c0ea7 4992
5f5c8ee5
GM
4993 while (p1 < end1
4994 && p2 < end2
42186983 4995 && GLYPH_CHAR_AND_FACE_EQUAL_P (p1, p2))
5f5c8ee5 4996 ++p1, ++p2;
177c0ea7 4997
5f5c8ee5 4998 return p1 - str1;
4588ec20
JB
4999}
5000
5f5c8ee5 5001
4588ec20 5002/* Char insertion/deletion cost vector, from term.c */
4588ec20 5003
5e617bc2 5004#define char_ins_del_cost(f) (&char_ins_del_vector[FRAME_TOTAL_COLS ((f))])
4588ec20 5005
5f5c8ee5
GM
5006
5007/* Perform a frame-based update on line VPOS in frame FRAME. */
5008
4588ec20 5009static void
971de7fb 5010update_frame_line (struct frame *f, int vpos)
4588ec20 5011{
5f5c8ee5 5012 struct glyph *obody, *nbody, *op1, *op2, *np1, *nend;
4588ec20
JB
5013 int tem;
5014 int osp, nsp, begmatch, endmatch, olen, nlen;
c363a1d6
GM
5015 struct glyph_matrix *current_matrix = f->current_matrix;
5016 struct glyph_matrix *desired_matrix = f->desired_matrix;
5f5c8ee5
GM
5017 struct glyph_row *current_row = MATRIX_ROW (current_matrix, vpos);
5018 struct glyph_row *desired_row = MATRIX_ROW (desired_matrix, vpos);
5019 int must_write_whole_line_p;
daf01701 5020 int write_spaces_p = FRAME_MUST_WRITE_SPACES (f);
c363a1d6 5021 int colored_spaces_p = (FACE_FROM_ID (f, DEFAULT_FACE_ID)->background
0a894bad
GM
5022 != FACE_TTY_DEFAULT_BG_COLOR);
5023
5024 if (colored_spaces_p)
5025 write_spaces_p = 1;
5f5c8ee5 5026
26c63686
GM
5027 /* Current row not enabled means it has unknown contents. We must
5028 write the whole desired line in that case. */
5f5c8ee5
GM
5029 must_write_whole_line_p = !current_row->enabled_p;
5030 if (must_write_whole_line_p)
4588ec20 5031 {
5f5c8ee5 5032 obody = 0;
4588ec20
JB
5033 olen = 0;
5034 }
5035 else
5036 {
5f5c8ee5
GM
5037 obody = MATRIX_ROW_GLYPH_START (current_matrix, vpos);
5038 olen = current_row->used[TEXT_AREA];
177c0ea7 5039
4cecaab8
MB
5040 /* Ignore trailing spaces, if we can. */
5041 if (!write_spaces_p)
5042 while (olen > 0 && CHAR_GLYPH_SPACE_P (obody[olen-1]))
5043 olen--;
4588ec20
JB
5044 }
5045
5f5c8ee5
GM
5046 current_row->enabled_p = 1;
5047 current_row->used[TEXT_AREA] = desired_row->used[TEXT_AREA];
4588ec20 5048
5f5c8ee5
GM
5049 /* If desired line is empty, just clear the line. */
5050 if (!desired_row->enabled_p)
4588ec20
JB
5051 {
5052 nlen = 0;
5053 goto just_erase;
5054 }
5055
5f5c8ee5
GM
5056 nbody = desired_row->glyphs[TEXT_AREA];
5057 nlen = desired_row->used[TEXT_AREA];
5058 nend = nbody + nlen;
5059
5060 /* If display line has unknown contents, write the whole line. */
5061 if (must_write_whole_line_p)
5062 {
26c63686 5063 /* Ignore spaces at the end, if we can. */
0a894bad 5064 if (!write_spaces_p)
74ca462f
GM
5065 while (nlen > 0 && CHAR_GLYPH_SPACE_P (nbody[nlen - 1]))
5066 --nlen;
5067
26c63686 5068 /* Write the contents of the desired line. */
74ca462f 5069 if (nlen)
26c63686 5070 {
385ed61f
KL
5071 cursor_to (f, vpos, 0);
5072 write_glyphs (f, nbody, nlen);
26c63686 5073 }
177c0ea7 5074
26c63686
GM
5075 /* Don't call clear_end_of_line if we already wrote the whole
5076 line. The cursor will not be at the right margin in that
5077 case but in the line below. */
7df02016 5078 if (nlen < FRAME_TOTAL_COLS (f))
26c63686 5079 {
385ed61f
KL
5080 cursor_to (f, vpos, nlen);
5081 clear_end_of_line (f, FRAME_TOTAL_COLS (f));
26c63686 5082 }
58827478
GM
5083 else
5084 /* Make sure we are in the right row, otherwise cursor movement
5085 with cmgoto might use `ch' in the wrong row. */
385ed61f 5086 cursor_to (f, vpos, 0);
177c0ea7 5087
5f5c8ee5
GM
5088 make_current (desired_matrix, current_matrix, vpos);
5089 return;
5090 }
4588ec20
JB
5091
5092 /* Pretend trailing spaces are not there at all,
5093 unless for one reason or another we must write all spaces. */
4cecaab8
MB
5094 if (!write_spaces_p)
5095 while (nlen > 0 && CHAR_GLYPH_SPACE_P (nbody[nlen - 1]))
5096 nlen--;
4588ec20
JB
5097
5098 /* If there's no i/d char, quickly do the best we can without it. */
daf01701 5099 if (!FRAME_CHAR_INS_DEL_OK (f))
4588ec20 5100 {
5f5c8ee5 5101 int i, j;
4588ec20 5102
5f5c8ee5
GM
5103 /* Find the first glyph in desired row that doesn't agree with
5104 a glyph in the current row, and write the rest from there on. */
4588ec20
JB
5105 for (i = 0; i < nlen; i++)
5106 {
5f5c8ee5 5107 if (i >= olen || !GLYPH_EQUAL_P (nbody + i, obody + i))
4588ec20 5108 {
5f5c8ee5
GM
5109 /* Find the end of the run of different glyphs. */
5110 j = i + 1;
5111 while (j < nlen
5112 && (j >= olen
5113 || !GLYPH_EQUAL_P (nbody + j, obody + j)
5114 || CHAR_GLYPH_PADDING_P (nbody[j])))
5115 ++j;
177c0ea7
JB
5116
5117 /* Output this run of non-matching chars. */
385ed61f
KL
5118 cursor_to (f, vpos, i);
5119 write_glyphs (f, nbody + i, j - i);
5f5c8ee5 5120 i = j - 1;
4588ec20
JB
5121
5122 /* Now find the next non-match. */
5123 }
5124 }
5125
5126 /* Clear the rest of the line, or the non-clear part of it. */
5127 if (olen > nlen)
5128 {
385ed61f
KL
5129 cursor_to (f, vpos, nlen);
5130 clear_end_of_line (f, olen);
4588ec20
JB
5131 }
5132
5f5c8ee5
GM
5133 /* Make current row = desired row. */
5134 make_current (desired_matrix, current_matrix, vpos);
4588ec20
JB
5135 return;
5136 }
5137
5f5c8ee5
GM
5138 /* Here when CHAR_INS_DEL_OK != 0, i.e. we can insert or delete
5139 characters in a row. */
5140
4588ec20
JB
5141 if (!olen)
5142 {
5f5c8ee5
GM
5143 /* If current line is blank, skip over initial spaces, if
5144 possible, and write the rest. */
4cecaab8 5145 if (write_spaces_p)
5f5c8ee5
GM
5146 nsp = 0;
5147 else
5148 nsp = count_blanks (nbody, nlen);
5149
4588ec20
JB
5150 if (nlen > nsp)
5151 {
385ed61f
KL
5152 cursor_to (f, vpos, nsp);
5153 write_glyphs (f, nbody + nsp, nlen - nsp);
4588ec20
JB
5154 }
5155
502b9b64 5156 /* Exchange contents between current_frame and new_frame. */
5f5c8ee5 5157 make_current (desired_matrix, current_matrix, vpos);
4588ec20
JB
5158 return;
5159 }
5160
4588ec20 5161 /* Compute number of leading blanks in old and new contents. */
5f5c8ee5 5162 osp = count_blanks (obody, olen);
4cecaab8 5163 nsp = (colored_spaces_p ? 0 : count_blanks (nbody, nlen));
4588ec20 5164
5f5c8ee5
GM
5165 /* Compute number of matching chars starting with first non-blank. */
5166 begmatch = count_match (obody + osp, obody + olen,
5167 nbody + nsp, nbody + nlen);
4588ec20
JB
5168
5169 /* Spaces in new match implicit space past the end of old. */
5170 /* A bug causing this to be a no-op was fixed in 18.29. */
0a894bad 5171 if (!write_spaces_p && osp + begmatch == olen)
4588ec20
JB
5172 {
5173 np1 = nbody + nsp;
5f5c8ee5
GM
5174 while (np1 + begmatch < nend && CHAR_GLYPH_SPACE_P (np1[begmatch]))
5175 ++begmatch;
4588ec20
JB
5176 }
5177
5178 /* Avoid doing insert/delete char
5179 just cause number of leading spaces differs
5f5c8ee5 5180 when the following text does not match. */
4588ec20
JB
5181 if (begmatch == 0 && osp != nsp)
5182 osp = nsp = min (osp, nsp);
5183
5184 /* Find matching characters at end of line */
5185 op1 = obody + olen;
5186 np1 = nbody + nlen;
5187 op2 = op1 + begmatch - min (olen - osp, nlen - nsp);
5f5c8ee5
GM
5188 while (op1 > op2
5189 && GLYPH_EQUAL_P (op1 - 1, np1 - 1))
4588ec20
JB
5190 {
5191 op1--;
5192 np1--;
5193 }
5194 endmatch = obody + olen - op1;
5195
4588ec20
JB
5196 /* tem gets the distance to insert or delete.
5197 endmatch is how many characters we save by doing so.
5198 Is it worth it? */
5199
5200 tem = (nlen - nsp) - (olen - osp);
5201 if (endmatch && tem
daf01701 5202 && (!FRAME_CHAR_INS_DEL_OK (f)
8a56675d 5203 || endmatch <= char_ins_del_cost (f)[tem]))
4588ec20
JB
5204 endmatch = 0;
5205
5206 /* nsp - osp is the distance to insert or delete.
5207 If that is nonzero, begmatch is known to be nonzero also.
5208 begmatch + endmatch is how much we save by doing the ins/del.
5209 Is it worth it? */
5210
5211 if (nsp != osp
daf01701 5212 && (!FRAME_CHAR_INS_DEL_OK (f)
c363a1d6 5213 || begmatch + endmatch <= char_ins_del_cost (f)[nsp - osp]))
4588ec20
JB
5214 {
5215 begmatch = 0;
5216 endmatch = 0;
5217 osp = nsp = min (osp, nsp);
5218 }
5219
5220 /* Now go through the line, inserting, writing and
5221 deleting as appropriate. */
5222
5223 if (osp > nsp)
5224 {
385ed61f
KL
5225 cursor_to (f, vpos, nsp);
5226 delete_glyphs (f, osp - nsp);
4588ec20
JB
5227 }
5228 else if (nsp > osp)
5229 {
5230 /* If going to delete chars later in line
5231 and insert earlier in the line,
5232 must delete first to avoid losing data in the insert */
5233 if (endmatch && nlen < olen + nsp - osp)
5234 {
385ed61f
KL
5235 cursor_to (f, vpos, nlen - endmatch + osp - nsp);
5236 delete_glyphs (f, olen + nsp - osp - nlen);
4588ec20
JB
5237 olen = nlen - (nsp - osp);
5238 }
385ed61f
KL
5239 cursor_to (f, vpos, osp);
5240 insert_glyphs (f, 0, nsp - osp);
4588ec20
JB
5241 }
5242 olen += nsp - osp;
5243
5244 tem = nsp + begmatch + endmatch;
5245 if (nlen != tem || olen != tem)
5246 {
4588ec20
JB
5247 if (!endmatch || nlen == olen)
5248 {
c363a1d6
GM
5249 /* If new text being written reaches right margin, there is
5250 no need to do clear-to-eol at the end of this function
5251 (and it would not be safe, since cursor is not going to
5252 be "at the margin" after the text is done). */
7df02016 5253 if (nlen == FRAME_TOTAL_COLS (f))
4588ec20 5254 olen = 0;
c363a1d6
GM
5255
5256 /* Function write_glyphs is prepared to do nothing
5257 if passed a length <= 0. Check it here to avoid
5258 unnecessary cursor movement. */
5259 if (nlen - tem > 0)
5260 {
385ed61f
KL
5261 cursor_to (f, vpos, nsp + begmatch);
5262 write_glyphs (f, nbody + nsp + begmatch, nlen - tem);
c363a1d6 5263 }
4588ec20
JB
5264 }
5265 else if (nlen > olen)
5266 {
24e86043
KH
5267 /* Here, we used to have the following simple code:
5268 ----------------------------------------
5269 write_glyphs (nbody + nsp + begmatch, olen - tem);
5270 insert_glyphs (nbody + nsp + begmatch + olen - tem, nlen - olen);
5271 ----------------------------------------
5272 but it doesn't work if nbody[nsp + begmatch + olen - tem]
5273 is a padding glyph. */
5274 int out = olen - tem; /* Columns to be overwritten originally. */
5275 int del;
5f5c8ee5 5276
385ed61f 5277 cursor_to (f, vpos, nsp + begmatch);
177c0ea7 5278
5f5c8ee5 5279 /* Calculate columns we can actually overwrite. */
c363a1d6
GM
5280 while (CHAR_GLYPH_PADDING_P (nbody[nsp + begmatch + out]))
5281 out--;
385ed61f 5282 write_glyphs (f, nbody + nsp + begmatch, out);
177c0ea7 5283
5f5c8ee5
GM
5284 /* If we left columns to be overwritten, we must delete them. */
5285 del = olen - tem - out;
c363a1d6 5286 if (del > 0)
385ed61f 5287 delete_glyphs (f, del);
177c0ea7 5288
5f5c8ee5 5289 /* At last, we insert columns not yet written out. */
385ed61f 5290 insert_glyphs (f, nbody + nsp + begmatch + out, nlen - olen + del);
5f5c8ee5
GM
5291 olen = nlen;
5292 }
5293 else if (olen > nlen)
5294 {
385ed61f
KL
5295 cursor_to (f, vpos, nsp + begmatch);
5296 write_glyphs (f, nbody + nsp + begmatch, nlen - tem);
5297 delete_glyphs (f, olen - nlen);
5f5c8ee5
GM
5298 olen = nlen;
5299 }
bd9e3e75 5300 }
5f5c8ee5
GM
5301
5302 just_erase:
5303 /* If any unerased characters remain after the new line, erase them. */
5304 if (olen > nlen)
078b3696 5305 {
385ed61f
KL
5306 cursor_to (f, vpos, nlen);
5307 clear_end_of_line (f, olen);
078b3696 5308 }
5f5c8ee5
GM
5309
5310 /* Exchange contents between current_frame and new_frame. */
5311 make_current (desired_matrix, current_matrix, vpos);
078b3696 5312}
5f5c8ee5
GM
5313
5314
078b3696 5315\f
5f5c8ee5
GM
5316/***********************************************************************
5317 X/Y Position -> Buffer Position
5318 ***********************************************************************/
5319
a1b0a6db 5320/* Determine what's under window-relative pixel position (*X, *Y).
2396cbba 5321 Return the OBJECT (string or buffer) that's there.
6b61353c 5322 Return in *POS the position in that object.
2396cbba
EZ
5323 Adjust *X and *Y to character positions.
5324 Return in *DX and *DY the pixel coordinates of the click,
5325 relative to the top left corner of OBJECT, or relative to
5326 the top left corner of the character glyph at (*X, *Y)
5327 if OBJECT is nil.
5328 Return WIDTH and HEIGHT of the object at (*X, *Y), or zero
5329 if the coordinates point to an empty area of the display. */
5f5c8ee5 5330
6b61353c 5331Lisp_Object
971de7fb 5332buffer_posn_from_coords (struct window *w, int *x, int *y, struct display_pos *pos, Lisp_Object *object, int *dx, int *dy, int *width, int *height)
4588ec20 5333{
5f5c8ee5 5334 struct it it;
707ea971 5335 Lisp_Object old_current_buffer = Fcurrent_buffer ();
5f5c8ee5 5336 struct text_pos startp;
6b61353c
KH
5337 Lisp_Object string;
5338 struct glyph_row *row;
cedd7cd9
KS
5339#ifdef HAVE_WINDOW_SYSTEM
5340 struct image *img = 0;
5341#endif
2396cbba 5342 int x0, x1, to_x;
57b3e30b 5343 void *itdata = NULL;
5f5c8ee5 5344
707ea971
CY
5345 /* We used to set current_buffer directly here, but that does the
5346 wrong thing with `face-remapping-alist' (bug#2044). */
5347 Fset_buffer (w->buffer);
57b3e30b 5348 itdata = bidi_shelve_cache ();
5f5c8ee5
GM
5349 SET_TEXT_POS_FROM_MARKER (startp, w->start);
5350 CHARPOS (startp) = min (ZV, max (BEGV, CHARPOS (startp)));
5351 BYTEPOS (startp) = min (ZV_BYTE, max (BEGV_BYTE, BYTEPOS (startp)));
5352 start_display (&it, w, startp);
352ec8ff
EZ
5353 /* start_display takes into account the header-line row, but IT's
5354 vpos still counts from the glyph row that includes the window's
5355 start position. Adjust for a possible header-line row. */
5356 it.vpos += WINDOW_WANTS_HEADER_LINE_P (w) ? 1 : 0;
177c0ea7 5357
9173a8fb 5358 x0 = *x;
2396cbba
EZ
5359
5360 /* First, move to the beginning of the row corresponding to *Y. We
5361 need to be in that row to get the correct value of base paragraph
40629f17 5362 direction for the text at (*X, *Y). */
2396cbba
EZ
5363 move_it_to (&it, -1, 0, *y, -1, MOVE_TO_X | MOVE_TO_Y);
5364
5365 /* TO_X is the pixel position that the iterator will compute for the
40629f17
EZ
5366 glyph at *X. We add it.first_visible_x because iterator
5367 positions include the hscroll. */
2396cbba
EZ
5368 to_x = x0 + it.first_visible_x;
5369 if (it.bidi_it.paragraph_dir == R2L)
5370 /* For lines in an R2L paragraph, we need to mirror TO_X wrt the
5371 text area. This is because the iterator, even in R2L
5372 paragraphs, delivers glyphs as if they started at the left
5373 margin of the window. (When we actually produce glyphs for
5374 display, we reverse their order in PRODUCE_GLYPHS, but the
5375 iterator doesn't know about that.) The following line adjusts
5376 the pixel position to the iterator geometry, which is what
40629f17
EZ
5377 move_it_* routines use. (The -1 is because in a window whose
5378 text-area width is W, the rightmost pixel position is W-1, and
5379 it should be mirrored into zero pixel position.) */
5380 to_x = window_box_width (w, TEXT_AREA) - to_x - 1;
5381
5382 /* Now move horizontally in the row to the glyph under *X. Second
5383 argument is ZV to prevent move_it_in_display_line from matching
5384 based on buffer positions. */
2396cbba 5385 move_it_in_display_line (&it, ZV, to_x, MOVE_TO_X);
35928349 5386 bidi_unshelve_cache (itdata, 0);
177c0ea7 5387
707ea971 5388 Fset_buffer (old_current_buffer);
a1b0a6db 5389
6b61353c
KH
5390 *dx = x0 + it.first_visible_x - it.current_x;
5391 *dy = *y - it.current_y;
5392
5393 string = w->buffer;
5394 if (STRINGP (it.string))
5395 string = it.string;
a1b0a6db 5396 *pos = it.current;
86282aab
KH
5397 if (it.what == IT_COMPOSITION
5398 && it.cmp_it.nchars > 1
5399 && it.cmp_it.reversed_p)
5400 {
5401 /* The current display element is a grapheme cluster in a
5402 composition. In that case, we need the position of the first
5403 character of the cluster. But, as it.cmp_it.reversed_p is 1,
5404 it.current points to the last character of the cluster, thus
5405 we must move back to the first character of the same
5406 cluster. */
5407 CHARPOS (pos->pos) -= it.cmp_it.nchars - 1;
5408 if (STRINGP (it.string))
5409 BYTEPOS (pos->pos) = string_char_to_byte (string, CHARPOS (pos->pos));
5410 else
425cc014
EZ
5411 BYTEPOS (pos->pos) = buf_charpos_to_bytepos (XBUFFER (w->buffer),
5412 CHARPOS (pos->pos));
86282aab 5413 }
6b61353c
KH
5414
5415#ifdef HAVE_WINDOW_SYSTEM
5416 if (it.what == IT_IMAGE)
5417 {
6b61353c
KH
5418 if ((img = IMAGE_FROM_ID (it.f, it.image_id)) != NULL
5419 && !NILP (img->spec))
5420 *object = img->spec;
5421 }
5422#endif
5423
b70d98e1
KS
5424 if (it.vpos < w->current_matrix->nrows
5425 && (row = MATRIX_ROW (w->current_matrix, it.vpos),
5426 row->enabled_p))
6b61353c
KH
5427 {
5428 if (it.hpos < row->used[TEXT_AREA])
5429 {
5430 struct glyph *glyph = row->glyphs[TEXT_AREA] + it.hpos;
6b61353c 5431#ifdef HAVE_WINDOW_SYSTEM
cedd7cd9
KS
5432 if (img)
5433 {
5434 *dy -= row->ascent - glyph->ascent;
4be9765d
KH
5435 *dx += glyph->slice.img.x;
5436 *dy += glyph->slice.img.y;
cedd7cd9
KS
5437 /* Image slices positions are still relative to the entire image */
5438 *width = img->width;
5439 *height = img->height;
5440 }
5441 else
6b61353c 5442#endif
cedd7cd9
KS
5443 {
5444 *width = glyph->pixel_width;
5445 *height = glyph->ascent + glyph->descent;
5446 }
6b61353c
KH
5447 }
5448 else
5449 {
5450 *width = 0;
5451 *height = row->height;
5452 }
5453 }
5454 else
5455 {
5456 *width = *height = 0;
5457 }
5458
5459 /* Add extra (default width) columns if clicked after EOL. */
5e617bc2 5460 x1 = max (0, it.current_x + it.pixel_width - it.first_visible_x);
6b61353c
KH
5461 if (x0 > x1)
5462 it.hpos += (x0 - x1) / WINDOW_FRAME_COLUMN_WIDTH (w);
5463
5464 *x = it.hpos;
5465 *y = it.vpos;
5466
5467 return string;
5f5c8ee5 5468}
4588ec20 5469
5f5c8ee5
GM
5470
5471/* Value is the string under window-relative coordinates X/Y in the
6b61353c
KH
5472 mode line or header line (PART says which) of window W, or nil if none.
5473 *CHARPOS is set to the position in the string returned. */
5f5c8ee5
GM
5474
5475Lisp_Object
ace1712c
EZ
5476mode_line_string (struct window *w, enum window_part part,
5477 int *x, int *y, EMACS_INT *charpos, Lisp_Object *object,
5478 int *dx, int *dy, int *width, int *height)
5f5c8ee5
GM
5479{
5480 struct glyph_row *row;
5481 struct glyph *glyph, *end;
6b61353c 5482 int x0, y0;
5f5c8ee5
GM
5483 Lisp_Object string = Qnil;
5484
641bdbf3 5485 if (part == ON_MODE_LINE)
5f5c8ee5
GM
5486 row = MATRIX_MODE_LINE_ROW (w->current_matrix);
5487 else
045dee35 5488 row = MATRIX_HEADER_LINE_ROW (w->current_matrix);
6b61353c
KH
5489 y0 = *y - row->y;
5490 *y = row - MATRIX_FIRST_TEXT_ROW (w->current_matrix);
5f5c8ee5
GM
5491
5492 if (row->mode_line_p && row->enabled_p)
4588ec20 5493 {
5f5c8ee5
GM
5494 /* Find the glyph under X. If we find one with a string object,
5495 it's the one we were looking for. */
5496 glyph = row->glyphs[TEXT_AREA];
5497 end = glyph + row->used[TEXT_AREA];
cfde341f 5498 for (x0 = *x; glyph < end && x0 >= glyph->pixel_width; ++glyph)
6b61353c
KH
5499 x0 -= glyph->pixel_width;
5500 *x = glyph - row->glyphs[TEXT_AREA];
5501 if (glyph < end)
5502 {
5503 string = glyph->object;
5504 *charpos = glyph->charpos;
5505 *width = glyph->pixel_width;
5506 *height = glyph->ascent + glyph->descent;
5507#ifdef HAVE_WINDOW_SYSTEM
5508 if (glyph->type == IMAGE_GLYPH)
5509 {
5510 struct image *img;
5511 img = IMAGE_FROM_ID (WINDOW_XFRAME (w), glyph->u.img_id);
5512 if (img != NULL)
5513 *object = img->spec;
5514 y0 -= row->ascent - glyph->ascent;
5515 }
5516#endif
5517 }
5518 else
5519 {
5520 /* Add extra (default width) columns if clicked after EOL. */
5521 *x += x0 / WINDOW_FRAME_COLUMN_WIDTH (w);
5522 *width = 0;
5523 *height = row->height;
5524 }
5525 }
5526 else
5527 {
5528 *x = 0;
5529 x0 = 0;
5530 *width = *height = 0;
4588ec20 5531 }
5f5c8ee5 5532
6b61353c
KH
5533 *dx = x0;
5534 *dy = y0;
5535
5f5c8ee5 5536 return string;
4588ec20 5537}
5f5c8ee5
GM
5538
5539
db1db309
GM
5540/* Value is the string under window-relative coordinates X/Y in either
5541 marginal area, or nil if none. *CHARPOS is set to the position in
5542 the string returned. */
5543
5544Lisp_Object
ace1712c
EZ
5545marginal_area_string (struct window *w, enum window_part part,
5546 int *x, int *y, EMACS_INT *charpos, Lisp_Object *object,
5547 int *dx, int *dy, int *width, int *height)
db1db309
GM
5548{
5549 struct glyph_row *row = w->current_matrix->rows;
5550 struct glyph *glyph, *end;
6b61353c 5551 int x0, y0, i, wy = *y;
641bdbf3 5552 int area;
db1db309
GM
5553 Lisp_Object string = Qnil;
5554
641bdbf3 5555 if (part == ON_LEFT_MARGIN)
db1db309 5556 area = LEFT_MARGIN_AREA;
641bdbf3 5557 else if (part == ON_RIGHT_MARGIN)
db1db309
GM
5558 area = RIGHT_MARGIN_AREA;
5559 else
5560 abort ();
5561
5562 for (i = 0; row->enabled_p && i < w->current_matrix->nrows; ++i, ++row)
5563 if (wy >= row->y && wy < MATRIX_ROW_BOTTOM_Y (row))
5564 break;
6b61353c
KH
5565 y0 = *y - row->y;
5566 *y = row - MATRIX_FIRST_TEXT_ROW (w->current_matrix);
db1db309
GM
5567
5568 if (row->enabled_p)
5569 {
5570 /* Find the glyph under X. If we find one with a string object,
5571 it's the one we were looking for. */
db1db309 5572 if (area == RIGHT_MARGIN_AREA)
7df02016 5573 x0 = ((WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
6b61353c 5574 ? WINDOW_LEFT_FRINGE_WIDTH (w)
7df02016
KS
5575 : WINDOW_TOTAL_FRINGE_WIDTH (w))
5576 + window_box_width (w, LEFT_MARGIN_AREA)
5577 + window_box_width (w, TEXT_AREA));
db1db309 5578 else
7df02016 5579 x0 = (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
6b61353c 5580 ? WINDOW_LEFT_FRINGE_WIDTH (w)
7df02016
KS
5581 : 0);
5582
6b61353c
KH
5583 glyph = row->glyphs[area];
5584 end = glyph + row->used[area];
cfde341f 5585 for (x0 = *x - x0; glyph < end && x0 >= glyph->pixel_width; ++glyph)
6b61353c
KH
5586 x0 -= glyph->pixel_width;
5587 *x = glyph - row->glyphs[area];
5588 if (glyph < end)
5589 {
5590 string = glyph->object;
5591 *charpos = glyph->charpos;
5592 *width = glyph->pixel_width;
5593 *height = glyph->ascent + glyph->descent;
5594#ifdef HAVE_WINDOW_SYSTEM
5595 if (glyph->type == IMAGE_GLYPH)
5596 {
5597 struct image *img;
5598 img = IMAGE_FROM_ID (WINDOW_XFRAME (w), glyph->u.img_id);
5599 if (img != NULL)
5600 *object = img->spec;
5601 y0 -= row->ascent - glyph->ascent;
4be9765d
KH
5602 x0 += glyph->slice.img.x;
5603 y0 += glyph->slice.img.y;
6b61353c
KH
5604 }
5605#endif
5606 }
5607 else
5608 {
5609 /* Add extra (default width) columns if clicked after EOL. */
5610 *x += x0 / WINDOW_FRAME_COLUMN_WIDTH (w);
5611 *width = 0;
5612 *height = row->height;
5613 }
db1db309 5614 }
6b61353c
KH
5615 else
5616 {
5617 x0 = 0;
5618 *x = 0;
5619 *width = *height = 0;
5620 }
5621
5622 *dx = x0;
5623 *dy = y0;
db1db309
GM
5624
5625 return string;
5626}
5627
5628
5f5c8ee5
GM
5629/***********************************************************************
5630 Changing Frame Sizes
5631 ***********************************************************************/
4588ec20
JB
5632
5633#ifdef SIGWINCH
5f5c8ee5 5634
9af30bdf 5635static void
971de7fb
DN
5636window_change_signal (int signalnum) /* If we don't have an argument, */
5637 /* some compilers complain in signal calls. */
4588ec20
JB
5638{
5639 int width, height;
4588ec20
JB
5640 int old_errno = errno;
5641
28d7d09f 5642 struct tty_display_info *tty;
4d553a13 5643
333f1b6f
JD
5644 signal (SIGWINCH, window_change_signal);
5645 SIGNAL_THREAD_CHECK (signalnum);
5646
9628b887
KL
5647 /* The frame size change obviously applies to a single
5648 termcap-controlled terminal, but we can't decide which.
5649 Therefore, we resize the frames corresponding to each tty.
9628b887
KL
5650 */
5651 for (tty = tty_list; tty; tty = tty->next) {
4588ec20 5652
0a125897
KL
5653 if (! tty->term_initted)
5654 continue;
4588ec20 5655
db878925
DN
5656 /* Suspended tty frames have tty->input == NULL avoid trying to
5657 use it. */
5658 if (!tty->input)
5659 continue;
5660
0b0d3e0b 5661 get_tty_size (fileno (tty->input), &width, &height);
3fc809e2 5662
bedeffcf 5663 if (width > 5 && height > 2) {
9628b887 5664 Lisp_Object tail, frame;
3fc809e2 5665
9628b887 5666 FOR_EACH_FRAME (tail, frame)
4d553a13
KL
5667 if (FRAME_TERMCAP_P (XFRAME (frame)) && FRAME_TTY (XFRAME (frame)) == tty)
5668 /* Record the new sizes, but don't reallocate the data
5669 structures now. Let that be done later outside of the
5670 signal handler. */
5671 change_frame_size (XFRAME (frame), height, width, 0, 1, 0);
9628b887 5672 }
4588ec20 5673 }
3fc809e2 5674
4588ec20
JB
5675 errno = old_errno;
5676}
5677#endif /* SIGWINCH */
5678
5679
b96fd3e8
GM
5680/* Do any change in frame size that was requested by a signal. SAFE
5681 non-zero means this function is called from a place where it is
5682 safe to change frame sizes while a redisplay is in progress. */
4588ec20 5683
dfcf069d 5684void
971de7fb 5685do_pending_window_change (int safe)
4588ec20
JB
5686{
5687 /* If window_change_signal should have run before, run it now. */
b96fd3e8
GM
5688 if (redisplaying_p && !safe)
5689 return;
177c0ea7 5690
4588ec20
JB
5691 while (delayed_size_change)
5692 {
35f56f96 5693 Lisp_Object tail, frame;
4588ec20
JB
5694
5695 delayed_size_change = 0;
5696
35f56f96 5697 FOR_EACH_FRAME (tail, frame)
4588ec20 5698 {
5f5c8ee5 5699 struct frame *f = XFRAME (frame);
35f56f96 5700
7df02016
KS
5701 if (f->new_text_lines != 0 || f->new_text_cols != 0)
5702 change_frame_size (f, f->new_text_lines, f->new_text_cols,
5703 0, 0, safe);
4588ec20
JB
5704 }
5705 }
5706}
5707
5708
502b9b64 5709/* Change the frame height and/or width. Values may be given as zero to
177c0ea7 5710 indicate no change is to take place.
4588ec20 5711
b6a65ac2
JB
5712 If DELAY is non-zero, then assume we're being called from a signal
5713 handler, and queue the change for later - perhaps the next
5714 redisplay. Since this tries to resize windows, we can't call it
b96fd3e8
GM
5715 from a signal handler.
5716
5717 SAFE non-zero means this function is called from a place where it's
5718 safe to change frame sizes while a redisplay is in progress. */
b6a65ac2 5719
dfcf069d 5720void
971de7fb 5721change_frame_size (register struct frame *f, int newheight, int newwidth, int pretend, int delay, int safe)
45140e01
RS
5722{
5723 Lisp_Object tail, frame;
3826ea1a 5724
9628b887 5725 if (FRAME_MSDOS_P (f))
45140e01 5726 {
9628b887
KL
5727 /* On MS-DOS, all frames use the same screen, so a change in
5728 size affects all frames. Termcap now supports multiple
5729 ttys. */
45140e01 5730 FOR_EACH_FRAME (tail, frame)
8a376b3b 5731 if (! FRAME_WINDOW_P (XFRAME (frame)))
45140e01 5732 change_frame_size_1 (XFRAME (frame), newheight, newwidth,
b96fd3e8 5733 pretend, delay, safe);
45140e01
RS
5734 }
5735 else
b96fd3e8 5736 change_frame_size_1 (f, newheight, newwidth, pretend, delay, safe);
45140e01
RS
5737}
5738
5739static void
971de7fb 5740change_frame_size_1 (register struct frame *f, int newheight, int newwidth, int pretend, int delay, int safe)
4588ec20 5741{
7df02016 5742 int new_frame_total_cols;
aed13378 5743 int count = SPECPDL_INDEX ();
3826ea1a 5744
4588ec20 5745 /* If we can't deal with the change now, queue it for later. */
b96fd3e8 5746 if (delay || (redisplaying_p && !safe))
4588ec20 5747 {
7df02016
KS
5748 f->new_text_lines = newheight;
5749 f->new_text_cols = newwidth;
4588ec20
JB
5750 delayed_size_change = 1;
5751 return;
5752 }
5753
502b9b64 5754 /* This size-change overrides any pending one for this frame. */
7df02016
KS
5755 f->new_text_lines = 0;
5756 f->new_text_cols = 0;
b6a65ac2 5757
08f7aa3e 5758 /* If an argument is zero, set it to the current value. */
ae19c6f2 5759 if (newheight == 0)
7df02016 5760 newheight = FRAME_LINES (f);
ae19c6f2 5761 if (newwidth == 0)
7df02016 5762 newwidth = FRAME_COLS (f);
3826ea1a 5763
5f5c8ee5
GM
5764 /* Compute width of windows in F.
5765 This is the width of the frame without vertical scroll bars. */
7df02016 5766 new_frame_total_cols = FRAME_TOTAL_COLS_ARG (f, newwidth);
3826ea1a 5767
b6a65ac2 5768 /* Round up to the smallest acceptable size. */
5f5c8ee5 5769 check_frame_size (f, &newheight, &newwidth);
b6a65ac2
JB
5770
5771 /* If we're not changing the frame size, quit now. */
5075d853
JD
5772 /* Frame width may be unchanged but the text portion may change, for example,
5773 fullscreen and remove/add scroll bar. */
7df02016 5774 if (newheight == FRAME_LINES (f)
5075d853
JD
5775 && newwidth == FRAME_COLS (f) // text portion unchanged
5776 && new_frame_total_cols == FRAME_TOTAL_COLS (f)) // frame width unchanged
4588ec20
JB
5777 return;
5778
cbb95688
RS
5779 BLOCK_INPUT;
5780
886a8a6c
KH
5781#ifdef MSDOS
5782 /* We only can set screen dimensions to certain values supported
5783 by our video hardware. Try to find the smallest size greater
5784 or equal to the requested dimensions. */
5785 dos_set_window_size (&newheight, &newwidth);
5786#endif
5787
7df02016 5788 if (newheight != FRAME_LINES (f))
4588ec20 5789 {
562dd5e9 5790 resize_frame_windows (f, newheight, 0);
b6a65ac2 5791
48e482e6
EZ
5792 /* MSDOS frames cannot PRETEND, as they change frame size by
5793 manipulating video hardware. */
5794 if ((FRAME_TERMCAP_P (f) && !pretend) || FRAME_MSDOS_P (f))
6548cf00 5795 FrameRows (FRAME_TTY (f)) = newheight;
4588ec20
JB
5796 }
5797
7df02016 5798 if (new_frame_total_cols != FRAME_TOTAL_COLS (f))
4588ec20 5799 {
562dd5e9 5800 resize_frame_windows (f, new_frame_total_cols, 1);
4588ec20 5801
48e482e6
EZ
5802 /* MSDOS frames cannot PRETEND, as they change frame size by
5803 manipulating video hardware. */
5804 if ((FRAME_TERMCAP_P (f) && !pretend) || FRAME_MSDOS_P (f))
6548cf00 5805 FrameCols (FRAME_TTY (f)) = newwidth;
5f5c8ee5 5806
9ea173e8 5807 if (WINDOWP (f->tool_bar_window))
7df02016 5808 XSETFASTINT (XWINDOW (f->tool_bar_window)->total_cols, newwidth);
4588ec20
JB
5809 }
5810
7df02016
KS
5811 FRAME_LINES (f) = newheight;
5812 SET_FRAME_COLS (f, newwidth);
986e61b8 5813
5f5c8ee5
GM
5814 {
5815 struct window *w = XWINDOW (FRAME_SELECTED_WINDOW (f));
5816 int text_area_x, text_area_y, text_area_width, text_area_height;
177c0ea7 5817
5f5c8ee5
GM
5818 window_box (w, TEXT_AREA, &text_area_x, &text_area_y, &text_area_width,
5819 &text_area_height);
5820 if (w->cursor.x >= text_area_x + text_area_width)
5821 w->cursor.hpos = w->cursor.x = 0;
5822 if (w->cursor.y >= text_area_y + text_area_height)
5823 w->cursor.vpos = w->cursor.y = 0;
5824 }
986e61b8 5825
5f5c8ee5 5826 adjust_glyphs (f);
5f5c8ee5 5827 calculate_costs (f);
cb02fa39
GM
5828 SET_FRAME_GARBAGED (f);
5829 f->resized_p = 1;
97cf50e7
RS
5830
5831 UNBLOCK_INPUT;
61730a69 5832
e523f7e5
RS
5833 record_unwind_protect (Fset_buffer, Fcurrent_buffer ());
5834
ef264c42 5835 run_window_configuration_change_hook (f);
e523f7e5
RS
5836
5837 unbind_to (count, Qnil);
4588ec20 5838}
5f5c8ee5
GM
5839
5840
4588ec20 5841\f
5f5c8ee5
GM
5842/***********************************************************************
5843 Terminal Related Lisp Functions
5844 ***********************************************************************/
5845
5846DEFUN ("open-termscript", Fopen_termscript, Sopen_termscript,
228299fa 5847 1, 1, "FOpen termscript file: ",
7ee72033
MB
5848 doc: /* Start writing all terminal output to FILE as well as the terminal.
5849FILE = nil means just close any termscript file currently open. */)
5842a27b 5850 (Lisp_Object file)
5f5c8ee5 5851{
0b0d3e0b
KL
5852 struct tty_display_info *tty;
5853
7d2f1216
EZ
5854 if (! FRAME_TERMCAP_P (SELECTED_FRAME ())
5855 && ! FRAME_MSDOS_P (SELECTED_FRAME ()))
0b0d3e0b
KL
5856 error ("Current frame is not on a tty device");
5857
5858 tty = CURTTY ();
5859
5860 if (tty->termscript != 0)
e18c7093
KL
5861 {
5862 BLOCK_INPUT;
0b0d3e0b 5863 fclose (tty->termscript);
e18c7093
KL
5864 UNBLOCK_INPUT;
5865 }
0b0d3e0b 5866 tty->termscript = 0;
5f5c8ee5
GM
5867
5868 if (! NILP (file))
5869 {
5870 file = Fexpand_file_name (file, Qnil);
42a5b22f 5871 tty->termscript = fopen (SSDATA (file), "w");
0b0d3e0b 5872 if (tty->termscript == 0)
5f5c8ee5
GM
5873 report_file_error ("Opening termscript", Fcons (file, Qnil));
5874 }
5875 return Qnil;
5876}
5877
5878
4588ec20 5879DEFUN ("send-string-to-terminal", Fsend_string_to_terminal,
62af879c 5880 Ssend_string_to_terminal, 1, 2, 0,
7ee72033 5881 doc: /* Send STRING to the terminal without alteration.
62af879c
KL
5882Control characters in STRING will have terminal-dependent effects.
5883
6ed8eeff 5884Optional parameter TERMINAL specifies the tty terminal device to use.
558759e4
AM
5885It may be a terminal object, a frame, or nil for the terminal used by
5886the currently selected frame. In batch mode, STRING is sent to stdout
5887when TERMINAL is nil. */)
5842a27b 5888 (Lisp_Object string, Lisp_Object terminal)
4588ec20 5889{
7cef7ce3
SM
5890 struct terminal *t = get_terminal (terminal, 1);
5891 FILE *out;
0b0d3e0b 5892
94f3db62 5893 /* ??? Perhaps we should do something special for multibyte strings here. */
b7826503 5894 CHECK_STRING (string);
2c1e4409 5895 BLOCK_INPUT;
0b0d3e0b 5896
6ed8eeff
KL
5897 if (!t)
5898 error ("Unknown terminal device");
0b0d3e0b 5899
7cef7ce3
SM
5900 if (t->type == output_initial)
5901 out = stdout;
5902 else if (t->type != output_termcap && t->type != output_msdos_raw)
5903 error ("Device %d is not a termcap terminal device", t->id);
5904 else
5905 {
5906 struct tty_display_info *tty = t->display_info.tty;
3fc809e2 5907
7cef7ce3
SM
5908 if (! tty->output)
5909 error ("Terminal is currently suspended");
cecfdea6 5910
7cef7ce3
SM
5911 if (tty->termscript)
5912 {
5913 fwrite (SDATA (string), 1, SBYTES (string), tty->termscript);
5914 fflush (tty->termscript);
5915 }
5916 out = tty->output;
4588ec20 5917 }
7cef7ce3
SM
5918 fwrite (SDATA (string), 1, SBYTES (string), out);
5919 fflush (out);
2c1e4409 5920 UNBLOCK_INPUT;
4588ec20
JB
5921 return Qnil;
5922}
5923
5f5c8ee5 5924
a7ca3326 5925DEFUN ("ding", Fding, Sding, 0, 1, 0,
7ee72033 5926 doc: /* Beep, or flash the screen.
228299fa 5927Also, unless an argument is given,
7ee72033 5928terminate any keyboard macro currently executing. */)
5842a27b 5929 (Lisp_Object arg)
4588ec20 5930{
efb859b4 5931 if (!NILP (arg))
4588ec20 5932 {
7fa788da
RS
5933 if (noninteractive)
5934 putchar (07);
5935 else
385ed61f 5936 ring_bell (XFRAME (selected_frame));
4588ec20
JB
5937 }
5938 else
5939 bitch_at_user ();
5940
5941 return Qnil;
5942}
5943
dfcf069d 5944void
971de7fb 5945bitch_at_user (void)
4588ec20
JB
5946{
5947 if (noninteractive)
5948 putchar (07);
5f5c8ee5 5949 else if (!INTERACTIVE) /* Stop executing a keyboard macro. */
4588ec20
JB
5950 error ("Keyboard macro terminated by a command ringing the bell");
5951 else
385ed61f 5952 ring_bell (XFRAME (selected_frame));
4588ec20
JB
5953}
5954
5f5c8ee5
GM
5955
5956\f
5957/***********************************************************************
5958 Sleeping, Waiting
5959 ***********************************************************************/
5960
a7ca3326 5961DEFUN ("sleep-for", Fsleep_for, Ssleep_for, 1, 2, 0,
7ee72033 5962 doc: /* Pause, without updating display, for SECONDS seconds.
228299fa
GM
5963SECONDS may be a floating-point value, meaning that you can wait for a
5964fraction of a second. Optional second arg MILLISECONDS specifies an
5965additional wait period, in milliseconds; this may be useful if your
5966Emacs was built without floating point support.
7ee72033 5967\(Not all operating systems support waiting for a fraction of a second.) */)
5842a27b 5968 (Lisp_Object seconds, Lisp_Object milliseconds)
4588ec20 5969{
767229f8 5970 int sec, usec;
4588ec20 5971
767229f8 5972 if (NILP (milliseconds))
e9c9a718 5973 XSETINT (milliseconds, 0);
767229f8 5974 else
b7826503 5975 CHECK_NUMBER (milliseconds);
b07646f5
JB
5976 usec = XINT (milliseconds) * 1000;
5977
b07646f5
JB
5978 {
5979 double duration = extract_float (seconds);
5980 sec = (int) duration;
5981 usec += (duration - sec) * 1000000;
5982 }
4588ec20 5983
a41f8bed 5984#ifndef EMACS_HAS_USECS
767229f8 5985 if (sec == 0 && usec != 0)
861e19b9 5986 error ("Millisecond `sleep-for' not supported on %s", SYSTEM_TYPE);
4588ec20 5987#endif
767229f8
JB
5988
5989 /* Assure that 0 <= usec < 1000000. */
5990 if (usec < 0)
5991 {
153a073c 5992 /* We can't rely on the rounding being correct if usec is negative. */
767229f8
JB
5993 if (-1000000 < usec)
5994 sec--, usec += 1000000;
5995 else
5996 sec -= -usec / 1000000, usec = 1000000 - (-usec % 1000000);
4588ec20 5997 }
767229f8
JB
5998 else
5999 sec += usec / 1000000, usec %= 1000000;
6000
6b5153b1 6001 if (sec < 0 || (sec == 0 && usec == 0))
767229f8 6002 return Qnil;
4588ec20 6003
dcd1ca45 6004 wait_reading_process_output (sec, usec, 0, 0, Qnil, NULL, 0);
4588ec20
JB
6005
6006 return Qnil;
6007}
6008
5f5c8ee5 6009
dcd1ca45 6010/* This is just like wait_reading_process_output, except that
902b9b6d 6011 it does redisplay.
f76475ad 6012
2bcac766
CY
6013 TIMEOUT is number of seconds to wait (float or integer),
6014 or t to wait forever.
902b9b6d
KS
6015 READING is 1 if reading input.
6016 If DO_DISPLAY is >0 display process output while waiting.
6017 If DO_DISPLAY is >1 perform an initial redisplay before waiting.
6018*/
4588ec20 6019
f76475ad 6020Lisp_Object
971de7fb 6021sit_for (Lisp_Object timeout, int reading, int do_display)
f76475ad 6022{
902b9b6d 6023 int sec, usec;
f222369e 6024
902b9b6d 6025 swallow_events (do_display);
ccddf474 6026
902b9b6d 6027 if ((detect_input_pending_run_timers (do_display))
29bcbe54 6028 || !NILP (Vexecuting_kbd_macro))
4588ec20 6029 return Qnil;
4588ec20 6030
902b9b6d
KS
6031 if (do_display >= 2)
6032 redisplay_preserve_echo_area (2);
6033
8e09f23f 6034 if (INTEGERP (timeout))
f222369e 6035 {
7ff14773 6036 sec = XINT (timeout);
8e09f23f 6037 usec = 0;
f222369e 6038 }
8e09f23f
KS
6039 else if (FLOATP (timeout))
6040 {
99a20368 6041 double seconds = XFLOAT_DATA (timeout);
902b9b6d
KS
6042 sec = (int) seconds;
6043 usec = (int) ((seconds - sec) * 1000000);
6044 }
2bcac766
CY
6045 else if (EQ (timeout, Qt))
6046 {
6047 sec = 0;
6048 usec = 0;
6049 }
902b9b6d 6050 else
8e09f23f 6051 wrong_type_argument (Qnumberp, timeout);
4588ec20 6052
2bcac766 6053 if (sec == 0 && usec == 0 && !EQ (timeout, Qt))
dfdb645c
JB
6054 return Qt;
6055
4588ec20 6056#ifdef SIGIO
8fc798e9 6057 gobble_input (0);
f76475ad
JB
6058#endif
6059
902b9b6d 6060 wait_reading_process_output (sec, usec, reading ? -1 : 1, do_display,
dcd1ca45 6061 Qnil, NULL, 0);
f76475ad 6062
4588ec20
JB
6063 return detect_input_pending () ? Qnil : Qt;
6064}
6065
5f5c8ee5 6066
a7ca3326 6067DEFUN ("redisplay", Fredisplay, Sredisplay, 0, 1, 0,
01327edf 6068 doc: /* Perform redisplay if no input is available.
a5c2c707 6069If optional arg FORCE is non-nil or `redisplay-dont-pause' is non-nil,
03240971
KS
6070perform a full redisplay even if input is available.
6071Return t if redisplay was performed, nil otherwise. */)
5842a27b 6072 (Lisp_Object force)
f76475ad 6073{
01327edf 6074 int count;
659d9874 6075
902b9b6d
KS
6076 swallow_events (1);
6077 if ((detect_input_pending_run_timers (1)
01327edf 6078 && NILP (force) && !redisplay_dont_pause)
7ba07a1a
CY
6079 || !NILP (Vexecuting_kbd_macro))
6080 return Qnil;
f76475ad 6081
01327edf
KS
6082 count = SPECPDL_INDEX ();
6083 if (!NILP (force) && !redisplay_dont_pause)
6084 specbind (Qredisplay_dont_pause, Qt);
7ba07a1a 6085 redisplay_preserve_echo_area (2);
01327edf 6086 unbind_to (count, Qnil);
7ba07a1a 6087 return Qt;
f76475ad 6088}
5f5c8ee5
GM
6089
6090
6091\f
6092/***********************************************************************
6093 Other Lisp Functions
6094 ***********************************************************************/
6095
6096/* A vector of size >= 2 * NFRAMES + 3 * NBUFFERS + 1, containing the
6097 session's frames, frame names, buffers, buffer-read-only flags, and
44edd521 6098 buffer-modified-flags. */
5f5c8ee5
GM
6099
6100static Lisp_Object frame_and_buffer_state;
6101
6102
6103DEFUN ("frame-or-buffer-changed-p", Fframe_or_buffer_changed_p,
44edd521 6104 Sframe_or_buffer_changed_p, 0, 1, 0,
bacf09b4 6105 doc: /* Return non-nil if the frame and buffer state appears to have changed.
44edd521
RS
6106VARIABLE is a variable name whose value is either nil or a state vector
6107that will be updated to contain all frames and buffers,
228299fa 6108aside from buffers whose names start with space,
44edd521
RS
6109along with the buffers' read-only and modified flags. This allows a fast
6110check to see whether buffer menus might need to be recomputed.
228299fa 6111If this function returns non-nil, it updates the internal vector to reflect
44edd521
RS
6112the current state.
6113
6114If VARIABLE is nil, an internal variable is used. Users should not
6115pass nil for VARIABLE. */)
5842a27b 6116 (Lisp_Object variable)
5f5c8ee5 6117{
44edd521
RS
6118 Lisp_Object state, tail, frame, buf;
6119 Lisp_Object *vecp, *end;
5f5c8ee5
GM
6120 int n;
6121
44edd521
RS
6122 if (! NILP (variable))
6123 {
6124 CHECK_SYMBOL (variable);
6125 state = Fsymbol_value (variable);
6126 if (! VECTORP (state))
6127 goto changed;
6128 }
6129 else
6130 state = frame_and_buffer_state;
6131
6132 vecp = XVECTOR (state)->contents;
77b37c05 6133 end = vecp + ASIZE (state);
44edd521 6134
5f5c8ee5
GM
6135 FOR_EACH_FRAME (tail, frame)
6136 {
44edd521
RS
6137 if (vecp == end)
6138 goto changed;
5f5c8ee5
GM
6139 if (!EQ (*vecp++, frame))
6140 goto changed;
44edd521
RS
6141 if (vecp == end)
6142 goto changed;
5f5c8ee5
GM
6143 if (!EQ (*vecp++, XFRAME (frame)->name))
6144 goto changed;
6145 }
44edd521 6146 /* Check that the buffer info matches. */
7539e11f 6147 for (tail = Vbuffer_alist; CONSP (tail); tail = XCDR (tail))
5f5c8ee5 6148 {
7539e11f 6149 buf = XCDR (XCAR (tail));
5f5c8ee5 6150 /* Ignore buffers that aren't included in buffer lists. */
4b4deea2 6151 if (SREF (BVAR (XBUFFER (buf), name), 0) == ' ')
5f5c8ee5 6152 continue;
44edd521
RS
6153 if (vecp == end)
6154 goto changed;
5f5c8ee5
GM
6155 if (!EQ (*vecp++, buf))
6156 goto changed;
44edd521
RS
6157 if (vecp == end)
6158 goto changed;
4b4deea2 6159 if (!EQ (*vecp++, BVAR (XBUFFER (buf), read_only)))
5f5c8ee5 6160 goto changed;
44edd521
RS
6161 if (vecp == end)
6162 goto changed;
5f5c8ee5
GM
6163 if (!EQ (*vecp++, Fbuffer_modified_p (buf)))
6164 goto changed;
6165 }
44edd521
RS
6166 if (vecp == end)
6167 goto changed;
5f5c8ee5
GM
6168 /* Detect deletion of a buffer at the end of the list. */
6169 if (EQ (*vecp, Qlambda))
6170 return Qnil;
44edd521
RS
6171
6172 /* Come here if we decide the data has changed. */
5f5c8ee5 6173 changed:
44edd521
RS
6174 /* Count the size we will need.
6175 Start with 1 so there is room for at least one lambda at the end. */
5f5c8ee5
GM
6176 n = 1;
6177 FOR_EACH_FRAME (tail, frame)
6178 n += 2;
7539e11f 6179 for (tail = Vbuffer_alist; CONSP (tail); tail = XCDR (tail))
5f5c8ee5 6180 n += 3;
44edd521
RS
6181 /* Reallocate the vector if data has grown to need it,
6182 or if it has shrunk a lot. */
6183 if (! VECTORP (state)
77b37c05
PE
6184 || n > ASIZE (state)
6185 || n + 20 < ASIZE (state) / 2)
5f5c8ee5 6186 /* Add 20 extra so we grow it less often. */
44edd521
RS
6187 {
6188 state = Fmake_vector (make_number (n + 20), Qlambda);
6189 if (! NILP (variable))
6190 Fset (variable, state);
6191 else
6192 frame_and_buffer_state = state;
6193 }
6194
6195 /* Record the new data in the (possibly reallocated) vector. */
6196 vecp = XVECTOR (state)->contents;
5f5c8ee5
GM
6197 FOR_EACH_FRAME (tail, frame)
6198 {
6199 *vecp++ = frame;
6200 *vecp++ = XFRAME (frame)->name;
6201 }
7539e11f 6202 for (tail = Vbuffer_alist; CONSP (tail); tail = XCDR (tail))
5f5c8ee5 6203 {
7539e11f 6204 buf = XCDR (XCAR (tail));
5f5c8ee5 6205 /* Ignore buffers that aren't included in buffer lists. */
4b4deea2 6206 if (SREF (BVAR (XBUFFER (buf), name), 0) == ' ')
5f5c8ee5
GM
6207 continue;
6208 *vecp++ = buf;
4b4deea2 6209 *vecp++ = BVAR (XBUFFER (buf), read_only);
5f5c8ee5
GM
6210 *vecp++ = Fbuffer_modified_p (buf);
6211 }
6212 /* Fill up the vector with lambdas (always at least one). */
6213 *vecp++ = Qlambda;
44edd521 6214 while (vecp - XVECTOR (state)->contents
77b37c05 6215 < ASIZE (state))
5f5c8ee5
GM
6216 *vecp++ = Qlambda;
6217 /* Make sure we didn't overflow the vector. */
44edd521 6218 if (vecp - XVECTOR (state)->contents
77b37c05 6219 > ASIZE (state))
5f5c8ee5
GM
6220 abort ();
6221 return Qt;
6222}
6223
6224
4588ec20 6225\f
5f5c8ee5
GM
6226/***********************************************************************
6227 Initialization
6228***********************************************************************/
6229
5f5c8ee5
GM
6230/* Initialization done when Emacs fork is started, before doing stty.
6231 Determine terminal type and set terminal_driver. Then invoke its
6232 decoding routine to set up variables in the terminal package. */
4588ec20 6233
dfcf069d 6234void
971de7fb 6235init_display (void)
4588ec20 6236{
28d440ab
KL
6237 char *terminal_type;
6238
5f5c8ee5
GM
6239 /* Construct the space glyph. */
6240 space_glyph.type = CHAR_GLYPH;
3fc809e2 6241 SET_CHAR_GLYPH (space_glyph, ' ', DEFAULT_FACE_ID, 0);
5f5c8ee5
GM
6242 space_glyph.charpos = -1;
6243
4588ec20
JB
6244 inverse_video = 0;
6245 cursor_in_echo_area = 0;
6246 terminal_type = (char *) 0;
6247
1315c181
JB
6248 /* Now is the time to initialize this; it's used by init_sys_modes
6249 during startup. */
2246281f 6250 Vinitial_window_system = Qnil;
4588ec20 6251
4181ad9c
KL
6252 /* SIGWINCH needs to be handled no matter what display we start
6253 with. Otherwise newly opened tty frames will not resize
6254 automatically. */
6255#ifdef SIGWINCH
6256#ifndef CANNOT_DUMP
6257 if (initialized)
6258#endif /* CANNOT_DUMP */
6259 signal (SIGWINCH, window_change_signal);
6260#endif /* SIGWINCH */
4588ec20 6261
d6ef42b9 6262 /* If running as a daemon, no need to initialize any frames/terminal. */
ff808935
DN
6263 if (IS_DAEMON)
6264 return;
d6ef42b9 6265
1315c181
JB
6266 /* If the user wants to use a window system, we shouldn't bother
6267 initializing the terminal. This is especially important when the
6268 terminal is so dumb that emacs gives up before and doesn't bother
6269 using the window system.
4588ec20 6270
36bbad1d
KH
6271 If the DISPLAY environment variable is set and nonempty,
6272 try to use X, and die with an error message if that doesn't work. */
4588ec20
JB
6273
6274#ifdef HAVE_X_WINDOWS
00d70d57 6275 if (! inhibit_window_system && ! display_arg)
d460af17 6276 {
36bbad1d 6277 char *display;
36bbad1d 6278 display = getenv ("DISPLAY");
36bbad1d 6279 display_arg = (display != 0 && *display != 0);
c1fc674b
AS
6280
6281 if (display_arg && !x_display_ok (display))
6282 {
6283 fprintf (stderr, "Display %s unavailable, simulating -nw\n",
6284 display);
6285 inhibit_window_system = 1;
6286 }
f040093a 6287 }
d460af17 6288
4fcc2638 6289 if (!inhibit_window_system && display_arg)
4588ec20 6290 {
111d9af3 6291 Vinitial_window_system = Qx;
4588ec20
JB
6292#ifdef HAVE_X11
6293 Vwindow_system_version = make_number (11);
039e5d71 6294#endif
8a2a6032 6295#if defined (GNU_LINUX) && defined (HAVE_LIBNCURSES)
039e5d71 6296 /* In some versions of ncurses,
6a428f77 6297 tputs crashes if we have not called tgetent.
039e5d71
KH
6298 So call tgetent. */
6299 { char b[2044]; tgetent (b, "xterm");}
4588ec20 6300#endif
5f5c8ee5 6301 adjust_frame_glyphs_initially ();
4588ec20
JB
6302 return;
6303 }
6304#endif /* HAVE_X_WINDOWS */
6305
fd2e066a 6306#ifdef HAVE_NTGUI
177c0ea7 6307 if (!inhibit_window_system)
fd2e066a 6308 {
111d9af3 6309 Vinitial_window_system = Qw32;
fd2e066a 6310 Vwindow_system_version = make_number (1);
5f5c8ee5 6311 adjust_frame_glyphs_initially ();
fd2e066a
GV
6312 return;
6313 }
6314#endif /* HAVE_NTGUI */
6315
edfda783
AR
6316#ifdef HAVE_NS
6317 if (!inhibit_window_system
6318#ifndef CANNOT_DUMP
6319 && initialized
6320#endif
6321 )
6322 {
111d9af3 6323 Vinitial_window_system = Qns;
5e617bc2 6324 Vwindow_system_version = make_number (10);
edfda783
AR
6325 adjust_frame_glyphs_initially ();
6326 return;
6327 }
6328#endif
6329
4588ec20
JB
6330 /* If no window system has been specified, try to use the terminal. */
6331 if (! isatty (0))
6332 {
1559a86d 6333 fatal ("standard input is not a tty");
4588ec20
JB
6334 exit (1);
6335 }
6336
6152361f
JR
6337#ifdef WINDOWSNT
6338 terminal_type = "w32console";
6339#else
153a073c 6340 /* Look at the TERM variable. */
4588ec20 6341 terminal_type = (char *) getenv ("TERM");
6152361f 6342#endif
4588ec20
JB
6343 if (!terminal_type)
6344 {
5d12ff0b 6345#ifdef HAVE_WINDOW_SYSTEM
b9e590fc
RS
6346 if (! inhibit_window_system)
6347 fprintf (stderr, "Please set the environment variable DISPLAY or TERM (see `tset').\n");
5d12ff0b
RS
6348 else
6349#endif /* HAVE_WINDOW_SYSTEM */
b9e590fc 6350 fprintf (stderr, "Please set the environment variable TERM; see `tset'.\n");
4588ec20
JB
6351 exit (1);
6352 }
6353
0a125897 6354 {
6ed8eeff 6355 struct terminal *t;
3224dac1
KL
6356 struct frame *f = XFRAME (selected_frame);
6357
6358 /* Open a display on the controlling tty. */
6ed8eeff 6359 t = init_tty (0, terminal_type, 1); /* Errors are fatal. */
3224dac1
KL
6360
6361 /* Convert the initial frame to use the new display. */
b04f5ad2 6362 if (f->output_method != output_initial)
3224dac1 6363 abort ();
6ed8eeff
KL
6364 f->output_method = t->type;
6365 f->terminal = t;
3224dac1 6366
6ed8eeff 6367 t->reference_count++;
7ac5dac9
EZ
6368#ifdef MSDOS
6369 f->output_data.tty->display_info = &the_only_display_info;
6370#else
6371 if (f->output_method == output_termcap)
6372 create_tty_output (f);
6373#endif
6ed8eeff 6374 t->display_info.tty->top_frame = selected_frame;
5b65d888 6375 change_frame_size (XFRAME (selected_frame),
6ed8eeff
KL
6376 FrameRows (t->display_info.tty),
6377 FrameCols (t->display_info.tty), 0, 0, 1);
3224dac1 6378
6ed8eeff
KL
6379 /* Delete the initial terminal. */
6380 if (--initial_terminal->reference_count == 0
6381 && initial_terminal->delete_terminal_hook)
6382 (*initial_terminal->delete_terminal_hook) (initial_terminal);
2666355c
KL
6383
6384 /* Update frame parameters to reflect the new type. */
6385 Fmodify_frame_parameters
6386 (selected_frame, Fcons (Fcons (Qtty_type,
6ed8eeff 6387 Ftty_type (selected_frame)), Qnil));
657ceaa0
EZ
6388 if (t->display_info.tty->name)
6389 Fmodify_frame_parameters (selected_frame,
6390 Fcons (Fcons (Qtty, build_string (t->display_info.tty->name)),
6391 Qnil));
6392 else
6393 Fmodify_frame_parameters (selected_frame, Fcons (Fcons (Qtty, Qnil),
6394 Qnil));
0a125897 6395 }
3fc809e2 6396
d86c299a 6397 {
91fb7e1b 6398 struct frame *sf = SELECTED_FRAME ();
7df02016
KS
6399 int width = FRAME_TOTAL_COLS (sf);
6400 int height = FRAME_LINES (sf);
d86c299a 6401
5f5c8ee5 6402 /* If these sizes are so big they cause overflow, just ignore the
dfd153ae
PE
6403 change. It's not clear what better we could do. The rest of
6404 the code assumes that (width + 2) * height * sizeof (struct glyph)
6405 does not overflow and does not exceed PTRDIFF_MAX or SIZE_MAX. */
e3c25c68
PE
6406 if (INT_ADD_RANGE_OVERFLOW (width, 2, INT_MIN, INT_MAX)
6407 || INT_MULTIPLY_RANGE_OVERFLOW (width + 2, height, INT_MIN, INT_MAX)
dfd153ae
PE
6408 || (min (PTRDIFF_MAX, SIZE_MAX) / sizeof (struct glyph)
6409 < (width + 2) * height))
1559a86d 6410 fatal ("screen size %dx%d too big", width, height);
d86c299a
RS
6411 }
6412
5f5c8ee5 6413 adjust_frame_glyphs_initially ();
91fb7e1b 6414 calculate_costs (XFRAME (selected_frame));
4588ec20 6415
5f5c8ee5
GM
6416 /* Set up faces of the initial terminal frame of a dumped Emacs. */
6417 if (initialized
6418 && !noninteractive
2246281f 6419 && NILP (Vinitial_window_system))
2d764c78
EZ
6420 {
6421 /* For the initial frame, we don't have any way of knowing what
6422 are the foreground and background colors of the terminal. */
5e617bc2 6423 struct frame *sf = SELECTED_FRAME ();
2d764c78 6424
f9d2fdc4
EZ
6425 FRAME_FOREGROUND_PIXEL (sf) = FACE_TTY_DEFAULT_FG_COLOR;
6426 FRAME_BACKGROUND_PIXEL (sf) = FACE_TTY_DEFAULT_BG_COLOR;
2d764c78
EZ
6427 call0 (intern ("tty-set-up-initial-frame-faces"));
6428 }
5f5c8ee5
GM
6429}
6430
6431
6432\f
6433/***********************************************************************
6434 Blinking cursor
6435 ***********************************************************************/
6436
c3f13540 6437DEFUN ("internal-show-cursor", Finternal_show_cursor,
5d7791b3 6438 Sinternal_show_cursor, 2, 2, 0,
7ee72033 6439 doc: /* Set the cursor-visibility flag of WINDOW to SHOW.
228299fa
GM
6440WINDOW nil means use the selected window. SHOW non-nil means
6441show a cursor in WINDOW in the next redisplay. SHOW nil means
7ee72033 6442don't show a cursor. */)
5842a27b 6443 (Lisp_Object window, Lisp_Object show)
5f5c8ee5 6444{
5f5c8ee5
GM
6445 /* Don't change cursor state while redisplaying. This could confuse
6446 output routines. */
6447 if (!redisplaying_p)
6448 {
6449 if (NILP (window))
6450 window = selected_window;
6451 else
b7826503 6452 CHECK_WINDOW (window);
177c0ea7 6453
5d7791b3 6454 XWINDOW (window)->cursor_off_p = NILP (show);
5f5c8ee5
GM
6455 }
6456
6457 return Qnil;
4588ec20 6458}
5f5c8ee5
GM
6459
6460
5d7791b3
GM
6461DEFUN ("internal-show-cursor-p", Finternal_show_cursor_p,
6462 Sinternal_show_cursor_p, 0, 1, 0,
bacf09b4 6463 doc: /* Value is non-nil if next redisplay will display a cursor in WINDOW.
7ee72033 6464WINDOW nil or omitted means report on the selected window. */)
5842a27b 6465 (Lisp_Object window)
5d7791b3
GM
6466{
6467 struct window *w;
177c0ea7 6468
5d7791b3
GM
6469 if (NILP (window))
6470 window = selected_window;
6471 else
b7826503 6472 CHECK_WINDOW (window);
177c0ea7 6473
5d7791b3 6474 w = XWINDOW (window);
177c0ea7 6475 return w->cursor_off_p ? Qnil : Qt;
5d7791b3
GM
6476}
6477
87478b52
SM
6478DEFUN ("last-nonminibuffer-frame", Flast_nonminibuf_frame,
6479 Slast_nonminibuf_frame, 0, 0, 0,
6480 doc: /* Value is last nonminibuffer frame. */)
5842a27b 6481 (void)
87478b52 6482{
4958ed94 6483 Lisp_Object frame = Qnil;
87478b52 6484
4958ed94
SM
6485 if (last_nonminibuf_frame)
6486 XSETFRAME (frame, last_nonminibuf_frame);
87478b52
SM
6487
6488 return frame;
6489}
4588ec20 6490\f
5f5c8ee5
GM
6491/***********************************************************************
6492 Initialization
6493 ***********************************************************************/
6494
dfcf069d 6495void
971de7fb 6496syms_of_display (void)
4588ec20 6497{
502b9b64 6498 defsubr (&Sredraw_frame);
4588ec20 6499 defsubr (&Sredraw_display);
078b3696 6500 defsubr (&Sframe_or_buffer_changed_p);
4588ec20
JB
6501 defsubr (&Sopen_termscript);
6502 defsubr (&Sding);
7ba07a1a 6503 defsubr (&Sredisplay);
4588ec20
JB
6504 defsubr (&Ssleep_for);
6505 defsubr (&Ssend_string_to_terminal);
c3f13540 6506 defsubr (&Sinternal_show_cursor);
5d7791b3 6507 defsubr (&Sinternal_show_cursor_p);
87478b52 6508 defsubr (&Slast_nonminibuf_frame);
4588ec20 6509
2d5912c1 6510#if GLYPH_DEBUG
9b0e97aa
GM
6511 defsubr (&Sdump_redisplay_history);
6512#endif
6513
d1dad759 6514 frame_and_buffer_state = Fmake_vector (make_number (20), Qlambda);
078b3696
KH
6515 staticpro (&frame_and_buffer_state);
6516
cd3520a4
JB
6517 DEFSYM (Qdisplay_table, "display-table");
6518 DEFSYM (Qredisplay_dont_pause, "redisplay-dont-pause");
9cda4f7c 6519
29208e82 6520 DEFVAR_INT ("baud-rate", baud_rate,
bacf09b4 6521 doc: /* *The output baud rate of the terminal.
228299fa
GM
6522On most systems, changing this value will affect the amount of padding
6523and the other strategic decisions made during redisplay. */);
177c0ea7 6524
29208e82 6525 DEFVAR_BOOL ("inverse-video", inverse_video,
bacf09b4 6526 doc: /* *Non-nil means invert the entire frame display.
228299fa 6527This means everything is in inverse video which otherwise would not be. */);
177c0ea7 6528
29208e82 6529 DEFVAR_BOOL ("visible-bell", visible_bell,
bacf09b4 6530 doc: /* *Non-nil means try to flash the frame to represent a bell.
552b1b01
EZ
6531
6532See also `ring-bell-function'. */);
177c0ea7 6533
29208e82 6534 DEFVAR_BOOL ("no-redraw-on-reenter", no_redraw_on_reenter,
bacf09b4 6535 doc: /* *Non-nil means no need to redraw entire frame after suspending.
228299fa
GM
6536A non-nil value is useful if the terminal can automatically preserve
6537Emacs's frame display when you reenter Emacs.
6538It is up to you to set this variable if your terminal can do that. */);
177c0ea7 6539
29208e82 6540 DEFVAR_LISP ("initial-window-system", Vinitial_window_system,
2246281f 6541 doc: /* Name of the window system that Emacs uses for the first frame.
89baa1df
EZ
6542The value is a symbol:
6543 nil for a termcap frame (a character-only terminal),
6544 'x' for an Emacs frame that is really an X window,
6545 'w32' for an Emacs frame that is a window on MS-Windows display,
6546 'ns' for an Emacs frame on a GNUstep or Macintosh Cocoa display,
6547 'pc' for a direct-write MS-DOS frame.
6548
6549Use of this variable as a boolean is deprecated. Instead,
6550use `display-graphic-p' or any of the other `display-*-p'
6551predicates which report frame's specific UI-related capabilities. */);
177c0ea7 6552
70b8d0a4
SM
6553 DEFVAR_KBOARD ("window-system", Vwindow_system,
6554 doc: /* Name of window system through which the selected frame is displayed.
89baa1df
EZ
6555The value is a symbol:
6556 nil for a termcap frame (a character-only terminal),
6557 'x' for an Emacs frame that is really an X window,
6558 'w32' for an Emacs frame that is a window on MS-Windows display,
6559 'ns' for an Emacs frame on a GNUstep or Macintosh Cocoa display,
6560 'pc' for a direct-write MS-DOS frame.
6561
6562Use of this variable as a boolean is deprecated. Instead,
6563use `display-graphic-p' or any of the other `display-*-p'
6564predicates which report frame's specific UI-related capabilities. */);
70b8d0a4 6565
29208e82 6566 DEFVAR_LISP ("window-system-version", Vwindow_system_version,
bacf09b4 6567 doc: /* The version number of the window system in use.
c22140f6 6568For X windows, this is 11. */);
177c0ea7 6569
29208e82 6570 DEFVAR_BOOL ("cursor-in-echo-area", cursor_in_echo_area,
bacf09b4 6571 doc: /* Non-nil means put cursor in minibuffer, at end of any message there. */);
177c0ea7 6572
29208e82 6573 DEFVAR_LISP ("glyph-table", Vglyph_table,
bacf09b4 6574 doc: /* Table defining how to output a glyph code to the frame.
228299fa
GM
6575If not nil, this is a vector indexed by glyph code to define the glyph.
6576Each element can be:
6577 integer: a glyph code which this glyph is an alias for.
6578 string: output this glyph using that string (not impl. in X windows).
6579 nil: this glyph mod 524288 is the code of a character to output,
6580 and this glyph / 524288 is the face number (see `face-id') to use
6581 while outputting it. */);
4588ec20
JB
6582 Vglyph_table = Qnil;
6583
29208e82 6584 DEFVAR_LISP ("standard-display-table", Vstandard_display_table,
bacf09b4 6585 doc: /* Display table to use for buffers that specify none.
228299fa 6586See `buffer-display-table' for more information. */);
4588ec20
JB
6587 Vstandard_display_table = Qnil;
6588
29208e82 6589 DEFVAR_BOOL ("redisplay-dont-pause", redisplay_dont_pause,
6bf7006f
EZ
6590 doc: /* *Non-nil means display update isn't paused when input is detected. */);
6591 redisplay_dont_pause = 1;
5f5c8ee5 6592
d012c62b 6593#if PERIODIC_PREEMPTION_CHECKING
29208e82 6594 DEFVAR_LISP ("redisplay-preemption-period", Vredisplay_preemption_period,
d012c62b
KS
6595 doc: /* *The period in seconds between checking for input during redisplay.
6596If input is detected, redisplay is pre-empted, and the input is processed.
6597If nil, never pre-empt redisplay. */);
6598 Vredisplay_preemption_period = make_float (0.10);
6599#endif
6600
4588ec20
JB
6601#ifdef CANNOT_DUMP
6602 if (noninteractive)
6603#endif
6604 {
2246281f 6605 Vinitial_window_system = Qnil;
4588ec20
JB
6606 Vwindow_system_version = Qnil;
6607 }
6608}