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