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