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