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