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