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