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