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