home *** CD-ROM | disk | FTP | other *** search
/ Dream 52 / Amiga_Dream_52.iso / OS2 / gnuinfo.zip / info / terminal.c < prev    next >
C/C++ Source or Header  |  1997-12-29  |  23KB  |  870 lines

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