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