Add the DragonFly cvs id and perform general cleanups on cvs/rcs/sccs ids. Most
[dragonfly.git] / contrib / texinfo / info / terminal.c
1 /* $FreeBSD: src/contrib/texinfo/info/terminal.c,v 1.6.2.1 2002/03/30 17:09:19 ru Exp $ */
2 /* $DragonFly: src/contrib/texinfo/info/Attic/terminal.c,v 1.2 2003/06/17 04:24:07 dillon Exp $ */
3 /* terminal.c -- How to handle the physical terminal for Info.
4    $Id: terminal.c,v 1.23 2001/11/16 23:16:04 karl Exp $
5
6    Copyright (C) 1988, 89, 90, 91, 92, 93, 96, 97, 98, 99, 2001
7    Free Software Foundation, Inc.
8
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 2, or (at your option)
12    any later version.
13
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18
19    You should have received a copy of the GNU General Public License
20    along with this program; if not, write to the Free Software
21    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22
23    Written by Brian Fox (bfox@ai.mit.edu). */
24
25 #include "info.h"
26 #include "terminal.h"
27 #include "termdep.h"
28
29 #include <sys/types.h>
30 #include <signal.h>
31
32 /* The Unix termcap interface code. */
33 #ifdef HAVE_NCURSES_TERMCAP_H
34 #include <ncurses/termcap.h>
35 #else
36 #ifdef HAVE_TERMCAP_H
37 #include <termcap.h>
38 #else
39 /* On Solaris2, sys/types.h #includes sys/reg.h, which #defines PC.
40    Unfortunately, PC is a global variable used by the termcap library. */
41 #undef PC
42
43 /* Termcap requires these variables, whether we access them or not. */
44 char *BC, *UP;
45 char PC;      /* Pad character */
46 short ospeed; /* Terminal output baud rate */
47 extern int tgetnum (), tgetflag (), tgetent ();
48 extern char *tgetstr (), *tgoto ();
49 extern void tputs ();
50 #endif /* not HAVE_TERMCAP_H */
51 #endif /* not HAVE_NCURSES_TERMCAP_H */
52
53 /* Function "hooks".  If you make one of these point to a function, that
54    function is called when appropriate instead of its namesake.  Your
55    function is called with exactly the same arguments that were passed
56    to the namesake function. */
57 VFunction *terminal_begin_inverse_hook = (VFunction *)NULL;
58 VFunction *terminal_end_inverse_hook = (VFunction *)NULL;
59 VFunction *terminal_prep_terminal_hook = (VFunction *)NULL;
60 VFunction *terminal_unprep_terminal_hook = (VFunction *)NULL;
61 VFunction *terminal_up_line_hook = (VFunction *)NULL;
62 VFunction *terminal_down_line_hook = (VFunction *)NULL;
63 VFunction *terminal_clear_screen_hook = (VFunction *)NULL;
64 VFunction *terminal_clear_to_eol_hook = (VFunction *)NULL;
65 VFunction *terminal_get_screen_size_hook = (VFunction *)NULL;
66 VFunction *terminal_goto_xy_hook = (VFunction *)NULL;
67 VFunction *terminal_initialize_terminal_hook = (VFunction *)NULL;
68 VFunction *terminal_new_terminal_hook = (VFunction *)NULL;
69 VFunction *terminal_put_text_hook = (VFunction *)NULL;
70 VFunction *terminal_ring_bell_hook = (VFunction *)NULL;
71 VFunction *terminal_write_chars_hook = (VFunction *)NULL;
72 VFunction *terminal_scroll_terminal_hook = (VFunction *)NULL;
73
74 /* **************************************************************** */
75 /*                                                                  */
76 /*                      Terminal and Termcap                        */
77 /*                                                                  */
78 /* **************************************************************** */
79
80 /* A buffer which holds onto the current terminal description, and a pointer
81    used to float within it.  And the name of the terminal.  */
82 static char *term_buffer = NULL;
83 static char *term_string_buffer = NULL;
84 static char *term_name;
85
86 /* Some strings to control terminal actions.  These are output by tputs (). */
87 static char *term_goto, *term_clreol, *term_cr, *term_clrpag;
88 static char *term_begin_use, *term_end_use;
89 static char *term_AL, *term_DL, *term_al, *term_dl;
90
91 static char *term_keypad_on, *term_keypad_off;
92
93 /* How to go up a line. */
94 static char *term_up;
95
96 /* How to go down a line. */
97 static char *term_dn;
98
99 /* An audible bell, if the terminal can be made to make noise. */
100 static char *audible_bell;
101
102 /* A visible bell, if the terminal can be made to flash the screen. */
103 static char *visible_bell;
104
105 /* The string to write to turn on the meta key, if this term has one. */
106 static char *term_mm;
107
108 /* The string to write to turn off the meta key, if this term has one. */
109 static char *term_mo;
110
111 /* The string to turn on inverse mode, if this term has one. */
112 static char *term_invbeg;
113
114 /* The string to turn off inverse mode, if this term has one. */
115 static char *term_invend;
116
117 /* Although I can't find any documentation that says this is supposed to
118    return its argument, all the code I've looked at (termutils, less)
119    does so, so fine.  */
120 static int
121 output_character_function (c)
122      int c;
123 {
124   putc (c, stdout);
125   return c;
126 }
127
128 /* Macro to send STRING to the terminal. */
129 #define send_to_terminal(string) \
130   do { \
131     if (string) \
132       tputs (string, 1, output_character_function); \
133      } while (0)
134
135 /* Tell the terminal that we will be doing cursor addressable motion.  */
136 static void
137 terminal_begin_using_terminal ()
138 {
139   RETSIGTYPE (*sigsave) ();
140
141   if (term_keypad_on)
142       send_to_terminal (term_keypad_on);
143   
144   if (!term_begin_use || !*term_begin_use)
145     return;
146
147 #ifdef SIGWINCH
148   sigsave = signal (SIGWINCH, SIG_IGN); 
149 #endif
150
151   send_to_terminal (term_begin_use);
152   fflush (stdout);
153   if (STREQ (term_name, "sun-cmd"))
154     /* Without this fflush and sleep, running info in a shelltool or
155        cmdtool (TERM=sun-cmd) with scrollbars loses -- the scrollbars are
156        not restored properly.
157        From: strube@physik3.gwdg.de (Hans Werner Strube).  */
158     sleep (1);
159
160 #ifdef SIGWINCH
161   signal (SIGWINCH, sigsave);
162 #endif
163 }
164
165 /* Tell the terminal that we will not be doing any more cursor
166    addressable motion. */
167 static void
168 terminal_end_using_terminal ()
169 {
170   RETSIGTYPE (*sigsave) ();
171
172   if (term_keypad_off)
173       send_to_terminal (term_keypad_off);
174   
175   if (!term_end_use || !*term_end_use)
176     return;
177
178 #ifdef SIGWINCH
179   sigsave = signal (SIGWINCH, SIG_IGN);
180 #endif
181
182   send_to_terminal (term_end_use);
183   fflush (stdout);
184   if (STREQ (term_name, "sun-cmd"))
185     /* See comments at other sleep.  */
186     sleep (1);
187
188 #ifdef SIGWINCH
189   signal (SIGWINCH, sigsave);
190 #endif
191 }
192 \f
193 /* **************************************************************** */
194 /*                                                                  */
195 /*                   Necessary Terminal Functions                   */
196 /*                                                                  */
197 /* **************************************************************** */
198
199 /* The functions and variables on this page implement the user visible
200    portion of the terminal interface. */
201
202 /* The width and height of the terminal. */
203 int screenwidth, screenheight;
204
205 /* Non-zero means this terminal can't really do anything. */
206 int terminal_is_dumb_p = 0;
207
208 /* Non-zero means that this terminal has a meta key. */
209 int terminal_has_meta_p = 0;
210
211 /* Non-zero means that this terminal can produce a visible bell. */
212 int terminal_has_visible_bell_p = 0;
213
214 /* Non-zero means to use that visible bell if at all possible. */
215 int terminal_use_visible_bell_p = 0;
216
217 /* Non-zero means that the terminal can do scrolling. */
218 int terminal_can_scroll = 0;
219
220 /* The key sequences output by the arrow keys, if this terminal has any. */
221 char *term_ku = NULL;
222 char *term_kd = NULL;
223 char *term_kr = NULL;
224 char *term_kl = NULL;
225 char *term_kP = NULL;   /* page-up */
226 char *term_kN = NULL;   /* page-down */
227 char *term_kh = NULL;   /* home */
228 char *term_ke = NULL;   /* end */
229 char *term_kD = NULL;   /* delete */
230 char *term_ki = NULL;   /* ins */
231 char *term_kx = NULL;   /* del */
232
233 /* Move the cursor to the terminal location of X and Y. */
234 void
235 terminal_goto_xy (x, y)
236      int x, y;
237 {
238   if (terminal_goto_xy_hook)
239     (*terminal_goto_xy_hook) (x, y);
240   else
241     {
242       if (term_goto)
243         tputs (tgoto (term_goto, x, y), 1, output_character_function);
244     }
245 }
246
247 /* Print STRING to the terminal at the current position. */
248 void
249 terminal_put_text (string)
250      char *string;
251 {
252   if (terminal_put_text_hook)
253     (*terminal_put_text_hook) (string);
254   else
255     {
256       printf ("%s", string);
257     }
258 }
259
260 /* Print NCHARS from STRING to the terminal at the current position. */
261 void
262 terminal_write_chars (string, nchars)
263      char *string;
264      int nchars;
265 {
266   if (terminal_write_chars_hook)
267     (*terminal_write_chars_hook) (string, nchars);
268   else
269     {
270       if (nchars)
271         fwrite (string, 1, nchars, stdout);
272     }
273 }
274
275 /* Clear from the current position of the cursor to the end of the line. */
276 void
277 terminal_clear_to_eol ()
278 {
279   if (terminal_clear_to_eol_hook)
280     (*terminal_clear_to_eol_hook) ();
281   else
282     {
283       send_to_terminal (term_clreol);
284     }
285 }
286
287 /* Clear the entire terminal screen. */
288 void
289 terminal_clear_screen ()
290 {
291   if (terminal_clear_screen_hook)
292     (*terminal_clear_screen_hook) ();
293   else
294     {
295       send_to_terminal (term_clrpag);
296     }
297 }
298
299 /* Move the cursor up one line. */
300 void
301 terminal_up_line ()
302 {
303   if (terminal_up_line_hook)
304     (*terminal_up_line_hook) ();
305   else
306     {
307       send_to_terminal (term_up);
308     }
309 }
310
311 /* Move the cursor down one line. */
312 void
313 terminal_down_line ()
314 {
315   if (terminal_down_line_hook)
316     (*terminal_down_line_hook) ();
317   else
318     {
319       send_to_terminal (term_dn);
320     }
321 }
322
323 /* Turn on reverse video if possible. */
324 void
325 terminal_begin_inverse ()
326 {
327   if (terminal_begin_inverse_hook)
328     (*terminal_begin_inverse_hook) ();
329   else
330     {
331       send_to_terminal (term_invbeg);
332     }
333 }
334
335 /* Turn off reverse video if possible. */
336 void
337 terminal_end_inverse ()
338 {
339   if (terminal_end_inverse_hook)
340     (*terminal_end_inverse_hook) ();
341   else
342     {
343       send_to_terminal (term_invend);
344     }
345 }
346
347 /* Ring the terminal bell.  The bell is run visibly if it both has one and
348    terminal_use_visible_bell_p is non-zero. */
349 void
350 terminal_ring_bell ()
351 {
352   if (terminal_ring_bell_hook)
353     (*terminal_ring_bell_hook) ();
354   else
355     {
356       if (terminal_has_visible_bell_p && terminal_use_visible_bell_p)
357         send_to_terminal (visible_bell);
358       else
359         send_to_terminal (audible_bell);
360     }
361 }
362
363 /* At the line START, delete COUNT lines from the terminal display. */
364 static void
365 terminal_delete_lines (start, count)
366      int start, count;
367 {
368   int lines;
369
370   /* Normalize arguments. */
371   if (start < 0)
372     start = 0;
373
374   lines = screenheight - start;
375   terminal_goto_xy (0, start);
376   if (term_DL)
377     tputs (tgoto (term_DL, 0, count), lines, output_character_function);
378   else
379     {
380       while (count--)
381         tputs (term_dl, lines, output_character_function);
382     }
383
384   fflush (stdout);
385 }
386
387 /* At the line START, insert COUNT lines in the terminal display. */
388 static void
389 terminal_insert_lines (start, count)
390      int start, count;
391 {
392   int lines;
393
394   /* Normalize arguments. */
395   if (start < 0)
396     start = 0;
397
398   lines = screenheight - start;
399   terminal_goto_xy (0, start);
400
401   if (term_AL)
402     tputs (tgoto (term_AL, 0, count), lines, output_character_function);
403   else
404     {
405       while (count--)
406         tputs (term_al, lines, output_character_function);
407     }
408
409   fflush (stdout);
410 }
411
412 /* Scroll an area of the terminal, starting with the region from START
413    to END, AMOUNT lines.  If AMOUNT is negative, the lines are scrolled
414    towards the top of the screen, else they are scrolled towards the
415    bottom of the screen. */
416 void
417 terminal_scroll_terminal (start, end, amount)
418      int start, end, amount;
419 {
420   if (!terminal_can_scroll)
421     return;
422
423   /* Any scrolling at all? */
424   if (amount == 0)
425     return;
426
427   if (terminal_scroll_terminal_hook)
428     (*terminal_scroll_terminal_hook) (start, end, amount);
429   else
430     {
431       /* If we are scrolling down, delete AMOUNT lines at END.  Then insert
432          AMOUNT lines at START. */
433       if (amount > 0)
434         {
435           terminal_delete_lines (end, amount);
436           terminal_insert_lines (start, amount);
437         }
438
439       /* If we are scrolling up, delete AMOUNT lines before START.  This
440          actually does the upwards scroll.  Then, insert AMOUNT lines
441          after the already scrolled region (i.e., END - AMOUNT). */
442       if (amount < 0)
443         {
444           int abs_amount = -amount;
445           terminal_delete_lines (start - abs_amount, abs_amount);
446           terminal_insert_lines (end - abs_amount, abs_amount);
447         }
448     }
449 }
450
451 /* Re-initialize the terminal considering that the TERM/TERMCAP variable
452    has changed. */
453 void
454 terminal_new_terminal (terminal_name)
455      char *terminal_name;
456 {
457   if (terminal_new_terminal_hook)
458     (*terminal_new_terminal_hook) (terminal_name);
459   else
460     {
461       terminal_initialize_terminal (terminal_name);
462     }
463 }
464
465 /* Set the global variables SCREENWIDTH and SCREENHEIGHT. */
466 void
467 terminal_get_screen_size ()
468 {
469   if (terminal_get_screen_size_hook)
470     (*terminal_get_screen_size_hook) ();
471   else
472     {
473       screenwidth = screenheight = 0;
474
475 #if defined (TIOCGWINSZ)
476       {
477         struct winsize window_size;
478
479         if (ioctl (fileno (stdout), TIOCGWINSZ, &window_size) == 0)
480           {
481             screenwidth = (int) window_size.ws_col;
482             screenheight = (int) window_size.ws_row;
483           }
484       }
485 #endif                          /* TIOCGWINSZ */
486
487       /* Environment variable COLUMNS overrides setting of "co". */
488       if (screenwidth <= 0)
489         {
490           char *sw = getenv ("COLUMNS");
491
492           if (sw)
493             screenwidth = atoi (sw);
494
495           if (screenwidth <= 0)
496             screenwidth = tgetnum ("co");
497         }
498
499       /* Environment variable LINES overrides setting of "li". */
500       if (screenheight <= 0)
501         {
502           char *sh = getenv ("LINES");
503
504           if (sh)
505             screenheight = atoi (sh);
506
507           if (screenheight <= 0)
508             screenheight = tgetnum ("li");
509         }
510
511       /* If all else fails, default to 80x24 terminal. */
512       if (screenwidth <= 0)
513         screenwidth = 80;
514
515       if (screenheight <= 0)
516         screenheight = 24;
517     }
518 }
519
520 /* Initialize the terminal which is known as TERMINAL_NAME.  If this
521    terminal doesn't have cursor addressability, `terminal_is_dumb_p'
522    becomes nonzero.  The variables SCREENHEIGHT and SCREENWIDTH are set
523    to the dimensions that this terminal actually has.  The variable
524    TERMINAL_HAS_META_P becomes nonzero if this terminal supports a Meta
525    key.  Finally, the terminal screen is cleared. */
526 void
527 terminal_initialize_terminal (terminal_name)
528      char *terminal_name;
529 {
530   char *buffer;
531
532   terminal_is_dumb_p = 0;
533
534   if (terminal_initialize_terminal_hook)
535     {
536       (*terminal_initialize_terminal_hook) (terminal_name);
537       return;
538     }
539
540   term_name = terminal_name ? terminal_name : getenv ("TERM");
541   if (!term_name)
542     term_name = "dumb";
543
544   if (!term_string_buffer)
545     term_string_buffer = xmalloc (2048);
546
547   if (!term_buffer)
548     term_buffer = xmalloc (2048);
549
550   buffer = term_string_buffer;
551
552   term_clrpag = term_cr = term_clreol = NULL;
553
554   /* HP-UX 11.x returns 0 for OK --jeff.hull@state.co.us.  */
555   if (tgetent (term_buffer, term_name) < 0)
556     {
557       terminal_is_dumb_p = 1;
558       screenwidth = 80;
559       screenheight = 24;
560       term_cr = "\r";
561       term_up = term_dn = audible_bell = visible_bell = NULL;
562       term_ku = term_kd = term_kl = term_kr = NULL;
563       term_kP = term_kN = NULL;
564       term_kh = term_ke = NULL;
565       term_kD = NULL;
566       return;
567     }
568
569   BC = tgetstr ("pc", &buffer);
570   PC = BC ? *BC : 0;
571
572 #if defined (HAVE_TERMIOS_H)
573   {
574     struct termios ti;
575     if (tcgetattr (fileno(stdout), &ti) != -1)
576       ospeed = cfgetospeed (&ti);
577     else
578       ospeed = B9600;
579   }
580 #else
581 # if defined (TIOCGETP)
582   {
583     struct sgttyb sg;
584
585     if (ioctl (fileno (stdout), TIOCGETP, &sg) != -1)
586       ospeed = sg.sg_ospeed;
587     else
588       ospeed = B9600;
589   }
590 # else
591   ospeed = B9600;
592 # endif /* !TIOCGETP */
593 #endif
594
595   term_cr = tgetstr ("cr", &buffer);
596   term_clreol = tgetstr ("ce", &buffer);
597   term_clrpag = tgetstr ("cl", &buffer);
598   term_goto = tgetstr ("cm", &buffer);
599
600   /* Find out about this terminal's scrolling capability. */
601   term_AL = tgetstr ("AL", &buffer);
602   term_DL = tgetstr ("DL", &buffer);
603   term_al = tgetstr ("al", &buffer);
604   term_dl = tgetstr ("dl", &buffer);
605
606   terminal_can_scroll = ((term_AL || term_al) && (term_DL || term_dl));
607
608   term_invbeg = tgetstr ("mr", &buffer);
609   if (term_invbeg)
610     term_invend = tgetstr ("me", &buffer);
611   else
612     term_invend = NULL;
613
614   if (!term_cr)
615     term_cr =  "\r";
616
617   terminal_get_screen_size ();
618
619   term_up = tgetstr ("up", &buffer);
620   term_dn = tgetstr ("dn", &buffer);
621   visible_bell = tgetstr ("vb", &buffer);
622   terminal_has_visible_bell_p = (visible_bell != NULL);
623   audible_bell = tgetstr ("bl", &buffer);
624   if (!audible_bell)
625     audible_bell = "\007";
626   term_begin_use = tgetstr ("ti", &buffer);
627   term_end_use = tgetstr ("te", &buffer);
628
629   term_keypad_on = tgetstr ("ks", &buffer);
630   term_keypad_off = tgetstr ("ke", &buffer);
631
632   /* Check to see if this terminal has a meta key. */
633   terminal_has_meta_p = (tgetflag ("km") || tgetflag ("MT"));
634   if (terminal_has_meta_p)
635     {
636       term_mm = tgetstr ("mm", &buffer);
637       term_mo = tgetstr ("mo", &buffer);
638     }
639   else
640     {
641       term_mm = NULL;
642       term_mo = NULL;
643     }
644
645   /* Attempt to find the arrow keys.  */
646   term_ku = tgetstr ("ku", &buffer);
647   term_kd = tgetstr ("kd", &buffer);
648   term_kr = tgetstr ("kr", &buffer);
649   term_kl = tgetstr ("kl", &buffer);
650
651   term_kP = tgetstr ("kP", &buffer);
652   term_kN = tgetstr ("kN", &buffer);
653
654 #if defined(INFOKEY)
655   term_kh = tgetstr ("kh", &buffer);
656   term_ke = tgetstr ("@7", &buffer);
657   term_ki = tgetstr ("kI", &buffer);
658   term_kx = tgetstr ("kD", &buffer);
659 #endif /* defined(INFOKEY) */
660
661   /* Home and end keys. */
662   term_kh = tgetstr ("kh", &buffer);
663   term_ke = tgetstr ("@7", &buffer);
664
665   term_kD = tgetstr ("kD", &buffer);
666
667   /* If this terminal is not cursor addressable, then it is really dumb. */
668   if (!term_goto)
669     terminal_is_dumb_p = 1;
670 }
671 \f
672 /* How to read characters from the terminal.  */
673
674 #if defined (HAVE_TERMIOS_H)
675 struct termios original_termios, ttybuff;
676 #else
677 #  if defined (HAVE_TERMIO_H)
678 /* A buffer containing the terminal mode flags upon entry to info. */
679 struct termio original_termio, ttybuff;
680 #  else /* !HAVE_TERMIO_H */
681 /* Buffers containing the terminal mode flags upon entry to info. */
682 int original_tty_flags = 0;
683 int original_lmode;
684 struct sgttyb ttybuff;
685
686 #    if defined(TIOCGETC) && defined(M_XENIX)
687 /* SCO 3.2v5.0.2 defines but does not support TIOCGETC.  Gak.  Maybe
688    better fix would be to use Posix termios in preference.  --gildea,
689    1jul99.  */
690 #      undef TIOCGETC
691 #    endif
692
693 #    if defined (TIOCGETC)
694 /* A buffer containing the terminal interrupt characters upon entry
695    to Info. */
696 struct tchars original_tchars;
697 #    endif
698
699 #    if defined (TIOCGLTC)
700 /* A buffer containing the local terminal mode characters upon entry
701    to Info. */
702 struct ltchars original_ltchars;
703 #    endif
704 #  endif /* !HAVE_TERMIO_H */
705 #endif /* !HAVE_TERMIOS_H */
706
707 /* Prepare to start using the terminal to read characters singly. */
708 void
709 terminal_prep_terminal ()
710 {
711   int tty;
712
713   if (terminal_prep_terminal_hook)
714     {
715       (*terminal_prep_terminal_hook) ();
716       return;
717     }
718
719   terminal_begin_using_terminal ();
720
721   tty = fileno (stdin);
722
723 #if defined (HAVE_TERMIOS_H)
724   tcgetattr (tty, &original_termios);
725   tcgetattr (tty, &ttybuff);
726 #else
727 #  if defined (HAVE_TERMIO_H)
728   ioctl (tty, TCGETA, &original_termio);
729   ioctl (tty, TCGETA, &ttybuff);
730 #  endif
731 #endif
732
733 #if defined (HAVE_TERMIOS_H) || defined (HAVE_TERMIO_H)
734   ttybuff.c_iflag &= (~ISTRIP & ~INLCR & ~IGNCR & ~ICRNL & ~IXON);
735 /* These output flags are not part of POSIX, so only use them if they
736    are defined.  */
737 #ifdef ONLCR
738   ttybuff.c_oflag &= ~ONLCR ;
739 #endif
740 #ifdef OCRNL
741   ttybuff.c_oflag &= ~OCRNL;
742 #endif
743   ttybuff.c_lflag &= (~ICANON & ~ECHO);
744
745   ttybuff.c_cc[VMIN] = 1;
746   ttybuff.c_cc[VTIME] = 0;
747
748   if (ttybuff.c_cc[VINTR] == '\177')
749     ttybuff.c_cc[VINTR] = -1;
750
751   if (ttybuff.c_cc[VQUIT] == '\177')
752     ttybuff.c_cc[VQUIT] = -1;
753
754 #ifdef VLNEXT
755   if (ttybuff.c_cc[VLNEXT] == '\026')
756     ttybuff.c_cc[VLNEXT] = -1;
757 #endif /* VLNEXT */
758 #endif /* TERMIOS or TERMIO */
759
760 /* cf. emacs/src/sysdep.c for being sure output is on. */
761 #if defined (HAVE_TERMIOS_H)
762   /* linux kernel 2.2.x needs a TCOFF followed by a TCOON to turn output
763      back on if the user presses ^S at the very beginning; just a TCOON
764      doesn't work.  --Kevin Ryde <user42@zip.com.au>, 16jun2000.  */
765   tcsetattr (tty, TCSANOW, &ttybuff);
766 #  ifdef TCOON
767   tcflow (tty, TCOOFF);
768   tcflow (tty, TCOON);
769 #  endif
770 #else
771 #  if defined (HAVE_TERMIO_H)
772   ioctl (tty, TCSETA, &ttybuff);
773 #    ifdef TCXONC
774   ioctl (tty, TCXONC, 1);
775 #    endif
776 #  endif
777 #endif
778
779 #if !defined (HAVE_TERMIOS_H) && !defined (HAVE_TERMIO_H)
780   ioctl (tty, TIOCGETP, &ttybuff);
781
782   if (!original_tty_flags)
783     original_tty_flags = ttybuff.sg_flags;
784
785   /* Make this terminal pass 8 bits around while we are using it. */
786 #  if defined (PASS8)
787   ttybuff.sg_flags |= PASS8;
788 #  endif /* PASS8 */
789
790 #  if defined (TIOCLGET) && defined (LPASS8)
791   {
792     int flags;
793     ioctl (tty, TIOCLGET, &flags);
794     original_lmode = flags;
795     flags |= LPASS8;
796     ioctl (tty, TIOCLSET, &flags);
797   }
798 #  endif /* TIOCLGET && LPASS8 */
799
800 #  if defined (TIOCGETC)
801   {
802     struct tchars temp;
803
804     ioctl (tty, TIOCGETC, &original_tchars);
805     temp = original_tchars;
806
807     /* C-s and C-q. */
808     temp.t_startc = temp.t_stopc = -1;
809
810     /* Often set to C-d. */
811     temp.t_eofc = -1;
812
813     /* If the a quit or interrupt character conflicts with one of our
814        commands, then make it go away. */
815     if (temp.t_intrc == '\177')
816       temp.t_intrc = -1;
817
818     if (temp.t_quitc == '\177')
819       temp.t_quitc = -1;
820
821     ioctl (tty, TIOCSETC, &temp);
822   }
823 #  endif /* TIOCGETC */
824
825 #  if defined (TIOCGLTC)
826   {
827     struct ltchars temp;
828
829     ioctl (tty, TIOCGLTC, &original_ltchars);
830     temp = original_ltchars;
831
832     /* Make the interrupt keys go away.  Just enough to make people happy. */
833     temp.t_lnextc = -1;         /* C-v. */
834     temp.t_dsuspc = -1;         /* C-y. */
835     temp.t_flushc = -1;         /* C-o. */
836     ioctl (tty, TIOCSLTC, &temp);
837   }
838 #  endif /* TIOCGLTC */
839
840   ttybuff.sg_flags &= ~ECHO;
841   ttybuff.sg_flags |= CBREAK;
842   ioctl (tty, TIOCSETN, &ttybuff);
843 #endif /* !HAVE_TERMIOS_H && !HAVE_TERMIO_H */
844 }
845
846 /* Restore the tty settings back to what they were before we started using
847    this terminal. */
848 void
849 terminal_unprep_terminal ()
850 {
851   int tty;
852
853   if (terminal_unprep_terminal_hook)
854     {
855       (*terminal_unprep_terminal_hook) ();
856       return;
857     }
858
859   tty = fileno (stdin);
860
861 #if defined (HAVE_TERMIOS_H)
862   tcsetattr (tty, TCSANOW, &original_termios);
863 #else
864 #  if defined (HAVE_TERMIO_H)
865   ioctl (tty, TCSETA, &original_termio);
866 #  else /* !HAVE_TERMIO_H */
867   ioctl (tty, TIOCGETP, &ttybuff);
868   ttybuff.sg_flags = original_tty_flags;
869   ioctl (tty, TIOCSETN, &ttybuff);
870
871 #  if defined (TIOCGETC)
872   ioctl (tty, TIOCSETC, &original_tchars);
873 #  endif /* TIOCGETC */
874
875 #  if defined (TIOCGLTC)
876   ioctl (tty, TIOCSLTC, &original_ltchars);
877 #  endif /* TIOCGLTC */
878
879 #  if defined (TIOCLGET) && defined (LPASS8)
880   ioctl (tty, TIOCLSET, &original_lmode);
881 #  endif /* TIOCLGET && LPASS8 */
882
883 #  endif /* !HAVE_TERMIO_H */
884 #endif /* !HAVE_TERMIOS_H */
885   terminal_end_using_terminal ();
886 }
887
888 #ifdef __MSDOS__
889 # include "pcterm.c"
890 #endif