1 /* Newly written part of redisplay code.
2    Copyright (C) 1985, 1986, 1987, 1988, 1990 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 
26 #ifdef HAVE_TIMEVAL
27 #ifdef HPUX
28 #include <time.h>
29 #else
30 #include <sys/time.h>
31 #endif
32 #endif
33 
34 #ifdef HAVE_TERMIO
35 #include <termio.h>
36 #ifdef TCOUTQ
37 #undef TIOCOUTQ
38 #define TIOCOUTQ TCOUTQ
39 #include <fcntl.h>
40 #endif /* TCOUTQ defined */
41 #else
42 #ifndef VMS
43 #include <sys/ioctl.h>
44 #endif /* not VMS */
45 #endif /* not HAVE_TERMIO */
46 
47 /* Allow m- file to inhibit use of FIONREAD.  */
48 #ifdef BROKEN_FIONREAD
49 #undef FIONREAD
50 #endif
51 
52 /* We are unable to use interrupts if FIONREAD is not available,
53    so flush SIGIO so we won't try. */
54 #ifndef FIONREAD
55 #ifdef SIGIO
56 #undef SIGIO
57 #endif
58 #endif
59 
60 #undef NULL
61 
62 #include "termchar.h"
63 #include "termopts.h"
64 #include "cm.h"
65 #include "dispextern.h"
66 #include "lisp.h"
67 #include "buffer.h"
68 #include "window.h"
69 #include "commands.h"
70 
71 #define max(a, b) ((a) > (b) ? (a) : (b))
72 #define min(a, b) ((a) < (b) ? (a) : (b))
73 
74 #ifndef PENDING_OUTPUT_COUNT
75 /* Get number of chars of output now in the buffer of a stdio stream.
76    This ought to be built in in stdio, but it isn't.
77    Some s- files override this because their stdio internals differ.  */
78 #ifdef __GNU_LIBRARY__
79 #define	PENDING_OUTPUT_COUNT(FILE) ((FILE)->__bp - (FILE)->__buf)
80 #else
81 #define PENDING_OUTPUT_COUNT(FILE) ((FILE)->_ptr - (FILE)->_base)
82 #endif
83 #endif /* No PENDING_OUTPUT_COUNT */
84 
85 /* Nonzero means do not assume anything about current
86    contents of actual terminal screen */
87 
88 int screen_garbaged;
89 
90 /* Desired terminal cursor position (to show position of point),
91    origin zero */
92 
93 int cursor_hpos, cursor_vpos;
94 
95 /* Nonzero means last display completed and cursor is really at
96    cursor_hpos, cursor_vpos.  Zero means it was preempted. */
97 
98 int display_completed;
99 
100 /* Lisp variable visible-bell; enables use of screen-flash
101    instead of audible bell.  */
102 
103 int visible_bell;
104 
105 /* Invert the color of the whole screen, at a low level.  */
106 
107 int inverse_video;
108 
109 /* Line speed of the terminal.  */
110 
111 int baud_rate;
112 
113 /* nil or a symbol naming the window system
114    under which emacs is running
115    ('x is the only current possibility).  */
116 
117 Lisp_Object Vwindow_system;
118 
119 /* Version number of window system, or nil if no window system.  */
120 
121 Lisp_Object Vwindow_system_version;
122 
123 /* Nonzero means reading single-character input with prompt
124    so put cursor on minibuffer after the prompt.  */
125 
126 int cursor_in_echo_area;
127 
128 /* Description of actual screen contents.  */
129 
130 struct matrix *current_screen;
131 
132 /* Description of desired screen contents.  */
133 
134 struct matrix *new_screen;
135 
136 /* Buffer sometimes used to hold partial screen contents.  */
137 
138 struct matrix *temp_screen;
139 
140 /* Stdio stream being used for copy of all terminal output.  */
141 
142 FILE *termscript;
143 
144 /* Structure for info on cursor positioning */
145 
146 struct cm Wcm;
147 
148 int in_display;		/* 1 if in redisplay: can't handle SIGWINCH now.  */
149 
150 int delayed_size_change;  /* 1 means SIGWINCH happened when not safe.  */
151 int delayed_screen_height;  /* Remembered new screen height.  */
152 int delayed_screen_width;   /* Remembered new screen width.  */
153 
154 /* This buffer records the history of display preemption.  */
155 
156 struct preempt
157 {
158   /* Number of keyboard characters read so far at preempt.  */
159   int keyboard_char_count;
160   /* Vertical position at which preemption occurred.  */
161   int vpos;
162 };
163 
164 #define N_PREEMPTIONS 50
165 
166 /* Circular buffer recording recent display preemptions.  */
167 struct preempt preemptions[N_PREEMPTIONS];
168 
169 /* Index of next element in preemptions.  */
170 int preemption_index;
171 
172 /* Set these variables in the debugger to force a display preemption.  */
173 int debug_preemption_vpos = -1;
174 int debug_preemption_char_count = -1;
175 
176 extern int num_input_chars;
177 
178 /* Free and reallocate current_screen and new_screen.  */
179 
180 struct matrix *make_screen_structure ();
181 
182 remake_screen_structures ()
183 {
184   if (current_screen)
185     free_screen_structure (current_screen);
186   if (new_screen)
187     free_screen_structure (new_screen);
188   if (temp_screen)
189     free_screen_structure (temp_screen);
190 
191   current_screen = make_screen_structure (0);
192   new_screen = make_screen_structure (0);
193   temp_screen = make_screen_structure (1);
194 
195   if (message_buf)
196     message_buf = (char *) xrealloc (message_buf, screen_width + 1);
197   else
198     message_buf = (char *) xmalloc (screen_width + 1);
199 }
200 
201 struct matrix *
202 make_screen_structure (empty)
203      int empty;
204 {
205   int i;
206   struct matrix *new = (struct matrix *) xmalloc (sizeof (struct matrix));
207 
208   new->height = screen_height;
209   new->width = screen_width;
210   new->highlight = (char *) xmalloc (screen_height);
211   new->enable = (char *) xmalloc (screen_height);
212   new->contents = (unsigned char **) xmalloc (screen_height * sizeof (char *));
213   new->used = (int *) xmalloc (screen_height * sizeof (int));
214   if (empty)
215     {
216       /* Make the buffer used by decode_mode_spec.  */
217       new->total_contents = (unsigned char *) xmalloc (screen_width + 2);
218       bzero (new->contents, screen_height * sizeof (char *));
219     }
220   else
221     {
222       /* Add 2 to leave extra bytes at beginning and end of each line.  */
223       new->total_contents = (unsigned char *) xmalloc (screen_height * (screen_width + 2));
224       bzero (new->total_contents, screen_height * (screen_width + 2));
225       for (i = 0; i < screen_height; i++)
226 	new->contents[i] = new->total_contents + i * (screen_width + 2) + 1;
227     }
228   bzero (new->enable, screen_height);
229   return new;
230 }
231 
232 free_screen_structure (matrix)
233      struct matrix *matrix;
234 {
235   if (matrix->total_contents)
236     free (matrix->total_contents);
237   free (matrix->contents);
238   free (matrix->highlight);
239   free (matrix->enable);
240   free (matrix->used);
241   free (matrix);
242 }
243 
244 /* Return the hash code of contents of line VPOS of screen-matrix M.  */
245 
246 int
247 line_hash_code (m, vpos)
248      struct matrix *m;
249      int vpos;
250 {
251   register unsigned char *body;
252   register int h = 0;
253   /* Give all lighlighted lines the same hash code
254      so as to encourage scrolling to leave them in place.  */
255   if (m->highlight[vpos])
256     return -1;
257 
258   body = m->contents[vpos];
259 
260   if (must_write_spaces)
261     {
262       while (1)
263 	{
264 	  int c = *body++;
265 	  if (c == 0)
266 	    break;
267 	  h = (((h << 4) + (h >> 24)) & 0x0fffffff) + c - ' ';
268 	}
269     }
270   else
271     {
272       while (1)
273 	{
274 	  int c = *body++;
275 	  if (c == 0)
276 	    break;
277 	  h = (((h << 4) + (h >> 24)) & 0x0fffffff) + c;
278 	}
279     }
280   if (h)
281     return h;
282   return 1;
283 }
284 
285 /* Return number of characters in line in M at vpos VPOS,
286    except don't count leading and trailing spaces
287    unless the terminal requires those to be explicitly output.  */
288 
289 int
290 line_draw_cost (m, vpos)
291      struct matrix *m;
292      int vpos;
293 {
294   register unsigned char *body;
295   register int i;
296 
297   if (must_write_spaces)
298     return m->used[vpos];
299 
300   body = m->contents[vpos];
301   for (i = m->used[vpos]; i > 0 && body[i - 2] == ' '; i--);
302 
303   i -= count_blanks (body);
304   return max (i, 0);
305 }
306 
307 /* The functions on this page are the interface from xdisp.c to redisplay.
308 
309  The only other interface into redisplay is through setting
310  cursor_hpos and cursor_vpos (in xdisp.c) and setting screen_garbaged. */
311 
312 /* cancel_line eliminates any request to display a line at position `vpos' */
313 
314 cancel_line (vpos)
315      int vpos;
316 {
317   new_screen->enable[vpos] = 0;
318 }
319 
320 clear_screen_records ()
321 {
322   int i;
323 
324   bzero (current_screen->enable, screen_height);
325 }
326 
327 /* Get ready to display on line `vpos'
328    and set it up for outputting starting at `hpos' within it.
329    Return the text string where that line is stored.  */
330 
331 unsigned char *
332 get_display_line (vpos, hpos)
333      int vpos;
334      register int hpos;
335 {
336   if (new_screen->enable[vpos] && new_screen->used[vpos] > hpos)
337     abort ();
338   if (! new_screen->enable[vpos])
339     {
340       new_screen->used[vpos] = 0;
341       new_screen->highlight[vpos] = 0;
342       new_screen->enable[vpos] = 1;
343     }
344 
345   if (hpos > new_screen->used[vpos])
346     {
347       unsigned char *p = new_screen->contents[vpos] + new_screen->used[vpos];
348       unsigned char *end = new_screen->contents[vpos] + hpos;
349       new_screen->used[vpos] = hpos;
350       while (p != end)
351 	*p++ = ' ';
352     }
353 
354   return new_screen->contents[vpos];
355 }
356 
357 /* Scroll lines from vpos `from' up to but not including vpos `end'
358  down by `amount' lines (`amount' may be negative).
359  Returns nonzero if done, zero if terminal cannot scroll them. */
360 
361 int
362 scroll_screen_lines (from, end, amount)
363      int from, end, amount;
364 {
365   register int i;
366 
367   if (!line_ins_del_ok)
368     return 0;
369 
370   if (amount == 0)
371     return 1;
372   if (amount > 0)
373     {
374       set_terminal_window (end + amount);
375       if (!scroll_region_ok)
376 	ins_del_lines (end, -amount);
377       ins_del_lines (from, amount);
378       set_terminal_window (0);
379 
380       rotate_vector (current_screen->contents + from,
381 		     sizeof (char *) * (end + amount - from),
382 		     amount * sizeof (char *));
383       safe_bcopy (current_screen->used + from,
384 		  current_screen->used + from + amount,
385 		  (end - from) * sizeof current_screen->used[0]);
386       safe_bcopy (current_screen->highlight + from,
387 		  current_screen->highlight + from + amount,
388 		  (end - from) * sizeof current_screen->highlight[0]);
389       safe_bcopy (current_screen->enable + from,
390 		  current_screen->enable + from + amount,
391 		  (end - from) * sizeof current_screen->enable[0]);
392       /* Mark the lines made empty by scrolling as enabled, empty and
393 	 normal video.  */
394       bzero (current_screen->used + from,
395 	     amount * sizeof current_screen->used[0]);
396       bzero (current_screen->highlight + from,
397 	     amount * sizeof current_screen->highlight[0]);
398       for (i = from; i < from + amount; i++)
399 	{
400 	  current_screen->contents[i][0] = '\0';
401 	  current_screen->enable[i] = 1;
402 	}
403     }
404   if (amount < 0)
405     {
406       set_terminal_window (end);
407       ins_del_lines (from + amount, amount);
408       if (!scroll_region_ok)
409 	ins_del_lines (end + amount, -amount);
410       set_terminal_window (0);
411 
412       rotate_vector (current_screen->contents + from + amount,
413 		     sizeof (char *) * (end - from - amount),
414 		     (end - from) * sizeof (char *));
415       safe_bcopy (current_screen->used + from,
416 		  current_screen->used + from + amount,
417 		  (end - from) * sizeof current_screen->used[0]);
418       safe_bcopy (current_screen->highlight + from,
419 		  current_screen->highlight + from + amount,
420 		  (end - from) * sizeof current_screen->highlight[0]);
421       safe_bcopy (current_screen->enable + from,
422 		  current_screen->enable + from + amount,
423 		  (end - from) * sizeof current_screen->enable[0]);
424       /* Mark the lines made empty by scrolling as enabled, empty and
425 	 normal video.  */
426       bzero (current_screen->used + end + amount,
427 	     - amount * sizeof current_screen->used[0]);
428       bzero (current_screen->highlight + end + amount,
429 	     - amount * sizeof current_screen->highlight[0]);
430       for (i = end + amount; i < end; i++)
431 	{
432 	  current_screen->contents[i][0] = '\0';
433 	  current_screen->enable[i] = 1;
434 	}
435     }
436   return 1;
437 }
438 
439 /* Rotate a vector of SIZE bytes, by DISTANCE bytes.
440    DISTANCE may be negative.  */
441 
442 rotate_vector (vector, size, distance)
443      char *vector;
444      int size;
445      int distance;
446 {
447   char *temp = (char *) alloca (size);
448 
449   if (distance < 0)
450     distance += size;
451 
452   bcopy (vector, temp + distance, size - distance);
453   bcopy (vector + size - distance, temp, distance);
454   bcopy (temp, vector, size);
455 }
456 
457 /* Like bcopy except never gets confused by overlap.  */
458 
459 safe_bcopy (from, to, size)
460      char *from, *to;
461      int size;
462 {
463   register char *endf;
464   register char *endt;
465 
466   if (size == 0)
467     return;
468   if (from > to)
469     {
470       /* If destination is lower in memory, we can go from the beginning.  */
471       endf = from + size;
472       while (from != endf)
473 	*to++ = *from++;
474       return;
475     }
476 
477   /* If destination is higher in memory, we can go backwards from the end.  */
478   endf = from + size;
479   endt = to + size;
480 
481   do
482     *--endt = *--endf;
483   while (endf != from);
484 }
485 
486 /* After updating a window w that isn't the full screen wide,
487  copy all the columns that w does not occupy
488  from current_screen to new_screen,
489  so that update_screen will not change those columns.  */
490 
491 preserve_other_columns (w)
492      struct window *w;
493 {
494   register int vpos;
495   int start = XFASTINT (w->left);
496   int end = XFASTINT (w->left) + XFASTINT (w->width);
497   int bot = XFASTINT (w->top) + XFASTINT (w->height);
498 
499   for (vpos = XFASTINT (w->top); vpos < bot; vpos++)
500     {
501       if (current_screen->enable[vpos] && new_screen->enable[vpos])
502 	{
503 	  if (start > 0)
504 	    {
505 	      int len;
506 
507 	      bcopy (current_screen->contents[vpos],
508 		     new_screen->contents[vpos], start);
509 	      len = min (start, current_screen->used[vpos]);
510 	      if (new_screen->used[vpos] < len)
511 		new_screen->used[vpos] = len;
512 	    }
513 	  if (current_screen->used[vpos] > end
514 	      && new_screen->used[vpos] < current_screen->used[vpos])
515 	    {
516 	      while (new_screen->used[vpos] < end)
517 		new_screen->contents[vpos][new_screen->used[vpos]++] = ' ';
518 	      bcopy (current_screen->contents[vpos] + end,
519 		     new_screen->contents[vpos] + end,
520 		     current_screen->used[vpos] - end);
521 	      new_screen->used[vpos] = current_screen->used[vpos];
522 	    }
523 	}
524     }
525 }
526 
527 /* On discovering that the redisplay for a window was no good,
528  cancel the columns of that window,
529  so that when the window is displayed over again
530  get_display_line will not complain. */
531 
532 cancel_my_columns (w)
533      struct window *w;
534 {
535   register int vpos;
536   register int start = XFASTINT (w->left);
537   register int bot = XFASTINT (w->top) + XFASTINT (w->height);
538 
539   for (vpos = XFASTINT (w->top); vpos < bot; vpos++)
540     if (new_screen->enable[vpos] && new_screen->used[vpos] >= start)
541       new_screen->used[vpos] = start;
542 }
543 
544 /* These functions try to perform directly and immediately on the screen
545    the necessary output for one change in the buffer.
546    They may return 0 meaning nothing was done if anything is difficult,
547    or 1 meaning the output was performed properly.
548    They assume that the screen was up to date before the buffer
549    change being displayed.  THey make various other assumptions too;
550    see command_loop_1 where these are called.  */
551 
552 int
553 direct_output_for_insert (c)
554      int c;
555 {
556 #ifndef COMPILER_REGISTER_BUG
557   register
558 #endif COMPILER_REGISTER_BUG
559     struct window *w = XWINDOW (selected_window);
560 #ifndef COMPILER_REGISTER_BUG
561   register
562 #endif COMPILER_REGISTER_BUG
563     int hpos = cursor_hpos;
564 #ifndef COMPILER_REGISTER_BUG
565   register
566 #endif COMPILER_REGISTER_BUG
567     int vpos = cursor_vpos;
568 
569   /* Give up if about to continue line */
570   if (hpos - XFASTINT (w->left) + 1 + 1 >= XFASTINT (w->width)
571 
572   /* Avoid losing if cursor is in invisible text off left margin */
573       || XINT (w->hscroll) && hpos == XFASTINT (w->left)
574 
575   /* Give up if cursor outside window (in minibuf, probably) */
576       || cursor_vpos < XFASTINT (w->top)
577       || cursor_vpos >= XFASTINT (w->top) + XFASTINT (w->height)
578 
579   /* Give up if cursor not really at cursor_hpos, cursor_vpos */
580       || !display_completed
581 
582   /* Give up if w is minibuffer and a message is being displayed there */
583       || EQ (selected_window, minibuf_window) && echo_area_contents)
584     return 0;
585 
586   current_screen->contents[vpos][hpos] = c;
587   unchanged_modified = MODIFF;
588   beg_unchanged = GPT - BEG;
589   XFASTINT (w->last_point) = point;
590   XFASTINT (w->last_point_x) = cursor_hpos;
591   XFASTINT (w->last_modified) = MODIFF;
592 
593   reassert_line_highlight (0, cursor_vpos);
594   output_chars (&current_screen->contents[vpos][hpos], 1);
595   fflush (stdout);
596   ++cursor_hpos;
597   if (hpos == current_screen->used[vpos])
598     {
599       current_screen->used[vpos] = hpos + 1;
600       current_screen->contents[vpos][hpos + 1] = 0;
601     }
602   return 1;
603 }
604 
605 int
606 direct_output_forward_char (n)
607      int n;
608 {
609   register struct window *w = XWINDOW (selected_window);
610 
611   /* Avoid losing if cursor is in invisible text off left margin */
612   if (XINT (w->hscroll) && cursor_hpos == XFASTINT (w->left))
613     return 0;
614 
615   cursor_hpos += n;
616   XFASTINT (w->last_point_x) = cursor_hpos;
617   XFASTINT (w->last_point) = point;
618   move_cursor (cursor_vpos, cursor_hpos);
619   fflush (stdout);
620   return 1;
621 }
622 
623 /* Update the actual terminal screen based on the data in new_screen.
624    Value is nonzero if redisplay stopped due to pending input.
625    FORCE nonzero means do not stop for pending input.  */
626 
627 update_screen (force, inhibit_hairy_id)
628      int force;
629      int inhibit_hairy_id;
630 {
631   register struct display_line **p;
632   register struct display_line *l, *lnew;
633   register int i;
634   int pause;
635   int preempt_count = baud_rate / 2400 + 1;
636   extern input_pending;
637 
638   if (screen_height == 0) abort (); /* Some bug zeros some core */
639 
640   detect_input_pending ();
641   if (!force
642       && ((num_input_chars == debug_preemption_char_count
643 	   && debug_preemption_vpos == screen_height - 1)
644 	  || input_pending))
645     {
646       pause = screen_height;
647       goto do_pause;
648     }
649 
650   update_begin ();
651 
652   if (!line_ins_del_ok)
653     inhibit_hairy_id = 1;
654 
655   /* Don't compute for i/d line if just want cursor motion. */
656   for (i = 0; i < screen_height; i++)
657     if (new_screen->enable)
658       break;
659 
660   /* Try doing i/d line, if not yet inhibited.  */
661   if (!inhibit_hairy_id && i < screen_height)
662     force |= scrolling ();
663 
664   /* Update the individual lines as needed.  Do bottom line first.  */
665 
666   if (new_screen->enable[screen_height - 1])
667     update_line (screen_height - 1);
668   for (i = 0; i < screen_height - 1 && (force || !input_pending); i++)
669     {
670       if (!force && num_input_chars == debug_preemption_char_count
671 	  && debug_preemption_vpos == i)
672 	break;
673       if (new_screen->enable[i])
674 	{
675 	  /* Flush out every so many lines.
676 	     Also flush out if likely to have more than 1k buffered
677 	     otherwise.   I'm told that telnet connections get really
678 	     screwed by more than 1k output at once.  */
679 	  int outq = PENDING_OUTPUT_COUNT (stdout);
680 	  if (outq > 900
681 	      || (outq > 20 && ((i - 1) % preempt_count == 0)))
682 	    {
683 	      fflush (stdout);
684 	      if (preempt_count == 1)
685 		{
686 #ifdef TIOCOUTQ
687 		  if (ioctl (0, TIOCOUTQ, &outq) < 0)
688 		    /* Probably not a tty.  Ignore the error and reset
689 		     * the outq count. */
690 		    outq = PENDING_OUTPUT_COUNT (stdout);
691 #endif
692 		  outq *= 10;
693 		  sleep (outq / baud_rate);
694 		}
695 	    }
696 	  if ((i - 1) % preempt_count == 0)
697 	    detect_input_pending ();
698 	  /* Now update this line.  */
699 	  update_line (i);
700 	}
701     }
702   pause = (i < screen_height - 1) ? i + 1 : 0;
703 
704   /* Now just clean up termcap drivers and set cursor, etc.  */
705   if (!pause)
706     {
707       if (cursor_in_echo_area < 0)
708 	move_cursor (screen_height - 1, 0);
709       else if (cursor_in_echo_area > 0
710 	       && !current_screen->enable[screen_height - 1])
711 	move_cursor (screen_height - 1, 0);
712       else if (cursor_in_echo_area)
713 	move_cursor (screen_height - 1,
714 		     min (screen_width - 1,
715 			  current_screen->used[screen_height - 1]));
716       else
717 	move_cursor (cursor_vpos, max (min (cursor_hpos, screen_width - 1), 0));
718     }
719 
720   update_end ();
721 
722   if (termscript)
723     fflush (termscript);
724   fflush (stdout);
725 
726   /* Here if output is preempted because input is detected.  */
727  do_pause:
728 
729   if (screen_height == 0) abort (); /* Some bug zeros some core */
730   display_completed = !pause;
731   if (pause)
732     {
733       preemptions[preemption_index].vpos = pause - 1;
734       preemptions[preemption_index].keyboard_char_count = num_input_chars;
735       preemption_index++;
736       if (preemption_index == N_PREEMPTIONS)
737 	preemption_index = 0;
738     }
739 
740   bzero (new_screen->enable, screen_height);
741   return pause;
742 }
743 
744 /* Called when about to quit, to check for doing so
745    at an improper time.  */
746 
747 void
748 quit_error_check ()
749 {
750   if (new_screen == 0)
751     return;
752   if (new_screen->enable[0])
753     abort ();
754   if (new_screen->enable[screen_height - 1])
755     abort ();
756 }
757 
758 /* Decide what insert/delete line to do, and do it */
759 
760 scrolling ()
761 {
762   int unchanged_at_top, unchanged_at_bottom;
763   int window_size;
764   int changed_lines;
765   int *old_hash = (int *) alloca (screen_height * sizeof (int));
766   int *new_hash = (int *) alloca (screen_height * sizeof (int));
767   int *draw_cost = (int *) alloca (screen_height * sizeof (int));
768   register int i;
769   int free_at_end_vpos = screen_height;
770 
771   /* Compute hash codes of all the lines.
772      Also calculate number of changed lines,
773      number of unchanged lines at the beginning,
774      and number of unchanged lines at the end.  */
775 
776   changed_lines = 0;
777   unchanged_at_top = 0;
778   unchanged_at_bottom = screen_height;
779   for (i = 0; i < screen_height; i++)
780     {
781       /* Give up on this scrolling if some old lines are not enabled.  */
782       if (!current_screen->enable[i])
783 	return 0;
784       old_hash[i] = line_hash_code (current_screen, i);
785       if (!new_screen->enable[i])
786 	new_hash[i] = old_hash[i];
787       else
788 	new_hash[i] = line_hash_code (new_screen, i);
789       if (old_hash[i] != new_hash[i])
790 	{
791 	  changed_lines++;
792 	  unchanged_at_bottom = screen_height - i - 1;
793 	}
794       else if (i == unchanged_at_top)
795 	unchanged_at_top++;
796       /* If line is not changing, its redraw cost is infinite,
797 	 since we can't redraw it.  */
798       if (!new_screen->enable[i])
799 	draw_cost[i] = INFINITY;
800       else
801 	draw_cost[i] = line_draw_cost (new_screen, i);
802     }
803 
804   /* If changed lines are few, don't allow preemption, don't scroll.  */
805   if (changed_lines < baud_rate / 2400 || unchanged_at_bottom == screen_height)
806     return 1;
807 
808   window_size = screen_height - unchanged_at_top - unchanged_at_bottom;
809 
810   if (scroll_region_ok)
811     free_at_end_vpos -= unchanged_at_bottom;
812   else if (memory_below_screen)
813     free_at_end_vpos = -1;
814 
815   /* If large window, fast terminal and few lines in common between
816      current_screen and new_screen, don't bother with i/d calc.  */
817   if (window_size >= 18 && baud_rate > 2400
818       && (window_size >=
819 	  10 * scrolling_max_lines_saved (unchanged_at_top,
820 					  screen_height - unchanged_at_bottom,
821 					  old_hash, new_hash, draw_cost)))
822     return 0;
823 
824   scrolling_1 (window_size, unchanged_at_top, unchanged_at_bottom,
825 	       draw_cost + unchanged_at_top - 1,
826 	       old_hash + unchanged_at_top - 1,
827 	       new_hash + unchanged_at_top - 1,
828 	       free_at_end_vpos - unchanged_at_top);
829 
830   return 0;
831 }
832 
833 update_line (vpos)
834      int vpos;
835 {
836   register unsigned char *obody, *nbody, *op1, *op2, *np1;
837   int tem;
838   int osp, nsp, begmatch, endmatch, olen, nlen;
839   int save;
840   unsigned char *temp;
841 
842   /* Check for highlighting change.  */
843   if (new_screen->highlight[vpos]
844       != (current_screen->enable[vpos] && current_screen->highlight[vpos]))
845     {
846       change_line_highlight (new_screen->highlight[vpos], vpos,
847 			     (current_screen->enable[vpos]
848 			      ? current_screen->used[vpos] : 0));
849       current_screen->enable[vpos] = 0;
850     }
851   else
852     reassert_line_highlight (new_screen->highlight[vpos], vpos);
853 
854   /* ??? */
855   if (! current_screen->enable[vpos])
856     {
857       olen = 0;
858     }
859   else
860     {
861       obody = current_screen->contents[vpos];
862       olen = current_screen->used[vpos];
863       if (! current_screen->highlight[vpos])
864 	{
865 	  /* Note obody[-1] is always 0.  */
866 	  if (!must_write_spaces)
867 	    while (obody[olen - 1] == ' ')
868 	      olen--;
869 	}
870       else
871 	{
872 	  /* For an inverse-video line, remember we gave it
873 	     spaces all the way to the screen edge
874 	     so that the reverse video extends all the way across.  */
875 	  while (olen < screen_width - 1)
876 	    obody[olen++] = ' ';
877 	}
878     }
879 
880   /* One way or another, this will enable the line being updated.  */
881   current_screen->enable[vpos] = 1;
882   current_screen->used[vpos] = new_screen->used[vpos];
883   current_screen->highlight[vpos] = new_screen->highlight[vpos];
884 
885   if (!new_screen->enable[vpos])
886     {
887       nlen = 0;
888       goto just_erase;
889     }
890 
891   nbody = new_screen->contents[vpos];
892   nlen = new_screen->used[vpos];
893 
894   /* Pretend trailing spaces are not there at all,
895      unless for one reason or another we must write all spaces.  */
896   /* We know that the previous character byte contains 0.  */
897   if (! new_screen->highlight[vpos])
898     {
899       if (!must_write_spaces)
900 	while (nbody[nlen - 1] == ' ')
901 	  nlen--;
902     }
903   else
904     {
905       /* For an inverse-video line, give it extra trailing spaces
906 	 all the way to the screen edge
907 	 so that the reverse video extends all the way across.  */
908       while (nlen < screen_width - 1)
909 	nbody[nlen++] = ' ';
910     }
911 
912   /* If there's no i/d char, quickly do the best we can without it.  */
913   if (!char_ins_del_ok)
914     {
915       int i,j;
916 
917       for (i = 0; i < nlen; i++)
918 	{
919 	  if (i >= olen || nbody[i] != obody[i])
920 	    {
921 	      /* We found a non-matching char.  */
922 	      move_cursor (vpos, i);
923 	      for (j = 1; (i + j < nlen &&
924 			   (i + j >= olen || nbody[i+j] != obody[i+j]));
925 		   j++);
926 	      /* Output this run of non-matching chars.  */
927 	      output_chars (nbody + i, j);
928 	      i += j - 1;
929 	      /* Now find the next non-match.  */
930 	    }
931 	}
932       /* Clear the rest of the line, or the non-clear part of it.  */
933       if (olen > nlen)
934 	{
935 	  move_cursor (vpos, nlen);
936 	  clear_end_of_line (olen);
937 	}
938 
939       /* Exchange contents between current_screen and new_screen.  */
940       temp = new_screen->contents[vpos];
941       new_screen->contents[vpos] = current_screen->contents[vpos];
942       current_screen->contents[vpos] = temp;
943       return;
944     }
945 
946   if (!olen)
947     {
948       nsp = (must_write_spaces || new_screen->highlight[vpos])
949 	      ? 0 : count_blanks (nbody);
950       if (nlen > nsp)
951 	{
952 	  move_cursor (vpos, nsp);
953 	  output_chars (nbody + nsp, nlen - nsp);
954 	}
955 
956       /* Exchange contents between current_screen and new_screen.  */
957       temp = new_screen->contents[vpos];
958       new_screen->contents[vpos] = current_screen->contents[vpos];
959       current_screen->contents[vpos] = temp;
960       return;
961     }
962 
963   obody[olen] = 1;
964   save = nbody[nlen];
965   nbody[nlen] = 0;
966 
967   /* Compute number of leading blanks in old and new contents.  */
968   osp = count_blanks (obody);
969   if (!new_screen->highlight[vpos])
970     nsp = count_blanks (nbody);
971   else
972     nsp = 0;
973 
974   /* Compute number of matching chars starting with first nonblank.  */
975   begmatch = count_match (obody + osp, nbody + nsp);
976 
977   /* Spaces in new match implicit space past the end of old.  */
978   /* A bug causing this to be a no-op was fixed in 18.29.  */
979   if (!must_write_spaces && osp + begmatch == olen)
980     {
981       np1 = nbody + nsp;
982       while (np1[begmatch] == ' ')
983 	begmatch++;
984     }
985 
986   /* Avoid doing insert/delete char
987      just cause number of leading spaces differs
988      when the following text does not match. */
989   if (begmatch == 0 && osp != nsp)
990     osp = nsp = min (osp, nsp);
991 
992   /* Find matching characters at end of line */
993   op1 = obody + olen;
994   np1 = nbody + nlen;
995   op2 = op1 + begmatch - min (olen - osp, nlen - nsp);
996   while (op1 > op2 && op1[-1] == np1[-1])
997     {
998       op1--;
999       np1--;
1000     }
1001   endmatch = obody + olen - op1;
1002 
1003   /* Put correct value back in nbody[nlen].
1004      This is important because direct_output_for_insert
1005      can write into the line at a later point.  */
1006   nbody[nlen] = save;
1007 
1008   /* tem gets the distance to insert or delete.
1009      endmatch is how many characters we save by doing so.
1010      Is it worth it?  */
1011 
1012   tem = (nlen - nsp) - (olen - osp);
1013   if (endmatch && tem && endmatch <= DCICcost[tem])
1014     endmatch = 0;
1015 
1016   /* nsp - osp is the distance to insert or delete.
1017      begmatch + endmatch is how much we save by doing so.
1018      Is it worth it?  */
1019 
1020   if (begmatch + endmatch > 0 && nsp != osp
1021       && begmatch + endmatch <= DCICcost[nsp - osp])
1022     {
1023       begmatch = 0;
1024       endmatch = 0;
1025       osp = nsp = min (osp, nsp);
1026     }
1027 
1028   /* Now go through the line, inserting, writing and deleting as appropriate.  */
1029 
1030   if (osp > nsp)
1031     {
1032       move_cursor (vpos, nsp);
1033       delete_chars (osp - nsp);
1034     }
1035   else if (nsp > osp)
1036     {
1037       /* If going to delete chars later in line
1038 	 and insert earlier in the line,
1039 	 must delete first to avoid losing data in the insert */
1040       if (endmatch && nlen < olen + nsp - osp)
1041 	{
1042 	  move_cursor (vpos, nlen - endmatch + osp - nsp);
1043 	  delete_chars (olen + nsp - osp - nlen);
1044 	  olen = nlen - (nsp - osp);
1045 	}
1046       move_cursor (vpos, osp);
1047       insert_chars ((char *)0, nsp - osp);
1048     }
1049   olen += nsp - osp;
1050 
1051   tem = nsp + begmatch + endmatch;
1052   if (nlen != tem || olen != tem)
1053     {
1054       move_cursor (vpos, nsp + begmatch);
1055       if (!endmatch || nlen == olen)
1056 	{
1057 	  /* If new text being written reaches right margin,
1058 	     there is no need to do clear-to-eol at the end.
1059 	     (and it would not be safe, since cursor is not
1060 	     going to be "at the margin" after the text is done) */
1061 	  if (nlen == screen_width)
1062 	    olen = 0;
1063 	  output_chars (nbody + nsp + begmatch, nlen - tem);
1064 #ifdef obsolete
1065 /* the following code loses disastrously if tem == nlen.
1066    Rather than trying to fix that case, I am trying the simpler
1067    solution found above.  */
1068 	  /* If the text reaches to the right margin,
1069 	     it will lose one way or another (depending on AutoWrap)
1070 	     to clear to end of line after outputting all the text.
1071 	     So pause with one character to go and clear the line then.  */
1072 	  if (nlen == screen_width && fast_clear_end_of_line && olen > nlen)
1073 	    {
1074 	      /* endmatch must be zero, and tem must equal nsp + begmatch */
1075 	      output_chars (nbody + tem, nlen - tem - 1);
1076 	      clear_end_of_line (olen);
1077 	      olen = 0;		/* Don't let it be cleared again later */
1078 	      output_chars (nbody + nlen - 1, 1);
1079 	    }
1080 	  else
1081 	    output_chars (nbody + nsp + begmatch, nlen - tem);
1082 #endif
1083 	}
1084       else if (nlen > olen)
1085 	{
1086 	  output_chars (nbody + nsp + begmatch, olen - tem);
1087 	  insert_chars (nbody + nsp + begmatch + olen - tem, nlen - olen);
1088 	  olen = nlen;
1089 	}
1090       else if (olen > nlen)
1091 	{
1092 	  output_chars (nbody + nsp + begmatch, nlen - tem);
1093 	  delete_chars (olen - nlen);
1094 	  olen = nlen;
1095 	}
1096     }
1097 
1098  just_erase:
1099   /* If any unerased characters remain after the new line, erase them.  */
1100   if (olen > nlen)
1101     {
1102       move_cursor (vpos, nlen);
1103       clear_end_of_line (olen);
1104     }
1105 
1106   /* Exchange contents between current_screen and new_screen.  */
1107   temp = new_screen->contents[vpos];
1108   new_screen->contents[vpos] = current_screen->contents[vpos];
1109   current_screen->contents[vpos] = temp;
1110 }
1111 
1112 count_blanks (str)
1113      char *str;
1114 {
1115   register char *p = str;
1116   while (*str++ == ' ');
1117   return str - p - 1;
1118 }
1119 
1120 count_match (str1, str2)
1121      char *str1, *str2;
1122 {
1123   register char *p1 = str1;
1124   register char *p2 = str2;
1125   while (*p1++ == *p2++);
1126   return p1 - str1 - 1;
1127 }
1128 
1129 DEFUN ("open-termscript", Fopen_termscript, Sopen_termscript,
1130   1, 1, "FOpen termscript file: ",
1131   "Start writing all terminal output to FILE as well as the terminal.\n\
1132 FILE = nil means just close any termscript file currently open.")
1133   (file)
1134      Lisp_Object file;
1135 {
1136   if (termscript != 0) fclose (termscript);
1137   termscript = 0;
1138 
1139   if (! NULL (file))
1140     {
1141       file = Fexpand_file_name (file, Qnil);
1142       termscript = fopen (XSTRING (file)->data, "w");
1143       if (termscript == 0)
1144 	report_file_error ("Opening termscript", Fcons (file, Qnil));
1145     }
1146   return Qnil;
1147 }
1148 
1149 DEFUN ("set-screen-height", Fset_screen_height, Sset_screen_height, 1, 2, 0,
1150   "Tell redisplay that the screen has LINES lines.\n\
1151 Optional second arg non-nil means that redisplay should use LINES lines\n\
1152 but that the idea of the actual height of the screen should not be changed.")
1153   (n, pretend)
1154      Lisp_Object n, pretend;
1155 {
1156   CHECK_NUMBER (n, 0);
1157   change_screen_size (XINT (n), 0, !NULL (pretend));
1158   return Qnil;
1159 }
1160 
1161 DEFUN ("set-screen-width", Fset_screen_width, Sset_screen_width, 1, 2, 0,
1162   "Tell redisplay that the screen has COLS columns.\n\
1163 Optional second arg non-nil means that redisplay should use COLS columns\n\
1164 but that the idea of the actual width of the screen should not be changed.")
1165   (n, pretend)
1166      Lisp_Object n, pretend;
1167 {
1168   CHECK_NUMBER (n, 0);
1169   change_screen_size (0, XINT (n), !NULL (pretend));
1170   return Qnil;
1171 }
1172 
1173 DEFUN ("screen-height", Fscreen_height, Sscreen_height, 0, 0, 0,
1174   "Return number of lines on screen available for display.")
1175   ()
1176 {
1177   return make_number (screen_height);
1178 }
1179 
1180 DEFUN ("screen-width", Fscreen_width, Sscreen_width, 0, 0, 0,
1181   "Return number of columns on screen available for display.")
1182   ()
1183 {
1184   return make_number (screen_width);
1185 }
1186 
1187 #ifdef SIGWINCH
1188 window_change_signal ()
1189 {
1190   int width, height;
1191   extern int errno;
1192   int old_errno = errno;
1193 
1194   get_screen_size (&width, &height);
1195   /* Record the new size, but don't reallocate the data structures now.
1196      Let that be done later outside of the signal handler.  */
1197   in_display++;
1198   change_screen_size (height, width, 0);
1199   in_display--;
1200   signal (SIGWINCH, window_change_signal);
1201 
1202   errno = old_errno;
1203 }
1204 #endif /* SIGWINCH */
1205 
1206 /* Do any change in screen size that was requested by a signal.  */
1207 
1208 do_pending_window_change ()
1209 {
1210   /* If change_screen_size should have run before, run it now.  */
1211   while (delayed_size_change)
1212     {
1213       int newwidth = delayed_screen_width;
1214       int newheight = delayed_screen_height;
1215       delayed_size_change = 0;
1216       change_screen_size_1 (newheight, newwidth, 0);
1217     }
1218 }
1219 
1220 /* Change the screen height and/or width.  Values may be given as zero to
1221    indicate no change is to take place.
1222    PRETEND is normally 0; 1 means change used-size only
1223    but don't change the size used for calculations;
1224    -1 means don't redisplay.  */
1225 
1226 change_screen_size (newlength, newwidth, pretend)
1227      register int newlength, newwidth, pretend;
1228 {
1229   /* If we can't deal with the change now, queue it for later.  */
1230   if (in_display)
1231     {
1232       delayed_screen_width = newwidth;
1233       delayed_screen_height = newlength;
1234       delayed_size_change = 1;
1235       return;
1236     }
1237   delayed_size_change = 0;
1238   change_screen_size_1 (newlength, newwidth, pretend);
1239 }
1240 
1241 change_screen_size_1 (newlength, newwidth, pretend)
1242      register int newlength, newwidth, pretend;
1243 {
1244   if ((newlength == 0 || newlength == screen_height)
1245       && (newwidth == 0 || newwidth == screen_width))
1246     return;
1247   if (newlength && newlength != screen_height)
1248     {
1249       set_window_height (XWINDOW (minibuf_window)->prev, newlength - 1, 0);
1250       XFASTINT (XWINDOW (minibuf_window)->top) = newlength - 1;
1251       set_window_height (minibuf_window, 1, 0);
1252       screen_height = newlength;
1253       if (pretend <= 0)
1254 	ScreenRows = newlength;
1255       set_terminal_window (0);
1256     }
1257   if (newwidth && newwidth != screen_width)
1258     {
1259       set_window_width (XWINDOW (minibuf_window)->prev, newwidth, 0);
1260       set_window_width (minibuf_window, newwidth, 0);
1261       screen_width = newwidth;
1262       if (pretend <= 0)
1263 	ScreenCols = newwidth;
1264     }
1265   remake_screen_structures ();
1266   screen_garbaged = 1;
1267   calculate_costs ();
1268   if (pretend >= 0)
1269     redisplay_preserve_echo_area ();
1270 }
1271 
1272 DEFUN ("baud-rate", Fbaud_rate, Sbaud_rate, 0, 0, 0,
1273   "Return the output baud rate of the terminal.")
1274   ()
1275 {
1276   Lisp_Object temp;
1277   XSET (temp, Lisp_Int, baud_rate);
1278   return temp;
1279 }
1280 
1281 DEFUN ("send-string-to-terminal", Fsend_string_to_terminal,
1282   Ssend_string_to_terminal, 1, 1, 0,
1283   "Send STRING to the terminal without alteration.\n\
1284 Control characters in STRING will have terminal-dependent effects.")
1285   (str)
1286      Lisp_Object str;
1287 {
1288   CHECK_STRING (str, 0);
1289   fwrite (XSTRING (str)->data, 1, XSTRING (str)->size, stdout);
1290   fflush (stdout);
1291   if (termscript)
1292     {
1293       fwrite (XSTRING (str)->data, 1, XSTRING (str)->size, termscript);
1294       fflush (termscript);
1295     }
1296   return Qnil;
1297 }
1298 
1299 DEFUN ("ding", Fding, Sding, 0, 1, 0,
1300   "Beep, or flash the screen.\n\
1301 Terminates any keyboard macro currently executing unless an argument\n\
1302 is given.")
1303   (arg)
1304   Lisp_Object arg;
1305 {
1306   if (!NULL (arg))
1307     {
1308       bell ();
1309       fflush (stdout);
1310     }
1311   else
1312     bell ();
1313   return Qnil;
1314 }
1315 
1316 bell ()
1317 {
1318   if (noninteractive)
1319     putchar (07);
1320   else if (!FROM_KBD)  /* Stop executing a keyboard macro. */
1321     error ("Keyboard macro terminated by a command ringing the bell");
1322   else
1323     ring_bell ();
1324   fflush (stdout);
1325 }
1326 
1327 DEFUN ("sleep-for", Fsleep_for, Ssleep_for, 1, 1, 0,
1328   "Pause, without updating display, for ARG seconds.")
1329   (n)
1330      Lisp_Object n;
1331 {
1332   register int t;
1333 #ifndef subprocesses
1334 #ifdef HAVE_TIMEVAL
1335   struct timeval timeout, end_time, garbage1;
1336 #endif /* HAVE_TIMEVAL */
1337 #endif /* no subprocesses */
1338 
1339   CHECK_NUMBER (n, 0);
1340   t = XINT (n);
1341   if (t <= 0)
1342     return Qnil;
1343 
1344 #ifdef subprocesses
1345   wait_reading_process_input (t, 0, 0);
1346 #else /* No subprocesses */
1347   immediate_quit = 1;
1348   QUIT;
1349 
1350 #ifdef VMS
1351   sys_sleep (t);
1352 #else /* not VMS */
1353 /* The reason this is done this way
1354     (rather than defined (H_S) && defined (H_T))
1355    is because the VMS preprocessor doesn't grok `defined' */
1356 #ifdef HAVE_SELECT
1357 #ifdef HAVE_TIMEVAL
1358   gettimeofday (&end_time, &garbage1);
1359   end_time.tv_sec += t;
1360 
1361   while (1)
1362     {
1363       gettimeofday (&timeout, &garbage1);
1364       timeout.tv_sec = end_time.tv_sec - timeout.tv_sec;
1365       timeout.tv_usec = end_time.tv_usec - timeout.tv_usec;
1366       if (timeout.tv_usec < 0)
1367 	timeout.tv_usec += 1000000,
1368       timeout.tv_sec--;
1369       if (timeout.tv_sec < 0)
1370 	break;
1371       if (!select (1, 0, 0, 0, &timeout))
1372 	break;
1373     }
1374 #else /* not HAVE_TIMEVAL */
1375   /* Is it safe to quit out of `sleep'?  I'm afraid to trust it.  */
1376   sleep (t);
1377 #endif /* HAVE_TIMEVAL */
1378 #else /* not HAVE_SELECT */
1379   sleep (t);
1380 #endif /* HAVE_SELECT */
1381 #endif /* not VMS */
1382 
1383   immediate_quit = 0;
1384 #endif /* no subprocesses */
1385   return Qnil;
1386 }
1387 
1388 DEFUN ("sit-for", Fsit_for, Ssit_for, 1, 2, 0,
1389   "Perform redisplay, then wait for ARG seconds or until input is available.\n\
1390 Optional second arg non-nil means don't redisplay.\n\
1391 Redisplay is preempted as always if input arrives, and does not happen\n\
1392 if input is available before it starts.\n\
1393 Value is t if waited the full time with no input arriving.")
1394   (n, nodisp)
1395      Lisp_Object n, nodisp;
1396 {
1397 #ifndef subprocesses
1398 #ifdef HAVE_TIMEVAL
1399   struct timeval timeout;
1400 #else
1401   int timeout_sec;
1402 #endif
1403   int waitchannels;
1404 #endif /* no subprocesses */
1405 
1406   CHECK_NUMBER (n, 0);
1407 
1408   if (detect_input_pending ())
1409     return Qnil;
1410 
1411   if (EQ (nodisp, Qnil))
1412     redisplay_preserve_echo_area ();
1413   if (XINT (n) > 0)
1414     {
1415 #ifdef subprocesses
1416 #ifdef SIGIO
1417       gobble_input ();
1418 #endif				/* SIGIO */
1419       wait_reading_process_input (XINT (n), 1, 1);
1420 #else				/* no subprocesses */
1421       immediate_quit = 1;
1422       QUIT;
1423 
1424       waitchannels = 1;
1425 #ifdef VMS
1426       input_wait_timeout (XINT (n));
1427 #else				/* not VMS */
1428 #ifndef HAVE_TIMEVAL
1429       timeout_sec = XINT (n);
1430       select (1, &waitchannels, 0, 0, &timeout_sec);
1431 #else				/* HAVE_TIMEVAL */
1432       timeout.tv_sec = XINT (n);
1433       timeout.tv_usec = 0;
1434       select (1, &waitchannels, 0, 0, &timeout);
1435 #endif				/* HAVE_TIMEVAL */
1436 #endif				/* not VMS */
1437 
1438       immediate_quit = 0;
1439 #endif				/* no subprocesses */
1440     }
1441   return detect_input_pending () ? Qnil : Qt;
1442 }
1443 
1444 char *terminal_type;
1445 
1446 /* Initialization done when Emacs fork is started, before doing stty. */
1447 /* Determine terminal type and set terminal_driver */
1448 /* Then invoke its decoding routine to set up variables
1449   in the terminal package */
1450 
1451 init_display ()
1452 {
1453 #ifdef HAVE_X_WINDOWS
1454   extern Lisp_Object Vxterm;
1455   Vxterm = Qnil;
1456 #endif
1457 
1458   Vwindow_system = Qnil;
1459   meta_key = 0;
1460   inverse_video = 0;
1461   cursor_in_echo_area = 0;
1462   terminal_type = (char *) 0;
1463 
1464   if (!inhibit_window_system)
1465     {
1466 #ifdef HAVE_X_WINDOWS
1467       extern char *alternate_display;
1468       char *disp = (char *) egetenv ("DISPLAY");
1469 
1470       /* Note KSH likes to provide an empty string as an envvar value.  */
1471       if (alternate_display || (disp && *disp))
1472 	{
1473 	  x_term_init ();
1474 	  Vxterm = Qt;
1475 	  Vwindow_system = intern ("x");
1476 #ifdef X11
1477 	  Vwindow_system_version = make_number (11);
1478 #else
1479 	  Vwindow_system_version = make_number (10);
1480 #endif
1481 	  goto term_init_done;
1482 	}
1483 #endif /* HAVE_X_WINDOWS */
1484       ;
1485     }
1486   /* Record we aren't using a window system.  */
1487   inhibit_window_system = 1;
1488 
1489   /* Look at the TERM variable */
1490   terminal_type = (char *) getenv ("TERM");
1491   if (!terminal_type)
1492     {
1493 #ifdef VMS
1494       fprintf (stderr, "Please specify your terminal type.\n\
1495 For types defined in VMS, use  set term /device=TYPE.\n\
1496 For types not defined in VMS, use  define emacs_term \"TYPE\".\n\
1497 \(The quotation marks are necessary since terminal types are lower case.)\n");
1498 #else
1499       fprintf (stderr, "Please set the environment variable TERM; see tset(1).\n");
1500 #endif
1501       exit (1);
1502     }
1503   term_init (terminal_type);
1504 
1505  term_init_done:
1506   remake_screen_structures ();
1507   calculate_costs ();
1508 
1509 #ifdef SIGWINCH
1510 #ifndef CANNOT_DUMP
1511   if (initialized)
1512 #endif /* CANNOT_DUMP */
1513     if (inhibit_window_system)
1514       signal (SIGWINCH, window_change_signal);
1515 #endif /* SIGWINCH */
1516 }
1517 
1518 syms_of_display ()
1519 {
1520   defsubr (&Sopen_termscript);
1521   defsubr (&Sding);
1522   defsubr (&Ssit_for);
1523   defsubr (&Sscreen_height);
1524   defsubr (&Sscreen_width);
1525   defsubr (&Sset_screen_height);
1526   defsubr (&Sset_screen_width);
1527   defsubr (&Ssleep_for);
1528   defsubr (&Sbaud_rate);
1529   defsubr (&Ssend_string_to_terminal);
1530 
1531   DEFVAR_BOOL ("inverse-video", &inverse_video,
1532     "*Non-nil means use inverse-video.");
1533   DEFVAR_BOOL ("visible-bell", &visible_bell,
1534     "*Non-nil means try to flash the screen to represent a bell.");
1535   DEFVAR_BOOL ("no-redraw-on-reenter", &no_redraw_on_reenter,
1536     "*Non-nil means no need to redraw entire screen after suspending.\n\
1537 It is up to you to set this variable to inform Emacs.");
1538   DEFVAR_LISP ("window-system", &Vwindow_system,
1539     "A symbol naming the window-system under which Emacs is running,\n\
1540 \(such as `x'), or nil if emacs is running on an ordinary terminal.");
1541   DEFVAR_LISP ("window-system-version", &Vwindow_system_version,
1542     "Version number of the window system Emacs is running under.");
1543   DEFVAR_BOOL ("cursor-in-echo-area", &cursor_in_echo_area,
1544     "Non-nil means put cursor in minibuffer after any message displayed there.");
1545 
1546   /* Initialize `window-system', unless init_display already decided it.  */
1547 #ifdef CANNOT_DUMP
1548   if (noninteractive)
1549 #endif
1550     {
1551       Vwindow_system_version = Qnil;
1552       Vwindow_system = Qnil;
1553     }
1554 }
1555