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