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