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