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