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