1114477Sru/* terminal.c -- how to handle the physical terminal for Info. 2146520Sru $Id: terminal.c,v 1.3 2004/04/11 17:56:46 karl Exp $ 321495Sjmacd 4114477Sru Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1996, 1997, 1998, 5146520Sru 1999, 2001, 2002, 2004 Free Software Foundation, Inc. 621495Sjmacd 721495Sjmacd This program is free software; you can redistribute it and/or modify 821495Sjmacd it under the terms of the GNU General Public License as published by 921495Sjmacd the Free Software Foundation; either version 2, or (at your option) 1021495Sjmacd any later version. 1121495Sjmacd 1221495Sjmacd This program is distributed in the hope that it will be useful, 1321495Sjmacd but WITHOUT ANY WARRANTY; without even the implied warranty of 1421495Sjmacd MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1521495Sjmacd GNU General Public License for more details. 1621495Sjmacd 1721495Sjmacd You should have received a copy of the GNU General Public License 1821495Sjmacd along with this program; if not, write to the Free Software 1921495Sjmacd Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 2021495Sjmacd 21146520Sru Originally written by Brian Fox (bfox@ai.mit.edu). */ 2221495Sjmacd 2342664Smarkm#include "info.h" 2421495Sjmacd#include "terminal.h" 2521495Sjmacd#include "termdep.h" 2621495Sjmacd 2742664Smarkm#include <sys/types.h> 2842664Smarkm#include <signal.h> 2921495Sjmacd 3021495Sjmacd/* The Unix termcap interface code. */ 3142664Smarkm#ifdef HAVE_NCURSES_TERMCAP_H 3242664Smarkm#include <ncurses/termcap.h> 3342664Smarkm#else 3442664Smarkm#ifdef HAVE_TERMCAP_H 3542664Smarkm#include <termcap.h> 3642664Smarkm#else 3742664Smarkm/* On Solaris2, sys/types.h #includes sys/reg.h, which #defines PC. 3842664Smarkm Unfortunately, PC is a global variable used by the termcap library. */ 3942664Smarkm#undef PC 4021495Sjmacd 4142664Smarkm/* Termcap requires these variables, whether we access them or not. */ 4242664Smarkmchar *BC, *UP; 4342664Smarkmchar PC; /* Pad character */ 4442664Smarkmshort ospeed; /* Terminal output baud rate */ 4521495Sjmacdextern int tgetnum (), tgetflag (), tgetent (); 4621495Sjmacdextern char *tgetstr (), *tgoto (); 4721495Sjmacdextern void tputs (); 4842664Smarkm#endif /* not HAVE_TERMCAP_H */ 4942664Smarkm#endif /* not HAVE_NCURSES_TERMCAP_H */ 5021495Sjmacd 5121495Sjmacd/* Function "hooks". If you make one of these point to a function, that 5221495Sjmacd function is called when appropriate instead of its namesake. Your 5321495Sjmacd function is called with exactly the same arguments that were passed 5421495Sjmacd to the namesake function. */ 5521495SjmacdVFunction *terminal_begin_inverse_hook = (VFunction *)NULL; 5621495SjmacdVFunction *terminal_end_inverse_hook = (VFunction *)NULL; 5721495SjmacdVFunction *terminal_prep_terminal_hook = (VFunction *)NULL; 5821495SjmacdVFunction *terminal_unprep_terminal_hook = (VFunction *)NULL; 5921495SjmacdVFunction *terminal_up_line_hook = (VFunction *)NULL; 6021495SjmacdVFunction *terminal_down_line_hook = (VFunction *)NULL; 6121495SjmacdVFunction *terminal_clear_screen_hook = (VFunction *)NULL; 6221495SjmacdVFunction *terminal_clear_to_eol_hook = (VFunction *)NULL; 6321495SjmacdVFunction *terminal_get_screen_size_hook = (VFunction *)NULL; 6421495SjmacdVFunction *terminal_goto_xy_hook = (VFunction *)NULL; 6521495SjmacdVFunction *terminal_initialize_terminal_hook = (VFunction *)NULL; 6621495SjmacdVFunction *terminal_new_terminal_hook = (VFunction *)NULL; 6721495SjmacdVFunction *terminal_put_text_hook = (VFunction *)NULL; 6821495SjmacdVFunction *terminal_ring_bell_hook = (VFunction *)NULL; 6921495SjmacdVFunction *terminal_write_chars_hook = (VFunction *)NULL; 7021495SjmacdVFunction *terminal_scroll_terminal_hook = (VFunction *)NULL; 7121495Sjmacd 7221495Sjmacd/* **************************************************************** */ 7342664Smarkm/* */ 7442664Smarkm/* Terminal and Termcap */ 7542664Smarkm/* */ 7621495Sjmacd/* **************************************************************** */ 7721495Sjmacd 7821495Sjmacd/* A buffer which holds onto the current terminal description, and a pointer 7956164Sru used to float within it. And the name of the terminal. */ 8056164Srustatic char *term_buffer = NULL; 8156164Srustatic char *term_string_buffer = NULL; 8256164Srustatic char *term_name; 8321495Sjmacd 8421495Sjmacd/* Some strings to control terminal actions. These are output by tputs (). */ 8521495Sjmacdstatic char *term_goto, *term_clreol, *term_cr, *term_clrpag; 8621495Sjmacdstatic char *term_begin_use, *term_end_use; 8721495Sjmacdstatic char *term_AL, *term_DL, *term_al, *term_dl; 8821495Sjmacd 8942664Smarkmstatic char *term_keypad_on, *term_keypad_off; 9042664Smarkm 9121495Sjmacd/* How to go up a line. */ 9221495Sjmacdstatic char *term_up; 9321495Sjmacd 9421495Sjmacd/* How to go down a line. */ 9521495Sjmacdstatic char *term_dn; 9621495Sjmacd 9721495Sjmacd/* An audible bell, if the terminal can be made to make noise. */ 9821495Sjmacdstatic char *audible_bell; 9921495Sjmacd 10021495Sjmacd/* A visible bell, if the terminal can be made to flash the screen. */ 10121495Sjmacdstatic char *visible_bell; 10221495Sjmacd 10321495Sjmacd/* The string to write to turn on the meta key, if this term has one. */ 10421495Sjmacdstatic char *term_mm; 10521495Sjmacd 10621495Sjmacd/* The string to turn on inverse mode, if this term has one. */ 10721495Sjmacdstatic char *term_invbeg; 10821495Sjmacd 10921495Sjmacd/* The string to turn off inverse mode, if this term has one. */ 11021495Sjmacdstatic char *term_invend; 11121495Sjmacd 11242664Smarkm/* Although I can't find any documentation that says this is supposed to 11342664Smarkm return its argument, all the code I've looked at (termutils, less) 11442664Smarkm does so, so fine. */ 11542664Smarkmstatic int 116146520Sruoutput_character_function (int c) 11721495Sjmacd{ 11821495Sjmacd putc (c, stdout); 11942664Smarkm return c; 12021495Sjmacd} 12121495Sjmacd 12221495Sjmacd/* Macro to send STRING to the terminal. */ 12321495Sjmacd#define send_to_terminal(string) \ 12421495Sjmacd do { \ 12521495Sjmacd if (string) \ 12621495Sjmacd tputs (string, 1, output_character_function); \ 12721495Sjmacd } while (0) 12821495Sjmacd 12942664Smarkm/* Tell the terminal that we will be doing cursor addressable motion. */ 13021495Sjmacdstatic void 131146520Sruterminal_begin_using_terminal (void) 13221495Sjmacd{ 133146520Sru RETSIGTYPE (*sigsave) (int signum); 13442664Smarkm 13542664Smarkm if (term_keypad_on) 13642664Smarkm send_to_terminal (term_keypad_on); 13742664Smarkm 13842664Smarkm if (!term_begin_use || !*term_begin_use) 13942664Smarkm return; 14042664Smarkm 14142664Smarkm#ifdef SIGWINCH 14242664Smarkm sigsave = signal (SIGWINCH, SIG_IGN); 14342664Smarkm#endif 14442664Smarkm 14521495Sjmacd send_to_terminal (term_begin_use); 14642664Smarkm fflush (stdout); 14756164Sru if (STREQ (term_name, "sun-cmd")) 14856164Sru /* Without this fflush and sleep, running info in a shelltool or 14956164Sru cmdtool (TERM=sun-cmd) with scrollbars loses -- the scrollbars are 15056164Sru not restored properly. 15156164Sru From: strube@physik3.gwdg.de (Hans Werner Strube). */ 15256164Sru sleep (1); 15342664Smarkm 15442664Smarkm#ifdef SIGWINCH 15542664Smarkm signal (SIGWINCH, sigsave); 15642664Smarkm#endif 15721495Sjmacd} 15821495Sjmacd 15942664Smarkm/* Tell the terminal that we will not be doing any more cursor 16042664Smarkm addressable motion. */ 16121495Sjmacdstatic void 162146520Sruterminal_end_using_terminal (void) 16321495Sjmacd{ 164146520Sru RETSIGTYPE (*sigsave) (int signum); 16542664Smarkm 16642664Smarkm if (term_keypad_off) 16742664Smarkm send_to_terminal (term_keypad_off); 16842664Smarkm 16942664Smarkm if (!term_end_use || !*term_end_use) 17042664Smarkm return; 17142664Smarkm 17242664Smarkm#ifdef SIGWINCH 17342664Smarkm sigsave = signal (SIGWINCH, SIG_IGN); 17442664Smarkm#endif 17542664Smarkm 17621495Sjmacd send_to_terminal (term_end_use); 17742664Smarkm fflush (stdout); 17856164Sru if (STREQ (term_name, "sun-cmd")) 17956164Sru /* See comments at other sleep. */ 18056164Sru sleep (1); 18142664Smarkm 18242664Smarkm#ifdef SIGWINCH 18342664Smarkm signal (SIGWINCH, sigsave); 18442664Smarkm#endif 18521495Sjmacd} 18621495Sjmacd 18721495Sjmacd/* **************************************************************** */ 18842664Smarkm/* */ 18942664Smarkm/* Necessary Terminal Functions */ 19042664Smarkm/* */ 19121495Sjmacd/* **************************************************************** */ 19221495Sjmacd 19321495Sjmacd/* The functions and variables on this page implement the user visible 19421495Sjmacd portion of the terminal interface. */ 19521495Sjmacd 19621495Sjmacd/* The width and height of the terminal. */ 19721495Sjmacdint screenwidth, screenheight; 19821495Sjmacd 19921495Sjmacd/* Non-zero means this terminal can't really do anything. */ 20021495Sjmacdint terminal_is_dumb_p = 0; 20121495Sjmacd 20221495Sjmacd/* Non-zero means that this terminal has a meta key. */ 20321495Sjmacdint terminal_has_meta_p = 0; 20421495Sjmacd 20521495Sjmacd/* Non-zero means that this terminal can produce a visible bell. */ 20621495Sjmacdint terminal_has_visible_bell_p = 0; 20721495Sjmacd 20821495Sjmacd/* Non-zero means to use that visible bell if at all possible. */ 20921495Sjmacdint terminal_use_visible_bell_p = 0; 21021495Sjmacd 21121495Sjmacd/* Non-zero means that the terminal can do scrolling. */ 21221495Sjmacdint terminal_can_scroll = 0; 21321495Sjmacd 21421495Sjmacd/* The key sequences output by the arrow keys, if this terminal has any. */ 21593142Sruchar *term_ku = NULL; 21693142Sruchar *term_kd = NULL; 21793142Sruchar *term_kr = NULL; 21893142Sruchar *term_kl = NULL; 21993142Sruchar *term_kP = NULL; /* page-up */ 22093142Sruchar *term_kN = NULL; /* page-down */ 22193142Sruchar *term_kh = NULL; /* home */ 22293142Sruchar *term_ke = NULL; /* end */ 22393142Sruchar *term_kD = NULL; /* delete */ 22493142Sruchar *term_ki = NULL; /* ins */ 22593142Sruchar *term_kx = NULL; /* del */ 22621495Sjmacd 22721495Sjmacd/* Move the cursor to the terminal location of X and Y. */ 22821495Sjmacdvoid 229146520Sruterminal_goto_xy (int x, int y) 23021495Sjmacd{ 23121495Sjmacd if (terminal_goto_xy_hook) 23221495Sjmacd (*terminal_goto_xy_hook) (x, y); 23321495Sjmacd else 23421495Sjmacd { 23521495Sjmacd if (term_goto) 23642664Smarkm tputs (tgoto (term_goto, x, y), 1, output_character_function); 23721495Sjmacd } 23821495Sjmacd} 23921495Sjmacd 24021495Sjmacd/* Print STRING to the terminal at the current position. */ 24121495Sjmacdvoid 242146520Sruterminal_put_text (char *string) 24321495Sjmacd{ 24421495Sjmacd if (terminal_put_text_hook) 24521495Sjmacd (*terminal_put_text_hook) (string); 24621495Sjmacd else 24721495Sjmacd { 24821495Sjmacd printf ("%s", string); 24921495Sjmacd } 25021495Sjmacd} 25121495Sjmacd 25221495Sjmacd/* Print NCHARS from STRING to the terminal at the current position. */ 25321495Sjmacdvoid 254146520Sruterminal_write_chars (char *string, int nchars) 25521495Sjmacd{ 25621495Sjmacd if (terminal_write_chars_hook) 25721495Sjmacd (*terminal_write_chars_hook) (string, nchars); 25821495Sjmacd else 25921495Sjmacd { 26021495Sjmacd if (nchars) 26142664Smarkm fwrite (string, 1, nchars, stdout); 26221495Sjmacd } 26321495Sjmacd} 26421495Sjmacd 26521495Sjmacd/* Clear from the current position of the cursor to the end of the line. */ 26621495Sjmacdvoid 267146520Sruterminal_clear_to_eol (void) 26821495Sjmacd{ 26921495Sjmacd if (terminal_clear_to_eol_hook) 27021495Sjmacd (*terminal_clear_to_eol_hook) (); 27121495Sjmacd else 27221495Sjmacd { 27321495Sjmacd send_to_terminal (term_clreol); 27421495Sjmacd } 27521495Sjmacd} 27621495Sjmacd 27721495Sjmacd/* Clear the entire terminal screen. */ 27821495Sjmacdvoid 279146520Sruterminal_clear_screen (void) 28021495Sjmacd{ 28121495Sjmacd if (terminal_clear_screen_hook) 28221495Sjmacd (*terminal_clear_screen_hook) (); 28321495Sjmacd else 28421495Sjmacd { 28521495Sjmacd send_to_terminal (term_clrpag); 28621495Sjmacd } 28721495Sjmacd} 28821495Sjmacd 28921495Sjmacd/* Move the cursor up one line. */ 29021495Sjmacdvoid 291146520Sruterminal_up_line (void) 29221495Sjmacd{ 29321495Sjmacd if (terminal_up_line_hook) 29421495Sjmacd (*terminal_up_line_hook) (); 29521495Sjmacd else 29621495Sjmacd { 29721495Sjmacd send_to_terminal (term_up); 29821495Sjmacd } 29921495Sjmacd} 30021495Sjmacd 30121495Sjmacd/* Move the cursor down one line. */ 30221495Sjmacdvoid 303146520Sruterminal_down_line (void) 30421495Sjmacd{ 30521495Sjmacd if (terminal_down_line_hook) 30621495Sjmacd (*terminal_down_line_hook) (); 30721495Sjmacd else 30821495Sjmacd { 30921495Sjmacd send_to_terminal (term_dn); 31021495Sjmacd } 31121495Sjmacd} 31221495Sjmacd 31321495Sjmacd/* Turn on reverse video if possible. */ 31421495Sjmacdvoid 315146520Sruterminal_begin_inverse (void) 31621495Sjmacd{ 31721495Sjmacd if (terminal_begin_inverse_hook) 31821495Sjmacd (*terminal_begin_inverse_hook) (); 31921495Sjmacd else 32021495Sjmacd { 32121495Sjmacd send_to_terminal (term_invbeg); 32221495Sjmacd } 32321495Sjmacd} 32421495Sjmacd 32521495Sjmacd/* Turn off reverse video if possible. */ 32621495Sjmacdvoid 327146520Sruterminal_end_inverse (void) 32821495Sjmacd{ 32921495Sjmacd if (terminal_end_inverse_hook) 33021495Sjmacd (*terminal_end_inverse_hook) (); 33121495Sjmacd else 33221495Sjmacd { 33321495Sjmacd send_to_terminal (term_invend); 33421495Sjmacd } 33521495Sjmacd} 33621495Sjmacd 33721495Sjmacd/* Ring the terminal bell. The bell is run visibly if it both has one and 33821495Sjmacd terminal_use_visible_bell_p is non-zero. */ 33921495Sjmacdvoid 340146520Sruterminal_ring_bell (void) 34121495Sjmacd{ 34221495Sjmacd if (terminal_ring_bell_hook) 34321495Sjmacd (*terminal_ring_bell_hook) (); 34421495Sjmacd else 34521495Sjmacd { 34621495Sjmacd if (terminal_has_visible_bell_p && terminal_use_visible_bell_p) 34742664Smarkm send_to_terminal (visible_bell); 34821495Sjmacd else 34942664Smarkm send_to_terminal (audible_bell); 35021495Sjmacd } 35121495Sjmacd} 35221495Sjmacd 35321495Sjmacd/* At the line START, delete COUNT lines from the terminal display. */ 35421495Sjmacdstatic void 355146520Sruterminal_delete_lines (int start, int count) 35621495Sjmacd{ 35721495Sjmacd int lines; 35821495Sjmacd 35921495Sjmacd /* Normalize arguments. */ 36021495Sjmacd if (start < 0) 36121495Sjmacd start = 0; 36221495Sjmacd 36321495Sjmacd lines = screenheight - start; 36421495Sjmacd terminal_goto_xy (0, start); 36521495Sjmacd if (term_DL) 36621495Sjmacd tputs (tgoto (term_DL, 0, count), lines, output_character_function); 36721495Sjmacd else 36821495Sjmacd { 36921495Sjmacd while (count--) 37042664Smarkm tputs (term_dl, lines, output_character_function); 37121495Sjmacd } 37221495Sjmacd 37321495Sjmacd fflush (stdout); 37421495Sjmacd} 37521495Sjmacd 37621495Sjmacd/* At the line START, insert COUNT lines in the terminal display. */ 37721495Sjmacdstatic void 378146520Sruterminal_insert_lines (int start, int count) 37921495Sjmacd{ 38021495Sjmacd int lines; 38121495Sjmacd 38221495Sjmacd /* Normalize arguments. */ 38321495Sjmacd if (start < 0) 38421495Sjmacd start = 0; 38521495Sjmacd 38621495Sjmacd lines = screenheight - start; 38721495Sjmacd terminal_goto_xy (0, start); 38821495Sjmacd 38921495Sjmacd if (term_AL) 39021495Sjmacd tputs (tgoto (term_AL, 0, count), lines, output_character_function); 39121495Sjmacd else 39221495Sjmacd { 39321495Sjmacd while (count--) 39442664Smarkm tputs (term_al, lines, output_character_function); 39521495Sjmacd } 39621495Sjmacd 39721495Sjmacd fflush (stdout); 39821495Sjmacd} 39921495Sjmacd 40021495Sjmacd/* Scroll an area of the terminal, starting with the region from START 40121495Sjmacd to END, AMOUNT lines. If AMOUNT is negative, the lines are scrolled 40221495Sjmacd towards the top of the screen, else they are scrolled towards the 40321495Sjmacd bottom of the screen. */ 40421495Sjmacdvoid 405146520Sruterminal_scroll_terminal (int start, int end, int amount) 40621495Sjmacd{ 40721495Sjmacd if (!terminal_can_scroll) 40821495Sjmacd return; 40921495Sjmacd 41021495Sjmacd /* Any scrolling at all? */ 41121495Sjmacd if (amount == 0) 41221495Sjmacd return; 41321495Sjmacd 41421495Sjmacd if (terminal_scroll_terminal_hook) 41521495Sjmacd (*terminal_scroll_terminal_hook) (start, end, amount); 41621495Sjmacd else 41721495Sjmacd { 41821495Sjmacd /* If we are scrolling down, delete AMOUNT lines at END. Then insert 41942664Smarkm AMOUNT lines at START. */ 42021495Sjmacd if (amount > 0) 42142664Smarkm { 42242664Smarkm terminal_delete_lines (end, amount); 42342664Smarkm terminal_insert_lines (start, amount); 42442664Smarkm } 42521495Sjmacd 42621495Sjmacd /* If we are scrolling up, delete AMOUNT lines before START. This 42742664Smarkm actually does the upwards scroll. Then, insert AMOUNT lines 42842664Smarkm after the already scrolled region (i.e., END - AMOUNT). */ 42921495Sjmacd if (amount < 0) 43042664Smarkm { 43142664Smarkm int abs_amount = -amount; 43242664Smarkm terminal_delete_lines (start - abs_amount, abs_amount); 43342664Smarkm terminal_insert_lines (end - abs_amount, abs_amount); 43442664Smarkm } 43521495Sjmacd } 43621495Sjmacd} 43721495Sjmacd 43821495Sjmacd/* Re-initialize the terminal considering that the TERM/TERMCAP variable 43921495Sjmacd has changed. */ 44021495Sjmacdvoid 441146520Sruterminal_new_terminal (char *terminal_name) 44221495Sjmacd{ 44321495Sjmacd if (terminal_new_terminal_hook) 44421495Sjmacd (*terminal_new_terminal_hook) (terminal_name); 44521495Sjmacd else 44621495Sjmacd { 44721495Sjmacd terminal_initialize_terminal (terminal_name); 44821495Sjmacd } 44921495Sjmacd} 45021495Sjmacd 45121495Sjmacd/* Set the global variables SCREENWIDTH and SCREENHEIGHT. */ 45221495Sjmacdvoid 453146520Sruterminal_get_screen_size (void) 45421495Sjmacd{ 45521495Sjmacd if (terminal_get_screen_size_hook) 45621495Sjmacd (*terminal_get_screen_size_hook) (); 45721495Sjmacd else 45821495Sjmacd { 45921495Sjmacd screenwidth = screenheight = 0; 46021495Sjmacd 46121495Sjmacd#if defined (TIOCGWINSZ) 46221495Sjmacd { 46342664Smarkm struct winsize window_size; 46421495Sjmacd 46542664Smarkm if (ioctl (fileno (stdout), TIOCGWINSZ, &window_size) == 0) 46642664Smarkm { 46742664Smarkm screenwidth = (int) window_size.ws_col; 46842664Smarkm screenheight = (int) window_size.ws_row; 46942664Smarkm } 47021495Sjmacd } 47142664Smarkm#endif /* TIOCGWINSZ */ 47221495Sjmacd 47321495Sjmacd /* Environment variable COLUMNS overrides setting of "co". */ 47421495Sjmacd if (screenwidth <= 0) 47542664Smarkm { 47642664Smarkm char *sw = getenv ("COLUMNS"); 47721495Sjmacd 47842664Smarkm if (sw) 47942664Smarkm screenwidth = atoi (sw); 48021495Sjmacd 48142664Smarkm if (screenwidth <= 0) 48242664Smarkm screenwidth = tgetnum ("co"); 48342664Smarkm } 48421495Sjmacd 48521495Sjmacd /* Environment variable LINES overrides setting of "li". */ 48621495Sjmacd if (screenheight <= 0) 48742664Smarkm { 48842664Smarkm char *sh = getenv ("LINES"); 48921495Sjmacd 49042664Smarkm if (sh) 49142664Smarkm screenheight = atoi (sh); 49221495Sjmacd 49342664Smarkm if (screenheight <= 0) 49442664Smarkm screenheight = tgetnum ("li"); 49542664Smarkm } 49621495Sjmacd 49721495Sjmacd /* If all else fails, default to 80x24 terminal. */ 49821495Sjmacd if (screenwidth <= 0) 49942664Smarkm screenwidth = 80; 50021495Sjmacd 50121495Sjmacd if (screenheight <= 0) 50242664Smarkm screenheight = 24; 50321495Sjmacd } 50421495Sjmacd} 50521495Sjmacd 50642664Smarkm/* Initialize the terminal which is known as TERMINAL_NAME. If this 50742664Smarkm terminal doesn't have cursor addressability, `terminal_is_dumb_p' 50842664Smarkm becomes nonzero. The variables SCREENHEIGHT and SCREENWIDTH are set 50942664Smarkm to the dimensions that this terminal actually has. The variable 51042664Smarkm TERMINAL_HAS_META_P becomes nonzero if this terminal supports a Meta 51142664Smarkm key. Finally, the terminal screen is cleared. */ 51221495Sjmacdvoid 513146520Sruterminal_initialize_terminal (char *terminal_name) 51421495Sjmacd{ 51556164Sru char *buffer; 51621495Sjmacd 51721495Sjmacd terminal_is_dumb_p = 0; 51821495Sjmacd 51921495Sjmacd if (terminal_initialize_terminal_hook) 52021495Sjmacd { 52121495Sjmacd (*terminal_initialize_terminal_hook) (terminal_name); 52221495Sjmacd return; 52321495Sjmacd } 52421495Sjmacd 52556164Sru term_name = terminal_name ? terminal_name : getenv ("TERM"); 52656164Sru if (!term_name) 52756164Sru term_name = "dumb"; 52821495Sjmacd 52921495Sjmacd if (!term_string_buffer) 53056164Sru term_string_buffer = xmalloc (2048); 53121495Sjmacd 53221495Sjmacd if (!term_buffer) 53356164Sru term_buffer = xmalloc (2048); 53421495Sjmacd 53521495Sjmacd buffer = term_string_buffer; 53621495Sjmacd 53756164Sru term_clrpag = term_cr = term_clreol = NULL; 53821495Sjmacd 53956164Sru /* HP-UX 11.x returns 0 for OK --jeff.hull@state.co.us. */ 54056164Sru if (tgetent (term_buffer, term_name) < 0) 54121495Sjmacd { 54221495Sjmacd terminal_is_dumb_p = 1; 54321495Sjmacd screenwidth = 80; 54421495Sjmacd screenheight = 24; 54521495Sjmacd term_cr = "\r"; 54656164Sru term_up = term_dn = audible_bell = visible_bell = NULL; 54756164Sru term_ku = term_kd = term_kl = term_kr = NULL; 54856164Sru term_kP = term_kN = NULL; 54993142Sru term_kh = term_ke = NULL; 55093142Sru term_kD = NULL; 55121495Sjmacd return; 55221495Sjmacd } 55321495Sjmacd 55421495Sjmacd BC = tgetstr ("pc", &buffer); 55521495Sjmacd PC = BC ? *BC : 0; 55621495Sjmacd 55756164Sru#if defined (HAVE_TERMIOS_H) 55821495Sjmacd { 55956164Sru struct termios ti; 56056164Sru if (tcgetattr (fileno(stdout), &ti) != -1) 56156164Sru ospeed = cfgetospeed (&ti); 56256164Sru else 56356164Sru ospeed = B9600; 56456164Sru } 56556164Sru#else 56656164Sru# if defined (TIOCGETP) 56756164Sru { 56821495Sjmacd struct sgttyb sg; 56921495Sjmacd 57021495Sjmacd if (ioctl (fileno (stdout), TIOCGETP, &sg) != -1) 57121495Sjmacd ospeed = sg.sg_ospeed; 57221495Sjmacd else 57321495Sjmacd ospeed = B9600; 57421495Sjmacd } 57556164Sru# else 57621495Sjmacd ospeed = B9600; 57756164Sru# endif /* !TIOCGETP */ 57856164Sru#endif 57921495Sjmacd 58021495Sjmacd term_cr = tgetstr ("cr", &buffer); 58121495Sjmacd term_clreol = tgetstr ("ce", &buffer); 58221495Sjmacd term_clrpag = tgetstr ("cl", &buffer); 58321495Sjmacd term_goto = tgetstr ("cm", &buffer); 58421495Sjmacd 58556164Sru /* Find out about this terminal's scrolling capability. */ 58621495Sjmacd term_AL = tgetstr ("AL", &buffer); 58721495Sjmacd term_DL = tgetstr ("DL", &buffer); 58821495Sjmacd term_al = tgetstr ("al", &buffer); 58921495Sjmacd term_dl = tgetstr ("dl", &buffer); 59021495Sjmacd 59121495Sjmacd terminal_can_scroll = ((term_AL || term_al) && (term_DL || term_dl)); 59221495Sjmacd 59321495Sjmacd term_invbeg = tgetstr ("mr", &buffer); 59421495Sjmacd if (term_invbeg) 59521495Sjmacd term_invend = tgetstr ("me", &buffer); 59621495Sjmacd else 59793142Sru term_invend = NULL; 59821495Sjmacd 59921495Sjmacd if (!term_cr) 60021495Sjmacd term_cr = "\r"; 60121495Sjmacd 60221495Sjmacd terminal_get_screen_size (); 60321495Sjmacd 60421495Sjmacd term_up = tgetstr ("up", &buffer); 60521495Sjmacd term_dn = tgetstr ("dn", &buffer); 60621495Sjmacd visible_bell = tgetstr ("vb", &buffer); 60793142Sru terminal_has_visible_bell_p = (visible_bell != NULL); 60821495Sjmacd audible_bell = tgetstr ("bl", &buffer); 60921495Sjmacd if (!audible_bell) 61021495Sjmacd audible_bell = "\007"; 61121495Sjmacd term_begin_use = tgetstr ("ti", &buffer); 61221495Sjmacd term_end_use = tgetstr ("te", &buffer); 61321495Sjmacd 61442664Smarkm term_keypad_on = tgetstr ("ks", &buffer); 61542664Smarkm term_keypad_off = tgetstr ("ke", &buffer); 61642664Smarkm 61721495Sjmacd /* Check to see if this terminal has a meta key. */ 61821495Sjmacd terminal_has_meta_p = (tgetflag ("km") || tgetflag ("MT")); 61921495Sjmacd if (terminal_has_meta_p) 62021495Sjmacd { 62121495Sjmacd term_mm = tgetstr ("mm", &buffer); 62221495Sjmacd } 62321495Sjmacd else 62421495Sjmacd { 62593142Sru term_mm = NULL; 62621495Sjmacd } 62721495Sjmacd 62842699Smarkm /* Attempt to find the arrow keys. */ 62921495Sjmacd term_ku = tgetstr ("ku", &buffer); 63021495Sjmacd term_kd = tgetstr ("kd", &buffer); 63121495Sjmacd term_kr = tgetstr ("kr", &buffer); 63221495Sjmacd term_kl = tgetstr ("kl", &buffer); 63342664Smarkm 63421787Sjmacd term_kP = tgetstr ("kP", &buffer); 63521787Sjmacd term_kN = tgetstr ("kN", &buffer); 63621495Sjmacd 63793142Sru#if defined(INFOKEY) 63893142Sru term_kh = tgetstr ("kh", &buffer); 63993142Sru term_ke = tgetstr ("@7", &buffer); 64093142Sru term_ki = tgetstr ("kI", &buffer); 64193142Sru term_kx = tgetstr ("kD", &buffer); 64293142Sru#endif /* defined(INFOKEY) */ 64393142Sru 64493142Sru /* Home and end keys. */ 64593142Sru term_kh = tgetstr ("kh", &buffer); 64693142Sru term_ke = tgetstr ("@7", &buffer); 64793142Sru 64893142Sru term_kD = tgetstr ("kD", &buffer); 64993142Sru 65021495Sjmacd /* If this terminal is not cursor addressable, then it is really dumb. */ 65121495Sjmacd if (!term_goto) 65221495Sjmacd terminal_is_dumb_p = 1; 65321495Sjmacd} 65421495Sjmacd 65556164Sru/* How to read characters from the terminal. */ 65621495Sjmacd 65721495Sjmacd#if defined (HAVE_TERMIOS_H) 65821495Sjmacdstruct termios original_termios, ttybuff; 65921495Sjmacd#else 66021495Sjmacd# if defined (HAVE_TERMIO_H) 66121495Sjmacd/* A buffer containing the terminal mode flags upon entry to info. */ 66221495Sjmacdstruct termio original_termio, ttybuff; 66321495Sjmacd# else /* !HAVE_TERMIO_H */ 66421495Sjmacd/* Buffers containing the terminal mode flags upon entry to info. */ 66521495Sjmacdint original_tty_flags = 0; 66621495Sjmacdint original_lmode; 66721495Sjmacdstruct sgttyb ttybuff; 66856164Sru 66956164Sru# if defined(TIOCGETC) && defined(M_XENIX) 67056164Sru/* SCO 3.2v5.0.2 defines but does not support TIOCGETC. Gak. Maybe 67156164Sru better fix would be to use Posix termios in preference. --gildea, 67256164Sru 1jul99. */ 67356164Sru# undef TIOCGETC 67456164Sru# endif 67556164Sru 67656164Sru# if defined (TIOCGETC) 67756164Sru/* A buffer containing the terminal interrupt characters upon entry 67856164Sru to Info. */ 67956164Srustruct tchars original_tchars; 68056164Sru# endif 68156164Sru 68256164Sru# if defined (TIOCGLTC) 68356164Sru/* A buffer containing the local terminal mode characters upon entry 68456164Sru to Info. */ 68556164Srustruct ltchars original_ltchars; 68656164Sru# endif 68721495Sjmacd# endif /* !HAVE_TERMIO_H */ 68821495Sjmacd#endif /* !HAVE_TERMIOS_H */ 68921495Sjmacd 69021495Sjmacd/* Prepare to start using the terminal to read characters singly. */ 69121495Sjmacdvoid 692146520Sruterminal_prep_terminal (void) 69321495Sjmacd{ 69421495Sjmacd int tty; 69521495Sjmacd 69621495Sjmacd if (terminal_prep_terminal_hook) 69721495Sjmacd { 69821495Sjmacd (*terminal_prep_terminal_hook) (); 69921495Sjmacd return; 70021495Sjmacd } 70121495Sjmacd 70242664Smarkm terminal_begin_using_terminal (); 70342664Smarkm 70421495Sjmacd tty = fileno (stdin); 70521495Sjmacd 70621495Sjmacd#if defined (HAVE_TERMIOS_H) 70721495Sjmacd tcgetattr (tty, &original_termios); 70821495Sjmacd tcgetattr (tty, &ttybuff); 70921495Sjmacd#else 71021495Sjmacd# if defined (HAVE_TERMIO_H) 71121495Sjmacd ioctl (tty, TCGETA, &original_termio); 71221495Sjmacd ioctl (tty, TCGETA, &ttybuff); 71321495Sjmacd# endif 71421495Sjmacd#endif 71521495Sjmacd 71621495Sjmacd#if defined (HAVE_TERMIOS_H) || defined (HAVE_TERMIO_H) 71721495Sjmacd ttybuff.c_iflag &= (~ISTRIP & ~INLCR & ~IGNCR & ~ICRNL & ~IXON); 71842664Smarkm/* These output flags are not part of POSIX, so only use them if they 71942664Smarkm are defined. */ 72042664Smarkm#ifdef ONLCR 72142664Smarkm ttybuff.c_oflag &= ~ONLCR ; 72242664Smarkm#endif 72342664Smarkm#ifdef OCRNL 72442664Smarkm ttybuff.c_oflag &= ~OCRNL; 72542664Smarkm#endif 72621495Sjmacd ttybuff.c_lflag &= (~ICANON & ~ECHO); 72721495Sjmacd 72821495Sjmacd ttybuff.c_cc[VMIN] = 1; 72921495Sjmacd ttybuff.c_cc[VTIME] = 0; 73021495Sjmacd 73121495Sjmacd if (ttybuff.c_cc[VINTR] == '\177') 73221495Sjmacd ttybuff.c_cc[VINTR] = -1; 73321495Sjmacd 73421495Sjmacd if (ttybuff.c_cc[VQUIT] == '\177') 73521495Sjmacd ttybuff.c_cc[VQUIT] = -1; 73621495Sjmacd 73742664Smarkm#ifdef VLNEXT 73842664Smarkm if (ttybuff.c_cc[VLNEXT] == '\026') 73942664Smarkm ttybuff.c_cc[VLNEXT] = -1; 74042664Smarkm#endif /* VLNEXT */ 74142664Smarkm#endif /* TERMIOS or TERMIO */ 74242664Smarkm 74393142Sru/* cf. emacs/src/sysdep.c for being sure output is on. */ 74421495Sjmacd#if defined (HAVE_TERMIOS_H) 74593142Sru /* linux kernel 2.2.x needs a TCOFF followed by a TCOON to turn output 74693142Sru back on if the user presses ^S at the very beginning; just a TCOON 74793142Sru doesn't work. --Kevin Ryde <user42@zip.com.au>, 16jun2000. */ 74821495Sjmacd tcsetattr (tty, TCSANOW, &ttybuff); 74993142Sru# ifdef TCOON 75093142Sru tcflow (tty, TCOOFF); 75193142Sru tcflow (tty, TCOON); 75293142Sru# endif 75321495Sjmacd#else 75421495Sjmacd# if defined (HAVE_TERMIO_H) 75521495Sjmacd ioctl (tty, TCSETA, &ttybuff); 75693142Sru# ifdef TCXONC 75793142Sru ioctl (tty, TCXONC, 1); 75893142Sru# endif 75921495Sjmacd# endif 76021495Sjmacd#endif 76121495Sjmacd 76221495Sjmacd#if !defined (HAVE_TERMIOS_H) && !defined (HAVE_TERMIO_H) 76321495Sjmacd ioctl (tty, TIOCGETP, &ttybuff); 76421495Sjmacd 76521495Sjmacd if (!original_tty_flags) 76621495Sjmacd original_tty_flags = ttybuff.sg_flags; 76721495Sjmacd 76821495Sjmacd /* Make this terminal pass 8 bits around while we are using it. */ 76921495Sjmacd# if defined (PASS8) 77021495Sjmacd ttybuff.sg_flags |= PASS8; 77121495Sjmacd# endif /* PASS8 */ 77221495Sjmacd 77321495Sjmacd# if defined (TIOCLGET) && defined (LPASS8) 77421495Sjmacd { 77521495Sjmacd int flags; 77621495Sjmacd ioctl (tty, TIOCLGET, &flags); 77721495Sjmacd original_lmode = flags; 77821495Sjmacd flags |= LPASS8; 77921495Sjmacd ioctl (tty, TIOCLSET, &flags); 78021495Sjmacd } 78121495Sjmacd# endif /* TIOCLGET && LPASS8 */ 78221495Sjmacd 78321495Sjmacd# if defined (TIOCGETC) 78421495Sjmacd { 78521495Sjmacd struct tchars temp; 78621495Sjmacd 78721495Sjmacd ioctl (tty, TIOCGETC, &original_tchars); 78821495Sjmacd temp = original_tchars; 78921495Sjmacd 79021495Sjmacd /* C-s and C-q. */ 79121495Sjmacd temp.t_startc = temp.t_stopc = -1; 79221495Sjmacd 79321495Sjmacd /* Often set to C-d. */ 79421495Sjmacd temp.t_eofc = -1; 79521495Sjmacd 79621495Sjmacd /* If the a quit or interrupt character conflicts with one of our 79721495Sjmacd commands, then make it go away. */ 79821495Sjmacd if (temp.t_intrc == '\177') 79921495Sjmacd temp.t_intrc = -1; 80021495Sjmacd 80121495Sjmacd if (temp.t_quitc == '\177') 80221495Sjmacd temp.t_quitc = -1; 80321495Sjmacd 80421495Sjmacd ioctl (tty, TIOCSETC, &temp); 80521495Sjmacd } 80621495Sjmacd# endif /* TIOCGETC */ 80721495Sjmacd 80821495Sjmacd# if defined (TIOCGLTC) 80921495Sjmacd { 81021495Sjmacd struct ltchars temp; 81121495Sjmacd 81221495Sjmacd ioctl (tty, TIOCGLTC, &original_ltchars); 81321495Sjmacd temp = original_ltchars; 81421495Sjmacd 81521495Sjmacd /* Make the interrupt keys go away. Just enough to make people happy. */ 81642664Smarkm temp.t_lnextc = -1; /* C-v. */ 81742664Smarkm temp.t_dsuspc = -1; /* C-y. */ 81842664Smarkm temp.t_flushc = -1; /* C-o. */ 81921495Sjmacd ioctl (tty, TIOCSLTC, &temp); 82021495Sjmacd } 82121495Sjmacd# endif /* TIOCGLTC */ 82221495Sjmacd 82321495Sjmacd ttybuff.sg_flags &= ~ECHO; 82421495Sjmacd ttybuff.sg_flags |= CBREAK; 82521495Sjmacd ioctl (tty, TIOCSETN, &ttybuff); 82621495Sjmacd#endif /* !HAVE_TERMIOS_H && !HAVE_TERMIO_H */ 82721495Sjmacd} 82821495Sjmacd 82921495Sjmacd/* Restore the tty settings back to what they were before we started using 83021495Sjmacd this terminal. */ 83121495Sjmacdvoid 832146520Sruterminal_unprep_terminal (void) 83321495Sjmacd{ 83421495Sjmacd int tty; 83521495Sjmacd 83621495Sjmacd if (terminal_unprep_terminal_hook) 83721495Sjmacd { 83821495Sjmacd (*terminal_unprep_terminal_hook) (); 83921495Sjmacd return; 84021495Sjmacd } 84121495Sjmacd 84221495Sjmacd tty = fileno (stdin); 84321495Sjmacd 84421495Sjmacd#if defined (HAVE_TERMIOS_H) 84521495Sjmacd tcsetattr (tty, TCSANOW, &original_termios); 84621495Sjmacd#else 84721495Sjmacd# if defined (HAVE_TERMIO_H) 84821495Sjmacd ioctl (tty, TCSETA, &original_termio); 84921495Sjmacd# else /* !HAVE_TERMIO_H */ 85021495Sjmacd ioctl (tty, TIOCGETP, &ttybuff); 85121495Sjmacd ttybuff.sg_flags = original_tty_flags; 85221495Sjmacd ioctl (tty, TIOCSETN, &ttybuff); 85321495Sjmacd 85421495Sjmacd# if defined (TIOCGETC) 85521495Sjmacd ioctl (tty, TIOCSETC, &original_tchars); 85621495Sjmacd# endif /* TIOCGETC */ 85721495Sjmacd 85821495Sjmacd# if defined (TIOCGLTC) 85921495Sjmacd ioctl (tty, TIOCSLTC, &original_ltchars); 86021495Sjmacd# endif /* TIOCGLTC */ 86121495Sjmacd 86221495Sjmacd# if defined (TIOCLGET) && defined (LPASS8) 86321495Sjmacd ioctl (tty, TIOCLSET, &original_lmode); 86421495Sjmacd# endif /* TIOCLGET && LPASS8 */ 86521495Sjmacd 86621495Sjmacd# endif /* !HAVE_TERMIO_H */ 86721495Sjmacd#endif /* !HAVE_TERMIOS_H */ 86821495Sjmacd terminal_end_using_terminal (); 86921495Sjmacd} 87042699Smarkm 87156164Sru#ifdef __MSDOS__ 87256164Sru# include "pcterm.c" 87356164Sru#endif 874