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