Back to index

tetex-bin  3.0
terminal.c
Go to the documentation of this file.
00001 /* terminal.c -- how to handle the physical terminal for Info.
00002    $Id: terminal.c,v 1.3 2004/04/11 17:56:46 karl Exp $
00003 
00004    Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1996, 1997, 1998,
00005    1999, 2001, 2002, 2004 Free Software Foundation, Inc.
00006 
00007    This program is free software; you can redistribute it and/or modify
00008    it under the terms of the GNU General Public License as published by
00009    the Free Software Foundation; either version 2, or (at your option)
00010    any later version.
00011 
00012    This program is distributed in the hope that it will be useful,
00013    but WITHOUT ANY WARRANTY; without even the implied warranty of
00014    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015    GNU General Public License for more details.
00016 
00017    You should have received a copy of the GNU General Public License
00018    along with this program; if not, write to the Free Software
00019    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00020 
00021    Originally written by Brian Fox (bfox@ai.mit.edu). */
00022 
00023 #include "info.h"
00024 #include "terminal.h"
00025 #include "termdep.h"
00026 
00027 #include <sys/types.h>
00028 #include <signal.h>
00029 
00030 /* The Unix termcap interface code. */
00031 #ifdef HAVE_NCURSES_TERMCAP_H
00032 #include <ncurses/termcap.h>
00033 #else
00034 #ifdef HAVE_TERMCAP_H
00035 #include <termcap.h>
00036 #else
00037 /* On Solaris2, sys/types.h #includes sys/reg.h, which #defines PC.
00038    Unfortunately, PC is a global variable used by the termcap library. */
00039 #undef PC
00040 
00041 /* Termcap requires these variables, whether we access them or not. */
00042 char *BC, *UP;
00043 char PC;      /* Pad character */
00044 short ospeed; /* Terminal output baud rate */
00045 extern int tgetnum (), tgetflag (), tgetent ();
00046 extern char *tgetstr (), *tgoto ();
00047 extern void tputs ();
00048 #endif /* not HAVE_TERMCAP_H */
00049 #endif /* not HAVE_NCURSES_TERMCAP_H */
00050 
00051 /* Function "hooks".  If you make one of these point to a function, that
00052    function is called when appropriate instead of its namesake.  Your
00053    function is called with exactly the same arguments that were passed
00054    to the namesake function. */
00055 VFunction *terminal_begin_inverse_hook = (VFunction *)NULL;
00056 VFunction *terminal_end_inverse_hook = (VFunction *)NULL;
00057 VFunction *terminal_prep_terminal_hook = (VFunction *)NULL;
00058 VFunction *terminal_unprep_terminal_hook = (VFunction *)NULL;
00059 VFunction *terminal_up_line_hook = (VFunction *)NULL;
00060 VFunction *terminal_down_line_hook = (VFunction *)NULL;
00061 VFunction *terminal_clear_screen_hook = (VFunction *)NULL;
00062 VFunction *terminal_clear_to_eol_hook = (VFunction *)NULL;
00063 VFunction *terminal_get_screen_size_hook = (VFunction *)NULL;
00064 VFunction *terminal_goto_xy_hook = (VFunction *)NULL;
00065 VFunction *terminal_initialize_terminal_hook = (VFunction *)NULL;
00066 VFunction *terminal_new_terminal_hook = (VFunction *)NULL;
00067 VFunction *terminal_put_text_hook = (VFunction *)NULL;
00068 VFunction *terminal_ring_bell_hook = (VFunction *)NULL;
00069 VFunction *terminal_write_chars_hook = (VFunction *)NULL;
00070 VFunction *terminal_scroll_terminal_hook = (VFunction *)NULL;
00071 
00072 /* **************************************************************** */
00073 /*                                                                  */
00074 /*                      Terminal and Termcap                        */
00075 /*                                                                  */
00076 /* **************************************************************** */
00077 
00078 /* A buffer which holds onto the current terminal description, and a pointer
00079    used to float within it.  And the name of the terminal.  */
00080 static char *term_buffer = NULL;
00081 static char *term_string_buffer = NULL;
00082 static char *term_name;
00083 
00084 /* Some strings to control terminal actions.  These are output by tputs (). */
00085 static char *term_goto, *term_clreol, *term_cr, *term_clrpag;
00086 static char *term_begin_use, *term_end_use;
00087 static char *term_AL, *term_DL, *term_al, *term_dl;
00088 
00089 static char *term_keypad_on, *term_keypad_off;
00090 
00091 /* How to go up a line. */
00092 static char *term_up;
00093 
00094 /* How to go down a line. */
00095 static char *term_dn;
00096 
00097 /* An audible bell, if the terminal can be made to make noise. */
00098 static char *audible_bell;
00099 
00100 /* A visible bell, if the terminal can be made to flash the screen. */
00101 static char *visible_bell;
00102 
00103 /* The string to write to turn on the meta key, if this term has one. */
00104 static char *term_mm;
00105 
00106 /* The string to turn on inverse mode, if this term has one. */
00107 static char *term_invbeg;
00108 
00109 /* The string to turn off inverse mode, if this term has one. */
00110 static char *term_invend;
00111 
00112 /* Although I can't find any documentation that says this is supposed to
00113    return its argument, all the code I've looked at (termutils, less)
00114    does so, so fine.  */
00115 static int
00116 output_character_function (int c)
00117 {
00118   putc (c, stdout);
00119   return c;
00120 }
00121 
00122 /* Macro to send STRING to the terminal. */
00123 #define send_to_terminal(string) \
00124   do { \
00125     if (string) \
00126       tputs (string, 1, output_character_function); \
00127      } while (0)
00128 
00129 /* Tell the terminal that we will be doing cursor addressable motion.  */
00130 static void
00131 terminal_begin_using_terminal (void)
00132 {
00133   RETSIGTYPE (*sigsave) (int signum);
00134 
00135   if (term_keypad_on)
00136       send_to_terminal (term_keypad_on);
00137   
00138   if (!term_begin_use || !*term_begin_use)
00139     return;
00140 
00141 #ifdef SIGWINCH
00142   sigsave = signal (SIGWINCH, SIG_IGN); 
00143 #endif
00144 
00145   send_to_terminal (term_begin_use);
00146   fflush (stdout);
00147   if (STREQ (term_name, "sun-cmd"))
00148     /* Without this fflush and sleep, running info in a shelltool or
00149        cmdtool (TERM=sun-cmd) with scrollbars loses -- the scrollbars are
00150        not restored properly.
00151        From: strube@physik3.gwdg.de (Hans Werner Strube).  */
00152     sleep (1);
00153 
00154 #ifdef SIGWINCH
00155   signal (SIGWINCH, sigsave);
00156 #endif
00157 }
00158 
00159 /* Tell the terminal that we will not be doing any more cursor
00160    addressable motion. */
00161 static void
00162 terminal_end_using_terminal (void)
00163 {
00164   RETSIGTYPE (*sigsave) (int signum);
00165 
00166   if (term_keypad_off)
00167       send_to_terminal (term_keypad_off);
00168   
00169   if (!term_end_use || !*term_end_use)
00170     return;
00171 
00172 #ifdef SIGWINCH
00173   sigsave = signal (SIGWINCH, SIG_IGN);
00174 #endif
00175 
00176   send_to_terminal (term_end_use);
00177   fflush (stdout);
00178   if (STREQ (term_name, "sun-cmd"))
00179     /* See comments at other sleep.  */
00180     sleep (1);
00181 
00182 #ifdef SIGWINCH
00183   signal (SIGWINCH, sigsave);
00184 #endif
00185 }
00186 
00187 /* **************************************************************** */
00188 /*                                                                  */
00189 /*                   Necessary Terminal Functions                   */
00190 /*                                                                  */
00191 /* **************************************************************** */
00192 
00193 /* The functions and variables on this page implement the user visible
00194    portion of the terminal interface. */
00195 
00196 /* The width and height of the terminal. */
00197 int screenwidth, screenheight;
00198 
00199 /* Non-zero means this terminal can't really do anything. */
00200 int terminal_is_dumb_p = 0;
00201 
00202 /* Non-zero means that this terminal has a meta key. */
00203 int terminal_has_meta_p = 0;
00204 
00205 /* Non-zero means that this terminal can produce a visible bell. */
00206 int terminal_has_visible_bell_p = 0;
00207 
00208 /* Non-zero means to use that visible bell if at all possible. */
00209 int terminal_use_visible_bell_p = 0;
00210 
00211 /* Non-zero means that the terminal can do scrolling. */
00212 int terminal_can_scroll = 0;
00213 
00214 /* The key sequences output by the arrow keys, if this terminal has any. */
00215 char *term_ku = NULL;
00216 char *term_kd = NULL;
00217 char *term_kr = NULL;
00218 char *term_kl = NULL;
00219 char *term_kP = NULL;   /* page-up */
00220 char *term_kN = NULL;   /* page-down */
00221 char *term_kh = NULL;       /* home */
00222 char *term_ke = NULL;       /* end */
00223 char *term_kD = NULL;       /* delete */
00224 char *term_ki = NULL;       /* ins */
00225 char *term_kx = NULL;       /* del */
00226 
00227 /* Move the cursor to the terminal location of X and Y. */
00228 void
00229 terminal_goto_xy (int x, int y)
00230 {
00231   if (terminal_goto_xy_hook)
00232     (*terminal_goto_xy_hook) (x, y);
00233   else
00234     {
00235       if (term_goto)
00236         tputs (tgoto (term_goto, x, y), 1, output_character_function);
00237     }
00238 }
00239 
00240 /* Print STRING to the terminal at the current position. */
00241 void
00242 terminal_put_text (char *string)
00243 {
00244   if (terminal_put_text_hook)
00245     (*terminal_put_text_hook) (string);
00246   else
00247     {
00248       printf ("%s", string);
00249     }
00250 }
00251 
00252 /* Print NCHARS from STRING to the terminal at the current position. */
00253 void
00254 terminal_write_chars (char *string, int nchars)
00255 {
00256   if (terminal_write_chars_hook)
00257     (*terminal_write_chars_hook) (string, nchars);
00258   else
00259     {
00260       if (nchars)
00261         fwrite (string, 1, nchars, stdout);
00262     }
00263 }
00264 
00265 /* Clear from the current position of the cursor to the end of the line. */
00266 void
00267 terminal_clear_to_eol (void)
00268 {
00269   if (terminal_clear_to_eol_hook)
00270     (*terminal_clear_to_eol_hook) ();
00271   else
00272     {
00273       send_to_terminal (term_clreol);
00274     }
00275 }
00276 
00277 /* Clear the entire terminal screen. */
00278 void
00279 terminal_clear_screen (void)
00280 {
00281   if (terminal_clear_screen_hook)
00282     (*terminal_clear_screen_hook) ();
00283   else
00284     {
00285       send_to_terminal (term_clrpag);
00286     }
00287 }
00288 
00289 /* Move the cursor up one line. */
00290 void
00291 terminal_up_line (void)
00292 {
00293   if (terminal_up_line_hook)
00294     (*terminal_up_line_hook) ();
00295   else
00296     {
00297       send_to_terminal (term_up);
00298     }
00299 }
00300 
00301 /* Move the cursor down one line. */
00302 void
00303 terminal_down_line (void)
00304 {
00305   if (terminal_down_line_hook)
00306     (*terminal_down_line_hook) ();
00307   else
00308     {
00309       send_to_terminal (term_dn);
00310     }
00311 }
00312 
00313 /* Turn on reverse video if possible. */
00314 void
00315 terminal_begin_inverse (void)
00316 {
00317   if (terminal_begin_inverse_hook)
00318     (*terminal_begin_inverse_hook) ();
00319   else
00320     {
00321       send_to_terminal (term_invbeg);
00322     }
00323 }
00324 
00325 /* Turn off reverse video if possible. */
00326 void
00327 terminal_end_inverse (void)
00328 {
00329   if (terminal_end_inverse_hook)
00330     (*terminal_end_inverse_hook) ();
00331   else
00332     {
00333       send_to_terminal (term_invend);
00334     }
00335 }
00336 
00337 /* Ring the terminal bell.  The bell is run visibly if it both has one and
00338    terminal_use_visible_bell_p is non-zero. */
00339 void
00340 terminal_ring_bell (void)
00341 {
00342   if (terminal_ring_bell_hook)
00343     (*terminal_ring_bell_hook) ();
00344   else
00345     {
00346       if (terminal_has_visible_bell_p && terminal_use_visible_bell_p)
00347         send_to_terminal (visible_bell);
00348       else
00349         send_to_terminal (audible_bell);
00350     }
00351 }
00352 
00353 /* At the line START, delete COUNT lines from the terminal display. */
00354 static void
00355 terminal_delete_lines (int start, int count)
00356 {
00357   int lines;
00358 
00359   /* Normalize arguments. */
00360   if (start < 0)
00361     start = 0;
00362 
00363   lines = screenheight - start;
00364   terminal_goto_xy (0, start);
00365   if (term_DL)
00366     tputs (tgoto (term_DL, 0, count), lines, output_character_function);
00367   else
00368     {
00369       while (count--)
00370         tputs (term_dl, lines, output_character_function);
00371     }
00372 
00373   fflush (stdout);
00374 }
00375 
00376 /* At the line START, insert COUNT lines in the terminal display. */
00377 static void
00378 terminal_insert_lines (int start, int count)
00379 {
00380   int lines;
00381 
00382   /* Normalize arguments. */
00383   if (start < 0)
00384     start = 0;
00385 
00386   lines = screenheight - start;
00387   terminal_goto_xy (0, start);
00388 
00389   if (term_AL)
00390     tputs (tgoto (term_AL, 0, count), lines, output_character_function);
00391   else
00392     {
00393       while (count--)
00394         tputs (term_al, lines, output_character_function);
00395     }
00396 
00397   fflush (stdout);
00398 }
00399 
00400 /* Scroll an area of the terminal, starting with the region from START
00401    to END, AMOUNT lines.  If AMOUNT is negative, the lines are scrolled
00402    towards the top of the screen, else they are scrolled towards the
00403    bottom of the screen. */
00404 void
00405 terminal_scroll_terminal (int start, int end, int amount)
00406 {
00407   if (!terminal_can_scroll)
00408     return;
00409 
00410   /* Any scrolling at all? */
00411   if (amount == 0)
00412     return;
00413 
00414   if (terminal_scroll_terminal_hook)
00415     (*terminal_scroll_terminal_hook) (start, end, amount);
00416   else
00417     {
00418       /* If we are scrolling down, delete AMOUNT lines at END.  Then insert
00419          AMOUNT lines at START. */
00420       if (amount > 0)
00421         {
00422           terminal_delete_lines (end, amount);
00423           terminal_insert_lines (start, amount);
00424         }
00425 
00426       /* If we are scrolling up, delete AMOUNT lines before START.  This
00427          actually does the upwards scroll.  Then, insert AMOUNT lines
00428          after the already scrolled region (i.e., END - AMOUNT). */
00429       if (amount < 0)
00430         {
00431           int abs_amount = -amount;
00432           terminal_delete_lines (start - abs_amount, abs_amount);
00433           terminal_insert_lines (end - abs_amount, abs_amount);
00434         }
00435     }
00436 }
00437 
00438 /* Re-initialize the terminal considering that the TERM/TERMCAP variable
00439    has changed. */
00440 void
00441 terminal_new_terminal (char *terminal_name)
00442 {
00443   if (terminal_new_terminal_hook)
00444     (*terminal_new_terminal_hook) (terminal_name);
00445   else
00446     {
00447       terminal_initialize_terminal (terminal_name);
00448     }
00449 }
00450 
00451 /* Set the global variables SCREENWIDTH and SCREENHEIGHT. */
00452 void
00453 terminal_get_screen_size (void)
00454 {
00455   if (terminal_get_screen_size_hook)
00456     (*terminal_get_screen_size_hook) ();
00457   else
00458     {
00459       screenwidth = screenheight = 0;
00460 
00461 #if defined (TIOCGWINSZ)
00462       {
00463         struct winsize window_size;
00464 
00465         if (ioctl (fileno (stdout), TIOCGWINSZ, &window_size) == 0)
00466           {
00467             screenwidth = (int) window_size.ws_col;
00468             screenheight = (int) window_size.ws_row;
00469           }
00470       }
00471 #endif                          /* TIOCGWINSZ */
00472 
00473       /* Environment variable COLUMNS overrides setting of "co". */
00474       if (screenwidth <= 0)
00475         {
00476           char *sw = getenv ("COLUMNS");
00477 
00478           if (sw)
00479             screenwidth = atoi (sw);
00480 
00481           if (screenwidth <= 0)
00482             screenwidth = tgetnum ("co");
00483         }
00484 
00485       /* Environment variable LINES overrides setting of "li". */
00486       if (screenheight <= 0)
00487         {
00488           char *sh = getenv ("LINES");
00489 
00490           if (sh)
00491             screenheight = atoi (sh);
00492 
00493           if (screenheight <= 0)
00494             screenheight = tgetnum ("li");
00495         }
00496 
00497       /* If all else fails, default to 80x24 terminal. */
00498       if (screenwidth <= 0)
00499         screenwidth = 80;
00500 
00501       if (screenheight <= 0)
00502         screenheight = 24;
00503     }
00504 }
00505 
00506 /* Initialize the terminal which is known as TERMINAL_NAME.  If this
00507    terminal doesn't have cursor addressability, `terminal_is_dumb_p'
00508    becomes nonzero.  The variables SCREENHEIGHT and SCREENWIDTH are set
00509    to the dimensions that this terminal actually has.  The variable
00510    TERMINAL_HAS_META_P becomes nonzero if this terminal supports a Meta
00511    key.  Finally, the terminal screen is cleared. */
00512 void
00513 terminal_initialize_terminal (char *terminal_name)
00514 {
00515   char *buffer;
00516 
00517   terminal_is_dumb_p = 0;
00518 
00519   if (terminal_initialize_terminal_hook)
00520     {
00521       (*terminal_initialize_terminal_hook) (terminal_name);
00522       return;
00523     }
00524 
00525   term_name = terminal_name ? terminal_name : getenv ("TERM");
00526   if (!term_name)
00527     term_name = "dumb";
00528 
00529   if (!term_string_buffer)
00530     term_string_buffer = xmalloc (2048);
00531 
00532   if (!term_buffer)
00533     term_buffer = xmalloc (2048);
00534 
00535   buffer = term_string_buffer;
00536 
00537   term_clrpag = term_cr = term_clreol = NULL;
00538 
00539   /* HP-UX 11.x returns 0 for OK --jeff.hull@state.co.us.  */
00540   if (tgetent (term_buffer, term_name) < 0)
00541     {
00542       terminal_is_dumb_p = 1;
00543       screenwidth = 80;
00544       screenheight = 24;
00545       term_cr = "\r";
00546       term_up = term_dn = audible_bell = visible_bell = NULL;
00547       term_ku = term_kd = term_kl = term_kr = NULL;
00548       term_kP = term_kN = NULL;
00549       term_kh = term_ke = NULL;
00550       term_kD = NULL;
00551       return;
00552     }
00553 
00554   BC = tgetstr ("pc", &buffer);
00555   PC = BC ? *BC : 0;
00556 
00557 #if defined (HAVE_TERMIOS_H)
00558   {
00559     struct termios ti;
00560     if (tcgetattr (fileno(stdout), &ti) != -1)
00561       ospeed = cfgetospeed (&ti);
00562     else
00563       ospeed = B9600;
00564   }
00565 #else
00566 # if defined (TIOCGETP)
00567   {
00568     struct sgttyb sg;
00569 
00570     if (ioctl (fileno (stdout), TIOCGETP, &sg) != -1)
00571       ospeed = sg.sg_ospeed;
00572     else
00573       ospeed = B9600;
00574   }
00575 # else
00576   ospeed = B9600;
00577 # endif /* !TIOCGETP */
00578 #endif
00579 
00580   term_cr = tgetstr ("cr", &buffer);
00581   term_clreol = tgetstr ("ce", &buffer);
00582   term_clrpag = tgetstr ("cl", &buffer);
00583   term_goto = tgetstr ("cm", &buffer);
00584 
00585   /* Find out about this terminal's scrolling capability. */
00586   term_AL = tgetstr ("AL", &buffer);
00587   term_DL = tgetstr ("DL", &buffer);
00588   term_al = tgetstr ("al", &buffer);
00589   term_dl = tgetstr ("dl", &buffer);
00590 
00591   terminal_can_scroll = ((term_AL || term_al) && (term_DL || term_dl));
00592 
00593   term_invbeg = tgetstr ("mr", &buffer);
00594   if (term_invbeg)
00595     term_invend = tgetstr ("me", &buffer);
00596   else
00597     term_invend = NULL;
00598 
00599   if (!term_cr)
00600     term_cr =  "\r";
00601 
00602   terminal_get_screen_size ();
00603 
00604   term_up = tgetstr ("up", &buffer);
00605   term_dn = tgetstr ("dn", &buffer);
00606   visible_bell = tgetstr ("vb", &buffer);
00607   terminal_has_visible_bell_p = (visible_bell != NULL);
00608   audible_bell = tgetstr ("bl", &buffer);
00609   if (!audible_bell)
00610     audible_bell = "\007";
00611   term_begin_use = tgetstr ("ti", &buffer);
00612   term_end_use = tgetstr ("te", &buffer);
00613 
00614   term_keypad_on = tgetstr ("ks", &buffer);
00615   term_keypad_off = tgetstr ("ke", &buffer);
00616 
00617   /* Check to see if this terminal has a meta key. */
00618   terminal_has_meta_p = (tgetflag ("km") || tgetflag ("MT"));
00619   if (terminal_has_meta_p)
00620     {
00621       term_mm = tgetstr ("mm", &buffer);
00622     }
00623   else
00624     {
00625       term_mm = NULL;
00626     }
00627 
00628   /* Attempt to find the arrow keys.  */
00629   term_ku = tgetstr ("ku", &buffer);
00630   term_kd = tgetstr ("kd", &buffer);
00631   term_kr = tgetstr ("kr", &buffer);
00632   term_kl = tgetstr ("kl", &buffer);
00633 
00634   term_kP = tgetstr ("kP", &buffer);
00635   term_kN = tgetstr ("kN", &buffer);
00636 
00637 #if defined(INFOKEY)
00638   term_kh = tgetstr ("kh", &buffer);
00639   term_ke = tgetstr ("@7", &buffer);
00640   term_ki = tgetstr ("kI", &buffer);
00641   term_kx = tgetstr ("kD", &buffer);
00642 #endif /* defined(INFOKEY) */
00643 
00644   /* Home and end keys. */
00645   term_kh = tgetstr ("kh", &buffer);
00646   term_ke = tgetstr ("@7", &buffer);
00647 
00648   term_kD = tgetstr ("kD", &buffer);
00649 
00650   /* If this terminal is not cursor addressable, then it is really dumb. */
00651   if (!term_goto)
00652     terminal_is_dumb_p = 1;
00653 }
00654 
00655 /* How to read characters from the terminal.  */
00656 
00657 #if defined (HAVE_TERMIOS_H)
00658 struct termios original_termios, ttybuff;
00659 #else
00660 #  if defined (HAVE_TERMIO_H)
00661 /* A buffer containing the terminal mode flags upon entry to info. */
00662 struct termio original_termio, ttybuff;
00663 #  else /* !HAVE_TERMIO_H */
00664 /* Buffers containing the terminal mode flags upon entry to info. */
00665 int original_tty_flags = 0;
00666 int original_lmode;
00667 struct sgttyb ttybuff;
00668 
00669 #    if defined(TIOCGETC) && defined(M_XENIX)
00670 /* SCO 3.2v5.0.2 defines but does not support TIOCGETC.  Gak.  Maybe
00671    better fix would be to use Posix termios in preference.  --gildea,
00672    1jul99.  */
00673 #      undef TIOCGETC
00674 #    endif
00675 
00676 #    if defined (TIOCGETC)
00677 /* A buffer containing the terminal interrupt characters upon entry
00678    to Info. */
00679 struct tchars original_tchars;
00680 #    endif
00681 
00682 #    if defined (TIOCGLTC)
00683 /* A buffer containing the local terminal mode characters upon entry
00684    to Info. */
00685 struct ltchars original_ltchars;
00686 #    endif
00687 #  endif /* !HAVE_TERMIO_H */
00688 #endif /* !HAVE_TERMIOS_H */
00689 
00690 /* Prepare to start using the terminal to read characters singly. */
00691 void
00692 terminal_prep_terminal (void)
00693 {
00694   int tty;
00695 
00696   if (terminal_prep_terminal_hook)
00697     {
00698       (*terminal_prep_terminal_hook) ();
00699       return;
00700     }
00701 
00702   terminal_begin_using_terminal ();
00703 
00704   tty = fileno (stdin);
00705 
00706 #if defined (HAVE_TERMIOS_H)
00707   tcgetattr (tty, &original_termios);
00708   tcgetattr (tty, &ttybuff);
00709 #else
00710 #  if defined (HAVE_TERMIO_H)
00711   ioctl (tty, TCGETA, &original_termio);
00712   ioctl (tty, TCGETA, &ttybuff);
00713 #  endif
00714 #endif
00715 
00716 #if defined (HAVE_TERMIOS_H) || defined (HAVE_TERMIO_H)
00717   ttybuff.c_iflag &= (~ISTRIP & ~INLCR & ~IGNCR & ~ICRNL & ~IXON);
00718 /* These output flags are not part of POSIX, so only use them if they
00719    are defined.  */
00720 #ifdef ONLCR
00721   ttybuff.c_oflag &= ~ONLCR ;
00722 #endif
00723 #ifdef OCRNL
00724   ttybuff.c_oflag &= ~OCRNL;
00725 #endif
00726   ttybuff.c_lflag &= (~ICANON & ~ECHO);
00727 
00728   ttybuff.c_cc[VMIN] = 1;
00729   ttybuff.c_cc[VTIME] = 0;
00730 
00731   if (ttybuff.c_cc[VINTR] == '\177')
00732     ttybuff.c_cc[VINTR] = -1;
00733 
00734   if (ttybuff.c_cc[VQUIT] == '\177')
00735     ttybuff.c_cc[VQUIT] = -1;
00736 
00737 #ifdef VLNEXT
00738   if (ttybuff.c_cc[VLNEXT] == '\026')
00739     ttybuff.c_cc[VLNEXT] = -1;
00740 #endif /* VLNEXT */
00741 #endif /* TERMIOS or TERMIO */
00742 
00743 /* cf. emacs/src/sysdep.c for being sure output is on. */
00744 #if defined (HAVE_TERMIOS_H)
00745   /* linux kernel 2.2.x needs a TCOFF followed by a TCOON to turn output
00746      back on if the user presses ^S at the very beginning; just a TCOON
00747      doesn't work.  --Kevin Ryde <user42@zip.com.au>, 16jun2000.  */
00748   tcsetattr (tty, TCSANOW, &ttybuff);
00749 #  ifdef TCOON
00750   tcflow (tty, TCOOFF);
00751   tcflow (tty, TCOON);
00752 #  endif
00753 #else
00754 #  if defined (HAVE_TERMIO_H)
00755   ioctl (tty, TCSETA, &ttybuff);
00756 #    ifdef TCXONC
00757   ioctl (tty, TCXONC, 1);
00758 #    endif
00759 #  endif
00760 #endif
00761 
00762 #if !defined (HAVE_TERMIOS_H) && !defined (HAVE_TERMIO_H)
00763   ioctl (tty, TIOCGETP, &ttybuff);
00764 
00765   if (!original_tty_flags)
00766     original_tty_flags = ttybuff.sg_flags;
00767 
00768   /* Make this terminal pass 8 bits around while we are using it. */
00769 #  if defined (PASS8)
00770   ttybuff.sg_flags |= PASS8;
00771 #  endif /* PASS8 */
00772 
00773 #  if defined (TIOCLGET) && defined (LPASS8)
00774   {
00775     int flags;
00776     ioctl (tty, TIOCLGET, &flags);
00777     original_lmode = flags;
00778     flags |= LPASS8;
00779     ioctl (tty, TIOCLSET, &flags);
00780   }
00781 #  endif /* TIOCLGET && LPASS8 */
00782 
00783 #  if defined (TIOCGETC)
00784   {
00785     struct tchars temp;
00786 
00787     ioctl (tty, TIOCGETC, &original_tchars);
00788     temp = original_tchars;
00789 
00790     /* C-s and C-q. */
00791     temp.t_startc = temp.t_stopc = -1;
00792 
00793     /* Often set to C-d. */
00794     temp.t_eofc = -1;
00795 
00796     /* If the a quit or interrupt character conflicts with one of our
00797        commands, then make it go away. */
00798     if (temp.t_intrc == '\177')
00799       temp.t_intrc = -1;
00800 
00801     if (temp.t_quitc == '\177')
00802       temp.t_quitc = -1;
00803 
00804     ioctl (tty, TIOCSETC, &temp);
00805   }
00806 #  endif /* TIOCGETC */
00807 
00808 #  if defined (TIOCGLTC)
00809   {
00810     struct ltchars temp;
00811 
00812     ioctl (tty, TIOCGLTC, &original_ltchars);
00813     temp = original_ltchars;
00814 
00815     /* Make the interrupt keys go away.  Just enough to make people happy. */
00816     temp.t_lnextc = -1;         /* C-v. */
00817     temp.t_dsuspc = -1;         /* C-y. */
00818     temp.t_flushc = -1;         /* C-o. */
00819     ioctl (tty, TIOCSLTC, &temp);
00820   }
00821 #  endif /* TIOCGLTC */
00822 
00823   ttybuff.sg_flags &= ~ECHO;
00824   ttybuff.sg_flags |= CBREAK;
00825   ioctl (tty, TIOCSETN, &ttybuff);
00826 #endif /* !HAVE_TERMIOS_H && !HAVE_TERMIO_H */
00827 }
00828 
00829 /* Restore the tty settings back to what they were before we started using
00830    this terminal. */
00831 void
00832 terminal_unprep_terminal (void)
00833 {
00834   int tty;
00835 
00836   if (terminal_unprep_terminal_hook)
00837     {
00838       (*terminal_unprep_terminal_hook) ();
00839       return;
00840     }
00841 
00842   tty = fileno (stdin);
00843 
00844 #if defined (HAVE_TERMIOS_H)
00845   tcsetattr (tty, TCSANOW, &original_termios);
00846 #else
00847 #  if defined (HAVE_TERMIO_H)
00848   ioctl (tty, TCSETA, &original_termio);
00849 #  else /* !HAVE_TERMIO_H */
00850   ioctl (tty, TIOCGETP, &ttybuff);
00851   ttybuff.sg_flags = original_tty_flags;
00852   ioctl (tty, TIOCSETN, &ttybuff);
00853 
00854 #  if defined (TIOCGETC)
00855   ioctl (tty, TIOCSETC, &original_tchars);
00856 #  endif /* TIOCGETC */
00857 
00858 #  if defined (TIOCGLTC)
00859   ioctl (tty, TIOCSLTC, &original_ltchars);
00860 #  endif /* TIOCGLTC */
00861 
00862 #  if defined (TIOCLGET) && defined (LPASS8)
00863   ioctl (tty, TIOCLSET, &original_lmode);
00864 #  endif /* TIOCLGET && LPASS8 */
00865 
00866 #  endif /* !HAVE_TERMIO_H */
00867 #endif /* !HAVE_TERMIOS_H */
00868   terminal_end_using_terminal ();
00869 }
00870 
00871 #ifdef __MSDOS__
00872 # include "pcterm.c"
00873 #endif