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