terminal.c revision 47558
121308Sache/* terminal.c -- controlling the terminal with termcap. */ 221308Sache 321308Sache/* Copyright (C) 1996 Free Software Foundation, Inc. 421308Sache 521308Sache This file is part of the GNU Readline Library, a library for 621308Sache reading lines of text with interactive input and history editing. 721308Sache 821308Sache The GNU Readline Library is free software; you can redistribute it 921308Sache and/or modify it under the terms of the GNU General Public License 1021308Sache as published by the Free Software Foundation; either version 1, or 1121308Sache (at your option) any later version. 1221308Sache 1321308Sache The GNU Readline Library is distributed in the hope that it will be 1421308Sache useful, but WITHOUT ANY WARRANTY; without even the implied warranty 1521308Sache of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1621308Sache GNU General Public License for more details. 1721308Sache 1821308Sache The GNU General Public License is often shipped with GNU software, and 1921308Sache is generally kept in a file called COPYING or LICENSE. If you do not 2021308Sache have a copy of the license, write to the Free Software Foundation, 2121308Sache 675 Mass Ave, Cambridge, MA 02139, USA. */ 2221308Sache#define READLINE_LIBRARY 2321308Sache 2421308Sache#if defined (HAVE_CONFIG_H) 2521308Sache# include <config.h> 2621308Sache#endif 2721308Sache 2821308Sache#include <sys/types.h> 2921308Sache#include "posixstat.h" 3021308Sache#include <fcntl.h> 3121308Sache#if defined (HAVE_SYS_FILE_H) 3221308Sache# include <sys/file.h> 3321308Sache#endif /* HAVE_SYS_FILE_H */ 3421308Sache 3521308Sache#if defined (HAVE_UNISTD_H) 3621308Sache# include <unistd.h> 3721308Sache#endif /* HAVE_UNISTD_H */ 3821308Sache 3921308Sache#if defined (HAVE_STDLIB_H) 4021308Sache# include <stdlib.h> 4121308Sache#else 4221308Sache# include "ansi_stdlib.h" 4321308Sache#endif /* HAVE_STDLIB_H */ 4421308Sache 4521308Sache#if defined (HAVE_LOCALE_H) 4621308Sache# include <locale.h> 4721308Sache#endif 4821308Sache 4921308Sache#include <signal.h> 5021308Sache#include <stdio.h> 5121308Sache#include <setjmp.h> 5221308Sache 5321308Sache/* System-specific feature definitions and include files. */ 5421308Sache#include "rldefs.h" 5521308Sache 5626497Sache#if defined (GWINSZ_IN_SYS_IOCTL) && !defined (TIOCGWINSZ) 5726497Sache# include <sys/ioctl.h> 5826497Sache#endif /* GWINSZ_IN_SYS_IOCTL && !TIOCGWINSZ */ 5926497Sache 6026497Sache#include "rltty.h" 6121308Sache#include "tcap.h" 6221308Sache 6321308Sache/* Some standard library routines. */ 6421308Sache#include "readline.h" 6521308Sache#include "history.h" 6621308Sache 6721308Sache/* Variables and functions imported from readline.c */ 6821308Sacheextern FILE *_rl_in_stream, *_rl_out_stream; 6921308Sacheextern int readline_echoing_p; 7021308Sacheextern int _rl_bell_preference; 7121308Sacheextern Keymap _rl_keymap; 7221308Sache 7326497Sache/* Functions imported from bind.c */ 7426497Sacheextern void _rl_bind_if_unbound (); 7526497Sache 7626497Sache/* Functions imported from shell.c */ 7726497Sacheextern void set_lines_and_columns (); 7826497Sacheextern char *get_env_value (); 7926497Sache 8021308Sache/* **************************************************************** */ 8121308Sache/* */ 8221308Sache/* Terminal and Termcap */ 8321308Sache/* */ 8421308Sache/* **************************************************************** */ 8521308Sache 8621308Sachestatic char *term_buffer = (char *)NULL; 8721308Sachestatic char *term_string_buffer = (char *)NULL; 8821308Sache 8921308Sachestatic int tcap_initialized; 9021308Sache 9121308Sache/* Non-zero means this terminal can't really do anything. */ 9221308Sachestatic int dumb_term; 9321308Sache 9421308Sache#if !defined (__linux__) 9526497Sache# if defined (__EMX__) || defined (NEED_EXTERN_PC) 9626497Sacheextern 9726497Sache# endif /* __EMX__ || NEED_EXTERN_PC */ 9826497Sachechar PC, *BC, *UP; 9921308Sache#endif /* __linux__ */ 10021308Sache 10121308Sache/* Some strings to control terminal actions. These are output by tputs (). */ 10221308Sachechar *term_goto, *term_clreol, *term_cr, *term_clrpag, *term_backspace; 10321308Sachechar *term_pc; 10421308Sache 10521308Sache/* Non-zero if we determine that the terminal can do character insertion. */ 10621308Sacheint terminal_can_insert = 0; 10721308Sache 10821308Sache/* How to insert characters. */ 10921308Sachechar *term_im, *term_ei, *term_ic, *term_ip, *term_IC; 11021308Sache 11121308Sache/* How to delete characters. */ 11221308Sachechar *term_dc, *term_DC; 11321308Sache 11421308Sache#if defined (HACK_TERMCAP_MOTION) 11521308Sachechar *term_forward_char; 11621308Sache#endif /* HACK_TERMCAP_MOTION */ 11721308Sache 11821308Sache/* How to go up a line. */ 11921308Sachechar *term_up; 12021308Sache 12121308Sache/* A visible bell, if the terminal can be made to flash the screen. */ 12221308Sachestatic char *visible_bell; 12321308Sache 12421308Sache/* Non-zero means the terminal can auto-wrap lines. */ 12521308Sacheint _rl_term_autowrap; 12621308Sache 12721308Sache/* Non-zero means that this terminal has a meta key. */ 12821308Sachestatic int term_has_meta; 12921308Sache 13021308Sache/* The sequences to write to turn on and off the meta key, if this 13121308Sache terminal has one. */ 13221308Sachestatic char *term_mm, *term_mo; 13321308Sache 13421308Sache/* The key sequences output by the arrow keys, if this terminal has any. */ 13521308Sachestatic char *term_ku, *term_kd, *term_kr, *term_kl; 13621308Sache 13721308Sache/* How to initialize and reset the arrow keys, if this terminal has any. */ 13821308Sachestatic char *term_ks, *term_ke; 13921308Sache 14021308Sache/* The key sequences sent by the Home and End keys, if any. */ 14121308Sachestatic char *term_kh, *term_kH; 14221308Sache 14321308Sache/* Variables that hold the screen dimensions, used by the display code. */ 14421308Sacheint screenwidth, screenheight, screenchars; 14521308Sache 14621308Sache/* Non-zero means the user wants to enable the keypad. */ 14721308Sacheint _rl_enable_keypad; 14821308Sache 14921308Sache/* Non-zero means the user wants to enable a meta key. */ 15021308Sacheint _rl_enable_meta = 1; 15121308Sache 15221308Sache/* Get readline's idea of the screen size. TTY is a file descriptor open 15321308Sache to the terminal. If IGNORE_ENV is true, we do not pay attention to the 15421308Sache values of $LINES and $COLUMNS. The tests for TERM_STRING_BUFFER being 15521308Sache non-null serve to check whether or not we have initialized termcap. */ 15621308Sachevoid 15721308Sache_rl_get_screen_size (tty, ignore_env) 15821308Sache int tty, ignore_env; 15921308Sache{ 16021308Sache char *ss; 16121308Sache#if defined (TIOCGWINSZ) 16221308Sache struct winsize window_size; 16321308Sache#endif /* TIOCGWINSZ */ 16426497Sache#if defined (__EMX__) 16526497Sache int sz[2]; 16626497Sache#endif 16721308Sache 16821308Sache#if defined (TIOCGWINSZ) 16921308Sache if (ioctl (tty, TIOCGWINSZ, &window_size) == 0) 17021308Sache { 17121308Sache screenwidth = (int) window_size.ws_col; 17221308Sache screenheight = (int) window_size.ws_row; 17321308Sache } 17421308Sache#endif /* TIOCGWINSZ */ 17521308Sache 17626497Sache#if defined (__EMX__) 17726497Sache _scrsize (sz); 17826497Sache screenwidth = sz[0]; 17926497Sache screenheight = sz[1]; 18026497Sache#endif 18126497Sache 18221308Sache /* Environment variable COLUMNS overrides setting of "co" if IGNORE_ENV 18321308Sache is unset. */ 18421308Sache if (screenwidth <= 0) 18521308Sache { 18626497Sache if (ignore_env == 0 && (ss = get_env_value ("COLUMNS"))) 18721308Sache screenwidth = atoi (ss); 18821308Sache 18921308Sache if (screenwidth <= 0 && term_string_buffer) 19021308Sache screenwidth = tgetnum ("co"); 19121308Sache } 19221308Sache 19321308Sache /* Environment variable LINES overrides setting of "li" if IGNORE_ENV 19421308Sache is unset. */ 19521308Sache if (screenheight <= 0) 19621308Sache { 19726497Sache if (ignore_env == 0 && (ss = get_env_value ("LINES"))) 19821308Sache screenheight = atoi (ss); 19921308Sache 20021308Sache if (screenheight <= 0 && term_string_buffer) 20121308Sache screenheight = tgetnum ("li"); 20221308Sache } 20321308Sache 20421308Sache /* If all else fails, default to 80x24 terminal. */ 20521308Sache if (screenwidth <= 1) 20621308Sache screenwidth = 80; 20721308Sache 20821308Sache if (screenheight <= 0) 20921308Sache screenheight = 24; 21021308Sache 21121308Sache /* If we're being compiled as part of bash, set the environment 21221308Sache variables $LINES and $COLUMNS to new values. Otherwise, just 21321308Sache do a pair of putenv () or setenv () calls. */ 21421308Sache set_lines_and_columns (screenheight, screenwidth); 21521308Sache 21621308Sache if (!_rl_term_autowrap) 21721308Sache screenwidth--; 21821308Sache 21921308Sache screenchars = screenwidth * screenheight; 22021308Sache} 22121308Sache 22221308Sachevoid 22321308Sache_rl_set_screen_size (rows, cols) 22421308Sache int rows, cols; 22521308Sache{ 22621308Sache screenheight = rows; 22721308Sache screenwidth = cols; 22821308Sache 22921308Sache if (_rl_term_autowrap == 0) 23021308Sache screenwidth--; 23121308Sache 23221308Sache screenchars = screenwidth * screenheight; 23321308Sache} 23421308Sache 23547558Sachevoid 23647558Sacherl_resize_terminal () 23747558Sache{ 23847558Sache if (readline_echoing_p) 23947558Sache { 24047558Sache _rl_get_screen_size (fileno (rl_instream), 1); 24147558Sache _rl_redisplay_after_sigwinch (); 24247558Sache } 24347558Sache} 24447558Sache 24521308Sachestruct _tc_string { 24621308Sache char *tc_var; 24721308Sache char **tc_value; 24821308Sache}; 24921308Sache 25021308Sache/* This should be kept sorted, just in case we decide to change the 25121308Sache search algorithm to something smarter. */ 25221308Sachestatic struct _tc_string tc_strings[] = 25321308Sache{ 25421308Sache "DC", &term_DC, 25521308Sache "IC", &term_IC, 25621308Sache "ce", &term_clreol, 25721308Sache "cl", &term_clrpag, 25821308Sache "cr", &term_cr, 25921308Sache "dc", &term_dc, 26021308Sache "ei", &term_ei, 26121308Sache "ic", &term_ic, 26221308Sache "im", &term_im, 26321308Sache "kd", &term_kd, 26421308Sache "kh", &term_kh, /* home */ 26521308Sache "kH", &term_kH, /* end */ 26621308Sache "kl", &term_kl, 26721308Sache "kr", &term_kr, 26821308Sache "ku", &term_ku, 26921308Sache "ks", &term_ks, 27021308Sache "ke", &term_ke, 27121308Sache "le", &term_backspace, 27221308Sache "mm", &term_mm, 27321308Sache "mo", &term_mo, 27421308Sache#if defined (HACK_TERMCAP_MOTION) 27521308Sache "nd", &term_forward_char, 27621308Sache#endif 27721308Sache "pc", &term_pc, 27821308Sache "up", &term_up, 27921308Sache "vb", &visible_bell, 28021308Sache}; 28121308Sache 28221308Sache#define NUM_TC_STRINGS (sizeof (tc_strings) / sizeof (struct _tc_string)) 28321308Sache 28421308Sache/* Read the desired terminal capability strings into BP. The capabilities 28521308Sache are described in the TC_STRINGS table. */ 28621308Sachestatic void 28721308Sacheget_term_capabilities (bp) 28821308Sache char **bp; 28921308Sache{ 29021308Sache register int i; 29121308Sache 29221308Sache for (i = 0; i < NUM_TC_STRINGS; i++) 29321308Sache *(tc_strings[i].tc_value) = tgetstr (tc_strings[i].tc_var, bp); 29421308Sache tcap_initialized = 1; 29521308Sache} 29621308Sache 29721308Sacheint 29821308Sache_rl_init_terminal_io (terminal_name) 29921308Sache char *terminal_name; 30021308Sache{ 30121308Sache#if defined (__GO32__) 30221308Sache screenwidth = ScreenCols (); 30321308Sache screenheight = ScreenRows (); 30421308Sache screenchars = screenwidth * screenheight; 30521308Sache term_cr = "\r"; 30621308Sache term_im = term_ei = term_ic = term_IC = (char *)NULL; 30721308Sache term_up = term_dc = term_DC = visible_bell = (char *)NULL; 30821308Sache 30921308Sache /* Does the __GO32__ have a meta key? I don't know. */ 31021308Sache term_has_meta = 0; 31121308Sache term_mm = term_mo = (char *)NULL; 31221308Sache 31321308Sache /* It probably has arrow keys, but I don't know what they are. */ 31421308Sache term_ku = term_kd = term_kr = term_kl = (char *)NULL; 31521308Sache 31621308Sache#if defined (HACK_TERMCAP_MOTION) 31721308Sache term_forward_char = (char *)NULL; 31821308Sache#endif /* HACK_TERMCAP_MOTION */ 31921308Sache terminal_can_insert = _rl_term_autowrap = 0; 32021308Sache return; 32121308Sache#else /* !__GO32__ */ 32221308Sache 32321308Sache char *term, *buffer; 32421308Sache int tty; 32521308Sache Keymap xkeymap; 32621308Sache 32726497Sache term = terminal_name ? terminal_name : get_env_value ("TERM"); 32821308Sache 32921308Sache if (term_string_buffer == 0) 33021308Sache term_string_buffer = xmalloc (2032); 33121308Sache 33221308Sache if (term_buffer == 0) 33321308Sache term_buffer = xmalloc (4080); 33421308Sache 33521308Sache buffer = term_string_buffer; 33621308Sache 33721308Sache term_clrpag = term_cr = term_clreol = (char *)NULL; 33821308Sache 33921308Sache if (term == 0) 34021308Sache term = "dumb"; 34121308Sache 34221308Sache if (tgetent (term_buffer, term) <= 0) 34321308Sache { 34421308Sache dumb_term = 1; 34521308Sache screenwidth = 79; 34621308Sache screenheight = 24; 34721308Sache screenchars = 79 * 24; 34821308Sache term_cr = "\r"; 34921308Sache term_im = term_ei = term_ic = term_IC = (char *)NULL; 35021308Sache term_up = term_dc = term_DC = visible_bell = (char *)NULL; 35121308Sache term_ku = term_kd = term_kl = term_kr = (char *)NULL; 35221308Sache#if defined (HACK_TERMCAP_MOTION) 35321308Sache term_forward_char = (char *)NULL; 35421308Sache#endif 35521308Sache terminal_can_insert = 0; 35621308Sache return 0; 35721308Sache } 35821308Sache 35921308Sache get_term_capabilities (&buffer); 36021308Sache 36121308Sache /* Set up the variables that the termcap library expects the application 36221308Sache to provide. */ 36321308Sache PC = term_pc ? *term_pc : 0; 36421308Sache BC = term_backspace; 36521308Sache UP = term_up; 36621308Sache 36721308Sache if (!term_cr) 36821308Sache term_cr = "\r"; 36921308Sache 37021308Sache tty = rl_instream ? fileno (rl_instream) : 0; 37121308Sache 37221308Sache screenwidth = screenheight = 0; 37321308Sache 37421308Sache _rl_term_autowrap = tgetflag ("am") && tgetflag ("xn"); 37521308Sache 37621308Sache _rl_get_screen_size (tty, 0); 37721308Sache 37821308Sache /* "An application program can assume that the terminal can do 37921308Sache character insertion if *any one of* the capabilities `IC', 38021308Sache `im', `ic' or `ip' is provided." But we can't do anything if 38121308Sache only `ip' is provided, so... */ 38221308Sache terminal_can_insert = (term_IC || term_im || term_ic); 38321308Sache 38421308Sache /* Check to see if this terminal has a meta key and clear the capability 38521308Sache variables if there is none. */ 38621308Sache term_has_meta = (tgetflag ("km") || tgetflag ("MT")); 38721308Sache if (!term_has_meta) 38821308Sache term_mm = term_mo = (char *)NULL; 38921308Sache 39021308Sache /* Attempt to find and bind the arrow keys. Do not override already 39121308Sache bound keys in an overzealous attempt, however. */ 39221308Sache xkeymap = _rl_keymap; 39321308Sache 39421308Sache _rl_keymap = emacs_standard_keymap; 39521308Sache _rl_bind_if_unbound (term_ku, rl_get_previous_history); 39621308Sache _rl_bind_if_unbound (term_kd, rl_get_next_history); 39721308Sache _rl_bind_if_unbound (term_kr, rl_forward); 39821308Sache _rl_bind_if_unbound (term_kl, rl_backward); 39921308Sache 40021308Sache _rl_bind_if_unbound (term_kh, rl_beg_of_line); /* Home */ 40121308Sache _rl_bind_if_unbound (term_kH, rl_end_of_line); /* End */ 40221308Sache 40321308Sache#if defined (VI_MODE) 40421308Sache _rl_keymap = vi_movement_keymap; 40521308Sache _rl_bind_if_unbound (term_ku, rl_get_previous_history); 40621308Sache _rl_bind_if_unbound (term_kd, rl_get_next_history); 40721308Sache _rl_bind_if_unbound (term_kr, rl_forward); 40821308Sache _rl_bind_if_unbound (term_kl, rl_backward); 40921308Sache 41021308Sache _rl_bind_if_unbound (term_kh, rl_beg_of_line); /* Home */ 41121308Sache _rl_bind_if_unbound (term_kH, rl_end_of_line); /* End */ 41221308Sache#endif /* VI_MODE */ 41321308Sache 41421308Sache _rl_keymap = xkeymap; 41521308Sache 41621308Sache#endif /* !__GO32__ */ 41721308Sache return 0; 41821308Sache} 41921308Sache 42021308Sachechar * 42121308Sacherl_get_termcap (cap) 42221308Sache char *cap; 42321308Sache{ 42421308Sache register int i; 42521308Sache 42621308Sache if (tcap_initialized == 0) 42721308Sache return ((char *)NULL); 42821308Sache for (i = 0; i < NUM_TC_STRINGS; i++) 42921308Sache { 43021308Sache if (tc_strings[i].tc_var[0] == cap[0] && strcmp (tc_strings[i].tc_var, cap) == 0) 43121308Sache return *(tc_strings[i].tc_value); 43221308Sache } 43321308Sache return ((char *)NULL); 43421308Sache} 43521308Sache 43626497Sache/* Re-initialize the terminal considering that the TERM/TERMCAP variable 43726497Sache has changed. */ 43826497Sacheint 43926497Sacherl_reset_terminal (terminal_name) 44026497Sache char *terminal_name; 44126497Sache{ 44226497Sache _rl_init_terminal_io (terminal_name); 44326497Sache return 0; 44426497Sache} 44526497Sache 44621308Sache/* A function for the use of tputs () */ 44735486Sache#ifdef _MINIX 44835486Sachevoid 44935486Sache_rl_output_character_function (c) 45035486Sache int c; 45135486Sache{ 45235486Sache putc (c, _rl_out_stream); 45335486Sache} 45435486Sache#else /* !_MINIX */ 45521308Sacheint 45621308Sache_rl_output_character_function (c) 45721308Sache int c; 45821308Sache{ 45921308Sache return putc (c, _rl_out_stream); 46021308Sache} 46135486Sache#endif /* !_MINIX */ 46221308Sache/* Write COUNT characters from STRING to the output stream. */ 46321308Sachevoid 46421308Sache_rl_output_some_chars (string, count) 46521308Sache char *string; 46621308Sache int count; 46721308Sache{ 46821308Sache fwrite (string, 1, count, _rl_out_stream); 46921308Sache} 47021308Sache 47121308Sache/* Move the cursor back. */ 47221308Sacheint 47321308Sache_rl_backspace (count) 47421308Sache int count; 47521308Sache{ 47621308Sache register int i; 47721308Sache 47821308Sache#if !defined (__GO32__) 47921308Sache if (term_backspace) 48021308Sache for (i = 0; i < count; i++) 48121308Sache tputs (term_backspace, 1, _rl_output_character_function); 48221308Sache else 48321308Sache#endif /* !__GO32__ */ 48421308Sache for (i = 0; i < count; i++) 48521308Sache putc ('\b', _rl_out_stream); 48621308Sache return 0; 48721308Sache} 48821308Sache 48921308Sache/* Move to the start of the next line. */ 49021308Sacheint 49121308Sachecrlf () 49221308Sache{ 49321308Sache#if defined (NEW_TTY_DRIVER) 49421308Sache if (term_cr) 49521308Sache tputs (term_cr, 1, _rl_output_character_function); 49621308Sache#endif /* NEW_TTY_DRIVER */ 49721308Sache putc ('\n', _rl_out_stream); 49821308Sache return 0; 49921308Sache} 50021308Sache 50121308Sache/* Ring the terminal bell. */ 50221308Sacheint 50321308Sacheding () 50421308Sache{ 50521308Sache if (readline_echoing_p) 50621308Sache { 50721308Sache#if !defined (__GO32__) 50821308Sache switch (_rl_bell_preference) 50921308Sache { 51021308Sache case NO_BELL: 51121308Sache default: 51221308Sache break; 51321308Sache case VISIBLE_BELL: 51421308Sache if (visible_bell) 51521308Sache { 51621308Sache tputs (visible_bell, 1, _rl_output_character_function); 51721308Sache break; 51821308Sache } 51921308Sache /* FALLTHROUGH */ 52021308Sache case AUDIBLE_BELL: 52121308Sache fprintf (stderr, "\007"); 52221308Sache fflush (stderr); 52321308Sache break; 52421308Sache } 52521308Sache#else /* __GO32__ */ 52621308Sache fprintf (stderr, "\007"); 52721308Sache fflush (stderr); 52821308Sache#endif /* __GO32__ */ 52921308Sache return (0); 53021308Sache } 53121308Sache return (-1); 53221308Sache} 53321308Sache 53421308Sache/* **************************************************************** */ 53521308Sache/* */ 53621308Sache/* Controlling the Meta Key and Keypad */ 53721308Sache/* */ 53821308Sache/* **************************************************************** */ 53921308Sache 54026497Sachevoid 54121308Sache_rl_enable_meta_key () 54221308Sache{ 54321308Sache if (term_has_meta && term_mm) 54435486Sache tputs (term_mm, 1, _rl_output_character_function); 54521308Sache} 54621308Sache 54721308Sachevoid 54821308Sache_rl_control_keypad (on) 54921308Sache int on; 55021308Sache{ 55121308Sache if (on && term_ks) 55235486Sache tputs (term_ks, 1, _rl_output_character_function); 55321308Sache else if (!on && term_ke) 55435486Sache tputs (term_ke, 1, _rl_output_character_function); 55521308Sache} 556