(Fget_char_property): Doc fix.
[bpt/emacs.git] / src / dispnew.c
CommitLineData
4588ec20 1/* Updating of data structures for redisplay.
60a8948a 2 Copyright (C) 1985, 86, 87, 88, 93, 94 Free Software Foundation, Inc.
4588ec20
JB
3
4This file is part of GNU Emacs.
5
6GNU Emacs is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
fa61c701 8the Free Software Foundation; either version 2, or (at your option)
4588ec20
JB
9any later version.
10
11GNU Emacs is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU Emacs; see the file COPYING. If not, write to
18the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
19
20
21#include <signal.h>
2396e3da 22#include <stdio.h>
4588ec20 23
18160b98 24#include <config.h>
4588ec20
JB
25#include <ctype.h>
26
47099d6f 27#include "lisp.h"
4588ec20
JB
28#include "termchar.h"
29#include "termopts.h"
3be08bea 30#include "termhooks.h"
4588ec20 31#include "cm.h"
4588ec20
JB
32#include "dispextern.h"
33#include "buffer.h"
502b9b64 34#include "frame.h"
4588ec20
JB
35#include "window.h"
36#include "commands.h"
37#include "disptab.h"
38#include "indent.h"
d169fe39 39#include "intervals.h"
4588ec20 40
648fa17d 41#include "systty.h"
a41f8bed
JB
42#include "systime.h"
43
4588ec20
JB
44#ifdef HAVE_X_WINDOWS
45#include "xterm.h"
46#endif /* HAVE_X_WINDOWS */
47
48#define max(a, b) ((a) > (b) ? (a) : (b))
49#define min(a, b) ((a) < (b) ? (a) : (b))
50
51#ifndef PENDING_OUTPUT_COUNT
52/* Get number of chars of output now in the buffer of a stdio stream.
53 This ought to be built in in stdio, but it isn't.
54 Some s- files override this because their stdio internals differ. */
e3271ae5
RM
55#ifdef __GNU_LIBRARY__
56#define PENDING_OUTPUT_COUNT(FILE) ((FILE)->__bufp - (FILE)->__buffer)
57#else
4588ec20
JB
58#define PENDING_OUTPUT_COUNT(FILE) ((FILE)->_ptr - (FILE)->_base)
59#endif
e3271ae5 60#endif
4588ec20 61
a41f8bed 62/* Nonzero upon entry to redisplay means do not assume anything about
502b9b64 63 current contents of actual terminal frame; clear and redraw it. */
4588ec20 64
502b9b64 65int frame_garbaged;
4588ec20
JB
66
67/* Nonzero means last display completed. Zero means it was preempted. */
68
69int display_completed;
70
71/* Lisp variable visible-bell; enables use of screen-flash
72 instead of audible bell. */
73
74int visible_bell;
75
502b9b64 76/* Invert the color of the whole frame, at a low level. */
4588ec20
JB
77
78int inverse_video;
79
80/* Line speed of the terminal. */
81
82int baud_rate;
83
84/* nil or a symbol naming the window system under which emacs is
85 running ('x is the only current possibility). */
86
87Lisp_Object Vwindow_system;
88
89/* Version number of X windows: 10, 11 or nil. */
90Lisp_Object Vwindow_system_version;
91
92/* Vector of glyph definitions. Indexed by glyph number,
93 the contents are a string which is how to output the glyph.
94
95 If Vglyph_table is nil, a glyph is output by using its low 8 bits
96 as a character code. */
97
98Lisp_Object Vglyph_table;
99
100/* Display table to use for vectors that don't specify their own. */
101
102Lisp_Object Vstandard_display_table;
103
104/* Nonzero means reading single-character input with prompt
1113d9db
JB
105 so put cursor on minibuffer after the prompt.
106 positive means at end of text in echo area;
107 negative means at beginning of line. */
4588ec20
JB
108int cursor_in_echo_area;
109\f
502b9b64
JB
110/* The currently selected frame.
111 In a single-frame version, this variable always remains 0. */
4588ec20 112
502b9b64 113FRAME_PTR selected_frame;
4588ec20 114
502b9b64
JB
115/* A frame which is not just a minibuffer, or 0 if there are no such
116 frames. This is usually the most recent such frame that was
117 selected. In a single-frame version, this variable always remains 0. */
118FRAME_PTR last_nonminibuf_frame;
e5d77022 119
502b9b64 120/* In a single-frame version, the information that would otherwise
190721ac
JB
121 exist inside frame objects lives in the following structure instead.
122
123 NOTE: the_only_frame is not checked for garbage collection; don't
eb8c3be9 124 store collectible objects in any of its fields!
190721ac
JB
125
126 You're not/The only frame in town/... */
4588ec20 127
502b9b64
JB
128#ifndef MULTI_FRAME
129struct frame the_only_frame;
e5d77022 130#endif
4588ec20
JB
131
132/* This is a vector, made larger whenever it isn't large enough,
502b9b64
JB
133 which is used inside `update_frame' to hold the old contents
134 of the FRAME_PHYS_LINES of the frame being updated. */
135struct frame_glyphs **ophys_lines;
4588ec20
JB
136/* Length of vector currently allocated. */
137int ophys_lines_length;
138
139FILE *termscript; /* Stdio stream being used for copy of all output. */
140
141struct cm Wcm; /* Structure for info on cursor positioning */
142
143extern short ospeed; /* Output speed (from sg_ospeed) */
144
4588ec20 145int delayed_size_change; /* 1 means SIGWINCH happened when not safe. */
4588ec20 146\f
502b9b64 147#ifdef MULTI_FRAME
4588ec20 148
502b9b64
JB
149DEFUN ("redraw-frame", Fredraw_frame, Sredraw_frame, 1, 1, 0,
150 "Clear frame FRAME and output again what is supposed to appear on it.")
151 (frame)
152 Lisp_Object frame;
4588ec20 153{
502b9b64 154 FRAME_PTR f;
4588ec20 155
502b9b64
JB
156 CHECK_LIVE_FRAME (frame, 0);
157 f = XFRAME (frame);
158 update_begin (f);
4588ec20 159 /* set_terminal_modes (); */
502b9b64 160 clear_frame ();
b6a65ac2 161 clear_frame_records (f);
502b9b64 162 update_end (f);
4588ec20 163 fflush (stdout);
4588ec20
JB
164 windows_or_buffers_changed++;
165 /* Mark all windows as INaccurate,
166 so that every window will have its redisplay done. */
502b9b64
JB
167 mark_window_display_accurate (FRAME_ROOT_WINDOW (f), 0);
168 f->garbaged = 0;
4588ec20
JB
169 return Qnil;
170}
171
502b9b64
JB
172redraw_frame (f)
173 FRAME_PTR f;
4588ec20 174{
502b9b64
JB
175 Lisp_Object frame;
176 XSET (frame, Lisp_Frame, f);
177 Fredraw_frame (frame);
4588ec20
JB
178}
179
35f56f96 180#else
4588ec20 181
d8039c5c 182DEFUN ("redraw-frame", Fredraw_frame, Sredraw_frame, 1, 1, 0,
35f56f96
JB
183 "Clear frame FRAME and output again what is supposed to appear on it.")
184 (frame)
185 Lisp_Object frame;
4588ec20
JB
186{
187 update_begin (0);
188 set_terminal_modes ();
502b9b64 189 clear_frame ();
4588ec20
JB
190 update_end (0);
191 fflush (stdout);
502b9b64 192 clear_frame_records (0);
4588ec20
JB
193 windows_or_buffers_changed++;
194 /* Mark all windows as INaccurate,
195 so that every window will have its redisplay done. */
b5c685f4 196 mark_window_display_accurate (FRAME_ROOT_WINDOW (0), 0);
4588ec20
JB
197 return Qnil;
198}
199
35f56f96
JB
200#endif
201
202DEFUN ("redraw-display", Fredraw_display, Sredraw_display, 0, 0, "",
203 "Clear and redisplay all visible frames.")
204 ()
205{
206 Lisp_Object tail, frame;
207
208 FOR_EACH_FRAME (tail, frame)
9223a96a 209 if (FRAME_VISIBLE_P (XFRAME (frame)))
35f56f96
JB
210 Fredraw_frame (frame);
211
212 return Qnil;
213}
214
9223a96a
RS
215/* This is used when frame_garbaged is set.
216 Redraw the individual frames marked as garbaged. */
217
218void
219redraw_garbaged_frames ()
220{
221 Lisp_Object tail, frame;
222
223 FOR_EACH_FRAME (tail, frame)
224 if (FRAME_VISIBLE_P (XFRAME (frame))
225 && FRAME_GARBAGED_P (XFRAME (frame)))
226 Fredraw_frame (frame);
227}
228
4588ec20 229\f
502b9b64
JB
230static struct frame_glyphs *
231make_frame_glyphs (frame, empty)
232 register FRAME_PTR frame;
4588ec20
JB
233 int empty;
234{
235 register int i;
502b9b64
JB
236 register width = FRAME_WIDTH (frame);
237 register height = FRAME_HEIGHT (frame);
60a8948a
RS
238 register struct frame_glyphs *new
239 = (struct frame_glyphs *) xmalloc (sizeof (struct frame_glyphs));
4588ec20 240
502b9b64 241 SET_GLYPHS_FRAME (new, frame);
4588ec20
JB
242 new->height = height;
243 new->width = width;
244 new->used = (int *) xmalloc (height * sizeof (int));
245 new->glyphs = (GLYPH **) xmalloc (height * sizeof (GLYPH *));
60a8948a 246 new->charstarts = (int **) xmalloc (height * sizeof (int *));
4588ec20
JB
247 new->highlight = (char *) xmalloc (height * sizeof (char));
248 new->enable = (char *) xmalloc (height * sizeof (char));
249 bzero (new->enable, height * sizeof (char));
250 new->bufp = (int *) xmalloc (height * sizeof (int));
251
252#ifdef HAVE_X_WINDOWS
b6a65ac2 253 if (FRAME_X_P (frame))
4588ec20 254 {
4588ec20
JB
255 new->top_left_x = (short *) xmalloc (height * sizeof (short));
256 new->top_left_y = (short *) xmalloc (height * sizeof (short));
257 new->pix_width = (short *) xmalloc (height * sizeof (short));
258 new->pix_height = (short *) xmalloc (height * sizeof (short));
448fd7c0 259 new->max_ascent = (short *) xmalloc (height * sizeof (short));
4588ec20
JB
260 }
261#endif
262
263 if (empty)
264 {
265 /* Make the buffer used by decode_mode_spec. This buffer is also
502b9b64 266 used as temporary storage when updating the frame. See scroll.c. */
4588ec20 267 unsigned int total_glyphs = (width + 2) * sizeof (GLYPH);
d52bad65 268 unsigned int total_charstarts = (width + 2) * sizeof (int);
4588ec20
JB
269
270 new->total_contents = (GLYPH *) xmalloc (total_glyphs);
271 bzero (new->total_contents, total_glyphs);
d52bad65
RS
272
273 new->total_charstarts = (int *) xmalloc (total_charstarts);
274 bzero (new->total_charstarts, total_glyphs);
4588ec20
JB
275 }
276 else
277 {
278 unsigned int total_glyphs = height * (width + 2) * sizeof (GLYPH);
279
280 new->total_contents = (GLYPH *) xmalloc (total_glyphs);
281 bzero (new->total_contents, total_glyphs);
282 for (i = 0; i < height; i++)
283 new->glyphs[i] = new->total_contents + i * (width + 2) + 1;
60a8948a
RS
284
285 if (!FRAME_TERMCAP_P (frame))
286 {
287 unsigned int total_charstarts = height * (width + 2) * sizeof (int);
288
289 new->total_charstarts = (int *) xmalloc (total_charstarts);
290 bzero (new->total_charstarts, total_charstarts);
291 for (i = 0; i < height; i++)
292 new->charstarts[i] = new->total_charstarts + i * (width + 2) + 1;
293 }
294 else
295 {
296 /* Without a window system, we don't really need charstarts.
297 So use a small amount of space to make enough data structure
298 to prevent crashes in display_text_line. */
299 new->total_charstarts = (int *) xmalloc ((width + 2) * sizeof (int));
300 for (i = 0; i < height; i++)
301 new->charstarts[i] = new->total_charstarts;
302 }
4588ec20
JB
303 }
304
305 return new;
306}
307
308static void
502b9b64
JB
309free_frame_glyphs (frame, glyphs)
310 FRAME_PTR frame;
311 struct frame_glyphs *glyphs;
4588ec20
JB
312{
313 if (glyphs->total_contents)
9ac0d9e0 314 xfree (glyphs->total_contents);
60a8948a
RS
315 if (glyphs->total_charstarts)
316 xfree (glyphs->total_charstarts);
4588ec20 317
9ac0d9e0
JB
318 xfree (glyphs->used);
319 xfree (glyphs->glyphs);
320 xfree (glyphs->highlight);
321 xfree (glyphs->enable);
322 xfree (glyphs->bufp);
60a8948a
RS
323 if (glyphs->charstarts)
324 xfree (glyphs->charstarts);
4588ec20
JB
325
326#ifdef HAVE_X_WINDOWS
b6a65ac2 327 if (FRAME_X_P (frame))
4588ec20 328 {
9ac0d9e0
JB
329 xfree (glyphs->top_left_x);
330 xfree (glyphs->top_left_y);
331 xfree (glyphs->pix_width);
332 xfree (glyphs->pix_height);
333 xfree (glyphs->max_ascent);
4588ec20
JB
334 }
335#endif
336
9ac0d9e0 337 xfree (glyphs);
4588ec20
JB
338}
339
340static void
502b9b64
JB
341remake_frame_glyphs (frame)
342 FRAME_PTR frame;
4588ec20 343{
502b9b64
JB
344 if (FRAME_CURRENT_GLYPHS (frame))
345 free_frame_glyphs (frame, FRAME_CURRENT_GLYPHS (frame));
346 if (FRAME_DESIRED_GLYPHS (frame))
347 free_frame_glyphs (frame, FRAME_DESIRED_GLYPHS (frame));
348 if (FRAME_TEMP_GLYPHS (frame))
349 free_frame_glyphs (frame, FRAME_TEMP_GLYPHS (frame));
350
351 if (FRAME_MESSAGE_BUF (frame))
832a0726
JB
352 {
353 /* Reallocate the frame's message buffer; remember that
354 echo_area_glyphs may be pointing here. */
355 char *old_message_buf = FRAME_MESSAGE_BUF (frame);
356
357 FRAME_MESSAGE_BUF (frame)
358 = (char *) xrealloc (FRAME_MESSAGE_BUF (frame),
359 FRAME_WIDTH (frame) + 1);
360
361 if (echo_area_glyphs == old_message_buf)
362 echo_area_glyphs = FRAME_MESSAGE_BUF (frame);
363 if (previous_echo_glyphs == old_message_buf)
364 previous_echo_glyphs = FRAME_MESSAGE_BUF (frame);
365 }
4588ec20 366 else
502b9b64
JB
367 FRAME_MESSAGE_BUF (frame)
368 = (char *) xmalloc (FRAME_WIDTH (frame) + 1);
4588ec20 369
502b9b64
JB
370 FRAME_CURRENT_GLYPHS (frame) = make_frame_glyphs (frame, 0);
371 FRAME_DESIRED_GLYPHS (frame) = make_frame_glyphs (frame, 0);
372 FRAME_TEMP_GLYPHS (frame) = make_frame_glyphs (frame, 1);
373 SET_FRAME_GARBAGED (frame);
4588ec20
JB
374}
375\f
502b9b64 376/* Return the hash code of contents of line VPOS in frame-matrix M. */
4588ec20
JB
377
378static int
379line_hash_code (m, vpos)
502b9b64 380 register struct frame_glyphs *m;
4588ec20
JB
381 int vpos;
382{
383 register GLYPH *body, *end;
384 register int h = 0;
385
386 if (!m->enable[vpos])
387 return 0;
388
94aa5d2d 389 /* Give all highlighted lines the same hash code
4588ec20
JB
390 so as to encourage scrolling to leave them in place. */
391 if (m->highlight[vpos])
392 return -1;
393
394 body = m->glyphs[vpos];
395
396 if (must_write_spaces)
397 while (1)
398 {
399 GLYPH g = *body++;
400
401 if (g == 0)
402 break;
403 h = (((h << 4) + (h >> 24)) & 0x0fffffff) + g - SPACEGLYPH;
404 }
405 else
406 while (1)
407 {
408 GLYPH g = *body++;
409
410 if (g == 0)
411 break;
412 h = (((h << 4) + (h >> 24)) & 0x0fffffff) + g;
413 }
414
415 if (h)
416 return h;
417 return 1;
418}
419
420/* Return number of characters in line in M at vpos VPOS,
421 except don't count leading and trailing spaces
422 unless the terminal requires those to be explicitly output. */
423
424static unsigned int
425line_draw_cost (m, vpos)
502b9b64 426 struct frame_glyphs *m;
4588ec20
JB
427 int vpos;
428{
429 register GLYPH *beg = m->glyphs[vpos];
430 register GLYPH *end = m->glyphs[vpos] + m->used[vpos];
431 register int i;
432 register int tlen = GLYPH_TABLE_LENGTH;
433 register Lisp_Object *tbase = GLYPH_TABLE_BASE;
434
435 /* Ignore trailing and leading spaces if we can. */
436 if (!must_write_spaces)
437 {
438 while ((end != beg) && (*end == SPACEGLYPH))
439 --end;
440 if (end == beg)
441 return (0); /* All blank line. */
442
443 while (*beg == SPACEGLYPH)
444 ++beg;
445 }
446
447 /* If we don't have a glyph-table, each glyph is one character,
448 so return the number of glyphs. */
449 if (tbase == 0)
450 return end - beg;
451
452 /* Otherwise, scan the glyphs and accumulate their total size in I. */
453 i = 0;
454 while ((beg <= end) && *beg)
455 {
456 register GLYPH g = *beg++;
457
458 if (GLYPH_SIMPLE_P (tbase, tlen, g))
459 i += 1;
460 else
461 i += GLYPH_LENGTH (tbase, g);
462 }
463 return i;
464}
465\f
466/* The functions on this page are the interface from xdisp.c to redisplay.
467
468 The only other interface into redisplay is through setting
502b9b64
JB
469 FRAME_CURSOR_X (frame) and FRAME_CURSOR_Y (frame)
470 and SET_FRAME_GARBAGED (frame). */
4588ec20
JB
471
472/* cancel_line eliminates any request to display a line at position `vpos' */
473
502b9b64 474cancel_line (vpos, frame)
4588ec20 475 int vpos;
502b9b64 476 register FRAME_PTR frame;
4588ec20 477{
502b9b64 478 FRAME_DESIRED_GLYPHS (frame)->enable[vpos] = 0;
4588ec20
JB
479}
480
502b9b64
JB
481clear_frame_records (frame)
482 register FRAME_PTR frame;
4588ec20 483{
502b9b64 484 bzero (FRAME_CURRENT_GLYPHS (frame)->enable, FRAME_HEIGHT (frame));
4588ec20
JB
485}
486
487/* Prepare to display on line VPOS starting at HPOS within it. */
488
489void
502b9b64
JB
490get_display_line (frame, vpos, hpos)
491 register FRAME_PTR frame;
4588ec20
JB
492 int vpos;
493 register int hpos;
494{
502b9b64
JB
495 register struct frame_glyphs *glyphs;
496 register struct frame_glyphs *desired_glyphs = FRAME_DESIRED_GLYPHS (frame);
4588ec20
JB
497 register GLYPH *p;
498
7c3c72ec 499 if (vpos < 0)
4588ec20
JB
500 abort ();
501
502 if ((desired_glyphs->enable[vpos]) && desired_glyphs->used[vpos] > hpos)
503 abort ();
504
505 if (! desired_glyphs->enable[vpos])
506 {
507 desired_glyphs->used[vpos] = 0;
508 desired_glyphs->highlight[vpos] = 0;
509 desired_glyphs->enable[vpos] = 1;
510 }
511
512 if (hpos > desired_glyphs->used[vpos])
513 {
514 GLYPH *g = desired_glyphs->glyphs[vpos] + desired_glyphs->used[vpos];
515 GLYPH *end = desired_glyphs->glyphs[vpos] + hpos;
516
517 desired_glyphs->used[vpos] = hpos;
518 while (g != end)
519 *g++ = SPACEGLYPH;
520 }
521}
522
523/* Like bcopy except never gets confused by overlap. */
524
525void
526safe_bcopy (from, to, size)
527 char *from, *to;
528 int size;
529{
b5c685f4 530 if (size <= 0 || from == to)
4588ec20
JB
531 return;
532
b5c685f4
JB
533 /* If the source and destination don't overlap, then bcopy can
534 handle it. If they do overlap, but the destination is lower in
535 memory than the source, we'll assume bcopy can handle that. */
536 if (to < from || from + size <= to)
537 bcopy (from, to, size);
538
539 /* Otherwise, we'll copy from the end. */
540 else
4588ec20 541 {
b5c685f4
JB
542 register char *endf = from + size;
543 register char *endt = to + size;
4588ec20
JB
544
545 /* If TO - FROM is large, then we should break the copy into
546 nonoverlapping chunks of TO - FROM bytes each. However, if
547 TO - FROM is small, then the bcopy function call overhead
548 makes this not worth it. The crossover point could be about
b5c685f4
JB
549 anywhere. Since I don't think the obvious copy loop is too
550 bad, I'm trying to err in its favor. */
4588ec20
JB
551 if (to - from < 64)
552 {
553 do
554 *--endt = *--endf;
555 while (endf != from);
556 }
557 else
558 {
b5c685f4 559 for (;;)
4588ec20
JB
560 {
561 endt -= (to - from);
562 endf -= (to - from);
563
b5c685f4
JB
564 if (endt < to)
565 break;
566
4588ec20
JB
567 bcopy (endf, endt, to - from);
568 }
b5c685f4
JB
569
570 /* If SIZE wasn't a multiple of TO - FROM, there will be a
4588ec20
JB
571 little left over. The amount left over is
572 (endt + (to - from)) - to, which is endt - from. */
573 bcopy (from, to, endt - from);
574 }
575 }
4588ec20
JB
576}
577
98038dc0 578/* Rotate a vector of SIZE bytes right, by DISTANCE bytes.
4588ec20
JB
579 DISTANCE may be negative. */
580
581static void
582rotate_vector (vector, size, distance)
583 char *vector;
584 int size;
585 int distance;
586{
587 char *temp = (char *) alloca (size);
588
589 if (distance < 0)
590 distance += size;
591
592 bcopy (vector, temp + distance, size - distance);
593 bcopy (vector + size - distance, temp, distance);
594 bcopy (temp, vector, size);
595}
596
597/* Scroll lines from vpos FROM up to but not including vpos END
598 down by AMOUNT lines (AMOUNT may be negative).
599 Returns nonzero if done, zero if terminal cannot scroll them. */
600
601int
d52bad65 602scroll_frame_lines (frame, from, end, amount, newpos)
502b9b64 603 register FRAME_PTR frame;
d52bad65 604 int from, end, amount, newpos;
4588ec20
JB
605{
606 register int i;
502b9b64
JB
607 register struct frame_glyphs *current_frame
608 = FRAME_CURRENT_GLYPHS (frame);
d52bad65 609 int pos_adjust;
23b0200c 610 int width = FRAME_WIDTH (frame);
4588ec20
JB
611
612 if (!line_ins_del_ok)
613 return 0;
614
615 if (amount == 0)
616 return 1;
617
618 if (amount > 0)
619 {
502b9b64 620 update_begin (frame);
4588ec20
JB
621 set_terminal_window (end + amount);
622 if (!scroll_region_ok)
623 ins_del_lines (end, -amount);
624 ins_del_lines (from, amount);
625 set_terminal_window (0);
626
502b9b64 627 rotate_vector (current_frame->glyphs + from,
4588ec20
JB
628 sizeof (GLYPH *) * (end + amount - from),
629 amount * sizeof (GLYPH *));
630
60a8948a 631 rotate_vector (current_frame->charstarts + from,
d52bad65
RS
632 sizeof (int *) * (end + amount - from),
633 amount * sizeof (int *));
634
23b0200c
RS
635 safe_bcopy (current_frame->used + from,
636 current_frame->used + from + amount,
637 (end - from) * sizeof current_frame->used[0]);
638
639 safe_bcopy (current_frame->highlight + from,
640 current_frame->highlight + from + amount,
641 (end - from) * sizeof current_frame->highlight[0]);
642
643 safe_bcopy (current_frame->enable + from,
644 current_frame->enable + from + amount,
645 (end - from) * sizeof current_frame->enable[0]);
646
d52bad65
RS
647 /* Adjust the lines by an amount
648 that puts the first of them at NEWPOS. */
23b0200c 649 pos_adjust = newpos - current_frame->charstarts[from + amount][0];
60a8948a
RS
650
651 /* Offset each char position in the charstarts lines we moved
652 by pos_adjust. */
23b0200c 653 for (i = from + amount; i < end + amount; i++)
60a8948a 654 {
d52bad65 655 int *line = current_frame->charstarts[i];
60a8948a 656 int col;
23b0200c
RS
657 for (col = 0; col < width; col++)
658 if (line[col] > 0)
659 line[col] += pos_adjust;
60a8948a 660 }
23b0200c 661 for (i = from; i < from + amount; i++)
60a8948a 662 {
d52bad65 663 int *line = current_frame->charstarts[i];
60a8948a
RS
664 int col;
665 line[0] = -1;
23b0200c 666 for (col = 0; col < width; col++)
60a8948a
RS
667 line[col] = 0;
668 }
669
4588ec20
JB
670 /* Mark the lines made empty by scrolling as enabled, empty and
671 normal video. */
502b9b64
JB
672 bzero (current_frame->used + from,
673 amount * sizeof current_frame->used[0]);
674 bzero (current_frame->highlight + from,
675 amount * sizeof current_frame->highlight[0]);
4588ec20
JB
676 for (i = from; i < from + amount; i++)
677 {
502b9b64 678 current_frame->glyphs[i][0] = '\0';
60a8948a 679 current_frame->charstarts[i][0] = -1;
502b9b64 680 current_frame->enable[i] = 1;
4588ec20
JB
681 }
682
502b9b64
JB
683 safe_bcopy (current_frame->bufp + from,
684 current_frame->bufp + from + amount,
685 (end - from) * sizeof current_frame->bufp[0]);
4588ec20
JB
686
687#ifdef HAVE_X_WINDOWS
b6a65ac2 688 if (FRAME_X_P (frame))
4588ec20 689 {
502b9b64
JB
690 safe_bcopy (current_frame->top_left_x + from,
691 current_frame->top_left_x + from + amount,
692 (end - from) * sizeof current_frame->top_left_x[0]);
4588ec20 693
502b9b64
JB
694 safe_bcopy (current_frame->top_left_y + from,
695 current_frame->top_left_y + from + amount,
696 (end - from) * sizeof current_frame->top_left_y[0]);
4588ec20 697
502b9b64
JB
698 safe_bcopy (current_frame->pix_width + from,
699 current_frame->pix_width + from + amount,
700 (end - from) * sizeof current_frame->pix_width[0]);
4588ec20 701
502b9b64
JB
702 safe_bcopy (current_frame->pix_height + from,
703 current_frame->pix_height + from + amount,
704 (end - from) * sizeof current_frame->pix_height[0]);
448fd7c0
JA
705
706 safe_bcopy (current_frame->max_ascent + from,
707 current_frame->max_ascent + from + amount,
708 (end - from) * sizeof current_frame->max_ascent[0]);
4588ec20
JB
709 }
710#endif /* HAVE_X_WINDOWS */
711
502b9b64 712 update_end (frame);
4588ec20
JB
713 }
714 if (amount < 0)
715 {
502b9b64 716 update_begin (frame);
4588ec20
JB
717 set_terminal_window (end);
718 ins_del_lines (from + amount, amount);
719 if (!scroll_region_ok)
720 ins_del_lines (end + amount, -amount);
721 set_terminal_window (0);
722
502b9b64 723 rotate_vector (current_frame->glyphs + from + amount,
4588ec20
JB
724 sizeof (GLYPH *) * (end - from - amount),
725 amount * sizeof (GLYPH *));
726
60a8948a 727 rotate_vector (current_frame->charstarts + from + amount,
d52bad65
RS
728 sizeof (int *) * (end - from - amount),
729 amount * sizeof (int *));
730
23b0200c
RS
731 safe_bcopy (current_frame->used + from,
732 current_frame->used + from + amount,
733 (end - from) * sizeof current_frame->used[0]);
734
735 safe_bcopy (current_frame->highlight + from,
736 current_frame->highlight + from + amount,
737 (end - from) * sizeof current_frame->highlight[0]);
738
739 safe_bcopy (current_frame->enable + from,
740 current_frame->enable + from + amount,
741 (end - from) * sizeof current_frame->enable[0]);
742
d52bad65
RS
743 /* Adjust the lines by an amount
744 that puts the first of them at NEWPOS. */
23b0200c 745 pos_adjust = newpos - current_frame->charstarts[from + amount][0];
60a8948a
RS
746
747 /* Offset each char position in the charstarts lines we moved
748 by pos_adjust. */
749 for (i = from + amount; i < end + amount; i++)
750 {
d52bad65 751 int *line = current_frame->charstarts[i];
60a8948a 752 int col;
23b0200c
RS
753 for (col = 0; col < width; col++)
754 if (line[col] > 0)
755 line[col] += pos_adjust;
60a8948a 756 }
23b0200c 757 for (i = end + amount; i < end; i++)
60a8948a 758 {
d52bad65 759 int *line = current_frame->charstarts[i];
60a8948a
RS
760 int col;
761 line[0] = -1;
23b0200c 762 for (col = 0; col < width; col++)
60a8948a
RS
763 line[col] = 0;
764 }
765
4588ec20
JB
766 /* Mark the lines made empty by scrolling as enabled, empty and
767 normal video. */
502b9b64
JB
768 bzero (current_frame->used + end + amount,
769 - amount * sizeof current_frame->used[0]);
770 bzero (current_frame->highlight + end + amount,
771 - amount * sizeof current_frame->highlight[0]);
4588ec20
JB
772 for (i = end + amount; i < end; i++)
773 {
502b9b64 774 current_frame->glyphs[i][0] = '\0';
60a8948a 775 current_frame->charstarts[i][0] = 0;
502b9b64 776 current_frame->enable[i] = 1;
4588ec20
JB
777 }
778
502b9b64
JB
779 safe_bcopy (current_frame->bufp + from,
780 current_frame->bufp + from + amount,
781 (end - from) * sizeof current_frame->bufp[0]);
4588ec20
JB
782
783#ifdef HAVE_X_WINDOWS
b6a65ac2 784 if (FRAME_X_P (frame))
4588ec20 785 {
502b9b64
JB
786 safe_bcopy (current_frame->top_left_x + from,
787 current_frame->top_left_x + from + amount,
788 (end - from) * sizeof current_frame->top_left_x[0]);
4588ec20 789
502b9b64
JB
790 safe_bcopy (current_frame->top_left_y + from,
791 current_frame->top_left_y + from + amount,
792 (end - from) * sizeof current_frame->top_left_y[0]);
4588ec20 793
502b9b64
JB
794 safe_bcopy (current_frame->pix_width + from,
795 current_frame->pix_width + from + amount,
796 (end - from) * sizeof current_frame->pix_width[0]);
4588ec20 797
502b9b64
JB
798 safe_bcopy (current_frame->pix_height + from,
799 current_frame->pix_height + from + amount,
800 (end - from) * sizeof current_frame->pix_height[0]);
448fd7c0
JA
801
802 safe_bcopy (current_frame->max_ascent + from,
803 current_frame->max_ascent + from + amount,
804 (end - from) * sizeof current_frame->max_ascent[0]);
4588ec20
JB
805 }
806#endif /* HAVE_X_WINDOWS */
807
502b9b64 808 update_end (frame);
4588ec20
JB
809 }
810 return 1;
811}
812\f
502b9b64 813/* After updating a window W that isn't the full frame wide,
4588ec20 814 copy all the columns that W does not occupy
502b9b64
JB
815 into the FRAME_DESIRED_GLYPHS (frame) from the FRAME_PHYS_GLYPHS (frame)
816 so that update_frame will not change those columns. */
4588ec20
JB
817
818preserve_other_columns (w)
819 struct window *w;
820{
821 register int vpos;
502b9b64
JB
822 register struct frame_glyphs *current_frame, *desired_frame;
823 register FRAME_PTR frame = XFRAME (w->frame);
4588ec20
JB
824 int start = XFASTINT (w->left);
825 int end = XFASTINT (w->left) + XFASTINT (w->width);
826 int bot = XFASTINT (w->top) + XFASTINT (w->height);
827
502b9b64
JB
828 current_frame = FRAME_CURRENT_GLYPHS (frame);
829 desired_frame = FRAME_DESIRED_GLYPHS (frame);
4588ec20
JB
830
831 for (vpos = XFASTINT (w->top); vpos < bot; vpos++)
832 {
502b9b64 833 if (current_frame->enable[vpos] && desired_frame->enable[vpos])
4588ec20
JB
834 {
835 if (start > 0)
836 {
837 int len;
838
502b9b64 839 bcopy (current_frame->glyphs[vpos],
aec9f5f6
JB
840 desired_frame->glyphs[vpos],
841 start * sizeof (current_frame->glyphs[vpos]));
60a8948a
RS
842 bcopy (current_frame->charstarts[vpos],
843 desired_frame->charstarts[vpos],
844 start * sizeof (current_frame->charstarts[vpos]));
502b9b64
JB
845 len = min (start, current_frame->used[vpos]);
846 if (desired_frame->used[vpos] < len)
847 desired_frame->used[vpos] = len;
4588ec20 848 }
502b9b64
JB
849 if (current_frame->used[vpos] > end
850 && desired_frame->used[vpos] < current_frame->used[vpos])
4588ec20 851 {
502b9b64 852 while (desired_frame->used[vpos] < end)
60a8948a
RS
853 {
854 int used = desired_frame->used[vpos]++;
855 desired_frame->glyphs[vpos][used] = SPACEGLYPH;
856 desired_frame->glyphs[vpos][used] = 0;
857 }
502b9b64
JB
858 bcopy (current_frame->glyphs[vpos] + end,
859 desired_frame->glyphs[vpos] + end,
aec9f5f6
JB
860 ((current_frame->used[vpos] - end)
861 * sizeof (current_frame->glyphs[vpos])));
60a8948a
RS
862 bcopy (current_frame->charstarts[vpos] + end,
863 desired_frame->charstarts[vpos] + end,
864 ((current_frame->used[vpos] - end)
865 * sizeof (current_frame->charstarts[vpos])));
502b9b64 866 desired_frame->used[vpos] = current_frame->used[vpos];
4588ec20
JB
867 }
868 }
869 }
870}
871\f
872#if 0
873
502b9b64 874/* If window w does not need to be updated and isn't the full frame wide,
4588ec20 875 copy all the columns that w does occupy
502b9b64
JB
876 into the FRAME_DESIRED_LINES (frame) from the FRAME_PHYS_LINES (frame)
877 so that update_frame will not change those columns.
4588ec20
JB
878
879 Have not been able to figure out how to use this correctly. */
880
881preserve_my_columns (w)
882 struct window *w;
883{
884 register int vpos, fin;
502b9b64
JB
885 register struct frame_glyphs *l1, *l2;
886 register FRAME_PTR frame = XFRAME (w->frame);
4588ec20
JB
887 int start = XFASTINT (w->left);
888 int end = XFASTINT (w->left) + XFASTINT (w->width);
889 int bot = XFASTINT (w->top) + XFASTINT (w->height);
890
891 for (vpos = XFASTINT (w->top); vpos < bot; vpos++)
892 {
502b9b64
JB
893 if ((l1 = FRAME_DESIRED_GLYPHS (frame)->glyphs[vpos + 1])
894 && (l2 = FRAME_PHYS_GLYPHS (frame)->glyphs[vpos + 1]))
4588ec20
JB
895 {
896 if (l2->length > start && l1->length < l2->length)
897 {
898 fin = l2->length;
899 if (fin > end) fin = end;
900 while (l1->length < start)
901 l1->body[l1->length++] = ' ';
902 bcopy (l2->body + start, l1->body + start, fin - start);
903 l1->length = fin;
904 }
905 }
906 }
907}
908
909#endif
910\f
b64b3980 911/* Adjust by ADJUST the charstart values in window W
23b0200c 912 after vpos VPOS, which counts relative to the frame
b64b3980
RS
913 (not relative to W itself). */
914
915void
916adjust_window_charstarts (w, vpos, adjust)
917 struct window *w;
918 int vpos;
919 int adjust;
920{
921 int left = XFASTINT (w->left);
922 int top = XFASTINT (w->top);
23b0200c
RS
923 int right = left + window_internal_width (w);
924 int bottom = top + window_internal_height (w);
b64b3980
RS
925 int i;
926
23b0200c 927 for (i = vpos + 1; i < bottom; i++)
b64b3980
RS
928 {
929 int *charstart
930 = FRAME_CURRENT_GLYPHS (XFRAME (WINDOW_FRAME (w)))->charstarts[i];
931 int j;
932 for (j = left; j < right; j++)
933 if (charstart[j] > 0)
934 charstart[j] += adjust;
935 }
936}
23b0200c
RS
937
938verify_charstarts (w)
939 struct window *w;
940{
941 FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
942 int i;
943 int top = XFASTINT (w->top);
944 int bottom = top + window_internal_height (w);
945 int left = XFASTINT (w->left);
946 int right = left + window_internal_width (w);
947 int next_line;
948
949 for (i = top; i < bottom; i++)
950 {
951 int j;
952 int last;
953 int *charstart
954 = FRAME_CURRENT_GLYPHS (XFRAME (WINDOW_FRAME (w)))->charstarts[i];
955
956 if (i != top)
957 if (charstart[left] != next_line)
958 abort ();
959
960 for (j = left; j < right; j++)
961 if (charstart[j] > 0)
962 last = charstart[j];
2e8907d3
RS
963 /* Record where the next line should start. */
964 next_line = last;
965 if (BUF_ZV (XBUFFER (w->buffer)) != last)
966 {
967 /* If there's a newline between the two lines, count that. */
968 int endchar = *BUF_CHAR_ADDRESS (XBUFFER (w->buffer), last);
969 if (endchar == '\n')
970 next_line++;
971 }
23b0200c
RS
972 }
973}
b64b3980 974\f
4588ec20
JB
975/* On discovering that the redisplay for a window was no good,
976 cancel the columns of that window, so that when the window is
977 displayed over again get_display_line will not complain. */
978
979cancel_my_columns (w)
980 struct window *w;
981{
982 register int vpos;
60a8948a
RS
983 register struct frame_glyphs *desired_glyphs
984 = FRAME_DESIRED_GLYPHS (XFRAME (w->frame));
4588ec20
JB
985 register int start = XFASTINT (w->left);
986 register int bot = XFASTINT (w->top) + XFASTINT (w->height);
987
988 for (vpos = XFASTINT (w->top); vpos < bot; vpos++)
989 if (desired_glyphs->enable[vpos]
990 && desired_glyphs->used[vpos] >= start)
991 desired_glyphs->used[vpos] = start;
992}
993\f
502b9b64 994/* These functions try to perform directly and immediately on the frame
4588ec20
JB
995 the necessary output for one change in the buffer.
996 They may return 0 meaning nothing was done if anything is difficult,
997 or 1 meaning the output was performed properly.
502b9b64 998 They assume that the frame was up to date before the buffer
94aa5d2d 999 change being displayed. They make various other assumptions too;
4588ec20
JB
1000 see command_loop_1 where these are called. */
1001
1002int
1003direct_output_for_insert (g)
1004 int g;
1005{
502b9b64
JB
1006 register FRAME_PTR frame = selected_frame;
1007 register struct frame_glyphs *current_frame
1008 = FRAME_CURRENT_GLYPHS (frame);
4588ec20
JB
1009
1010#ifndef COMPILER_REGISTER_BUG
1011 register
1012#endif /* COMPILER_REGISTER_BUG */
1013 struct window *w = XWINDOW (selected_window);
1014#ifndef COMPILER_REGISTER_BUG
1015 register
1016#endif /* COMPILER_REGISTER_BUG */
502b9b64 1017 int hpos = FRAME_CURSOR_X (frame);
4588ec20
JB
1018#ifndef COMPILER_REGISTER_BUG
1019 register
1020#endif /* COMPILER_REGISTER_BUG */
502b9b64 1021 int vpos = FRAME_CURSOR_Y (frame);
4588ec20 1022
fa61c701
JB
1023 /* Give up if about to continue line. */
1024 if (hpos >= XFASTINT (w->left) + window_internal_width (w) - 1
1025
4588ec20
JB
1026 /* Avoid losing if cursor is in invisible text off left margin */
1027 || (XINT (w->hscroll) && hpos == XFASTINT (w->left))
1028
1029 /* Give up if cursor outside window (in minibuf, probably) */
648fa17d 1030 || cursor_in_echo_area
502b9b64
JB
1031 || FRAME_CURSOR_Y (frame) < XFASTINT (w->top)
1032 || FRAME_CURSOR_Y (frame) >= XFASTINT (w->top) + XFASTINT (w->height)
4588ec20 1033
502b9b64 1034 /* Give up if cursor not really at FRAME_CURSOR_X, FRAME_CURSOR_Y */
4588ec20
JB
1035 || !display_completed
1036
1037 /* Give up if buffer appears in two places. */
1038 || buffer_shared > 1
1039
d169fe39
RS
1040#ifdef USE_TEXT_PROPERTIES
1041 /* Intervals have already been adjusted, point is after the
1042 character that was just inserted. */
ef4d2f9e 1043 /* Give up if character is invisible. */
d169fe39
RS
1044 /* Give up if character has a face property.
1045 At the moment we only lose at end of line or end of buffer
1046 and only with faces that have some background */
1047 /* Instead of wasting time, give up if character has any text properties */
1048 || ! NILP (Ftext_properties_at (XFASTINT (point - 1), Qnil))
1049#endif
1050
4588ec20
JB
1051 /* Give up if w is minibuffer and a message is being displayed there */
1052 || (MINI_WINDOW_P (w) && echo_area_glyphs))
1053 return 0;
1054
517b2e01
JB
1055 {
1056#ifdef HAVE_X_WINDOWS
1057 int dummy;
90b5299a 1058 int face = compute_char_face (frame, w, point - 1, -1, -1, &dummy, point);
517b2e01 1059#endif
a1c3de84 1060 current_frame->glyphs[vpos][hpos] = MAKE_GLYPH (frame, g, face);
839c7dfb
RS
1061 current_frame->charstarts[vpos][hpos] = point - 1;
1062 /* Record the entry for after the newly inserted character. */
1063 current_frame->charstarts[vpos][hpos + 1] = point;
b64b3980 1064 adjust_window_charstarts (w, vpos, 1);
517b2e01 1065 }
4588ec20
JB
1066 unchanged_modified = MODIFF;
1067 beg_unchanged = GPT - BEG;
1068 XFASTINT (w->last_point) = point;
1069 XFASTINT (w->last_point_x) = hpos;
1070 XFASTINT (w->last_modified) = MODIFF;
1071
1072 reassert_line_highlight (0, vpos);
502b9b64 1073 write_glyphs (&current_frame->glyphs[vpos][hpos], 1);
4588ec20 1074 fflush (stdout);
502b9b64
JB
1075 ++FRAME_CURSOR_X (frame);
1076 if (hpos == current_frame->used[vpos])
4588ec20 1077 {
502b9b64
JB
1078 current_frame->used[vpos] = hpos + 1;
1079 current_frame->glyphs[vpos][hpos + 1] = 0;
4588ec20
JB
1080 }
1081
1082 return 1;
1083}
1084
1085int
1086direct_output_forward_char (n)
1087 int n;
1088{
502b9b64 1089 register FRAME_PTR frame = selected_frame;
4588ec20 1090 register struct window *w = XWINDOW (selected_window);
d169fe39 1091 int position;
ea0d86af
RS
1092 int hpos = FRAME_CURSOR_X (frame);
1093
1094 /* Give up if in truncated text at end of line. */
1095 if (hpos >= XFASTINT (w->left) + window_internal_width (w) - 1)
1096 return 0;
1097
a9764248
JB
1098 /* Avoid losing if cursor is in invisible text off left margin
1099 or about to go off either side of window. */
502b9b64 1100 if ((FRAME_CURSOR_X (frame) == XFASTINT (w->left)
a9764248
JB
1101 && (XINT (w->hscroll) || n < 0))
1102 || (n > 0
fa61c701 1103 && (FRAME_CURSOR_X (frame) + 1 >= window_internal_width (w) - 1))
648fa17d 1104 || cursor_in_echo_area)
4588ec20 1105 return 0;
d169fe39 1106
de83c314
RS
1107 /* Can't use direct output if highlighting a region. */
1108 if (!NILP (Vtransient_mark_mode) && !NILP (current_buffer->mark_active))
1109 return 0;
1110
d169fe39
RS
1111#ifdef USE_TEXT_PROPERTIES
1112 /* Don't use direct output next to an invisible character
1113 since we might need to do something special. */
1114
2f24f5ac
RS
1115 XFASTINT (position) = point;
1116 if (XFASTINT (position) < ZV
294634fb 1117 && ! NILP (Fget_char_property (position,
2f24f5ac 1118 Qinvisible,
294634fb
KH
1119 selected_window)))
1120 return 0;
d169fe39 1121
2f24f5ac
RS
1122 XFASTINT (position) = point - 1;
1123 if (XFASTINT (position) >= BEGV
294634fb 1124 && ! NILP (Fget_char_property (position,
2f24f5ac 1125 Qinvisible,
294634fb
KH
1126 selected_window)))
1127 return 0;
d169fe39
RS
1128#endif
1129
502b9b64
JB
1130 FRAME_CURSOR_X (frame) += n;
1131 XFASTINT (w->last_point_x) = FRAME_CURSOR_X (frame);
4588ec20 1132 XFASTINT (w->last_point) = point;
502b9b64 1133 cursor_to (FRAME_CURSOR_Y (frame), FRAME_CURSOR_X (frame));
4588ec20 1134 fflush (stdout);
d169fe39 1135
4588ec20
JB
1136 return 1;
1137}
1138\f
1139static void update_line ();
1140
502b9b64 1141/* Update frame F based on the data in FRAME_DESIRED_GLYPHS.
4588ec20
JB
1142 Value is nonzero if redisplay stopped due to pending input.
1143 FORCE nonzero means do not stop for pending input. */
1144
1145int
502b9b64
JB
1146update_frame (f, force, inhibit_hairy_id)
1147 FRAME_PTR f;
4588ec20
JB
1148 int force;
1149 int inhibit_hairy_id;
1150{
502b9b64
JB
1151 register struct frame_glyphs *current_frame = FRAME_CURRENT_GLYPHS (f);
1152 register struct frame_glyphs *desired_frame = FRAME_DESIRED_GLYPHS (f);
4588ec20
JB
1153 register int i;
1154 int pause;
1155 int preempt_count = baud_rate / 2400 + 1;
1156 extern input_pending;
1157#ifdef HAVE_X_WINDOWS
1158 register int downto, leftmost;
1159#endif
1160
d88c2b9e
RS
1161 if (preempt_count <= 0)
1162 preempt_count = 1;
1163
502b9b64 1164 if (FRAME_HEIGHT (f) == 0) abort (); /* Some bug zeros some core */
4588ec20
JB
1165
1166 detect_input_pending ();
1167 if (input_pending && !force)
1168 {
1169 pause = 1;
1170 goto do_pause;
1171 }
1172
502b9b64 1173 update_begin (f);
4588ec20
JB
1174
1175 if (!line_ins_del_ok)
1176 inhibit_hairy_id = 1;
1177
efb859b4
JB
1178 /* See if any of the desired lines are enabled; don't compute for
1179 i/d line if just want cursor motion. */
502b9b64
JB
1180 for (i = 0; i < FRAME_HEIGHT (f); i++)
1181 if (desired_frame->enable[i])
4588ec20
JB
1182 break;
1183
1184 /* Try doing i/d line, if not yet inhibited. */
502b9b64
JB
1185 if (!inhibit_hairy_id && i < FRAME_HEIGHT (f))
1186 force |= scrolling (f);
4588ec20
JB
1187
1188 /* Update the individual lines as needed. Do bottom line first. */
1189
502b9b64
JB
1190 if (desired_frame->enable[FRAME_HEIGHT (f) - 1])
1191 update_line (f, FRAME_HEIGHT (f) - 1);
4588ec20
JB
1192
1193#ifdef HAVE_X_WINDOWS
b6a65ac2 1194 if (FRAME_X_P (f))
4588ec20 1195 {
502b9b64
JB
1196 leftmost = downto = f->display.x->internal_border_width;
1197 if (desired_frame->enable[0])
4588ec20 1198 {
502b9b64
JB
1199 current_frame->top_left_x[FRAME_HEIGHT (f) - 1] = leftmost;
1200 current_frame->top_left_y[FRAME_HEIGHT (f) - 1]
1201 = PIXEL_HEIGHT (f) - f->display.x->internal_border_width
448fd7c0 1202 - current_frame->pix_height[FRAME_HEIGHT (f) - 1];
502b9b64
JB
1203 current_frame->top_left_x[0] = leftmost;
1204 current_frame->top_left_y[0] = downto;
4588ec20
JB
1205 }
1206 }
1207#endif /* HAVE_X_WINDOWS */
1208
1209 /* Now update the rest of the lines. */
502b9b64 1210 for (i = 0; i < FRAME_HEIGHT (f) - 1 && (force || !input_pending); i++)
4588ec20 1211 {
502b9b64 1212 if (desired_frame->enable[i])
4588ec20 1213 {
b6a65ac2 1214 if (FRAME_TERMCAP_P (f))
4588ec20
JB
1215 {
1216 /* Flush out every so many lines.
1217 Also flush out if likely to have more than 1k buffered
1218 otherwise. I'm told that some telnet connections get
1219 really screwed by more than 1k output at once. */
1220 int outq = PENDING_OUTPUT_COUNT (stdout);
1221 if (outq > 900
1222 || (outq > 20 && ((i - 1) % preempt_count == 0)))
1223 {
1224 fflush (stdout);
1225 if (preempt_count == 1)
1226 {
a41f8bed
JB
1227#ifdef EMACS_OUTQSIZE
1228 if (EMACS_OUTQSIZE (0, &outq) < 0)
4588ec20
JB
1229 /* Probably not a tty. Ignore the error and reset
1230 * the outq count. */
1231 outq = PENDING_OUTPUT_COUNT (stdout);
1232#endif
1233 outq *= 10;
4d9c0ca4 1234 if (baud_rate >= outq)
d88c2b9e 1235 sleep (outq / baud_rate);
4588ec20
JB
1236 }
1237 }
1238 if ((i - 1) % preempt_count == 0)
1239 detect_input_pending ();
1240 }
1241
502b9b64 1242 update_line (f, i);
4588ec20 1243#ifdef HAVE_X_WINDOWS
b6a65ac2 1244 if (FRAME_X_P (f))
4588ec20 1245 {
502b9b64
JB
1246 current_frame->top_left_y[i] = downto;
1247 current_frame->top_left_x[i] = leftmost;
4588ec20
JB
1248 }
1249#endif /* HAVE_X_WINDOWS */
1250 }
1251
e5d77022 1252#ifdef HAVE_X_WINDOWS
b6a65ac2 1253 if (FRAME_X_P (f))
448fd7c0 1254 downto += current_frame->pix_height[i];
e5d77022 1255#endif
4588ec20 1256 }
502b9b64 1257 pause = (i < FRAME_HEIGHT (f) - 1) ? i : 0;
4588ec20
JB
1258
1259 /* Now just clean up termcap drivers and set cursor, etc. */
1260 if (!pause)
1261 {
648fa17d
JB
1262 if (cursor_in_echo_area
1263 && FRAME_HAS_MINIBUF_P (f))
1113d9db 1264 {
648fa17d
JB
1265 int top = XINT (XWINDOW (FRAME_MINIBUF_WINDOW (f))->top);
1266 int row, col;
1267
1268 if (cursor_in_echo_area < 0)
1269 {
1270 row = top;
1271 col = 0;
1272 }
1113d9db 1273 else
648fa17d
JB
1274 {
1275 /* If the minibuffer is several lines high, find the last
1276 line that has any text on it. */
1277 row = FRAME_HEIGHT (f);
1278 do
1279 {
1280 row--;
1281 if (current_frame->enable[row])
1282 col = current_frame->used[row];
1283 else
1284 col = 0;
1285 }
1286 while (row > top && col == 0);
1287
1288 if (col >= FRAME_WIDTH (f))
1289 {
1290 col = 0;
1291 if (row < FRAME_HEIGHT (f) - 1)
1292 row++;
1293 }
1294 }
1295
1296 cursor_to (row, col);
1113d9db 1297 }
4588ec20 1298 else
502b9b64
JB
1299 cursor_to (FRAME_CURSOR_Y (f), max (min (FRAME_CURSOR_X (f),
1300 FRAME_WIDTH (f) - 1), 0));
4588ec20
JB
1301 }
1302
502b9b64 1303 update_end (f);
4588ec20
JB
1304
1305 if (termscript)
1306 fflush (termscript);
1307 fflush (stdout);
1308
1309 /* Here if output is preempted because input is detected. */
1310 do_pause:
1311
502b9b64 1312 if (FRAME_HEIGHT (f) == 0) abort (); /* Some bug zeros some core */
4588ec20
JB
1313 display_completed = !pause;
1314
502b9b64 1315 bzero (desired_frame->enable, FRAME_HEIGHT (f));
4588ec20
JB
1316 return pause;
1317}
1318
1319/* Called when about to quit, to check for doing so
1320 at an improper time. */
1321
1322void
1323quit_error_check ()
1324{
502b9b64 1325 if (FRAME_DESIRED_GLYPHS (selected_frame) == 0)
4588ec20 1326 return;
502b9b64 1327 if (FRAME_DESIRED_GLYPHS (selected_frame)->enable[0])
4588ec20 1328 abort ();
502b9b64 1329 if (FRAME_DESIRED_GLYPHS (selected_frame)->enable[FRAME_HEIGHT (selected_frame) - 1])
4588ec20
JB
1330 abort ();
1331}
1332\f
1333/* Decide what insert/delete line to do, and do it */
1334
1335extern void scrolling_1 ();
1336
502b9b64
JB
1337scrolling (frame)
1338 FRAME_PTR frame;
4588ec20
JB
1339{
1340 int unchanged_at_top, unchanged_at_bottom;
1341 int window_size;
1342 int changed_lines;
502b9b64
JB
1343 int *old_hash = (int *) alloca (FRAME_HEIGHT (frame) * sizeof (int));
1344 int *new_hash = (int *) alloca (FRAME_HEIGHT (frame) * sizeof (int));
1345 int *draw_cost = (int *) alloca (FRAME_HEIGHT (frame) * sizeof (int));
4588ec20 1346 register int i;
502b9b64
JB
1347 int free_at_end_vpos = FRAME_HEIGHT (frame);
1348 register struct frame_glyphs *current_frame = FRAME_CURRENT_GLYPHS (frame);
1349 register struct frame_glyphs *desired_frame = FRAME_DESIRED_GLYPHS (frame);
4588ec20
JB
1350
1351 /* Compute hash codes of all the lines.
1352 Also calculate number of changed lines,
1353 number of unchanged lines at the beginning,
1354 and number of unchanged lines at the end. */
1355
1356 changed_lines = 0;
1357 unchanged_at_top = 0;
502b9b64
JB
1358 unchanged_at_bottom = FRAME_HEIGHT (frame);
1359 for (i = 0; i < FRAME_HEIGHT (frame); i++)
4588ec20
JB
1360 {
1361 /* Give up on this scrolling if some old lines are not enabled. */
502b9b64 1362 if (!current_frame->enable[i])
4588ec20 1363 return 0;
502b9b64
JB
1364 old_hash[i] = line_hash_code (current_frame, i);
1365 if (! desired_frame->enable[i])
4588ec20
JB
1366 new_hash[i] = old_hash[i];
1367 else
502b9b64 1368 new_hash[i] = line_hash_code (desired_frame, i);
4588ec20
JB
1369
1370 if (old_hash[i] != new_hash[i])
1371 {
1372 changed_lines++;
502b9b64 1373 unchanged_at_bottom = FRAME_HEIGHT (frame) - i - 1;
4588ec20
JB
1374 }
1375 else if (i == unchanged_at_top)
1376 unchanged_at_top++;
502b9b64 1377 draw_cost[i] = line_draw_cost (desired_frame, i);
4588ec20
JB
1378 }
1379
1380 /* If changed lines are few, don't allow preemption, don't scroll. */
1381 if (changed_lines < baud_rate / 2400
502b9b64 1382 || unchanged_at_bottom == FRAME_HEIGHT (frame))
4588ec20
JB
1383 return 1;
1384
502b9b64 1385 window_size = (FRAME_HEIGHT (frame) - unchanged_at_top
4588ec20
JB
1386 - unchanged_at_bottom);
1387
1388 if (scroll_region_ok)
1389 free_at_end_vpos -= unchanged_at_bottom;
502b9b64 1390 else if (memory_below_frame)
4588ec20
JB
1391 free_at_end_vpos = -1;
1392
1393 /* If large window, fast terminal and few lines in common between
502b9b64 1394 current frame and desired frame, don't bother with i/d calc. */
4588ec20
JB
1395 if (window_size >= 18 && baud_rate > 2400
1396 && (window_size >=
1397 10 * scrolling_max_lines_saved (unchanged_at_top,
502b9b64 1398 FRAME_HEIGHT (frame) - unchanged_at_bottom,
4588ec20
JB
1399 old_hash, new_hash, draw_cost)))
1400 return 0;
1401
502b9b64 1402 scrolling_1 (frame, window_size, unchanged_at_top, unchanged_at_bottom,
4588ec20
JB
1403 draw_cost + unchanged_at_top - 1,
1404 old_hash + unchanged_at_top - 1,
1405 new_hash + unchanged_at_top - 1,
1406 free_at_end_vpos - unchanged_at_top);
1407
1408 return 0;
1409}
1410\f
1411/* Return the offset in its buffer of the character at location col, line
1412 in the given window. */
1413int
1414buffer_posn_from_coords (window, col, line)
1415 struct window *window;
1416 int col, line;
1417{
ef0fdbb1 1418 int hscroll = XINT (window->hscroll);
4588ec20
JB
1419 int window_left = XFASTINT (window->left);
1420
1421 /* The actual width of the window is window->width less one for the
efb859b4
JB
1422 DISP_CONTINUE_GLYPH, and less one if it's not the rightmost
1423 window. */
fa61c701 1424 int window_width = window_internal_width (window) - 1;
4588ec20 1425
efb859b4 1426 int startp = marker_position (window->start);
4588ec20
JB
1427
1428 /* Since compute_motion will only operate on the current buffer,
1429 we need to save the old one and restore it when we're done. */
1430 struct buffer *old_current_buffer = current_buffer;
efb859b4 1431 struct position *posn;
4588ec20
JB
1432
1433 current_buffer = XBUFFER (window->buffer);
1434
502b9b64
JB
1435 /* It would be nice if we could use FRAME_CURRENT_GLYPHS (XFRAME
1436 (window->frame))->bufp to avoid scanning from the very top of
efb859b4
JB
1437 the window, but it isn't maintained correctly, and I'm not even
1438 sure I will keep it. */
1439 posn = compute_motion (startp, 0,
1440 (window == XWINDOW (minibuf_window) && startp == 1
ef0fdbb1
KH
1441 ? minibuf_prompt_width : 0)
1442 + (hscroll ? 1 - hscroll : 0),
fb0f454a 1443 ZV, line, col,
ef0fdbb1 1444 window_width, hscroll, 0);
4588ec20
JB
1445
1446 current_buffer = old_current_buffer;
1447
502b9b64 1448 /* compute_motion considers frame points past the end of a line
efb859b4
JB
1449 to be *after* the newline, i.e. at the start of the next line.
1450 This is reasonable, but not really what we want. So if the
1451 result is on a line below LINE, back it up one character. */
1452 if (posn->vpos > line)
1453 return posn->bufpos - 1;
1454 else
1455 return posn->bufpos;
4588ec20
JB
1456}
1457\f
1458static int
1459count_blanks (r)
1460 register GLYPH *r;
1461{
1462 register GLYPH *p = r;
94aa5d2d
RS
1463 while (*p++ == SPACEGLYPH);
1464 return p - r - 1;
4588ec20
JB
1465}
1466
1467static int
1468count_match (str1, str2)
1469 GLYPH *str1, *str2;
1470{
1471 register GLYPH *p1 = str1;
1472 register GLYPH *p2 = str2;
1473 while (*p1++ == *p2++);
1474 return p1 - str1 - 1;
1475}
1476
1477/* Char insertion/deletion cost vector, from term.c */
1478extern int *char_ins_del_vector;
1479
945807a3 1480#define char_ins_del_cost(f) (&char_ins_del_vector[FRAME_WIDTH((f))])
4588ec20
JB
1481
1482static void
502b9b64
JB
1483update_line (frame, vpos)
1484 register FRAME_PTR frame;
4588ec20
JB
1485 int vpos;
1486{
1487 register GLYPH *obody, *nbody, *op1, *op2, *np1, *temp;
60a8948a 1488 int *temp1;
4588ec20
JB
1489 int tem;
1490 int osp, nsp, begmatch, endmatch, olen, nlen;
1491 int save;
502b9b64
JB
1492 register struct frame_glyphs *current_frame
1493 = FRAME_CURRENT_GLYPHS (frame);
1494 register struct frame_glyphs *desired_frame
1495 = FRAME_DESIRED_GLYPHS (frame);
4588ec20 1496
502b9b64
JB
1497 if (desired_frame->highlight[vpos]
1498 != (current_frame->enable[vpos] && current_frame->highlight[vpos]))
4588ec20 1499 {
502b9b64
JB
1500 change_line_highlight (desired_frame->highlight[vpos], vpos,
1501 (current_frame->enable[vpos] ?
1502 current_frame->used[vpos] : 0));
1503 current_frame->enable[vpos] = 0;
4588ec20
JB
1504 }
1505 else
502b9b64 1506 reassert_line_highlight (desired_frame->highlight[vpos], vpos);
4588ec20 1507
502b9b64 1508 if (! current_frame->enable[vpos])
4588ec20
JB
1509 {
1510 olen = 0;
1511 }
1512 else
1513 {
502b9b64
JB
1514 obody = current_frame->glyphs[vpos];
1515 olen = current_frame->used[vpos];
1516 if (! current_frame->highlight[vpos])
4588ec20
JB
1517 {
1518 if (!must_write_spaces)
1519 while (obody[olen - 1] == SPACEGLYPH && olen > 0)
1520 olen--;
1521 }
1522 else
1523 {
1524 /* For an inverse-video line, remember we gave it
502b9b64 1525 spaces all the way to the frame edge
4588ec20
JB
1526 so that the reverse video extends all the way across. */
1527
502b9b64 1528 while (olen < FRAME_WIDTH (frame) - 1)
4588ec20
JB
1529 obody[olen++] = SPACEGLYPH;
1530 }
1531 }
1532
1533 /* One way or another, this will enable the line being updated. */
502b9b64
JB
1534 current_frame->enable[vpos] = 1;
1535 current_frame->used[vpos] = desired_frame->used[vpos];
1536 current_frame->highlight[vpos] = desired_frame->highlight[vpos];
1537 current_frame->bufp[vpos] = desired_frame->bufp[vpos];
4588ec20
JB
1538
1539#ifdef HAVE_X_WINDOWS
b6a65ac2 1540 if (FRAME_X_P (frame))
4588ec20 1541 {
502b9b64
JB
1542 current_frame->pix_width[vpos]
1543 = current_frame->used[vpos]
1544 * FONT_WIDTH (frame->display.x->font);
1545 current_frame->pix_height[vpos]
1546 = FONT_HEIGHT (frame->display.x->font);
4588ec20
JB
1547 }
1548#endif /* HAVE_X_WINDOWS */
1549
502b9b64 1550 if (!desired_frame->enable[vpos])
4588ec20
JB
1551 {
1552 nlen = 0;
1553 goto just_erase;
1554 }
1555
502b9b64
JB
1556 nbody = desired_frame->glyphs[vpos];
1557 nlen = desired_frame->used[vpos];
4588ec20
JB
1558
1559 /* Pretend trailing spaces are not there at all,
1560 unless for one reason or another we must write all spaces. */
502b9b64 1561 if (! desired_frame->highlight[vpos])
4588ec20
JB
1562 {
1563 if (!must_write_spaces)
1564 /* We know that the previous character byte contains 0. */
1565 while (nbody[nlen - 1] == SPACEGLYPH)
1566 nlen--;
1567 }
1568 else
1569 {
1570 /* For an inverse-video line, give it extra trailing spaces
502b9b64 1571 all the way to the frame edge
4588ec20
JB
1572 so that the reverse video extends all the way across. */
1573
502b9b64 1574 while (nlen < FRAME_WIDTH (frame) - 1)
4588ec20
JB
1575 nbody[nlen++] = SPACEGLYPH;
1576 }
1577
1578 /* If there's no i/d char, quickly do the best we can without it. */
1579 if (!char_ins_del_ok)
1580 {
1581 int i,j;
1582
76426794
RS
1583#if 0
1584 if (FRAME_X_P (frame))
1585 {
1586 /* Under X, erase everything we are going to rewrite,
1587 and rewrite everything from the first char that's changed.
1588 This is part of supporting fonts like Courier
1589 whose chars can overlap outside the char width. */
1590 for (i = 0; i < nlen; i++)
1591 if (i >= olen || nbody[i] != obody[i])
1592 break;
1593
1594 cursor_to (vpos, i);
1595 if (i != olen)
1596 clear_end_of_line (olen);
1597 write_glyphs (nbody + i, nlen - i);
1598 }
1599 else
1600 {}
1601#endif /* 0 */
4588ec20
JB
1602 for (i = 0; i < nlen; i++)
1603 {
1604 if (i >= olen || nbody[i] != obody[i]) /* A non-matching char. */
1605 {
1606 cursor_to (vpos, i);
1607 for (j = 1; (i + j < nlen &&
1608 (i + j >= olen || nbody[i+j] != obody[i+j]));
1609 j++);
1610
1611 /* Output this run of non-matching chars. */
1612 write_glyphs (nbody + i, j);
1613 i += j - 1;
1614
1615 /* Now find the next non-match. */
1616 }
1617 }
1618
1619 /* Clear the rest of the line, or the non-clear part of it. */
1620 if (olen > nlen)
1621 {
1622 cursor_to (vpos, nlen);
1623 clear_end_of_line (olen);
1624 }
1625
502b9b64
JB
1626 /* Exchange contents between current_frame and new_frame. */
1627 temp = desired_frame->glyphs[vpos];
1628 desired_frame->glyphs[vpos] = current_frame->glyphs[vpos];
1629 current_frame->glyphs[vpos] = temp;
4588ec20 1630
60a8948a
RS
1631 /* Exchange charstarts between current_frame and new_frame. */
1632 temp1 = desired_frame->charstarts[vpos];
1633 desired_frame->charstarts[vpos] = current_frame->charstarts[vpos];
1634 current_frame->charstarts[vpos] = temp1;
1635
4588ec20
JB
1636 return;
1637 }
1638
1639 if (!olen)
1640 {
502b9b64 1641 nsp = (must_write_spaces || desired_frame->highlight[vpos])
4588ec20
JB
1642 ? 0 : count_blanks (nbody);
1643 if (nlen > nsp)
1644 {
1645 cursor_to (vpos, nsp);
1646 write_glyphs (nbody + nsp, nlen - nsp);
1647 }
1648
502b9b64
JB
1649 /* Exchange contents between current_frame and new_frame. */
1650 temp = desired_frame->glyphs[vpos];
1651 desired_frame->glyphs[vpos] = current_frame->glyphs[vpos];
1652 current_frame->glyphs[vpos] = temp;
4588ec20 1653
60a8948a
RS
1654 /* Exchange charstarts between current_frame and new_frame. */
1655 temp1 = desired_frame->charstarts[vpos];
1656 desired_frame->charstarts[vpos] = current_frame->charstarts[vpos];
1657 current_frame->charstarts[vpos] = temp1;
1658
4588ec20
JB
1659 return;
1660 }
1661
1662 obody[olen] = 1;
1663 save = nbody[nlen];
1664 nbody[nlen] = 0;
1665
1666 /* Compute number of leading blanks in old and new contents. */
1667 osp = count_blanks (obody);
502b9b64 1668 if (!desired_frame->highlight[vpos])
4588ec20
JB
1669 nsp = count_blanks (nbody);
1670 else
1671 nsp = 0;
1672
1673 /* Compute number of matching chars starting with first nonblank. */
1674 begmatch = count_match (obody + osp, nbody + nsp);
1675
1676 /* Spaces in new match implicit space past the end of old. */
1677 /* A bug causing this to be a no-op was fixed in 18.29. */
1678 if (!must_write_spaces && osp + begmatch == olen)
1679 {
1680 np1 = nbody + nsp;
1681 while (np1[begmatch] == SPACEGLYPH)
1682 begmatch++;
1683 }
1684
1685 /* Avoid doing insert/delete char
1686 just cause number of leading spaces differs
1687 when the following text does not match. */
1688 if (begmatch == 0 && osp != nsp)
1689 osp = nsp = min (osp, nsp);
1690
1691 /* Find matching characters at end of line */
1692 op1 = obody + olen;
1693 np1 = nbody + nlen;
1694 op2 = op1 + begmatch - min (olen - osp, nlen - nsp);
1695 while (op1 > op2 && op1[-1] == np1[-1])
1696 {
1697 op1--;
1698 np1--;
1699 }
1700 endmatch = obody + olen - op1;
1701
1702 /* Put correct value back in nbody[nlen].
1703 This is important because direct_output_for_insert
1704 can write into the line at a later point.
1705 If this screws up the zero at the end of the line, re-establish it. */
1706 nbody[nlen] = save;
1707 obody[olen] = 0;
1708
1709 /* tem gets the distance to insert or delete.
1710 endmatch is how many characters we save by doing so.
1711 Is it worth it? */
1712
1713 tem = (nlen - nsp) - (olen - osp);
1714 if (endmatch && tem
502b9b64 1715 && (!char_ins_del_ok || endmatch <= char_ins_del_cost (frame)[tem]))
4588ec20
JB
1716 endmatch = 0;
1717
1718 /* nsp - osp is the distance to insert or delete.
1719 If that is nonzero, begmatch is known to be nonzero also.
1720 begmatch + endmatch is how much we save by doing the ins/del.
1721 Is it worth it? */
1722
1723 if (nsp != osp
1724 && (!char_ins_del_ok
502b9b64 1725 || begmatch + endmatch <= char_ins_del_cost (frame)[nsp - osp]))
4588ec20
JB
1726 {
1727 begmatch = 0;
1728 endmatch = 0;
1729 osp = nsp = min (osp, nsp);
1730 }
1731
1732 /* Now go through the line, inserting, writing and
1733 deleting as appropriate. */
1734
1735 if (osp > nsp)
1736 {
1737 cursor_to (vpos, nsp);
1738 delete_glyphs (osp - nsp);
1739 }
1740 else if (nsp > osp)
1741 {
1742 /* If going to delete chars later in line
1743 and insert earlier in the line,
1744 must delete first to avoid losing data in the insert */
1745 if (endmatch && nlen < olen + nsp - osp)
1746 {
1747 cursor_to (vpos, nlen - endmatch + osp - nsp);
1748 delete_glyphs (olen + nsp - osp - nlen);
1749 olen = nlen - (nsp - osp);
1750 }
1751 cursor_to (vpos, osp);
1752 insert_glyphs ((char *)0, nsp - osp);
1753 }
1754 olen += nsp - osp;
1755
1756 tem = nsp + begmatch + endmatch;
1757 if (nlen != tem || olen != tem)
1758 {
1759 cursor_to (vpos, nsp + begmatch);
1760 if (!endmatch || nlen == olen)
1761 {
1762 /* If new text being written reaches right margin,
1763 there is no need to do clear-to-eol at the end.
1764 (and it would not be safe, since cursor is not
1765 going to be "at the margin" after the text is done) */
502b9b64 1766 if (nlen == FRAME_WIDTH (frame))
4588ec20
JB
1767 olen = 0;
1768 write_glyphs (nbody + nsp + begmatch, nlen - tem);
1769
1770#ifdef obsolete
1771
1772/* the following code loses disastrously if tem == nlen.
1773 Rather than trying to fix that case, I am trying the simpler
1774 solution found above. */
1775
1776 /* If the text reaches to the right margin,
1777 it will lose one way or another (depending on AutoWrap)
1778 to clear to end of line after outputting all the text.
1779 So pause with one character to go and clear the line then. */
502b9b64 1780 if (nlen == FRAME_WIDTH (frame) && fast_clear_end_of_line && olen > nlen)
4588ec20
JB
1781 {
1782 /* endmatch must be zero, and tem must equal nsp + begmatch */
1783 write_glyphs (nbody + tem, nlen - tem - 1);
1784 clear_end_of_line (olen);
1785 olen = 0; /* Don't let it be cleared again later */
1786 write_glyphs (nbody + nlen - 1, 1);
1787 }
1788 else
1789 write_glyphs (nbody + nsp + begmatch, nlen - tem);
1790#endif /* OBSOLETE */
1791
1792 }
1793 else if (nlen > olen)
1794 {
1795 write_glyphs (nbody + nsp + begmatch, olen - tem);
1796 insert_glyphs (nbody + nsp + begmatch + olen - tem, nlen - olen);
1797 olen = nlen;
1798 }
1799 else if (olen > nlen)
1800 {
1801 write_glyphs (nbody + nsp + begmatch, nlen - tem);
1802 delete_glyphs (olen - nlen);
1803 olen = nlen;
1804 }
1805 }
1806
1807 just_erase:
1808 /* If any unerased characters remain after the new line, erase them. */
1809 if (olen > nlen)
1810 {
1811 cursor_to (vpos, nlen);
1812 clear_end_of_line (olen);
1813 }
1814
502b9b64
JB
1815 /* Exchange contents between current_frame and new_frame. */
1816 temp = desired_frame->glyphs[vpos];
1817 desired_frame->glyphs[vpos] = current_frame->glyphs[vpos];
1818 current_frame->glyphs[vpos] = temp;
60a8948a
RS
1819
1820 /* Exchange charstarts between current_frame and new_frame. */
1821 temp1 = desired_frame->charstarts[vpos];
1822 desired_frame->charstarts[vpos] = current_frame->charstarts[vpos];
1823 current_frame->charstarts[vpos] = temp1;
4588ec20
JB
1824}
1825\f
1826DEFUN ("open-termscript", Fopen_termscript, Sopen_termscript,
1827 1, 1, "FOpen termscript file: ",
1828 "Start writing all terminal output to FILE as well as the terminal.\n\
1829FILE = nil means just close any termscript file currently open.")
1830 (file)
1831 Lisp_Object file;
1832{
1833 if (termscript != 0) fclose (termscript);
1834 termscript = 0;
1835
efb859b4 1836 if (! NILP (file))
4588ec20
JB
1837 {
1838 file = Fexpand_file_name (file, Qnil);
1839 termscript = fopen (XSTRING (file)->data, "w");
1840 if (termscript == 0)
1841 report_file_error ("Opening termscript", Fcons (file, Qnil));
1842 }
1843 return Qnil;
1844}
1845\f
1846
1847#ifdef SIGWINCH
efb859b4 1848SIGTYPE
4588ec20
JB
1849window_change_signal ()
1850{
1851 int width, height;
1852 extern int errno;
1853 int old_errno = errno;
1854
502b9b64 1855 get_frame_size (&width, &height);
4588ec20 1856
502b9b64
JB
1857 /* The frame size change obviously applies to a termcap-controlled
1858 frame. Find such a frame in the list, and assume it's the only
4588ec20 1859 one (since the redisplay code always writes to stdout, not a
502b9b64 1860 FILE * specified in the frame structure). Record the new size,
4588ec20
JB
1861 but don't reallocate the data structures now. Let that be done
1862 later outside of the signal handler. */
1863
1864 {
35f56f96 1865 Lisp_Object tail, frame;
4588ec20 1866
35f56f96 1867 FOR_EACH_FRAME (tail, frame)
4588ec20 1868 {
35f56f96 1869 if (FRAME_TERMCAP_P (XFRAME (frame)))
4588ec20 1870 {
35f56f96 1871 change_frame_size (XFRAME (frame), height, width, 0, 1);
4588ec20
JB
1872 break;
1873 }
1874 }
1875 }
1876
1877 signal (SIGWINCH, window_change_signal);
1878 errno = old_errno;
1879}
1880#endif /* SIGWINCH */
1881
1882
502b9b64 1883/* Do any change in frame size that was requested by a signal. */
4588ec20
JB
1884
1885do_pending_window_change ()
1886{
1887 /* If window_change_signal should have run before, run it now. */
1888 while (delayed_size_change)
1889 {
35f56f96 1890 Lisp_Object tail, frame;
4588ec20
JB
1891
1892 delayed_size_change = 0;
1893
35f56f96 1894 FOR_EACH_FRAME (tail, frame)
4588ec20 1895 {
35f56f96
JB
1896 FRAME_PTR f = XFRAME (frame);
1897
502b9b64
JB
1898 int height = FRAME_NEW_HEIGHT (f);
1899 int width = FRAME_NEW_WIDTH (f);
4588ec20 1900
08f7aa3e 1901 if (height != 0 || width != 0)
b6a65ac2 1902 change_frame_size (f, height, width, 0, 0);
4588ec20
JB
1903 }
1904 }
1905}
1906
1907
502b9b64 1908/* Change the frame height and/or width. Values may be given as zero to
b6a65ac2 1909 indicate no change is to take place.
4588ec20 1910
b6a65ac2
JB
1911 If DELAY is non-zero, then assume we're being called from a signal
1912 handler, and queue the change for later - perhaps the next
1913 redisplay. Since this tries to resize windows, we can't call it
1914 from a signal handler. */
1915
1916change_frame_size (frame, newheight, newwidth, pretend, delay)
502b9b64 1917 register FRAME_PTR frame;
b6a65ac2 1918 int newheight, newwidth, pretend;
4588ec20
JB
1919{
1920 /* If we can't deal with the change now, queue it for later. */
b6a65ac2 1921 if (delay)
4588ec20 1922 {
b6a65ac2 1923 FRAME_NEW_HEIGHT (frame) = newheight;
502b9b64 1924 FRAME_NEW_WIDTH (frame) = newwidth;
4588ec20
JB
1925 delayed_size_change = 1;
1926 return;
1927 }
1928
502b9b64
JB
1929 /* This size-change overrides any pending one for this frame. */
1930 FRAME_NEW_HEIGHT (frame) = 0;
b6a65ac2
JB
1931 FRAME_NEW_WIDTH (frame) = 0;
1932
08f7aa3e 1933 /* If an argument is zero, set it to the current value. */
b6a65ac2
JB
1934 newheight || (newheight = FRAME_HEIGHT (frame));
1935 newwidth || (newwidth = FRAME_WIDTH (frame));
4588ec20 1936
b6a65ac2
JB
1937 /* Round up to the smallest acceptable size. */
1938 check_frame_size (frame, &newheight, &newwidth);
1939
1940 /* If we're not changing the frame size, quit now. */
1941 if (newheight == FRAME_HEIGHT (frame)
1942 && newwidth == FRAME_WIDTH (frame))
4588ec20
JB
1943 return;
1944
b6a65ac2 1945 if (newheight != FRAME_HEIGHT (frame))
4588ec20 1946 {
b6a65ac2 1947 if (FRAME_HAS_MINIBUF_P (frame)
502b9b64 1948 && ! FRAME_MINIBUF_ONLY_P (frame))
4588ec20 1949 {
502b9b64
JB
1950 /* Frame has both root and minibuffer. */
1951 set_window_height (FRAME_ROOT_WINDOW (frame),
cb470ab1 1952 newheight - 1 - FRAME_MENU_BAR_LINES (frame), 0);
502b9b64 1953 XFASTINT (XWINDOW (FRAME_MINIBUF_WINDOW (frame))->top)
b6a65ac2 1954 = newheight - 1;
502b9b64 1955 set_window_height (FRAME_MINIBUF_WINDOW (frame), 1, 0);
4588ec20
JB
1956 }
1957 else
502b9b64 1958 /* Frame has just one top-level window. */
cb470ab1
RS
1959 set_window_height (FRAME_ROOT_WINDOW (frame),
1960 newheight - FRAME_MENU_BAR_LINES (frame), 0);
b6a65ac2
JB
1961
1962 if (FRAME_TERMCAP_P (frame) && !pretend)
1963 FrameRows = newheight;
4588ec20
JB
1964
1965#if 0
502b9b64 1966 if (frame->output_method == output_termcap)
4588ec20 1967 {
b6a65ac2 1968 frame_height = newheight;
4588ec20 1969 if (!pretend)
b6a65ac2 1970 FrameRows = newheight;
4588ec20
JB
1971 }
1972#endif
1973 }
1974
b6a65ac2 1975 if (newwidth != FRAME_WIDTH (frame))
4588ec20 1976 {
502b9b64 1977 set_window_width (FRAME_ROOT_WINDOW (frame), newwidth, 0);
b6a65ac2 1978 if (FRAME_HAS_MINIBUF_P (frame))
502b9b64 1979 set_window_width (FRAME_MINIBUF_WINDOW (frame), newwidth, 0);
4588ec20 1980
b6a65ac2 1981 if (FRAME_TERMCAP_P (frame) && !pretend)
502b9b64 1982 FrameCols = newwidth;
4588ec20 1983#if 0
502b9b64 1984 if (frame->output_method == output_termcap)
4588ec20 1985 {
502b9b64 1986 frame_width = newwidth;
4588ec20 1987 if (!pretend)
502b9b64 1988 FrameCols = newwidth;
4588ec20
JB
1989 }
1990#endif
1991 }
1992
b6a65ac2
JB
1993 FRAME_HEIGHT (frame) = newheight;
1994 FRAME_WIDTH (frame) = newwidth;
1995
502b9b64
JB
1996 remake_frame_glyphs (frame);
1997 calculate_costs (frame);
4588ec20
JB
1998}
1999\f
2000DEFUN ("send-string-to-terminal", Fsend_string_to_terminal,
2001 Ssend_string_to_terminal, 1, 1, 0,
2002 "Send STRING to the terminal without alteration.\n\
2003Control characters in STRING will have terminal-dependent effects.")
2004 (str)
2005 Lisp_Object str;
2006{
2007 CHECK_STRING (str, 0);
2008 fwrite (XSTRING (str)->data, 1, XSTRING (str)->size, stdout);
2009 fflush (stdout);
2010 if (termscript)
2011 {
2012 fwrite (XSTRING (str)->data, 1, XSTRING (str)->size, termscript);
2013 fflush (termscript);
2014 }
2015 return Qnil;
2016}
2017
2018DEFUN ("ding", Fding, Sding, 0, 1, 0,
2019 "Beep, or flash the screen.\n\
2020Also, unless an argument is given,\n\
2021terminate any keyboard macro currently executing.")
2022 (arg)
2023 Lisp_Object arg;
2024{
efb859b4 2025 if (!NILP (arg))
4588ec20 2026 {
7fa788da
RS
2027 if (noninteractive)
2028 putchar (07);
2029 else
2030 ring_bell ();
4588ec20
JB
2031 fflush (stdout);
2032 }
2033 else
2034 bitch_at_user ();
2035
2036 return Qnil;
2037}
2038
2039bitch_at_user ()
2040{
2041 if (noninteractive)
2042 putchar (07);
2043 else if (!INTERACTIVE) /* Stop executing a keyboard macro. */
2044 error ("Keyboard macro terminated by a command ringing the bell");
2045 else
2046 ring_bell ();
2047 fflush (stdout);
2048}
2049
2050DEFUN ("sleep-for", Fsleep_for, Ssleep_for, 1, 2, 0,
767229f8 2051 "Pause, without updating display, for SECONDS seconds.\n\
b07646f5
JB
2052SECONDS may be a floating-point value, meaning that you can wait for a\n\
2053fraction of a second. Optional second arg MILLISECONDS specifies an\n\
2054additional wait period, in milliseconds; this may be useful if your\n\
2055Emacs was built without floating point support.\n\
2056\(Not all operating systems support waiting for a fraction of a second.)")
767229f8
JB
2057 (seconds, milliseconds)
2058 Lisp_Object seconds, milliseconds;
4588ec20 2059{
767229f8 2060 int sec, usec;
4588ec20 2061
767229f8
JB
2062 if (NILP (milliseconds))
2063 XSET (milliseconds, Lisp_Int, 0);
2064 else
2065 CHECK_NUMBER (milliseconds, 1);
b07646f5
JB
2066 usec = XINT (milliseconds) * 1000;
2067
2068#ifdef LISP_FLOAT_TYPE
2069 {
2070 double duration = extract_float (seconds);
2071 sec = (int) duration;
2072 usec += (duration - sec) * 1000000;
2073 }
2074#else
2075 CHECK_NUMBER (seconds, 0);
2076 sec = XINT (seconds);
2077#endif
4588ec20 2078
a41f8bed 2079#ifndef EMACS_HAS_USECS
767229f8
JB
2080 if (sec == 0 && usec != 0)
2081 error ("millisecond `sleep-for' not supported on %s", SYSTEM_TYPE);
4588ec20 2082#endif
767229f8
JB
2083
2084 /* Assure that 0 <= usec < 1000000. */
2085 if (usec < 0)
2086 {
2087 /* We can't rely on the rounding being correct if user is negative. */
2088 if (-1000000 < usec)
2089 sec--, usec += 1000000;
2090 else
2091 sec -= -usec / 1000000, usec = 1000000 - (-usec % 1000000);
4588ec20 2092 }
767229f8
JB
2093 else
2094 sec += usec / 1000000, usec %= 1000000;
2095
5c48f0da 2096 if (sec <= 0)
767229f8 2097 return Qnil;
4588ec20 2098
f76475ad
JB
2099 {
2100 Lisp_Object zero;
2101
2102 XFASTINT (zero) = 0;
2103 wait_reading_process_input (sec, usec, zero, 0);
2104 }
d1af74e9 2105
767229f8
JB
2106 /* We should always have wait_reading_process_input; we have a dummy
2107 implementation for systems which don't support subprocesses. */
2108#if 0
2109 /* No wait_reading_process_input */
4588ec20
JB
2110 immediate_quit = 1;
2111 QUIT;
2112
2113#ifdef VMS
2114 sys_sleep (sec);
2115#else /* not VMS */
2116/* The reason this is done this way
2117 (rather than defined (H_S) && defined (H_T))
2118 is because the VMS preprocessor doesn't grok `defined' */
2119#ifdef HAVE_SELECT
a41f8bed
JB
2120 EMACS_GET_TIME (end_time);
2121 EMACS_SET_SECS_USECS (timeout, sec, usec);
d1af74e9 2122 EMACS_ADD_TIME (end_time, end_time, timeout);
a41f8bed 2123
4588ec20
JB
2124 while (1)
2125 {
a41f8bed
JB
2126 EMACS_GET_TIME (timeout);
2127 EMACS_SUB_TIME (timeout, end_time, timeout);
2128 if (EMACS_TIME_NEG_P (timeout)
2129 || !select (1, 0, 0, 0, &timeout))
4588ec20
JB
2130 break;
2131 }
4588ec20
JB
2132#else /* not HAVE_SELECT */
2133 sleep (sec);
2134#endif /* HAVE_SELECT */
2135#endif /* not VMS */
2136
2137 immediate_quit = 0;
2138#endif /* no subprocesses */
2139
2140 return Qnil;
2141}
2142
f76475ad
JB
2143/* This is just like wait_reading_process_input, except that
2144 it does the redisplay.
2145
ea0d86af
RS
2146 It's also much like Fsit_for, except that it can be used for
2147 waiting for input as well. One differnce is that sit_for
2148 does not call prepare_menu_bars; Fsit_for does call that. */
4588ec20 2149
f76475ad
JB
2150Lisp_Object
2151sit_for (sec, usec, reading, display)
2152 int sec, usec, reading, display;
2153{
2154 Lisp_Object read_kbd;
4588ec20
JB
2155
2156 if (detect_input_pending ())
2157 return Qnil;
4588ec20 2158
f76475ad
JB
2159 if (display)
2160 redisplay_preserve_echo_area ();
4588ec20 2161
dfdb645c
JB
2162 if (sec == 0 && usec == 0)
2163 return Qt;
2164
4588ec20 2165#ifdef SIGIO
8fc798e9 2166 gobble_input (0);
f76475ad
JB
2167#endif
2168
2169 XSET (read_kbd, Lisp_Int, reading ? -1 : 1);
2170 wait_reading_process_input (sec, usec, read_kbd, display);
2171
d1af74e9 2172
500ab754
JB
2173 /* wait_reading_process_input should always be available now; it is
2174 simulated in a simple way on systems that don't support
2175 subprocesses. */
2176#if 0
2177 /* No wait_reading_process_input available. */
4588ec20
JB
2178 immediate_quit = 1;
2179 QUIT;
2180
2181 waitchannels = 1;
2182#ifdef VMS
f76475ad 2183 input_wait_timeout (XINT (arg));
4588ec20 2184#else /* not VMS */
d1af74e9
JB
2185#ifndef HAVE_TIMEVAL
2186 timeout_sec = sec;
2187 select (1, &waitchannels, 0, 0, &timeout_sec);
2188#else /* HAVE_TIMEVAL */
2189 timeout.tv_sec = sec;
2190 timeout.tv_usec = usec;
4588ec20 2191 select (1, &waitchannels, 0, 0, &timeout);
d1af74e9 2192#endif /* HAVE_TIMEVAL */
4588ec20
JB
2193#endif /* not VMS */
2194
2195 immediate_quit = 0;
d1af74e9 2196#endif
4588ec20
JB
2197
2198 return detect_input_pending () ? Qnil : Qt;
2199}
2200
f76475ad 2201DEFUN ("sit-for", Fsit_for, Ssit_for, 1, 3, 0,
767229f8 2202 "Perform redisplay, then wait for SECONDS seconds or until input is available.\n\
b07646f5
JB
2203SECONDS may be a floating-point value, meaning that you can wait for a\n\
2204fraction of a second. Optional second arg MILLISECONDS specifies an\n\
2205additional wait period, in milliseconds; this may be useful if your\n\
2206Emacs was built without floating point support.\n\
2207\(Not all operating systems support waiting for a fraction of a second.)\n\
f76475ad
JB
2208Optional third arg non-nil means don't redisplay, just wait for input.\n\
2209Redisplay is preempted as always if input arrives, and does not happen\n\
2210if input is available before it starts.\n\
2211Value is t if waited the full time with no input arriving.")
767229f8
JB
2212 (seconds, milliseconds, nodisp)
2213 Lisp_Object seconds, milliseconds, nodisp;
f76475ad 2214{
767229f8 2215 int sec, usec;
f76475ad 2216
767229f8
JB
2217 if (NILP (milliseconds))
2218 XSET (milliseconds, Lisp_Int, 0);
2219 else
2220 CHECK_NUMBER (milliseconds, 1);
b07646f5
JB
2221 usec = XINT (milliseconds) * 1000;
2222
2223#ifdef LISP_FLOAT_TYPE
2224 {
2225 double duration = extract_float (seconds);
2226 sec = (int) duration;
2227 usec += (duration - sec) * 1000000;
2228 }
2229#else
2230 CHECK_NUMBER (seconds, 0);
2231 sec = XINT (seconds);
2232#endif
f76475ad 2233
f76475ad 2234#ifndef EMACS_HAS_USECS
767229f8
JB
2235 if (usec != 0 && sec == 0)
2236 error ("millisecond `sit-for' not supported on %s", SYSTEM_TYPE);
f76475ad 2237#endif
f76475ad 2238
ea0d86af
RS
2239 if (NILP (nodisp))
2240 prepare_menu_bars ();
f76475ad
JB
2241 return sit_for (sec, usec, 0, NILP (nodisp));
2242}
4588ec20
JB
2243\f
2244char *terminal_type;
2245
2246/* Initialization done when Emacs fork is started, before doing stty. */
2247/* Determine terminal type and set terminal_driver */
2248/* Then invoke its decoding routine to set up variables
2249 in the terminal package */
2250
2251init_display ()
2252{
2253#ifdef HAVE_X_WINDOWS
2254 extern int display_arg;
2255#endif
2256
2257 meta_key = 0;
2258 inverse_video = 0;
2259 cursor_in_echo_area = 0;
2260 terminal_type = (char *) 0;
2261
1315c181
JB
2262 /* Now is the time to initialize this; it's used by init_sys_modes
2263 during startup. */
2264 Vwindow_system = Qnil;
4588ec20 2265
1315c181
JB
2266 /* If the user wants to use a window system, we shouldn't bother
2267 initializing the terminal. This is especially important when the
2268 terminal is so dumb that emacs gives up before and doesn't bother
2269 using the window system.
4588ec20 2270
1315c181
JB
2271 If the DISPLAY environment variable is set, try to use X, and die
2272 with an error message if that doesn't work. */
4588ec20
JB
2273
2274#ifdef HAVE_X_WINDOWS
d460af17
JB
2275 if (! display_arg)
2276 {
2277#ifdef VMS
5de9f849 2278 display_arg = (getenv ("DECW$DISPLAY") != 0);
d460af17 2279#else
5de9f849 2280 display_arg = (getenv ("DISPLAY") != 0);
d460af17 2281#endif
f040093a 2282 }
d460af17
JB
2283
2284 if (!inhibit_window_system && display_arg)
4588ec20
JB
2285 {
2286 Vwindow_system = intern ("x");
2287#ifdef HAVE_X11
2288 Vwindow_system_version = make_number (11);
2289#else
2290 Vwindow_system_version = make_number (10);
2291#endif
2292 return;
2293 }
2294#endif /* HAVE_X_WINDOWS */
2295
2296 /* If no window system has been specified, try to use the terminal. */
2297 if (! isatty (0))
2298 {
2299 fprintf (stderr, "emacs: standard input is not a tty\n");
2300 exit (1);
2301 }
2302
2303 /* Look at the TERM variable */
2304 terminal_type = (char *) getenv ("TERM");
2305 if (!terminal_type)
2306 {
2307#ifdef VMS
2308 fprintf (stderr, "Please specify your terminal type.\n\
2309For types defined in VMS, use set term /device=TYPE.\n\
2310For types not defined in VMS, use define emacs_term \"TYPE\".\n\
2311\(The quotation marks are necessary since terminal types are lower case.)\n");
2312#else
2313 fprintf (stderr, "Please set the environment variable TERM; see tset(1).\n");
2314#endif
2315 exit (1);
2316 }
2317
2318#ifdef VMS
2319 /* VMS DCL tends to upcase things, so downcase term type.
2320 Hardly any uppercase letters in terminal types; should be none. */
2321 {
2322 char *new = (char *) xmalloc (strlen (terminal_type) + 1);
2323 char *p;
2324
2325 strcpy (new, terminal_type);
2326
2327 for (p = new; *p; p++)
2328 if (isupper (*p))
2329 *p = tolower (*p);
2330
2331 terminal_type = new;
2332 }
2333#endif
2334
2335 term_init (terminal_type);
2336
502b9b64
JB
2337 remake_frame_glyphs (selected_frame);
2338 calculate_costs (selected_frame);
4588ec20
JB
2339
2340 /* X and Y coordinates of the cursor between updates. */
502b9b64
JB
2341 FRAME_CURSOR_X (selected_frame) = 0;
2342 FRAME_CURSOR_Y (selected_frame) = 0;
4588ec20
JB
2343
2344#ifdef SIGWINCH
2345#ifndef CANNOT_DUMP
2346 if (initialized)
2347#endif /* CANNOT_DUMP */
2348 signal (SIGWINCH, window_change_signal);
2349#endif /* SIGWINCH */
2350}
2351\f
2352syms_of_display ()
2353{
502b9b64
JB
2354#ifdef MULTI_FRAME
2355 defsubr (&Sredraw_frame);
4588ec20
JB
2356#endif
2357 defsubr (&Sredraw_display);
2358 defsubr (&Sopen_termscript);
2359 defsubr (&Sding);
2360 defsubr (&Ssit_for);
2361 defsubr (&Ssleep_for);
2362 defsubr (&Ssend_string_to_terminal);
2363
2364 DEFVAR_INT ("baud-rate", &baud_rate,
2365 "The output baud rate of the terminal.\n\
2366On most systems, changing this value will affect the amount of padding\n\
2367and the other strategic decisions made during redisplay.");
2368 DEFVAR_BOOL ("inverse-video", &inverse_video,
502b9b64 2369 "*Non-nil means invert the entire frame display.\n\
4588ec20
JB
2370This means everything is in inverse video which otherwise would not be.");
2371 DEFVAR_BOOL ("visible-bell", &visible_bell,
502b9b64 2372 "*Non-nil means try to flash the frame to represent a bell.");
4588ec20 2373 DEFVAR_BOOL ("no-redraw-on-reenter", &no_redraw_on_reenter,
502b9b64 2374 "*Non-nil means no need to redraw entire frame after suspending.\n\
4588ec20 2375A non-nil value is useful if the terminal can automatically preserve\n\
502b9b64 2376Emacs's frame display when you reenter Emacs.\n\
4588ec20
JB
2377It is up to you to set this variable if your terminal can do that.");
2378 DEFVAR_LISP ("window-system", &Vwindow_system,
2379 "A symbol naming the window-system under which Emacs is running\n\
2380\(such as `x'), or nil if emacs is running on an ordinary terminal.");
2381 DEFVAR_LISP ("window-system-version", &Vwindow_system_version,
2382 "The version number of the window system in use.\n\
2383For X windows, this is 10 or 11.");
2384 DEFVAR_BOOL ("cursor-in-echo-area", &cursor_in_echo_area,
2385 "Non-nil means put cursor in minibuffer, at end of any message there.");
2386 DEFVAR_LISP ("glyph-table", &Vglyph_table,
502b9b64 2387 "Table defining how to output a glyph code to the frame.\n\
4588ec20
JB
2388If not nil, this is a vector indexed by glyph code to define the glyph.\n\
2389Each element can be:\n\
2390 integer: a glyph code which this glyph is an alias for.\n\
2391 string: output this glyph using that string (not impl. in X windows).\n\
2392 nil: this glyph mod 256 is char code to output,\n\
2393 and this glyph / 256 is face code for X windows (see `x-set-face').");
2394 Vglyph_table = Qnil;
2395
2396 DEFVAR_LISP ("standard-display-table", &Vstandard_display_table,
2397 "Display table to use for buffers that specify none.\n\
2398See `buffer-display-table' for more information.");
2399 Vstandard_display_table = Qnil;
2400
2401 /* Initialize `window-system', unless init_display already decided it. */
2402#ifdef CANNOT_DUMP
2403 if (noninteractive)
2404#endif
2405 {
2406 Vwindow_system = Qnil;
2407 Vwindow_system_version = Qnil;
2408 }
2409}