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