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