From da51dc9cf202772f60bd2da975dbef257bd9237c Mon Sep 17 00:00:00 2001 From: Eliseo Martínez Date: Mon, 12 May 2014 02:25:17 +0200 Subject: Introduce nvim namespace: Move files. Move files from src/ to src/nvim/. - src/nvim/ becomes the new root dir for nvim executable sources. - src/libnvim/ is planned to become root dir of the neovim library. --- src/nvim/term.c | 4732 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 4732 insertions(+) create mode 100644 src/nvim/term.c (limited to 'src/nvim/term.c') diff --git a/src/nvim/term.c b/src/nvim/term.c new file mode 100644 index 0000000000..61dc6f4631 --- /dev/null +++ b/src/nvim/term.c @@ -0,0 +1,4732 @@ +/* + * VIM - Vi IMproved by Bram Moolenaar + * + * Do ":help uganda" in Vim to read copying and usage conditions. + * Do ":help credits" in Vim to see a list of people who contributed. + * See README.txt for an overview of the Vim source code. + */ +/* + * + * term.c: functions for controlling the terminal + * + * primitive termcap support for Win32 included + * + * NOTE: padding and variable substitution is not performed, + * when compiling without HAVE_TGETENT, we use tputs() and tgoto() dummies. + */ + +/* + * Some systems have a prototype for tgetstr() with (char *) instead of + * (char **). This define removes that prototype. We include our own prototype + * below. + */ + +#define tgetstr tgetstr_defined_wrong +#include + +#include "vim.h" +#include "term.h" +#include "buffer.h" +#include "charset.h" +#include "edit.h" +#include "eval.h" +#include "ex_getln.h" +#include "fileio.h" +#include "getchar.h" +#include "message.h" +#include "misc2.h" +#include "garray.h" +#include "keymap.h" +#include "memory.h" +#include "move.h" +#include "normal.h" +#include "option.h" +#include "os_unix.h" +#include "popupmnu.h" +#include "screen.h" +#include "syntax.h" +#include "ui.h" +#include "window.h" +#include "os/os.h" +#include "os/time.h" + +#ifdef HAVE_TGETENT +# ifdef HAVE_TERMIOS_H +# include /* seems to be required for some Linux */ +# endif +# ifdef HAVE_TERMCAP_H +# include +# endif + +/* + * A few linux systems define outfuntype in termcap.h to be used as the third + * argument for tputs(). + */ +# define TPUTSFUNCAST (int (*)()) +#endif + +#undef tgetstr + +/* + * Here are the builtin termcap entries. They are not stored as complete + * structures with all entries, as such a structure is too big. + * + * The entries are compact, therefore they normally are included even when + * HAVE_TGETENT is defined. When HAVE_TGETENT is defined, the builtin entries + * can be accessed with "builtin_amiga", "builtin_ansi", "builtin_debug", etc. + * + * Each termcap is a list of builtin_term structures. It always starts with + * KS_NAME, which separates the entries. See parse_builtin_tcap() for all + * details. + * bt_entry is either a KS_xxx code (>= 0), or a K_xxx code. + * + * Entries marked with "guessed" may be wrong. + */ +struct builtin_term { + int bt_entry; + char *bt_string; +}; + +/* start of keys that are not directly used by Vim but can be mapped */ +#define BT_EXTRA_KEYS 0x101 + +static struct builtin_term *find_builtin_term(char_u *name); +static void parse_builtin_tcap(char_u *s); +static void term_color(char_u *s, int n); +static void gather_termleader(void); +static void req_codes_from_term(void); +static void req_more_codes_from_term(void); +static void got_code_from_term(char_u *code, int len); +static void check_for_codes_from_term(void); +#if defined(FEAT_GUI) \ + || (defined(FEAT_MOUSE) && (!defined(UNIX) || defined(FEAT_MOUSE_XTERM) \ + || defined(FEAT_MOUSE_GPM) || defined(FEAT_SYSMOUSE))) +static int get_bytes_from_buf(char_u *, char_u *, int); +#endif +static void del_termcode_idx(int idx); +static int term_is_builtin(char_u *name); +static int term_7to8bit(char_u *p); +static void switch_to_8bit(void); + +#ifdef HAVE_TGETENT +static char_u *tgetent_error(char_u *, char_u *); + +/* + * Here is our own prototype for tgetstr(), any prototypes from the include + * files have been disabled by the define at the start of this file. + */ +char *tgetstr(char *, char **); + +/* Change this to "if 1" to debug what happens with termresponse. */ +# define LOG_TR(msg) +/* Request Terminal Version status: */ +# define CRV_GET 1 /* send T_CRV when switched to RAW mode */ +# define CRV_SENT 2 /* did send T_CRV, waiting for answer */ +# define CRV_GOT 3 /* received T_CRV response */ +static int crv_status = CRV_GET; +/* Request Cursor position report: */ +# define U7_GET 1 /* send T_U7 when switched to RAW mode */ +# define U7_SENT 2 /* did send T_U7, waiting for answer */ +# define U7_GOT 3 /* received T_U7 response */ +static int u7_status = U7_GET; + +/* + * Don't declare these variables if termcap.h contains them. + * Autoconf checks if these variables should be declared extern (not all + * systems have them). + * Some versions define ospeed to be speed_t, but that is incompatible with + * BSD, where ospeed is short and speed_t is long. + */ +# ifndef HAVE_OSPEED +# ifdef OSPEED_EXTERN +extern short ospeed; +# else +short ospeed; +# endif +# endif +# ifndef HAVE_UP_BC_PC +# ifdef UP_BC_PC_EXTERN +extern char *UP, *BC, PC; +# else +char *UP, *BC, PC; +# endif +# endif + +# define TGETSTR(s, p) vim_tgetstr((s), (p)) +# define TGETENT(b, t) tgetent((char *)(b), (char *)(t)) +static char_u *vim_tgetstr(char *s, char_u **pp); +#endif /* HAVE_TGETENT */ + +static int detected_8bit = FALSE; /* detected 8-bit terminal */ + +static struct builtin_term builtin_termcaps[] = +{ + + +#ifndef NO_BUILTIN_TCAPS + +# if defined(ALL_BUILTIN_TCAPS) + /* + * Amiga console window, default for Amiga + */ + {(int)KS_NAME, "amiga"}, + {(int)KS_CE, "\033[K"}, + {(int)KS_CD, "\033[J"}, + {(int)KS_AL, "\033[L"}, +# ifdef TERMINFO + {(int)KS_CAL, "\033[%p1%dL"}, +# else + {(int)KS_CAL, "\033[%dL"}, +# endif + {(int)KS_DL, "\033[M"}, +# ifdef TERMINFO + {(int)KS_CDL, "\033[%p1%dM"}, +# else + {(int)KS_CDL, "\033[%dM"}, +# endif + {(int)KS_CL, "\014"}, + {(int)KS_VI, "\033[0 p"}, + {(int)KS_VE, "\033[1 p"}, + {(int)KS_ME, "\033[0m"}, + {(int)KS_MR, "\033[7m"}, + {(int)KS_MD, "\033[1m"}, + {(int)KS_SE, "\033[0m"}, + {(int)KS_SO, "\033[33m"}, + {(int)KS_US, "\033[4m"}, + {(int)KS_UE, "\033[0m"}, + {(int)KS_CZH, "\033[3m"}, + {(int)KS_CZR, "\033[0m"}, + {(int)KS_MS, "y"}, + {(int)KS_UT, "y"}, /* guessed */ + {(int)KS_LE, "\b"}, +# ifdef TERMINFO + {(int)KS_CM, "\033[%i%p1%d;%p2%dH"}, +# else + {(int)KS_CM, "\033[%i%d;%dH"}, +# endif +# ifdef TERMINFO + {(int)KS_CRI, "\033[%p1%dC"}, +# else + {(int)KS_CRI, "\033[%dC"}, +# endif + {K_UP, "\233A"}, + {K_DOWN, "\233B"}, + {K_LEFT, "\233D"}, + {K_RIGHT, "\233C"}, + {K_S_UP, "\233T"}, + {K_S_DOWN, "\233S"}, + {K_S_LEFT, "\233 A"}, + {K_S_RIGHT, "\233 @"}, + {K_S_TAB, "\233Z"}, + {K_F1, "\233\060~"}, /* some compilers don't dig "\2330" */ + {K_F2, "\233\061~"}, + {K_F3, "\233\062~"}, + {K_F4, "\233\063~"}, + {K_F5, "\233\064~"}, + {K_F6, "\233\065~"}, + {K_F7, "\233\066~"}, + {K_F8, "\233\067~"}, + {K_F9, "\233\070~"}, + {K_F10, "\233\071~"}, + {K_S_F1, "\233\061\060~"}, + {K_S_F2, "\233\061\061~"}, + {K_S_F3, "\233\061\062~"}, + {K_S_F4, "\233\061\063~"}, + {K_S_F5, "\233\061\064~"}, + {K_S_F6, "\233\061\065~"}, + {K_S_F7, "\233\061\066~"}, + {K_S_F8, "\233\061\067~"}, + {K_S_F9, "\233\061\070~"}, + {K_S_F10, "\233\061\071~"}, + {K_HELP, "\233?~"}, + {K_INS, "\233\064\060~"}, /* 101 key keyboard */ + {K_PAGEUP, "\233\064\061~"}, /* 101 key keyboard */ + {K_PAGEDOWN, "\233\064\062~"}, /* 101 key keyboard */ + {K_HOME, "\233\064\064~"}, /* 101 key keyboard */ + {K_END, "\233\064\065~"}, /* 101 key keyboard */ + + {BT_EXTRA_KEYS, ""}, + {TERMCAP2KEY('#', '2'), "\233\065\064~"}, /* shifted home key */ + {TERMCAP2KEY('#', '3'), "\233\065\060~"}, /* shifted insert key */ + {TERMCAP2KEY('*', '7'), "\233\065\065~"}, /* shifted end key */ +# endif + +# if defined(__BEOS__) || defined(ALL_BUILTIN_TCAPS) + /* + * almost standard ANSI terminal, default for bebox + */ + {(int)KS_NAME, "beos-ansi"}, + {(int)KS_CE, "\033[K"}, + {(int)KS_CD, "\033[J"}, + {(int)KS_AL, "\033[L"}, +# ifdef TERMINFO + {(int)KS_CAL, "\033[%p1%dL"}, +# else + {(int)KS_CAL, "\033[%dL"}, +# endif + {(int)KS_DL, "\033[M"}, +# ifdef TERMINFO + {(int)KS_CDL, "\033[%p1%dM"}, +# else + {(int)KS_CDL, "\033[%dM"}, +# endif +#ifdef BEOS_PR_OR_BETTER +# ifdef TERMINFO + {(int)KS_CS, "\033[%i%p1%d;%p2%dr"}, +# else + {(int)KS_CS, "\033[%i%d;%dr"}, /* scroll region */ +# endif +#endif + {(int)KS_CL, "\033[H\033[2J"}, +#ifdef notyet + {(int)KS_VI, "[VI]"}, /* cursor invisible, VT320: CSI ? 25 l */ + {(int)KS_VE, "[VE]"}, /* cursor visible, VT320: CSI ? 25 h */ +#endif + {(int)KS_ME, "\033[m"}, /* normal mode */ + {(int)KS_MR, "\033[7m"}, /* reverse */ + {(int)KS_MD, "\033[1m"}, /* bold */ + {(int)KS_SO, "\033[31m"}, /* standout mode: red */ + {(int)KS_SE, "\033[m"}, /* standout end */ + {(int)KS_CZH, "\033[35m"}, /* italic: purple */ + {(int)KS_CZR, "\033[m"}, /* italic end */ + {(int)KS_US, "\033[4m"}, /* underscore mode */ + {(int)KS_UE, "\033[m"}, /* underscore end */ + {(int)KS_CCO, "8"}, /* allow 8 colors */ +# ifdef TERMINFO + {(int)KS_CAB, "\033[4%p1%dm"}, /* set background color */ + {(int)KS_CAF, "\033[3%p1%dm"}, /* set foreground color */ +# else + {(int)KS_CAB, "\033[4%dm"}, /* set background color */ + {(int)KS_CAF, "\033[3%dm"}, /* set foreground color */ +# endif + {(int)KS_OP, "\033[m"}, /* reset colors */ + {(int)KS_MS, "y"}, /* safe to move cur in reverse mode */ + {(int)KS_UT, "y"}, /* guessed */ + {(int)KS_LE, "\b"}, +# ifdef TERMINFO + {(int)KS_CM, "\033[%i%p1%d;%p2%dH"}, +# else + {(int)KS_CM, "\033[%i%d;%dH"}, +# endif + {(int)KS_SR, "\033M"}, +# ifdef TERMINFO + {(int)KS_CRI, "\033[%p1%dC"}, +# else + {(int)KS_CRI, "\033[%dC"}, +# endif +#if defined(BEOS_DR8) + {(int)KS_DB, ""}, /* hack! see screen.c */ +#endif + + {K_UP, "\033[A"}, + {K_DOWN, "\033[B"}, + {K_LEFT, "\033[D"}, + {K_RIGHT, "\033[C"}, +# endif + +# if defined(UNIX) || defined(ALL_BUILTIN_TCAPS) || defined(SOME_BUILTIN_TCAPS) + /* + * standard ANSI terminal, default for unix + */ + {(int)KS_NAME, "ansi"}, + {(int)KS_CE, IF_EB("\033[K", ESC_STR "[K")}, + {(int)KS_AL, IF_EB("\033[L", ESC_STR "[L")}, +# ifdef TERMINFO + {(int)KS_CAL, IF_EB("\033[%p1%dL", ESC_STR "[%p1%dL")}, +# else + {(int)KS_CAL, IF_EB("\033[%dL", ESC_STR "[%dL")}, +# endif + {(int)KS_DL, IF_EB("\033[M", ESC_STR "[M")}, +# ifdef TERMINFO + {(int)KS_CDL, IF_EB("\033[%p1%dM", ESC_STR "[%p1%dM")}, +# else + {(int)KS_CDL, IF_EB("\033[%dM", ESC_STR "[%dM")}, +# endif + {(int)KS_CL, IF_EB("\033[H\033[2J", ESC_STR "[H" ESC_STR_nc "[2J")}, + {(int)KS_ME, IF_EB("\033[0m", ESC_STR "[0m")}, + {(int)KS_MR, IF_EB("\033[7m", ESC_STR "[7m")}, + {(int)KS_MS, "y"}, + {(int)KS_UT, "y"}, /* guessed */ + {(int)KS_LE, "\b"}, +# ifdef TERMINFO + {(int)KS_CM, IF_EB("\033[%i%p1%d;%p2%dH", ESC_STR "[%i%p1%d;%p2%dH")}, +# else + {(int)KS_CM, IF_EB("\033[%i%d;%dH", ESC_STR "[%i%d;%dH")}, +# endif +# ifdef TERMINFO + {(int)KS_CRI, IF_EB("\033[%p1%dC", ESC_STR "[%p1%dC")}, +# else + {(int)KS_CRI, IF_EB("\033[%dC", ESC_STR "[%dC")}, +# endif +# endif + +# if defined(ALL_BUILTIN_TCAPS) + /* + * These codes are valid when nansi.sys or equivalent has been installed. + * Function keys on a PC are preceded with a NUL. These are converted into + * K_NUL '\316' in os_inchar(), because we cannot handle NULs in key codes. + * CTRL-arrow is used instead of SHIFT-arrow. + */ + {(int)KS_NAME, "pcansi"}, + {(int)KS_DL, "\033[M"}, + {(int)KS_AL, "\033[L"}, + {(int)KS_CE, "\033[K"}, + {(int)KS_CL, "\033[2J"}, + {(int)KS_ME, "\033[0m"}, + {(int)KS_MR, "\033[5m"}, /* reverse: black on lightgrey */ + {(int)KS_MD, "\033[1m"}, /* bold: white text */ + {(int)KS_SE, "\033[0m"}, /* standout end */ + {(int)KS_SO, "\033[31m"}, /* standout: white on blue */ + {(int)KS_CZH, "\033[34;43m"}, /* italic mode: blue text on yellow */ + {(int)KS_CZR, "\033[0m"}, /* italic mode end */ + {(int)KS_US, "\033[36;41m"}, /* underscore mode: cyan text on red */ + {(int)KS_UE, "\033[0m"}, /* underscore mode end */ + {(int)KS_CCO, "8"}, /* allow 8 colors */ +# ifdef TERMINFO + {(int)KS_CAB, "\033[4%p1%dm"}, /* set background color */ + {(int)KS_CAF, "\033[3%p1%dm"}, /* set foreground color */ +# else + {(int)KS_CAB, "\033[4%dm"}, /* set background color */ + {(int)KS_CAF, "\033[3%dm"}, /* set foreground color */ +# endif + {(int)KS_OP, "\033[0m"}, /* reset colors */ + {(int)KS_MS, "y"}, + {(int)KS_UT, "y"}, /* guessed */ + {(int)KS_LE, "\b"}, +# ifdef TERMINFO + {(int)KS_CM, "\033[%i%p1%d;%p2%dH"}, +# else + {(int)KS_CM, "\033[%i%d;%dH"}, +# endif +# ifdef TERMINFO + {(int)KS_CRI, "\033[%p1%dC"}, +# else + {(int)KS_CRI, "\033[%dC"}, +# endif + {K_UP, "\316H"}, + {K_DOWN, "\316P"}, + {K_LEFT, "\316K"}, + {K_RIGHT, "\316M"}, + {K_S_LEFT, "\316s"}, + {K_S_RIGHT, "\316t"}, + {K_F1, "\316;"}, + {K_F2, "\316<"}, + {K_F3, "\316="}, + {K_F4, "\316>"}, + {K_F5, "\316?"}, + {K_F6, "\316@"}, + {K_F7, "\316A"}, + {K_F8, "\316B"}, + {K_F9, "\316C"}, + {K_F10, "\316D"}, + {K_F11, "\316\205"}, /* guessed */ + {K_F12, "\316\206"}, /* guessed */ + {K_S_F1, "\316T"}, + {K_S_F2, "\316U"}, + {K_S_F3, "\316V"}, + {K_S_F4, "\316W"}, + {K_S_F5, "\316X"}, + {K_S_F6, "\316Y"}, + {K_S_F7, "\316Z"}, + {K_S_F8, "\316["}, + {K_S_F9, "\316\\"}, + {K_S_F10, "\316]"}, + {K_S_F11, "\316\207"}, /* guessed */ + {K_S_F12, "\316\210"}, /* guessed */ + {K_INS, "\316R"}, + {K_DEL, "\316S"}, + {K_HOME, "\316G"}, + {K_END, "\316O"}, + {K_PAGEDOWN, "\316Q"}, + {K_PAGEUP, "\316I"}, +# endif + + +# if defined(WIN3264) || defined(ALL_BUILTIN_TCAPS) + /* + * These codes are valid for the Win32 Console . The entries that start with + * ESC | are translated into console calls in os_win32.c. The function keys + * are also translated in os_win32.c. + */ + {(int)KS_NAME, "win32"}, + {(int)KS_CE, "\033|K"}, /* clear to end of line */ + {(int)KS_AL, "\033|L"}, /* add new blank line */ +# ifdef TERMINFO + {(int)KS_CAL, "\033|%p1%dL"}, /* add number of new blank lines */ +# else + {(int)KS_CAL, "\033|%dL"}, /* add number of new blank lines */ +# endif + {(int)KS_DL, "\033|M"}, /* delete line */ +# ifdef TERMINFO + {(int)KS_CDL, "\033|%p1%dM"}, /* delete number of lines */ +# else + {(int)KS_CDL, "\033|%dM"}, /* delete number of lines */ +# endif + {(int)KS_CL, "\033|J"}, /* clear screen */ + {(int)KS_CD, "\033|j"}, /* clear to end of display */ + {(int)KS_VI, "\033|v"}, /* cursor invisible */ + {(int)KS_VE, "\033|V"}, /* cursor visible */ + + {(int)KS_ME, "\033|0m"}, /* normal */ + {(int)KS_MR, "\033|112m"}, /* reverse: black on lightgray */ + {(int)KS_MD, "\033|15m"}, /* bold: white on black */ + {(int)KS_SO, "\033|31m"}, /* standout: white on blue */ + {(int)KS_SE, "\033|0m"}, /* standout end */ + {(int)KS_CZH, "\033|225m"}, /* italic: blue text on yellow */ + {(int)KS_CZR, "\033|0m"}, /* italic end */ + {(int)KS_US, "\033|67m"}, /* underscore: cyan text on red */ + {(int)KS_UE, "\033|0m"}, /* underscore end */ + {(int)KS_CCO, "16"}, /* allow 16 colors */ +# ifdef TERMINFO + {(int)KS_CAB, "\033|%p1%db"}, /* set background color */ + {(int)KS_CAF, "\033|%p1%df"}, /* set foreground color */ +# else + {(int)KS_CAB, "\033|%db"}, /* set background color */ + {(int)KS_CAF, "\033|%df"}, /* set foreground color */ +# endif + + {(int)KS_MS, "y"}, /* save to move cur in reverse mode */ + {(int)KS_UT, "y"}, + {(int)KS_LE, "\b"}, +# ifdef TERMINFO + {(int)KS_CM, "\033|%i%p1%d;%p2%dH"}, /* cursor motion */ +# else + {(int)KS_CM, "\033|%i%d;%dH"}, /* cursor motion */ +# endif + {(int)KS_VB, "\033|B"}, /* visual bell */ + {(int)KS_TI, "\033|S"}, /* put terminal in termcap mode */ + {(int)KS_TE, "\033|E"}, /* out of termcap mode */ +# ifdef TERMINFO + {(int)KS_CS, "\033|%i%p1%d;%p2%dr"}, /* scroll region */ +# else + {(int)KS_CS, "\033|%i%d;%dr"}, /* scroll region */ +# endif + + {K_UP, "\316H"}, + {K_DOWN, "\316P"}, + {K_LEFT, "\316K"}, + {K_RIGHT, "\316M"}, + {K_S_UP, "\316\304"}, + {K_S_DOWN, "\316\317"}, + {K_S_LEFT, "\316\311"}, + {K_C_LEFT, "\316s"}, + {K_S_RIGHT, "\316\313"}, + {K_C_RIGHT, "\316t"}, + {K_S_TAB, "\316\017"}, + {K_F1, "\316;"}, + {K_F2, "\316<"}, + {K_F3, "\316="}, + {K_F4, "\316>"}, + {K_F5, "\316?"}, + {K_F6, "\316@"}, + {K_F7, "\316A"}, + {K_F8, "\316B"}, + {K_F9, "\316C"}, + {K_F10, "\316D"}, + {K_F11, "\316\205"}, + {K_F12, "\316\206"}, + {K_S_F1, "\316T"}, + {K_S_F2, "\316U"}, + {K_S_F3, "\316V"}, + {K_S_F4, "\316W"}, + {K_S_F5, "\316X"}, + {K_S_F6, "\316Y"}, + {K_S_F7, "\316Z"}, + {K_S_F8, "\316["}, + {K_S_F9, "\316\\"}, + {K_S_F10, "\316]"}, + {K_S_F11, "\316\207"}, + {K_S_F12, "\316\210"}, + {K_INS, "\316R"}, + {K_DEL, "\316S"}, + {K_HOME, "\316G"}, + {K_S_HOME, "\316\302"}, + {K_C_HOME, "\316w"}, + {K_END, "\316O"}, + {K_S_END, "\316\315"}, + {K_C_END, "\316u"}, + {K_PAGEDOWN, "\316Q"}, + {K_PAGEUP, "\316I"}, + {K_KPLUS, "\316N"}, + {K_KMINUS, "\316J"}, + {K_KMULTIPLY, "\316\067"}, + {K_K0, "\316\332"}, + {K_K1, "\316\336"}, + {K_K2, "\316\342"}, + {K_K3, "\316\346"}, + {K_K4, "\316\352"}, + {K_K5, "\316\356"}, + {K_K6, "\316\362"}, + {K_K7, "\316\366"}, + {K_K8, "\316\372"}, + {K_K9, "\316\376"}, +# endif + +# if defined(ALL_BUILTIN_TCAPS) + /* + * VT320 is working as an ANSI terminal compatible DEC terminal. + * (it covers VT1x0, VT2x0 and VT3x0 up to VT320 on VMS as well) + * Note: K_F1...K_F5 are for internal use, should not be defined. + * TODO:- rewrite ESC[ codes to CSI + * - keyboard languages (CSI ? 26 n) + */ + {(int)KS_NAME, "vt320"}, + {(int)KS_CE, IF_EB("\033[K", ESC_STR "[K")}, + {(int)KS_AL, IF_EB("\033[L", ESC_STR "[L")}, +# ifdef TERMINFO + {(int)KS_CAL, IF_EB("\033[%p1%dL", ESC_STR "[%p1%dL")}, +# else + {(int)KS_CAL, IF_EB("\033[%dL", ESC_STR "[%dL")}, +# endif + {(int)KS_DL, IF_EB("\033[M", ESC_STR "[M")}, +# ifdef TERMINFO + {(int)KS_CDL, IF_EB("\033[%p1%dM", ESC_STR "[%p1%dM")}, +# else + {(int)KS_CDL, IF_EB("\033[%dM", ESC_STR "[%dM")}, +# endif + {(int)KS_CL, IF_EB("\033[H\033[2J", ESC_STR "[H" ESC_STR_nc "[2J")}, + {(int)KS_CD, IF_EB("\033[J", ESC_STR "[J")}, + {(int)KS_CCO, "8"}, /* allow 8 colors */ + {(int)KS_ME, IF_EB("\033[0m", ESC_STR "[0m")}, + {(int)KS_MR, IF_EB("\033[7m", ESC_STR "[7m")}, + {(int)KS_MD, IF_EB("\033[1m", ESC_STR "[1m")}, /* bold mode */ + {(int)KS_SE, IF_EB("\033[22m", ESC_STR "[22m")}, /* normal mode */ + {(int)KS_UE, IF_EB("\033[24m", ESC_STR "[24m")}, /* exit underscore mode */ + {(int)KS_US, IF_EB("\033[4m", ESC_STR "[4m")}, /* underscore mode */ + {(int)KS_CZH, IF_EB("\033[34;43m", ESC_STR "[34;43m")}, /* italic mode: blue text on yellow */ + {(int)KS_CZR, IF_EB("\033[0m", ESC_STR "[0m")}, /* italic mode end */ + {(int)KS_CAB, IF_EB("\033[4%dm", ESC_STR "[4%dm")}, /* set background color (ANSI) */ + {(int)KS_CAF, IF_EB("\033[3%dm", ESC_STR "[3%dm")}, /* set foreground color (ANSI) */ + {(int)KS_CSB, IF_EB("\033[102;%dm", ESC_STR "[102;%dm")}, /* set screen background color */ + {(int)KS_CSF, IF_EB("\033[101;%dm", ESC_STR "[101;%dm")}, /* set screen foreground color */ + {(int)KS_MS, "y"}, + {(int)KS_UT, "y"}, + {(int)KS_LE, "\b"}, +# ifdef TERMINFO + {(int)KS_CM, IF_EB("\033[%i%p1%d;%p2%dH", + ESC_STR "[%i%p1%d;%p2%dH")}, +# else + {(int)KS_CM, IF_EB("\033[%i%d;%dH", ESC_STR "[%i%d;%dH")}, +# endif +# ifdef TERMINFO + {(int)KS_CRI, IF_EB("\033[%p1%dC", ESC_STR "[%p1%dC")}, +# else + {(int)KS_CRI, IF_EB("\033[%dC", ESC_STR "[%dC")}, +# endif + {K_UP, IF_EB("\033[A", ESC_STR "[A")}, + {K_DOWN, IF_EB("\033[B", ESC_STR "[B")}, + {K_RIGHT, IF_EB("\033[C", ESC_STR "[C")}, + {K_LEFT, IF_EB("\033[D", ESC_STR "[D")}, + {K_F1, IF_EB("\033[11~", ESC_STR "[11~")}, + {K_F2, IF_EB("\033[12~", ESC_STR "[12~")}, + {K_F3, IF_EB("\033[13~", ESC_STR "[13~")}, + {K_F4, IF_EB("\033[14~", ESC_STR "[14~")}, + {K_F5, IF_EB("\033[15~", ESC_STR "[15~")}, + {K_F6, IF_EB("\033[17~", ESC_STR "[17~")}, + {K_F7, IF_EB("\033[18~", ESC_STR "[18~")}, + {K_F8, IF_EB("\033[19~", ESC_STR "[19~")}, + {K_F9, IF_EB("\033[20~", ESC_STR "[20~")}, + {K_F10, IF_EB("\033[21~", ESC_STR "[21~")}, + {K_F11, IF_EB("\033[23~", ESC_STR "[23~")}, + {K_F12, IF_EB("\033[24~", ESC_STR "[24~")}, + {K_F13, IF_EB("\033[25~", ESC_STR "[25~")}, + {K_F14, IF_EB("\033[26~", ESC_STR "[26~")}, + {K_F15, IF_EB("\033[28~", ESC_STR "[28~")}, /* Help */ + {K_F16, IF_EB("\033[29~", ESC_STR "[29~")}, /* Select */ + {K_F17, IF_EB("\033[31~", ESC_STR "[31~")}, + {K_F18, IF_EB("\033[32~", ESC_STR "[32~")}, + {K_F19, IF_EB("\033[33~", ESC_STR "[33~")}, + {K_F20, IF_EB("\033[34~", ESC_STR "[34~")}, + {K_INS, IF_EB("\033[2~", ESC_STR "[2~")}, + {K_DEL, IF_EB("\033[3~", ESC_STR "[3~")}, + {K_HOME, IF_EB("\033[1~", ESC_STR "[1~")}, + {K_END, IF_EB("\033[4~", ESC_STR "[4~")}, + {K_PAGEUP, IF_EB("\033[5~", ESC_STR "[5~")}, + {K_PAGEDOWN, IF_EB("\033[6~", ESC_STR "[6~")}, + {K_KPLUS, IF_EB("\033Ok", ESC_STR "Ok")}, /* keypad plus */ + {K_KMINUS, IF_EB("\033Om", ESC_STR "Om")}, /* keypad minus */ + {K_KDIVIDE, IF_EB("\033Oo", ESC_STR "Oo")}, /* keypad / */ + {K_KMULTIPLY, IF_EB("\033Oj", ESC_STR "Oj")}, /* keypad * */ + {K_KENTER, IF_EB("\033OM", ESC_STR "OM")}, /* keypad Enter */ + {K_BS, "\x7f"}, /* for some reason 0177 doesn't work */ +# endif + +# if defined(ALL_BUILTIN_TCAPS) || defined(__MINT__) + /* + * Ordinary vt52 + */ + {(int)KS_NAME, "vt52"}, + {(int)KS_CE, IF_EB("\033K", ESC_STR "K")}, + {(int)KS_CD, IF_EB("\033J", ESC_STR "J")}, + {(int)KS_CM, IF_EB("\033Y%+ %+ ", ESC_STR "Y%+ %+ ")}, + {(int)KS_LE, "\b"}, + {(int)KS_AL, IF_EB("\033T", ESC_STR "T")}, + {(int)KS_DL, IF_EB("\033U", ESC_STR "U")}, + {(int)KS_CL, IF_EB("\033H\033J", ESC_STR "H" ESC_STR_nc "J")}, + {(int)KS_ME, IF_EB("\033SO", ESC_STR "SO")}, + {(int)KS_MR, IF_EB("\033S2", ESC_STR "S2")}, + {(int)KS_MS, "y"}, +# endif + +# if defined(UNIX) || defined(ALL_BUILTIN_TCAPS) || defined(SOME_BUILTIN_TCAPS) + {(int)KS_NAME, "xterm"}, + {(int)KS_CE, IF_EB("\033[K", ESC_STR "[K")}, + {(int)KS_AL, IF_EB("\033[L", ESC_STR "[L")}, +# ifdef TERMINFO + {(int)KS_CAL, IF_EB("\033[%p1%dL", ESC_STR "[%p1%dL")}, +# else + {(int)KS_CAL, IF_EB("\033[%dL", ESC_STR "[%dL")}, +# endif + {(int)KS_DL, IF_EB("\033[M", ESC_STR "[M")}, +# ifdef TERMINFO + {(int)KS_CDL, IF_EB("\033[%p1%dM", ESC_STR "[%p1%dM")}, +# else + {(int)KS_CDL, IF_EB("\033[%dM", ESC_STR "[%dM")}, +# endif +# ifdef TERMINFO + {(int)KS_CS, IF_EB("\033[%i%p1%d;%p2%dr", + ESC_STR "[%i%p1%d;%p2%dr")}, +# else + {(int)KS_CS, IF_EB("\033[%i%d;%dr", ESC_STR "[%i%d;%dr")}, +# endif + {(int)KS_CL, IF_EB("\033[H\033[2J", ESC_STR "[H" ESC_STR_nc "[2J")}, + {(int)KS_CD, IF_EB("\033[J", ESC_STR "[J")}, + {(int)KS_ME, IF_EB("\033[m", ESC_STR "[m")}, + {(int)KS_MR, IF_EB("\033[7m", ESC_STR "[7m")}, + {(int)KS_MD, IF_EB("\033[1m", ESC_STR "[1m")}, + {(int)KS_UE, IF_EB("\033[m", ESC_STR "[m")}, + {(int)KS_US, IF_EB("\033[4m", ESC_STR "[4m")}, + {(int)KS_MS, "y"}, + {(int)KS_UT, "y"}, + {(int)KS_LE, "\b"}, +# ifdef TERMINFO + {(int)KS_CM, IF_EB("\033[%i%p1%d;%p2%dH", + ESC_STR "[%i%p1%d;%p2%dH")}, +# else + {(int)KS_CM, IF_EB("\033[%i%d;%dH", ESC_STR "[%i%d;%dH")}, +# endif + {(int)KS_SR, IF_EB("\033M", ESC_STR "M")}, +# ifdef TERMINFO + {(int)KS_CRI, IF_EB("\033[%p1%dC", ESC_STR "[%p1%dC")}, +# else + {(int)KS_CRI, IF_EB("\033[%dC", ESC_STR "[%dC")}, +# endif + {(int)KS_KS, IF_EB("\033[?1h\033=", ESC_STR "[?1h" ESC_STR_nc "=")}, + {(int)KS_KE, IF_EB("\033[?1l\033>", ESC_STR "[?1l" ESC_STR_nc ">")}, + {(int)KS_CIS, IF_EB("\033]1;", ESC_STR "]1;")}, + {(int)KS_CIE, "\007"}, + {(int)KS_TS, IF_EB("\033]2;", ESC_STR "]2;")}, + {(int)KS_FS, "\007"}, +# ifdef TERMINFO + {(int)KS_CWS, IF_EB("\033[8;%p1%d;%p2%dt", + ESC_STR "[8;%p1%d;%p2%dt")}, + {(int)KS_CWP, IF_EB("\033[3;%p1%d;%p2%dt", + ESC_STR "[3;%p1%d;%p2%dt")}, +# else + {(int)KS_CWS, IF_EB("\033[8;%d;%dt", ESC_STR "[8;%d;%dt")}, + {(int)KS_CWP, IF_EB("\033[3;%d;%dt", ESC_STR "[3;%d;%dt")}, +# endif + {(int)KS_CRV, IF_EB("\033[>c", ESC_STR "[>c")}, + {(int)KS_U7, IF_EB("\033[6n", ESC_STR "[6n")}, + + {K_UP, IF_EB("\033O*A", ESC_STR "O*A")}, + {K_DOWN, IF_EB("\033O*B", ESC_STR "O*B")}, + {K_RIGHT, IF_EB("\033O*C", ESC_STR "O*C")}, + {K_LEFT, IF_EB("\033O*D", ESC_STR "O*D")}, + /* An extra set of cursor keys for vt100 mode */ + {K_XUP, IF_EB("\033[1;*A", ESC_STR "[1;*A")}, + {K_XDOWN, IF_EB("\033[1;*B", ESC_STR "[1;*B")}, + {K_XRIGHT, IF_EB("\033[1;*C", ESC_STR "[1;*C")}, + {K_XLEFT, IF_EB("\033[1;*D", ESC_STR "[1;*D")}, + /* An extra set of function keys for vt100 mode */ + {K_XF1, IF_EB("\033O*P", ESC_STR "O*P")}, + {K_XF2, IF_EB("\033O*Q", ESC_STR "O*Q")}, + {K_XF3, IF_EB("\033O*R", ESC_STR "O*R")}, + {K_XF4, IF_EB("\033O*S", ESC_STR "O*S")}, + {K_F1, IF_EB("\033[11;*~", ESC_STR "[11;*~")}, + {K_F2, IF_EB("\033[12;*~", ESC_STR "[12;*~")}, + {K_F3, IF_EB("\033[13;*~", ESC_STR "[13;*~")}, + {K_F4, IF_EB("\033[14;*~", ESC_STR "[14;*~")}, + {K_F5, IF_EB("\033[15;*~", ESC_STR "[15;*~")}, + {K_F6, IF_EB("\033[17;*~", ESC_STR "[17;*~")}, + {K_F7, IF_EB("\033[18;*~", ESC_STR "[18;*~")}, + {K_F8, IF_EB("\033[19;*~", ESC_STR "[19;*~")}, + {K_F9, IF_EB("\033[20;*~", ESC_STR "[20;*~")}, + {K_F10, IF_EB("\033[21;*~", ESC_STR "[21;*~")}, + {K_F11, IF_EB("\033[23;*~", ESC_STR "[23;*~")}, + {K_F12, IF_EB("\033[24;*~", ESC_STR "[24;*~")}, + {K_S_TAB, IF_EB("\033[Z", ESC_STR "[Z")}, + {K_HELP, IF_EB("\033[28;*~", ESC_STR "[28;*~")}, + {K_UNDO, IF_EB("\033[26;*~", ESC_STR "[26;*~")}, + {K_INS, IF_EB("\033[2;*~", ESC_STR "[2;*~")}, + {K_HOME, IF_EB("\033[1;*H", ESC_STR "[1;*H")}, + /* {K_S_HOME, IF_EB("\033O2H", ESC_STR "O2H")}, */ + /* {K_C_HOME, IF_EB("\033O5H", ESC_STR "O5H")}, */ + {K_KHOME, IF_EB("\033[1;*~", ESC_STR "[1;*~")}, + {K_XHOME, IF_EB("\033O*H", ESC_STR "O*H")}, /* other Home */ + {K_ZHOME, IF_EB("\033[7;*~", ESC_STR "[7;*~")}, /* other Home */ + {K_END, IF_EB("\033[1;*F", ESC_STR "[1;*F")}, + /* {K_S_END, IF_EB("\033O2F", ESC_STR "O2F")}, */ + /* {K_C_END, IF_EB("\033O5F", ESC_STR "O5F")}, */ + {K_KEND, IF_EB("\033[4;*~", ESC_STR "[4;*~")}, + {K_XEND, IF_EB("\033O*F", ESC_STR "O*F")}, /* other End */ + {K_ZEND, IF_EB("\033[8;*~", ESC_STR "[8;*~")}, + {K_PAGEUP, IF_EB("\033[5;*~", ESC_STR "[5;*~")}, + {K_PAGEDOWN, IF_EB("\033[6;*~", ESC_STR "[6;*~")}, + {K_KPLUS, IF_EB("\033O*k", ESC_STR "O*k")}, /* keypad plus */ + {K_KMINUS, IF_EB("\033O*m", ESC_STR "O*m")}, /* keypad minus */ + {K_KDIVIDE, IF_EB("\033O*o", ESC_STR "O*o")}, /* keypad / */ + {K_KMULTIPLY, IF_EB("\033O*j", ESC_STR "O*j")}, /* keypad * */ + {K_KENTER, IF_EB("\033O*M", ESC_STR "O*M")}, /* keypad Enter */ + {K_KPOINT, IF_EB("\033O*n", ESC_STR "O*n")}, /* keypad . */ + {K_KDEL, IF_EB("\033[3;*~", ESC_STR "[3;*~")}, /* keypad Del */ + + {BT_EXTRA_KEYS, ""}, + {TERMCAP2KEY('k', '0'), IF_EB("\033[10;*~", ESC_STR "[10;*~")}, /* F0 */ + {TERMCAP2KEY('F', '3'), IF_EB("\033[25;*~", ESC_STR "[25;*~")}, /* F13 */ + /* F14 and F15 are missing, because they send the same codes as the undo + * and help key, although they don't work on all keyboards. */ + {TERMCAP2KEY('F', '6'), IF_EB("\033[29;*~", ESC_STR "[29;*~")}, /* F16 */ + {TERMCAP2KEY('F', '7'), IF_EB("\033[31;*~", ESC_STR "[31;*~")}, /* F17 */ + {TERMCAP2KEY('F', '8'), IF_EB("\033[32;*~", ESC_STR "[32;*~")}, /* F18 */ + {TERMCAP2KEY('F', '9'), IF_EB("\033[33;*~", ESC_STR "[33;*~")}, /* F19 */ + {TERMCAP2KEY('F', 'A'), IF_EB("\033[34;*~", ESC_STR "[34;*~")}, /* F20 */ + + {TERMCAP2KEY('F', 'B'), IF_EB("\033[42;*~", ESC_STR "[42;*~")}, /* F21 */ + {TERMCAP2KEY('F', 'C'), IF_EB("\033[43;*~", ESC_STR "[43;*~")}, /* F22 */ + {TERMCAP2KEY('F', 'D'), IF_EB("\033[44;*~", ESC_STR "[44;*~")}, /* F23 */ + {TERMCAP2KEY('F', 'E'), IF_EB("\033[45;*~", ESC_STR "[45;*~")}, /* F24 */ + {TERMCAP2KEY('F', 'F'), IF_EB("\033[46;*~", ESC_STR "[46;*~")}, /* F25 */ + {TERMCAP2KEY('F', 'G'), IF_EB("\033[47;*~", ESC_STR "[47;*~")}, /* F26 */ + {TERMCAP2KEY('F', 'H'), IF_EB("\033[48;*~", ESC_STR "[48;*~")}, /* F27 */ + {TERMCAP2KEY('F', 'I'), IF_EB("\033[49;*~", ESC_STR "[49;*~")}, /* F28 */ + {TERMCAP2KEY('F', 'J'), IF_EB("\033[50;*~", ESC_STR "[50;*~")}, /* F29 */ + {TERMCAP2KEY('F', 'K'), IF_EB("\033[51;*~", ESC_STR "[51;*~")}, /* F30 */ + + {TERMCAP2KEY('F', 'L'), IF_EB("\033[52;*~", ESC_STR "[52;*~")}, /* F31 */ + {TERMCAP2KEY('F', 'M'), IF_EB("\033[53;*~", ESC_STR "[53;*~")}, /* F32 */ + {TERMCAP2KEY('F', 'N'), IF_EB("\033[54;*~", ESC_STR "[54;*~")}, /* F33 */ + {TERMCAP2KEY('F', 'O'), IF_EB("\033[55;*~", ESC_STR "[55;*~")}, /* F34 */ + {TERMCAP2KEY('F', 'P'), IF_EB("\033[56;*~", ESC_STR "[56;*~")}, /* F35 */ + {TERMCAP2KEY('F', 'Q'), IF_EB("\033[57;*~", ESC_STR "[57;*~")}, /* F36 */ + {TERMCAP2KEY('F', 'R'), IF_EB("\033[58;*~", ESC_STR "[58;*~")}, /* F37 */ +# endif + +# if defined(UNIX) || defined(ALL_BUILTIN_TCAPS) + /* + * iris-ansi for Silicon Graphics machines. + */ + {(int)KS_NAME, "iris-ansi"}, + {(int)KS_CE, "\033[K"}, + {(int)KS_CD, "\033[J"}, + {(int)KS_AL, "\033[L"}, +# ifdef TERMINFO + {(int)KS_CAL, "\033[%p1%dL"}, +# else + {(int)KS_CAL, "\033[%dL"}, +# endif + {(int)KS_DL, "\033[M"}, +# ifdef TERMINFO + {(int)KS_CDL, "\033[%p1%dM"}, +# else + {(int)KS_CDL, "\033[%dM"}, +# endif + {(int)KS_CL, "\033[H\033[2J"}, + {(int)KS_VE, "\033[9/y\033[12/y"}, /* These aren't documented */ + {(int)KS_VS, "\033[10/y\033[=1h\033[=2l"}, /* These aren't documented */ + {(int)KS_TI, "\033[=6h"}, + {(int)KS_TE, "\033[=6l"}, + {(int)KS_SE, "\033[21;27m"}, + {(int)KS_SO, "\033[1;7m"}, + {(int)KS_ME, "\033[m"}, + {(int)KS_MR, "\033[7m"}, + {(int)KS_MD, "\033[1m"}, + {(int)KS_CCO, "8"}, /* allow 8 colors */ + {(int)KS_CZH, "\033[3m"}, /* italic mode on */ + {(int)KS_CZR, "\033[23m"}, /* italic mode off */ + {(int)KS_US, "\033[4m"}, /* underline on */ + {(int)KS_UE, "\033[24m"}, /* underline off */ +# ifdef TERMINFO + {(int)KS_CAB, "\033[4%p1%dm"}, /* set background color (ANSI) */ + {(int)KS_CAF, "\033[3%p1%dm"}, /* set foreground color (ANSI) */ + {(int)KS_CSB, "\033[102;%p1%dm"}, /* set screen background color */ + {(int)KS_CSF, "\033[101;%p1%dm"}, /* set screen foreground color */ +# else + {(int)KS_CAB, "\033[4%dm"}, /* set background color (ANSI) */ + {(int)KS_CAF, "\033[3%dm"}, /* set foreground color (ANSI) */ + {(int)KS_CSB, "\033[102;%dm"}, /* set screen background color */ + {(int)KS_CSF, "\033[101;%dm"}, /* set screen foreground color */ +# endif + {(int)KS_MS, "y"}, /* guessed */ + {(int)KS_UT, "y"}, /* guessed */ + {(int)KS_LE, "\b"}, +# ifdef TERMINFO + {(int)KS_CM, "\033[%i%p1%d;%p2%dH"}, +# else + {(int)KS_CM, "\033[%i%d;%dH"}, +# endif + {(int)KS_SR, "\033M"}, +# ifdef TERMINFO + {(int)KS_CRI, "\033[%p1%dC"}, +# else + {(int)KS_CRI, "\033[%dC"}, +# endif + {(int)KS_CIS, "\033P3.y"}, + {(int)KS_CIE, "\234"}, /* ST "String Terminator" */ + {(int)KS_TS, "\033P1.y"}, + {(int)KS_FS, "\234"}, /* ST "String Terminator" */ +# ifdef TERMINFO + {(int)KS_CWS, "\033[203;%p1%d;%p2%d/y"}, + {(int)KS_CWP, "\033[205;%p1%d;%p2%d/y"}, +# else + {(int)KS_CWS, "\033[203;%d;%d/y"}, + {(int)KS_CWP, "\033[205;%d;%d/y"}, +# endif + {K_UP, "\033[A"}, + {K_DOWN, "\033[B"}, + {K_LEFT, "\033[D"}, + {K_RIGHT, "\033[C"}, + {K_S_UP, "\033[161q"}, + {K_S_DOWN, "\033[164q"}, + {K_S_LEFT, "\033[158q"}, + {K_S_RIGHT, "\033[167q"}, + {K_F1, "\033[001q"}, + {K_F2, "\033[002q"}, + {K_F3, "\033[003q"}, + {K_F4, "\033[004q"}, + {K_F5, "\033[005q"}, + {K_F6, "\033[006q"}, + {K_F7, "\033[007q"}, + {K_F8, "\033[008q"}, + {K_F9, "\033[009q"}, + {K_F10, "\033[010q"}, + {K_F11, "\033[011q"}, + {K_F12, "\033[012q"}, + {K_S_F1, "\033[013q"}, + {K_S_F2, "\033[014q"}, + {K_S_F3, "\033[015q"}, + {K_S_F4, "\033[016q"}, + {K_S_F5, "\033[017q"}, + {K_S_F6, "\033[018q"}, + {K_S_F7, "\033[019q"}, + {K_S_F8, "\033[020q"}, + {K_S_F9, "\033[021q"}, + {K_S_F10, "\033[022q"}, + {K_S_F11, "\033[023q"}, + {K_S_F12, "\033[024q"}, + {K_INS, "\033[139q"}, + {K_HOME, "\033[H"}, + {K_END, "\033[146q"}, + {K_PAGEUP, "\033[150q"}, + {K_PAGEDOWN, "\033[154q"}, +# endif + +# if defined(DEBUG) || defined(ALL_BUILTIN_TCAPS) + /* + * for debugging + */ + {(int)KS_NAME, "debug"}, + {(int)KS_CE, "[CE]"}, + {(int)KS_CD, "[CD]"}, + {(int)KS_AL, "[AL]"}, +# ifdef TERMINFO + {(int)KS_CAL, "[CAL%p1%d]"}, +# else + {(int)KS_CAL, "[CAL%d]"}, +# endif + {(int)KS_DL, "[DL]"}, +# ifdef TERMINFO + {(int)KS_CDL, "[CDL%p1%d]"}, +# else + {(int)KS_CDL, "[CDL%d]"}, +# endif +# ifdef TERMINFO + {(int)KS_CS, "[%p1%dCS%p2%d]"}, +# else + {(int)KS_CS, "[%dCS%d]"}, +# endif +# ifdef TERMINFO + {(int)KS_CSV, "[%p1%dCSV%p2%d]"}, +# else + {(int)KS_CSV, "[%dCSV%d]"}, +# endif +# ifdef TERMINFO + {(int)KS_CAB, "[CAB%p1%d]"}, + {(int)KS_CAF, "[CAF%p1%d]"}, + {(int)KS_CSB, "[CSB%p1%d]"}, + {(int)KS_CSF, "[CSF%p1%d]"}, +# else + {(int)KS_CAB, "[CAB%d]"}, + {(int)KS_CAF, "[CAF%d]"}, + {(int)KS_CSB, "[CSB%d]"}, + {(int)KS_CSF, "[CSF%d]"}, +# endif + {(int)KS_OP, "[OP]"}, + {(int)KS_LE, "[LE]"}, + {(int)KS_CL, "[CL]"}, + {(int)KS_VI, "[VI]"}, + {(int)KS_VE, "[VE]"}, + {(int)KS_VS, "[VS]"}, + {(int)KS_ME, "[ME]"}, + {(int)KS_MR, "[MR]"}, + {(int)KS_MB, "[MB]"}, + {(int)KS_MD, "[MD]"}, + {(int)KS_SE, "[SE]"}, + {(int)KS_SO, "[SO]"}, + {(int)KS_UE, "[UE]"}, + {(int)KS_US, "[US]"}, + {(int)KS_UCE, "[UCE]"}, + {(int)KS_UCS, "[UCS]"}, + {(int)KS_MS, "[MS]"}, + {(int)KS_UT, "[UT]"}, +# ifdef TERMINFO + {(int)KS_CM, "[%p1%dCM%p2%d]"}, +# else + {(int)KS_CM, "[%dCM%d]"}, +# endif + {(int)KS_SR, "[SR]"}, +# ifdef TERMINFO + {(int)KS_CRI, "[CRI%p1%d]"}, +# else + {(int)KS_CRI, "[CRI%d]"}, +# endif + {(int)KS_VB, "[VB]"}, + {(int)KS_KS, "[KS]"}, + {(int)KS_KE, "[KE]"}, + {(int)KS_TI, "[TI]"}, + {(int)KS_TE, "[TE]"}, + {(int)KS_CIS, "[CIS]"}, + {(int)KS_CIE, "[CIE]"}, + {(int)KS_TS, "[TS]"}, + {(int)KS_FS, "[FS]"}, +# ifdef TERMINFO + {(int)KS_CWS, "[%p1%dCWS%p2%d]"}, + {(int)KS_CWP, "[%p1%dCWP%p2%d]"}, +# else + {(int)KS_CWS, "[%dCWS%d]"}, + {(int)KS_CWP, "[%dCWP%d]"}, +# endif + {(int)KS_CRV, "[CRV]"}, + {(int)KS_U7, "[U7]"}, + {K_UP, "[KU]"}, + {K_DOWN, "[KD]"}, + {K_LEFT, "[KL]"}, + {K_RIGHT, "[KR]"}, + {K_XUP, "[xKU]"}, + {K_XDOWN, "[xKD]"}, + {K_XLEFT, "[xKL]"}, + {K_XRIGHT, "[xKR]"}, + {K_S_UP, "[S-KU]"}, + {K_S_DOWN, "[S-KD]"}, + {K_S_LEFT, "[S-KL]"}, + {K_C_LEFT, "[C-KL]"}, + {K_S_RIGHT, "[S-KR]"}, + {K_C_RIGHT, "[C-KR]"}, + {K_F1, "[F1]"}, + {K_XF1, "[xF1]"}, + {K_F2, "[F2]"}, + {K_XF2, "[xF2]"}, + {K_F3, "[F3]"}, + {K_XF3, "[xF3]"}, + {K_F4, "[F4]"}, + {K_XF4, "[xF4]"}, + {K_F5, "[F5]"}, + {K_F6, "[F6]"}, + {K_F7, "[F7]"}, + {K_F8, "[F8]"}, + {K_F9, "[F9]"}, + {K_F10, "[F10]"}, + {K_F11, "[F11]"}, + {K_F12, "[F12]"}, + {K_S_F1, "[S-F1]"}, + {K_S_XF1, "[S-xF1]"}, + {K_S_F2, "[S-F2]"}, + {K_S_XF2, "[S-xF2]"}, + {K_S_F3, "[S-F3]"}, + {K_S_XF3, "[S-xF3]"}, + {K_S_F4, "[S-F4]"}, + {K_S_XF4, "[S-xF4]"}, + {K_S_F5, "[S-F5]"}, + {K_S_F6, "[S-F6]"}, + {K_S_F7, "[S-F7]"}, + {K_S_F8, "[S-F8]"}, + {K_S_F9, "[S-F9]"}, + {K_S_F10, "[S-F10]"}, + {K_S_F11, "[S-F11]"}, + {K_S_F12, "[S-F12]"}, + {K_HELP, "[HELP]"}, + {K_UNDO, "[UNDO]"}, + {K_BS, "[BS]"}, + {K_INS, "[INS]"}, + {K_KINS, "[KINS]"}, + {K_DEL, "[DEL]"}, + {K_KDEL, "[KDEL]"}, + {K_HOME, "[HOME]"}, + {K_S_HOME, "[C-HOME]"}, + {K_C_HOME, "[C-HOME]"}, + {K_KHOME, "[KHOME]"}, + {K_XHOME, "[XHOME]"}, + {K_ZHOME, "[ZHOME]"}, + {K_END, "[END]"}, + {K_S_END, "[C-END]"}, + {K_C_END, "[C-END]"}, + {K_KEND, "[KEND]"}, + {K_XEND, "[XEND]"}, + {K_ZEND, "[ZEND]"}, + {K_PAGEUP, "[PAGEUP]"}, + {K_PAGEDOWN, "[PAGEDOWN]"}, + {K_KPAGEUP, "[KPAGEUP]"}, + {K_KPAGEDOWN, "[KPAGEDOWN]"}, + {K_MOUSE, "[MOUSE]"}, + {K_KPLUS, "[KPLUS]"}, + {K_KMINUS, "[KMINUS]"}, + {K_KDIVIDE, "[KDIVIDE]"}, + {K_KMULTIPLY, "[KMULTIPLY]"}, + {K_KENTER, "[KENTER]"}, + {K_KPOINT, "[KPOINT]"}, + {K_K0, "[K0]"}, + {K_K1, "[K1]"}, + {K_K2, "[K2]"}, + {K_K3, "[K3]"}, + {K_K4, "[K4]"}, + {K_K5, "[K5]"}, + {K_K6, "[K6]"}, + {K_K7, "[K7]"}, + {K_K8, "[K8]"}, + {K_K9, "[K9]"}, +# endif + +#endif /* NO_BUILTIN_TCAPS */ + + /* + * The most minimal terminal: only clear screen and cursor positioning + * Always included. + */ + {(int)KS_NAME, "dumb"}, + {(int)KS_CL, "\014"}, +#ifdef TERMINFO + {(int)KS_CM, IF_EB("\033[%i%p1%d;%p2%dH", + ESC_STR "[%i%p1%d;%p2%dH")}, +#else + {(int)KS_CM, IF_EB("\033[%i%d;%dH", ESC_STR "[%i%d;%dH")}, +#endif + + /* + * end marker + */ + {(int)KS_NAME, NULL} + +}; /* end of builtin_termcaps */ + +/* + * DEFAULT_TERM is used, when no terminal is specified with -T option or $TERM. + */ + + + +#if defined(UNIX) && !defined(__MINT__) +# define DEFAULT_TERM (char_u *)"ansi" +#endif + + + + + +#ifndef DEFAULT_TERM +# define DEFAULT_TERM (char_u *)"dumb" +#endif + +/* + * Term_strings contains currently used terminal output strings. + * It is initialized with the default values by parse_builtin_tcap(). + * The values can be changed by setting the option with the same name. + */ +char_u *(term_strings[(int)KS_LAST + 1]); + +static int need_gather = FALSE; /* need to fill termleader[] */ +static char_u termleader[256 + 1]; /* for check_termcode() */ +static int check_for_codes = FALSE; /* check for key code response */ + +static struct builtin_term *find_builtin_term(char_u *term) +{ + struct builtin_term *p; + + p = builtin_termcaps; + while (p->bt_string != NULL) { + if (p->bt_entry == (int)KS_NAME) { +#ifdef UNIX + if (STRCMP(p->bt_string, "iris-ansi") == 0 && vim_is_iris(term)) + return p; + else if (STRCMP(p->bt_string, "xterm") == 0 && vim_is_xterm(term)) + return p; + else +#endif + if (STRCMP(term, p->bt_string) == 0) + return p; + } + ++p; + } + return p; +} + +/* + * Parsing of the builtin termcap entries. + * Caller should check if 'name' is a valid builtin term. + * The terminal's name is not set, as this is already done in termcapinit(). + */ +static void parse_builtin_tcap(char_u *term) +{ + struct builtin_term *p; + char_u name[2]; + int term_8bit; + + p = find_builtin_term(term); + term_8bit = term_is_8bit(term); + + /* Do not parse if builtin term not found */ + if (p->bt_string == NULL) + return; + + for (++p; p->bt_entry != (int)KS_NAME && p->bt_entry != BT_EXTRA_KEYS; ++p) { + if ((int)p->bt_entry >= 0) { /* KS_xx entry */ + /* Only set the value if it wasn't set yet. */ + if (term_strings[p->bt_entry] == NULL + || term_strings[p->bt_entry] == empty_option) { + /* 8bit terminal: use CSI instead of [ */ + if (term_8bit && term_7to8bit((char_u *)p->bt_string) != 0) { + char_u *s, *t; + + s = vim_strsave((char_u *)p->bt_string); + if (s != NULL) { + for (t = s; *t; ++t) + if (term_7to8bit(t)) { + *t = term_7to8bit(t); + STRCPY(t + 1, t + 2); + } + term_strings[p->bt_entry] = s; + set_term_option_alloced(&term_strings[p->bt_entry]); + } + } else + term_strings[p->bt_entry] = (char_u *)p->bt_string; + } + } else { + name[0] = KEY2TERMCAP0((int)p->bt_entry); + name[1] = KEY2TERMCAP1((int)p->bt_entry); + if (find_termcode(name) == NULL) + add_termcode(name, (char_u *)p->bt_string, term_8bit); + } + } +} +static void set_color_count(int nr); + +/* + * Set number of colors. + * Store it as a number in t_colors. + * Store it as a string in T_CCO (using nr_colors[]). + */ +static void set_color_count(int nr) +{ + char_u nr_colors[20]; /* string for number of colors */ + + t_colors = nr; + if (t_colors > 1) + sprintf((char *)nr_colors, "%d", t_colors); + else + *nr_colors = NUL; + set_string_option_direct((char_u *)"t_Co", -1, nr_colors, OPT_FREE, 0); +} + +#ifdef HAVE_TGETENT +static char *(key_names[]) = +{ + /* Do this one first, it may cause a screen redraw. */ + "Co", + "ku", "kd", "kr", "kl", + "#2", "#4", "%i", "*7", + "k1", "k2", "k3", "k4", "k5", "k6", + "k7", "k8", "k9", "k;", "F1", "F2", + "%1", "&8", "kb", "kI", "kD", "kh", + "@7", "kP", "kN", "K1", "K3", "K4", "K5", "kB", + NULL +}; +#endif + +/* + * Set terminal options for terminal "term". + * Return OK if terminal 'term' was found in a termcap, FAIL otherwise. + * + * While doing this, until ttest(), some options may be NULL, be careful. + */ +int set_termname(char_u *term) +{ + struct builtin_term *termp; +#ifdef HAVE_TGETENT + int builtin_first = p_tbi; + int try; + int termcap_cleared = FALSE; +#endif + int width = 0, height = 0; + char_u *error_msg = NULL; + char_u *bs_p, *del_p; + + /* In silect mode (ex -s) we don't use the 'term' option. */ + if (silent_mode) + return OK; + + detected_8bit = FALSE; /* reset 8-bit detection */ + + if (term_is_builtin(term)) { + term += 8; +#ifdef HAVE_TGETENT + builtin_first = 1; +#endif + } + + /* + * If HAVE_TGETENT is not defined, only the builtin termcap is used, otherwise: + * If builtin_first is TRUE: + * 0. try builtin termcap + * 1. try external termcap + * 2. if both fail default to a builtin terminal + * If builtin_first is FALSE: + * 1. try external termcap + * 2. try builtin termcap, if both fail default to a builtin terminal + */ +#ifdef HAVE_TGETENT + for (try = builtin_first ? 0 : 1; try < 3; ++try) { + /* + * Use external termcap + */ + if (try == 1) { + char_u *p; + static char_u tstrbuf[TBUFSZ]; + int i; + char_u tbuf[TBUFSZ]; + char_u *tp; + static struct { + enum SpecialKey dest; /* index in term_strings[] */ + char *name; /* termcap name for string */ + } string_names[] = + { {KS_CE, "ce"}, {KS_AL, "al"}, {KS_CAL,"AL"}, + {KS_DL, "dl"}, {KS_CDL,"DL"}, {KS_CS, "cs"}, + {KS_CL, "cl"}, {KS_CD, "cd"}, + {KS_VI, "vi"}, {KS_VE, "ve"}, {KS_MB, "mb"}, + {KS_VS, "vs"}, {KS_ME, "me"}, {KS_MR, "mr"}, + {KS_MD, "md"}, {KS_SE, "se"}, {KS_SO, "so"}, + {KS_CZH,"ZH"}, {KS_CZR,"ZR"}, {KS_UE, "ue"}, + {KS_US, "us"}, {KS_UCE, "Ce"}, {KS_UCS, "Cs"}, + {KS_CM, "cm"}, {KS_SR, "sr"}, + {KS_CRI,"RI"}, {KS_VB, "vb"}, {KS_KS, "ks"}, + {KS_KE, "ke"}, {KS_TI, "ti"}, {KS_TE, "te"}, + {KS_BC, "bc"}, {KS_CSB,"Sb"}, {KS_CSF,"Sf"}, + {KS_CAB,"AB"}, {KS_CAF,"AF"}, {KS_LE, "le"}, + {KS_ND, "nd"}, {KS_OP, "op"}, {KS_CRV, "RV"}, + {KS_CIS, "IS"}, {KS_CIE, "IE"}, + {KS_TS, "ts"}, {KS_FS, "fs"}, + {KS_CWP, "WP"}, {KS_CWS, "WS"}, + {KS_CSI, "SI"}, {KS_CEI, "EI"}, + {KS_U7, "u7"}, + {(enum SpecialKey)0, NULL}}; + + /* + * If the external termcap does not have a matching entry, try the + * builtin ones. + */ + if ((error_msg = tgetent_error(tbuf, term)) == NULL) { + tp = tstrbuf; + if (!termcap_cleared) { + clear_termoptions(); /* clear old options */ + termcap_cleared = TRUE; + } + + /* get output strings */ + for (i = 0; string_names[i].name != NULL; ++i) { + if (term_str(string_names[i].dest) == NULL + || term_str(string_names[i].dest) == empty_option) + term_str(string_names[i].dest) = + TGETSTR(string_names[i].name, &tp); + } + + /* tgetflag() returns 1 if the flag is present, 0 if not and + * possibly -1 if the flag doesn't exist. */ + if ((T_MS == NULL || T_MS == empty_option) + && tgetflag("ms") > 0) + T_MS = (char_u *)"y"; + if ((T_XS == NULL || T_XS == empty_option) + && tgetflag("xs") > 0) + T_XS = (char_u *)"y"; + if ((T_DB == NULL || T_DB == empty_option) + && tgetflag("db") > 0) + T_DB = (char_u *)"y"; + if ((T_DA == NULL || T_DA == empty_option) + && tgetflag("da") > 0) + T_DA = (char_u *)"y"; + if ((T_UT == NULL || T_UT == empty_option) + && tgetflag("ut") > 0) + T_UT = (char_u *)"y"; + + + /* + * get key codes + */ + for (i = 0; key_names[i] != NULL; ++i) { + if (find_termcode((char_u *)key_names[i]) == NULL) { + p = TGETSTR(key_names[i], &tp); + /* if cursor-left == backspace, ignore it (televideo + * 925) */ + if (p != NULL + && (*p != Ctrl_H + || key_names[i][0] != 'k' + || key_names[i][1] != 'l')) + add_termcode((char_u *)key_names[i], p, FALSE); + } + } + + if (height == 0) + height = tgetnum("li"); + if (width == 0) + width = tgetnum("co"); + + /* + * Get number of colors (if not done already). + */ + if (term_str(KS_CCO) == NULL + || term_str(KS_CCO) == empty_option) + set_color_count(tgetnum("Co")); + + BC = (char *)TGETSTR("bc", &tp); + UP = (char *)TGETSTR("up", &tp); + p = TGETSTR("pc", &tp); + if (p) + PC = *p; + } + } else /* try == 0 || try == 2 */ +#endif /* HAVE_TGETENT */ + /* + * Use builtin termcap + */ + { +#ifdef HAVE_TGETENT + /* + * If builtin termcap was already used, there is no need to search + * for the builtin termcap again, quit now. + */ + if (try == 2 && builtin_first && termcap_cleared) + break; +#endif + /* + * search for 'term' in builtin_termcaps[] + */ + termp = find_builtin_term(term); + if (termp->bt_string == NULL) { /* did not find it */ +#ifdef HAVE_TGETENT + /* + * If try == 0, first try the external termcap. If that is not + * found we'll get back here with try == 2. + * If termcap_cleared is set we used the external termcap, + * don't complain about not finding the term in the builtin + * termcap. + */ + if (try == 0) /* try external one */ + continue; + if (termcap_cleared) /* found in external termcap */ + break; +#endif + + mch_errmsg("\r\n"); + if (error_msg != NULL) { + mch_errmsg((char *)error_msg); + mch_errmsg("\r\n"); + } + mch_errmsg("'"); + mch_errmsg((char *)term); + mch_errmsg(_("' not known. Available builtin terminals are:")); + mch_errmsg("\r\n"); + for (termp = &(builtin_termcaps[0]); termp->bt_string != NULL; + ++termp) { + if (termp->bt_entry == (int)KS_NAME) { +#ifdef HAVE_TGETENT + mch_errmsg(" builtin_"); +#else + mch_errmsg(" "); +#endif + mch_errmsg(termp->bt_string); + mch_errmsg("\r\n"); + } + } + /* when user typed :set term=xxx, quit here */ + if (starting != NO_SCREEN) { + screen_start(); /* don't know where cursor is now */ + wait_return(TRUE); + return FAIL; + } + term = DEFAULT_TERM; + mch_errmsg(_("defaulting to '")); + mch_errmsg((char *)term); + mch_errmsg("'\r\n"); + if (emsg_silent == 0) { + screen_start(); /* don't know where cursor is now */ + out_flush(); + ui_delay(2000L, TRUE); + } + set_string_option_direct((char_u *)"term", -1, term, + OPT_FREE, 0); + display_errors(); + } + out_flush(); +#ifdef HAVE_TGETENT + if (!termcap_cleared) { +#endif + clear_termoptions(); /* clear old options */ +#ifdef HAVE_TGETENT + termcap_cleared = TRUE; + } +#endif + parse_builtin_tcap(term); + } +#ifdef HAVE_TGETENT +} +#endif + + /* + * special: There is no info in the termcap about whether the cursor + * positioning is relative to the start of the screen or to the start of the + * scrolling region. We just guess here. Only msdos pcterm is known to do it + * relative. + */ + if (STRCMP(term, "pcterm") == 0) + T_CCS = (char_u *)"yes"; + else + T_CCS = empty_option; + +#ifdef UNIX + /* + * Any "stty" settings override the default for t_kb from the termcap. + * This is in os_unix.c, because it depends a lot on the version of unix that + * is being used. + * Don't do this when the GUI is active, it uses "t_kb" and "t_kD" directly. + */ + get_stty(); +#endif + + /* + * If the termcap has no entry for 'bs' and/or 'del' and the ioctl() also + * didn't work, use the default CTRL-H + * The default for t_kD is DEL, unless t_kb is DEL. + * The vim_strsave'd strings are probably lost forever, well it's only two + * bytes. Don't do this when the GUI is active, it uses "t_kb" and "t_kD" + * directly. + */ + { + bs_p = find_termcode((char_u *)"kb"); + del_p = find_termcode((char_u *)"kD"); + if (bs_p == NULL || *bs_p == NUL) + add_termcode((char_u *)"kb", (bs_p = (char_u *)CTRL_H_STR), FALSE); + if ((del_p == NULL || *del_p == NUL) && + (bs_p == NULL || *bs_p != DEL)) + add_termcode((char_u *)"kD", (char_u *)DEL_STR, FALSE); + } + +#if defined(UNIX) + term_is_xterm = vim_is_xterm(term); +#endif + +# if defined(UNIX) + /* + * For Unix, set the 'ttymouse' option to the type of mouse to be used. + * The termcode for the mouse is added as a side effect in option.c. + */ + { + char_u *p; + + p = (char_u *)""; + if (use_xterm_like_mouse(term)) { + if (use_xterm_mouse()) + p = NULL; /* keep existing value, might be "xterm2" */ + else + p = (char_u *)"xterm"; + } + if (p != NULL) { + set_option_value((char_u *)"ttym", 0L, p, 0); + /* Reset the WAS_SET flag, 'ttymouse' can be set to "sgr" or + * "xterm2" in check_termcode(). */ + reset_option_was_set((char_u *)"ttym"); + } + if (p == NULL + ) + check_mouse_termcode(); /* set mouse termcode anyway */ + } +# else + set_mouse_termcode(KS_MOUSE, (char_u *)"\233M"); +# endif + + +#ifdef USE_TERM_CONSOLE + /* DEFAULT_TERM indicates that it is the machine console. */ + if (STRCMP(term, DEFAULT_TERM) != 0) + term_console = FALSE; + else { + term_console = TRUE; + } +#endif + +#if defined(UNIX) + /* + * 'ttyfast' is default on for xterm, iris-ansi and a few others. + */ + if (vim_is_fastterm(term)) + p_tf = TRUE; +#endif +#ifdef USE_TERM_CONSOLE + /* + * 'ttyfast' is default on consoles + */ + if (term_console) + p_tf = TRUE; +#endif + + ttest(TRUE); /* make sure we have a valid set of terminal codes */ + + full_screen = TRUE; /* we can use termcap codes from now on */ + set_term_defaults(); /* use current values as defaults */ + LOG_TR("setting crv_status to CRV_GET"); + crv_status = CRV_GET; /* Get terminal version later */ + + /* + * Initialize the terminal with the appropriate termcap codes. + * Set the mouse and window title if possible. + * Don't do this when starting, need to parse the .vimrc first, because it + * may redefine t_TI etc. + */ + if (starting != NO_SCREEN) { + starttermcap(); /* may change terminal mode */ + setmouse(); /* may start using the mouse */ + maketitle(); /* may display window title */ + } + + /* display initial screen after ttest() checking. jw. */ + if (width <= 0 || height <= 0) { + /* termcap failed to report size */ + /* set defaults, in case ui_get_shellsize() also fails */ + width = 80; + height = 24; /* most terminals are 24 lines */ + } + set_shellsize(width, height, FALSE); /* may change Rows */ + if (starting != NO_SCREEN) { + if (scroll_region) + scroll_region_reset(); /* In case Rows changed */ + check_map_keycodes(); /* check mappings for terminal codes used */ + + { + buf_T *old_curbuf; + + /* + * Execute the TermChanged autocommands for each buffer that is + * loaded. + */ + old_curbuf = curbuf; + for (curbuf = firstbuf; curbuf != NULL; curbuf = curbuf->b_next) { + if (curbuf->b_ml.ml_mfp != NULL) + apply_autocmds(EVENT_TERMCHANGED, NULL, NULL, FALSE, + curbuf); + } + if (buf_valid(old_curbuf)) + curbuf = old_curbuf; + } + } + + may_req_termresponse(); + + return OK; +} + + +# define HMT_NORMAL 1 +# define HMT_NETTERM 2 +# define HMT_DEC 4 +# define HMT_JSBTERM 8 +# define HMT_PTERM 16 +# define HMT_URXVT 32 +# define HMT_SGR 64 +static int has_mouse_termcode = 0; + +void +set_mouse_termcode ( + int n, /* KS_MOUSE, KS_NETTERM_MOUSE or KS_DEC_MOUSE */ + char_u *s +) +{ + char_u name[2]; + + name[0] = n; + name[1] = KE_FILLER; + add_termcode(name, s, FALSE); +# ifdef FEAT_MOUSE_JSB + if (n == KS_JSBTERM_MOUSE) + has_mouse_termcode |= HMT_JSBTERM; + else +# endif + if (n == KS_NETTERM_MOUSE) + has_mouse_termcode |= HMT_NETTERM; + else if (n == KS_DEC_MOUSE) + has_mouse_termcode |= HMT_DEC; + else if (n == KS_URXVT_MOUSE) + has_mouse_termcode |= HMT_URXVT; + else if (n == KS_SGR_MOUSE) + has_mouse_termcode |= HMT_SGR; + else + has_mouse_termcode |= HMT_NORMAL; +} + +# if (defined(UNIX) && defined(FEAT_MOUSE_TTY)) || defined(PROTO) +void +del_mouse_termcode ( + int n /* KS_MOUSE, KS_NETTERM_MOUSE or KS_DEC_MOUSE */ +) +{ + char_u name[2]; + + name[0] = n; + name[1] = KE_FILLER; + del_termcode(name); +# ifdef FEAT_MOUSE_JSB + if (n == KS_JSBTERM_MOUSE) + has_mouse_termcode &= ~HMT_JSBTERM; + else +# endif + if (n == KS_NETTERM_MOUSE) + has_mouse_termcode &= ~HMT_NETTERM; + else if (n == KS_DEC_MOUSE) + has_mouse_termcode &= ~HMT_DEC; + else if (n == KS_URXVT_MOUSE) + has_mouse_termcode &= ~HMT_URXVT; + else if (n == KS_SGR_MOUSE) + has_mouse_termcode &= ~HMT_SGR; + else + has_mouse_termcode &= ~HMT_NORMAL; +} +# endif + +#ifdef HAVE_TGETENT +/* + * Call tgetent() + * Return error message if it fails, NULL if it's OK. + */ +static char_u *tgetent_error(char_u *tbuf, char_u *term) +{ + int i; + + i = TGETENT(tbuf, term); + if (i < 0 /* -1 is always an error */ +# ifdef TGETENT_ZERO_ERR + || i == 0 /* sometimes zero is also an error */ +# endif + ) { + /* On FreeBSD tputs() gets a SEGV after a tgetent() which fails. Call + * tgetent() with the always existing "dumb" entry to avoid a crash or + * hang. */ + (void)TGETENT(tbuf, "dumb"); + + if (i < 0) +# ifdef TGETENT_ZERO_ERR + return (char_u *)_("E557: Cannot open termcap file"); + if (i == 0) +# endif +#ifdef TERMINFO + return (char_u *)_("E558: Terminal entry not found in terminfo"); +#else + return (char_u *)_("E559: Terminal entry not found in termcap"); +#endif + } + return NULL; +} + +/* + * Some versions of tgetstr() have been reported to return -1 instead of NULL. + * Fix that here. + */ +static char_u *vim_tgetstr(char *s, char_u **pp) +{ + char *p; + + p = tgetstr(s, (char **)pp); + if (p == (char *)-1) + p = NULL; + return (char_u *)p; +} +#endif /* HAVE_TGETENT */ + +#if defined(HAVE_TGETENT) && (defined(UNIX) || defined(MACOS_X)) +/* + * Get Columns and Rows from the termcap. Used after a window signal if the + * ioctl() fails. It doesn't make sense to call tgetent each time if the "co" + * and "li" entries never change. But on some systems this works. + * Errors while getting the entries are ignored. + */ +void +getlinecol ( + long *cp, /* pointer to columns */ + long *rp /* pointer to rows */ +) +{ + char_u tbuf[TBUFSZ]; + + if (T_NAME != NULL && *T_NAME != NUL && + tgetent_error(tbuf, T_NAME) == NULL) { + if (*cp == 0) + *cp = tgetnum("co"); + if (*rp == 0) + *rp = tgetnum("li"); + } +} +#endif /* defined(HAVE_TGETENT) && defined(UNIX) */ + +/* + * Get a string entry from the termcap and add it to the list of termcodes. + * Used for special keys. + * Give an error message for failure when not sourcing. + * If force given, replace an existing entry. + * Return FAIL if the entry was not found, OK if the entry was added. + */ +int add_termcap_entry(char_u *name, int force) +{ + char_u *term; + int key; + struct builtin_term *termp; +#ifdef HAVE_TGETENT + char_u *string; + int i; + int builtin_first; + char_u tbuf[TBUFSZ]; + char_u tstrbuf[TBUFSZ]; + char_u *tp = tstrbuf; + char_u *error_msg = NULL; +#endif + + /* + * If the GUI is running or will start in a moment, we only support the keys + * that the GUI can produce. + */ + + if (!force && find_termcode(name) != NULL) /* it's already there */ + return OK; + + term = T_NAME; + if (term == NULL || *term == NUL) /* 'term' not defined yet */ + return FAIL; + + if (term_is_builtin(term)) { /* name starts with "builtin_" */ + term += 8; +#ifdef HAVE_TGETENT + builtin_first = TRUE; +#endif + } +#ifdef HAVE_TGETENT + else + builtin_first = p_tbi; +#endif + +#ifdef HAVE_TGETENT + /* + * We can get the entry from the builtin termcap and from the external one. + * If 'ttybuiltin' is on or the terminal name starts with "builtin_", try + * builtin termcap first. + * If 'ttybuiltin' is off, try external termcap first. + */ + for (i = 0; i < 2; ++i) { + if (!builtin_first == i) +#e