1/* $NetBSD: terminal.c,v 1.10 2008/09/02 08:00:24 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. */ 45char *BC, *UP; 46char PC; /* Pad character */ 47short ospeed; /* Terminal output baud rate */ 48extern int tgetnum (), tgetflag (), tgetent (); 49extern char *tgetstr (), *tgoto (); 50extern 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. */ 58VFunction *terminal_begin_inverse_hook = (VFunction *)NULL; 59VFunction *terminal_end_inverse_hook = (VFunction *)NULL; 60VFunction *terminal_prep_terminal_hook = (VFunction *)NULL; 61VFunction *terminal_unprep_terminal_hook = (VFunction *)NULL; 62VFunction *terminal_up_line_hook = (VFunction *)NULL; 63VFunction *terminal_down_line_hook = (VFunction *)NULL; 64VFunction *terminal_clear_screen_hook = (VFunction *)NULL; 65VFunction *terminal_clear_to_eol_hook = (VFunction *)NULL; 66VFunction *terminal_get_screen_size_hook = (VFunction *)NULL; 67VFunction *terminal_goto_xy_hook = (VFunction *)NULL; 68VFunction *terminal_initialize_terminal_hook = (VFunction *)NULL; 69VFunction *terminal_new_terminal_hook = (VFunction *)NULL; 70VFunction *terminal_put_text_hook = (VFunction *)NULL; 71VFunction *terminal_ring_bell_hook = (VFunction *)NULL; 72VFunction *terminal_write_chars_hook = (VFunction *)NULL; 73VFunction *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. */ 83static char *term_buffer = NULL; 84static char *term_string_buffer = NULL; 85static char *term_name; 86 87/* Some strings to control terminal actions. These are output by tputs (). */ 88static char *term_goto, *term_clreol, *term_cr, *term_clrpag; 89static char *term_begin_use, *term_end_use; 90static char *term_AL, *term_DL, *term_al, *term_dl; 91 92static char *term_keypad_on, *term_keypad_off; 93 94/* How to go up a line. */ 95static char *term_up; 96 97/* How to go down a line. */ 98static char *term_dn; 99 100/* An audible bell, if the terminal can be made to make noise. */ 101static char *audible_bell; 102 103/* A visible bell, if the terminal can be made to flash the screen. */ 104static char *visible_bell; 105 106/* The string to write to turn on the meta key, if this term has one. */ 107static char *term_mm; 108 109/* The string to turn on inverse mode, if this term has one. */ 110static char *term_invbeg; 111 112/* The string to turn off inverse mode, if this term has one. */ 113static 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. */ 118static int 119output_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. */ 133static void 134terminal_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. */ 164static void 165terminal_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. */ 200int screenwidth, screenheight; 201 202/* Non-zero means this terminal can't really do anything. */ 203int terminal_is_dumb_p = 0; 204 205/* Non-zero means that this terminal has a meta key. */ 206int terminal_has_meta_p = 0; 207 208/* Non-zero means that this terminal can produce a visible bell. */ 209int terminal_has_visible_bell_p = 0; 210 211/* Non-zero means to use that visible bell if at all possible. */ 212int terminal_use_visible_bell_p = 0; 213 214/* Non-zero means that the terminal can do scrolling. */ 215int terminal_can_scroll = 0; 216 217/* The key sequences output by the arrow keys, if this terminal has any. */ 218char *term_ku = NULL; 219char *term_kd = NULL; 220char *term_kr = NULL; 221char *term_kl = NULL; 222char *term_kP = NULL; /* page-up */ 223char *term_kN = NULL; /* page-down */ 224char *term_kh = NULL; /* home */ 225char *term_ke = NULL; /* end */ 226char *term_kD = NULL; /* delete */ 227char *term_ki = NULL; /* ins */ 228char *term_kx = NULL; /* del */ 229 230/* Move the cursor to the terminal location of X and Y. */ 231void 232terminal_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. */ 244void 245terminal_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. */ 256void 257terminal_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. */ 269void 270terminal_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. */ 281void 282terminal_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. */ 293void 294terminal_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. */ 305void 306terminal_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. */ 317void 318terminal_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. */ 329void 330terminal_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. */ 342void 343terminal_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. */ 357static void 358terminal_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. */ 380static void 381terminal_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. */ 407void 408terminal_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. */ 443void 444terminal_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. */ 455void 456terminal_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. */ 515void 516terminal_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) 661struct termios original_termios, ttybuff; 662#else 663# if defined (HAVE_TERMIO_H) 664/* A buffer containing the terminal mode flags upon entry to info. */ 665struct termio original_termio, ttybuff; 666# else /* !HAVE_TERMIO_H */ 667/* Buffers containing the terminal mode flags upon entry to info. */ 668int original_tty_flags = 0; 669int original_lmode; 670struct 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. */ 682struct tchars original_tchars; 683# endif 684 685# if defined (TIOCGLTC) 686/* A buffer containing the local terminal mode characters upon entry 687 to Info. */ 688struct 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. */ 694void 695terminal_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. */ 834void 835terminal_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