xref: /vim-8.2.3635/src/term.c (revision b3a29558)
1edf3f97aSBram Moolenaar /* vi:set ts=8 sts=4 sw=4 noet:
2071d4279SBram Moolenaar  *
3071d4279SBram Moolenaar  * VIM - Vi IMproved	by Bram Moolenaar
4071d4279SBram Moolenaar  *
5071d4279SBram Moolenaar  * Do ":help uganda"  in Vim to read copying and usage conditions.
6071d4279SBram Moolenaar  * Do ":help credits" in Vim to see a list of people who contributed.
7071d4279SBram Moolenaar  * See README.txt for an overview of the Vim source code.
8071d4279SBram Moolenaar  */
9071d4279SBram Moolenaar /*
10071d4279SBram Moolenaar  *
11071d4279SBram Moolenaar  * term.c: functions for controlling the terminal
12071d4279SBram Moolenaar  *
1348e330afSBram Moolenaar  * primitive termcap support for Amiga and Win32 included
14071d4279SBram Moolenaar  *
15071d4279SBram Moolenaar  * NOTE: padding and variable substitution is not performed,
16071d4279SBram Moolenaar  * when compiling without HAVE_TGETENT, we use tputs() and tgoto() dummies.
17071d4279SBram Moolenaar  */
18071d4279SBram Moolenaar 
19071d4279SBram Moolenaar /*
20071d4279SBram Moolenaar  * Some systems have a prototype for tgetstr() with (char *) instead of
21071d4279SBram Moolenaar  * (char **). This define removes that prototype. We include our own prototype
22071d4279SBram Moolenaar  * below.
23071d4279SBram Moolenaar  */
24071d4279SBram Moolenaar #define tgetstr tgetstr_defined_wrong
25ad3ec76bSBram Moolenaar 
26071d4279SBram Moolenaar #include "vim.h"
27071d4279SBram Moolenaar 
28071d4279SBram Moolenaar #ifdef HAVE_TGETENT
29071d4279SBram Moolenaar # ifdef HAVE_TERMIOS_H
300d6f5d97SBram Moolenaar #  include <termios.h>	    // seems to be required for some Linux
31071d4279SBram Moolenaar # endif
32071d4279SBram Moolenaar # ifdef HAVE_TERMCAP_H
33071d4279SBram Moolenaar #  include <termcap.h>
34071d4279SBram Moolenaar # endif
35071d4279SBram Moolenaar 
36071d4279SBram Moolenaar /*
37071d4279SBram Moolenaar  * A few linux systems define outfuntype in termcap.h to be used as the third
38071d4279SBram Moolenaar  * argument for tputs().
39071d4279SBram Moolenaar  */
40071d4279SBram Moolenaar # ifdef VMS
41467676d4SBram Moolenaar #  define TPUTSFUNCAST (void (*)(unsigned int))
42071d4279SBram Moolenaar # else
43071d4279SBram Moolenaar #  ifdef HAVE_OUTFUNTYPE
44071d4279SBram Moolenaar #   define TPUTSFUNCAST (outfuntype)
45071d4279SBram Moolenaar #  else
4686394aa9SBram Moolenaar #   define TPUTSFUNCAST (int (*)(int))
47071d4279SBram Moolenaar #  endif
48071d4279SBram Moolenaar # endif
49071d4279SBram Moolenaar #endif
50071d4279SBram Moolenaar 
51071d4279SBram Moolenaar #undef tgetstr
52071d4279SBram Moolenaar 
53071d4279SBram Moolenaar /*
54071d4279SBram Moolenaar  * Here are the builtin termcap entries.  They are not stored as complete
55e60acc18SBram Moolenaar  * structures with all entries, as such a structure is too big.
56071d4279SBram Moolenaar  *
57071d4279SBram Moolenaar  * The entries are compact, therefore they normally are included even when
58071d4279SBram Moolenaar  * HAVE_TGETENT is defined. When HAVE_TGETENT is defined, the builtin entries
59071d4279SBram Moolenaar  * can be accessed with "builtin_amiga", "builtin_ansi", "builtin_debug", etc.
60071d4279SBram Moolenaar  *
61071d4279SBram Moolenaar  * Each termcap is a list of builtin_term structures. It always starts with
62071d4279SBram Moolenaar  * KS_NAME, which separates the entries.  See parse_builtin_tcap() for all
63071d4279SBram Moolenaar  * details.
64071d4279SBram Moolenaar  * bt_entry is either a KS_xxx code (>= 0), or a K_xxx code.
65071d4279SBram Moolenaar  *
66071d4279SBram Moolenaar  * Entries marked with "guessed" may be wrong.
67071d4279SBram Moolenaar  */
68071d4279SBram Moolenaar struct builtin_term
69071d4279SBram Moolenaar {
70071d4279SBram Moolenaar     int		bt_entry;
71071d4279SBram Moolenaar     char	*bt_string;
72071d4279SBram Moolenaar };
73071d4279SBram Moolenaar 
740d6f5d97SBram Moolenaar // start of keys that are not directly used by Vim but can be mapped
75071d4279SBram Moolenaar #define BT_EXTRA_KEYS	0x101
76071d4279SBram Moolenaar 
77baaa7e9eSBram Moolenaar static void parse_builtin_tcap(char_u *s);
78baaa7e9eSBram Moolenaar static void gather_termleader(void);
79071d4279SBram Moolenaar #ifdef FEAT_TERMRESPONSE
80baaa7e9eSBram Moolenaar static void req_codes_from_term(void);
81baaa7e9eSBram Moolenaar static void req_more_codes_from_term(void);
82baaa7e9eSBram Moolenaar static void got_code_from_term(char_u *code, int len);
83baaa7e9eSBram Moolenaar static void check_for_codes_from_term(void);
84071d4279SBram Moolenaar #endif
85baaa7e9eSBram Moolenaar static void del_termcode_idx(int idx);
865843f5f3SBram Moolenaar static int find_term_bykeys(char_u *src);
87baaa7e9eSBram Moolenaar static int term_is_builtin(char_u *name);
88baaa7e9eSBram Moolenaar static int term_7to8bit(char_u *p);
89071d4279SBram Moolenaar 
90071d4279SBram Moolenaar #ifdef HAVE_TGETENT
91f9e3e09fSBram Moolenaar static char *tgetent_error(char_u *, char_u *);
92071d4279SBram Moolenaar 
93071d4279SBram Moolenaar /*
94071d4279SBram Moolenaar  * Here is our own prototype for tgetstr(), any prototypes from the include
95071d4279SBram Moolenaar  * files have been disabled by the define at the start of this file.
96071d4279SBram Moolenaar  */
97baaa7e9eSBram Moolenaar char		*tgetstr(char *, char **);
98071d4279SBram Moolenaar 
99071d4279SBram Moolenaar # ifdef FEAT_TERMRESPONSE
1000d6f5d97SBram Moolenaar     // Change this to "if 1" to debug what happens with termresponse.
1012951b77eSBram Moolenaar #  if 0
1022951b77eSBram Moolenaar #   define DEBUG_TERMRESPONSE
103952d9d82SBram Moolenaar static void log_tr(const char *fmt, ...) ATTRIBUTE_FORMAT_PRINTF(1, 2);
104b255b905SBram Moolenaar #   define LOG_TR(msg) log_tr msg
1052951b77eSBram Moolenaar #  else
106b255b905SBram Moolenaar #   define LOG_TR(msg) do { /**/ } while (0)
1072951b77eSBram Moolenaar #  endif
1083eee06e7SBram Moolenaar 
109afd78266SBram Moolenaar typedef enum {
110afd78266SBram Moolenaar     STATUS_GET,		// send request when switching to RAW mode
111afd78266SBram Moolenaar     STATUS_SENT,	// did send request, checking for response
112afd78266SBram Moolenaar     STATUS_GOT,		// received response
113afd78266SBram Moolenaar     STATUS_FAIL		// timed out
114afd78266SBram Moolenaar } request_progress_T;
1153eee06e7SBram Moolenaar 
116afd78266SBram Moolenaar typedef struct {
117afd78266SBram Moolenaar     request_progress_T	    tr_progress;
118afd78266SBram Moolenaar     time_t		    tr_start;	// when request was sent, -1 for never
119afd78266SBram Moolenaar } termrequest_T;
1203eee06e7SBram Moolenaar 
121afd78266SBram Moolenaar #  define TERMREQUEST_INIT {STATUS_GET, -1}
122afd78266SBram Moolenaar 
123afd78266SBram Moolenaar // Request Terminal Version status:
124afd78266SBram Moolenaar static termrequest_T crv_status = TERMREQUEST_INIT;
125afd78266SBram Moolenaar 
126afd78266SBram Moolenaar // Request Cursor position report:
127afd78266SBram Moolenaar static termrequest_T u7_status = TERMREQUEST_INIT;
1283eee06e7SBram Moolenaar 
129a45551a5SBram Moolenaar // Request xterm compatibility check:
130a45551a5SBram Moolenaar static termrequest_T xcc_status = TERMREQUEST_INIT;
131a45551a5SBram Moolenaar 
13265e4c4f6SBram Moolenaar #  ifdef FEAT_TERMINAL
133afd78266SBram Moolenaar // Request foreground color report:
134afd78266SBram Moolenaar static termrequest_T rfg_status = TERMREQUEST_INIT;
13565e4c4f6SBram Moolenaar static int fg_r = 0;
13665e4c4f6SBram Moolenaar static int fg_g = 0;
13765e4c4f6SBram Moolenaar static int fg_b = 0;
13865e4c4f6SBram Moolenaar static int bg_r = 255;
13965e4c4f6SBram Moolenaar static int bg_g = 255;
14065e4c4f6SBram Moolenaar static int bg_b = 255;
14165e4c4f6SBram Moolenaar #  endif
14265e4c4f6SBram Moolenaar 
1430d6f5d97SBram Moolenaar // Request background color report:
144afd78266SBram Moolenaar static termrequest_T rbg_status = TERMREQUEST_INIT;
1453eee06e7SBram Moolenaar 
1460d6f5d97SBram Moolenaar // Request cursor blinking mode report:
147afd78266SBram Moolenaar static termrequest_T rbm_status = TERMREQUEST_INIT;
1484db25549SBram Moolenaar 
1490d6f5d97SBram Moolenaar // Request cursor style report:
150afd78266SBram Moolenaar static termrequest_T rcs_status = TERMREQUEST_INIT;
15189894aa6SBram Moolenaar 
1524b96df5aSBram Moolenaar // Request window's position report:
153afd78266SBram Moolenaar static termrequest_T winpos_status = TERMREQUEST_INIT;
154afd78266SBram Moolenaar 
155afd78266SBram Moolenaar static termrequest_T *all_termrequests[] = {
156afd78266SBram Moolenaar     &crv_status,
157afd78266SBram Moolenaar     &u7_status,
158a45551a5SBram Moolenaar     &xcc_status,
159afd78266SBram Moolenaar #  ifdef FEAT_TERMINAL
160afd78266SBram Moolenaar     &rfg_status,
161afd78266SBram Moolenaar #  endif
162afd78266SBram Moolenaar     &rbg_status,
163afd78266SBram Moolenaar     &rbm_status,
164afd78266SBram Moolenaar     &rcs_status,
165afd78266SBram Moolenaar     &winpos_status,
166afd78266SBram Moolenaar     NULL
167afd78266SBram Moolenaar };
168071d4279SBram Moolenaar # endif
169071d4279SBram Moolenaar 
170071d4279SBram Moolenaar /*
171071d4279SBram Moolenaar  * Don't declare these variables if termcap.h contains them.
172071d4279SBram Moolenaar  * Autoconf checks if these variables should be declared extern (not all
173071d4279SBram Moolenaar  * systems have them).
174071d4279SBram Moolenaar  * Some versions define ospeed to be speed_t, but that is incompatible with
175071d4279SBram Moolenaar  * BSD, where ospeed is short and speed_t is long.
176071d4279SBram Moolenaar  */
177071d4279SBram Moolenaar # ifndef HAVE_OSPEED
178071d4279SBram Moolenaar #  ifdef OSPEED_EXTERN
179071d4279SBram Moolenaar extern short ospeed;
180071d4279SBram Moolenaar #   else
181071d4279SBram Moolenaar short ospeed;
182071d4279SBram Moolenaar #   endif
183071d4279SBram Moolenaar # endif
184071d4279SBram Moolenaar # ifndef HAVE_UP_BC_PC
185071d4279SBram Moolenaar #  ifdef UP_BC_PC_EXTERN
186071d4279SBram Moolenaar extern char *UP, *BC, PC;
187071d4279SBram Moolenaar #  else
188071d4279SBram Moolenaar char *UP, *BC, PC;
189071d4279SBram Moolenaar #  endif
190071d4279SBram Moolenaar # endif
191071d4279SBram Moolenaar 
192071d4279SBram Moolenaar # define TGETSTR(s, p)	vim_tgetstr((s), (p))
193071d4279SBram Moolenaar # define TGETENT(b, t)	tgetent((char *)(b), (char *)(t))
194baaa7e9eSBram Moolenaar static char_u *vim_tgetstr(char *s, char_u **pp);
1950d6f5d97SBram Moolenaar #endif // HAVE_TGETENT
196071d4279SBram Moolenaar 
1970d6f5d97SBram Moolenaar static int  detected_8bit = FALSE;	// detected 8-bit terminal
198071d4279SBram Moolenaar 
199681fc3faSBram Moolenaar #if (defined(UNIX) || defined(VMS))
200681fc3faSBram Moolenaar static int focus_mode = FALSE; // xterm's "focus reporting" availability
201681fc3faSBram Moolenaar static int focus_state = FALSE; // TRUE if the terminal window gains focus
202681fc3faSBram Moolenaar #endif
203681fc3faSBram Moolenaar 
20437b9b819SBram Moolenaar #ifdef FEAT_TERMRESPONSE
2050d6f5d97SBram Moolenaar // When the cursor shape was detected these values are used:
2060d6f5d97SBram Moolenaar // 1: block, 2: underline, 3: vertical bar
2073eee06e7SBram Moolenaar static int initial_cursor_shape = 0;
2084db25549SBram Moolenaar 
2090d6f5d97SBram Moolenaar // The blink flag from the style response may be inverted from the actual
2100d6f5d97SBram Moolenaar // blinking state, xterm XORs the flags.
2114db25549SBram Moolenaar static int initial_cursor_shape_blink = FALSE;
2124db25549SBram Moolenaar 
2130d6f5d97SBram Moolenaar // The blink flag from the blinking-cursor mode response
2143eee06e7SBram Moolenaar static int initial_cursor_blink = FALSE;
21537b9b819SBram Moolenaar #endif
2163eee06e7SBram Moolenaar 
2176c0b44b5SBram Moolenaar static struct builtin_term builtin_termcaps[] =
218071d4279SBram Moolenaar {
219071d4279SBram Moolenaar 
220071d4279SBram Moolenaar #if defined(FEAT_GUI)
221071d4279SBram Moolenaar /*
222071d4279SBram Moolenaar  * GUI pseudo term-cap.
223071d4279SBram Moolenaar  */
224071d4279SBram Moolenaar     {(int)KS_NAME,	"gui"},
225071d4279SBram Moolenaar     {(int)KS_CE,	IF_EB("\033|$", ESC_STR "|$")},
226071d4279SBram Moolenaar     {(int)KS_AL,	IF_EB("\033|i", ESC_STR "|i")},
227071d4279SBram Moolenaar # ifdef TERMINFO
228071d4279SBram Moolenaar     {(int)KS_CAL,	IF_EB("\033|%p1%dI", ESC_STR "|%p1%dI")},
229071d4279SBram Moolenaar # else
230071d4279SBram Moolenaar     {(int)KS_CAL,	IF_EB("\033|%dI", ESC_STR "|%dI")},
231071d4279SBram Moolenaar # endif
232071d4279SBram Moolenaar     {(int)KS_DL,	IF_EB("\033|d", ESC_STR "|d")},
233071d4279SBram Moolenaar # ifdef TERMINFO
234071d4279SBram Moolenaar     {(int)KS_CDL,	IF_EB("\033|%p1%dD", ESC_STR "|%p1%dD")},
235071d4279SBram Moolenaar     {(int)KS_CS,	IF_EB("\033|%p1%d;%p2%dR", ESC_STR "|%p1%d;%p2%dR")},
236071d4279SBram Moolenaar     {(int)KS_CSV,	IF_EB("\033|%p1%d;%p2%dV", ESC_STR "|%p1%d;%p2%dV")},
237071d4279SBram Moolenaar # else
238071d4279SBram Moolenaar     {(int)KS_CDL,	IF_EB("\033|%dD", ESC_STR "|%dD")},
239071d4279SBram Moolenaar     {(int)KS_CS,	IF_EB("\033|%d;%dR", ESC_STR "|%d;%dR")},
240071d4279SBram Moolenaar     {(int)KS_CSV,	IF_EB("\033|%d;%dV", ESC_STR "|%d;%dV")},
241071d4279SBram Moolenaar # endif
242071d4279SBram Moolenaar     {(int)KS_CL,	IF_EB("\033|C", ESC_STR "|C")},
2430d6f5d97SBram Moolenaar 			// attributes switched on with 'h', off with * 'H'
2440d6f5d97SBram Moolenaar     {(int)KS_ME,	IF_EB("\033|31H", ESC_STR "|31H")}, // HL_ALL
2450d6f5d97SBram Moolenaar     {(int)KS_MR,	IF_EB("\033|1h", ESC_STR "|1h")},   // HL_INVERSE
2460d6f5d97SBram Moolenaar     {(int)KS_MD,	IF_EB("\033|2h", ESC_STR "|2h")},   // HL_BOLD
2470d6f5d97SBram Moolenaar     {(int)KS_SE,	IF_EB("\033|16H", ESC_STR "|16H")}, // HL_STANDOUT
2480d6f5d97SBram Moolenaar     {(int)KS_SO,	IF_EB("\033|16h", ESC_STR "|16h")}, // HL_STANDOUT
2490d6f5d97SBram Moolenaar     {(int)KS_UE,	IF_EB("\033|8H", ESC_STR "|8H")},   // HL_UNDERLINE
2500d6f5d97SBram Moolenaar     {(int)KS_US,	IF_EB("\033|8h", ESC_STR "|8h")},   // HL_UNDERLINE
2510d6f5d97SBram Moolenaar     {(int)KS_UCE,	IF_EB("\033|8C", ESC_STR "|8C")},   // HL_UNDERCURL
2520d6f5d97SBram Moolenaar     {(int)KS_UCS,	IF_EB("\033|8c", ESC_STR "|8c")},   // HL_UNDERCURL
2530d6f5d97SBram Moolenaar     {(int)KS_STE,	IF_EB("\033|4C", ESC_STR "|4C")},   // HL_STRIKETHROUGH
2540d6f5d97SBram Moolenaar     {(int)KS_STS,	IF_EB("\033|4c", ESC_STR "|4c")},   // HL_STRIKETHROUGH
2550d6f5d97SBram Moolenaar     {(int)KS_CZR,	IF_EB("\033|4H", ESC_STR "|4H")},   // HL_ITALIC
2560d6f5d97SBram Moolenaar     {(int)KS_CZH,	IF_EB("\033|4h", ESC_STR "|4h")},   // HL_ITALIC
257071d4279SBram Moolenaar     {(int)KS_VB,	IF_EB("\033|f", ESC_STR "|f")},
258071d4279SBram Moolenaar     {(int)KS_MS,	"y"},
259071d4279SBram Moolenaar     {(int)KS_UT,	"y"},
260494838a3SBram Moolenaar     {(int)KS_XN,	"y"},
2610d6f5d97SBram Moolenaar     {(int)KS_LE,	"\b"},		// cursor-left = BS
2620d6f5d97SBram Moolenaar     {(int)KS_ND,	"\014"},	// cursor-right = CTRL-L
263071d4279SBram Moolenaar # ifdef TERMINFO
264071d4279SBram Moolenaar     {(int)KS_CM,	IF_EB("\033|%p1%d;%p2%dM", ESC_STR "|%p1%d;%p2%dM")},
265071d4279SBram Moolenaar # else
266071d4279SBram Moolenaar     {(int)KS_CM,	IF_EB("\033|%d;%dM", ESC_STR "|%d;%dM")},
267071d4279SBram Moolenaar # endif
2680d6f5d97SBram Moolenaar 	// there are no key sequences here, the GUI sequences are recognized
2690d6f5d97SBram Moolenaar 	// in check_termcode()
270071d4279SBram Moolenaar #endif
271071d4279SBram Moolenaar 
272071d4279SBram Moolenaar #ifndef NO_BUILTIN_TCAPS
273071d4279SBram Moolenaar 
274071d4279SBram Moolenaar # if defined(AMIGA) || defined(ALL_BUILTIN_TCAPS)
275071d4279SBram Moolenaar /*
276071d4279SBram Moolenaar  * Amiga console window, default for Amiga
277071d4279SBram Moolenaar  */
278071d4279SBram Moolenaar     {(int)KS_NAME,	"amiga"},
279071d4279SBram Moolenaar     {(int)KS_CE,	"\033[K"},
280071d4279SBram Moolenaar     {(int)KS_CD,	"\033[J"},
281071d4279SBram Moolenaar     {(int)KS_AL,	"\033[L"},
282071d4279SBram Moolenaar #  ifdef TERMINFO
283071d4279SBram Moolenaar     {(int)KS_CAL,	"\033[%p1%dL"},
284071d4279SBram Moolenaar #  else
285071d4279SBram Moolenaar     {(int)KS_CAL,	"\033[%dL"},
286071d4279SBram Moolenaar #  endif
287071d4279SBram Moolenaar     {(int)KS_DL,	"\033[M"},
288071d4279SBram Moolenaar #  ifdef TERMINFO
289071d4279SBram Moolenaar     {(int)KS_CDL,	"\033[%p1%dM"},
290071d4279SBram Moolenaar #  else
291071d4279SBram Moolenaar     {(int)KS_CDL,	"\033[%dM"},
292071d4279SBram Moolenaar #  endif
293071d4279SBram Moolenaar     {(int)KS_CL,	"\014"},
294071d4279SBram Moolenaar     {(int)KS_VI,	"\033[0 p"},
295071d4279SBram Moolenaar     {(int)KS_VE,	"\033[1 p"},
296071d4279SBram Moolenaar     {(int)KS_ME,	"\033[0m"},
297071d4279SBram Moolenaar     {(int)KS_MR,	"\033[7m"},
298071d4279SBram Moolenaar     {(int)KS_MD,	"\033[1m"},
299071d4279SBram Moolenaar     {(int)KS_SE,	"\033[0m"},
300071d4279SBram Moolenaar     {(int)KS_SO,	"\033[33m"},
301071d4279SBram Moolenaar     {(int)KS_US,	"\033[4m"},
302071d4279SBram Moolenaar     {(int)KS_UE,	"\033[0m"},
303071d4279SBram Moolenaar     {(int)KS_CZH,	"\033[3m"},
304071d4279SBram Moolenaar     {(int)KS_CZR,	"\033[0m"},
3052d718267SBram Moolenaar #if defined(__amigaos4__) || defined(__MORPHOS__) || defined(__AROS__)
3060d6f5d97SBram Moolenaar     {(int)KS_CCO,	"8"},		// allow 8 colors
307071d4279SBram Moolenaar #  ifdef TERMINFO
3080d6f5d97SBram Moolenaar     {(int)KS_CAB,	"\033[4%p1%dm"},// set background color
3090d6f5d97SBram Moolenaar     {(int)KS_CAF,	"\033[3%p1%dm"},// set foreground color
310071d4279SBram Moolenaar #  else
3110d6f5d97SBram Moolenaar     {(int)KS_CAB,	"\033[4%dm"},	// set background color
3120d6f5d97SBram Moolenaar     {(int)KS_CAF,	"\033[3%dm"},	// set foreground color
313071d4279SBram Moolenaar #  endif
3140d6f5d97SBram Moolenaar     {(int)KS_OP,	"\033[m"},	// reset colors
315071d4279SBram Moolenaar #endif
316071d4279SBram Moolenaar     {(int)KS_MS,	"y"},
3170d6f5d97SBram Moolenaar     {(int)KS_UT,	"y"},		// guessed
318071d4279SBram Moolenaar     {(int)KS_LE,	"\b"},
319071d4279SBram Moolenaar #  ifdef TERMINFO
320071d4279SBram Moolenaar     {(int)KS_CM,	"\033[%i%p1%d;%p2%dH"},
321071d4279SBram Moolenaar #  else
322071d4279SBram Moolenaar     {(int)KS_CM,	"\033[%i%d;%dH"},
323071d4279SBram Moolenaar #  endif
324071d4279SBram Moolenaar #if defined(__MORPHOS__)
325071d4279SBram Moolenaar     {(int)KS_SR,	"\033M"},
326071d4279SBram Moolenaar #endif
327071d4279SBram Moolenaar #  ifdef TERMINFO
328071d4279SBram Moolenaar     {(int)KS_CRI,	"\033[%p1%dC"},
329071d4279SBram Moolenaar #  else
330071d4279SBram Moolenaar     {(int)KS_CRI,	"\033[%dC"},
331071d4279SBram Moolenaar #  endif
332071d4279SBram Moolenaar     {K_UP,		"\233A"},
333071d4279SBram Moolenaar     {K_DOWN,		"\233B"},
334071d4279SBram Moolenaar     {K_LEFT,		"\233D"},
335071d4279SBram Moolenaar     {K_RIGHT,		"\233C"},
336071d4279SBram Moolenaar     {K_S_UP,		"\233T"},
337071d4279SBram Moolenaar     {K_S_DOWN,		"\233S"},
338071d4279SBram Moolenaar     {K_S_LEFT,		"\233 A"},
339071d4279SBram Moolenaar     {K_S_RIGHT,		"\233 @"},
340071d4279SBram Moolenaar     {K_S_TAB,		"\233Z"},
3410d6f5d97SBram Moolenaar     {K_F1,		"\233\060~"},// some compilers don't dig "\2330"
342071d4279SBram Moolenaar     {K_F2,		"\233\061~"},
343071d4279SBram Moolenaar     {K_F3,		"\233\062~"},
344071d4279SBram Moolenaar     {K_F4,		"\233\063~"},
345071d4279SBram Moolenaar     {K_F5,		"\233\064~"},
346071d4279SBram Moolenaar     {K_F6,		"\233\065~"},
347071d4279SBram Moolenaar     {K_F7,		"\233\066~"},
348071d4279SBram Moolenaar     {K_F8,		"\233\067~"},
349071d4279SBram Moolenaar     {K_F9,		"\233\070~"},
350071d4279SBram Moolenaar     {K_F10,		"\233\071~"},
351071d4279SBram Moolenaar     {K_S_F1,		"\233\061\060~"},
352071d4279SBram Moolenaar     {K_S_F2,		"\233\061\061~"},
353071d4279SBram Moolenaar     {K_S_F3,		"\233\061\062~"},
354071d4279SBram Moolenaar     {K_S_F4,		"\233\061\063~"},
355071d4279SBram Moolenaar     {K_S_F5,		"\233\061\064~"},
356071d4279SBram Moolenaar     {K_S_F6,		"\233\061\065~"},
357071d4279SBram Moolenaar     {K_S_F7,		"\233\061\066~"},
358071d4279SBram Moolenaar     {K_S_F8,		"\233\061\067~"},
359071d4279SBram Moolenaar     {K_S_F9,		"\233\061\070~"},
360071d4279SBram Moolenaar     {K_S_F10,		"\233\061\071~"},
361071d4279SBram Moolenaar     {K_HELP,		"\233?~"},
3620d6f5d97SBram Moolenaar     {K_INS,		"\233\064\060~"},	// 101 key keyboard
3630d6f5d97SBram Moolenaar     {K_PAGEUP,		"\233\064\061~"},	// 101 key keyboard
3640d6f5d97SBram Moolenaar     {K_PAGEDOWN,	"\233\064\062~"},	// 101 key keyboard
3650d6f5d97SBram Moolenaar     {K_HOME,		"\233\064\064~"},	// 101 key keyboard
3660d6f5d97SBram Moolenaar     {K_END,		"\233\064\065~"},	// 101 key keyboard
367071d4279SBram Moolenaar 
368071d4279SBram Moolenaar     {BT_EXTRA_KEYS,	""},
3690d6f5d97SBram Moolenaar     {TERMCAP2KEY('#', '2'), "\233\065\064~"},	// shifted home key
3700d6f5d97SBram Moolenaar     {TERMCAP2KEY('#', '3'), "\233\065\060~"},	// shifted insert key
3710d6f5d97SBram Moolenaar     {TERMCAP2KEY('*', '7'), "\233\065\065~"},	// shifted end key
372071d4279SBram Moolenaar # endif
373071d4279SBram Moolenaar 
374041c7107SBram Moolenaar # ifdef ALL_BUILTIN_TCAPS
375071d4279SBram Moolenaar /*
376041c7107SBram Moolenaar  * almost standard ANSI terminal
377071d4279SBram Moolenaar  */
378071d4279SBram Moolenaar     {(int)KS_CE,	"\033[K"},
379071d4279SBram Moolenaar     {(int)KS_CD,	"\033[J"},
380071d4279SBram Moolenaar     {(int)KS_AL,	"\033[L"},
381071d4279SBram Moolenaar #  ifdef TERMINFO
382071d4279SBram Moolenaar     {(int)KS_CAL,	"\033[%p1%dL"},
383071d4279SBram Moolenaar #  else
384071d4279SBram Moolenaar     {(int)KS_CAL,	"\033[%dL"},
385071d4279SBram Moolenaar #  endif
386071d4279SBram Moolenaar     {(int)KS_DL,	"\033[M"},
387071d4279SBram Moolenaar #  ifdef TERMINFO
388071d4279SBram Moolenaar     {(int)KS_CDL,	"\033[%p1%dM"},
389071d4279SBram Moolenaar #  else
390071d4279SBram Moolenaar     {(int)KS_CDL,	"\033[%dM"},
391071d4279SBram Moolenaar #  endif
392071d4279SBram Moolenaar     {(int)KS_CL,	"\033[H\033[2J"},
393071d4279SBram Moolenaar #ifdef notyet
3940d6f5d97SBram Moolenaar     {(int)KS_VI,	"[VI]"}, // cursor invisible, VT320: CSI ? 25 l
3950d6f5d97SBram Moolenaar     {(int)KS_VE,	"[VE]"}, // cursor visible, VT320: CSI ? 25 h
396071d4279SBram Moolenaar #endif
3970d6f5d97SBram Moolenaar     {(int)KS_ME,	"\033[m"},	// normal mode
3980d6f5d97SBram Moolenaar     {(int)KS_MR,	"\033[7m"},	// reverse
3990d6f5d97SBram Moolenaar     {(int)KS_MD,	"\033[1m"},	// bold
4000d6f5d97SBram Moolenaar     {(int)KS_SO,	"\033[31m"},	// standout mode: red
4010d6f5d97SBram Moolenaar     {(int)KS_SE,	"\033[m"},	// standout end
4020d6f5d97SBram Moolenaar     {(int)KS_CZH,	"\033[35m"},	// italic: purple
4030d6f5d97SBram Moolenaar     {(int)KS_CZR,	"\033[m"},	// italic end
4040d6f5d97SBram Moolenaar     {(int)KS_US,	"\033[4m"},	// underscore mode
4050d6f5d97SBram Moolenaar     {(int)KS_UE,	"\033[m"},	// underscore end
4060d6f5d97SBram Moolenaar     {(int)KS_CCO,	"8"},		// allow 8 colors
407071d4279SBram Moolenaar #  ifdef TERMINFO
4080d6f5d97SBram Moolenaar     {(int)KS_CAB,	"\033[4%p1%dm"},// set background color
4090d6f5d97SBram Moolenaar     {(int)KS_CAF,	"\033[3%p1%dm"},// set foreground color
410071d4279SBram Moolenaar #  else
4110d6f5d97SBram Moolenaar     {(int)KS_CAB,	"\033[4%dm"},	// set background color
4120d6f5d97SBram Moolenaar     {(int)KS_CAF,	"\033[3%dm"},	// set foreground color
413071d4279SBram Moolenaar #  endif
4140d6f5d97SBram Moolenaar     {(int)KS_OP,	"\033[m"},	// reset colors
4150d6f5d97SBram Moolenaar     {(int)KS_MS,	"y"},		// safe to move cur in reverse mode
4160d6f5d97SBram Moolenaar     {(int)KS_UT,	"y"},		// guessed
417071d4279SBram Moolenaar     {(int)KS_LE,	"\b"},
418071d4279SBram Moolenaar #  ifdef TERMINFO
419071d4279SBram Moolenaar     {(int)KS_CM,	"\033[%i%p1%d;%p2%dH"},
420071d4279SBram Moolenaar #  else
421071d4279SBram Moolenaar     {(int)KS_CM,	"\033[%i%d;%dH"},
422071d4279SBram Moolenaar #  endif
423071d4279SBram Moolenaar     {(int)KS_SR,	"\033M"},
424071d4279SBram Moolenaar #  ifdef TERMINFO
425071d4279SBram Moolenaar     {(int)KS_CRI,	"\033[%p1%dC"},
426071d4279SBram Moolenaar #  else
427071d4279SBram Moolenaar     {(int)KS_CRI,	"\033[%dC"},
428071d4279SBram Moolenaar #  endif
429071d4279SBram Moolenaar 
430071d4279SBram Moolenaar     {K_UP,		"\033[A"},
431071d4279SBram Moolenaar     {K_DOWN,		"\033[B"},
432071d4279SBram Moolenaar     {K_LEFT,		"\033[D"},
433071d4279SBram Moolenaar     {K_RIGHT,		"\033[C"},
434071d4279SBram Moolenaar # endif
435071d4279SBram Moolenaar 
436a06ecab7SBram Moolenaar # if defined(UNIX) || defined(ALL_BUILTIN_TCAPS) || defined(SOME_BUILTIN_TCAPS)
437071d4279SBram Moolenaar /*
438071d4279SBram Moolenaar  * standard ANSI terminal, default for unix
439071d4279SBram Moolenaar  */
440071d4279SBram Moolenaar     {(int)KS_NAME,	"ansi"},
441071d4279SBram Moolenaar     {(int)KS_CE,	IF_EB("\033[K", ESC_STR "[K")},
442071d4279SBram Moolenaar     {(int)KS_AL,	IF_EB("\033[L", ESC_STR "[L")},
443071d4279SBram Moolenaar #  ifdef TERMINFO
444071d4279SBram Moolenaar     {(int)KS_CAL,	IF_EB("\033[%p1%dL", ESC_STR "[%p1%dL")},
445071d4279SBram Moolenaar #  else
446071d4279SBram Moolenaar     {(int)KS_CAL,	IF_EB("\033[%dL", ESC_STR "[%dL")},
447071d4279SBram Moolenaar #  endif
448071d4279SBram Moolenaar     {(int)KS_DL,	IF_EB("\033[M", ESC_STR "[M")},
449071d4279SBram Moolenaar #  ifdef TERMINFO
450071d4279SBram Moolenaar     {(int)KS_CDL,	IF_EB("\033[%p1%dM", ESC_STR "[%p1%dM")},
451071d4279SBram Moolenaar #  else
452071d4279SBram Moolenaar     {(int)KS_CDL,	IF_EB("\033[%dM", ESC_STR "[%dM")},
453071d4279SBram Moolenaar #  endif
454071d4279SBram Moolenaar     {(int)KS_CL,	IF_EB("\033[H\033[2J", ESC_STR "[H" ESC_STR_nc "[2J")},
455071d4279SBram Moolenaar     {(int)KS_ME,	IF_EB("\033[0m", ESC_STR "[0m")},
456071d4279SBram Moolenaar     {(int)KS_MR,	IF_EB("\033[7m", ESC_STR "[7m")},
457071d4279SBram Moolenaar     {(int)KS_MS,	"y"},
4580d6f5d97SBram Moolenaar     {(int)KS_UT,	"y"},		// guessed
459071d4279SBram Moolenaar     {(int)KS_LE,	"\b"},
460071d4279SBram Moolenaar #  ifdef TERMINFO
461071d4279SBram Moolenaar     {(int)KS_CM,	IF_EB("\033[%i%p1%d;%p2%dH", ESC_STR "[%i%p1%d;%p2%dH")},
462071d4279SBram Moolenaar #  else
463071d4279SBram Moolenaar     {(int)KS_CM,	IF_EB("\033[%i%d;%dH", ESC_STR "[%i%d;%dH")},
464071d4279SBram Moolenaar #  endif
465071d4279SBram Moolenaar #  ifdef TERMINFO
466071d4279SBram Moolenaar     {(int)KS_CRI,	IF_EB("\033[%p1%dC", ESC_STR "[%p1%dC")},
467071d4279SBram Moolenaar #  else
468071d4279SBram Moolenaar     {(int)KS_CRI,	IF_EB("\033[%dC", ESC_STR "[%dC")},
469071d4279SBram Moolenaar #  endif
470071d4279SBram Moolenaar # endif
471071d4279SBram Moolenaar 
472a06ecab7SBram Moolenaar # if defined(ALL_BUILTIN_TCAPS)
473071d4279SBram Moolenaar /*
474071d4279SBram Moolenaar  * These codes are valid when nansi.sys or equivalent has been installed.
475071d4279SBram Moolenaar  * Function keys on a PC are preceded with a NUL. These are converted into
476071d4279SBram Moolenaar  * K_NUL '\316' in mch_inchar(), because we cannot handle NULs in key codes.
477071d4279SBram Moolenaar  * CTRL-arrow is used instead of SHIFT-arrow.
478071d4279SBram Moolenaar  */
479071d4279SBram Moolenaar     {(int)KS_NAME,	"pcansi"},
480071d4279SBram Moolenaar     {(int)KS_DL,	"\033[M"},
481071d4279SBram Moolenaar     {(int)KS_AL,	"\033[L"},
482071d4279SBram Moolenaar     {(int)KS_CE,	"\033[K"},
483071d4279SBram Moolenaar     {(int)KS_CL,	"\033[2J"},
484071d4279SBram Moolenaar     {(int)KS_ME,	"\033[0m"},
4850d6f5d97SBram Moolenaar     {(int)KS_MR,	"\033[5m"},	// reverse: black on lightgrey
4860d6f5d97SBram Moolenaar     {(int)KS_MD,	"\033[1m"},	// bold: white text
4870d6f5d97SBram Moolenaar     {(int)KS_SE,	"\033[0m"},	// standout end
4880d6f5d97SBram Moolenaar     {(int)KS_SO,	"\033[31m"},	// standout: white on blue
4890d6f5d97SBram Moolenaar     {(int)KS_CZH,	"\033[34;43m"},	// italic mode: blue text on yellow
4900d6f5d97SBram Moolenaar     {(int)KS_CZR,	"\033[0m"},	// italic mode end
4910d6f5d97SBram Moolenaar     {(int)KS_US,	"\033[36;41m"},	// underscore mode: cyan text on red
4920d6f5d97SBram Moolenaar     {(int)KS_UE,	"\033[0m"},	// underscore mode end
4930d6f5d97SBram Moolenaar     {(int)KS_CCO,	"8"},		// allow 8 colors
494071d4279SBram Moolenaar #  ifdef TERMINFO
4950d6f5d97SBram Moolenaar     {(int)KS_CAB,	"\033[4%p1%dm"},// set background color
4960d6f5d97SBram Moolenaar     {(int)KS_CAF,	"\033[3%p1%dm"},// set foreground color
497071d4279SBram Moolenaar #  else
4980d6f5d97SBram Moolenaar     {(int)KS_CAB,	"\033[4%dm"},	// set background color
4990d6f5d97SBram Moolenaar     {(int)KS_CAF,	"\033[3%dm"},	// set foreground color
500071d4279SBram Moolenaar #  endif
5010d6f5d97SBram Moolenaar     {(int)KS_OP,	"\033[0m"},	// reset colors
502071d4279SBram Moolenaar     {(int)KS_MS,	"y"},
5030d6f5d97SBram Moolenaar     {(int)KS_UT,	"y"},		// guessed
504071d4279SBram Moolenaar     {(int)KS_LE,	"\b"},
505071d4279SBram Moolenaar #  ifdef TERMINFO
506071d4279SBram Moolenaar     {(int)KS_CM,	"\033[%i%p1%d;%p2%dH"},
507071d4279SBram Moolenaar #  else
508071d4279SBram Moolenaar     {(int)KS_CM,	"\033[%i%d;%dH"},
509071d4279SBram Moolenaar #  endif
510071d4279SBram Moolenaar #  ifdef TERMINFO
511071d4279SBram Moolenaar     {(int)KS_CRI,	"\033[%p1%dC"},
512071d4279SBram Moolenaar #  else
513071d4279SBram Moolenaar     {(int)KS_CRI,	"\033[%dC"},
514071d4279SBram Moolenaar #  endif
515071d4279SBram Moolenaar     {K_UP,		"\316H"},
516071d4279SBram Moolenaar     {K_DOWN,		"\316P"},
517071d4279SBram Moolenaar     {K_LEFT,		"\316K"},
518071d4279SBram Moolenaar     {K_RIGHT,		"\316M"},
519071d4279SBram Moolenaar     {K_S_LEFT,		"\316s"},
520071d4279SBram Moolenaar     {K_S_RIGHT,		"\316t"},
521071d4279SBram Moolenaar     {K_F1,		"\316;"},
522071d4279SBram Moolenaar     {K_F2,		"\316<"},
523071d4279SBram Moolenaar     {K_F3,		"\316="},
524071d4279SBram Moolenaar     {K_F4,		"\316>"},
525071d4279SBram Moolenaar     {K_F5,		"\316?"},
526071d4279SBram Moolenaar     {K_F6,		"\316@"},
527071d4279SBram Moolenaar     {K_F7,		"\316A"},
528071d4279SBram Moolenaar     {K_F8,		"\316B"},
529071d4279SBram Moolenaar     {K_F9,		"\316C"},
530071d4279SBram Moolenaar     {K_F10,		"\316D"},
5310d6f5d97SBram Moolenaar     {K_F11,		"\316\205"},	// guessed
5320d6f5d97SBram Moolenaar     {K_F12,		"\316\206"},	// guessed
533071d4279SBram Moolenaar     {K_S_F1,		"\316T"},
534071d4279SBram Moolenaar     {K_S_F2,		"\316U"},
535071d4279SBram Moolenaar     {K_S_F3,		"\316V"},
536071d4279SBram Moolenaar     {K_S_F4,		"\316W"},
537071d4279SBram Moolenaar     {K_S_F5,		"\316X"},
538071d4279SBram Moolenaar     {K_S_F6,		"\316Y"},
539071d4279SBram Moolenaar     {K_S_F7,		"\316Z"},
540071d4279SBram Moolenaar     {K_S_F8,		"\316["},
541071d4279SBram Moolenaar     {K_S_F9,		"\316\\"},
542071d4279SBram Moolenaar     {K_S_F10,		"\316]"},
5430d6f5d97SBram Moolenaar     {K_S_F11,		"\316\207"},	// guessed
5440d6f5d97SBram Moolenaar     {K_S_F12,		"\316\210"},	// guessed
545071d4279SBram Moolenaar     {K_INS,		"\316R"},
546071d4279SBram Moolenaar     {K_DEL,		"\316S"},
547071d4279SBram Moolenaar     {K_HOME,		"\316G"},
548071d4279SBram Moolenaar     {K_END,		"\316O"},
549071d4279SBram Moolenaar     {K_PAGEDOWN,	"\316Q"},
550071d4279SBram Moolenaar     {K_PAGEUP,		"\316I"},
551071d4279SBram Moolenaar # endif
552071d4279SBram Moolenaar 
5534f97475dSBram Moolenaar # if defined(MSWIN) || defined(ALL_BUILTIN_TCAPS)
554071d4279SBram Moolenaar /*
555071d4279SBram Moolenaar  * These codes are valid for the Win32 Console .  The entries that start with
556071d4279SBram Moolenaar  * ESC | are translated into console calls in os_win32.c.  The function keys
557071d4279SBram Moolenaar  * are also translated in os_win32.c.
558071d4279SBram Moolenaar  */
559071d4279SBram Moolenaar     {(int)KS_NAME,	"win32"},
5606982f42fSBram Moolenaar     {(int)KS_CE,	"\033|K"},	// clear to end of line
5616982f42fSBram Moolenaar     {(int)KS_AL,	"\033|L"},	// add new blank line
562071d4279SBram Moolenaar #  ifdef TERMINFO
5636982f42fSBram Moolenaar     {(int)KS_CAL,	"\033|%p1%dL"},	// add number of new blank lines
564071d4279SBram Moolenaar #  else
5656982f42fSBram Moolenaar     {(int)KS_CAL,	"\033|%dL"},	// add number of new blank lines
566071d4279SBram Moolenaar #  endif
5676982f42fSBram Moolenaar     {(int)KS_DL,	"\033|M"},	// delete line
568071d4279SBram Moolenaar #  ifdef TERMINFO
5696982f42fSBram Moolenaar     {(int)KS_CDL,	"\033|%p1%dM"},	// delete number of lines
5706982f42fSBram Moolenaar     {(int)KS_CSV,	"\033|%p1%d;%p2%dV"},
571071d4279SBram Moolenaar #  else
5726982f42fSBram Moolenaar     {(int)KS_CDL,	"\033|%dM"},	// delete number of lines
5736982f42fSBram Moolenaar     {(int)KS_CSV,	"\033|%d;%dV"},
574071d4279SBram Moolenaar #  endif
5756982f42fSBram Moolenaar     {(int)KS_CL,	"\033|J"},	// clear screen
5766982f42fSBram Moolenaar     {(int)KS_CD,	"\033|j"},	// clear to end of display
5776982f42fSBram Moolenaar     {(int)KS_VI,	"\033|v"},	// cursor invisible
5786982f42fSBram Moolenaar     {(int)KS_VE,	"\033|V"},	// cursor visible
579071d4279SBram Moolenaar 
5806982f42fSBram Moolenaar     {(int)KS_ME,	"\033|0m"},	// normal
5816982f42fSBram Moolenaar     {(int)KS_MR,	"\033|112m"},	// reverse: black on lightgray
5826982f42fSBram Moolenaar     {(int)KS_MD,	"\033|15m"},	// bold: white on black
583071d4279SBram Moolenaar #if 1
5846982f42fSBram Moolenaar     {(int)KS_SO,	"\033|31m"},	// standout: white on blue
5856982f42fSBram Moolenaar     {(int)KS_SE,	"\033|0m"},	// standout end
586071d4279SBram Moolenaar #else
5876982f42fSBram Moolenaar     {(int)KS_SO,	"\033|F"},	// standout: high intensity
5886982f42fSBram Moolenaar     {(int)KS_SE,	"\033|f"},	// standout end
589071d4279SBram Moolenaar #endif
5906982f42fSBram Moolenaar     {(int)KS_CZH,	"\033|225m"},	// italic: blue text on yellow
5916982f42fSBram Moolenaar     {(int)KS_CZR,	"\033|0m"},	// italic end
5926982f42fSBram Moolenaar     {(int)KS_US,	"\033|67m"},	// underscore: cyan text on red
5936982f42fSBram Moolenaar     {(int)KS_UE,	"\033|0m"},	// underscore end
5946982f42fSBram Moolenaar     {(int)KS_CCO,	"16"},		// allow 16 colors
595071d4279SBram Moolenaar #  ifdef TERMINFO
5966982f42fSBram Moolenaar     {(int)KS_CAB,	"\033|%p1%db"},	// set background color
5976982f42fSBram Moolenaar     {(int)KS_CAF,	"\033|%p1%df"},	// set foreground color
598071d4279SBram Moolenaar #  else
5996982f42fSBram Moolenaar     {(int)KS_CAB,	"\033|%db"},	// set background color
6006982f42fSBram Moolenaar     {(int)KS_CAF,	"\033|%df"},	// set foreground color
601071d4279SBram Moolenaar #  endif
602071d4279SBram Moolenaar 
6036982f42fSBram Moolenaar     {(int)KS_MS,	"y"},		// save to move cur in reverse mode
604071d4279SBram Moolenaar     {(int)KS_UT,	"y"},
605494838a3SBram Moolenaar     {(int)KS_XN,	"y"},
606071d4279SBram Moolenaar     {(int)KS_LE,	"\b"},
607071d4279SBram Moolenaar #  ifdef TERMINFO
6086982f42fSBram Moolenaar     {(int)KS_CM,	"\033|%i%p1%d;%p2%dH"}, // cursor motion
609071d4279SBram Moolenaar #  else
6106982f42fSBram Moolenaar     {(int)KS_CM,	"\033|%i%d;%dH"}, // cursor motion
611071d4279SBram Moolenaar #  endif
6126982f42fSBram Moolenaar     {(int)KS_VB,	"\033|B"},	// visual bell
6136982f42fSBram Moolenaar     {(int)KS_TI,	"\033|S"},	// put terminal in termcap mode
6146982f42fSBram Moolenaar     {(int)KS_TE,	"\033|E"},	// out of termcap mode
615071d4279SBram Moolenaar #  ifdef TERMINFO
6166982f42fSBram Moolenaar     {(int)KS_CS,	"\033|%i%p1%d;%p2%dr"}, // scroll region
617071d4279SBram Moolenaar #  else
6186982f42fSBram Moolenaar     {(int)KS_CS,	"\033|%i%d;%dr"}, // scroll region
619071d4279SBram Moolenaar #  endif
620cafafb38SBram Moolenaar #  ifdef FEAT_TERMGUICOLORS
621cafafb38SBram Moolenaar     {(int)KS_8F,	"\033|38;2;%lu;%lu;%lum"},
622cafafb38SBram Moolenaar     {(int)KS_8B,	"\033|48;2;%lu;%lu;%lum"},
623cafafb38SBram Moolenaar #  endif
624071d4279SBram Moolenaar 
625071d4279SBram Moolenaar     {K_UP,		"\316H"},
626071d4279SBram Moolenaar     {K_DOWN,		"\316P"},
627071d4279SBram Moolenaar     {K_LEFT,		"\316K"},
628071d4279SBram Moolenaar     {K_RIGHT,		"\316M"},
629071d4279SBram Moolenaar     {K_S_UP,		"\316\304"},
630071d4279SBram Moolenaar     {K_S_DOWN,		"\316\317"},
631071d4279SBram Moolenaar     {K_S_LEFT,		"\316\311"},
632071d4279SBram Moolenaar     {K_C_LEFT,		"\316s"},
633071d4279SBram Moolenaar     {K_S_RIGHT,		"\316\313"},
634071d4279SBram Moolenaar     {K_C_RIGHT,		"\316t"},
635071d4279SBram Moolenaar     {K_S_TAB,		"\316\017"},
636071d4279SBram Moolenaar     {K_F1,		"\316;"},
637071d4279SBram Moolenaar     {K_F2,		"\316<"},
638071d4279SBram Moolenaar     {K_F3,		"\316="},
639071d4279SBram Moolenaar     {K_F4,		"\316>"},
640071d4279SBram Moolenaar     {K_F5,		"\316?"},
641071d4279SBram Moolenaar     {K_F6,		"\316@"},
642071d4279SBram Moolenaar     {K_F7,		"\316A"},
643071d4279SBram Moolenaar     {K_F8,		"\316B"},
644071d4279SBram Moolenaar     {K_F9,		"\316C"},
645071d4279SBram Moolenaar     {K_F10,		"\316D"},
646071d4279SBram Moolenaar     {K_F11,		"\316\205"},
647071d4279SBram Moolenaar     {K_F12,		"\316\206"},
648071d4279SBram Moolenaar     {K_S_F1,		"\316T"},
649071d4279SBram Moolenaar     {K_S_F2,		"\316U"},
650071d4279SBram Moolenaar     {K_S_F3,		"\316V"},
651071d4279SBram Moolenaar     {K_S_F4,		"\316W"},
652071d4279SBram Moolenaar     {K_S_F5,		"\316X"},
653071d4279SBram Moolenaar     {K_S_F6,		"\316Y"},
654071d4279SBram Moolenaar     {K_S_F7,		"\316Z"},
655071d4279SBram Moolenaar     {K_S_F8,		"\316["},
656071d4279SBram Moolenaar     {K_S_F9,		"\316\\"},
657071d4279SBram Moolenaar     {K_S_F10,		"\316]"},
658071d4279SBram Moolenaar     {K_S_F11,		"\316\207"},
659071d4279SBram Moolenaar     {K_S_F12,		"\316\210"},
660071d4279SBram Moolenaar     {K_INS,		"\316R"},
661071d4279SBram Moolenaar     {K_DEL,		"\316S"},
662071d4279SBram Moolenaar     {K_HOME,		"\316G"},
663071d4279SBram Moolenaar     {K_S_HOME,		"\316\302"},
664071d4279SBram Moolenaar     {K_C_HOME,		"\316w"},
665071d4279SBram Moolenaar     {K_END,		"\316O"},
666071d4279SBram Moolenaar     {K_S_END,		"\316\315"},
667071d4279SBram Moolenaar     {K_C_END,		"\316u"},
668071d4279SBram Moolenaar     {K_PAGEDOWN,	"\316Q"},
669071d4279SBram Moolenaar     {K_PAGEUP,		"\316I"},
670071d4279SBram Moolenaar     {K_KPLUS,		"\316N"},
671071d4279SBram Moolenaar     {K_KMINUS,		"\316J"},
672071d4279SBram Moolenaar     {K_KMULTIPLY,	"\316\067"},
673071d4279SBram Moolenaar     {K_K0,		"\316\332"},
674071d4279SBram Moolenaar     {K_K1,		"\316\336"},
675071d4279SBram Moolenaar     {K_K2,		"\316\342"},
676071d4279SBram Moolenaar     {K_K3,		"\316\346"},
677071d4279SBram Moolenaar     {K_K4,		"\316\352"},
678071d4279SBram Moolenaar     {K_K5,		"\316\356"},
679071d4279SBram Moolenaar     {K_K6,		"\316\362"},
680071d4279SBram Moolenaar     {K_K7,		"\316\366"},
681071d4279SBram Moolenaar     {K_K8,		"\316\372"},
682071d4279SBram Moolenaar     {K_K9,		"\316\376"},
683b70a47b7SBram Moolenaar     {K_BS,		"\316x"},
684071d4279SBram Moolenaar # endif
685071d4279SBram Moolenaar 
686071d4279SBram Moolenaar # if defined(VMS) || defined(ALL_BUILTIN_TCAPS)
687071d4279SBram Moolenaar /*
688071d4279SBram Moolenaar  * VT320 is working as an ANSI terminal compatible DEC terminal.
689071d4279SBram Moolenaar  * (it covers VT1x0, VT2x0 and VT3x0 up to VT320 on VMS as well)
690071d4279SBram Moolenaar  * TODO:- rewrite ESC[ codes to CSI
691071d4279SBram Moolenaar  *      - keyboard languages (CSI ? 26 n)
692071d4279SBram Moolenaar  */
693071d4279SBram Moolenaar     {(int)KS_NAME,	"vt320"},
694071d4279SBram Moolenaar     {(int)KS_CE,	IF_EB("\033[K", ESC_STR "[K")},
695071d4279SBram Moolenaar     {(int)KS_AL,	IF_EB("\033[L", ESC_STR "[L")},
696071d4279SBram Moolenaar #  ifdef TERMINFO
697071d4279SBram Moolenaar     {(int)KS_CAL,	IF_EB("\033[%p1%dL", ESC_STR "[%p1%dL")},
698071d4279SBram Moolenaar #  else
699071d4279SBram Moolenaar     {(int)KS_CAL,	IF_EB("\033[%dL", ESC_STR "[%dL")},
700071d4279SBram Moolenaar #  endif
701071d4279SBram Moolenaar     {(int)KS_DL,	IF_EB("\033[M", ESC_STR "[M")},
702071d4279SBram Moolenaar #  ifdef TERMINFO
703071d4279SBram Moolenaar     {(int)KS_CDL,	IF_EB("\033[%p1%dM", ESC_STR "[%p1%dM")},
704071d4279SBram Moolenaar #  else
705071d4279SBram Moolenaar     {(int)KS_CDL,	IF_EB("\033[%dM", ESC_STR "[%dM")},
706071d4279SBram Moolenaar #  endif
707071d4279SBram Moolenaar     {(int)KS_CL,	IF_EB("\033[H\033[2J", ESC_STR "[H" ESC_STR_nc "[2J")},
708d4755bb0SBram Moolenaar     {(int)KS_CD,	IF_EB("\033[J", ESC_STR "[J")},
7090d6f5d97SBram Moolenaar     {(int)KS_CCO,	"8"},			// allow 8 colors
710071d4279SBram Moolenaar     {(int)KS_ME,	IF_EB("\033[0m", ESC_STR "[0m")},
711071d4279SBram Moolenaar     {(int)KS_MR,	IF_EB("\033[7m", ESC_STR "[7m")},
7120d6f5d97SBram Moolenaar     {(int)KS_MD,	IF_EB("\033[1m", ESC_STR "[1m")},  // bold mode
7130d6f5d97SBram Moolenaar     {(int)KS_SE,	IF_EB("\033[22m", ESC_STR "[22m")},// normal mode
7140d6f5d97SBram Moolenaar     {(int)KS_UE,	IF_EB("\033[24m", ESC_STR "[24m")},// exit underscore mode
7150d6f5d97SBram Moolenaar     {(int)KS_US,	IF_EB("\033[4m", ESC_STR "[4m")},  // underscore mode
7160d6f5d97SBram Moolenaar     {(int)KS_CZH,	IF_EB("\033[34;43m", ESC_STR "[34;43m")},  // italic mode: blue text on yellow
7170d6f5d97SBram Moolenaar     {(int)KS_CZR,	IF_EB("\033[0m", ESC_STR "[0m")},	    // italic mode end
7180d6f5d97SBram Moolenaar     {(int)KS_CAB,	IF_EB("\033[4%dm", ESC_STR "[4%dm")},	    // set background color (ANSI)
7190d6f5d97SBram Moolenaar     {(int)KS_CAF,	IF_EB("\033[3%dm", ESC_STR "[3%dm")},	    // set foreground color (ANSI)
7200d6f5d97SBram Moolenaar     {(int)KS_CSB,	IF_EB("\033[102;%dm", ESC_STR "[102;%dm")},	// set screen background color
7210d6f5d97SBram Moolenaar     {(int)KS_CSF,	IF_EB("\033[101;%dm", ESC_STR "[101;%dm")},	// set screen foreground color
722071d4279SBram Moolenaar     {(int)KS_MS,	"y"},
723071d4279SBram Moolenaar     {(int)KS_UT,	"y"},
724494838a3SBram Moolenaar     {(int)KS_XN,	"y"},
725071d4279SBram Moolenaar     {(int)KS_LE,	"\b"},
726071d4279SBram Moolenaar #  ifdef TERMINFO
727071d4279SBram Moolenaar     {(int)KS_CM,	IF_EB("\033[%i%p1%d;%p2%dH",
728071d4279SBram Moolenaar 						  ESC_STR "[%i%p1%d;%p2%dH")},
729071d4279SBram Moolenaar #  else
730071d4279SBram Moolenaar     {(int)KS_CM,	IF_EB("\033[%i%d;%dH", ESC_STR "[%i%d;%dH")},
731071d4279SBram Moolenaar #  endif
732071d4279SBram Moolenaar #  ifdef TERMINFO
733071d4279SBram Moolenaar     {(int)KS_CRI,	IF_EB("\033[%p1%dC", ESC_STR "[%p1%dC")},
734071d4279SBram Moolenaar #  else
735071d4279SBram Moolenaar     {(int)KS_CRI,	IF_EB("\033[%dC", ESC_STR "[%dC")},
736071d4279SBram Moolenaar #  endif
737071d4279SBram Moolenaar     {K_UP,		IF_EB("\033[A", ESC_STR "[A")},
738071d4279SBram Moolenaar     {K_DOWN,		IF_EB("\033[B", ESC_STR "[B")},
739071d4279SBram Moolenaar     {K_RIGHT,		IF_EB("\033[C", ESC_STR "[C")},
740071d4279SBram Moolenaar     {K_LEFT,		IF_EB("\033[D", ESC_STR "[D")},
741e6882bdcSBram Moolenaar     // Note: cursor key sequences for application cursor mode are omitted,
742e6882bdcSBram Moolenaar     // because they interfere with typed commands: <Esc>OA.
743d857f0e0SBram Moolenaar     {K_F1,		IF_EB("\033[11~", ESC_STR "[11~")},
744d857f0e0SBram Moolenaar     {K_F2,		IF_EB("\033[12~", ESC_STR "[12~")},
745d857f0e0SBram Moolenaar     {K_F3,		IF_EB("\033[13~", ESC_STR "[13~")},
746d857f0e0SBram Moolenaar     {K_F4,		IF_EB("\033[14~", ESC_STR "[14~")},
747d857f0e0SBram Moolenaar     {K_F5,		IF_EB("\033[15~", ESC_STR "[15~")},
748071d4279SBram Moolenaar     {K_F6,		IF_EB("\033[17~", ESC_STR "[17~")},
749071d4279SBram Moolenaar     {K_F7,		IF_EB("\033[18~", ESC_STR "[18~")},
750071d4279SBram Moolenaar     {K_F8,		IF_EB("\033[19~", ESC_STR "[19~")},
751071d4279SBram Moolenaar     {K_F9,		IF_EB("\033[20~", ESC_STR "[20~")},
752071d4279SBram Moolenaar     {K_F10,		IF_EB("\033[21~", ESC_STR "[21~")},
753d857f0e0SBram Moolenaar     {K_F11,		IF_EB("\033[23~", ESC_STR "[23~")},
754071d4279SBram Moolenaar     {K_F12,		IF_EB("\033[24~", ESC_STR "[24~")},
755071d4279SBram Moolenaar     {K_F13,		IF_EB("\033[25~", ESC_STR "[25~")},
756071d4279SBram Moolenaar     {K_F14,		IF_EB("\033[26~", ESC_STR "[26~")},
7570d6f5d97SBram Moolenaar     {K_F15,		IF_EB("\033[28~", ESC_STR "[28~")},	// Help
7580d6f5d97SBram Moolenaar     {K_F16,		IF_EB("\033[29~", ESC_STR "[29~")},	// Select
759071d4279SBram Moolenaar     {K_F17,		IF_EB("\033[31~", ESC_STR "[31~")},
760071d4279SBram Moolenaar     {K_F18,		IF_EB("\033[32~", ESC_STR "[32~")},
761071d4279SBram Moolenaar     {K_F19,		IF_EB("\033[33~", ESC_STR "[33~")},
762071d4279SBram Moolenaar     {K_F20,		IF_EB("\033[34~", ESC_STR "[34~")},
763071d4279SBram Moolenaar     {K_INS,		IF_EB("\033[2~", ESC_STR "[2~")},
764071d4279SBram Moolenaar     {K_DEL,		IF_EB("\033[3~", ESC_STR "[3~")},
765071d4279SBram Moolenaar     {K_HOME,		IF_EB("\033[1~", ESC_STR "[1~")},
766071d4279SBram Moolenaar     {K_END,		IF_EB("\033[4~", ESC_STR "[4~")},
767071d4279SBram Moolenaar     {K_PAGEUP,		IF_EB("\033[5~", ESC_STR "[5~")},
768071d4279SBram Moolenaar     {K_PAGEDOWN,	IF_EB("\033[6~", ESC_STR "[6~")},
769e6882bdcSBram Moolenaar     // These sequences starting with <Esc> O may interfere with what the user
770e6882bdcSBram Moolenaar     // is typing.  Remove these if that bothers you.
7710d6f5d97SBram Moolenaar     {K_KPLUS,		IF_EB("\033Ok", ESC_STR "Ok")},	// keypad plus
7720d6f5d97SBram Moolenaar     {K_KMINUS,		IF_EB("\033Om", ESC_STR "Om")},	// keypad minus
7730d6f5d97SBram Moolenaar     {K_KDIVIDE,		IF_EB("\033Oo", ESC_STR "Oo")},	// keypad /
7740d6f5d97SBram Moolenaar     {K_KMULTIPLY,	IF_EB("\033Oj", ESC_STR "Oj")},	// keypad *
7750d6f5d97SBram Moolenaar     {K_KENTER,		IF_EB("\033OM", ESC_STR "OM")},	// keypad Enter
7760d6f5d97SBram Moolenaar     {K_K0,		IF_EB("\033Op", ESC_STR "Op")},	// keypad 0
7770d6f5d97SBram Moolenaar     {K_K1,		IF_EB("\033Oq", ESC_STR "Oq")},	// keypad 1
7780d6f5d97SBram Moolenaar     {K_K2,		IF_EB("\033Or", ESC_STR "Or")},	// keypad 2
7790d6f5d97SBram Moolenaar     {K_K3,		IF_EB("\033Os", ESC_STR "Os")},	// keypad 3
7800d6f5d97SBram Moolenaar     {K_K4,		IF_EB("\033Ot", ESC_STR "Ot")},	// keypad 4
7810d6f5d97SBram Moolenaar     {K_K5,		IF_EB("\033Ou", ESC_STR "Ou")},	// keypad 5
7820d6f5d97SBram Moolenaar     {K_K6,		IF_EB("\033Ov", ESC_STR "Ov")},	// keypad 6
7830d6f5d97SBram Moolenaar     {K_K7,		IF_EB("\033Ow", ESC_STR "Ow")},	// keypad 7
7840d6f5d97SBram Moolenaar     {K_K8,		IF_EB("\033Ox", ESC_STR "Ox")},	// keypad 8
7850d6f5d97SBram Moolenaar     {K_K9,		IF_EB("\033Oy", ESC_STR "Oy")},	// keypad 9
7860d6f5d97SBram Moolenaar     {K_BS,		"\x7f"},	// for some reason 0177 doesn't work
787071d4279SBram Moolenaar # endif
788071d4279SBram Moolenaar 
789e3f915d1SBram Moolenaar # if defined(ALL_BUILTIN_TCAPS)
790071d4279SBram Moolenaar /*
791071d4279SBram Moolenaar  * Ordinary vt52
792071d4279SBram Moolenaar  */
793071d4279SBram Moolenaar     {(int)KS_NAME,	"vt52"},
794071d4279SBram Moolenaar     {(int)KS_CE,	IF_EB("\033K", ESC_STR "K")},
795071d4279SBram Moolenaar     {(int)KS_CD,	IF_EB("\033J", ESC_STR "J")},
7962a1b474fSBram Moolenaar #  ifdef TERMINFO
7972a1b474fSBram Moolenaar     {(int)KS_CM,	IF_EB("\033Y%p1%' '%+%c%p2%' '%+%c",
7982a1b474fSBram Moolenaar 			    ESC_STR "Y%p1%' '%+%c%p2%' '%+%c")},
7992a1b474fSBram Moolenaar #  else
800071d4279SBram Moolenaar     {(int)KS_CM,	IF_EB("\033Y%+ %+ ", ESC_STR "Y%+ %+ ")},
8012a1b474fSBram Moolenaar #  endif
802071d4279SBram Moolenaar     {(int)KS_LE,	"\b"},
8032a1b474fSBram Moolenaar     {(int)KS_SR,	IF_EB("\033I", ESC_STR "I")},
804071d4279SBram Moolenaar     {(int)KS_AL,	IF_EB("\033L", ESC_STR "L")},
805071d4279SBram Moolenaar     {(int)KS_DL,	IF_EB("\033M", ESC_STR "M")},
806071d4279SBram Moolenaar     {K_UP,		IF_EB("\033A", ESC_STR "A")},
807071d4279SBram Moolenaar     {K_DOWN,		IF_EB("\033B", ESC_STR "B")},
808071d4279SBram Moolenaar     {K_LEFT,		IF_EB("\033D", ESC_STR "D")},
809071d4279SBram Moolenaar     {K_RIGHT,		IF_EB("\033C", ESC_STR "C")},
8102a1b474fSBram Moolenaar     {K_F1,		IF_EB("\033P", ESC_STR "P")},
8112a1b474fSBram Moolenaar     {K_F2,		IF_EB("\033Q", ESC_STR "Q")},
8122a1b474fSBram Moolenaar     {K_F3,		IF_EB("\033R", ESC_STR "R")},
813071d4279SBram Moolenaar     {(int)KS_CL,	IF_EB("\033H\033J", ESC_STR "H" ESC_STR_nc "J")},
814071d4279SBram Moolenaar     {(int)KS_MS,	"y"},
815071d4279SBram Moolenaar # endif
816071d4279SBram Moolenaar 
817a06ecab7SBram Moolenaar # if defined(UNIX) || defined(ALL_BUILTIN_TCAPS) || defined(SOME_BUILTIN_TCAPS)
818b2fa54a8SBram Moolenaar     {(int)KS_NAME,	"xterm"},
819071d4279SBram Moolenaar     {(int)KS_CE,	IF_EB("\033[K", ESC_STR "[K")},
820071d4279SBram Moolenaar     {(int)KS_AL,	IF_EB("\033[L", ESC_STR "[L")},
821071d4279SBram Moolenaar #  ifdef TERMINFO
822071d4279SBram Moolenaar     {(int)KS_CAL,	IF_EB("\033[%p1%dL", ESC_STR "[%p1%dL")},
823071d4279SBram Moolenaar #  else
824071d4279SBram Moolenaar     {(int)KS_CAL,	IF_EB("\033[%dL", ESC_STR "[%dL")},
825071d4279SBram Moolenaar #  endif
826071d4279SBram Moolenaar     {(int)KS_DL,	IF_EB("\033[M", ESC_STR "[M")},
827071d4279SBram Moolenaar #  ifdef TERMINFO
828071d4279SBram Moolenaar     {(int)KS_CDL,	IF_EB("\033[%p1%dM", ESC_STR "[%p1%dM")},
829071d4279SBram Moolenaar #  else
830071d4279SBram Moolenaar     {(int)KS_CDL,	IF_EB("\033[%dM", ESC_STR "[%dM")},
831071d4279SBram Moolenaar #  endif
832071d4279SBram Moolenaar #  ifdef TERMINFO
833071d4279SBram Moolenaar     {(int)KS_CS,	IF_EB("\033[%i%p1%d;%p2%dr",
834071d4279SBram Moolenaar 						  ESC_STR "[%i%p1%d;%p2%dr")},
835071d4279SBram Moolenaar #  else
836071d4279SBram Moolenaar     {(int)KS_CS,	IF_EB("\033[%i%d;%dr", ESC_STR "[%i%d;%dr")},
837071d4279SBram Moolenaar #  endif
838071d4279SBram Moolenaar     {(int)KS_CL,	IF_EB("\033[H\033[2J", ESC_STR "[H" ESC_STR_nc "[2J")},
839071d4279SBram Moolenaar     {(int)KS_CD,	IF_EB("\033[J", ESC_STR "[J")},
840071d4279SBram Moolenaar     {(int)KS_ME,	IF_EB("\033[m", ESC_STR "[m")},
841071d4279SBram Moolenaar     {(int)KS_MR,	IF_EB("\033[7m", ESC_STR "[7m")},
842071d4279SBram Moolenaar     {(int)KS_MD,	IF_EB("\033[1m", ESC_STR "[1m")},
843071d4279SBram Moolenaar     {(int)KS_UE,	IF_EB("\033[m", ESC_STR "[m")},
844071d4279SBram Moolenaar     {(int)KS_US,	IF_EB("\033[4m", ESC_STR "[4m")},
845cf4b00c8SBram Moolenaar     {(int)KS_STE,	IF_EB("\033[29m", ESC_STR "[29m")},
846cf4b00c8SBram Moolenaar     {(int)KS_STS,	IF_EB("\033[9m", ESC_STR "[9m")},
847071d4279SBram Moolenaar     {(int)KS_MS,	"y"},
848071d4279SBram Moolenaar     {(int)KS_UT,	"y"},
849071d4279SBram Moolenaar     {(int)KS_LE,	"\b"},
8503cd43cccSBram Moolenaar     {(int)KS_VI,	IF_EB("\033[?25l", ESC_STR "[?25l")},
8513cd43cccSBram Moolenaar     {(int)KS_VE,	IF_EB("\033[?25h", ESC_STR "[?25h")},
85293c92effSBram Moolenaar     {(int)KS_VS,	IF_EB("\033[?12h", ESC_STR "[?12h")},
853ce1c3278SBram Moolenaar     {(int)KS_CVS,	IF_EB("\033[?12l", ESC_STR "[?12l")},
8543cd43cccSBram Moolenaar #  ifdef TERMINFO
8553cd43cccSBram Moolenaar     {(int)KS_CSH,	IF_EB("\033[%p1%d q", ESC_STR "[%p1%d q")},
8563cd43cccSBram Moolenaar #  else
8573cd43cccSBram Moolenaar     {(int)KS_CSH,	IF_EB("\033[%d q", ESC_STR "[%d q")},
8583cd43cccSBram Moolenaar #  endif
8594db25549SBram Moolenaar     {(int)KS_CRC,	IF_EB("\033[?12$p", ESC_STR "[?12$p")},
8603eee06e7SBram Moolenaar     {(int)KS_CRS,	IF_EB("\033P$q q\033\\", ESC_STR "P$q q" ESC_STR "\\")},
861071d4279SBram Moolenaar #  ifdef TERMINFO
862071d4279SBram Moolenaar     {(int)KS_CM,	IF_EB("\033[%i%p1%d;%p2%dH",
863071d4279SBram Moolenaar 						  ESC_STR "[%i%p1%d;%p2%dH")},
864071d4279SBram Moolenaar #  else
865071d4279SBram Moolenaar     {(int)KS_CM,	IF_EB("\033[%i%d;%dH", ESC_STR "[%i%d;%dH")},
866071d4279SBram Moolenaar #  endif
867071d4279SBram Moolenaar     {(int)KS_SR,	IF_EB("\033M", ESC_STR "M")},
868071d4279SBram Moolenaar #  ifdef TERMINFO
869071d4279SBram Moolenaar     {(int)KS_CRI,	IF_EB("\033[%p1%dC", ESC_STR "[%p1%dC")},
870071d4279SBram Moolenaar #  else
871071d4279SBram Moolenaar     {(int)KS_CRI,	IF_EB("\033[%dC", ESC_STR "[%dC")},
872071d4279SBram Moolenaar #  endif
873071d4279SBram Moolenaar     {(int)KS_KS,	IF_EB("\033[?1h\033=", ESC_STR "[?1h" ESC_STR_nc "=")},
874071d4279SBram Moolenaar     {(int)KS_KE,	IF_EB("\033[?1l\033>", ESC_STR "[?1l" ESC_STR_nc ">")},
875071d4279SBram Moolenaar #  ifdef FEAT_XTERM_SAVE
876071d4279SBram Moolenaar     {(int)KS_TI,	IF_EB("\0337\033[?47h", ESC_STR "7" ESC_STR_nc "[?47h")},
877d02e508aSBram Moolenaar     {(int)KS_TE,	IF_EB("\033[?47l\0338",
878d02e508aSBram Moolenaar 					   ESC_STR_nc "[?47l" ESC_STR_nc "8")},
879071d4279SBram Moolenaar #  endif
8804b57018eSBram Moolenaar     {(int)KS_CTI,	IF_EB("\033[>4;2m", ESC_STR_nc "[>4;2m")},
8814b57018eSBram Moolenaar     {(int)KS_CTE,	IF_EB("\033[>4;m", ESC_STR_nc "[>4;m")},
882071d4279SBram Moolenaar     {(int)KS_CIS,	IF_EB("\033]1;", ESC_STR "]1;")},
883071d4279SBram Moolenaar     {(int)KS_CIE,	"\007"},
884071d4279SBram Moolenaar     {(int)KS_TS,	IF_EB("\033]2;", ESC_STR "]2;")},
885071d4279SBram Moolenaar     {(int)KS_FS,	"\007"},
8863cd43cccSBram Moolenaar     {(int)KS_CSC,	IF_EB("\033]12;", ESC_STR "]12;")},
8873cd43cccSBram Moolenaar     {(int)KS_CEC,	"\007"},
888071d4279SBram Moolenaar #  ifdef TERMINFO
889071d4279SBram Moolenaar     {(int)KS_CWS,	IF_EB("\033[8;%p1%d;%p2%dt",
890071d4279SBram Moolenaar 						  ESC_STR "[8;%p1%d;%p2%dt")},
891071d4279SBram Moolenaar     {(int)KS_CWP,	IF_EB("\033[3;%p1%d;%p2%dt",
892071d4279SBram Moolenaar 						  ESC_STR "[3;%p1%d;%p2%dt")},
893ba6ec182SBram Moolenaar     {(int)KS_CGP,	IF_EB("\033[13t", ESC_STR "[13t")},
894071d4279SBram Moolenaar #  else
895071d4279SBram Moolenaar     {(int)KS_CWS,	IF_EB("\033[8;%d;%dt", ESC_STR "[8;%d;%dt")},
896071d4279SBram Moolenaar     {(int)KS_CWP,	IF_EB("\033[3;%d;%dt", ESC_STR "[3;%d;%dt")},
897ba6ec182SBram Moolenaar     {(int)KS_CGP,	IF_EB("\033[13t", ESC_STR "[13t")},
898071d4279SBram Moolenaar #  endif
899071d4279SBram Moolenaar     {(int)KS_CRV,	IF_EB("\033[>c", ESC_STR "[>c")},
90065e4c4f6SBram Moolenaar     {(int)KS_RFG,	IF_EB("\033]10;?\007", ESC_STR "]10;?\007")},
901b5c32655SBram Moolenaar     {(int)KS_RBG,	IF_EB("\033]11;?\007", ESC_STR "]11;?\007")},
9029584b31aSBram Moolenaar     {(int)KS_U7,	IF_EB("\033[6n", ESC_STR "[6n")},
90361be73bbSBram Moolenaar #  ifdef FEAT_TERMGUICOLORS
9040d6f5d97SBram Moolenaar     // These are printf strings, not terminal codes.
905b2fa54a8SBram Moolenaar     {(int)KS_8F,	IF_EB("\033[38;2;%lu;%lu;%lum", ESC_STR "[38;2;%lu;%lu;%lum")},
906b2fa54a8SBram Moolenaar     {(int)KS_8B,	IF_EB("\033[48;2;%lu;%lu;%lum", ESC_STR "[48;2;%lu;%lu;%lum")},
907e023e88bSBram Moolenaar     {(int)KS_8U,	IF_EB("\033[58;2;%lu;%lu;%lum", ESC_STR "[58;2;%lu;%lu;%lum")},
908b2fa54a8SBram Moolenaar #  endif
909e023e88bSBram Moolenaar     {(int)KS_CAU,	IF_EB("\033[58;5;%dm", ESC_STR "[58;5;%dm")},
910ec2da36cSBram Moolenaar     {(int)KS_CBE,	IF_EB("\033[?2004h", ESC_STR "[?2004h")},
911ec2da36cSBram Moolenaar     {(int)KS_CBD,	IF_EB("\033[?2004l", ESC_STR "[?2004l")},
91240385dbcSBram Moolenaar     {(int)KS_CST,	IF_EB("\033[22;2t", ESC_STR "[22;2t")},
91340385dbcSBram Moolenaar     {(int)KS_CRT,	IF_EB("\033[23;2t", ESC_STR "[23;2t")},
91440385dbcSBram Moolenaar     {(int)KS_SSI,	IF_EB("\033[22;1t", ESC_STR "[22;1t")},
91540385dbcSBram Moolenaar     {(int)KS_SRI,	IF_EB("\033[23;1t", ESC_STR "[23;1t")},
916681fc3faSBram Moolenaar #  if (defined(UNIX) || defined(VMS))
917681fc3faSBram Moolenaar     {(int)KS_FD,	IF_EB("\033[?1004l", ESC_STR "[?1004l")},
918681fc3faSBram Moolenaar     {(int)KS_FE,	IF_EB("\033[?1004h", ESC_STR "[?1004h")},
919681fc3faSBram Moolenaar #  endif
920bc7aa85dSBram Moolenaar 
921bc7aa85dSBram Moolenaar     {K_UP,		IF_EB("\033O*A", ESC_STR "O*A")},
922bc7aa85dSBram Moolenaar     {K_DOWN,		IF_EB("\033O*B", ESC_STR "O*B")},
923bc7aa85dSBram Moolenaar     {K_RIGHT,		IF_EB("\033O*C", ESC_STR "O*C")},
924bc7aa85dSBram Moolenaar     {K_LEFT,		IF_EB("\033O*D", ESC_STR "O*D")},
9250d6f5d97SBram Moolenaar     // An extra set of cursor keys for vt100 mode
9264d8c96d4SBram Moolenaar     {K_XUP,		IF_EB("\033[@;*A", ESC_STR "[@;*A")},
9274d8c96d4SBram Moolenaar     {K_XDOWN,		IF_EB("\033[@;*B", ESC_STR "[@;*B")},
9284d8c96d4SBram Moolenaar     {K_XRIGHT,		IF_EB("\033[@;*C", ESC_STR "[@;*C")},
9294d8c96d4SBram Moolenaar     {K_XLEFT,		IF_EB("\033[@;*D", ESC_STR "[@;*D")},
9300d6f5d97SBram Moolenaar     // An extra set of function keys for vt100 mode
931bc7aa85dSBram Moolenaar     {K_XF1,		IF_EB("\033O*P", ESC_STR "O*P")},
932bc7aa85dSBram Moolenaar     {K_XF2,		IF_EB("\033O*Q", ESC_STR "O*Q")},
933bc7aa85dSBram Moolenaar     {K_XF3,		IF_EB("\033O*R", ESC_STR "O*R")},
934bc7aa85dSBram Moolenaar     {K_XF4,		IF_EB("\033O*S", ESC_STR "O*S")},
93519a09a18SBram Moolenaar     {K_F1,		IF_EB("\033[11;*~", ESC_STR "[11;*~")},
93619a09a18SBram Moolenaar     {K_F2,		IF_EB("\033[12;*~", ESC_STR "[12;*~")},
93719a09a18SBram Moolenaar     {K_F3,		IF_EB("\033[13;*~", ESC_STR "[13;*~")},
93819a09a18SBram Moolenaar     {K_F4,		IF_EB("\033[14;*~", ESC_STR "[14;*~")},
93919a09a18SBram Moolenaar     {K_F5,		IF_EB("\033[15;*~", ESC_STR "[15;*~")},
94019a09a18SBram Moolenaar     {K_F6,		IF_EB("\033[17;*~", ESC_STR "[17;*~")},
94119a09a18SBram Moolenaar     {K_F7,		IF_EB("\033[18;*~", ESC_STR "[18;*~")},
94219a09a18SBram Moolenaar     {K_F8,		IF_EB("\033[19;*~", ESC_STR "[19;*~")},
94319a09a18SBram Moolenaar     {K_F9,		IF_EB("\033[20;*~", ESC_STR "[20;*~")},
94419a09a18SBram Moolenaar     {K_F10,		IF_EB("\033[21;*~", ESC_STR "[21;*~")},
94519a09a18SBram Moolenaar     {K_F11,		IF_EB("\033[23;*~", ESC_STR "[23;*~")},
94619a09a18SBram Moolenaar     {K_F12,		IF_EB("\033[24;*~", ESC_STR "[24;*~")},
947071d4279SBram Moolenaar     {K_S_TAB,		IF_EB("\033[Z", ESC_STR "[Z")},
94819a09a18SBram Moolenaar     {K_HELP,		IF_EB("\033[28;*~", ESC_STR "[28;*~")},
94919a09a18SBram Moolenaar     {K_UNDO,		IF_EB("\033[26;*~", ESC_STR "[26;*~")},
95019a09a18SBram Moolenaar     {K_INS,		IF_EB("\033[2;*~", ESC_STR "[2;*~")},
95119a09a18SBram Moolenaar     {K_HOME,		IF_EB("\033[1;*H", ESC_STR "[1;*H")},
9520d6f5d97SBram Moolenaar     // {K_S_HOME,		IF_EB("\033O2H", ESC_STR "O2H")},
9530d6f5d97SBram Moolenaar     // {K_C_HOME,		IF_EB("\033O5H", ESC_STR "O5H")},
95468b76a69SBram Moolenaar     {K_KHOME,		IF_EB("\033[1;*~", ESC_STR "[1;*~")},
9550d6f5d97SBram Moolenaar     {K_XHOME,		IF_EB("\033O*H", ESC_STR "O*H")},	// other Home
9560d6f5d97SBram Moolenaar     {K_ZHOME,		IF_EB("\033[7;*~", ESC_STR "[7;*~")},	// other Home
95719a09a18SBram Moolenaar     {K_END,		IF_EB("\033[1;*F", ESC_STR "[1;*F")},
9580d6f5d97SBram Moolenaar     // {K_S_END,		IF_EB("\033O2F", ESC_STR "O2F")},
9590d6f5d97SBram Moolenaar     // {K_C_END,		IF_EB("\033O5F", ESC_STR "O5F")},
96019a09a18SBram Moolenaar     {K_KEND,		IF_EB("\033[4;*~", ESC_STR "[4;*~")},
9610d6f5d97SBram Moolenaar     {K_XEND,		IF_EB("\033O*F", ESC_STR "O*F")},	// other End
96268b76a69SBram Moolenaar     {K_ZEND,		IF_EB("\033[8;*~", ESC_STR "[8;*~")},
96319a09a18SBram Moolenaar     {K_PAGEUP,		IF_EB("\033[5;*~", ESC_STR "[5;*~")},
96419a09a18SBram Moolenaar     {K_PAGEDOWN,	IF_EB("\033[6;*~", ESC_STR "[6;*~")},
9650d6f5d97SBram Moolenaar     {K_KPLUS,		IF_EB("\033O*k", ESC_STR "O*k")},     // keypad plus
9660d6f5d97SBram Moolenaar     {K_KMINUS,		IF_EB("\033O*m", ESC_STR "O*m")},     // keypad minus
9670d6f5d97SBram Moolenaar     {K_KDIVIDE,		IF_EB("\033O*o", ESC_STR "O*o")},     // keypad /
9680d6f5d97SBram Moolenaar     {K_KMULTIPLY,	IF_EB("\033O*j", ESC_STR "O*j")},     // keypad *
9690d6f5d97SBram Moolenaar     {K_KENTER,		IF_EB("\033O*M", ESC_STR "O*M")},     // keypad Enter
9700d6f5d97SBram Moolenaar     {K_KPOINT,		IF_EB("\033O*n", ESC_STR "O*n")},     // keypad .
9710d6f5d97SBram Moolenaar     {K_K0,		IF_EB("\033O*p", ESC_STR "O*p")},     // keypad 0
9720d6f5d97SBram Moolenaar     {K_K1,		IF_EB("\033O*q", ESC_STR "O*q")},     // keypad 1
9730d6f5d97SBram Moolenaar     {K_K2,		IF_EB("\033O*r", ESC_STR "O*r")},     // keypad 2
9740d6f5d97SBram Moolenaar     {K_K3,		IF_EB("\033O*s", ESC_STR "O*s")},     // keypad 3
9750d6f5d97SBram Moolenaar     {K_K4,		IF_EB("\033O*t", ESC_STR "O*t")},     // keypad 4
9760d6f5d97SBram Moolenaar     {K_K5,		IF_EB("\033O*u", ESC_STR "O*u")},     // keypad 5
9770d6f5d97SBram Moolenaar     {K_K6,		IF_EB("\033O*v", ESC_STR "O*v")},     // keypad 6
9780d6f5d97SBram Moolenaar     {K_K7,		IF_EB("\033O*w", ESC_STR "O*w")},     // keypad 7
9790d6f5d97SBram Moolenaar     {K_K8,		IF_EB("\033O*x", ESC_STR "O*x")},     // keypad 8
9800d6f5d97SBram Moolenaar     {K_K9,		IF_EB("\033O*y", ESC_STR "O*y")},     // keypad 9
9810d6f5d97SBram Moolenaar     {K_KDEL,		IF_EB("\033[3;*~", ESC_STR "[3;*~")}, // keypad Del
9820d6f5d97SBram Moolenaar     {K_PS,		IF_EB("\033[200~", ESC_STR "[200~")}, // paste start
9830d6f5d97SBram Moolenaar     {K_PE,		IF_EB("\033[201~", ESC_STR "[201~")}, // paste end
984071d4279SBram Moolenaar 
985071d4279SBram Moolenaar     {BT_EXTRA_KEYS,   ""},
9860d6f5d97SBram Moolenaar     {TERMCAP2KEY('k', '0'), IF_EB("\033[10;*~", ESC_STR "[10;*~")}, // F0
9870d6f5d97SBram Moolenaar     {TERMCAP2KEY('F', '3'), IF_EB("\033[25;*~", ESC_STR "[25;*~")}, // F13
9880d6f5d97SBram Moolenaar     // F14 and F15 are missing, because they send the same codes as the undo
9890d6f5d97SBram Moolenaar     // and help key, although they don't work on all keyboards.
9900d6f5d97SBram Moolenaar     {TERMCAP2KEY('F', '6'), IF_EB("\033[29;*~", ESC_STR "[29;*~")}, // F16
9910d6f5d97SBram Moolenaar     {TERMCAP2KEY('F', '7'), IF_EB("\033[31;*~", ESC_STR "[31;*~")}, // F17
9920d6f5d97SBram Moolenaar     {TERMCAP2KEY('F', '8'), IF_EB("\033[32;*~", ESC_STR "[32;*~")}, // F18
9930d6f5d97SBram Moolenaar     {TERMCAP2KEY('F', '9'), IF_EB("\033[33;*~", ESC_STR "[33;*~")}, // F19
9940d6f5d97SBram Moolenaar     {TERMCAP2KEY('F', 'A'), IF_EB("\033[34;*~", ESC_STR "[34;*~")}, // F20
99519a09a18SBram Moolenaar 
9960d6f5d97SBram Moolenaar     {TERMCAP2KEY('F', 'B'), IF_EB("\033[42;*~", ESC_STR "[42;*~")}, // F21
9970d6f5d97SBram Moolenaar     {TERMCAP2KEY('F', 'C'), IF_EB("\033[43;*~", ESC_STR "[43;*~")}, // F22
9980d6f5d97SBram Moolenaar     {TERMCAP2KEY('F', 'D'), IF_EB("\033[44;*~", ESC_STR "[44;*~")}, // F23
9990d6f5d97SBram Moolenaar     {TERMCAP2KEY('F', 'E'), IF_EB("\033[45;*~", ESC_STR "[45;*~")}, // F24
10000d6f5d97SBram Moolenaar     {TERMCAP2KEY('F', 'F'), IF_EB("\033[46;*~", ESC_STR "[46;*~")}, // F25
10010d6f5d97SBram Moolenaar     {TERMCAP2KEY('F', 'G'), IF_EB("\033[47;*~", ESC_STR "[47;*~")}, // F26
10020d6f5d97SBram Moolenaar     {TERMCAP2KEY('F', 'H'), IF_EB("\033[48;*~", ESC_STR "[48;*~")}, // F27
10030d6f5d97SBram Moolenaar     {TERMCAP2KEY('F', 'I'), IF_EB("\033[49;*~", ESC_STR "[49;*~")}, // F28
10040d6f5d97SBram Moolenaar     {TERMCAP2KEY('F', 'J'), IF_EB("\033[50;*~", ESC_STR "[50;*~")}, // F29
10050d6f5d97SBram Moolenaar     {TERMCAP2KEY('F', 'K'), IF_EB("\033[51;*~", ESC_STR "[51;*~")}, // F30
100619a09a18SBram Moolenaar 
10070d6f5d97SBram Moolenaar     {TERMCAP2KEY('F', 'L'), IF_EB("\033[52;*~", ESC_STR "[52;*~")}, // F31
10080d6f5d97SBram Moolenaar     {TERMCAP2KEY('F', 'M'), IF_EB("\033[53;*~", ESC_STR "[53;*~")}, // F32
10090d6f5d97SBram Moolenaar     {TERMCAP2KEY('F', 'N'), IF_EB("\033[54;*~", ESC_STR "[54;*~")}, // F33
10100d6f5d97SBram Moolenaar     {TERMCAP2KEY('F', 'O'), IF_EB("\033[55;*~", ESC_STR "[55;*~")}, // F34
10110d6f5d97SBram Moolenaar     {TERMCAP2KEY('F', 'P'), IF_EB("\033[56;*~", ESC_STR "[56;*~")}, // F35
10120d6f5d97SBram Moolenaar     {TERMCAP2KEY('F', 'Q'), IF_EB("\033[57;*~", ESC_STR "[57;*~")}, // F36
10130d6f5d97SBram Moolenaar     {TERMCAP2KEY('F', 'R'), IF_EB("\033[58;*~", ESC_STR "[58;*~")}, // F37
1014071d4279SBram Moolenaar # endif
1015071d4279SBram Moolenaar 
1016071d4279SBram Moolenaar # if defined(UNIX) || defined(ALL_BUILTIN_TCAPS)
1017071d4279SBram Moolenaar /*
1018071d4279SBram Moolenaar  * iris-ansi for Silicon Graphics machines.
1019071d4279SBram Moolenaar  */
1020071d4279SBram Moolenaar     {(int)KS_NAME,	"iris-ansi"},
1021071d4279SBram Moolenaar     {(int)KS_CE,	"\033[K"},
1022071d4279SBram Moolenaar     {(int)KS_CD,	"\033[J"},
1023071d4279SBram Moolenaar     {(int)KS_AL,	"\033[L"},
1024071d4279SBram Moolenaar #  ifdef TERMINFO
1025071d4279SBram Moolenaar     {(int)KS_CAL,	"\033[%p1%dL"},
1026071d4279SBram Moolenaar #  else
1027071d4279SBram Moolenaar     {(int)KS_CAL,	"\033[%dL"},
1028071d4279SBram Moolenaar #  endif
1029071d4279SBram Moolenaar     {(int)KS_DL,	"\033[M"},
1030071d4279SBram Moolenaar #  ifdef TERMINFO
1031071d4279SBram Moolenaar     {(int)KS_CDL,	"\033[%p1%dM"},
1032071d4279SBram Moolenaar #  else
1033071d4279SBram Moolenaar     {(int)KS_CDL,	"\033[%dM"},
1034071d4279SBram Moolenaar #  endif
10350d6f5d97SBram Moolenaar #if 0	// The scroll region is not working as Vim expects.
1036071d4279SBram Moolenaar #  ifdef TERMINFO
1037071d4279SBram Moolenaar     {(int)KS_CS,	"\033[%i%p1%d;%p2%dr"},
1038071d4279SBram Moolenaar #  else
1039071d4279SBram Moolenaar     {(int)KS_CS,	"\033[%i%d;%dr"},
1040071d4279SBram Moolenaar #  endif
1041071d4279SBram Moolenaar #endif
1042071d4279SBram Moolenaar     {(int)KS_CL,	"\033[H\033[2J"},
10430d6f5d97SBram Moolenaar     {(int)KS_VE,	"\033[9/y\033[12/y"},	// These aren't documented
10440d6f5d97SBram Moolenaar     {(int)KS_VS,	"\033[10/y\033[=1h\033[=2l"}, // These aren't documented
1045071d4279SBram Moolenaar     {(int)KS_TI,	"\033[=6h"},
1046071d4279SBram Moolenaar     {(int)KS_TE,	"\033[=6l"},
1047071d4279SBram Moolenaar     {(int)KS_SE,	"\033[21;27m"},
1048071d4279SBram Moolenaar     {(int)KS_SO,	"\033[1;7m"},
1049071d4279SBram Moolenaar     {(int)KS_ME,	"\033[m"},
1050071d4279SBram Moolenaar     {(int)KS_MR,	"\033[7m"},
1051071d4279SBram Moolenaar     {(int)KS_MD,	"\033[1m"},
10520d6f5d97SBram Moolenaar     {(int)KS_CCO,	"8"},			// allow 8 colors
10530d6f5d97SBram Moolenaar     {(int)KS_CZH,	"\033[3m"},		// italic mode on
10540d6f5d97SBram Moolenaar     {(int)KS_CZR,	"\033[23m"},		// italic mode off
10550d6f5d97SBram Moolenaar     {(int)KS_US,	"\033[4m"},		// underline on
10560d6f5d97SBram Moolenaar     {(int)KS_UE,	"\033[24m"},		// underline off
1057071d4279SBram Moolenaar #  ifdef TERMINFO
10580d6f5d97SBram Moolenaar     {(int)KS_CAB,	"\033[4%p1%dm"},    // set background color (ANSI)
10590d6f5d97SBram Moolenaar     {(int)KS_CAF,	"\033[3%p1%dm"},    // set foreground color (ANSI)
10600d6f5d97SBram Moolenaar     {(int)KS_CSB,	"\033[102;%p1%dm"}, // set screen background color
10610d6f5d97SBram Moolenaar     {(int)KS_CSF,	"\033[101;%p1%dm"}, // set screen foreground color
1062071d4279SBram Moolenaar #  else
10630d6f5d97SBram Moolenaar     {(int)KS_CAB,	"\033[4%dm"},	    // set background color (ANSI)
10640d6f5d97SBram Moolenaar     {(int)KS_CAF,	"\033[3%dm"},	    // set foreground color (ANSI)
10650d6f5d97SBram Moolenaar     {(int)KS_CSB,	"\033[102;%dm"},    // set screen background color
10660d6f5d97SBram Moolenaar     {(int)KS_CSF,	"\033[101;%dm"},    // set screen foreground color
1067071d4279SBram Moolenaar #  endif
10680d6f5d97SBram Moolenaar     {(int)KS_MS,	"y"},		// guessed
10690d6f5d97SBram Moolenaar     {(int)KS_UT,	"y"},		// guessed
1070071d4279SBram Moolenaar     {(int)KS_LE,	"\b"},
1071071d4279SBram Moolenaar #  ifdef TERMINFO
1072071d4279SBram Moolenaar     {(int)KS_CM,	"\033[%i%p1%d;%p2%dH"},
1073071d4279SBram Moolenaar #  else
1074071d4279SBram Moolenaar     {(int)KS_CM,	"\033[%i%d;%dH"},
1075071d4279SBram Moolenaar #  endif
1076071d4279SBram Moolenaar     {(int)KS_SR,	"\033M"},
1077071d4279SBram Moolenaar #  ifdef TERMINFO
1078071d4279SBram Moolenaar     {(int)KS_CRI,	"\033[%p1%dC"},
1079071d4279SBram Moolenaar #  else
1080071d4279SBram Moolenaar     {(int)KS_CRI,	"\033[%dC"},
1081071d4279SBram Moolenaar #  endif
1082071d4279SBram Moolenaar     {(int)KS_CIS,	"\033P3.y"},
10830d6f5d97SBram Moolenaar     {(int)KS_CIE,	"\234"},    // ST "String Terminator"
1084071d4279SBram Moolenaar     {(int)KS_TS,	"\033P1.y"},
10850d6f5d97SBram Moolenaar     {(int)KS_FS,	"\234"},    // ST "String Terminator"
1086071d4279SBram Moolenaar #  ifdef TERMINFO
1087071d4279SBram Moolenaar     {(int)KS_CWS,	"\033[203;%p1%d;%p2%d/y"},
1088071d4279SBram Moolenaar     {(int)KS_CWP,	"\033[205;%p1%d;%p2%d/y"},
1089071d4279SBram Moolenaar #  else
1090071d4279SBram Moolenaar     {(int)KS_CWS,	"\033[203;%d;%d/y"},
1091071d4279SBram Moolenaar     {(int)KS_CWP,	"\033[205;%d;%d/y"},
1092071d4279SBram Moolenaar #  endif
1093071d4279SBram Moolenaar     {K_UP,		"\033[A"},
1094071d4279SBram Moolenaar     {K_DOWN,		"\033[B"},
1095071d4279SBram Moolenaar     {K_LEFT,		"\033[D"},
1096071d4279SBram Moolenaar     {K_RIGHT,		"\033[C"},
1097071d4279SBram Moolenaar     {K_S_UP,		"\033[161q"},
1098071d4279SBram Moolenaar     {K_S_DOWN,		"\033[164q"},
1099071d4279SBram Moolenaar     {K_S_LEFT,		"\033[158q"},
1100071d4279SBram Moolenaar     {K_S_RIGHT,		"\033[167q"},
1101071d4279SBram Moolenaar     {K_F1,		"\033[001q"},
1102071d4279SBram Moolenaar     {K_F2,		"\033[002q"},
1103071d4279SBram Moolenaar     {K_F3,		"\033[003q"},
1104071d4279SBram Moolenaar     {K_F4,		"\033[004q"},
1105071d4279SBram Moolenaar     {K_F5,		"\033[005q"},
1106071d4279SBram Moolenaar     {K_F6,		"\033[006q"},
1107071d4279SBram Moolenaar     {K_F7,		"\033[007q"},
1108071d4279SBram Moolenaar     {K_F8,		"\033[008q"},
1109071d4279SBram Moolenaar     {K_F9,		"\033[009q"},
1110071d4279SBram Moolenaar     {K_F10,		"\033[010q"},
1111071d4279SBram Moolenaar     {K_F11,		"\033[011q"},
1112071d4279SBram Moolenaar     {K_F12,		"\033[012q"},
1113071d4279SBram Moolenaar     {K_S_F1,		"\033[013q"},
1114071d4279SBram Moolenaar     {K_S_F2,		"\033[014q"},
1115071d4279SBram Moolenaar     {K_S_F3,		"\033[015q"},
1116071d4279SBram Moolenaar     {K_S_F4,		"\033[016q"},
1117071d4279SBram Moolenaar     {K_S_F5,		"\033[017q"},
1118071d4279SBram Moolenaar     {K_S_F6,		"\033[018q"},
1119071d4279SBram Moolenaar     {K_S_F7,		"\033[019q"},
1120071d4279SBram Moolenaar     {K_S_F8,		"\033[020q"},
1121071d4279SBram Moolenaar     {K_S_F9,		"\033[021q"},
1122071d4279SBram Moolenaar     {K_S_F10,		"\033[022q"},
1123071d4279SBram Moolenaar     {K_S_F11,		"\033[023q"},
1124071d4279SBram Moolenaar     {K_S_F12,		"\033[024q"},
1125071d4279SBram Moolenaar     {K_INS,		"\033[139q"},
1126071d4279SBram Moolenaar     {K_HOME,		"\033[H"},
1127071d4279SBram Moolenaar     {K_END,		"\033[146q"},
1128071d4279SBram Moolenaar     {K_PAGEUP,		"\033[150q"},
1129071d4279SBram Moolenaar     {K_PAGEDOWN,	"\033[154q"},
1130071d4279SBram Moolenaar # endif
1131071d4279SBram Moolenaar 
1132071d4279SBram Moolenaar # if defined(DEBUG) || defined(ALL_BUILTIN_TCAPS)
1133071d4279SBram Moolenaar /*
1134071d4279SBram Moolenaar  * for debugging
1135071d4279SBram Moolenaar  */
1136071d4279SBram Moolenaar     {(int)KS_NAME,	"debug"},
1137071d4279SBram Moolenaar     {(int)KS_CE,	"[CE]"},
1138071d4279SBram Moolenaar     {(int)KS_CD,	"[CD]"},
1139071d4279SBram Moolenaar     {(int)KS_AL,	"[AL]"},
1140071d4279SBram Moolenaar #  ifdef TERMINFO
1141071d4279SBram Moolenaar     {(int)KS_CAL,	"[CAL%p1%d]"},
1142071d4279SBram Moolenaar #  else
1143071d4279SBram Moolenaar     {(int)KS_CAL,	"[CAL%d]"},
1144071d4279SBram Moolenaar #  endif
1145071d4279SBram Moolenaar     {(int)KS_DL,	"[DL]"},
1146071d4279SBram Moolenaar #  ifdef TERMINFO
1147071d4279SBram Moolenaar     {(int)KS_CDL,	"[CDL%p1%d]"},
1148071d4279SBram Moolenaar #  else
1149071d4279SBram Moolenaar     {(int)KS_CDL,	"[CDL%d]"},
1150071d4279SBram Moolenaar #  endif
1151071d4279SBram Moolenaar #  ifdef TERMINFO
1152071d4279SBram Moolenaar     {(int)KS_CS,	"[%p1%dCS%p2%d]"},
1153071d4279SBram Moolenaar #  else
1154071d4279SBram Moolenaar     {(int)KS_CS,	"[%dCS%d]"},
1155071d4279SBram Moolenaar #  endif
1156071d4279SBram Moolenaar #  ifdef TERMINFO
1157071d4279SBram Moolenaar     {(int)KS_CSV,	"[%p1%dCSV%p2%d]"},
1158071d4279SBram Moolenaar #  else
1159071d4279SBram Moolenaar     {(int)KS_CSV,	"[%dCSV%d]"},
1160071d4279SBram Moolenaar #  endif
1161071d4279SBram Moolenaar #  ifdef TERMINFO
1162071d4279SBram Moolenaar     {(int)KS_CAB,	"[CAB%p1%d]"},
1163071d4279SBram Moolenaar     {(int)KS_CAF,	"[CAF%p1%d]"},
1164071d4279SBram Moolenaar     {(int)KS_CSB,	"[CSB%p1%d]"},
1165071d4279SBram Moolenaar     {(int)KS_CSF,	"[CSF%p1%d]"},
1166071d4279SBram Moolenaar #  else
1167071d4279SBram Moolenaar     {(int)KS_CAB,	"[CAB%d]"},
1168071d4279SBram Moolenaar     {(int)KS_CAF,	"[CAF%d]"},
1169071d4279SBram Moolenaar     {(int)KS_CSB,	"[CSB%d]"},
1170071d4279SBram Moolenaar     {(int)KS_CSF,	"[CSF%d]"},
1171071d4279SBram Moolenaar #  endif
1172e023e88bSBram Moolenaar     {(int)KS_CAU,	"[CAU%d]"},
1173071d4279SBram Moolenaar     {(int)KS_OP,	"[OP]"},
1174071d4279SBram Moolenaar     {(int)KS_LE,	"[LE]"},
1175071d4279SBram Moolenaar     {(int)KS_CL,	"[CL]"},
1176071d4279SBram Moolenaar     {(int)KS_VI,	"[VI]"},
1177071d4279SBram Moolenaar     {(int)KS_VE,	"[VE]"},
1178071d4279SBram Moolenaar     {(int)KS_VS,	"[VS]"},
1179071d4279SBram Moolenaar     {(int)KS_ME,	"[ME]"},
1180071d4279SBram Moolenaar     {(int)KS_MR,	"[MR]"},
1181071d4279SBram Moolenaar     {(int)KS_MB,	"[MB]"},
1182071d4279SBram Moolenaar     {(int)KS_MD,	"[MD]"},
1183071d4279SBram Moolenaar     {(int)KS_SE,	"[SE]"},
1184071d4279SBram Moolenaar     {(int)KS_SO,	"[SO]"},
1185071d4279SBram Moolenaar     {(int)KS_UE,	"[UE]"},
1186071d4279SBram Moolenaar     {(int)KS_US,	"[US]"},
1187e2cc9702SBram Moolenaar     {(int)KS_UCE,	"[UCE]"},
1188e2cc9702SBram Moolenaar     {(int)KS_UCS,	"[UCS]"},
1189cf4b00c8SBram Moolenaar     {(int)KS_STE,	"[STE]"},
1190cf4b00c8SBram Moolenaar     {(int)KS_STS,	"[STS]"},
1191071d4279SBram Moolenaar     {(int)KS_MS,	"[MS]"},
1192071d4279SBram Moolenaar     {(int)KS_UT,	"[UT]"},
1193494838a3SBram Moolenaar     {(int)KS_XN,	"[XN]"},
1194071d4279SBram Moolenaar #  ifdef TERMINFO
1195071d4279SBram Moolenaar     {(int)KS_CM,	"[%p1%dCM%p2%d]"},
1196071d4279SBram Moolenaar #  else
1197071d4279SBram Moolenaar     {(int)KS_CM,	"[%dCM%d]"},
1198071d4279SBram Moolenaar #  endif
1199071d4279SBram Moolenaar     {(int)KS_SR,	"[SR]"},
1200071d4279SBram Moolenaar #  ifdef TERMINFO
1201071d4279SBram Moolenaar     {(int)KS_CRI,	"[CRI%p1%d]"},
1202071d4279SBram Moolenaar #  else
1203071d4279SBram Moolenaar     {(int)KS_CRI,	"[CRI%d]"},
1204071d4279SBram Moolenaar #  endif
1205071d4279SBram Moolenaar     {(int)KS_VB,	"[VB]"},
1206071d4279SBram Moolenaar     {(int)KS_KS,	"[KS]"},
1207071d4279SBram Moolenaar     {(int)KS_KE,	"[KE]"},
1208071d4279SBram Moolenaar     {(int)KS_TI,	"[TI]"},
1209071d4279SBram Moolenaar     {(int)KS_TE,	"[TE]"},
1210071d4279SBram Moolenaar     {(int)KS_CIS,	"[CIS]"},
1211071d4279SBram Moolenaar     {(int)KS_CIE,	"[CIE]"},
12123cd43cccSBram Moolenaar     {(int)KS_CSC,	"[CSC]"},
12133cd43cccSBram Moolenaar     {(int)KS_CEC,	"[CEC]"},
1214071d4279SBram Moolenaar     {(int)KS_TS,	"[TS]"},
1215071d4279SBram Moolenaar     {(int)KS_FS,	"[FS]"},
1216071d4279SBram Moolenaar #  ifdef TERMINFO
1217071d4279SBram Moolenaar     {(int)KS_CWS,	"[%p1%dCWS%p2%d]"},
1218071d4279SBram Moolenaar     {(int)KS_CWP,	"[%p1%dCWP%p2%d]"},
1219071d4279SBram Moolenaar #  else
1220071d4279SBram Moolenaar     {(int)KS_CWS,	"[%dCWS%d]"},
1221071d4279SBram Moolenaar     {(int)KS_CWP,	"[%dCWP%d]"},
1222071d4279SBram Moolenaar #  endif
1223071d4279SBram Moolenaar     {(int)KS_CRV,	"[CRV]"},
12249584b31aSBram Moolenaar     {(int)KS_U7,	"[U7]"},
122565e4c4f6SBram Moolenaar     {(int)KS_RFG,	"[RFG]"},
1226b5c32655SBram Moolenaar     {(int)KS_RBG,	"[RBG]"},
1227071d4279SBram Moolenaar     {K_UP,		"[KU]"},
1228071d4279SBram Moolenaar     {K_DOWN,		"[KD]"},
1229071d4279SBram Moolenaar     {K_LEFT,		"[KL]"},
1230071d4279SBram Moolenaar     {K_RIGHT,		"[KR]"},
1231bc7aa85dSBram Moolenaar     {K_XUP,		"[xKU]"},
1232bc7aa85dSBram Moolenaar     {K_XDOWN,		"[xKD]"},
1233bc7aa85dSBram Moolenaar     {K_XLEFT,		"[xKL]"},
1234bc7aa85dSBram Moolenaar     {K_XRIGHT,		"[xKR]"},
1235071d4279SBram Moolenaar     {K_S_UP,		"[S-KU]"},
1236071d4279SBram Moolenaar     {K_S_DOWN,		"[S-KD]"},
1237071d4279SBram Moolenaar     {K_S_LEFT,		"[S-KL]"},
1238071d4279SBram Moolenaar     {K_C_LEFT,		"[C-KL]"},
1239071d4279SBram Moolenaar     {K_S_RIGHT,		"[S-KR]"},
1240071d4279SBram Moolenaar     {K_C_RIGHT,		"[C-KR]"},
1241071d4279SBram Moolenaar     {K_F1,		"[F1]"},
1242071d4279SBram Moolenaar     {K_XF1,		"[xF1]"},
1243071d4279SBram Moolenaar     {K_F2,		"[F2]"},
1244071d4279SBram Moolenaar     {K_XF2,		"[xF2]"},
1245071d4279SBram Moolenaar     {K_F3,		"[F3]"},
1246071d4279SBram Moolenaar     {K_XF3,		"[xF3]"},
1247071d4279SBram Moolenaar     {K_F4,		"[F4]"},
1248071d4279SBram Moolenaar     {K_XF4,		"[xF4]"},
1249071d4279SBram Moolenaar     {K_F5,		"[F5]"},
1250071d4279SBram Moolenaar     {K_F6,		"[F6]"},
1251071d4279SBram Moolenaar     {K_F7,		"[F7]"},
1252071d4279SBram Moolenaar     {K_F8,		"[F8]"},
1253071d4279SBram Moolenaar     {K_F9,		"[F9]"},
1254071d4279SBram Moolenaar     {K_F10,		"[F10]"},
1255071d4279SBram Moolenaar     {K_F11,		"[F11]"},
1256071d4279SBram Moolenaar     {K_F12,		"[F12]"},
1257071d4279SBram Moolenaar     {K_S_F1,		"[S-F1]"},
1258071d4279SBram Moolenaar     {K_S_XF1,		"[S-xF1]"},
1259071d4279SBram Moolenaar     {K_S_F2,		"[S-F2]"},
1260071d4279SBram Moolenaar     {K_S_XF2,		"[S-xF2]"},
1261071d4279SBram Moolenaar     {K_S_F3,		"[S-F3]"},
1262071d4279SBram Moolenaar     {K_S_XF3,		"[S-xF3]"},
1263071d4279SBram Moolenaar     {K_S_F4,		"[S-F4]"},
1264071d4279SBram Moolenaar     {K_S_XF4,		"[S-xF4]"},
1265071d4279SBram Moolenaar     {K_S_F5,		"[S-F5]"},
1266071d4279SBram Moolenaar     {K_S_F6,		"[S-F6]"},
1267071d4279SBram Moolenaar     {K_S_F7,		"[S-F7]"},
1268071d4279SBram Moolenaar     {K_S_F8,		"[S-F8]"},
1269071d4279SBram Moolenaar     {K_S_F9,		"[S-F9]"},
1270071d4279SBram Moolenaar     {K_S_F10,		"[S-F10]"},
1271071d4279SBram Moolenaar     {K_S_F11,		"[S-F11]"},
1272071d4279SBram Moolenaar     {K_S_F12,		"[S-F12]"},
1273071d4279SBram Moolenaar     {K_HELP,		"[HELP]"},
1274071d4279SBram Moolenaar     {K_UNDO,		"[UNDO]"},
1275071d4279SBram Moolenaar     {K_BS,		"[BS]"},
1276071d4279SBram Moolenaar     {K_INS,		"[INS]"},
1277071d4279SBram Moolenaar     {K_KINS,		"[KINS]"},
1278071d4279SBram Moolenaar     {K_DEL,		"[DEL]"},
1279071d4279SBram Moolenaar     {K_KDEL,		"[KDEL]"},
1280071d4279SBram Moolenaar     {K_HOME,		"[HOME]"},
1281071d4279SBram Moolenaar     {K_S_HOME,		"[C-HOME]"},
1282071d4279SBram Moolenaar     {K_C_HOME,		"[C-HOME]"},
1283071d4279SBram Moolenaar     {K_KHOME,		"[KHOME]"},
1284071d4279SBram Moolenaar     {K_XHOME,		"[XHOME]"},
128568b76a69SBram Moolenaar     {K_ZHOME,		"[ZHOME]"},
1286071d4279SBram Moolenaar     {K_END,		"[END]"},
1287071d4279SBram Moolenaar     {K_S_END,		"[C-END]"},
1288071d4279SBram Moolenaar     {K_C_END,		"[C-END]"},
1289071d4279SBram Moolenaar     {K_KEND,		"[KEND]"},
1290071d4279SBram Moolenaar     {K_XEND,		"[XEND]"},
129168b76a69SBram Moolenaar     {K_ZEND,		"[ZEND]"},
1292071d4279SBram Moolenaar     {K_PAGEUP,		"[PAGEUP]"},
1293071d4279SBram Moolenaar     {K_PAGEDOWN,	"[PAGEDOWN]"},
1294071d4279SBram Moolenaar     {K_KPAGEUP,		"[KPAGEUP]"},
1295071d4279SBram Moolenaar     {K_KPAGEDOWN,	"[KPAGEDOWN]"},
1296071d4279SBram Moolenaar     {K_MOUSE,		"[MOUSE]"},
1297071d4279SBram Moolenaar     {K_KPLUS,		"[KPLUS]"},
1298071d4279SBram Moolenaar     {K_KMINUS,		"[KMINUS]"},
1299071d4279SBram Moolenaar     {K_KDIVIDE,		"[KDIVIDE]"},
1300071d4279SBram Moolenaar     {K_KMULTIPLY,	"[KMULTIPLY]"},
1301071d4279SBram Moolenaar     {K_KENTER,		"[KENTER]"},
1302071d4279SBram Moolenaar     {K_KPOINT,		"[KPOINT]"},
1303ec2da36cSBram Moolenaar     {K_PS,		"[PASTE-START]"},
1304ec2da36cSBram Moolenaar     {K_PE,		"[PASTE-END]"},
1305071d4279SBram Moolenaar     {K_K0,		"[K0]"},
1306071d4279SBram Moolenaar     {K_K1,		"[K1]"},
1307071d4279SBram Moolenaar     {K_K2,		"[K2]"},
1308071d4279SBram Moolenaar     {K_K3,		"[K3]"},
1309071d4279SBram Moolenaar     {K_K4,		"[K4]"},
1310071d4279SBram Moolenaar     {K_K5,		"[K5]"},
1311071d4279SBram Moolenaar     {K_K6,		"[K6]"},
1312071d4279SBram Moolenaar     {K_K7,		"[K7]"},
1313071d4279SBram Moolenaar     {K_K8,		"[K8]"},
1314071d4279SBram Moolenaar     {K_K9,		"[K9]"},
1315071d4279SBram Moolenaar # endif
1316071d4279SBram Moolenaar 
13170d6f5d97SBram Moolenaar #endif // NO_BUILTIN_TCAPS
1318071d4279SBram Moolenaar 
1319071d4279SBram Moolenaar /*
1320071d4279SBram Moolenaar  * The most minimal terminal: only clear screen and cursor positioning
1321071d4279SBram Moolenaar  * Always included.
1322071d4279SBram Moolenaar  */
1323071d4279SBram Moolenaar     {(int)KS_NAME,	"dumb"},
1324071d4279SBram Moolenaar     {(int)KS_CL,	"\014"},
1325071d4279SBram Moolenaar #ifdef TERMINFO
1326071d4279SBram Moolenaar     {(int)KS_CM,	IF_EB("\033[%i%p1%d;%p2%dH",
1327071d4279SBram Moolenaar 						  ESC_STR "[%i%p1%d;%p2%dH")},
1328071d4279SBram Moolenaar #else
1329071d4279SBram Moolenaar     {(int)KS_CM,	IF_EB("\033[%i%d;%dH", ESC_STR "[%i%d;%dH")},
1330071d4279SBram Moolenaar #endif
1331071d4279SBram Moolenaar 
1332071d4279SBram Moolenaar /*
1333071d4279SBram Moolenaar  * end marker
1334071d4279SBram Moolenaar  */
1335071d4279SBram Moolenaar     {(int)KS_NAME,	NULL}
1336071d4279SBram Moolenaar 
13370d6f5d97SBram Moolenaar };	// end of builtin_termcaps
1338071d4279SBram Moolenaar 
133961be73bbSBram Moolenaar #if defined(FEAT_TERMGUICOLORS) || defined(PROTO)
13405843f5f3SBram Moolenaar     static guicolor_T
termgui_mch_get_color(char_u * name)134161be73bbSBram Moolenaar termgui_mch_get_color(char_u *name)
13428a633e34SBram Moolenaar {
1343ab302219SBram Moolenaar     return gui_get_color_cmn(name);
13448a633e34SBram Moolenaar }
13458a633e34SBram Moolenaar 
13468a633e34SBram Moolenaar     guicolor_T
termgui_get_color(char_u * name)134761be73bbSBram Moolenaar termgui_get_color(char_u *name)
13488a633e34SBram Moolenaar {
13498a633e34SBram Moolenaar     guicolor_T	t;
13508a633e34SBram Moolenaar 
13518a633e34SBram Moolenaar     if (*name == NUL)
13528a633e34SBram Moolenaar 	return INVALCOLOR;
135361be73bbSBram Moolenaar     t = termgui_mch_get_color(name);
13548a633e34SBram Moolenaar 
13558a633e34SBram Moolenaar     if (t == INVALCOLOR)
1356e30d1025SDrew Vogel 	semsg(_(e_cannot_allocate_color_str), name);
13578a633e34SBram Moolenaar     return t;
13588a633e34SBram Moolenaar }
13598a633e34SBram Moolenaar 
13601b58cdd1SBram Moolenaar     guicolor_T
termgui_mch_get_rgb(guicolor_T color)136161be73bbSBram Moolenaar termgui_mch_get_rgb(guicolor_T color)
13628a633e34SBram Moolenaar {
13631b58cdd1SBram Moolenaar     return color;
13648a633e34SBram Moolenaar }
13658a633e34SBram Moolenaar #endif
13668a633e34SBram Moolenaar 
1367071d4279SBram Moolenaar /*
1368071d4279SBram Moolenaar  * DEFAULT_TERM is used, when no terminal is specified with -T option or $TERM.
1369071d4279SBram Moolenaar  */
1370071d4279SBram Moolenaar #ifdef AMIGA
1371071d4279SBram Moolenaar # define DEFAULT_TERM	(char_u *)"amiga"
1372071d4279SBram Moolenaar #endif
1373071d4279SBram Moolenaar 
1374071d4279SBram Moolenaar #ifdef MSWIN
1375071d4279SBram Moolenaar # define DEFAULT_TERM	(char_u *)"win32"
1376071d4279SBram Moolenaar #endif
1377071d4279SBram Moolenaar 
1378e3f915d1SBram Moolenaar #if defined(UNIX)
1379071d4279SBram Moolenaar # define DEFAULT_TERM	(char_u *)"ansi"
1380071d4279SBram Moolenaar #endif
1381071d4279SBram Moolenaar 
1382071d4279SBram Moolenaar #ifdef VMS
1383071d4279SBram Moolenaar # define DEFAULT_TERM	(char_u *)"vt320"
1384071d4279SBram Moolenaar #endif
1385071d4279SBram Moolenaar 
1386b3f74069SBram Moolenaar #ifdef __HAIKU__
1387b3f74069SBram Moolenaar # undef DEFAULT_TERM
1388b3f74069SBram Moolenaar # define DEFAULT_TERM	(char_u *)"xterm"
1389b3f74069SBram Moolenaar #endif
1390b3f74069SBram Moolenaar 
1391071d4279SBram Moolenaar #ifndef DEFAULT_TERM
1392071d4279SBram Moolenaar # define DEFAULT_TERM	(char_u *)"dumb"
1393071d4279SBram Moolenaar #endif
1394071d4279SBram Moolenaar 
1395071d4279SBram Moolenaar /*
1396071d4279SBram Moolenaar  * Term_strings contains currently used terminal output strings.
1397071d4279SBram Moolenaar  * It is initialized with the default values by parse_builtin_tcap().
1398071d4279SBram Moolenaar  * The values can be changed by setting the option with the same name.
1399071d4279SBram Moolenaar  */
1400071d4279SBram Moolenaar char_u *(term_strings[(int)KS_LAST + 1]);
1401071d4279SBram Moolenaar 
14020d6f5d97SBram Moolenaar static int	need_gather = FALSE;	    // need to fill termleader[]
14030d6f5d97SBram Moolenaar static char_u	termleader[256 + 1];	    // for check_termcode()
1404071d4279SBram Moolenaar #ifdef FEAT_TERMRESPONSE
14050d6f5d97SBram Moolenaar static int	check_for_codes = FALSE;    // check for key code response
1406517f00f7SBram Moolenaar 
1407517f00f7SBram Moolenaar /*
1408517f00f7SBram Moolenaar  * Structure and table to store terminal features that can be detected by
1409517f00f7SBram Moolenaar  * querying the terminal.  Either by inspecting the termresponse or a more
1410517f00f7SBram Moolenaar  * specific request.  Besides this there are:
1411517f00f7SBram Moolenaar  * t_colors - number of colors supported
1412517f00f7SBram Moolenaar  */
1413517f00f7SBram Moolenaar typedef struct {
1414517f00f7SBram Moolenaar     char    *tpr_name;
1415517f00f7SBram Moolenaar     int	    tpr_set_by_termresponse;
1416517f00f7SBram Moolenaar     int	    tpr_status;
1417517f00f7SBram Moolenaar } termprop_T;
1418517f00f7SBram Moolenaar 
1419517f00f7SBram Moolenaar // Values for tpr_status.
1420517f00f7SBram Moolenaar #define TPR_UNKNOWN	    'u'
1421517f00f7SBram Moolenaar #define TPR_YES		    'y'
1422517f00f7SBram Moolenaar #define TPR_NO		    'n'
1423517f00f7SBram Moolenaar #define TPR_MOUSE_XTERM     'x'	// use "xterm" for 'ttymouse'
1424517f00f7SBram Moolenaar #define TPR_MOUSE_XTERM2    '2'	// use "xterm2" for 'ttymouse'
1425517f00f7SBram Moolenaar #define TPR_MOUSE_SGR	    's'	// use "sgr" for 'ttymouse'
1426517f00f7SBram Moolenaar 
1427517f00f7SBram Moolenaar // can request the cursor style without messing up the display
1428517f00f7SBram Moolenaar #define TPR_CURSOR_STYLE	    0
1429517f00f7SBram Moolenaar // can request the cursor blink mode without messing up the display
1430517f00f7SBram Moolenaar #define TPR_CURSOR_BLINK	    1
1431517f00f7SBram Moolenaar // can set the underline color with t_8u without resetting other colors
1432517f00f7SBram Moolenaar #define TPR_UNDERLINE_RGB	    2
1433517f00f7SBram Moolenaar // mouse support - TPR_MOUSE_XTERM, TPR_MOUSE_XTERM2 or TPR_MOUSE_SGR
1434517f00f7SBram Moolenaar #define TPR_MOUSE		    3
1435517f00f7SBram Moolenaar // table size
1436517f00f7SBram Moolenaar #define TPR_COUNT		    4
1437517f00f7SBram Moolenaar 
1438517f00f7SBram Moolenaar static termprop_T term_props[TPR_COUNT];
1439517f00f7SBram Moolenaar 
1440517f00f7SBram Moolenaar /*
1441517f00f7SBram Moolenaar  * Initialize the term_props table.
1442517f00f7SBram Moolenaar  * When "all" is FALSE only set those that are detected from the version
1443517f00f7SBram Moolenaar  * response.
1444517f00f7SBram Moolenaar  */
14450c0eddd3SBram Moolenaar     void
init_term_props(int all)1446517f00f7SBram Moolenaar init_term_props(int all)
1447517f00f7SBram Moolenaar {
1448517f00f7SBram Moolenaar     int i;
1449517f00f7SBram Moolenaar 
1450517f00f7SBram Moolenaar     term_props[TPR_CURSOR_STYLE].tpr_name = "cursor_style";
1451517f00f7SBram Moolenaar     term_props[TPR_CURSOR_STYLE].tpr_set_by_termresponse = FALSE;
1452517f00f7SBram Moolenaar     term_props[TPR_CURSOR_BLINK].tpr_name = "cursor_blink_mode";
1453517f00f7SBram Moolenaar     term_props[TPR_CURSOR_BLINK].tpr_set_by_termresponse = FALSE;
1454517f00f7SBram Moolenaar     term_props[TPR_UNDERLINE_RGB].tpr_name = "underline_rgb";
1455517f00f7SBram Moolenaar     term_props[TPR_UNDERLINE_RGB].tpr_set_by_termresponse = TRUE;
1456517f00f7SBram Moolenaar     term_props[TPR_MOUSE].tpr_name = "mouse";
1457517f00f7SBram Moolenaar     term_props[TPR_MOUSE].tpr_set_by_termresponse = TRUE;
1458517f00f7SBram Moolenaar 
1459517f00f7SBram Moolenaar     for (i = 0; i < TPR_COUNT; ++i)
1460517f00f7SBram Moolenaar 	if (all || term_props[i].tpr_set_by_termresponse)
1461517f00f7SBram Moolenaar 	    term_props[i].tpr_status = TPR_UNKNOWN;
1462517f00f7SBram Moolenaar }
1463071d4279SBram Moolenaar #endif
1464071d4279SBram Moolenaar 
14650c0eddd3SBram Moolenaar #if defined(FEAT_EVAL) || defined(PROTO)
14660c0eddd3SBram Moolenaar     void
f_terminalprops(typval_T * argvars UNUSED,typval_T * rettv)14670c0eddd3SBram Moolenaar f_terminalprops(typval_T *argvars UNUSED, typval_T *rettv)
14680c0eddd3SBram Moolenaar {
14690c0eddd3SBram Moolenaar # ifdef FEAT_TERMRESPONSE
14700c0eddd3SBram Moolenaar     int i;
14710c0eddd3SBram Moolenaar # endif
14720c0eddd3SBram Moolenaar 
14730c0eddd3SBram Moolenaar     if (rettv_dict_alloc(rettv) != OK)
14740c0eddd3SBram Moolenaar 	return;
14750c0eddd3SBram Moolenaar # ifdef FEAT_TERMRESPONSE
14760c0eddd3SBram Moolenaar     for (i = 0; i < TPR_COUNT; ++i)
14770c0eddd3SBram Moolenaar     {
14780c0eddd3SBram Moolenaar 	char_u	value[2];
14790c0eddd3SBram Moolenaar 
14800c0eddd3SBram Moolenaar 	value[0] = term_props[i].tpr_status;
14810c0eddd3SBram Moolenaar 	value[1] = NUL;
14820c0eddd3SBram Moolenaar 	dict_add_string(rettv->vval.v_dict, term_props[i].tpr_name, value);
14830c0eddd3SBram Moolenaar     }
14840c0eddd3SBram Moolenaar # endif
14850c0eddd3SBram Moolenaar }
14860c0eddd3SBram Moolenaar #endif
14870c0eddd3SBram Moolenaar 
1488071d4279SBram Moolenaar     static struct builtin_term *
find_builtin_term(char_u * term)1489764b23c8SBram Moolenaar find_builtin_term(char_u *term)
1490071d4279SBram Moolenaar {
1491071d4279SBram Moolenaar     struct builtin_term *p;
1492071d4279SBram Moolenaar 
1493071d4279SBram Moolenaar     p = builtin_termcaps;
1494071d4279SBram Moolenaar     while (p->bt_string != NULL)
1495071d4279SBram Moolenaar     {
1496071d4279SBram Moolenaar 	if (p->bt_entry == (int)KS_NAME)
1497071d4279SBram Moolenaar 	{
1498071d4279SBram Moolenaar #ifdef UNIX
1499071d4279SBram Moolenaar 	    if (STRCMP(p->bt_string, "iris-ansi") == 0 && vim_is_iris(term))
1500071d4279SBram Moolenaar 		return p;
1501071d4279SBram Moolenaar 	    else if (STRCMP(p->bt_string, "xterm") == 0 && vim_is_xterm(term))
1502071d4279SBram Moolenaar 		return p;
1503071d4279SBram Moolenaar 	    else
1504071d4279SBram Moolenaar #endif
1505071d4279SBram Moolenaar #ifdef VMS
1506071d4279SBram Moolenaar 		if (STRCMP(p->bt_string, "vt320") == 0 && vim_is_vt300(term))
1507071d4279SBram Moolenaar 		    return p;
1508071d4279SBram Moolenaar 		else
1509071d4279SBram Moolenaar #endif
1510071d4279SBram Moolenaar 		  if (STRCMP(term, p->bt_string) == 0)
1511071d4279SBram Moolenaar 		    return p;
1512071d4279SBram Moolenaar 	}
1513071d4279SBram Moolenaar 	++p;
1514071d4279SBram Moolenaar     }
1515071d4279SBram Moolenaar     return p;
1516071d4279SBram Moolenaar }
1517071d4279SBram Moolenaar 
1518071d4279SBram Moolenaar /*
1519071d4279SBram Moolenaar  * Parsing of the builtin termcap entries.
1520071d4279SBram Moolenaar  * Caller should check if 'name' is a valid builtin term.
1521071d4279SBram Moolenaar  * The terminal's name is not set, as this is already done in termcapinit().
1522071d4279SBram Moolenaar  */
1523071d4279SBram Moolenaar     static void
parse_builtin_tcap(char_u * term)1524764b23c8SBram Moolenaar parse_builtin_tcap(char_u *term)
1525071d4279SBram Moolenaar {
1526071d4279SBram Moolenaar     struct builtin_term	    *p;
1527071d4279SBram Moolenaar     char_u		    name[2];
1528071d4279SBram Moolenaar     int			    term_8bit;
1529071d4279SBram Moolenaar 
1530071d4279SBram Moolenaar     p = find_builtin_term(term);
1531071d4279SBram Moolenaar     term_8bit = term_is_8bit(term);
1532071d4279SBram Moolenaar 
15330d6f5d97SBram Moolenaar     // Do not parse if builtin term not found
1534071d4279SBram Moolenaar     if (p->bt_string == NULL)
1535071d4279SBram Moolenaar 	return;
1536071d4279SBram Moolenaar 
1537071d4279SBram Moolenaar     for (++p; p->bt_entry != (int)KS_NAME && p->bt_entry != BT_EXTRA_KEYS; ++p)
1538071d4279SBram Moolenaar     {
15390d6f5d97SBram Moolenaar 	if ((int)p->bt_entry >= 0)	// KS_xx entry
1540071d4279SBram Moolenaar 	{
15410d6f5d97SBram Moolenaar 	    // Only set the value if it wasn't set yet.
1542071d4279SBram Moolenaar 	    if (term_strings[p->bt_entry] == NULL
1543071d4279SBram Moolenaar 				 || term_strings[p->bt_entry] == empty_option)
1544071d4279SBram Moolenaar 	    {
154535bc7d6cSBram Moolenaar #ifdef FEAT_EVAL
154635bc7d6cSBram Moolenaar 		int opt_idx = -1;
154735bc7d6cSBram Moolenaar #endif
15480d6f5d97SBram Moolenaar 		// 8bit terminal: use CSI instead of <Esc>[
1549071d4279SBram Moolenaar 		if (term_8bit && term_7to8bit((char_u *)p->bt_string) != 0)
1550071d4279SBram Moolenaar 		{
1551071d4279SBram Moolenaar 		    char_u  *s, *t;
1552071d4279SBram Moolenaar 
1553071d4279SBram Moolenaar 		    s = vim_strsave((char_u *)p->bt_string);
1554071d4279SBram Moolenaar 		    if (s != NULL)
1555071d4279SBram Moolenaar 		    {
1556071d4279SBram Moolenaar 			for (t = s; *t; ++t)
1557071d4279SBram Moolenaar 			    if (term_7to8bit(t))
1558071d4279SBram Moolenaar 			    {
1559071d4279SBram Moolenaar 				*t = term_7to8bit(t);
156018085faeSBram Moolenaar 				STRMOVE(t + 1, t + 2);
1561071d4279SBram Moolenaar 			    }
1562071d4279SBram Moolenaar 			term_strings[p->bt_entry] = s;
156335bc7d6cSBram Moolenaar #ifdef FEAT_EVAL
156435bc7d6cSBram Moolenaar 			opt_idx =
156535bc7d6cSBram Moolenaar #endif
156635bc7d6cSBram Moolenaar 				  set_term_option_alloced(
156735bc7d6cSBram Moolenaar 						   &term_strings[p->bt_entry]);
1568071d4279SBram Moolenaar 		    }
1569071d4279SBram Moolenaar 		}
1570071d4279SBram Moolenaar 		else
157135bc7d6cSBram Moolenaar 		{
1572071d4279SBram Moolenaar 		    term_strings[p->bt_entry] = (char_u *)p->bt_string;
157335bc7d6cSBram Moolenaar #ifdef FEAT_EVAL
157435bc7d6cSBram Moolenaar 		    opt_idx = get_term_opt_idx(&term_strings[p->bt_entry]);
157535bc7d6cSBram Moolenaar #endif
157635bc7d6cSBram Moolenaar 		}
157735bc7d6cSBram Moolenaar #ifdef FEAT_EVAL
157835bc7d6cSBram Moolenaar 		set_term_option_sctx_idx(NULL, opt_idx);
157935bc7d6cSBram Moolenaar #endif
1580071d4279SBram Moolenaar 	    }
1581071d4279SBram Moolenaar 	}
1582071d4279SBram Moolenaar 	else
1583071d4279SBram Moolenaar 	{
1584071d4279SBram Moolenaar 	    name[0] = KEY2TERMCAP0((int)p->bt_entry);
1585071d4279SBram Moolenaar 	    name[1] = KEY2TERMCAP1((int)p->bt_entry);
1586071d4279SBram Moolenaar 	    if (find_termcode(name) == NULL)
1587071d4279SBram Moolenaar 		add_termcode(name, (char_u *)p->bt_string, term_8bit);
1588071d4279SBram Moolenaar 	}
1589071d4279SBram Moolenaar     }
1590071d4279SBram Moolenaar }
1591d7d3cbedSBram Moolenaar 
1592071d4279SBram Moolenaar /*
1593071d4279SBram Moolenaar  * Set number of colors.
1594071d4279SBram Moolenaar  * Store it as a number in t_colors.
1595071d4279SBram Moolenaar  * Store it as a string in T_CCO (using nr_colors[]).
1596071d4279SBram Moolenaar  */
1597acc770a1SBram Moolenaar     void
set_color_count(int nr)1598764b23c8SBram Moolenaar set_color_count(int nr)
1599071d4279SBram Moolenaar {
16000d6f5d97SBram Moolenaar     char_u	nr_colors[20];		// string for number of colors
1601071d4279SBram Moolenaar 
1602071d4279SBram Moolenaar     t_colors = nr;
1603071d4279SBram Moolenaar     if (t_colors > 1)
1604071d4279SBram Moolenaar 	sprintf((char *)nr_colors, "%d", t_colors);
1605071d4279SBram Moolenaar     else
1606071d4279SBram Moolenaar 	*nr_colors = NUL;
16075e3cb7e8SBram Moolenaar     set_string_option_direct((char_u *)"t_Co", -1, nr_colors, OPT_FREE, 0);
1608071d4279SBram Moolenaar }
1609b7a8dfebSBram Moolenaar 
1610d7d3cbedSBram Moolenaar #if defined(FEAT_TERMRESPONSE)
1611b7a8dfebSBram Moolenaar /*
1612b7a8dfebSBram Moolenaar  * Set the color count to "val" and redraw if it changed.
1613b7a8dfebSBram Moolenaar  */
1614b7a8dfebSBram Moolenaar     static void
may_adjust_color_count(int val)1615b7a8dfebSBram Moolenaar may_adjust_color_count(int val)
1616b7a8dfebSBram Moolenaar {
1617b7a8dfebSBram Moolenaar     if (val != t_colors)
1618b7a8dfebSBram Moolenaar     {
16190d6f5d97SBram Moolenaar 	// Nr of colors changed, initialize highlighting and
16200d6f5d97SBram Moolenaar 	// redraw everything.  This causes a redraw, which usually
16210d6f5d97SBram Moolenaar 	// clears the message.  Try keeping the message if it
16220d6f5d97SBram Moolenaar 	// might work.
1623b7a8dfebSBram Moolenaar 	set_keep_msg_from_hist();
1624b7a8dfebSBram Moolenaar 	set_color_count(val);
1625b7a8dfebSBram Moolenaar 	init_highlight(TRUE, FALSE);
1626b7a8dfebSBram Moolenaar # ifdef DEBUG_TERMRESPONSE
1627b7a8dfebSBram Moolenaar 	{
1628b7a8dfebSBram Moolenaar 	    int r = redraw_asap(CLEAR);
1629b7a8dfebSBram Moolenaar 
1630b255b905SBram Moolenaar 	    log_tr("Received t_Co, redraw_asap(): %d", r);
1631b7a8dfebSBram Moolenaar 	}
1632b7a8dfebSBram Moolenaar # else
1633b7a8dfebSBram Moolenaar 	redraw_asap(CLEAR);
1634b7a8dfebSBram Moolenaar # endif
1635b7a8dfebSBram Moolenaar     }
1636b7a8dfebSBram Moolenaar }
1637071d4279SBram Moolenaar #endif
1638071d4279SBram Moolenaar 
1639071d4279SBram Moolenaar #ifdef HAVE_TGETENT
1640071d4279SBram Moolenaar static char *(key_names[]) =
1641071d4279SBram Moolenaar {
1642071d4279SBram Moolenaar # ifdef FEAT_TERMRESPONSE
16430d6f5d97SBram Moolenaar     // Do this one first, it may cause a screen redraw.
1644071d4279SBram Moolenaar     "Co",
1645071d4279SBram Moolenaar # endif
1646071d4279SBram Moolenaar     "ku", "kd", "kr", "kl",
1647071d4279SBram Moolenaar     "#2", "#4", "%i", "*7",
1648071d4279SBram Moolenaar     "k1", "k2", "k3", "k4", "k5", "k6",
1649071d4279SBram Moolenaar     "k7", "k8", "k9", "k;", "F1", "F2",
1650071d4279SBram Moolenaar     "%1", "&8", "kb", "kI", "kD", "kh",
1651071d4279SBram Moolenaar     "@7", "kP", "kN", "K1", "K3", "K4", "K5", "kB",
1652071d4279SBram Moolenaar     NULL
1653071d4279SBram Moolenaar };
1654071d4279SBram Moolenaar #endif
1655071d4279SBram Moolenaar 
16569289df5cSBram Moolenaar #ifdef HAVE_TGETENT
165769e05691SBram Moolenaar     static void
get_term_entries(int * height,int * width)165869e05691SBram Moolenaar get_term_entries(int *height, int *width)
165969e05691SBram Moolenaar {
166069e05691SBram Moolenaar     static struct {
16610d6f5d97SBram Moolenaar 		    enum SpecialKey dest; // index in term_strings[]
16620d6f5d97SBram Moolenaar 		    char *name;		  // termcap name for string
166369e05691SBram Moolenaar 		  } string_names[] =
166469e05691SBram Moolenaar 		    {	{KS_CE, "ce"}, {KS_AL, "al"}, {KS_CAL,"AL"},
166569e05691SBram Moolenaar 			{KS_DL, "dl"}, {KS_CDL,"DL"}, {KS_CS, "cs"},
166669e05691SBram Moolenaar 			{KS_CL, "cl"}, {KS_CD, "cd"},
166769e05691SBram Moolenaar 			{KS_VI, "vi"}, {KS_VE, "ve"}, {KS_MB, "mb"},
166869e05691SBram Moolenaar 			{KS_ME, "me"}, {KS_MR, "mr"},
166969e05691SBram Moolenaar 			{KS_MD, "md"}, {KS_SE, "se"}, {KS_SO, "so"},
167069e05691SBram Moolenaar 			{KS_CZH,"ZH"}, {KS_CZR,"ZR"}, {KS_UE, "ue"},
167169e05691SBram Moolenaar 			{KS_US, "us"}, {KS_UCE, "Ce"}, {KS_UCS, "Cs"},
167269e05691SBram Moolenaar 			{KS_STE,"Te"}, {KS_STS,"Ts"},
167369e05691SBram Moolenaar 			{KS_CM, "cm"}, {KS_SR, "sr"},
167469e05691SBram Moolenaar 			{KS_CRI,"RI"}, {KS_VB, "vb"}, {KS_KS, "ks"},
167569e05691SBram Moolenaar 			{KS_KE, "ke"}, {KS_TI, "ti"}, {KS_TE, "te"},
1676171a921bSBram Moolenaar 			{KS_CTI, "TI"}, {KS_CTE, "TE"},
167769e05691SBram Moolenaar 			{KS_BC, "bc"}, {KS_CSB,"Sb"}, {KS_CSF,"Sf"},
1678e023e88bSBram Moolenaar 			{KS_CAB,"AB"}, {KS_CAF,"AF"}, {KS_CAU,"AU"},
1679e023e88bSBram Moolenaar 			{KS_LE, "le"},
168069e05691SBram Moolenaar 			{KS_ND, "nd"}, {KS_OP, "op"}, {KS_CRV, "RV"},
168169e05691SBram Moolenaar 			{KS_VS, "vs"}, {KS_CVS, "VS"},
168269e05691SBram Moolenaar 			{KS_CIS, "IS"}, {KS_CIE, "IE"},
168369e05691SBram Moolenaar 			{KS_CSC, "SC"}, {KS_CEC, "EC"},
168469e05691SBram Moolenaar 			{KS_TS, "ts"}, {KS_FS, "fs"},
168569e05691SBram Moolenaar 			{KS_CWP, "WP"}, {KS_CWS, "WS"},
168669e05691SBram Moolenaar 			{KS_CSI, "SI"}, {KS_CEI, "EI"},
168769e05691SBram Moolenaar 			{KS_U7, "u7"}, {KS_RFG, "RF"}, {KS_RBG, "RB"},
1688e023e88bSBram Moolenaar 			{KS_8F, "8f"}, {KS_8B, "8b"}, {KS_8U, "8u"},
168969e05691SBram Moolenaar 			{KS_CBE, "BE"}, {KS_CBD, "BD"},
169069e05691SBram Moolenaar 			{KS_CPS, "PS"}, {KS_CPE, "PE"},
169140385dbcSBram Moolenaar 			{KS_CST, "ST"}, {KS_CRT, "RT"},
169240385dbcSBram Moolenaar 			{KS_SSI, "Si"}, {KS_SRI, "Ri"},
169369e05691SBram Moolenaar 			{(enum SpecialKey)0, NULL}
169469e05691SBram Moolenaar 		    };
169569e05691SBram Moolenaar     int		    i;
169669e05691SBram Moolenaar     char_u	    *p;
169769e05691SBram Moolenaar     static char_u   tstrbuf[TBUFSZ];
169869e05691SBram Moolenaar     char_u	    *tp = tstrbuf;
169969e05691SBram Moolenaar 
170069e05691SBram Moolenaar     /*
170169e05691SBram Moolenaar      * get output strings
170269e05691SBram Moolenaar      */
170369e05691SBram Moolenaar     for (i = 0; string_names[i].name != NULL; ++i)
170469e05691SBram Moolenaar     {
170569e05691SBram Moolenaar 	if (TERM_STR(string_names[i].dest) == NULL
170669e05691SBram Moolenaar 			     || TERM_STR(string_names[i].dest) == empty_option)
170735bc7d6cSBram Moolenaar 	{
170869e05691SBram Moolenaar 	    TERM_STR(string_names[i].dest) = TGETSTR(string_names[i].name, &tp);
170935bc7d6cSBram Moolenaar #ifdef FEAT_EVAL
171035bc7d6cSBram Moolenaar 	    set_term_option_sctx_idx(string_names[i].name, -1);
171135bc7d6cSBram Moolenaar #endif
171235bc7d6cSBram Moolenaar 	}
171369e05691SBram Moolenaar     }
171469e05691SBram Moolenaar 
17150d6f5d97SBram Moolenaar     // tgetflag() returns 1 if the flag is present, 0 if not and
17160d6f5d97SBram Moolenaar     // possibly -1 if the flag doesn't exist.
171769e05691SBram Moolenaar     if ((T_MS == NULL || T_MS == empty_option) && tgetflag("ms") > 0)
171869e05691SBram Moolenaar 	T_MS = (char_u *)"y";
171969e05691SBram Moolenaar     if ((T_XS == NULL || T_XS == empty_option) && tgetflag("xs") > 0)
172069e05691SBram Moolenaar 	T_XS = (char_u *)"y";
172169e05691SBram Moolenaar     if ((T_XN == NULL || T_XN == empty_option) && tgetflag("xn") > 0)
172269e05691SBram Moolenaar 	T_XN = (char_u *)"y";
172369e05691SBram Moolenaar     if ((T_DB == NULL || T_DB == empty_option) && tgetflag("db") > 0)
172469e05691SBram Moolenaar 	T_DB = (char_u *)"y";
172569e05691SBram Moolenaar     if ((T_DA == NULL || T_DA == empty_option) && tgetflag("da") > 0)
172669e05691SBram Moolenaar 	T_DA = (char_u *)"y";
172769e05691SBram Moolenaar     if ((T_UT == NULL || T_UT == empty_option) && tgetflag("ut") > 0)
172869e05691SBram Moolenaar 	T_UT = (char_u *)"y";
172969e05691SBram Moolenaar 
173069e05691SBram Moolenaar     /*
173169e05691SBram Moolenaar      * get key codes
173269e05691SBram Moolenaar      */
173369e05691SBram Moolenaar     for (i = 0; key_names[i] != NULL; ++i)
173469e05691SBram Moolenaar 	if (find_termcode((char_u *)key_names[i]) == NULL)
173569e05691SBram Moolenaar 	{
173669e05691SBram Moolenaar 	    p = TGETSTR(key_names[i], &tp);
17370d6f5d97SBram Moolenaar 	    // if cursor-left == backspace, ignore it (televideo 925)
173869e05691SBram Moolenaar 	    if (p != NULL
173969e05691SBram Moolenaar 		    && (*p != Ctrl_H
174069e05691SBram Moolenaar 			|| key_names[i][0] != 'k'
174169e05691SBram Moolenaar 			|| key_names[i][1] != 'l'))
174269e05691SBram Moolenaar 		add_termcode((char_u *)key_names[i], p, FALSE);
174369e05691SBram Moolenaar 	}
174469e05691SBram Moolenaar 
174569e05691SBram Moolenaar     if (*height == 0)
174669e05691SBram Moolenaar 	*height = tgetnum("li");
174769e05691SBram Moolenaar     if (*width == 0)
174869e05691SBram Moolenaar 	*width = tgetnum("co");
174969e05691SBram Moolenaar 
175069e05691SBram Moolenaar     /*
175169e05691SBram Moolenaar      * Get number of colors (if not done already).
175269e05691SBram Moolenaar      */
175369e05691SBram Moolenaar     if (TERM_STR(KS_CCO) == NULL || TERM_STR(KS_CCO) == empty_option)
175435bc7d6cSBram Moolenaar     {
175569e05691SBram Moolenaar 	set_color_count(tgetnum("Co"));
175635bc7d6cSBram Moolenaar #ifdef FEAT_EVAL
175735bc7d6cSBram Moolenaar 	set_term_option_sctx_idx("Co", -1);
175835bc7d6cSBram Moolenaar #endif
175935bc7d6cSBram Moolenaar     }
176069e05691SBram Moolenaar 
176169e05691SBram Moolenaar # ifndef hpux
176269e05691SBram Moolenaar     BC = (char *)TGETSTR("bc", &tp);
176369e05691SBram Moolenaar     UP = (char *)TGETSTR("up", &tp);
176469e05691SBram Moolenaar     p = TGETSTR("pc", &tp);
176569e05691SBram Moolenaar     if (p)
176669e05691SBram Moolenaar 	PC = *p;
176769e05691SBram Moolenaar # endif
176869e05691SBram Moolenaar }
17699289df5cSBram Moolenaar #endif
177069e05691SBram Moolenaar 
177169e05691SBram Moolenaar     static void
report_term_error(char * error_msg,char_u * term)1772f9e3e09fSBram Moolenaar report_term_error(char *error_msg, char_u *term)
177369e05691SBram Moolenaar {
177469e05691SBram Moolenaar     struct builtin_term *termp;
1775ecd34bf5SBram Moolenaar     int			i;
177669e05691SBram Moolenaar 
177769e05691SBram Moolenaar     mch_errmsg("\r\n");
177869e05691SBram Moolenaar     if (error_msg != NULL)
177969e05691SBram Moolenaar     {
1780f9e3e09fSBram Moolenaar 	mch_errmsg(error_msg);
178169e05691SBram Moolenaar 	mch_errmsg("\r\n");
178269e05691SBram Moolenaar     }
178369e05691SBram Moolenaar     mch_errmsg("'");
178469e05691SBram Moolenaar     mch_errmsg((char *)term);
178569e05691SBram Moolenaar     mch_errmsg(_("' not known. Available builtin terminals are:"));
178669e05691SBram Moolenaar     mch_errmsg("\r\n");
178769e05691SBram Moolenaar     for (termp = &(builtin_termcaps[0]); termp->bt_string != NULL; ++termp)
178869e05691SBram Moolenaar     {
17890f5575d0SBram Moolenaar 	if (termp->bt_entry == (int)KS_NAME
17900f5575d0SBram Moolenaar 		&& STRCMP(termp->bt_string, "gui") != 0)
179169e05691SBram Moolenaar 	{
179269e05691SBram Moolenaar #ifdef HAVE_TGETENT
179369e05691SBram Moolenaar 	    mch_errmsg("    builtin_");
179469e05691SBram Moolenaar #else
179569e05691SBram Moolenaar 	    mch_errmsg("    ");
179669e05691SBram Moolenaar #endif
179769e05691SBram Moolenaar 	    mch_errmsg(termp->bt_string);
179869e05691SBram Moolenaar 	    mch_errmsg("\r\n");
179969e05691SBram Moolenaar 	}
180069e05691SBram Moolenaar     }
1801ecd34bf5SBram Moolenaar     // Output extra 'cmdheight' line breaks to avoid that the following error
1802ecd34bf5SBram Moolenaar     // message overwrites the last terminal name.
1803ecd34bf5SBram Moolenaar     for (i = 1; i < p_ch; ++i)
1804ecd34bf5SBram Moolenaar 	mch_errmsg("\r\n");
180569e05691SBram Moolenaar }
180669e05691SBram Moolenaar 
180769e05691SBram Moolenaar     static void
report_default_term(char_u * term)180869e05691SBram Moolenaar report_default_term(char_u *term)
180969e05691SBram Moolenaar {
181069e05691SBram Moolenaar     mch_errmsg(_("defaulting to '"));
181169e05691SBram Moolenaar     mch_errmsg((char *)term);
181269e05691SBram Moolenaar     mch_errmsg("'\r\n");
181328ee892aSBram Moolenaar     if (emsg_silent == 0 && !in_assert_fails)
181469e05691SBram Moolenaar     {
18150d6f5d97SBram Moolenaar 	screen_start();	// don't know where cursor is now
181669e05691SBram Moolenaar 	out_flush();
181769e05691SBram Moolenaar 	if (!is_not_a_term())
1818eda1da0cSBram Moolenaar 	    ui_delay(2007L, TRUE);
181969e05691SBram Moolenaar     }
182069e05691SBram Moolenaar }
182169e05691SBram Moolenaar 
1822071d4279SBram Moolenaar /*
1823071d4279SBram Moolenaar  * Set terminal options for terminal "term".
1824071d4279SBram Moolenaar  * Return OK if terminal 'term' was found in a termcap, FAIL otherwise.
1825071d4279SBram Moolenaar  *
1826071d4279SBram Moolenaar  * While doing this, until ttest(), some options may be NULL, be careful.
1827071d4279SBram Moolenaar  */
1828071d4279SBram Moolenaar     int
set_termname(char_u * term)1829764b23c8SBram Moolenaar set_termname(char_u *term)
1830071d4279SBram Moolenaar {
1831071d4279SBram Moolenaar     struct builtin_term *termp;
1832071d4279SBram Moolenaar #ifdef HAVE_TGETENT
1833071d4279SBram Moolenaar     int		builtin_first = p_tbi;
1834071d4279SBram Moolenaar     int		try;
1835071d4279SBram Moolenaar     int		termcap_cleared = FALSE;
1836071d4279SBram Moolenaar #endif
1837071d4279SBram Moolenaar     int		width = 0, height = 0;
1838f9e3e09fSBram Moolenaar     char	*error_msg = NULL;
1839071d4279SBram Moolenaar     char_u	*bs_p, *del_p;
1840071d4279SBram Moolenaar 
18410d6f5d97SBram Moolenaar     // In silect mode (ex -s) we don't use the 'term' option.
184226a60b45SBram Moolenaar     if (silent_mode)
184326a60b45SBram Moolenaar 	return OK;
184426a60b45SBram Moolenaar 
18450d6f5d97SBram Moolenaar     detected_8bit = FALSE;		// reset 8-bit detection
1846071d4279SBram Moolenaar 
1847071d4279SBram Moolenaar     if (term_is_builtin(term))
1848071d4279SBram Moolenaar     {
1849071d4279SBram Moolenaar 	term += 8;
1850071d4279SBram Moolenaar #ifdef HAVE_TGETENT
1851071d4279SBram Moolenaar 	builtin_first = 1;
1852071d4279SBram Moolenaar #endif
1853071d4279SBram Moolenaar     }
1854071d4279SBram Moolenaar 
1855071d4279SBram Moolenaar /*
1856071d4279SBram Moolenaar  * If HAVE_TGETENT is not defined, only the builtin termcap is used, otherwise:
1857071d4279SBram Moolenaar  *   If builtin_first is TRUE:
1858071d4279SBram Moolenaar  *     0. try builtin termcap
1859071d4279SBram Moolenaar  *     1. try external termcap
1860071d4279SBram Moolenaar  *     2. if both fail default to a builtin terminal
1861071d4279SBram Moolenaar  *   If builtin_first is FALSE:
1862071d4279SBram Moolenaar  *     1. try external termcap
1863071d4279SBram Moolenaar  *     2. try builtin termcap, if both fail default to a builtin terminal
1864071d4279SBram Moolenaar  */
1865071d4279SBram Moolenaar #ifdef HAVE_TGETENT
1866071d4279SBram Moolenaar     for (try = builtin_first ? 0 : 1; try < 3; ++try)
1867071d4279SBram Moolenaar     {
1868071d4279SBram Moolenaar 	/*
1869071d4279SBram Moolenaar 	 * Use external termcap
1870071d4279SBram Moolenaar 	 */
1871071d4279SBram Moolenaar 	if (try == 1)
1872071d4279SBram Moolenaar 	{
1873071d4279SBram Moolenaar 	    char_u	    tbuf[TBUFSZ];
1874071d4279SBram Moolenaar 
1875071d4279SBram Moolenaar 	    /*
1876071d4279SBram Moolenaar 	     * If the external termcap does not have a matching entry, try the
1877071d4279SBram Moolenaar 	     * builtin ones.
1878071d4279SBram Moolenaar 	     */
1879071d4279SBram Moolenaar 	    if ((error_msg = tgetent_error(tbuf, term)) == NULL)
1880071d4279SBram Moolenaar 	    {
1881071d4279SBram Moolenaar 		if (!termcap_cleared)
1882071d4279SBram Moolenaar 		{
18830d6f5d97SBram Moolenaar 		    clear_termoptions();	// clear old options
1884071d4279SBram Moolenaar 		    termcap_cleared = TRUE;
1885071d4279SBram Moolenaar 		}
1886071d4279SBram Moolenaar 
188769e05691SBram Moolenaar 		get_term_entries(&height, &width);
1888071d4279SBram Moolenaar 	    }
1889071d4279SBram Moolenaar 	}
18900d6f5d97SBram Moolenaar 	else	    // try == 0 || try == 2
18910d6f5d97SBram Moolenaar #endif // HAVE_TGETENT
1892071d4279SBram Moolenaar 	/*
1893071d4279SBram Moolenaar 	 * Use builtin termcap
1894071d4279SBram Moolenaar 	 */
1895071d4279SBram Moolenaar 	{
1896071d4279SBram Moolenaar #ifdef HAVE_TGETENT
1897071d4279SBram Moolenaar 	    /*
1898071d4279SBram Moolenaar 	     * If builtin termcap was already used, there is no need to search
1899071d4279SBram Moolenaar 	     * for the builtin termcap again, quit now.
1900071d4279SBram Moolenaar 	     */
1901071d4279SBram Moolenaar 	    if (try == 2 && builtin_first && termcap_cleared)
1902071d4279SBram Moolenaar 		break;
1903071d4279SBram Moolenaar #endif
1904071d4279SBram Moolenaar 	    /*
1905071d4279SBram Moolenaar 	     * search for 'term' in builtin_termcaps[]
1906071d4279SBram Moolenaar 	     */
1907071d4279SBram Moolenaar 	    termp = find_builtin_term(term);
19080d6f5d97SBram Moolenaar 	    if (termp->bt_string == NULL)	// did not find it
1909071d4279SBram Moolenaar 	    {
1910071d4279SBram Moolenaar #ifdef HAVE_TGETENT
1911071d4279SBram Moolenaar 		/*
1912071d4279SBram Moolenaar 		 * If try == 0, first try the external termcap. If that is not
1913071d4279SBram Moolenaar 		 * found we'll get back here with try == 2.
1914071d4279SBram Moolenaar 		 * If termcap_cleared is set we used the external termcap,
1915071d4279SBram Moolenaar 		 * don't complain about not finding the term in the builtin
1916071d4279SBram Moolenaar 		 * termcap.
1917071d4279SBram Moolenaar 		 */
19180d6f5d97SBram Moolenaar 		if (try == 0)			// try external one
1919071d4279SBram Moolenaar 		    continue;
19200d6f5d97SBram Moolenaar 		if (termcap_cleared)		// found in external termcap
1921071d4279SBram Moolenaar 		    break;
1922071d4279SBram Moolenaar #endif
192369e05691SBram Moolenaar 		report_term_error(error_msg, term);
1924071d4279SBram Moolenaar 
19250d6f5d97SBram Moolenaar 		// when user typed :set term=xxx, quit here
1926071d4279SBram Moolenaar 		if (starting != NO_SCREEN)
1927071d4279SBram Moolenaar 		{
19280d6f5d97SBram Moolenaar 		    screen_start();	// don't know where cursor is now
1929071d4279SBram Moolenaar 		    wait_return(TRUE);
1930071d4279SBram Moolenaar 		    return FAIL;
1931071d4279SBram Moolenaar 		}
1932071d4279SBram Moolenaar 		term = DEFAULT_TERM;
193369e05691SBram Moolenaar 		report_default_term(term);
19345e3cb7e8SBram Moolenaar 		set_string_option_direct((char_u *)"term", -1, term,
19355e3cb7e8SBram Moolenaar 								 OPT_FREE, 0);
1936071d4279SBram Moolenaar 		display_errors();
1937071d4279SBram Moolenaar 	    }
1938071d4279SBram Moolenaar 	    out_flush();
1939071d4279SBram Moolenaar #ifdef HAVE_TGETENT
1940071d4279SBram Moolenaar 	    if (!termcap_cleared)
1941071d4279SBram Moolenaar 	    {
1942071d4279SBram Moolenaar #endif
19430d6f5d97SBram Moolenaar 		clear_termoptions();	    // clear old options
1944071d4279SBram Moolenaar #ifdef HAVE_TGETENT
1945071d4279SBram Moolenaar 		termcap_cleared = TRUE;
1946071d4279SBram Moolenaar 	    }
1947071d4279SBram Moolenaar #endif
1948071d4279SBram Moolenaar 	    parse_builtin_tcap(term);
1949071d4279SBram Moolenaar #ifdef FEAT_GUI
1950071d4279SBram Moolenaar 	    if (term_is_gui(term))
1951071d4279SBram Moolenaar 	    {
1952071d4279SBram Moolenaar 		out_flush();
1953071d4279SBram Moolenaar 		gui_init();
19540d6f5d97SBram Moolenaar 		// If starting the GUI failed, don't do any of the other
19550d6f5d97SBram Moolenaar 		// things for this terminal
1956071d4279SBram Moolenaar 		if (!gui.in_use)
1957071d4279SBram Moolenaar 		    return FAIL;
1958071d4279SBram Moolenaar #ifdef HAVE_TGETENT
19590d6f5d97SBram Moolenaar 		break;		// don't try using external termcap
1960071d4279SBram Moolenaar #endif
1961071d4279SBram Moolenaar 	    }
19620d6f5d97SBram Moolenaar #endif // FEAT_GUI
1963071d4279SBram Moolenaar 	}
1964071d4279SBram Moolenaar #ifdef HAVE_TGETENT
1965071d4279SBram Moolenaar     }
1966071d4279SBram Moolenaar #endif
1967071d4279SBram Moolenaar 
1968071d4279SBram Moolenaar /*
1969071d4279SBram Moolenaar  * special: There is no info in the termcap about whether the cursor
1970071d4279SBram Moolenaar  * positioning is relative to the start of the screen or to the start of the
1971071d4279SBram Moolenaar  * scrolling region.  We just guess here. Only msdos pcterm is known to do it
1972071d4279SBram Moolenaar  * relative.
1973071d4279SBram Moolenaar  */
1974071d4279SBram Moolenaar     if (STRCMP(term, "pcterm") == 0)
1975071d4279SBram Moolenaar 	T_CCS = (char_u *)"yes";
1976071d4279SBram Moolenaar     else
1977071d4279SBram Moolenaar 	T_CCS = empty_option;
1978071d4279SBram Moolenaar 
1979071d4279SBram Moolenaar #ifdef UNIX
1980071d4279SBram Moolenaar /*
1981071d4279SBram Moolenaar  * Any "stty" settings override the default for t_kb from the termcap.
1982071d4279SBram Moolenaar  * This is in os_unix.c, because it depends a lot on the version of unix that
1983071d4279SBram Moolenaar  * is being used.
1984071d4279SBram Moolenaar  * Don't do this when the GUI is active, it uses "t_kb" and "t_kD" directly.
1985071d4279SBram Moolenaar  */
1986071d4279SBram Moolenaar # ifdef FEAT_GUI
1987071d4279SBram Moolenaar     if (!gui.in_use)
1988071d4279SBram Moolenaar # endif
1989071d4279SBram Moolenaar 	get_stty();
1990071d4279SBram Moolenaar #endif
1991071d4279SBram Moolenaar 
1992071d4279SBram Moolenaar /*
1993071d4279SBram Moolenaar  * If the termcap has no entry for 'bs' and/or 'del' and the ioctl() also
1994071d4279SBram Moolenaar  * didn't work, use the default CTRL-H
1995071d4279SBram Moolenaar  * The default for t_kD is DEL, unless t_kb is DEL.
1996071d4279SBram Moolenaar  * The vim_strsave'd strings are probably lost forever, well it's only two
1997071d4279SBram Moolenaar  * bytes.  Don't do this when the GUI is active, it uses "t_kb" and "t_kD"
1998071d4279SBram Moolenaar  * directly.
1999071d4279SBram Moolenaar  */
2000071d4279SBram Moolenaar #ifdef FEAT_GUI
2001071d4279SBram Moolenaar     if (!gui.in_use)
2002071d4279SBram Moolenaar #endif
2003071d4279SBram Moolenaar     {
2004071d4279SBram Moolenaar 	bs_p = find_termcode((char_u *)"kb");
2005071d4279SBram Moolenaar 	del_p = find_termcode((char_u *)"kD");
2006071d4279SBram Moolenaar 	if (bs_p == NULL || *bs_p == NUL)
2007071d4279SBram Moolenaar 	    add_termcode((char_u *)"kb", (bs_p = (char_u *)CTRL_H_STR), FALSE);
2008071d4279SBram Moolenaar 	if ((del_p == NULL || *del_p == NUL) &&
2009071d4279SBram Moolenaar 					    (bs_p == NULL || *bs_p != DEL))
2010071d4279SBram Moolenaar 	    add_termcode((char_u *)"kD", (char_u *)DEL_STR, FALSE);
2011071d4279SBram Moolenaar     }
2012071d4279SBram Moolenaar 
2013071d4279SBram Moolenaar #if defined(UNIX) || defined(VMS)
2014071d4279SBram Moolenaar     term_is_xterm = vim_is_xterm(term);
2015071d4279SBram Moolenaar #endif
20160d2c4bf1SBram Moolenaar #ifdef FEAT_TERMRESPONSE
2017517f00f7SBram Moolenaar     // Reset terminal properties that are set based on the termresponse, which
2018517f00f7SBram Moolenaar     // will be sent out soon.
2019517f00f7SBram Moolenaar     init_term_props(FALSE);
20200d2c4bf1SBram Moolenaar #endif
2021071d4279SBram Moolenaar 
2022071d4279SBram Moolenaar #if defined(UNIX) || defined(VMS)
2023071d4279SBram Moolenaar     /*
2024071d4279SBram Moolenaar      * For Unix, set the 'ttymouse' option to the type of mouse to be used.
2025071d4279SBram Moolenaar      * The termcode for the mouse is added as a side effect in option.c.
2026071d4279SBram Moolenaar      */
2027071d4279SBram Moolenaar     {
20286d006f9eSBram Moolenaar 	char_u	*p = (char_u *)"";
2029071d4279SBram Moolenaar 
2030071d4279SBram Moolenaar # ifdef FEAT_MOUSE_XTERM
2031864207deSBram Moolenaar 	if (use_xterm_like_mouse(term))
2032071d4279SBram Moolenaar 	{
2033071d4279SBram Moolenaar 	    if (use_xterm_mouse())
20340d6f5d97SBram Moolenaar 		p = NULL;	// keep existing value, might be "xterm2"
2035071d4279SBram Moolenaar 	    else
2036071d4279SBram Moolenaar 		p = (char_u *)"xterm";
2037071d4279SBram Moolenaar 	}
2038071d4279SBram Moolenaar # endif
2039071d4279SBram Moolenaar 	if (p != NULL)
204015d55decSBram Moolenaar 	{
2041071d4279SBram Moolenaar 	    set_option_value((char_u *)"ttym", 0L, p, 0);
20420d6f5d97SBram Moolenaar 	    // Reset the WAS_SET flag, 'ttymouse' can be set to "sgr" or
20430d6f5d97SBram Moolenaar 	    // "xterm2" in check_termcode().
204415d55decSBram Moolenaar 	    reset_option_was_set((char_u *)"ttym");
204515d55decSBram Moolenaar 	}
2046071d4279SBram Moolenaar 	if (p == NULL
2047071d4279SBram Moolenaar #  ifdef FEAT_GUI
2048071d4279SBram Moolenaar 		|| gui.in_use
2049071d4279SBram Moolenaar #  endif
2050071d4279SBram Moolenaar 		)
20510d6f5d97SBram Moolenaar 	    check_mouse_termcode();	// set mouse termcode anyway
2052071d4279SBram Moolenaar     }
2053071d4279SBram Moolenaar #else
2054071d4279SBram Moolenaar     set_mouse_termcode(KS_MOUSE, (char_u *)"\233M");
2055071d4279SBram Moolenaar #endif
2056071d4279SBram Moolenaar 
2057bf78974cSBram Moolenaar #ifdef FEAT_MOUSE_XTERM
2058681fc3faSBram Moolenaar     // focus reporting is supported by xterm compatible terminals and tmux.
2059681fc3faSBram Moolenaar     if (use_xterm_like_mouse(term))
2060681fc3faSBram Moolenaar     {
2061681fc3faSBram Moolenaar 	char_u name[3];
2062681fc3faSBram Moolenaar 
2063681fc3faSBram Moolenaar 	// handle focus in event
2064bf78974cSBram Moolenaar 	name[0] = KS_EXTRA;
2065bf78974cSBram Moolenaar 	name[1] = KE_FOCUSGAINED;
2066bf78974cSBram Moolenaar 	name[2] = NUL;
2067681fc3faSBram Moolenaar 	add_termcode(name, (char_u *)"\033[I", FALSE);
2068681fc3faSBram Moolenaar 
2069681fc3faSBram Moolenaar 	// handle focus out event
2070bf78974cSBram Moolenaar 	name[1] = KE_FOCUSLOST;
2071681fc3faSBram Moolenaar 	add_termcode(name, (char_u *)"\033[O", FALSE);
2072681fc3faSBram Moolenaar 
2073681fc3faSBram Moolenaar 	focus_mode = TRUE;
2074681fc3faSBram Moolenaar 	focus_state = TRUE;
207551b477f7SBram Moolenaar 	need_gather = TRUE;
2076681fc3faSBram Moolenaar     }
2077681fc3faSBram Moolenaar #endif
2078681fc3faSBram Moolenaar 
2079071d4279SBram Moolenaar #ifdef USE_TERM_CONSOLE
20800d6f5d97SBram Moolenaar     // DEFAULT_TERM indicates that it is the machine console.
2081071d4279SBram Moolenaar     if (STRCMP(term, DEFAULT_TERM) != 0)
2082071d4279SBram Moolenaar 	term_console = FALSE;
2083071d4279SBram Moolenaar     else
2084071d4279SBram Moolenaar     {
2085071d4279SBram Moolenaar 	term_console = TRUE;
2086071d4279SBram Moolenaar # ifdef AMIGA
20870d6f5d97SBram Moolenaar 	win_resize_on();	// enable window resizing reports
2088071d4279SBram Moolenaar # endif
2089071d4279SBram Moolenaar     }
2090071d4279SBram Moolenaar #endif
2091071d4279SBram Moolenaar 
2092071d4279SBram Moolenaar #if defined(UNIX) || defined(VMS)
2093071d4279SBram Moolenaar     /*
2094071d4279SBram Moolenaar      * 'ttyfast' is default on for xterm, iris-ansi and a few others.
2095071d4279SBram Moolenaar      */
2096071d4279SBram Moolenaar     if (vim_is_fastterm(term))
2097071d4279SBram Moolenaar 	p_tf = TRUE;
2098071d4279SBram Moolenaar #endif
2099071d4279SBram Moolenaar #ifdef USE_TERM_CONSOLE
2100071d4279SBram Moolenaar     /*
2101071d4279SBram Moolenaar      * 'ttyfast' is default on consoles
2102071d4279SBram Moolenaar      */
2103071d4279SBram Moolenaar     if (term_console)
2104071d4279SBram Moolenaar 	p_tf = TRUE;
2105071d4279SBram Moolenaar #endif
2106071d4279SBram Moolenaar 
21070d6f5d97SBram Moolenaar     ttest(TRUE);	// make sure we have a valid set of terminal codes
2108071d4279SBram Moolenaar 
21090d6f5d97SBram Moolenaar     full_screen = TRUE;		// we can use termcap codes from now on
21100d6f5d97SBram Moolenaar     set_term_defaults();	// use current values as defaults
2111071d4279SBram Moolenaar #ifdef FEAT_TERMRESPONSE
2112b255b905SBram Moolenaar     LOG_TR(("setting crv_status to STATUS_GET"));
2113afd78266SBram Moolenaar     crv_status.tr_progress = STATUS_GET;	// Get terminal version later
2114071d4279SBram Moolenaar #endif
2115071d4279SBram Moolenaar 
2116071d4279SBram Moolenaar     /*
2117071d4279SBram Moolenaar      * Initialize the terminal with the appropriate termcap codes.
2118071d4279SBram Moolenaar      * Set the mouse and window title if possible.
2119071d4279SBram Moolenaar      * Don't do this when starting, need to parse the .vimrc first, because it
2120071d4279SBram Moolenaar      * may redefine t_TI etc.
2121071d4279SBram Moolenaar      */
2122071d4279SBram Moolenaar     if (starting != NO_SCREEN)
2123071d4279SBram Moolenaar     {
21240d6f5d97SBram Moolenaar 	starttermcap();		// may change terminal mode
21250d6f5d97SBram Moolenaar 	setmouse();		// may start using the mouse
2126071d4279SBram Moolenaar #ifdef FEAT_TITLE
21270d6f5d97SBram Moolenaar 	maketitle();		// may display window title
2128071d4279SBram Moolenaar #endif
2129071d4279SBram Moolenaar     }
2130071d4279SBram Moolenaar 
21310d6f5d97SBram Moolenaar 	// display initial screen after ttest() checking. jw.
2132071d4279SBram Moolenaar     if (width <= 0 || height <= 0)
2133071d4279SBram Moolenaar     {
21340d6f5d97SBram Moolenaar 	// termcap failed to report size
21350d6f5d97SBram Moolenaar 	// set defaults, in case ui_get_shellsize() also fails
2136071d4279SBram Moolenaar 	width = 80;
21374f97475dSBram Moolenaar #if defined(MSWIN)
21380d6f5d97SBram Moolenaar 	height = 25;	    // console is often 25 lines
2139071d4279SBram Moolenaar #else
21400d6f5d97SBram Moolenaar 	height = 24;	    // most terminals are 24 lines
2141071d4279SBram Moolenaar #endif
2142071d4279SBram Moolenaar     }
21430d6f5d97SBram Moolenaar     set_shellsize(width, height, FALSE);	// may change Rows
2144071d4279SBram Moolenaar     if (starting != NO_SCREEN)
2145071d4279SBram Moolenaar     {
2146071d4279SBram Moolenaar 	if (scroll_region)
21470d6f5d97SBram Moolenaar 	    scroll_region_reset();		// In case Rows changed
21480d6f5d97SBram Moolenaar 	check_map_keycodes();	// check mappings for terminal codes used
2149071d4279SBram Moolenaar 
2150071d4279SBram Moolenaar 	{
21510c81d1b1SBram Moolenaar 	    buf_T	*buf;
21520c81d1b1SBram Moolenaar 	    aco_save_T	aco;
2153071d4279SBram Moolenaar 
2154071d4279SBram Moolenaar 	    /*
2155071d4279SBram Moolenaar 	     * Execute the TermChanged autocommands for each buffer that is
2156071d4279SBram Moolenaar 	     * loaded.
2157071d4279SBram Moolenaar 	     */
21580c81d1b1SBram Moolenaar 	    FOR_ALL_BUFFERS(buf)
2159071d4279SBram Moolenaar 	    {
2160071d4279SBram Moolenaar 		if (curbuf->b_ml.ml_mfp != NULL)
21610c81d1b1SBram Moolenaar 		{
21620c81d1b1SBram Moolenaar 		    aucmd_prepbuf(&aco, buf);
2163071d4279SBram Moolenaar 		    apply_autocmds(EVENT_TERMCHANGED, NULL, NULL, FALSE,
2164071d4279SBram Moolenaar 								      curbuf);
21650c81d1b1SBram Moolenaar 		    // restore curwin/curbuf and a few other things
21660c81d1b1SBram Moolenaar 		    aucmd_restbuf(&aco);
2167071d4279SBram Moolenaar 		}
21680c81d1b1SBram Moolenaar 	    }
2169071d4279SBram Moolenaar 	}
2170071d4279SBram Moolenaar     }
2171071d4279SBram Moolenaar 
2172071d4279SBram Moolenaar #ifdef FEAT_TERMRESPONSE
2173071d4279SBram Moolenaar     may_req_termresponse();
2174071d4279SBram Moolenaar #endif
2175071d4279SBram Moolenaar 
2176071d4279SBram Moolenaar     return OK;
2177071d4279SBram Moolenaar }
2178071d4279SBram Moolenaar 
2179*b3a29558SBram Moolenaar #if defined(EXITFREE) || defined(PROTO)
2180*b3a29558SBram Moolenaar 
2181*b3a29558SBram Moolenaar # ifdef HAVE_DEL_CURTERM
2182*b3a29558SBram Moolenaar #  undef TERMINAL	    // name clash in term.h
2183*b3a29558SBram Moolenaar #  include <term.h>	    // declares cur_term
2184*b3a29558SBram Moolenaar # endif
2185*b3a29558SBram Moolenaar 
2186*b3a29558SBram Moolenaar /*
2187*b3a29558SBram Moolenaar  * If supported, delete "cur_term", which caches terminal related entries.
2188*b3a29558SBram Moolenaar  * Avoids that valgrind reports possibly lost memory.
2189*b3a29558SBram Moolenaar  */
2190*b3a29558SBram Moolenaar     void
free_cur_term()2191*b3a29558SBram Moolenaar free_cur_term()
2192*b3a29558SBram Moolenaar {
2193*b3a29558SBram Moolenaar # ifdef HAVE_DEL_CURTERM
2194*b3a29558SBram Moolenaar     if (cur_term)
2195*b3a29558SBram Moolenaar 	del_curterm(cur_term);
2196*b3a29558SBram Moolenaar # endif
2197*b3a29558SBram Moolenaar }
2198*b3a29558SBram Moolenaar 
2199*b3a29558SBram Moolenaar #endif
2200*b3a29558SBram Moolenaar 
2201071d4279SBram Moolenaar #ifdef HAVE_TGETENT
2202071d4279SBram Moolenaar /*
2203071d4279SBram Moolenaar  * Call tgetent()
2204071d4279SBram Moolenaar  * Return error message if it fails, NULL if it's OK.
2205071d4279SBram Moolenaar  */
2206f9e3e09fSBram Moolenaar     static char *
tgetent_error(char_u * tbuf,char_u * term)2207764b23c8SBram Moolenaar tgetent_error(char_u *tbuf, char_u *term)
2208071d4279SBram Moolenaar {
2209071d4279SBram Moolenaar     int	    i;
2210071d4279SBram Moolenaar 
22116b649ac4SBram Moolenaar     // Note: Valgrind may report a leak here, because the library keeps one
22126b649ac4SBram Moolenaar     // buffer around that we can't ever free.
2213071d4279SBram Moolenaar     i = TGETENT(tbuf, term);
22140d6f5d97SBram Moolenaar     if (i < 0		    // -1 is always an error
2215071d4279SBram Moolenaar # ifdef TGETENT_ZERO_ERR
22160d6f5d97SBram Moolenaar 	    || i == 0	    // sometimes zero is also an error
2217071d4279SBram Moolenaar # endif
2218071d4279SBram Moolenaar        )
2219071d4279SBram Moolenaar     {
22200d6f5d97SBram Moolenaar 	// On FreeBSD tputs() gets a SEGV after a tgetent() which fails.  Call
22210d6f5d97SBram Moolenaar 	// tgetent() with the always existing "dumb" entry to avoid a crash or
22220d6f5d97SBram Moolenaar 	// hang.
2223071d4279SBram Moolenaar 	(void)TGETENT(tbuf, "dumb");
2224071d4279SBram Moolenaar 
2225071d4279SBram Moolenaar 	if (i < 0)
2226071d4279SBram Moolenaar # ifdef TGETENT_ZERO_ERR
2227f9e3e09fSBram Moolenaar 	    return _("E557: Cannot open termcap file");
2228071d4279SBram Moolenaar 	if (i == 0)
2229071d4279SBram Moolenaar # endif
2230071d4279SBram Moolenaar #ifdef TERMINFO
2231f9e3e09fSBram Moolenaar 	    return _("E558: Terminal entry not found in terminfo");
2232071d4279SBram Moolenaar #else
2233f9e3e09fSBram Moolenaar 	    return _("E559: Terminal entry not found in termcap");
2234071d4279SBram Moolenaar #endif
2235071d4279SBram Moolenaar     }
2236071d4279SBram Moolenaar     return NULL;
2237071d4279SBram Moolenaar }
2238071d4279SBram Moolenaar 
2239071d4279SBram Moolenaar /*
2240071d4279SBram Moolenaar  * Some versions of tgetstr() have been reported to return -1 instead of NULL.
2241071d4279SBram Moolenaar  * Fix that here.
2242071d4279SBram Moolenaar  */
2243071d4279SBram Moolenaar     static char_u *
vim_tgetstr(char * s,char_u ** pp)2244764b23c8SBram Moolenaar vim_tgetstr(char *s, char_u **pp)
2245071d4279SBram Moolenaar {
2246071d4279SBram Moolenaar     char	*p;
2247071d4279SBram Moolenaar 
2248071d4279SBram Moolenaar     p = tgetstr(s, (char **)pp);
2249071d4279SBram Moolenaar     if (p == (char *)-1)
2250071d4279SBram Moolenaar 	p = NULL;
2251071d4279SBram Moolenaar     return (char_u *)p;
2252071d4279SBram Moolenaar }
22530d6f5d97SBram Moolenaar #endif // HAVE_TGETENT
2254071d4279SBram Moolenaar 
2255a06ecab7SBram Moolenaar #if defined(HAVE_TGETENT) && (defined(UNIX) || defined(VMS) || defined(MACOS_X))
2256071d4279SBram Moolenaar /*
2257071d4279SBram Moolenaar  * Get Columns and Rows from the termcap. Used after a window signal if the
2258071d4279SBram Moolenaar  * ioctl() fails. It doesn't make sense to call tgetent each time if the "co"
2259071d4279SBram Moolenaar  * and "li" entries never change. But on some systems this works.
2260071d4279SBram Moolenaar  * Errors while getting the entries are ignored.
2261071d4279SBram Moolenaar  */
2262071d4279SBram Moolenaar     void
getlinecol(long * cp,long * rp)2263764b23c8SBram Moolenaar getlinecol(
22640d6f5d97SBram Moolenaar     long	*cp,	// pointer to columns
22650d6f5d97SBram Moolenaar     long	*rp)	// pointer to rows
2266071d4279SBram Moolenaar {
2267071d4279SBram Moolenaar     char_u	tbuf[TBUFSZ];
2268071d4279SBram Moolenaar 
2269071d4279SBram Moolenaar     if (T_NAME != NULL && *T_NAME != NUL && tgetent_error(tbuf, T_NAME) == NULL)
2270071d4279SBram Moolenaar     {
2271071d4279SBram Moolenaar 	if (*cp == 0)
2272071d4279SBram Moolenaar 	    *cp = tgetnum("co");
2273071d4279SBram Moolenaar 	if (*rp == 0)
2274071d4279SBram Moolenaar 	    *rp = tgetnum("li");
2275071d4279SBram Moolenaar     }
2276071d4279SBram Moolenaar }
22770d6f5d97SBram Moolenaar #endif // defined(HAVE_TGETENT) && defined(UNIX)
2278071d4279SBram Moolenaar 
2279071d4279SBram Moolenaar /*
2280071d4279SBram Moolenaar  * Get a string entry from the termcap and add it to the list of termcodes.
2281071d4279SBram Moolenaar  * Used for <t_xx> special keys.
2282071d4279SBram Moolenaar  * Give an error message for failure when not sourcing.
2283071d4279SBram Moolenaar  * If force given, replace an existing entry.
2284071d4279SBram Moolenaar  * Return FAIL if the entry was not found, OK if the entry was added.
2285071d4279SBram Moolenaar  */
2286071d4279SBram Moolenaar     int
add_termcap_entry(char_u * name,int force)2287764b23c8SBram Moolenaar add_termcap_entry(char_u *name, int force)
2288071d4279SBram Moolenaar {
2289071d4279SBram Moolenaar     char_u  *term;
2290071d4279SBram Moolenaar     int	    key;
2291071d4279SBram Moolenaar     struct builtin_term *termp;
2292071d4279SBram Moolenaar #ifdef HAVE_TGETENT
2293071d4279SBram Moolenaar     char_u  *string;
2294071d4279SBram Moolenaar     int	    i;
2295071d4279SBram Moolenaar     int	    builtin_first;
2296071d4279SBram Moolenaar     char_u  tbuf[TBUFSZ];
2297071d4279SBram Moolenaar     char_u  tstrbuf[TBUFSZ];
2298071d4279SBram Moolenaar     char_u  *tp = tstrbuf;
2299f9e3e09fSBram Moolenaar     char    *error_msg = NULL;
2300071d4279SBram Moolenaar #endif
2301071d4279SBram Moolenaar 
2302071d4279SBram Moolenaar /*
2303071d4279SBram Moolenaar  * If the GUI is running or will start in a moment, we only support the keys
2304071d4279SBram Moolenaar  * that the GUI can produce.
2305071d4279SBram Moolenaar  */
2306071d4279SBram Moolenaar #ifdef FEAT_GUI
2307071d4279SBram Moolenaar     if (gui.in_use || gui.starting)
2308071d4279SBram Moolenaar 	return gui_mch_haskey(name);
2309071d4279SBram Moolenaar #endif
2310071d4279SBram Moolenaar 
23110d6f5d97SBram Moolenaar     if (!force && find_termcode(name) != NULL)	    // it's already there
2312071d4279SBram Moolenaar 	return OK;
2313071d4279SBram Moolenaar 
2314071d4279SBram Moolenaar     term = T_NAME;
23150d6f5d97SBram Moolenaar     if (term == NULL || *term == NUL)	    // 'term' not defined yet
2316071d4279SBram Moolenaar 	return FAIL;
2317071d4279SBram Moolenaar 
23180d6f5d97SBram Moolenaar     if (term_is_builtin(term))		    // name starts with "builtin_"
2319071d4279SBram Moolenaar     {
2320071d4279SBram Moolenaar 	term += 8;
2321071d4279SBram Moolenaar #ifdef HAVE_TGETENT
2322071d4279SBram Moolenaar 	builtin_first = TRUE;
2323071d4279SBram Moolenaar #endif
2324071d4279SBram Moolenaar     }
2325071d4279SBram Moolenaar #ifdef HAVE_TGETENT
2326071d4279SBram Moolenaar     else
2327071d4279SBram Moolenaar 	builtin_first = p_tbi;
2328071d4279SBram Moolenaar #endif
2329071d4279SBram Moolenaar 
2330071d4279SBram Moolenaar #ifdef HAVE_TGETENT
2331071d4279SBram Moolenaar /*
2332071d4279SBram Moolenaar  * We can get the entry from the builtin termcap and from the external one.
2333071d4279SBram Moolenaar  * If 'ttybuiltin' is on or the terminal name starts with "builtin_", try
2334071d4279SBram Moolenaar  * builtin termcap first.
2335071d4279SBram Moolenaar  * If 'ttybuiltin' is off, try external termcap first.
2336071d4279SBram Moolenaar  */
2337071d4279SBram Moolenaar     for (i = 0; i < 2; ++i)
2338071d4279SBram Moolenaar     {
233998b30a47SBram Moolenaar 	if ((!builtin_first) == i)
2340071d4279SBram Moolenaar #endif
2341071d4279SBram Moolenaar 	/*
2342071d4279SBram Moolenaar 	 * Search in builtin termcap
2343071d4279SBram Moolenaar 	 */
2344071d4279SBram Moolenaar 	{
2345071d4279SBram Moolenaar 	    termp = find_builtin_term(term);
23460d6f5d97SBram Moolenaar 	    if (termp->bt_string != NULL)	// found it
2347071d4279SBram Moolenaar 	    {
2348071d4279SBram Moolenaar 		key = TERMCAP2KEY(name[0], name[1]);
2349e7808481SBram Moolenaar 		++termp;
2350071d4279SBram Moolenaar 		while (termp->bt_entry != (int)KS_NAME)
2351071d4279SBram Moolenaar 		{
2352071d4279SBram Moolenaar 		    if ((int)termp->bt_entry == key)
2353071d4279SBram Moolenaar 		    {
2354071d4279SBram Moolenaar 			add_termcode(name, (char_u *)termp->bt_string,
2355071d4279SBram Moolenaar 							  term_is_8bit(term));
2356071d4279SBram Moolenaar 			return OK;
2357071d4279SBram Moolenaar 		    }
2358071d4279SBram Moolenaar 		    ++termp;
2359071d4279SBram Moolenaar 		}
2360071d4279SBram Moolenaar 	    }
2361071d4279SBram Moolenaar 	}
2362071d4279SBram Moolenaar #ifdef HAVE_TGETENT
2363071d4279SBram Moolenaar 	else
2364071d4279SBram Moolenaar 	/*
2365071d4279SBram Moolenaar 	 * Search in external termcap
2366071d4279SBram Moolenaar 	 */
2367071d4279SBram Moolenaar 	{
2368071d4279SBram Moolenaar 	    error_msg = tgetent_error(tbuf, term);
2369071d4279SBram Moolenaar 	    if (error_msg == NULL)
2370071d4279SBram Moolenaar 	    {
2371071d4279SBram Moolenaar 		string = TGETSTR((char *)name, &tp);
2372071d4279SBram Moolenaar 		if (string != NULL && *string != NUL)
2373071d4279SBram Moolenaar 		{
2374071d4279SBram Moolenaar 		    add_termcode(name, string, FALSE);
2375071d4279SBram Moolenaar 		    return OK;
2376071d4279SBram Moolenaar 		}
2377071d4279SBram Moolenaar 	    }
2378071d4279SBram Moolenaar 	}
2379071d4279SBram Moolenaar     }
2380071d4279SBram Moolenaar #endif
2381071d4279SBram Moolenaar 
23821a47ae32SBram Moolenaar     if (SOURCING_NAME == NULL)
2383071d4279SBram Moolenaar     {
2384071d4279SBram Moolenaar #ifdef HAVE_TGETENT
2385071d4279SBram Moolenaar 	if (error_msg != NULL)
2386f9e3e09fSBram Moolenaar 	    emsg(error_msg);
2387071d4279SBram Moolenaar 	else
2388071d4279SBram Moolenaar #endif
2389f9e3e09fSBram Moolenaar 	    semsg(_("E436: No \"%s\" entry in termcap"), name);
2390071d4279SBram Moolenaar     }
2391071d4279SBram Moolenaar     return FAIL;
2392071d4279SBram Moolenaar }
2393071d4279SBram Moolenaar 
2394071d4279SBram Moolenaar     static int
term_is_builtin(char_u * name)2395764b23c8SBram Moolenaar term_is_builtin(char_u *name)
2396071d4279SBram Moolenaar {
2397071d4279SBram Moolenaar     return (STRNCMP(name, "builtin_", (size_t)8) == 0);
2398071d4279SBram Moolenaar }
2399071d4279SBram Moolenaar 
2400071d4279SBram Moolenaar /*
2401071d4279SBram Moolenaar  * Return TRUE if terminal "name" uses CSI instead of <Esc>[.
2402071d4279SBram Moolenaar  * Assume that the terminal is using 8-bit controls when the name contains
2403071d4279SBram Moolenaar  * "8bit", like in "xterm-8bit".
2404071d4279SBram Moolenaar  */
2405071d4279SBram Moolenaar     int
term_is_8bit(char_u * name)2406764b23c8SBram Moolenaar term_is_8bit(char_u *name)
2407071d4279SBram Moolenaar {
2408071d4279SBram Moolenaar     return (detected_8bit || strstr((char *)name, "8bit") != NULL);
2409071d4279SBram Moolenaar }
2410071d4279SBram Moolenaar 
2411071d4279SBram Moolenaar /*
2412071d4279SBram Moolenaar  * Translate terminal control chars from 7-bit to 8-bit:
24133cd43cccSBram Moolenaar  * <Esc>[ -> CSI  <M_C_[>
24143cd43cccSBram Moolenaar  * <Esc>] -> OSC  <M-C-]>
2415071d4279SBram Moolenaar  * <Esc>O -> <M-C-O>
2416071d4279SBram Moolenaar  */
2417071d4279SBram Moolenaar     static int
term_7to8bit(char_u * p)2418764b23c8SBram Moolenaar term_7to8bit(char_u *p)
2419071d4279SBram Moolenaar {
2420071d4279SBram Moolenaar     if (*p == ESC)
2421071d4279SBram Moolenaar     {
2422071d4279SBram Moolenaar 	if (p[1] == '[')
2423071d4279SBram Moolenaar 	    return CSI;
2424071d4279SBram Moolenaar 	if (p[1] == ']')
242546fd4df7SBram Moolenaar 	    return OSC;
2426071d4279SBram Moolenaar 	if (p[1] == 'O')
2427071d4279SBram Moolenaar 	    return 0x8f;
2428071d4279SBram Moolenaar     }
2429071d4279SBram Moolenaar     return 0;
2430071d4279SBram Moolenaar }
2431071d4279SBram Moolenaar 
24321c17ffa4SBram Moolenaar #if defined(FEAT_GUI) || defined(PROTO)
2433071d4279SBram Moolenaar     int
term_is_gui(char_u * name)2434764b23c8SBram Moolenaar term_is_gui(char_u *name)
2435071d4279SBram Moolenaar {
2436071d4279SBram Moolenaar     return (STRCMP(name, "builtin_gui") == 0 || STRCMP(name, "gui") == 0);
2437071d4279SBram Moolenaar }
2438071d4279SBram Moolenaar #endif
2439071d4279SBram Moolenaar 
2440071d4279SBram Moolenaar #if !defined(HAVE_TGETENT) || defined(AMIGA) || defined(PROTO)
2441071d4279SBram Moolenaar 
2442071d4279SBram Moolenaar     char_u *
tltoa(unsigned long i)2443764b23c8SBram Moolenaar tltoa(unsigned long i)
2444071d4279SBram Moolenaar {
2445071d4279SBram Moolenaar     static char_u buf[16];
2446071d4279SBram Moolenaar     char_u	*p;
2447071d4279SBram Moolenaar 
2448071d4279SBram Moolenaar     p = buf + 15;
2449071d4279SBram Moolenaar     *p = '\0';
2450071d4279SBram Moolenaar     do
2451071d4279SBram Moolenaar     {
2452071d4279SBram Moolenaar 	--p;
2453071d4279SBram Moolenaar 	*p = (char_u) (i % 10 + '0');
2454071d4279SBram Moolenaar 	i /= 10;
2455071d4279SBram Moolenaar     }
2456071d4279SBram Moolenaar     while (i > 0 && p > buf);
2457071d4279SBram Moolenaar     return p;
2458071d4279SBram Moolenaar }
2459071d4279SBram Moolenaar #endif
2460071d4279SBram Moolenaar 
2461071d4279SBram Moolenaar #ifndef HAVE_TGETENT
2462071d4279SBram Moolenaar 
2463071d4279SBram Moolenaar /*
2464071d4279SBram Moolenaar  * minimal tgoto() implementation.
2465071d4279SBram Moolenaar  * no padding and we only parse for %i %d and %+char
2466071d4279SBram Moolenaar  */
24676c0b44b5SBram Moolenaar     static char *
tgoto(char * cm,int x,int y)2468764b23c8SBram Moolenaar tgoto(char *cm, int x, int y)
2469071d4279SBram Moolenaar {
2470071d4279SBram Moolenaar     static char buf[30];
2471071d4279SBram Moolenaar     char *p, *s, *e;
2472071d4279SBram Moolenaar 
2473071d4279SBram Moolenaar     if (!cm)
2474071d4279SBram Moolenaar 	return "OOPS";
2475071d4279SBram Moolenaar     e = buf + 29;
2476071d4279SBram Moolenaar     for (s = buf; s < e && *cm; cm++)
2477071d4279SBram Moolenaar     {
2478071d4279SBram Moolenaar 	if (*cm != '%')
2479071d4279SBram Moolenaar 	{
2480071d4279SBram Moolenaar 	    *s++ = *cm;
2481071d4279SBram Moolenaar 	    continue;
2482071d4279SBram Moolenaar 	}
2483071d4279SBram Moolenaar 	switch (*++cm)
2484071d4279SBram Moolenaar 	{
2485071d4279SBram Moolenaar 	case 'd':
2486071d4279SBram Moolenaar 	    p = (char *)tltoa((unsigned long)y);
2487071d4279SBram Moolenaar 	    y = x;
2488071d4279SBram Moolenaar 	    while (*p)
2489071d4279SBram Moolenaar 		*s++ = *p++;
2490071d4279SBram Moolenaar 	    break;
2491071d4279SBram Moolenaar 	case 'i':
2492071d4279SBram Moolenaar 	    x++;
2493071d4279SBram Moolenaar 	    y++;
2494071d4279SBram Moolenaar 	    break;
2495071d4279SBram Moolenaar 	case '+':
2496071d4279SBram Moolenaar 	    *s++ = (char)(*++cm + y);
2497071d4279SBram Moolenaar 	    y = x;
2498071d4279SBram Moolenaar 	    break;
2499071d4279SBram Moolenaar 	case '%':
2500071d4279SBram Moolenaar 	    *s++ = *cm;
2501071d4279SBram Moolenaar 	    break;
2502071d4279SBram Moolenaar 	default:
2503071d4279SBram Moolenaar 	    return "OOPS";
2504071d4279SBram Moolenaar 	}
2505071d4279SBram Moolenaar     }
2506071d4279SBram Moolenaar     *s = '\0';
2507071d4279SBram Moolenaar     return buf;
2508071d4279SBram Moolenaar }
2509071d4279SBram Moolenaar 
25100d6f5d97SBram Moolenaar #endif // HAVE_TGETENT
2511071d4279SBram Moolenaar 
2512071d4279SBram Moolenaar /*
2513071d4279SBram Moolenaar  * Set the terminal name and initialize the terminal options.
2514071d4279SBram Moolenaar  * If "name" is NULL or empty, get the terminal name from the environment.
2515071d4279SBram Moolenaar  * If that fails, use the default terminal name.
2516071d4279SBram Moolenaar  */
2517071d4279SBram Moolenaar     void
termcapinit(char_u * name)2518764b23c8SBram Moolenaar termcapinit(char_u *name)
2519071d4279SBram Moolenaar {
2520071d4279SBram Moolenaar     char_u	*term;
2521071d4279SBram Moolenaar 
2522071d4279SBram Moolenaar     if (name != NULL && *name == NUL)
25230d6f5d97SBram Moolenaar 	name = NULL;	    // empty name is equal to no name
2524071d4279SBram Moolenaar     term = name;
2525071d4279SBram Moolenaar 
2526071d4279SBram Moolenaar #ifndef MSWIN
2527071d4279SBram Moolenaar     if (term == NULL)
2528071d4279SBram Moolenaar 	term = mch_getenv((char_u *)"TERM");
2529071d4279SBram Moolenaar #endif
2530071d4279SBram Moolenaar     if (term == NULL || *term == NUL)
2531071d4279SBram Moolenaar 	term = DEFAULT_TERM;
25325e3cb7e8SBram Moolenaar     set_string_option_direct((char_u *)"term", -1, term, OPT_FREE, 0);
2533071d4279SBram Moolenaar 
25340d6f5d97SBram Moolenaar     // Set the default terminal name.
2535071d4279SBram Moolenaar     set_string_default("term", term);
2536071d4279SBram Moolenaar     set_string_default("ttytype", term);
2537071d4279SBram Moolenaar 
2538071d4279SBram Moolenaar     /*
2539071d4279SBram Moolenaar      * Avoid using "term" here, because the next mch_getenv() may overwrite it.
2540071d4279SBram Moolenaar      */
2541071d4279SBram Moolenaar     set_termname(T_NAME != NULL ? T_NAME : term);
2542071d4279SBram Moolenaar }
2543071d4279SBram Moolenaar 
2544071d4279SBram Moolenaar /*
25455da04ef1SBram Moolenaar  * The number of calls to ui_write is reduced by using "out_buf".
2546071d4279SBram Moolenaar  */
2547071d4279SBram Moolenaar #define OUT_SIZE	2047
25485da04ef1SBram Moolenaar 
25495da04ef1SBram Moolenaar // add one to allow mch_write() in os_win32.c to append a NUL
2550071d4279SBram Moolenaar static char_u		out_buf[OUT_SIZE + 1];
25515da04ef1SBram Moolenaar 
25525da04ef1SBram Moolenaar static int		out_pos = 0;	// number of chars in out_buf
25535da04ef1SBram Moolenaar 
25545da04ef1SBram Moolenaar // Since the maximum number of SGR parameters shown as a normal value range is
25555da04ef1SBram Moolenaar // 16, the escape sequence length can be 4 * 16 + lead + tail.
25565da04ef1SBram Moolenaar #define MAX_ESC_SEQ_LEN	80
2557071d4279SBram Moolenaar 
2558071d4279SBram Moolenaar /*
2559071d4279SBram Moolenaar  * out_flush(): flush the output buffer
2560071d4279SBram Moolenaar  */
2561071d4279SBram Moolenaar     void
out_flush(void)2562764b23c8SBram Moolenaar out_flush(void)
2563071d4279SBram Moolenaar {
2564071d4279SBram Moolenaar     int	    len;
2565071d4279SBram Moolenaar 
2566071d4279SBram Moolenaar     if (out_pos != 0)
2567071d4279SBram Moolenaar     {
25680d6f5d97SBram Moolenaar 	// set out_pos to 0 before ui_write, to avoid recursiveness
2569071d4279SBram Moolenaar 	len = out_pos;
2570071d4279SBram Moolenaar 	out_pos = 0;
25714c86830fSBram Moolenaar 	ui_write(out_buf, len, FALSE);
257286394aa9SBram Moolenaar #ifdef FEAT_JOB_CHANNEL
257386394aa9SBram Moolenaar 	if (ch_log_output)
257486394aa9SBram Moolenaar 	{
257586394aa9SBram Moolenaar 	    out_buf[len] = NUL;
2576681fc3faSBram Moolenaar 	    ch_log(NULL, "raw %s output: \"%s\"",
2577e1ee58acSBram Moolenaar # ifdef FEAT_GUI
2578e1ee58acSBram Moolenaar 			(gui.in_use && !gui.dying && !gui.starting) ? "GUI" :
2579e1ee58acSBram Moolenaar # endif
2580e1ee58acSBram Moolenaar 			"terminal",
2581681fc3faSBram Moolenaar 			out_buf);
258286394aa9SBram Moolenaar 	    ch_log_output = FALSE;
258386394aa9SBram Moolenaar 	}
258486394aa9SBram Moolenaar #endif
2585071d4279SBram Moolenaar     }
2586071d4279SBram Moolenaar }
2587071d4279SBram Moolenaar 
2588a338adcfSBram Moolenaar /*
2589d23a8236SBram Moolenaar  * out_flush_cursor(): flush the output buffer and redraw the cursor.
2590d23a8236SBram Moolenaar  * Does not flush recursively in the GUI to avoid slow drawing.
2591a338adcfSBram Moolenaar  */
2592a338adcfSBram Moolenaar     void
out_flush_cursor(int force UNUSED,int clear_selection UNUSED)2593a338adcfSBram Moolenaar out_flush_cursor(
25940d6f5d97SBram Moolenaar     int	    force UNUSED,   // when TRUE, update cursor even when not moved
25950d6f5d97SBram Moolenaar     int	    clear_selection UNUSED) // clear selection under cursor
2596a338adcfSBram Moolenaar {
2597a338adcfSBram Moolenaar     mch_disable_flush();
2598a338adcfSBram Moolenaar     out_flush();
2599a338adcfSBram Moolenaar     mch_enable_flush();
2600a338adcfSBram Moolenaar #ifdef FEAT_GUI
2601a338adcfSBram Moolenaar     if (gui.in_use)
2602a338adcfSBram Moolenaar     {
2603a338adcfSBram Moolenaar 	gui_update_cursor(force, clear_selection);
2604a338adcfSBram Moolenaar 	gui_may_flush();
2605a338adcfSBram Moolenaar     }
2606a338adcfSBram Moolenaar #endif
2607a338adcfSBram Moolenaar }
2608a338adcfSBram Moolenaar 
2609a338adcfSBram Moolenaar 
2610071d4279SBram Moolenaar /*
2611071d4279SBram Moolenaar  * Sometimes a byte out of a multi-byte character is written with out_char().
2612071d4279SBram Moolenaar  * To avoid flushing half of the character, call this function first.
2613071d4279SBram Moolenaar  */
2614071d4279SBram Moolenaar     void
out_flush_check(void)2615764b23c8SBram Moolenaar out_flush_check(void)
2616071d4279SBram Moolenaar {
2617071d4279SBram Moolenaar     if (enc_dbcs != 0 && out_pos >= OUT_SIZE - MB_MAXBYTES)
2618071d4279SBram Moolenaar 	out_flush();
2619071d4279SBram Moolenaar }
2620071d4279SBram Moolenaar 
2621071d4279SBram Moolenaar #ifdef FEAT_GUI
2622071d4279SBram Moolenaar /*
2623071d4279SBram Moolenaar  * out_trash(): Throw away the contents of the output buffer
2624071d4279SBram Moolenaar  */
2625071d4279SBram Moolenaar     void
out_trash(void)2626764b23c8SBram Moolenaar out_trash(void)
2627071d4279SBram Moolenaar {
2628071d4279SBram Moolenaar     out_pos = 0;
2629071d4279SBram Moolenaar }
2630071d4279SBram Moolenaar #endif
2631071d4279SBram Moolenaar 
2632071d4279SBram Moolenaar /*
2633071d4279SBram Moolenaar  * out_char(c): put a byte into the output buffer.
2634071d4279SBram Moolenaar  *		Flush it if it becomes full.
2635071d4279SBram Moolenaar  * This should not be used for outputting text on the screen (use functions
2636071d4279SBram Moolenaar  * like msg_puts() and screen_putchar() for that).
2637071d4279SBram Moolenaar  */
2638071d4279SBram Moolenaar     void
out_char(unsigned c)2639764b23c8SBram Moolenaar out_char(unsigned c)
2640071d4279SBram Moolenaar {
2641d057301bSBram Moolenaar #if defined(UNIX) || defined(VMS) || defined(AMIGA) || defined(MACOS_X)
26420d6f5d97SBram Moolenaar     if (c == '\n')	// turn LF into CR-LF (CRMOD doesn't seem to do this)
2643071d4279SBram Moolenaar 	out_char('\r');
2644071d4279SBram Moolenaar #endif
2645071d4279SBram Moolenaar 
2646071d4279SBram Moolenaar     out_buf[out_pos++] = c;
2647071d4279SBram Moolenaar 
26480d6f5d97SBram Moolenaar     // For testing we flush each time.
2649071d4279SBram Moolenaar     if (out_pos >= OUT_SIZE || p_wd)
2650071d4279SBram Moolenaar 	out_flush();
2651071d4279SBram Moolenaar }
2652071d4279SBram Moolenaar 
2653071d4279SBram Moolenaar /*
2654ec6f7350SBram Moolenaar  * Output "c" like out_char(), but don't flush when p_wd is set.
2655071d4279SBram Moolenaar  */
265686394aa9SBram Moolenaar     static int
out_char_nf(int c)265786394aa9SBram Moolenaar out_char_nf(int c)
2658071d4279SBram Moolenaar {
265986394aa9SBram Moolenaar     out_buf[out_pos++] = (unsigned)c;
2660071d4279SBram Moolenaar 
2661071d4279SBram Moolenaar     if (out_pos >= OUT_SIZE)
2662071d4279SBram Moolenaar 	out_flush();
266386394aa9SBram Moolenaar     return (unsigned)c;
2664071d4279SBram Moolenaar }
2665071d4279SBram Moolenaar 
2666071d4279SBram Moolenaar /*
2667ec6f7350SBram Moolenaar  * A never-padding out_str().
2668ec6f7350SBram Moolenaar  * Use this whenever you don't want to run the string through tputs().
2669ec6f7350SBram Moolenaar  * tputs() above is harmless, but tputs() from the termcap library
2670071d4279SBram Moolenaar  * is likely to strip off leading digits, that it mistakes for padding
2671071d4279SBram Moolenaar  * information, and "%i", "%d", etc.
2672071d4279SBram Moolenaar  * This should only be used for writing terminal codes, not for outputting
2673071d4279SBram Moolenaar  * normal text (use functions like msg_puts() and screen_putchar() for that).
2674071d4279SBram Moolenaar  */
2675071d4279SBram Moolenaar     void
out_str_nf(char_u * s)2676764b23c8SBram Moolenaar out_str_nf(char_u *s)
2677071d4279SBram Moolenaar {
26785da04ef1SBram Moolenaar     // avoid terminal strings being split up
26795da04ef1SBram Moolenaar     if (out_pos > OUT_SIZE - MAX_ESC_SEQ_LEN)
2680071d4279SBram Moolenaar 	out_flush();
26815da04ef1SBram Moolenaar 
2682071d4279SBram Moolenaar     while (*s)
2683071d4279SBram Moolenaar 	out_char_nf(*s++);
2684071d4279SBram Moolenaar 
26855da04ef1SBram Moolenaar     // For testing we write one string at a time.
2686071d4279SBram Moolenaar     if (p_wd)
2687071d4279SBram Moolenaar 	out_flush();
2688071d4279SBram Moolenaar }
2689071d4279SBram Moolenaar 
2690071d4279SBram Moolenaar /*
26912e147caaSBram Moolenaar  * A conditional-flushing out_str, mainly for visualbell.
26922e147caaSBram Moolenaar  * Handles a delay internally, because termlib may not respect the delay or do
26932e147caaSBram Moolenaar  * it at the wrong time.
26942e147caaSBram Moolenaar  * Note: Only for terminal strings.
26952e147caaSBram Moolenaar  */
26962e147caaSBram Moolenaar     void
out_str_cf(char_u * s)26972e147caaSBram Moolenaar out_str_cf(char_u *s)
26982e147caaSBram Moolenaar {
26992e147caaSBram Moolenaar     if (s != NULL && *s)
27002e147caaSBram Moolenaar     {
2701c2226845SBram Moolenaar #ifdef HAVE_TGETENT
27022e147caaSBram Moolenaar 	char_u *p;
2703c2226845SBram Moolenaar #endif
27042e147caaSBram Moolenaar 
27052e147caaSBram Moolenaar #ifdef FEAT_GUI
27060d6f5d97SBram Moolenaar 	// Don't use tputs() when GUI is used, ncurses crashes.
27072e147caaSBram Moolenaar 	if (gui.in_use)
27082e147caaSBram Moolenaar 	{
27092e147caaSBram Moolenaar 	    out_str_nf(s);
27102e147caaSBram Moolenaar 	    return;
27112e147caaSBram Moolenaar 	}
27122e147caaSBram Moolenaar #endif
27135da04ef1SBram Moolenaar 	if (out_pos > OUT_SIZE - MAX_ESC_SEQ_LEN)
27142e147caaSBram Moolenaar 	    out_flush();
27152e147caaSBram Moolenaar #ifdef HAVE_TGETENT
27162e147caaSBram Moolenaar 	for (p = s; *s; ++s)
27172e147caaSBram Moolenaar 	{
27180d6f5d97SBram Moolenaar 	    // flush just before delay command
27192e147caaSBram Moolenaar 	    if (*s == '$' && *(s + 1) == '<')
27202e147caaSBram Moolenaar 	    {
27212e147caaSBram Moolenaar 		char_u save_c = *s;
27222e147caaSBram Moolenaar 		int duration = atoi((char *)s + 2);
27232e147caaSBram Moolenaar 
27242e147caaSBram Moolenaar 		*s = NUL;
27252e147caaSBram Moolenaar 		tputs((char *)p, 1, TPUTSFUNCAST out_char_nf);
27262e147caaSBram Moolenaar 		*s = save_c;
27272e147caaSBram Moolenaar 		out_flush();
27282e147caaSBram Moolenaar # ifdef ELAPSED_FUNC
27290d6f5d97SBram Moolenaar 		// Only sleep here if we can limit this happening in
27300d6f5d97SBram Moolenaar 		// vim_beep().
27312e147caaSBram Moolenaar 		p = vim_strchr(s, '>');
27322e147caaSBram Moolenaar 		if (p == NULL || duration <= 0)
27332e147caaSBram Moolenaar 		{
27340d6f5d97SBram Moolenaar 		    // can't parse the time, don't sleep here
27352e147caaSBram Moolenaar 		    p = s;
27362e147caaSBram Moolenaar 		}
27372e147caaSBram Moolenaar 		else
27382e147caaSBram Moolenaar 		{
27392e147caaSBram Moolenaar 		    ++p;
2740e2edc2edSBram Moolenaar 		    do_sleep(duration, FALSE);
27412e147caaSBram Moolenaar 		}
27422e147caaSBram Moolenaar # else
27430d6f5d97SBram Moolenaar 		// Rely on the terminal library to sleep.
27442e147caaSBram Moolenaar 		p = s;
27452e147caaSBram Moolenaar # endif
27462e147caaSBram Moolenaar 		break;
27472e147caaSBram Moolenaar 	    }
27482e147caaSBram Moolenaar 	}
27492e147caaSBram Moolenaar 	tputs((char *)p, 1, TPUTSFUNCAST out_char_nf);
27502e147caaSBram Moolenaar #else
27512e147caaSBram Moolenaar 	while (*s)
27522e147caaSBram Moolenaar 	    out_char_nf(*s++);
27532e147caaSBram Moolenaar #endif
27542e147caaSBram Moolenaar 
27550d6f5d97SBram Moolenaar 	// For testing we write one string at a time.
27562e147caaSBram Moolenaar 	if (p_wd)
27572e147caaSBram Moolenaar 	    out_flush();
27582e147caaSBram Moolenaar     }
27592e147caaSBram Moolenaar }
27602e147caaSBram Moolenaar 
27612e147caaSBram Moolenaar /*
2762071d4279SBram Moolenaar  * out_str(s): Put a character string a byte at a time into the output buffer.
2763ec6f7350SBram Moolenaar  * If HAVE_TGETENT is defined use tputs(), the termcap parser. (jw)
2764071d4279SBram Moolenaar  * This should only be used for writing terminal codes, not for outputting
2765071d4279SBram Moolenaar  * normal text (use functions like msg_puts() and screen_putchar() for that).
2766071d4279SBram Moolenaar  */
2767071d4279SBram Moolenaar     void
out_str(char_u * s)2768764b23c8SBram Moolenaar out_str(char_u *s)
2769071d4279SBram Moolenaar {
2770071d4279SBram Moolenaar     if (s != NULL && *s)
2771071d4279SBram Moolenaar     {
2772071d4279SBram Moolenaar #ifdef FEAT_GUI
27730d6f5d97SBram Moolenaar 	// Don't use tputs() when GUI is used, ncurses crashes.
2774071d4279SBram Moolenaar 	if (gui.in_use)
2775071d4279SBram Moolenaar 	{
2776071d4279SBram Moolenaar 	    out_str_nf(s);
2777071d4279SBram Moolenaar 	    return;
2778071d4279SBram Moolenaar 	}
2779071d4279SBram Moolenaar #endif
27800d6f5d97SBram Moolenaar 	// avoid terminal strings being split up
27815da04ef1SBram Moolenaar 	if (out_pos > OUT_SIZE - MAX_ESC_SEQ_LEN)
2782071d4279SBram Moolenaar 	    out_flush();
2783071d4279SBram Moolenaar #ifdef HAVE_TGETENT
2784071d4279SBram Moolenaar 	tputs((char *)s, 1, TPUTSFUNCAST out_char_nf);
2785071d4279SBram Moolenaar #else
2786071d4279SBram Moolenaar 	while (*s)
2787071d4279SBram Moolenaar 	    out_char_nf(*s++);
2788071d4279SBram Moolenaar #endif
2789071d4279SBram Moolenaar 
27900d6f5d97SBram Moolenaar 	// For testing we write one string at a time.
2791071d4279SBram Moolenaar 	if (p_wd)
2792071d4279SBram Moolenaar 	    out_flush();
2793071d4279SBram Moolenaar     }
2794071d4279SBram Moolenaar }
2795071d4279SBram Moolenaar 
2796071d4279SBram Moolenaar /*
2797071d4279SBram Moolenaar  * cursor positioning using termcap parser. (jw)
2798071d4279SBram Moolenaar  */
2799071d4279SBram Moolenaar     void
term_windgoto(int row,int col)2800764b23c8SBram Moolenaar term_windgoto(int row, int col)
2801071d4279SBram Moolenaar {
2802071d4279SBram Moolenaar     OUT_STR(tgoto((char *)T_CM, col, row));
2803071d4279SBram Moolenaar }
2804071d4279SBram Moolenaar 
2805071d4279SBram Moolenaar     void
term_cursor_right(int i)2806764b23c8SBram Moolenaar term_cursor_right(int i)
2807071d4279SBram Moolenaar {
2808071d4279SBram Moolenaar     OUT_STR(tgoto((char *)T_CRI, 0, i));
2809071d4279SBram Moolenaar }
2810071d4279SBram Moolenaar 
2811071d4279SBram Moolenaar     void
term_append_lines(int line_count)2812764b23c8SBram Moolenaar term_append_lines(int line_count)
2813071d4279SBram Moolenaar {
2814071d4279SBram Moolenaar     OUT_STR(tgoto((char *)T_CAL, 0, line_count));
2815071d4279SBram Moolenaar }
2816071d4279SBram Moolenaar 
2817071d4279SBram Moolenaar     void
term_delete_lines(int line_count)2818764b23c8SBram Moolenaar term_delete_lines(int line_count)
2819071d4279SBram Moolenaar {
2820071d4279SBram Moolenaar     OUT_STR(tgoto((char *)T_CDL, 0, line_count));
2821071d4279SBram Moolenaar }
2822071d4279SBram Moolenaar 
2823071d4279SBram Moolenaar #if defined(HAVE_TGETENT) || defined(PROTO)
2824071d4279SBram Moolenaar     void
term_set_winpos(int x,int y)2825764b23c8SBram Moolenaar term_set_winpos(int x, int y)
2826071d4279SBram Moolenaar {
28270d6f5d97SBram Moolenaar     // Can't handle a negative value here
2828071d4279SBram Moolenaar     if (x < 0)
2829071d4279SBram Moolenaar 	x = 0;
2830071d4279SBram Moolenaar     if (y < 0)
2831071d4279SBram Moolenaar 	y = 0;
2832071d4279SBram Moolenaar     OUT_STR(tgoto((char *)T_CWP, y, x));
2833071d4279SBram Moolenaar }
2834071d4279SBram Moolenaar 
2835ba6ec182SBram Moolenaar # if defined(FEAT_TERMRESPONSE) || defined(PROTO)
2836ba6ec182SBram Moolenaar /*
2837ba6ec182SBram Moolenaar  * Return TRUE if we can request the terminal for a response.
2838ba6ec182SBram Moolenaar  */
2839ba6ec182SBram Moolenaar     static int
can_get_termresponse()2840ba6ec182SBram Moolenaar can_get_termresponse()
2841ba6ec182SBram Moolenaar {
2842ba6ec182SBram Moolenaar     return cur_tmode == TMODE_RAW
2843ba6ec182SBram Moolenaar 	    && termcap_active
2844ba6ec182SBram Moolenaar #  ifdef UNIX
2845ba6ec182SBram Moolenaar 	    && (is_not_a_term() || (isatty(1) && isatty(read_cmd_fd)))
2846ba6ec182SBram Moolenaar #  endif
2847ba6ec182SBram Moolenaar 	    && p_ek;
2848ba6ec182SBram Moolenaar }
2849ba6ec182SBram Moolenaar 
2850afd78266SBram Moolenaar /*
2851afd78266SBram Moolenaar  * Set "status" to STATUS_SENT.
2852afd78266SBram Moolenaar  */
2853afd78266SBram Moolenaar     static void
termrequest_sent(termrequest_T * status)2854afd78266SBram Moolenaar termrequest_sent(termrequest_T *status)
2855afd78266SBram Moolenaar {
2856afd78266SBram Moolenaar     status->tr_progress = STATUS_SENT;
2857afd78266SBram Moolenaar     status->tr_start = time(NULL);
2858afd78266SBram Moolenaar }
2859afd78266SBram Moolenaar 
2860afd78266SBram Moolenaar /*
2861afd78266SBram Moolenaar  * Return TRUE if any of the requests are in STATUS_SENT.
2862afd78266SBram Moolenaar  */
2863afd78266SBram Moolenaar     static int
termrequest_any_pending()2864afd78266SBram Moolenaar termrequest_any_pending()
2865afd78266SBram Moolenaar {
2866afd78266SBram Moolenaar     int	    i;
2867afd78266SBram Moolenaar     time_t  now = time(NULL);
2868afd78266SBram Moolenaar 
2869afd78266SBram Moolenaar     for (i = 0; all_termrequests[i] != NULL; ++i)
2870afd78266SBram Moolenaar     {
2871afd78266SBram Moolenaar 	if (all_termrequests[i]->tr_progress == STATUS_SENT)
2872afd78266SBram Moolenaar 	{
2873afd78266SBram Moolenaar 	    if (all_termrequests[i]->tr_start > 0 && now > 0
2874afd78266SBram Moolenaar 				    && all_termrequests[i]->tr_start + 2 < now)
2875afd78266SBram Moolenaar 		// Sent the request more than 2 seconds ago and didn't get a
2876afd78266SBram Moolenaar 		// response, assume it failed.
2877afd78266SBram Moolenaar 		all_termrequests[i]->tr_progress = STATUS_FAIL;
2878afd78266SBram Moolenaar 	    else
2879afd78266SBram Moolenaar 		return TRUE;
2880afd78266SBram Moolenaar 	}
2881afd78266SBram Moolenaar     }
2882afd78266SBram Moolenaar     return FALSE;
2883afd78266SBram Moolenaar }
2884afd78266SBram Moolenaar 
288589894aa6SBram Moolenaar static int winpos_x = -1;
288689894aa6SBram Moolenaar static int winpos_y = -1;
288789894aa6SBram Moolenaar static int did_request_winpos = 0;
2888ba6ec182SBram Moolenaar 
28896bc9305aSBram Moolenaar # if defined(FEAT_EVAL) || defined(FEAT_TERMINAL) || defined(PROTO)
2890ba6ec182SBram Moolenaar /*
2891ba6ec182SBram Moolenaar  * Try getting the Vim window position from the terminal.
2892ba6ec182SBram Moolenaar  * Returns OK or FAIL.
2893ba6ec182SBram Moolenaar  */
2894ba6ec182SBram Moolenaar     int
term_get_winpos(int * x,int * y,varnumber_T timeout)28953f54fd31SBram Moolenaar term_get_winpos(int *x, int *y, varnumber_T timeout)
2896ba6ec182SBram Moolenaar {
2897ba6ec182SBram Moolenaar     int count = 0;
289889894aa6SBram Moolenaar     int prev_winpos_x = winpos_x;
289989894aa6SBram Moolenaar     int prev_winpos_y = winpos_y;
2900ba6ec182SBram Moolenaar 
2901ba6ec182SBram Moolenaar     if (*T_CGP == NUL || !can_get_termresponse())
2902ba6ec182SBram Moolenaar 	return FAIL;
2903ba6ec182SBram Moolenaar     winpos_x = -1;
2904ba6ec182SBram Moolenaar     winpos_y = -1;
290589894aa6SBram Moolenaar     ++did_request_winpos;
2906afd78266SBram Moolenaar     termrequest_sent(&winpos_status);
2907ba6ec182SBram Moolenaar     OUT_STR(T_CGP);
2908ba6ec182SBram Moolenaar     out_flush();
2909ba6ec182SBram Moolenaar 
29100d6f5d97SBram Moolenaar     // Try reading the result for "timeout" msec.
291189894aa6SBram Moolenaar     while (count++ <= timeout / 10 && !got_int)
2912ba6ec182SBram Moolenaar     {
2913ba6ec182SBram Moolenaar 	(void)vpeekc_nomap();
2914ba6ec182SBram Moolenaar 	if (winpos_x >= 0 && winpos_y >= 0)
2915ba6ec182SBram Moolenaar 	{
2916ba6ec182SBram Moolenaar 	    *x = winpos_x;
2917ba6ec182SBram Moolenaar 	    *y = winpos_y;
2918ba6ec182SBram Moolenaar 	    return OK;
2919ba6ec182SBram Moolenaar 	}
2920eda1da0cSBram Moolenaar 	ui_delay(10L, FALSE);
2921ba6ec182SBram Moolenaar     }
29220d6f5d97SBram Moolenaar     // Do not reset "did_request_winpos", if we timed out the response might
29230d6f5d97SBram Moolenaar     // still come later and we must consume it.
292489894aa6SBram Moolenaar 
292589894aa6SBram Moolenaar     winpos_x = prev_winpos_x;
292689894aa6SBram Moolenaar     winpos_y = prev_winpos_y;
29271c17ffa4SBram Moolenaar     if (timeout < 10 && prev_winpos_y >= 0 && prev_winpos_x >= 0)
292889894aa6SBram Moolenaar     {
29290d6f5d97SBram Moolenaar 	// Polling: return previous values if we have them.
293089894aa6SBram Moolenaar 	*x = winpos_x;
293189894aa6SBram Moolenaar 	*y = winpos_y;
293289894aa6SBram Moolenaar 	return OK;
293389894aa6SBram Moolenaar     }
293489894aa6SBram Moolenaar 
2935ba6ec182SBram Moolenaar     return FALSE;
2936ba6ec182SBram Moolenaar }
2937ba6ec182SBram Moolenaar #  endif
2938113e1072SBram Moolenaar # endif
2939ba6ec182SBram Moolenaar 
2940071d4279SBram Moolenaar     void
term_set_winsize(int height,int width)2941b7a8dfebSBram Moolenaar term_set_winsize(int height, int width)
2942071d4279SBram Moolenaar {
2943b7a8dfebSBram Moolenaar     OUT_STR(tgoto((char *)T_CWS, width, height));
2944071d4279SBram Moolenaar }
2945071d4279SBram Moolenaar #endif
2946071d4279SBram Moolenaar 
2947071d4279SBram Moolenaar     static void
term_color(char_u * s,int n)2948764b23c8SBram Moolenaar term_color(char_u *s, int n)
2949071d4279SBram Moolenaar {
2950071d4279SBram Moolenaar     char	buf[20];
2951cafafb38SBram Moolenaar     int		i = *s == CSI ? 1 : 2;
29520d6f5d97SBram Moolenaar 		// index in s[] just after <Esc>[ or CSI
2953071d4279SBram Moolenaar 
29540d6f5d97SBram Moolenaar     // Special handling of 16 colors, because termcap can't handle it
29550d6f5d97SBram Moolenaar     // Also accept "\e[3%dm" for TERMINFO, it is sometimes used
29560d6f5d97SBram Moolenaar     // Also accept CSI instead of <Esc>[
2957071d4279SBram Moolenaar     if (n >= 8 && t_colors >= 16
2958c5cd8855SBram Moolenaar 	      && ((s[0] == ESC && s[1] == '[')
2959c5cd8855SBram Moolenaar #if defined(FEAT_VTP) && defined(FEAT_TERMGUICOLORS)
2960c5cd8855SBram Moolenaar 		  || (s[0] == ESC && s[1] == '|')
2961c5cd8855SBram Moolenaar #endif
2962c5cd8855SBram Moolenaar 		  || (s[0] == CSI && (i = 1) == 1))
2963071d4279SBram Moolenaar 	      && s[i] != NUL
2964071d4279SBram Moolenaar 	      && (STRCMP(s + i + 1, "%p1%dm") == 0
2965071d4279SBram Moolenaar 		  || STRCMP(s + i + 1, "%dm") == 0)
2966071d4279SBram Moolenaar 	      && (s[i] == '3' || s[i] == '4'))
2967071d4279SBram Moolenaar     {
2968071d4279SBram Moolenaar #ifdef TERMINFO
2969827b165bSBram Moolenaar 	char *format = "%s%s%%p1%%dm";
2970071d4279SBram Moolenaar #else
2971827b165bSBram Moolenaar 	char *format = "%s%s%%dm";
2972071d4279SBram Moolenaar #endif
2973d315cf55SBram Moolenaar 	char *lead = i == 2 ? (
2974c5cd8855SBram Moolenaar #if defined(FEAT_VTP) && defined(FEAT_TERMGUICOLORS)
2975c5cd8855SBram Moolenaar 		    s[1] == '|' ? IF_EB("\033|", ESC_STR "|") :
2976c5cd8855SBram Moolenaar #endif
2977d315cf55SBram Moolenaar 		    IF_EB("\033[", ESC_STR "[")) : "\233";
2978d315cf55SBram Moolenaar 	char *tail = s[i] == '3' ? (n >= 16 ? "38;5;" : "9")
2979d315cf55SBram Moolenaar 				 : (n >= 16 ? "48;5;" : "10");
2980d315cf55SBram Moolenaar 
2981d315cf55SBram Moolenaar 	sprintf(buf, format, lead, tail);
2982071d4279SBram Moolenaar 	OUT_STR(tgoto(buf, 0, n >= 16 ? n : n - 8));
2983071d4279SBram Moolenaar     }
2984071d4279SBram Moolenaar     else
2985071d4279SBram Moolenaar 	OUT_STR(tgoto((char *)s, 0, n));
2986071d4279SBram Moolenaar }
2987071d4279SBram Moolenaar 
2988cafafb38SBram Moolenaar     void
term_fg_color(int n)2989cafafb38SBram Moolenaar term_fg_color(int n)
2990cafafb38SBram Moolenaar {
29910d6f5d97SBram Moolenaar     // Use "AF" termcap entry if present, "Sf" entry otherwise
2992cafafb38SBram Moolenaar     if (*T_CAF)
2993cafafb38SBram Moolenaar 	term_color(T_CAF, n);
2994cafafb38SBram Moolenaar     else if (*T_CSF)
2995cafafb38SBram Moolenaar 	term_color(T_CSF, n);
2996cafafb38SBram Moolenaar }
2997cafafb38SBram Moolenaar 
2998cafafb38SBram Moolenaar     void
term_bg_color(int n)2999cafafb38SBram Moolenaar term_bg_color(int n)
3000cafafb38SBram Moolenaar {
30010d6f5d97SBram Moolenaar     // Use "AB" termcap entry if present, "Sb" entry otherwise
3002cafafb38SBram Moolenaar     if (*T_CAB)
3003cafafb38SBram Moolenaar 	term_color(T_CAB, n);
3004cafafb38SBram Moolenaar     else if (*T_CSB)
3005cafafb38SBram Moolenaar 	term_color(T_CSB, n);
3006cafafb38SBram Moolenaar }
3007cafafb38SBram Moolenaar 
3008e023e88bSBram Moolenaar     void
term_ul_color(int n)3009e023e88bSBram Moolenaar term_ul_color(int n)
3010e023e88bSBram Moolenaar {
3011e023e88bSBram Moolenaar     if (*T_CAU)
3012e023e88bSBram Moolenaar 	term_color(T_CAU, n);
3013e023e88bSBram Moolenaar }
3014e023e88bSBram Moolenaar 
30157bae0b1bSBram Moolenaar /*
30167bae0b1bSBram Moolenaar  * Return "dark" or "light" depending on the kind of terminal.
30177bae0b1bSBram Moolenaar  * This is just guessing!  Recognized are:
30187bae0b1bSBram Moolenaar  * "linux"	    Linux console
30197bae0b1bSBram Moolenaar  * "screen.linux"   Linux console with screen
30207bae0b1bSBram Moolenaar  * "cygwin.*"	    Cygwin shell
30217bae0b1bSBram Moolenaar  * "putty.*"	    Putty program
30227bae0b1bSBram Moolenaar  * We also check the COLORFGBG environment variable, which is set by
30237bae0b1bSBram Moolenaar  * rxvt and derivatives. This variable contains either two or three
30247bae0b1bSBram Moolenaar  * values separated by semicolons; we want the last value in either
30257bae0b1bSBram Moolenaar  * case. If this value is 0-6 or 8, our background is dark.
30267bae0b1bSBram Moolenaar  */
30277bae0b1bSBram Moolenaar     char_u *
term_bg_default(void)30287bae0b1bSBram Moolenaar term_bg_default(void)
30297bae0b1bSBram Moolenaar {
30307bae0b1bSBram Moolenaar #if defined(MSWIN)
30310d6f5d97SBram Moolenaar     // DOS console is nearly always black
30327bae0b1bSBram Moolenaar     return (char_u *)"dark";
30337bae0b1bSBram Moolenaar #else
30347bae0b1bSBram Moolenaar     char_u	*p;
30357bae0b1bSBram Moolenaar 
30367bae0b1bSBram Moolenaar     if (STRCMP(T_NAME, "linux") == 0
30377bae0b1bSBram Moolenaar 	    || STRCMP(T_NAME, "screen.linux") == 0
30387bae0b1bSBram Moolenaar 	    || STRNCMP(T_NAME, "cygwin", 6) == 0
30397bae0b1bSBram Moolenaar 	    || STRNCMP(T_NAME, "putty", 5) == 0
30407bae0b1bSBram Moolenaar 	    || ((p = mch_getenv((char_u *)"COLORFGBG")) != NULL
30417bae0b1bSBram Moolenaar 		&& (p = vim_strrchr(p, ';')) != NULL
30427bae0b1bSBram Moolenaar 		&& ((p[1] >= '0' && p[1] <= '6') || p[1] == '8')
30437bae0b1bSBram Moolenaar 		&& p[2] == NUL))
30447bae0b1bSBram Moolenaar 	return (char_u *)"dark";
30457bae0b1bSBram Moolenaar     return (char_u *)"light";
30467bae0b1bSBram Moolenaar #endif
30477bae0b1bSBram Moolenaar }
30487bae0b1bSBram Moolenaar 
304961be73bbSBram Moolenaar #if defined(FEAT_TERMGUICOLORS) || defined(PROTO)
30508a633e34SBram Moolenaar 
30511b58cdd1SBram Moolenaar #define RED(rgb)   (((long_u)(rgb) >> 16) & 0xFF)
30521b58cdd1SBram Moolenaar #define GREEN(rgb) (((long_u)(rgb) >>  8) & 0xFF)
30531b58cdd1SBram Moolenaar #define BLUE(rgb)  (((long_u)(rgb)      ) & 0xFF)
30548a633e34SBram Moolenaar 
30558a633e34SBram Moolenaar     static void
term_rgb_color(char_u * s,guicolor_T rgb)30561b58cdd1SBram Moolenaar term_rgb_color(char_u *s, guicolor_T rgb)
30578a633e34SBram Moolenaar {
3058380130f1SBram Moolenaar #define MAX_COLOR_STR_LEN 100
3059380130f1SBram Moolenaar     char	buf[MAX_COLOR_STR_LEN];
30608a633e34SBram Moolenaar 
3061a1c487eeSBram Moolenaar     vim_snprintf(buf, MAX_COLOR_STR_LEN,
3062380130f1SBram Moolenaar 				  (char *)s, RED(rgb), GREEN(rgb), BLUE(rgb));
306306b7b584SBram Moolenaar #ifdef FEAT_VTP
306406b7b584SBram Moolenaar     if (use_wt())
306506b7b584SBram Moolenaar     {
306606b7b584SBram Moolenaar 	out_flush();
306706b7b584SBram Moolenaar 	buf[1] = '[';
306806b7b584SBram Moolenaar 	vtp_printf(buf);
306906b7b584SBram Moolenaar     }
307006b7b584SBram Moolenaar     else
307106b7b584SBram Moolenaar #endif
30728a633e34SBram Moolenaar 	OUT_STR(buf);
30738a633e34SBram Moolenaar }
30741b58cdd1SBram Moolenaar 
30751b58cdd1SBram Moolenaar     void
term_fg_rgb_color(guicolor_T rgb)30761b58cdd1SBram Moolenaar term_fg_rgb_color(guicolor_T rgb)
30771b58cdd1SBram Moolenaar {
30781b58cdd1SBram Moolenaar     term_rgb_color(T_8F, rgb);
30791b58cdd1SBram Moolenaar }
30801b58cdd1SBram Moolenaar 
30811b58cdd1SBram Moolenaar     void
term_bg_rgb_color(guicolor_T rgb)30821b58cdd1SBram Moolenaar term_bg_rgb_color(guicolor_T rgb)
30831b58cdd1SBram Moolenaar {
30841b58cdd1SBram Moolenaar     term_rgb_color(T_8B, rgb);
30851b58cdd1SBram Moolenaar }
3086e023e88bSBram Moolenaar 
3087e023e88bSBram Moolenaar     void
term_ul_rgb_color(guicolor_T rgb)3088e023e88bSBram Moolenaar term_ul_rgb_color(guicolor_T rgb)
3089e023e88bSBram Moolenaar {
3090e023e88bSBram Moolenaar     term_rgb_color(T_8U, rgb);
3091e023e88bSBram Moolenaar }
30928a633e34SBram Moolenaar #endif
30938a633e34SBram Moolenaar 
3094e7fedb6eSBram Moolenaar #if (defined(FEAT_TITLE) && (defined(UNIX) || defined(VMS) \
3095e7fedb6eSBram Moolenaar 	|| defined(MACOS_X))) || defined(PROTO)
3096071d4279SBram Moolenaar /*
3097071d4279SBram Moolenaar  * Generic function to set window title, using t_ts and t_fs.
3098071d4279SBram Moolenaar  */
3099071d4279SBram Moolenaar     void
term_settitle(char_u * title)3100764b23c8SBram Moolenaar term_settitle(char_u *title)
3101071d4279SBram Moolenaar {
310286394aa9SBram Moolenaar #ifdef FEAT_JOB_CHANNEL
310386394aa9SBram Moolenaar     ch_log_output = TRUE;
310486394aa9SBram Moolenaar #endif
3105ec6f7350SBram Moolenaar     // t_ts takes one argument: column in status line
3106ec6f7350SBram Moolenaar     OUT_STR(tgoto((char *)T_TS, 0, 0));	// set title start
3107071d4279SBram Moolenaar     out_str_nf(title);
3108ec6f7350SBram Moolenaar     out_str(T_FS);			// set title end
3109071d4279SBram Moolenaar     out_flush();
3110071d4279SBram Moolenaar }
311140385dbcSBram Moolenaar 
311240385dbcSBram Moolenaar /*
311340385dbcSBram Moolenaar  * Tell the terminal to push (save) the title and/or icon, so that it can be
311440385dbcSBram Moolenaar  * popped (restored) later.
311540385dbcSBram Moolenaar  */
311640385dbcSBram Moolenaar     void
term_push_title(int which)311740385dbcSBram Moolenaar term_push_title(int which)
311840385dbcSBram Moolenaar {
311927821260SBram Moolenaar     if ((which & SAVE_RESTORE_TITLE) && T_CST != NULL && *T_CST != NUL)
312040385dbcSBram Moolenaar     {
312140385dbcSBram Moolenaar 	OUT_STR(T_CST);
312240385dbcSBram Moolenaar 	out_flush();
312340385dbcSBram Moolenaar     }
312440385dbcSBram Moolenaar 
312527821260SBram Moolenaar     if ((which & SAVE_RESTORE_ICON) && T_SSI != NULL && *T_SSI != NUL)
312640385dbcSBram Moolenaar     {
312740385dbcSBram Moolenaar 	OUT_STR(T_SSI);
312840385dbcSBram Moolenaar 	out_flush();
312940385dbcSBram Moolenaar     }
313040385dbcSBram Moolenaar }
313140385dbcSBram Moolenaar 
313240385dbcSBram Moolenaar /*
313340385dbcSBram Moolenaar  * Tell the terminal to pop the title and/or icon.
313440385dbcSBram Moolenaar  */
313540385dbcSBram Moolenaar     void
term_pop_title(int which)313640385dbcSBram Moolenaar term_pop_title(int which)
313740385dbcSBram Moolenaar {
313827821260SBram Moolenaar     if ((which & SAVE_RESTORE_TITLE) && T_CRT != NULL && *T_CRT != NUL)
313940385dbcSBram Moolenaar     {
314040385dbcSBram Moolenaar 	OUT_STR(T_CRT);
314140385dbcSBram Moolenaar 	out_flush();
314240385dbcSBram Moolenaar     }
314340385dbcSBram Moolenaar 
314427821260SBram Moolenaar     if ((which & SAVE_RESTORE_ICON) && T_SRI != NULL && *T_SRI != NUL)
314540385dbcSBram Moolenaar     {
314640385dbcSBram Moolenaar 	OUT_STR(T_SRI);
314740385dbcSBram Moolenaar 	out_flush();
314840385dbcSBram Moolenaar     }
314940385dbcSBram Moolenaar }
3150071d4279SBram Moolenaar #endif
3151071d4279SBram Moolenaar 
3152071d4279SBram Moolenaar /*
3153071d4279SBram Moolenaar  * Make sure we have a valid set or terminal options.
3154071d4279SBram Moolenaar  * Replace all entries that are NULL by empty_option
3155071d4279SBram Moolenaar  */
3156071d4279SBram Moolenaar     void
ttest(int pairs)3157764b23c8SBram Moolenaar ttest(int pairs)
3158071d4279SBram Moolenaar {
3159b7a8dfebSBram Moolenaar     char_u *env_colors;
3160b7a8dfebSBram Moolenaar 
31610d6f5d97SBram Moolenaar     check_options();		    // make sure no options are NULL
3162071d4279SBram Moolenaar 
3163071d4279SBram Moolenaar     /*
3164071d4279SBram Moolenaar      * MUST have "cm": cursor motion.
3165071d4279SBram Moolenaar      */
3166071d4279SBram Moolenaar     if (*T_CM == NUL)
3167f9e3e09fSBram Moolenaar 	emsg(_("E437: terminal capability \"cm\" required"));
3168071d4279SBram Moolenaar 
3169071d4279SBram Moolenaar     /*
3170071d4279SBram Moolenaar      * if "cs" defined, use a scroll region, it's faster.
3171071d4279SBram Moolenaar      */
3172071d4279SBram Moolenaar     if (*T_CS != NUL)
3173071d4279SBram Moolenaar 	scroll_region = TRUE;
3174071d4279SBram Moolenaar     else
3175071d4279SBram Moolenaar 	scroll_region = FALSE;
3176071d4279SBram Moolenaar 
3177071d4279SBram Moolenaar     if (pairs)
3178071d4279SBram Moolenaar     {
3179071d4279SBram Moolenaar 	/*
3180071d4279SBram Moolenaar 	 * optional pairs
3181071d4279SBram Moolenaar 	 */
31820d6f5d97SBram Moolenaar 	// TP goes to normal mode for TI (invert) and TB (bold)
3183071d4279SBram Moolenaar 	if (*T_ME == NUL)
3184071d4279SBram Moolenaar 	    T_ME = T_MR = T_MD = T_MB = empty_option;
3185071d4279SBram Moolenaar 	if (*T_SO == NUL || *T_SE == NUL)
3186071d4279SBram Moolenaar 	    T_SO = T_SE = empty_option;
3187071d4279SBram Moolenaar 	if (*T_US == NUL || *T_UE == NUL)
3188071d4279SBram Moolenaar 	    T_US = T_UE = empty_option;
3189071d4279SBram Moolenaar 	if (*T_CZH == NUL || *T_CZR == NUL)
3190071d4279SBram Moolenaar 	    T_CZH = T_CZR = empty_option;
3191071d4279SBram Moolenaar 
31920d6f5d97SBram Moolenaar 	// T_VE is needed even though T_VI is not defined
3193071d4279SBram Moolenaar 	if (*T_VE == NUL)
3194071d4279SBram Moolenaar 	    T_VI = empty_option;
3195071d4279SBram Moolenaar 
31960d6f5d97SBram Moolenaar 	// if 'mr' or 'me' is not defined use 'so' and 'se'
3197071d4279SBram Moolenaar 	if (*T_ME == NUL)
3198071d4279SBram Moolenaar 	{
3199071d4279SBram Moolenaar 	    T_ME = T_SE;
3200071d4279SBram Moolenaar 	    T_MR = T_SO;
3201071d4279SBram Moolenaar 	    T_MD = T_SO;
3202071d4279SBram Moolenaar 	}
3203071d4279SBram Moolenaar 
32040d6f5d97SBram Moolenaar 	// if 'so' or 'se' is not defined use 'mr' and 'me'
3205071d4279SBram Moolenaar 	if (*T_SO == NUL)
3206071d4279SBram Moolenaar 	{
3207071d4279SBram Moolenaar 	    T_SE = T_ME;
3208071d4279SBram Moolenaar 	    if (*T_MR == NUL)
3209071d4279SBram Moolenaar 		T_SO = T_MD;
3210071d4279SBram Moolenaar 	    else
3211071d4279SBram Moolenaar 		T_SO = T_MR;
3212071d4279SBram Moolenaar 	}
3213071d4279SBram Moolenaar 
32140d6f5d97SBram Moolenaar 	// if 'ZH' or 'ZR' is not defined use 'mr' and 'me'
3215071d4279SBram Moolenaar 	if (*T_CZH == NUL)
3216071d4279SBram Moolenaar 	{
3217071d4279SBram Moolenaar 	    T_CZR = T_ME;
3218071d4279SBram Moolenaar 	    if (*T_MR == NUL)
3219071d4279SBram Moolenaar 		T_CZH = T_MD;
3220071d4279SBram Moolenaar 	    else
3221071d4279SBram Moolenaar 		T_CZH = T_MR;
3222071d4279SBram Moolenaar 	}
3223071d4279SBram Moolenaar 
32240d6f5d97SBram Moolenaar 	// "Sb" and "Sf" come in pairs
3225071d4279SBram Moolenaar 	if (*T_CSB == NUL || *T_CSF == NUL)
3226071d4279SBram Moolenaar 	{
3227071d4279SBram Moolenaar 	    T_CSB = empty_option;
3228071d4279SBram Moolenaar 	    T_CSF = empty_option;
3229071d4279SBram Moolenaar 	}
3230071d4279SBram Moolenaar 
32310d6f5d97SBram Moolenaar 	// "AB" and "AF" come in pairs
3232071d4279SBram Moolenaar 	if (*T_CAB == NUL || *T_CAF == NUL)
3233071d4279SBram Moolenaar 	{
3234071d4279SBram Moolenaar 	    T_CAB = empty_option;
3235071d4279SBram Moolenaar 	    T_CAF = empty_option;
3236071d4279SBram Moolenaar 	}
3237071d4279SBram Moolenaar 
32380d6f5d97SBram Moolenaar 	// if 'Sb' and 'AB' are not defined, reset "Co"
3239071d4279SBram Moolenaar 	if (*T_CSB == NUL && *T_CAB == NUL)
3240363cb67aSBram Moolenaar 	    free_one_termoption(T_CCO);
3241071d4279SBram Moolenaar 
32420d6f5d97SBram Moolenaar 	// Set 'weirdinvert' according to value of 't_xs'
3243071d4279SBram Moolenaar 	p_wiv = (*T_XS != NUL);
3244071d4279SBram Moolenaar     }
3245071d4279SBram Moolenaar     need_gather = TRUE;
3246071d4279SBram Moolenaar 
3247759d8154SBram Moolenaar     // Set t_colors to the value of $COLORS or t_Co.  Ignore $COLORS in the
3248759d8154SBram Moolenaar     // GUI.
3249071d4279SBram Moolenaar     t_colors = atoi((char *)T_CCO);
3250759d8154SBram Moolenaar #ifdef FEAT_GUI
3251759d8154SBram Moolenaar     if (!gui.in_use)
3252759d8154SBram Moolenaar #endif
3253759d8154SBram Moolenaar     {
3254b7a8dfebSBram Moolenaar 	env_colors = mch_getenv((char_u *)"COLORS");
3255b7a8dfebSBram Moolenaar 	if (env_colors != NULL && isdigit(*env_colors))
3256b7a8dfebSBram Moolenaar 	{
3257b7a8dfebSBram Moolenaar 	    int colors = atoi((char *)env_colors);
3258b7a8dfebSBram Moolenaar 
3259b7a8dfebSBram Moolenaar 	    if (colors != t_colors)
3260b7a8dfebSBram Moolenaar 		set_color_count(colors);
3261b7a8dfebSBram Moolenaar 	}
3262071d4279SBram Moolenaar     }
3263759d8154SBram Moolenaar }
3264071d4279SBram Moolenaar 
3265071d4279SBram Moolenaar #if (defined(FEAT_GUI) && (defined(FEAT_MENU) || !defined(USE_ON_FLY_SCROLL))) \
3266071d4279SBram Moolenaar 	|| defined(PROTO)
3267071d4279SBram Moolenaar /*
3268071d4279SBram Moolenaar  * Represent the given long_u as individual bytes, with the most significant
3269071d4279SBram Moolenaar  * byte first, and store them in dst.
3270071d4279SBram Moolenaar  */
3271071d4279SBram Moolenaar     void
add_long_to_buf(long_u val,char_u * dst)3272764b23c8SBram Moolenaar add_long_to_buf(long_u val, char_u *dst)
3273071d4279SBram Moolenaar {
3274071d4279SBram Moolenaar     int	    i;
3275071d4279SBram Moolenaar     int	    shift;
3276071d4279SBram Moolenaar 
32772c4278fcSBram Moolenaar     for (i = 1; i <= (int)sizeof(long_u); i++)
3278071d4279SBram Moolenaar     {
3279071d4279SBram Moolenaar 	shift = 8 * (sizeof(long_u) - i);
3280071d4279SBram Moolenaar 	dst[i - 1] = (char_u) ((val >> shift) & 0xff);
3281071d4279SBram Moolenaar     }
3282071d4279SBram Moolenaar }
3283071d4279SBram Moolenaar 
3284071d4279SBram Moolenaar /*
3285071d4279SBram Moolenaar  * Interpret the next string of bytes in buf as a long integer, with the most
3286071d4279SBram Moolenaar  * significant byte first.  Note that it is assumed that buf has been through
3287071d4279SBram Moolenaar  * inchar(), so that NUL and K_SPECIAL will be represented as three bytes each.
3288071d4279SBram Moolenaar  * Puts result in val, and returns the number of bytes read from buf
3289071d4279SBram Moolenaar  * (between sizeof(long_u) and 2 * sizeof(long_u)), or -1 if not enough bytes
3290071d4279SBram Moolenaar  * were present.
3291071d4279SBram Moolenaar  */
3292071d4279SBram Moolenaar     static int
get_long_from_buf(char_u * buf,long_u * val)3293764b23c8SBram Moolenaar get_long_from_buf(char_u *buf, long_u *val)
3294071d4279SBram Moolenaar {
3295071d4279SBram Moolenaar     int	    len;
3296071d4279SBram Moolenaar     char_u  bytes[sizeof(long_u)];
3297071d4279SBram Moolenaar     int	    i;
3298071d4279SBram Moolenaar     int	    shift;
3299071d4279SBram Moolenaar 
3300071d4279SBram Moolenaar     *val = 0;
3301071d4279SBram Moolenaar     len = get_bytes_from_buf(buf, bytes, (int)sizeof(long_u));
3302071d4279SBram Moolenaar     if (len != -1)
3303071d4279SBram Moolenaar     {
33042c4278fcSBram Moolenaar 	for (i = 0; i < (int)sizeof(long_u); i++)
3305071d4279SBram Moolenaar 	{
3306071d4279SBram Moolenaar 	    shift = 8 * (sizeof(long_u) - 1 - i);
3307071d4279SBram Moolenaar 	    *val += (long_u)bytes[i] << shift;
3308071d4279SBram Moolenaar 	}
3309071d4279SBram Moolenaar     }
3310071d4279SBram Moolenaar     return len;
3311071d4279SBram Moolenaar }
3312071d4279SBram Moolenaar #endif
3313071d4279SBram Moolenaar 
3314071d4279SBram Moolenaar /*
3315071d4279SBram Moolenaar  * Read the next num_bytes bytes from buf, and store them in bytes.  Assume
3316071d4279SBram Moolenaar  * that buf has been through inchar().	Returns the actual number of bytes used
3317071d4279SBram Moolenaar  * from buf (between num_bytes and num_bytes*2), or -1 if not enough bytes were
3318071d4279SBram Moolenaar  * available.
3319071d4279SBram Moolenaar  */
3320b8ff5c27SBram Moolenaar     int
get_bytes_from_buf(char_u * buf,char_u * bytes,int num_bytes)3321764b23c8SBram Moolenaar get_bytes_from_buf(char_u *buf, char_u *bytes, int num_bytes)
3322071d4279SBram Moolenaar {
3323071d4279SBram Moolenaar     int	    len = 0;
3324071d4279SBram Moolenaar     int	    i;
3325071d4279SBram Moolenaar     char_u  c;
3326071d4279SBram Moolenaar 
3327071d4279SBram Moolenaar     for (i = 0; i < num_bytes; i++)
3328071d4279SBram Moolenaar     {
3329071d4279SBram Moolenaar 	if ((c = buf[len++]) == NUL)
3330071d4279SBram Moolenaar 	    return -1;
3331071d4279SBram Moolenaar 	if (c == K_SPECIAL)
3332071d4279SBram Moolenaar 	{
33330d6f5d97SBram Moolenaar 	    if (buf[len] == NUL || buf[len + 1] == NUL)	    // cannot happen?
3334071d4279SBram Moolenaar 		return -1;
3335071d4279SBram Moolenaar 	    if (buf[len++] == (int)KS_ZERO)
3336071d4279SBram Moolenaar 		c = NUL;
33370d6f5d97SBram Moolenaar 	    // else it should be KS_SPECIAL; when followed by KE_FILLER c is
33380d6f5d97SBram Moolenaar 	    // K_SPECIAL, or followed by KE_CSI and c must be CSI.
33390e710d60SBram Moolenaar 	    if (buf[len++] == (int)KE_CSI)
33400e710d60SBram Moolenaar 		c = CSI;
3341071d4279SBram Moolenaar 	}
33428d1ab51eSBram Moolenaar 	else if (c == CSI && buf[len] == KS_EXTRA
33438d1ab51eSBram Moolenaar 					       && buf[len + 1] == (int)KE_CSI)
33440d6f5d97SBram Moolenaar 	    // CSI is stored as CSI KS_SPECIAL KE_CSI to avoid confusion with
33450d6f5d97SBram Moolenaar 	    // the start of a special key, see add_to_input_buf_csi().
33461d2ba7faSBram Moolenaar 	    len += 2;
3347071d4279SBram Moolenaar 	bytes[i] = c;
3348071d4279SBram Moolenaar     }
3349071d4279SBram Moolenaar     return len;
3350071d4279SBram Moolenaar }
3351071d4279SBram Moolenaar 
3352071d4279SBram Moolenaar /*
3353e057d40dSBram Moolenaar  * Check if the new shell size is valid, correct it if it's too small or way
3354e057d40dSBram Moolenaar  * too big.
3355071d4279SBram Moolenaar  */
3356071d4279SBram Moolenaar     void
check_shellsize(void)3357764b23c8SBram Moolenaar check_shellsize(void)
3358071d4279SBram Moolenaar {
33590d6f5d97SBram Moolenaar     if (Rows < min_rows())	// need room for one window and command line
3360071d4279SBram Moolenaar 	Rows = min_rows();
3361e057d40dSBram Moolenaar     limit_screen_size();
3362e057d40dSBram Moolenaar }
3363e057d40dSBram Moolenaar 
3364e057d40dSBram Moolenaar /*
3365e057d40dSBram Moolenaar  * Limit Rows and Columns to avoid an overflow in Rows * Columns.
3366e057d40dSBram Moolenaar  */
3367e057d40dSBram Moolenaar     void
limit_screen_size(void)3368764b23c8SBram Moolenaar limit_screen_size(void)
3369e057d40dSBram Moolenaar {
3370e057d40dSBram Moolenaar     if (Columns < MIN_COLUMNS)
3371e057d40dSBram Moolenaar 	Columns = MIN_COLUMNS;
3372e057d40dSBram Moolenaar     else if (Columns > 10000)
3373e057d40dSBram Moolenaar 	Columns = 10000;
3374e057d40dSBram Moolenaar     if (Rows > 1000)
3375e057d40dSBram Moolenaar 	Rows = 1000;
3376071d4279SBram Moolenaar }
3377071d4279SBram Moolenaar 
337886b68359SBram Moolenaar /*
337986b68359SBram Moolenaar  * Invoked just before the screen structures are going to be (re)allocated.
338086b68359SBram Moolenaar  */
3381071d4279SBram Moolenaar     void
win_new_shellsize(void)3382764b23c8SBram Moolenaar win_new_shellsize(void)
3383071d4279SBram Moolenaar {
3384071d4279SBram Moolenaar     static int	old_Rows = 0;
3385071d4279SBram Moolenaar     static int	old_Columns = 0;
3386071d4279SBram Moolenaar 
3387071d4279SBram Moolenaar     if (old_Rows != Rows || old_Columns != Columns)
3388071d4279SBram Moolenaar 	ui_new_shellsize();
3389071d4279SBram Moolenaar     if (old_Rows != Rows)
3390071d4279SBram Moolenaar     {
33910a1a6a1aSBram Moolenaar 	// If 'window' uses the whole screen, keep it using that.
33920a1a6a1aSBram Moolenaar 	// Don't change it when set with "-w size" on the command line.
33930a1a6a1aSBram Moolenaar 	if (p_window == old_Rows - 1 || (old_Rows == 0 && p_window == 0))
33944399ef47SBram Moolenaar 	    p_window = Rows - 1;
3395071d4279SBram Moolenaar 	old_Rows = Rows;
33960d6f5d97SBram Moolenaar 	shell_new_rows();	// update window sizes
3397071d4279SBram Moolenaar     }
3398071d4279SBram Moolenaar     if (old_Columns != Columns)
3399071d4279SBram Moolenaar     {
3400071d4279SBram Moolenaar 	old_Columns = Columns;
34010d6f5d97SBram Moolenaar 	shell_new_columns();	// update window sizes
3402071d4279SBram Moolenaar     }
3403071d4279SBram Moolenaar }
3404071d4279SBram Moolenaar 
3405071d4279SBram Moolenaar /*
3406071d4279SBram Moolenaar  * Call this function when the Vim shell has been resized in any way.
3407071d4279SBram Moolenaar  * Will obtain the current size and redraw (also when size didn't change).
3408071d4279SBram Moolenaar  */
3409071d4279SBram Moolenaar     void
shell_resized(void)3410764b23c8SBram Moolenaar shell_resized(void)
3411071d4279SBram Moolenaar {
3412071d4279SBram Moolenaar     set_shellsize(0, 0, FALSE);
3413071d4279SBram Moolenaar }
3414071d4279SBram Moolenaar 
3415071d4279SBram Moolenaar /*
3416071d4279SBram Moolenaar  * Check if the shell size changed.  Handle a resize.
3417071d4279SBram Moolenaar  * When the size didn't change, nothing happens.
3418071d4279SBram Moolenaar  */
3419071d4279SBram Moolenaar     void
shell_resized_check(void)3420764b23c8SBram Moolenaar shell_resized_check(void)
3421071d4279SBram Moolenaar {
3422071d4279SBram Moolenaar     int		old_Rows = Rows;
3423071d4279SBram Moolenaar     int		old_Columns = Columns;
3424071d4279SBram Moolenaar 
34253633dc01SBram Moolenaar     if (!exiting
34263633dc01SBram Moolenaar #ifdef FEAT_GUI
34270d6f5d97SBram Moolenaar 	    // Do not get the size when executing a shell command during
34280d6f5d97SBram Moolenaar 	    // startup.
34293633dc01SBram Moolenaar 	    && !gui.starting
34303633dc01SBram Moolenaar #endif
34313633dc01SBram Moolenaar 	    )
34329980835cSBram Moolenaar     {
3433071d4279SBram Moolenaar 	(void)ui_get_shellsize();
3434071d4279SBram Moolenaar 	check_shellsize();
3435071d4279SBram Moolenaar 	if (old_Rows != Rows || old_Columns != Columns)
3436071d4279SBram Moolenaar 	    shell_resized();
3437071d4279SBram Moolenaar     }
34389980835cSBram Moolenaar }
3439071d4279SBram Moolenaar 
3440071d4279SBram Moolenaar /*
3441071d4279SBram Moolenaar  * Set size of the Vim shell.
3442071d4279SBram Moolenaar  * If 'mustset' is TRUE, we must set Rows and Columns, do not get the real
3443071d4279SBram Moolenaar  * window size (this is used for the :win command).
3444071d4279SBram Moolenaar  * If 'mustset' is FALSE, we may try to get the real window size and if
3445071d4279SBram Moolenaar  * it fails use 'width' and 'height'.
3446071d4279SBram Moolenaar  */
3447071d4279SBram Moolenaar     void
set_shellsize(int width,int height,int mustset)3448764b23c8SBram Moolenaar set_shellsize(int width, int height, int mustset)
3449071d4279SBram Moolenaar {
3450071d4279SBram Moolenaar     static int		busy = FALSE;
3451071d4279SBram Moolenaar 
3452071d4279SBram Moolenaar     /*
3453071d4279SBram Moolenaar      * Avoid recursiveness, can happen when setting the window size causes
3454071d4279SBram Moolenaar      * another window-changed signal.
3455071d4279SBram Moolenaar      */
3456071d4279SBram Moolenaar     if (busy)
3457071d4279SBram Moolenaar 	return;
3458071d4279SBram Moolenaar 
34590d6f5d97SBram Moolenaar     if (width < 0 || height < 0)    // just checking...
3460071d4279SBram Moolenaar 	return;
3461071d4279SBram Moolenaar 
3462a971b82bSBram Moolenaar     if (State == HITRETURN || State == SETWSIZE)
3463071d4279SBram Moolenaar     {
3464847a5d69SBram Moolenaar 	// postpone the resizing
3465071d4279SBram Moolenaar 	State = SETWSIZE;
3466071d4279SBram Moolenaar 	return;
3467071d4279SBram Moolenaar     }
3468071d4279SBram Moolenaar 
3469847a5d69SBram Moolenaar     if (updating_screen)
3470847a5d69SBram Moolenaar 	// resizing while in update_screen() may cause a crash
3471847a5d69SBram Moolenaar 	return;
3472847a5d69SBram Moolenaar 
34730d6f5d97SBram Moolenaar     // curwin->w_buffer can be NULL when we are closing a window and the
34742808da39SBram Moolenaar     // buffer (or window) has already been closed and removing a scrollbar
34752808da39SBram Moolenaar     // causes a resize event. Don't resize then, it will happen after entering
34762808da39SBram Moolenaar     // another buffer.
34772808da39SBram Moolenaar     if (curwin->w_buffer == NULL || curwin->w_lines == NULL)
3478a971b82bSBram Moolenaar 	return;
3479a971b82bSBram Moolenaar 
3480071d4279SBram Moolenaar     ++busy;
3481071d4279SBram Moolenaar 
3482071d4279SBram Moolenaar #ifdef AMIGA
34830d6f5d97SBram Moolenaar     out_flush();	    // must do this before mch_get_shellsize() for
34840d6f5d97SBram Moolenaar 			    // some obscure reason
3485071d4279SBram Moolenaar #endif
3486071d4279SBram Moolenaar 
3487071d4279SBram Moolenaar     if (mustset || (ui_get_shellsize() == FAIL && height != 0))
3488071d4279SBram Moolenaar     {
3489071d4279SBram Moolenaar 	Rows = height;
3490071d4279SBram Moolenaar 	Columns = width;
3491071d4279SBram Moolenaar 	check_shellsize();
3492071d4279SBram Moolenaar 	ui_set_shellsize(mustset);
3493071d4279SBram Moolenaar     }
3494071d4279SBram Moolenaar     else
3495071d4279SBram Moolenaar 	check_shellsize();
3496071d4279SBram Moolenaar 
34970d6f5d97SBram Moolenaar     // The window layout used to be adjusted here, but it now happens in
34980d6f5d97SBram Moolenaar     // screenalloc() (also invoked from screenclear()).  That is because the
34990d6f5d97SBram Moolenaar     // "busy" check above may skip this, but not screenalloc().
3500071d4279SBram Moolenaar 
3501071d4279SBram Moolenaar     if (State != ASKMORE && State != EXTERNCMD && State != CONFIRM)
3502071d4279SBram Moolenaar 	screenclear();
3503071d4279SBram Moolenaar     else
35040d6f5d97SBram Moolenaar 	screen_start();	    // don't know where cursor is now
3505071d4279SBram Moolenaar 
3506071d4279SBram Moolenaar     if (starting != NO_SCREEN)
3507071d4279SBram Moolenaar     {
3508071d4279SBram Moolenaar #ifdef FEAT_TITLE
3509071d4279SBram Moolenaar 	maketitle();
3510071d4279SBram Moolenaar #endif
3511071d4279SBram Moolenaar 	changed_line_abv_curs();
3512071d4279SBram Moolenaar 	invalidate_botline();
3513071d4279SBram Moolenaar 
3514071d4279SBram Moolenaar 	/*
3515071d4279SBram Moolenaar 	 * We only redraw when it's needed:
3516071d4279SBram Moolenaar 	 * - While at the more prompt or executing an external command, don't
3517071d4279SBram Moolenaar 	 *   redraw, but position the cursor.
3518071d4279SBram Moolenaar 	 * - While editing the command line, only redraw that.
3519071d4279SBram Moolenaar 	 * - in Ex mode, don't redraw anything.
3520071d4279SBram Moolenaar 	 * - Otherwise, redraw right now, and position the cursor.
3521071d4279SBram Moolenaar 	 * Always need to call update_screen() or screenalloc(), to make
3522071d4279SBram Moolenaar 	 * sure Rows/Columns and the size of ScreenLines[] is correct!
3523071d4279SBram Moolenaar 	 */
3524071d4279SBram Moolenaar 	if (State == ASKMORE || State == EXTERNCMD || State == CONFIRM
3525071d4279SBram Moolenaar 							     || exmode_active)
3526071d4279SBram Moolenaar 	{
3527071d4279SBram Moolenaar 	    screenalloc(FALSE);
3528071d4279SBram Moolenaar 	    repeat_message();
3529071d4279SBram Moolenaar 	}
353009ef47a3SBram Moolenaar 	else
353109ef47a3SBram Moolenaar 	{
353209ef47a3SBram Moolenaar 	    if (curwin->w_p_scb)
353309ef47a3SBram Moolenaar 		do_check_scrollbind(TRUE);
353409ef47a3SBram Moolenaar 	    if (State & CMDLINE)
3535071d4279SBram Moolenaar 	    {
3536071d4279SBram Moolenaar 		update_screen(NOT_VALID);
3537071d4279SBram Moolenaar 		redrawcmdline();
3538071d4279SBram Moolenaar 	    }
3539071d4279SBram Moolenaar 	    else
3540071d4279SBram Moolenaar 	    {
3541071d4279SBram Moolenaar 		update_topline();
3542280f126eSBram Moolenaar 		if (pum_visible())
3543280f126eSBram Moolenaar 		{
3544280f126eSBram Moolenaar 		    redraw_later(NOT_VALID);
3545a5e6621aSBram Moolenaar 		    ins_compl_show_pum();
3546280f126eSBram Moolenaar 		}
3547071d4279SBram Moolenaar 		update_screen(NOT_VALID);
3548071d4279SBram Moolenaar 		if (redrawing())
3549071d4279SBram Moolenaar 		    setcursor();
3550071d4279SBram Moolenaar 	    }
355109ef47a3SBram Moolenaar 	}
35520d6f5d97SBram Moolenaar 	cursor_on();	    // redrawing may have switched it off
3553071d4279SBram Moolenaar     }
3554071d4279SBram Moolenaar     out_flush();
3555071d4279SBram Moolenaar     --busy;
3556071d4279SBram Moolenaar }
3557071d4279SBram Moolenaar 
3558071d4279SBram Moolenaar /*
3559071d4279SBram Moolenaar  * Set the terminal to TMODE_RAW (for Normal mode) or TMODE_COOK (for external
3560071d4279SBram Moolenaar  * commands and Ex mode).
3561071d4279SBram Moolenaar  */
3562071d4279SBram Moolenaar     void
settmode(tmode_T tmode)3563f4e16ae0SBram Moolenaar settmode(tmode_T tmode)
3564071d4279SBram Moolenaar {
3565071d4279SBram Moolenaar #ifdef FEAT_GUI
35660d6f5d97SBram Moolenaar     // don't set the term where gvim was started to any mode
3567071d4279SBram Moolenaar     if (gui.in_use)
3568071d4279SBram Moolenaar 	return;
3569071d4279SBram Moolenaar #endif
3570071d4279SBram Moolenaar 
3571071d4279SBram Moolenaar     if (full_screen)
3572071d4279SBram Moolenaar     {
3573071d4279SBram Moolenaar 	/*
35743b1f18f7SBram Moolenaar 	 * When returning after calling a shell cur_tmode is TMODE_UNKNOWN,
35753b1f18f7SBram Moolenaar 	 * set the terminal to raw mode, even though we think it already is,
35763b1f18f7SBram Moolenaar 	 * because the shell program may have reset the terminal mode.
3577071d4279SBram Moolenaar 	 * When we think the terminal is normal, don't try to set it to
3578071d4279SBram Moolenaar 	 * normal again, because that causes problems (logout!) on some
3579071d4279SBram Moolenaar 	 * machines.
3580071d4279SBram Moolenaar 	 */
35813b1f18f7SBram Moolenaar 	if (tmode != cur_tmode)
3582071d4279SBram Moolenaar 	{
3583071d4279SBram Moolenaar #ifdef FEAT_TERMRESPONSE
35842bf6a2d7SBram Moolenaar # ifdef FEAT_GUI
35852bf6a2d7SBram Moolenaar 	    if (!gui.in_use && !gui.starting)
35862bf6a2d7SBram Moolenaar # endif
35872bf6a2d7SBram Moolenaar 	    {
3588afd78266SBram Moolenaar 		// May need to check for T_CRV response and termcodes, it
3589afd78266SBram Moolenaar 		// doesn't work in Cooked mode, an external program may get
3590afd78266SBram Moolenaar 		// them.
3591afd78266SBram Moolenaar 		if (tmode != TMODE_RAW && termrequest_any_pending())
3592071d4279SBram Moolenaar 		    (void)vpeekc_nomap();
3593071d4279SBram Moolenaar 		check_for_codes_from_term();
35942bf6a2d7SBram Moolenaar 	    }
3595071d4279SBram Moolenaar #endif
3596071d4279SBram Moolenaar 	    if (tmode != TMODE_RAW)
3597958eabe5SBram Moolenaar 		mch_setmouse(FALSE);	// switch mouse off
359826e86445SBram Moolenaar 
359926e86445SBram Moolenaar 	    // Disable bracketed paste and modifyOtherKeys in cooked mode.
360026e86445SBram Moolenaar 	    // Avoid doing this too often, on some terminals the codes are not
360126e86445SBram Moolenaar 	    // handled properly.
360226e86445SBram Moolenaar 	    if (termcap_active && tmode != TMODE_SLEEP
360326e86445SBram Moolenaar 						   && cur_tmode != TMODE_SLEEP)
3604958eabe5SBram Moolenaar 	    {
360586394aa9SBram Moolenaar #ifdef FEAT_JOB_CHANNEL
360686394aa9SBram Moolenaar 		ch_log_output = TRUE;
360786394aa9SBram Moolenaar #endif
360862cf09b5SBram Moolenaar 		if (tmode != TMODE_RAW)
3609645e3fe3SBram Moolenaar 		{
3610958eabe5SBram Moolenaar 		    out_str(T_BD);	// disable bracketed paste mode
3611645e3fe3SBram Moolenaar 		    out_str(T_CTE);	// possibly disables modifyOtherKeys
3612645e3fe3SBram Moolenaar 		}
3613958eabe5SBram Moolenaar 		else
3614645e3fe3SBram Moolenaar 		{
3615958eabe5SBram Moolenaar 		    out_str(T_BE);	// enable bracketed paste mode (should
3616958eabe5SBram Moolenaar 					// be before mch_settmode().
3617645e3fe3SBram Moolenaar 		    out_str(T_CTI);	// possibly enables modifyOtherKeys
3618645e3fe3SBram Moolenaar 		}
3619958eabe5SBram Moolenaar 	    }
3620071d4279SBram Moolenaar 	    out_flush();
3621958eabe5SBram Moolenaar 	    mch_settmode(tmode);	// machine specific function
3622071d4279SBram Moolenaar 	    cur_tmode = tmode;
3623071d4279SBram Moolenaar 	    if (tmode == TMODE_RAW)
3624958eabe5SBram Moolenaar 		setmouse();		// may switch mouse on
3625071d4279SBram Moolenaar 	    out_flush();
3626071d4279SBram Moolenaar 	}
3627071d4279SBram Moolenaar #ifdef FEAT_TERMRESPONSE
3628071d4279SBram Moolenaar 	may_req_termresponse();
3629071d4279SBram Moolenaar #endif
3630071d4279SBram Moolenaar     }
3631071d4279SBram Moolenaar }
3632071d4279SBram Moolenaar 
3633071d4279SBram Moolenaar     void
starttermcap(void)3634764b23c8SBram Moolenaar starttermcap(void)
3635071d4279SBram Moolenaar {
3636071d4279SBram Moolenaar     if (full_screen && !termcap_active)
3637071d4279SBram Moolenaar     {
363886394aa9SBram Moolenaar #ifdef FEAT_JOB_CHANNEL
363986394aa9SBram Moolenaar 	ch_log_output = TRUE;
364086394aa9SBram Moolenaar #endif
36410d6f5d97SBram Moolenaar 	out_str(T_TI);			// start termcap mode
36420d6f5d97SBram Moolenaar 	out_str(T_CTI);			// start "raw" mode
36430d6f5d97SBram Moolenaar 	out_str(T_KS);			// start "keypad transmit" mode
36440d6f5d97SBram Moolenaar 	out_str(T_BE);			// enable bracketed paste mode
3645681fc3faSBram Moolenaar 
364651b477f7SBram Moolenaar #if defined(UNIX) || defined(VMS)
364751b477f7SBram Moolenaar 	// Enable xterm's focus reporting mode when 'esckeys' is set.
364851b477f7SBram Moolenaar 	if (focus_mode && p_ek && *T_FE != NUL)
3649681fc3faSBram Moolenaar 	    out_str(T_FE);
3650681fc3faSBram Moolenaar #endif
3651681fc3faSBram Moolenaar 
3652071d4279SBram Moolenaar 	out_flush();
3653071d4279SBram Moolenaar 	termcap_active = TRUE;
36540d6f5d97SBram Moolenaar 	screen_start();			// don't know where cursor is now
3655071d4279SBram Moolenaar #ifdef FEAT_TERMRESPONSE
36562bf6a2d7SBram Moolenaar # ifdef FEAT_GUI
36572bf6a2d7SBram Moolenaar 	if (!gui.in_use && !gui.starting)
36582bf6a2d7SBram Moolenaar # endif
36592bf6a2d7SBram Moolenaar 	{
3660071d4279SBram Moolenaar 	    may_req_termresponse();
36610d6f5d97SBram Moolenaar 	    // Immediately check for a response.  If t_Co changes, we don't
36620d6f5d97SBram Moolenaar 	    // want to redraw with wrong colors first.
3663afd78266SBram Moolenaar 	    if (crv_status.tr_progress == STATUS_SENT)
3664071d4279SBram Moolenaar 		check_for_codes_from_term();
36652bf6a2d7SBram Moolenaar 	}
3666071d4279SBram Moolenaar #endif
3667071d4279SBram Moolenaar     }
3668071d4279SBram Moolenaar }
3669071d4279SBram Moolenaar 
3670071d4279SBram Moolenaar     void
stoptermcap(void)3671764b23c8SBram Moolenaar stoptermcap(void)
3672071d4279SBram Moolenaar {
3673071d4279SBram Moolenaar     screen_stop_highlight();
3674071d4279SBram Moolenaar     reset_cterm_colors();
3675071d4279SBram Moolenaar     if (termcap_active)
3676071d4279SBram Moolenaar     {
3677071d4279SBram Moolenaar #ifdef FEAT_TERMRESPONSE
36782bf6a2d7SBram Moolenaar # ifdef FEAT_GUI
36792bf6a2d7SBram Moolenaar 	if (!gui.in_use && !gui.starting)
36802bf6a2d7SBram Moolenaar # endif
36812bf6a2d7SBram Moolenaar 	{
3682afd78266SBram Moolenaar 	    // May need to discard T_CRV, T_U7 or T_RBG response.
3683afd78266SBram Moolenaar 	    if (termrequest_any_pending())
368429607acfSBram Moolenaar 	    {
368529607acfSBram Moolenaar # ifdef UNIX
3686afd78266SBram Moolenaar 		// Give the terminal a chance to respond.
36870981c872SBram Moolenaar 		mch_delay(100L, 0);
368829607acfSBram Moolenaar # endif
368929607acfSBram Moolenaar # ifdef TCIFLUSH
3690afd78266SBram Moolenaar 		// Discard data received but not read.
369129607acfSBram Moolenaar 		if (exiting)
369229607acfSBram Moolenaar 		    tcflush(fileno(stdin), TCIFLUSH);
369329607acfSBram Moolenaar # endif
369429607acfSBram Moolenaar 	    }
36950d6f5d97SBram Moolenaar 	    // Check for termcodes first, otherwise an external program may
36960d6f5d97SBram Moolenaar 	    // get them.
3697071d4279SBram Moolenaar 	    check_for_codes_from_term();
36982bf6a2d7SBram Moolenaar 	}
3699071d4279SBram Moolenaar #endif
370086394aa9SBram Moolenaar #ifdef FEAT_JOB_CHANNEL
370186394aa9SBram Moolenaar 	ch_log_output = TRUE;
370286394aa9SBram Moolenaar #endif
3703681fc3faSBram Moolenaar 
370451b477f7SBram Moolenaar #if defined(UNIX) || defined(VMS)
370551b477f7SBram Moolenaar 	// Disable xterm's focus reporting mode if 'esckeys' is set.
370651b477f7SBram Moolenaar 	if (focus_mode && p_ek && *T_FD != NUL)
3707681fc3faSBram Moolenaar 	    out_str(T_FD);
3708681fc3faSBram Moolenaar #endif
3709681fc3faSBram Moolenaar 
37100d6f5d97SBram Moolenaar 	out_str(T_BD);			// disable bracketed paste mode
37110d6f5d97SBram Moolenaar 	out_str(T_KE);			// stop "keypad transmit" mode
3712071d4279SBram Moolenaar 	out_flush();
3713071d4279SBram Moolenaar 	termcap_active = FALSE;
37140d6f5d97SBram Moolenaar 	cursor_on();			// just in case it is still off
37150d6f5d97SBram Moolenaar 	out_str(T_CTE);			// stop "raw" mode
37160d6f5d97SBram Moolenaar 	out_str(T_TE);			// stop termcap mode
37170d6f5d97SBram Moolenaar 	screen_start();			// don't know where cursor is now
3718071d4279SBram Moolenaar 	out_flush();
3719071d4279SBram Moolenaar     }
3720071d4279SBram Moolenaar }
3721071d4279SBram Moolenaar 
3722cbc17d66SBram Moolenaar #if defined(FEAT_TERMRESPONSE) || defined(PROTO)
3723071d4279SBram Moolenaar /*
3724071d4279SBram Moolenaar  * Request version string (for xterm) when needed.
3725071d4279SBram Moolenaar  * Only do this after switching to raw mode, otherwise the result will be
3726071d4279SBram Moolenaar  * echoed.
3727a40ceaf8SBram Moolenaar  * Only do this after startup has finished, to avoid that the response comes
3728cf0dfa2fSBram Moolenaar  * while executing "-c !cmd" or even after "-c quit".
3729071d4279SBram Moolenaar  * Only do this after termcap mode has been started, otherwise the codes for
3730071d4279SBram Moolenaar  * the cursor keys may be wrong.
3731ebefac63SBram Moolenaar  * Only do this when 'esckeys' is on, otherwise the response causes trouble in
3732ebefac63SBram Moolenaar  * Insert mode.
37334399ef47SBram Moolenaar  * On Unix only do it when both output and input are a tty (avoid writing
37344399ef47SBram Moolenaar  * request to terminal while reading from a file).
3735071d4279SBram Moolenaar  * The result is caught in check_termcode().
3736071d4279SBram Moolenaar  */
3737a40ceaf8SBram Moolenaar     void
may_req_termresponse(void)3738764b23c8SBram Moolenaar may_req_termresponse(void)
3739071d4279SBram Moolenaar {
3740afd78266SBram Moolenaar     if (crv_status.tr_progress == STATUS_GET
3741ba6ec182SBram Moolenaar 	    && can_get_termresponse()
3742a40ceaf8SBram Moolenaar 	    && starting == 0
3743071d4279SBram Moolenaar 	    && *T_CRV != NUL)
3744071d4279SBram Moolenaar     {
374586394aa9SBram Moolenaar #ifdef FEAT_JOB_CHANNEL
374686394aa9SBram Moolenaar 	ch_log_output = TRUE;
374786394aa9SBram Moolenaar #endif
3748b255b905SBram Moolenaar 	LOG_TR(("Sending CRV request"));
3749071d4279SBram Moolenaar 	out_str(T_CRV);
3750afd78266SBram Moolenaar 	termrequest_sent(&crv_status);
37510d6f5d97SBram Moolenaar 	// check for the characters now, otherwise they might be eaten by
37520d6f5d97SBram Moolenaar 	// get_keystroke()
3753071d4279SBram Moolenaar 	out_flush();
3754071d4279SBram Moolenaar 	(void)vpeekc_nomap();
3755071d4279SBram Moolenaar     }
3756071d4279SBram Moolenaar }
37579584b31aSBram Moolenaar 
37589584b31aSBram Moolenaar /*
3759a45551a5SBram Moolenaar  * Send sequences to the terminal and check with t_u7 how the cursor moves, to
3760a45551a5SBram Moolenaar  * find out properties of the terminal.
3761517f00f7SBram Moolenaar  * Note that this goes out before T_CRV, so that the result can be used when
3762517f00f7SBram Moolenaar  * the termresponse arrives.
37639584b31aSBram Moolenaar  */
37649584b31aSBram Moolenaar     void
check_terminal_behavior(void)3765a45551a5SBram Moolenaar check_terminal_behavior(void)
37669584b31aSBram Moolenaar {
3767a45551a5SBram Moolenaar     int	    did_send = FALSE;
3768a45551a5SBram Moolenaar 
3769a45551a5SBram Moolenaar     if (!can_get_termresponse() || starting != 0 || *T_U7 == NUL)
3770a45551a5SBram Moolenaar 	return;
3771a45551a5SBram Moolenaar 
3772afd78266SBram Moolenaar     if (u7_status.tr_progress == STATUS_GET
37739584b31aSBram Moolenaar 	    && !option_was_set((char_u *)"ambiwidth"))
37749584b31aSBram Moolenaar     {
37759584b31aSBram Moolenaar 	char_u	buf[16];
37769584b31aSBram Moolenaar 
3777a45551a5SBram Moolenaar 	// Ambiguous width check.
3778a45551a5SBram Moolenaar 	// Check how the terminal treats ambiguous character width (UAX #11).
3779a45551a5SBram Moolenaar 	// First, we move the cursor to (1, 0) and print a test ambiguous
3780a45551a5SBram Moolenaar 	// character \u25bd (WHITE DOWN-POINTING TRIANGLE) and then query
3781a45551a5SBram Moolenaar 	// the current cursor position.  If the terminal treats \u25bd as
3782a45551a5SBram Moolenaar 	// single width, the position is (1, 1), or if it is treated as double
3783a45551a5SBram Moolenaar 	// width, that will be (1, 2).  This function has the side effect that
3784a45551a5SBram Moolenaar 	// changes cursor position, so it must be called immediately after
3785a45551a5SBram Moolenaar 	// entering termcap mode.
378686394aa9SBram Moolenaar #ifdef FEAT_JOB_CHANNEL
378786394aa9SBram Moolenaar 	ch_log_output = TRUE;
378886394aa9SBram Moolenaar #endif
3789a45551a5SBram Moolenaar 	LOG_TR(("Sending request for ambiwidth check"));
37900d6f5d97SBram Moolenaar 	// Do this in the second row.  In the first row the returned sequence
37910d6f5d97SBram Moolenaar 	// may be CSI 1;2R, which is the same as <S-F3>.
37922951b77eSBram Moolenaar 	term_windgoto(1, 0);
3793a45551a5SBram Moolenaar 	buf[mb_char2bytes(0x25bd, buf)] = NUL;
37949584b31aSBram Moolenaar 	out_str(buf);
37959584b31aSBram Moolenaar 	out_str(T_U7);
3796afd78266SBram Moolenaar 	termrequest_sent(&u7_status);
37979c8c8c5dSBram Moolenaar 	out_flush();
3798a45551a5SBram Moolenaar 	did_send = TRUE;
3799976787d1SBram Moolenaar 
38000d6f5d97SBram Moolenaar 	// This overwrites a few characters on the screen, a redraw is needed
38010d6f5d97SBram Moolenaar 	// after this. Clear them out for now.
380206029a85SBram Moolenaar 	screen_stop_highlight();
38039c8c8c5dSBram Moolenaar 	term_windgoto(1, 0);
38049584b31aSBram Moolenaar 	out_str((char_u *)"  ");
380596916ac6SBram Moolenaar 	line_was_clobbered(1);
3806a45551a5SBram Moolenaar     }
3807a45551a5SBram Moolenaar 
3808a45551a5SBram Moolenaar     if (xcc_status.tr_progress == STATUS_GET)
3809a45551a5SBram Moolenaar     {
3810a45551a5SBram Moolenaar 	// 2. Check compatibility with xterm.
3811a45551a5SBram Moolenaar 	// We move the cursor to (2, 0), print a test sequence and then query
3812a45551a5SBram Moolenaar 	// the current cursor position.  If the terminal properly handles
3813a45551a5SBram Moolenaar 	// unknown DCS string and CSI sequence with intermediate byte, the test
3814a45551a5SBram Moolenaar 	// sequence is ignored and the cursor does not move.  If the terminal
3815a45551a5SBram Moolenaar 	// handles test sequence incorrectly, a garbage string is displayed and
3816a45551a5SBram Moolenaar 	// the cursor does move.
381786394aa9SBram Moolenaar #ifdef FEAT_JOB_CHANNEL
381886394aa9SBram Moolenaar 	ch_log_output = TRUE;
381986394aa9SBram Moolenaar #endif
3820a45551a5SBram Moolenaar 	LOG_TR(("Sending xterm compatibility test sequence."));
3821a45551a5SBram Moolenaar 	// Do this in the third row.  Second row is used by ambiguous
38228e7d6223SBram Moolenaar 	// character width check.
3823a45551a5SBram Moolenaar 	term_windgoto(2, 0);
3824a45551a5SBram Moolenaar 	// send the test DCS string.
3825a45551a5SBram Moolenaar 	out_str((char_u *)"\033Pzz\033\\");
3826a45551a5SBram Moolenaar 	// send the test CSI sequence with intermediate byte.
3827a45551a5SBram Moolenaar 	out_str((char_u *)"\033[0%m");
3828a45551a5SBram Moolenaar 	out_str(T_U7);
3829a45551a5SBram Moolenaar 	termrequest_sent(&xcc_status);
3830a45551a5SBram Moolenaar 	out_flush();
3831a45551a5SBram Moolenaar 	did_send = TRUE;
3832a45551a5SBram Moolenaar 
3833a45551a5SBram Moolenaar 	// If the terminal handles test sequence incorrectly, garbage text is
3834a45551a5SBram Moolenaar 	// displayed. Clear them out for now.
3835a45551a5SBram Moolenaar 	screen_stop_highlight();
3836a45551a5SBram Moolenaar 	term_windgoto(2, 0);
3837a45551a5SBram Moolenaar 	out_str((char_u *)"           ");
383896916ac6SBram Moolenaar 	line_was_clobbered(2);
3839a45551a5SBram Moolenaar     }
3840a45551a5SBram Moolenaar 
3841a45551a5SBram Moolenaar     if (did_send)
3842a45551a5SBram Moolenaar     {
38439584b31aSBram Moolenaar 	term_windgoto(0, 0);
3844976787d1SBram Moolenaar 
38450d6f5d97SBram Moolenaar 	// Need to reset the known cursor position.
384605684310SBram Moolenaar 	screen_start();
384705684310SBram Moolenaar 
38480d6f5d97SBram Moolenaar 	// check for the characters now, otherwise they might be eaten by
38490d6f5d97SBram Moolenaar 	// get_keystroke()
38509584b31aSBram Moolenaar 	out_flush();
38519584b31aSBram Moolenaar 	(void)vpeekc_nomap();
38529584b31aSBram Moolenaar     }
38539584b31aSBram Moolenaar }
38542951b77eSBram Moolenaar 
3855b5c32655SBram Moolenaar /*
38564921c24bSBram Moolenaar  * Similar to requesting the version string: Request the terminal background
38574921c24bSBram Moolenaar  * color when it is the right moment.
3858b5c32655SBram Moolenaar  */
3859b5c32655SBram Moolenaar     void
may_req_bg_color(void)3860764b23c8SBram Moolenaar may_req_bg_color(void)
3861b5c32655SBram Moolenaar {
38623eee06e7SBram Moolenaar     if (can_get_termresponse() && starting == 0)
38633eee06e7SBram Moolenaar     {
386465e4c4f6SBram Moolenaar 	int didit = FALSE;
386565e4c4f6SBram Moolenaar 
386665e4c4f6SBram Moolenaar # ifdef FEAT_TERMINAL
38670d6f5d97SBram Moolenaar 	// Only request foreground if t_RF is set.
3868afd78266SBram Moolenaar 	if (rfg_status.tr_progress == STATUS_GET && *T_RFG != NUL)
386965e4c4f6SBram Moolenaar 	{
387086394aa9SBram Moolenaar #ifdef FEAT_JOB_CHANNEL
387186394aa9SBram Moolenaar 	    ch_log_output = TRUE;
387286394aa9SBram Moolenaar #endif
3873b255b905SBram Moolenaar 	    LOG_TR(("Sending FG request"));
387465e4c4f6SBram Moolenaar 	    out_str(T_RFG);
3875afd78266SBram Moolenaar 	    termrequest_sent(&rfg_status);
387665e4c4f6SBram Moolenaar 	    didit = TRUE;
387765e4c4f6SBram Moolenaar 	}
387865e4c4f6SBram Moolenaar # endif
387965e4c4f6SBram Moolenaar 
38800d6f5d97SBram Moolenaar 	// Only request background if t_RB is set.
3881afd78266SBram Moolenaar 	if (rbg_status.tr_progress == STATUS_GET && *T_RBG != NUL)
3882b5c32655SBram Moolenaar 	{
388386394aa9SBram Moolenaar #ifdef FEAT_JOB_CHANNEL
388486394aa9SBram Moolenaar 	    ch_log_output = TRUE;
388586394aa9SBram Moolenaar #endif
3886b255b905SBram Moolenaar 	    LOG_TR(("Sending BG request"));
3887b5c32655SBram Moolenaar 	    out_str(T_RBG);
3888afd78266SBram Moolenaar 	    termrequest_sent(&rbg_status);
388965e4c4f6SBram Moolenaar 	    didit = TRUE;
389065e4c4f6SBram Moolenaar 	}
38913eee06e7SBram Moolenaar 
389265e4c4f6SBram Moolenaar 	if (didit)
389365e4c4f6SBram Moolenaar 	{
38940d6f5d97SBram Moolenaar 	    // check for the characters now, otherwise they might be eaten by
38950d6f5d97SBram Moolenaar 	    // get_keystroke()
3896b5c32655SBram Moolenaar 	    out_flush();
3897b5c32655SBram Moolenaar 	    (void)vpeekc_nomap();
3898b5c32655SBram Moolenaar 	}
3899b5c32655SBram Moolenaar     }
3900833e0e3cSBram Moolenaar }
3901b5c32655SBram Moolenaar 
39022951b77eSBram Moolenaar # ifdef DEBUG_TERMRESPONSE
39032951b77eSBram Moolenaar     static void
log_tr(const char * fmt,...)3904b255b905SBram Moolenaar log_tr(const char *fmt, ...)
39052951b77eSBram Moolenaar {
39062951b77eSBram Moolenaar     static FILE *fd_tr = NULL;
39072951b77eSBram Moolenaar     static proftime_T start;
39082951b77eSBram Moolenaar     proftime_T now;
3909b255b905SBram Moolenaar     va_list ap;
39102951b77eSBram Moolenaar 
39112951b77eSBram Moolenaar     if (fd_tr == NULL)
39122951b77eSBram Moolenaar     {
39132951b77eSBram Moolenaar 	fd_tr = fopen("termresponse.log", "w");
39142951b77eSBram Moolenaar 	profile_start(&start);
39152951b77eSBram Moolenaar     }
39162951b77eSBram Moolenaar     now = start;
39172951b77eSBram Moolenaar     profile_end(&now);
3918b255b905SBram Moolenaar     fprintf(fd_tr, "%s: %s ", profile_msg(&now),
39192951b77eSBram Moolenaar 					must_redraw == NOT_VALID ? "NV"
3920b255b905SBram Moolenaar 					: must_redraw == CLEAR ? "CL" : "  ");
3921b255b905SBram Moolenaar     va_start(ap, fmt);
3922b255b905SBram Moolenaar     vfprintf(fd_tr, fmt, ap);
3923b255b905SBram Moolenaar     va_end(ap);
3924b255b905SBram Moolenaar     fputc('\n', fd_tr);
3925b255b905SBram Moolenaar     fflush(fd_tr);
39262951b77eSBram Moolenaar }
39272951b77eSBram Moolenaar # endif
3928071d4279SBram Moolenaar #endif
3929071d4279SBram Moolenaar 
3930071d4279SBram Moolenaar /*
3931071d4279SBram Moolenaar  * Return TRUE when saving and restoring the screen.
3932071d4279SBram Moolenaar  */
3933071d4279SBram Moolenaar     int
swapping_screen(void)3934764b23c8SBram Moolenaar swapping_screen(void)
3935071d4279SBram Moolenaar {
3936071d4279SBram Moolenaar     return (full_screen && *T_TI != NUL);
3937071d4279SBram Moolenaar }
3938071d4279SBram Moolenaar 
3939071d4279SBram Moolenaar /*
3940071d4279SBram Moolenaar  * By outputting the 'cursor very visible' termcap code, for some windowed
3941071d4279SBram Moolenaar  * terminals this makes the screen scrolled to the correct position.
3942071d4279SBram Moolenaar  * Used when starting Vim or returning from a shell.
3943071d4279SBram Moolenaar  */
3944071d4279SBram Moolenaar     void
scroll_start(void)3945764b23c8SBram Moolenaar scroll_start(void)
3946071d4279SBram Moolenaar {
3947ce1c3278SBram Moolenaar     if (*T_VS != NUL && *T_CVS != NUL)
3948071d4279SBram Moolenaar     {
394986394aa9SBram Moolenaar #ifdef FEAT_JOB_CHANNEL
395086394aa9SBram Moolenaar 	ch_log_output = TRUE;
395186394aa9SBram Moolenaar #endif
3952071d4279SBram Moolenaar 	out_str(T_VS);
3953ce1c3278SBram Moolenaar 	out_str(T_CVS);
39540d6f5d97SBram Moolenaar 	screen_start();		// don't know where cursor is now
3955071d4279SBram Moolenaar     }
3956071d4279SBram Moolenaar }
3957071d4279SBram Moolenaar 
395809f067fcSBram Moolenaar // True if cursor is not visible
3959071d4279SBram Moolenaar static int cursor_is_off = FALSE;
3960071d4279SBram Moolenaar 
396109f067fcSBram Moolenaar // True if cursor is not visible due to an ongoing cursor-less sleep
396209f067fcSBram Moolenaar static int cursor_is_asleep = FALSE;
396309f067fcSBram Moolenaar 
3964071d4279SBram Moolenaar /*
39652e31048cSBram Moolenaar  * Enable the cursor without checking if it's already enabled.
39662e31048cSBram Moolenaar  */
39672e31048cSBram Moolenaar     void
cursor_on_force(void)39682e31048cSBram Moolenaar cursor_on_force(void)
39692e31048cSBram Moolenaar {
39702e31048cSBram Moolenaar     out_str(T_VE);
39712e31048cSBram Moolenaar     cursor_is_off = FALSE;
397209f067fcSBram Moolenaar     cursor_is_asleep = FALSE;
39732e31048cSBram Moolenaar }
39742e31048cSBram Moolenaar 
39752e31048cSBram Moolenaar /*
39762e31048cSBram Moolenaar  * Enable the cursor if it's currently off.
3977071d4279SBram Moolenaar  */
3978071d4279SBram Moolenaar     void
cursor_on(void)3979764b23c8SBram Moolenaar cursor_on(void)
3980071d4279SBram Moolenaar {
398109f067fcSBram Moolenaar     if (cursor_is_off && !cursor_is_asleep)
39822e31048cSBram Moolenaar 	cursor_on_force();
3983071d4279SBram Moolenaar }
3984071d4279SBram Moolenaar 
3985071d4279SBram Moolenaar /*
3986071d4279SBram Moolenaar  * Disable the cursor.
3987071d4279SBram Moolenaar  */
3988071d4279SBram Moolenaar     void
cursor_off(void)3989764b23c8SBram Moolenaar cursor_off(void)
3990071d4279SBram Moolenaar {
3991ce1c3278SBram Moolenaar     if (full_screen && !cursor_is_off)
3992071d4279SBram Moolenaar     {
39930d6f5d97SBram Moolenaar 	out_str(T_VI);	    // disable cursor
3994071d4279SBram Moolenaar 	cursor_is_off = TRUE;
3995071d4279SBram Moolenaar     }
3996071d4279SBram Moolenaar }
3997071d4279SBram Moolenaar 
399809f067fcSBram Moolenaar /*
399909f067fcSBram Moolenaar  * Check whether the cursor is invisible due to an ongoing cursor-less sleep
400009f067fcSBram Moolenaar  */
400109f067fcSBram Moolenaar     int
cursor_is_sleeping(void)400209f067fcSBram Moolenaar cursor_is_sleeping(void)
400309f067fcSBram Moolenaar {
400409f067fcSBram Moolenaar     return cursor_is_asleep;
400509f067fcSBram Moolenaar }
400609f067fcSBram Moolenaar 
400709f067fcSBram Moolenaar /*
400809f067fcSBram Moolenaar  * Disable the cursor and mark it disabled by cursor-less sleep
400909f067fcSBram Moolenaar  */
401009f067fcSBram Moolenaar     void
cursor_sleep(void)401109f067fcSBram Moolenaar cursor_sleep(void)
401209f067fcSBram Moolenaar {
401309f067fcSBram Moolenaar     cursor_is_asleep = TRUE;
401409f067fcSBram Moolenaar     cursor_off();
401509f067fcSBram Moolenaar }
401609f067fcSBram Moolenaar 
401709f067fcSBram Moolenaar /*
401809f067fcSBram Moolenaar  * Enable the cursor and mark it not disabled by cursor-less sleep
401909f067fcSBram Moolenaar  */
402009f067fcSBram Moolenaar     void
cursor_unsleep(void)402109f067fcSBram Moolenaar cursor_unsleep(void)
402209f067fcSBram Moolenaar {
402309f067fcSBram Moolenaar     cursor_is_asleep = FALSE;
402409f067fcSBram Moolenaar     cursor_on();
402509f067fcSBram Moolenaar }
402609f067fcSBram Moolenaar 
40271cd871b5SBram Moolenaar #if defined(CURSOR_SHAPE) || defined(PROTO)
4028071d4279SBram Moolenaar /*
40291e7813a1SBram Moolenaar  * Set cursor shape to match Insert or Replace mode.
4030293ee4d4SBram Moolenaar  */
4031293ee4d4SBram Moolenaar     void
term_cursor_mode(int forced)40323cd43cccSBram Moolenaar term_cursor_mode(int forced)
4033293ee4d4SBram Moolenaar {
4034c9770920SBram Moolenaar     static int showing_mode = -1;
40351e7813a1SBram Moolenaar     char_u *p;
4036293ee4d4SBram Moolenaar 
40370d6f5d97SBram Moolenaar     // Only do something when redrawing the screen and we can restore the
40380d6f5d97SBram Moolenaar     // mode.
40391e7813a1SBram Moolenaar     if (!full_screen || *T_CEI == NUL)
40403eee06e7SBram Moolenaar     {
404137b9b819SBram Moolenaar # ifdef FEAT_TERMRESPONSE
40423eee06e7SBram Moolenaar 	if (forced && initial_cursor_shape > 0)
40430d6f5d97SBram Moolenaar 	    // Restore to initial values.
40443eee06e7SBram Moolenaar 	    term_cursor_shape(initial_cursor_shape, initial_cursor_blink);
404537b9b819SBram Moolenaar # endif
4046293ee4d4SBram Moolenaar 	return;
40473eee06e7SBram Moolenaar     }
4048293ee4d4SBram Moolenaar 
40491e7813a1SBram Moolenaar     if ((State & REPLACE) == REPLACE)
4050293ee4d4SBram Moolenaar     {
40513cd43cccSBram Moolenaar 	if (forced || showing_mode != REPLACE)
40521e7813a1SBram Moolenaar 	{
40531e7813a1SBram Moolenaar 	    if (*T_CSR != NUL)
40540d6f5d97SBram Moolenaar 		p = T_CSR;	// Replace mode cursor
4055293ee4d4SBram Moolenaar 	    else
40560d6f5d97SBram Moolenaar 		p = T_CSI;	// fall back to Insert mode cursor
40571e7813a1SBram Moolenaar 	    if (*p != NUL)
4058293ee4d4SBram Moolenaar 	    {
40591e7813a1SBram Moolenaar 		out_str(p);
40601e7813a1SBram Moolenaar 		showing_mode = REPLACE;
40611e7813a1SBram Moolenaar 	    }
40621e7813a1SBram Moolenaar 	}
40631e7813a1SBram Moolenaar     }
40641e7813a1SBram Moolenaar     else if (State & INSERT)
40651e7813a1SBram Moolenaar     {
40663cd43cccSBram Moolenaar 	if ((forced || showing_mode != INSERT) && *T_CSI != NUL)
40671e7813a1SBram Moolenaar 	{
40680d6f5d97SBram Moolenaar 	    out_str(T_CSI);	    // Insert mode cursor
40691e7813a1SBram Moolenaar 	    showing_mode = INSERT;
40701e7813a1SBram Moolenaar 	}
40711e7813a1SBram Moolenaar     }
40723cd43cccSBram Moolenaar     else if (forced || showing_mode != NORMAL)
40731e7813a1SBram Moolenaar     {
40740d6f5d97SBram Moolenaar 	out_str(T_CEI);		    // non-Insert mode cursor
40751e7813a1SBram Moolenaar 	showing_mode = NORMAL;
4076293ee4d4SBram Moolenaar     }
4077293ee4d4SBram Moolenaar }
40783cd43cccSBram Moolenaar 
40793cd43cccSBram Moolenaar # if defined(FEAT_TERMINAL) || defined(PROTO)
40803cd43cccSBram Moolenaar     void
term_cursor_color(char_u * color)40813cd43cccSBram Moolenaar term_cursor_color(char_u *color)
40823cd43cccSBram Moolenaar {
40833cd43cccSBram Moolenaar     if (*T_CSC != NUL)
40843cd43cccSBram Moolenaar     {
4085ec6f7350SBram Moolenaar 	out_str(T_CSC);		// set cursor color start
40863cd43cccSBram Moolenaar 	out_str_nf(color);
4087ec6f7350SBram Moolenaar 	out_str(T_CEC);		// set cursor color end
40883cd43cccSBram Moolenaar 	out_flush();
40893cd43cccSBram Moolenaar     }
40903cd43cccSBram Moolenaar }
4091fc8bec0bSBram Moolenaar # endif
40923cd43cccSBram Moolenaar 
40934db25549SBram Moolenaar     int
blink_state_is_inverted()40944db25549SBram Moolenaar blink_state_is_inverted()
40954db25549SBram Moolenaar {
40963c37a8e6SBram Moolenaar #ifdef FEAT_TERMRESPONSE
409766761db1SBram Moolenaar     return rbm_status.tr_progress == STATUS_GOT
409866761db1SBram Moolenaar 	&& rcs_status.tr_progress == STATUS_GOT
40994db25549SBram Moolenaar 		&& initial_cursor_blink != initial_cursor_shape_blink;
41003c37a8e6SBram Moolenaar #else
41013c37a8e6SBram Moolenaar     return FALSE;
41023c37a8e6SBram Moolenaar #endif
41034db25549SBram Moolenaar }
41044db25549SBram Moolenaar 
41053cd43cccSBram Moolenaar /*
4106ce1c3278SBram Moolenaar  * "shape": 1 = block, 2 = underline, 3 = vertical bar
41073cd43cccSBram Moolenaar  */
41083cd43cccSBram Moolenaar     void
term_cursor_shape(int shape,int blink)41093cd43cccSBram Moolenaar term_cursor_shape(int shape, int blink)
41103cd43cccSBram Moolenaar {
41113cd43cccSBram Moolenaar     if (*T_CSH != NUL)
41123cd43cccSBram Moolenaar     {
41133cd43cccSBram Moolenaar 	OUT_STR(tgoto((char *)T_CSH, 0, shape * 2 - blink));
41143cd43cccSBram Moolenaar 	out_flush();
41153cd43cccSBram Moolenaar     }
41164db25549SBram Moolenaar     else
41174db25549SBram Moolenaar     {
41184db25549SBram Moolenaar 	int do_blink = blink;
41194db25549SBram Moolenaar 
41200d6f5d97SBram Moolenaar 	// t_SH is empty: try setting just the blink state.
41210d6f5d97SBram Moolenaar 	// The blink flags are XORed together, if the initial blinking from
41220d6f5d97SBram Moolenaar 	// style and shape differs, we need to invert the flag here.
41234db25549SBram Moolenaar 	if (blink_state_is_inverted())
41244db25549SBram Moolenaar 	    do_blink = !blink;
41254db25549SBram Moolenaar 
41264db25549SBram Moolenaar 	if (do_blink && *T_VS != NUL)
4127ce1c3278SBram Moolenaar 	{
4128ce1c3278SBram Moolenaar 	    out_str(T_VS);
4129ce1c3278SBram Moolenaar 	    out_flush();
4130ce1c3278SBram Moolenaar 	}
41314db25549SBram Moolenaar 	else if (!do_blink && *T_CVS != NUL)
4132ce1c3278SBram Moolenaar 	{
4133ce1c3278SBram Moolenaar 	    out_str(T_CVS);
4134ce1c3278SBram Moolenaar 	    out_flush();
4135ce1c3278SBram Moolenaar 	}
41363cd43cccSBram Moolenaar     }
41374db25549SBram Moolenaar }
41383cd43cccSBram Moolenaar #endif
4139293ee4d4SBram Moolenaar 
4140293ee4d4SBram Moolenaar /*
4141071d4279SBram Moolenaar  * Set scrolling region for window 'wp'.
4142071d4279SBram Moolenaar  * The region starts 'off' lines from the start of the window.
4143071d4279SBram Moolenaar  * Also set the vertical scroll region for a vertically split window.  Always
4144071d4279SBram Moolenaar  * the full width of the window, excluding the vertical separator.
4145071d4279SBram Moolenaar  */
4146071d4279SBram Moolenaar     void
scroll_region_set(win_T * wp,int off)4147764b23c8SBram Moolenaar scroll_region_set(win_T *wp, int off)
4148071d4279SBram Moolenaar {
4149071d4279SBram Moolenaar     OUT_STR(tgoto((char *)T_CS, W_WINROW(wp) + wp->w_height - 1,
4150071d4279SBram Moolenaar 							 W_WINROW(wp) + off));
4151071d4279SBram Moolenaar     if (*T_CSV != NUL && wp->w_width != Columns)
415253f8174eSBram Moolenaar 	OUT_STR(tgoto((char *)T_CSV, wp->w_wincol + wp->w_width - 1,
415353f8174eSBram Moolenaar 							       wp->w_wincol));
41540d6f5d97SBram Moolenaar     screen_start();		    // don't know where cursor is now
4155071d4279SBram Moolenaar }
4156071d4279SBram Moolenaar 
4157071d4279SBram Moolenaar /*
4158071d4279SBram Moolenaar  * Reset scrolling region to the whole screen.
4159071d4279SBram Moolenaar  */
4160071d4279SBram Moolenaar     void
scroll_region_reset(void)4161764b23c8SBram Moolenaar scroll_region_reset(void)
4162071d4279SBram Moolenaar {
4163071d4279SBram Moolenaar     OUT_STR(tgoto((char *)T_CS, (int)Rows - 1, 0));
4164071d4279SBram Moolenaar     if (*T_CSV != NUL)
4165071d4279SBram Moolenaar 	OUT_STR(tgoto((char *)T_CSV, (int)Columns - 1, 0));
41660d6f5d97SBram Moolenaar     screen_start();		    // don't know where cursor is now
4167071d4279SBram Moolenaar }
4168071d4279SBram Moolenaar 
4169071d4279SBram Moolenaar 
4170071d4279SBram Moolenaar /*
4171071d4279SBram Moolenaar  * List of terminal codes that are currently recognized.
4172071d4279SBram Moolenaar  */
4173071d4279SBram Moolenaar 
41746c0b44b5SBram Moolenaar static struct termcode
4175071d4279SBram Moolenaar {
41760d6f5d97SBram Moolenaar     char_u  name[2];	    // termcap name of entry
41770d6f5d97SBram Moolenaar     char_u  *code;	    // terminal code (in allocated memory)
41780d6f5d97SBram Moolenaar     int	    len;	    // STRLEN(code)
41790d6f5d97SBram Moolenaar     int	    modlen;	    // length of part before ";*~".
4180071d4279SBram Moolenaar } *termcodes = NULL;
4181071d4279SBram Moolenaar 
41820d6f5d97SBram Moolenaar static int  tc_max_len = 0; // number of entries that termcodes[] can hold
41830d6f5d97SBram Moolenaar static int  tc_len = 0;	    // current number of entries in termcodes[]
4184071d4279SBram Moolenaar 
4185baaa7e9eSBram Moolenaar static int termcode_star(char_u *code, int len);
4186bc7aa85dSBram Moolenaar 
4187071d4279SBram Moolenaar     void
clear_termcodes(void)4188764b23c8SBram Moolenaar clear_termcodes(void)
4189071d4279SBram Moolenaar {
4190071d4279SBram Moolenaar     while (tc_len > 0)
4191071d4279SBram Moolenaar 	vim_free(termcodes[--tc_len].code);
4192d23a8236SBram Moolenaar     VIM_CLEAR(termcodes);
4193071d4279SBram Moolenaar     tc_max_len = 0;
4194071d4279SBram Moolenaar 
4195071d4279SBram Moolenaar #ifdef HAVE_TGETENT
4196071d4279SBram Moolenaar     BC = (char *)empty_option;
4197071d4279SBram Moolenaar     UP = (char *)empty_option;
41980d6f5d97SBram Moolenaar     PC = NUL;			// set pad character to NUL
4199071d4279SBram Moolenaar     ospeed = 0;
4200071d4279SBram Moolenaar #endif
4201071d4279SBram Moolenaar 
42020d6f5d97SBram Moolenaar     need_gather = TRUE;		// need to fill termleader[]
4203071d4279SBram Moolenaar }
4204071d4279SBram Moolenaar 
4205bc7aa85dSBram Moolenaar #define ATC_FROM_TERM 55
4206bc7aa85dSBram Moolenaar 
4207071d4279SBram Moolenaar /*
4208071d4279SBram Moolenaar  * Add a new entry to the list of terminal codes.
4209071d4279SBram Moolenaar  * The list is kept alphabetical for ":set termcap"
4210bc7aa85dSBram Moolenaar  * "flags" is TRUE when replacing 7-bit by 8-bit controls is desired.
4211bc7aa85dSBram Moolenaar  * "flags" can also be ATC_FROM_TERM for got_code_from_term().
4212071d4279SBram Moolenaar  */
4213071d4279SBram Moolenaar     void
add_termcode(char_u * name,char_u * string,int flags)4214764b23c8SBram Moolenaar add_termcode(char_u *name, char_u *string, int flags)
4215071d4279SBram Moolenaar {
4216071d4279SBram Moolenaar     struct termcode *new_tc;
4217071d4279SBram Moolenaar     int		    i, j;
4218071d4279SBram Moolenaar     char_u	    *s;
421919a09a18SBram Moolenaar     int		    len;
4220071d4279SBram Moolenaar 
4221071d4279SBram Moolenaar     if (string == NULL || *string == NUL)
4222071d4279SBram Moolenaar     {
4223071d4279SBram Moolenaar 	del_termcode(name);
4224071d4279SBram Moolenaar 	return;
4225071d4279SBram Moolenaar     }
4226071d4279SBram Moolenaar 
42274f97475dSBram Moolenaar #if defined(MSWIN) && !defined(FEAT_GUI)
422871ccd03eSBram Moolenaar     s = vim_strnsave(string, STRLEN(string) + 1);
422945500912SBram Moolenaar #else
4230afde13b6SBram Moolenaar # ifdef VIMDLL
4231afde13b6SBram Moolenaar     if (!gui.in_use)
423271ccd03eSBram Moolenaar 	s = vim_strnsave(string, STRLEN(string) + 1);
4233afde13b6SBram Moolenaar     else
4234afde13b6SBram Moolenaar # endif
4235071d4279SBram Moolenaar 	s = vim_strsave(string);
423645500912SBram Moolenaar #endif
4237071d4279SBram Moolenaar     if (s == NULL)
4238071d4279SBram Moolenaar 	return;
4239071d4279SBram Moolenaar 
42400d6f5d97SBram Moolenaar     // Change leading <Esc>[ to CSI, change <Esc>O to <M-O>.
4241bc7aa85dSBram Moolenaar     if (flags != 0 && flags != ATC_FROM_TERM && term_7to8bit(string) != 0)
4242071d4279SBram Moolenaar     {
4243864207deSBram Moolenaar 	STRMOVE(s, s + 1);
4244071d4279SBram Moolenaar 	s[0] = term_7to8bit(string);
4245071d4279SBram Moolenaar     }
424645500912SBram Moolenaar 
4247afde13b6SBram Moolenaar #if defined(MSWIN) && (!defined(FEAT_GUI) || defined(VIMDLL))
4248afde13b6SBram Moolenaar # ifdef VIMDLL
4249afde13b6SBram Moolenaar     if (!gui.in_use)
4250afde13b6SBram Moolenaar # endif
4251afde13b6SBram Moolenaar     {
425245500912SBram Moolenaar 	if (s[0] == K_NUL)
425345500912SBram Moolenaar 	{
425445500912SBram Moolenaar 	    STRMOVE(s + 1, s);
425545500912SBram Moolenaar 	    s[1] = 3;
425645500912SBram Moolenaar 	}
4257afde13b6SBram Moolenaar     }
425845500912SBram Moolenaar #endif
425945500912SBram Moolenaar 
426019a09a18SBram Moolenaar     len = (int)STRLEN(s);
4261071d4279SBram Moolenaar 
42620d6f5d97SBram Moolenaar     need_gather = TRUE;		// need to fill termleader[]
4263071d4279SBram Moolenaar 
4264071d4279SBram Moolenaar     /*
4265071d4279SBram Moolenaar      * need to make space for more entries
4266071d4279SBram Moolenaar      */
4267071d4279SBram Moolenaar     if (tc_len == tc_max_len)
4268071d4279SBram Moolenaar     {
4269071d4279SBram Moolenaar 	tc_max_len += 20;
4270c799fe20SBram Moolenaar 	new_tc = ALLOC_MULT(struct termcode, tc_max_len);
4271071d4279SBram Moolenaar 	if (new_tc == NULL)
4272071d4279SBram Moolenaar 	{
4273071d4279SBram Moolenaar 	    tc_max_len -= 20;
427428cf44f7SDominique Pelle 	    vim_free(s);
4275071d4279SBram Moolenaar 	    return;
4276071d4279SBram Moolenaar 	}
4277071d4279SBram Moolenaar 	for (i = 0; i < tc_len; ++i)
4278071d4279SBram Moolenaar 	    new_tc[i] = termcodes[i];
4279071d4279SBram Moolenaar 	vim_free(termcodes);
4280071d4279SBram Moolenaar 	termcodes = new_tc;
4281071d4279SBram Moolenaar     }
4282071d4279SBram Moolenaar 
4283071d4279SBram Moolenaar     /*
4284071d4279SBram Moolenaar      * Look for existing entry with the same name, it is replaced.
4285071d4279SBram Moolenaar      * Look for an existing entry that is alphabetical higher, the new entry
4286071d4279SBram Moolenaar      * is inserted in front of it.
4287071d4279SBram Moolenaar      */
4288071d4279SBram Moolenaar     for (i = 0; i < tc_len; ++i)
4289071d4279SBram Moolenaar     {
4290071d4279SBram Moolenaar 	if (termcodes[i].name[0] < name[0])
4291071d4279SBram Moolenaar 	    continue;
4292071d4279SBram Moolenaar 	if (termcodes[i].name[0] == name[0])
4293071d4279SBram Moolenaar 	{
4294071d4279SBram Moolenaar 	    if (termcodes[i].name[1] < name[1])
4295071d4279SBram Moolenaar 		continue;
4296071d4279SBram Moolenaar 	    /*
4297bc7aa85dSBram Moolenaar 	     * Exact match: May replace old code.
4298071d4279SBram Moolenaar 	     */
4299071d4279SBram Moolenaar 	    if (termcodes[i].name[1] == name[1])
4300071d4279SBram Moolenaar 	    {
4301bc7aa85dSBram Moolenaar 		if (flags == ATC_FROM_TERM && (j = termcode_star(
4302bc7aa85dSBram Moolenaar 				    termcodes[i].code, termcodes[i].len)) > 0)
430319a09a18SBram Moolenaar 		{
43040d6f5d97SBram Moolenaar 		    // Don't replace ESC[123;*X or ESC O*X with another when
43050d6f5d97SBram Moolenaar 		    // invoked from got_code_from_term().
4306bc7aa85dSBram Moolenaar 		    if (len == termcodes[i].len - j
430719a09a18SBram Moolenaar 			    && STRNCMP(s, termcodes[i].code, len - 1) == 0
4308bc7aa85dSBram Moolenaar 			    && s[len - 1]
4309bc7aa85dSBram Moolenaar 				   == termcodes[i].code[termcodes[i].len - 1])
431019a09a18SBram Moolenaar 		    {
43110d6f5d97SBram Moolenaar 			// They are equal but for the ";*": don't add it.
431219a09a18SBram Moolenaar 			vim_free(s);
431319a09a18SBram Moolenaar 			return;
431419a09a18SBram Moolenaar 		    }
431519a09a18SBram Moolenaar 		}
431619a09a18SBram Moolenaar 		else
431719a09a18SBram Moolenaar 		{
43180d6f5d97SBram Moolenaar 		    // Replace old code.
4319071d4279SBram Moolenaar 		    vim_free(termcodes[i].code);
4320071d4279SBram Moolenaar 		    --tc_len;
4321071d4279SBram Moolenaar 		    break;
4322071d4279SBram Moolenaar 		}
4323071d4279SBram Moolenaar 	    }
432419a09a18SBram Moolenaar 	}
4325071d4279SBram Moolenaar 	/*
4326071d4279SBram Moolenaar 	 * Found alphabetical larger entry, move rest to insert new entry
4327071d4279SBram Moolenaar 	 */
4328071d4279SBram Moolenaar 	for (j = tc_len; j > i; --j)
4329071d4279SBram Moolenaar 	    termcodes[j] = termcodes[j - 1];
4330071d4279SBram Moolenaar 	break;
4331071d4279SBram Moolenaar     }
4332071d4279SBram Moolenaar 
4333071d4279SBram Moolenaar     termcodes[i].name[0] = name[0];
4334071d4279SBram Moolenaar     termcodes[i].name[1] = name[1];
4335071d4279SBram Moolenaar     termcodes[i].code = s;
433619a09a18SBram Moolenaar     termcodes[i].len = len;
4337bc7aa85dSBram Moolenaar 
43380d6f5d97SBram Moolenaar     // For xterm we recognize special codes like "ESC[42;*X" and "ESC O*X" that
43390d6f5d97SBram Moolenaar     // accept modifiers.
434019a09a18SBram Moolenaar     termcodes[i].modlen = 0;
4341bc7aa85dSBram Moolenaar     j = termcode_star(s, len);
4342bc7aa85dSBram Moolenaar     if (j > 0)
43434d8c96d4SBram Moolenaar     {
4344bc7aa85dSBram Moolenaar 	termcodes[i].modlen = len - 1 - j;
43454d8c96d4SBram Moolenaar 	// For "CSI[@;X" the "@" is not included in "modlen".
43464d8c96d4SBram Moolenaar 	if (termcodes[i].code[termcodes[i].modlen - 1] == '@')
43474d8c96d4SBram Moolenaar 	    --termcodes[i].modlen;
43484d8c96d4SBram Moolenaar     }
4349071d4279SBram Moolenaar     ++tc_len;
4350071d4279SBram Moolenaar }
4351071d4279SBram Moolenaar 
4352bc7aa85dSBram Moolenaar /*
4353a529ce06SBram Moolenaar  * Check termcode "code[len]" for ending in ;*X or *X.
4354bc7aa85dSBram Moolenaar  * The "X" can be any character.
4355a529ce06SBram Moolenaar  * Return 0 if not found, 2 for ;*X and 1 for *X.
4356bc7aa85dSBram Moolenaar  */
4357bc7aa85dSBram Moolenaar     static int
termcode_star(char_u * code,int len)4358764b23c8SBram Moolenaar termcode_star(char_u *code, int len)
4359bc7aa85dSBram Moolenaar {
43604d8c96d4SBram Moolenaar     // Shortest is <M-O>*X.  With ; shortest is <CSI>@;*X
4361bc7aa85dSBram Moolenaar     if (len >= 3 && code[len - 2] == '*')
4362bc7aa85dSBram Moolenaar     {
4363bc7aa85dSBram Moolenaar 	if (len >= 5 && code[len - 3] == ';')
4364bc7aa85dSBram Moolenaar 	    return 2;
4365a529ce06SBram Moolenaar 	else
4366bc7aa85dSBram Moolenaar 	    return 1;
4367bc7aa85dSBram Moolenaar     }
4368bc7aa85dSBram Moolenaar     return 0;
4369bc7aa85dSBram Moolenaar }
4370bc7aa85dSBram Moolenaar 
4371071d4279SBram Moolenaar     char_u  *
find_termcode(char_u * name)4372764b23c8SBram Moolenaar find_termcode(char_u *name)
4373071d4279SBram Moolenaar {
4374071d4279SBram Moolenaar     int	    i;
4375071d4279SBram Moolenaar 
4376071d4279SBram Moolenaar     for (i = 0; i < tc_len; ++i)
4377071d4279SBram Moolenaar 	if (termcodes[i].name[0] == name[0] && termcodes[i].name[1] == name[1])
4378071d4279SBram Moolenaar 	    return termcodes[i].code;
4379071d4279SBram Moolenaar     return NULL;
4380071d4279SBram Moolenaar }
4381071d4279SBram Moolenaar 
4382071d4279SBram Moolenaar     char_u *
get_termcode(int i)4383764b23c8SBram Moolenaar get_termcode(int i)
4384071d4279SBram Moolenaar {
4385071d4279SBram Moolenaar     if (i >= tc_len)
4386071d4279SBram Moolenaar 	return NULL;
4387071d4279SBram Moolenaar     return &termcodes[i].name[0];
4388071d4279SBram Moolenaar }
4389071d4279SBram Moolenaar 
4390b8ff5c27SBram Moolenaar /*
4391b8ff5c27SBram Moolenaar  * Returns the length of the terminal code at index 'idx'.
4392b8ff5c27SBram Moolenaar  */
4393b8ff5c27SBram Moolenaar     int
get_termcode_len(int idx)4394b8ff5c27SBram Moolenaar get_termcode_len(int idx)
4395b8ff5c27SBram Moolenaar {
4396b8ff5c27SBram Moolenaar     return termcodes[idx].len;
4397b8ff5c27SBram Moolenaar }
4398b8ff5c27SBram Moolenaar 
4399b20b9e14SBram Moolenaar     void
del_termcode(char_u * name)4400764b23c8SBram Moolenaar del_termcode(char_u *name)
4401071d4279SBram Moolenaar {
4402071d4279SBram Moolenaar     int	    i;
4403071d4279SBram Moolenaar 
44040d6f5d97SBram Moolenaar     if (termcodes == NULL)	// nothing there yet
4405071d4279SBram Moolenaar 	return;
4406071d4279SBram Moolenaar 
44070d6f5d97SBram Moolenaar     need_gather = TRUE;		// need to fill termleader[]
4408071d4279SBram Moolenaar 
4409071d4279SBram Moolenaar     for (i = 0; i < tc_len; ++i)
4410071d4279SBram Moolenaar 	if (termcodes[i].name[0] == name[0] && termcodes[i].name[1] == name[1])
4411071d4279SBram Moolenaar 	{
4412071d4279SBram Moolenaar 	    del_termcode_idx(i);
4413071d4279SBram Moolenaar 	    return;
4414071d4279SBram Moolenaar 	}
44150d6f5d97SBram Moolenaar     // not found. Give error message?
4416071d4279SBram Moolenaar }
4417071d4279SBram Moolenaar 
4418071d4279SBram Moolenaar     static void
del_termcode_idx(int idx)4419764b23c8SBram Moolenaar del_termcode_idx(int idx)
4420071d4279SBram Moolenaar {
4421071d4279SBram Moolenaar     int		i;
4422071d4279SBram Moolenaar 
4423071d4279SBram Moolenaar     vim_free(termcodes[idx].code);
4424071d4279SBram Moolenaar     --tc_len;
4425071d4279SBram Moolenaar     for (i = idx; i < tc_len; ++i)
4426071d4279SBram Moolenaar 	termcodes[i] = termcodes[i + 1];
4427071d4279SBram Moolenaar }
4428071d4279SBram Moolenaar 
4429071d4279SBram Moolenaar #ifdef FEAT_TERMRESPONSE
4430071d4279SBram Moolenaar /*
4431071d4279SBram Moolenaar  * Called when detected that the terminal sends 8-bit codes.
4432071d4279SBram Moolenaar  * Convert all 7-bit codes to their 8-bit equivalent.
4433071d4279SBram Moolenaar  */
4434071d4279SBram Moolenaar     static void
switch_to_8bit(void)4435764b23c8SBram Moolenaar switch_to_8bit(void)
4436071d4279SBram Moolenaar {
4437071d4279SBram Moolenaar     int		i;
4438071d4279SBram Moolenaar     int		c;
4439071d4279SBram Moolenaar 
44400d6f5d97SBram Moolenaar     // Only need to do something when not already using 8-bit codes.
4441071d4279SBram Moolenaar     if (!term_is_8bit(T_NAME))
4442071d4279SBram Moolenaar     {
4443071d4279SBram Moolenaar 	for (i = 0; i < tc_len; ++i)
4444071d4279SBram Moolenaar 	{
4445071d4279SBram Moolenaar 	    c = term_7to8bit(termcodes[i].code);
4446071d4279SBram Moolenaar 	    if (c != 0)
4447071d4279SBram Moolenaar 	    {
4448864207deSBram Moolenaar 		STRMOVE(termcodes[i].code + 1, termcodes[i].code + 2);
4449071d4279SBram Moolenaar 		termcodes[i].code[0] = c;
4450071d4279SBram Moolenaar 	    }
4451071d4279SBram Moolenaar 	}
44520d6f5d97SBram Moolenaar 	need_gather = TRUE;		// need to fill termleader[]
4453071d4279SBram Moolenaar     }
4454071d4279SBram Moolenaar     detected_8bit = TRUE;
4455b255b905SBram Moolenaar     LOG_TR(("Switching to 8 bit"));
4456071d4279SBram Moolenaar }
4457071d4279SBram Moolenaar #endif
4458071d4279SBram Moolenaar 
4459071d4279SBram Moolenaar #ifdef CHECK_DOUBLE_CLICK
4460071d4279SBram Moolenaar static linenr_T orig_topline = 0;
4461071d4279SBram Moolenaar # ifdef FEAT_DIFF
4462071d4279SBram Moolenaar static int orig_topfill = 0;
4463071d4279SBram Moolenaar # endif
4464071d4279SBram Moolenaar #endif
44654033c55eSBram Moolenaar #if defined(CHECK_DOUBLE_CLICK) || defined(PROTO)
4466071d4279SBram Moolenaar /*
4467071d4279SBram Moolenaar  * Checking for double clicks ourselves.
4468071d4279SBram Moolenaar  * "orig_topline" is used to avoid detecting a double-click when the window
4469071d4279SBram Moolenaar  * contents scrolled (e.g., when 'scrolloff' is non-zero).
4470071d4279SBram Moolenaar  */
4471071d4279SBram Moolenaar /*
4472071d4279SBram Moolenaar  * Set orig_topline.  Used when jumping to another window, so that a double
4473071d4279SBram Moolenaar  * click still works.
4474071d4279SBram Moolenaar  */
4475071d4279SBram Moolenaar     void
set_mouse_topline(win_T * wp)4476764b23c8SBram Moolenaar set_mouse_topline(win_T *wp)
4477071d4279SBram Moolenaar {
4478071d4279SBram Moolenaar     orig_topline = wp->w_topline;
4479071d4279SBram Moolenaar # ifdef FEAT_DIFF
4480071d4279SBram Moolenaar     orig_topfill = wp->w_topfill;
4481071d4279SBram Moolenaar # endif
4482071d4279SBram Moolenaar }
4483b8ff5c27SBram Moolenaar 
4484b8ff5c27SBram Moolenaar /*
4485b8ff5c27SBram Moolenaar  * Returns TRUE if the top line and top fill of window 'wp' matches the saved
4486b8ff5c27SBram Moolenaar  * topline and topfill.
4487b8ff5c27SBram Moolenaar  */
4488b8ff5c27SBram Moolenaar     int
is_mouse_topline(win_T * wp)4489b8ff5c27SBram Moolenaar is_mouse_topline(win_T *wp)
4490b8ff5c27SBram Moolenaar {
4491b8ff5c27SBram Moolenaar     return orig_topline == wp->w_topline
4492b8ff5c27SBram Moolenaar #ifdef FEAT_DIFF
4493b8ff5c27SBram Moolenaar 	&& orig_topfill == wp->w_topfill
4494b8ff5c27SBram Moolenaar #endif
4495b8ff5c27SBram Moolenaar 	;
4496b8ff5c27SBram Moolenaar }
4497071d4279SBram Moolenaar #endif
4498071d4279SBram Moolenaar 
4499071d4279SBram Moolenaar /*
45006a0299d8SBram Moolenaar  * Put "string[new_slen]" in typebuf, or in "buf[bufsize]" if "buf" is not NULL.
45016a0299d8SBram Moolenaar  * Remove "slen" bytes.
45026a0299d8SBram Moolenaar  * Returns FAIL for error.
45036a0299d8SBram Moolenaar  */
4504975a880aSBram Moolenaar     int
put_string_in_typebuf(int offset,int slen,char_u * string,int new_slen,char_u * buf,int bufsize,int * buflen)45056a0299d8SBram Moolenaar put_string_in_typebuf(
45066a0299d8SBram Moolenaar 	int	offset,
45076a0299d8SBram Moolenaar 	int	slen,
45086a0299d8SBram Moolenaar 	char_u	*string,
45096a0299d8SBram Moolenaar 	int	new_slen,
45106a0299d8SBram Moolenaar 	char_u	*buf,
45116a0299d8SBram Moolenaar 	int	bufsize,
45126a0299d8SBram Moolenaar 	int	*buflen)
45136a0299d8SBram Moolenaar {
45146a0299d8SBram Moolenaar     int		extra = new_slen - slen;
45156a0299d8SBram Moolenaar 
45166a0299d8SBram Moolenaar     string[new_slen] = NUL;
45176a0299d8SBram Moolenaar     if (buf == NULL)
45186a0299d8SBram Moolenaar     {
45196a0299d8SBram Moolenaar 	if (extra < 0)
45206a0299d8SBram Moolenaar 	    // remove matched chars, taking care of noremap
45216a0299d8SBram Moolenaar 	    del_typebuf(-extra, offset);
45226a0299d8SBram Moolenaar 	else if (extra > 0)
45236a0299d8SBram Moolenaar 	    // insert the extra space we need
45246a0299d8SBram Moolenaar 	    ins_typebuf(string + slen, REMAP_YES, offset, FALSE, FALSE);
45256a0299d8SBram Moolenaar 
45266a0299d8SBram Moolenaar 	// Careful: del_typebuf() and ins_typebuf() may have reallocated
45276a0299d8SBram Moolenaar 	// typebuf.tb_buf[]!
45286a0299d8SBram Moolenaar 	mch_memmove(typebuf.tb_buf + typebuf.tb_off + offset, string,
45296a0299d8SBram Moolenaar 							     (size_t)new_slen);
45306a0299d8SBram Moolenaar     }
45316a0299d8SBram Moolenaar     else
45326a0299d8SBram Moolenaar     {
45336a0299d8SBram Moolenaar 	if (extra < 0)
45346a0299d8SBram Moolenaar 	    // remove matched characters
45356a0299d8SBram Moolenaar 	    mch_memmove(buf + offset, buf + offset - extra,
45366a0299d8SBram Moolenaar 					   (size_t)(*buflen + offset + extra));
45376a0299d8SBram Moolenaar 	else if (extra > 0)
45386a0299d8SBram Moolenaar 	{
45396a0299d8SBram Moolenaar 	    // Insert the extra space we need.  If there is insufficient
45406a0299d8SBram Moolenaar 	    // space return -1.
45416a0299d8SBram Moolenaar 	    if (*buflen + extra + new_slen >= bufsize)
45426a0299d8SBram Moolenaar 		return FAIL;
45436a0299d8SBram Moolenaar 	    mch_memmove(buf + offset + extra, buf + offset,
45446a0299d8SBram Moolenaar 						   (size_t)(*buflen - offset));
45456a0299d8SBram Moolenaar 	}
45466a0299d8SBram Moolenaar 	mch_memmove(buf + offset, string, (size_t)new_slen);
45476a0299d8SBram Moolenaar 	*buflen = *buflen + extra + new_slen;
45486a0299d8SBram Moolenaar     }
45496a0299d8SBram Moolenaar     return OK;
45506a0299d8SBram Moolenaar }
45516a0299d8SBram Moolenaar 
45526a0299d8SBram Moolenaar /*
45536a0299d8SBram Moolenaar  * Decode a modifier number as xterm provides it into MOD_MASK bits.
45546a0299d8SBram Moolenaar  */
4555fc4ea2a7SBram Moolenaar     int
decode_modifiers(int n)45566a0299d8SBram Moolenaar decode_modifiers(int n)
45576a0299d8SBram Moolenaar {
45586a0299d8SBram Moolenaar     int	    code = n - 1;
45596a0299d8SBram Moolenaar     int	    modifiers = 0;
45606a0299d8SBram Moolenaar 
45616a0299d8SBram Moolenaar     if (code & 1)
45626a0299d8SBram Moolenaar 	modifiers |= MOD_MASK_SHIFT;
45636a0299d8SBram Moolenaar     if (code & 2)
45646a0299d8SBram Moolenaar 	modifiers |= MOD_MASK_ALT;
45656a0299d8SBram Moolenaar     if (code & 4)
45666a0299d8SBram Moolenaar 	modifiers |= MOD_MASK_CTRL;
45676a0299d8SBram Moolenaar     if (code & 8)
45686a0299d8SBram Moolenaar 	modifiers |= MOD_MASK_META;
45696a0299d8SBram Moolenaar     return modifiers;
45706a0299d8SBram Moolenaar }
45716a0299d8SBram Moolenaar 
45726a0299d8SBram Moolenaar     static int
modifiers2keycode(int modifiers,int * key,char_u * string)45736a0299d8SBram Moolenaar modifiers2keycode(int modifiers, int *key, char_u *string)
45746a0299d8SBram Moolenaar {
45756a0299d8SBram Moolenaar     int new_slen = 0;
45766a0299d8SBram Moolenaar 
45776a0299d8SBram Moolenaar     if (modifiers != 0)
45786a0299d8SBram Moolenaar     {
45796a0299d8SBram Moolenaar 	// Some keys have the modifier included.  Need to handle that here to
4580749bc952SBram Moolenaar 	// make mappings work.  This may result in a special key, such as
4581749bc952SBram Moolenaar 	// K_S_TAB.
45826a0299d8SBram Moolenaar 	*key = simplify_key(*key, &modifiers);
45836a0299d8SBram Moolenaar 	if (modifiers != 0)
45846a0299d8SBram Moolenaar 	{
45856a0299d8SBram Moolenaar 	    string[new_slen++] = K_SPECIAL;
45866a0299d8SBram Moolenaar 	    string[new_slen++] = (int)KS_MODIFIER;
45876a0299d8SBram Moolenaar 	    string[new_slen++] = modifiers;
45886a0299d8SBram Moolenaar 	}
45896a0299d8SBram Moolenaar     }
45906a0299d8SBram Moolenaar     return new_slen;
45916a0299d8SBram Moolenaar }
45926a0299d8SBram Moolenaar 
45930ca8b5baSBram Moolenaar #ifdef FEAT_TERMRESPONSE
45940ca8b5baSBram Moolenaar /*
45950ca8b5baSBram Moolenaar  * Handle a cursor position report.
45960ca8b5baSBram Moolenaar  */
4597218cb0fbSBram Moolenaar     static void
handle_u7_response(int * arg,char_u * tp UNUSED,int csi_len UNUSED)45980ca8b5baSBram Moolenaar handle_u7_response(int *arg, char_u *tp UNUSED, int csi_len UNUSED)
4599218cb0fbSBram Moolenaar {
4600218cb0fbSBram Moolenaar     if (arg[0] == 2 && arg[1] >= 2)
4601218cb0fbSBram Moolenaar     {
4602218cb0fbSBram Moolenaar 	char *aw = NULL;
4603218cb0fbSBram Moolenaar 
4604218cb0fbSBram Moolenaar 	LOG_TR(("Received U7 status: %s", tp));
4605218cb0fbSBram Moolenaar 	u7_status.tr_progress = STATUS_GOT;
4606218cb0fbSBram Moolenaar 	did_cursorhold = TRUE;
4607218cb0fbSBram Moolenaar 	if (arg[1] == 2)
4608218cb0fbSBram Moolenaar 	    aw = "single";
4609218cb0fbSBram Moolenaar 	else if (arg[1] == 3)
4610218cb0fbSBram Moolenaar 	    aw = "double";
4611218cb0fbSBram Moolenaar 	if (aw != NULL && STRCMP(aw, p_ambw) != 0)
4612218cb0fbSBram Moolenaar 	{
4613218cb0fbSBram Moolenaar 	    // Setting the option causes a screen redraw. Do
4614218cb0fbSBram Moolenaar 	    // that right away if possible, keeping any
4615218cb0fbSBram Moolenaar 	    // messages.
46160ca8b5baSBram Moolenaar 	    set_option_value((char_u *)"ambw", 0L, (char_u *)aw, 0);
4617218cb0fbSBram Moolenaar # ifdef DEBUG_TERMRESPONSE
4618218cb0fbSBram Moolenaar 	    {
4619218cb0fbSBram Moolenaar 		int r = redraw_asap(CLEAR);
4620218cb0fbSBram Moolenaar 
4621218cb0fbSBram Moolenaar 		log_tr("set 'ambiwidth', redraw_asap(): %d", r);
4622218cb0fbSBram Moolenaar 	    }
4623218cb0fbSBram Moolenaar # else
4624218cb0fbSBram Moolenaar 	    redraw_asap(CLEAR);
4625218cb0fbSBram Moolenaar # endif
4626218cb0fbSBram Moolenaar # ifdef FEAT_EVAL
4627218cb0fbSBram Moolenaar 	    set_vim_var_string(VV_TERMU7RESP, tp, csi_len);
4628218cb0fbSBram Moolenaar # endif
4629218cb0fbSBram Moolenaar 	}
4630218cb0fbSBram Moolenaar     }
4631218cb0fbSBram Moolenaar     else if (arg[0] == 3)
4632218cb0fbSBram Moolenaar     {
4633517f00f7SBram Moolenaar 	int value;
4634517f00f7SBram Moolenaar 
4635218cb0fbSBram Moolenaar 	LOG_TR(("Received compatibility test result: %s", tp));
4636218cb0fbSBram Moolenaar 	xcc_status.tr_progress = STATUS_GOT;
4637517f00f7SBram Moolenaar 
4638517f00f7SBram Moolenaar 	// Third row: xterm compatibility test.
4639517f00f7SBram Moolenaar 	// If the cursor is on the first column then the terminal can handle
4640517f00f7SBram Moolenaar 	// the request for cursor style and blinking.
4641517f00f7SBram Moolenaar 	value = arg[1] == 1 ? TPR_YES : TPR_NO;
4642517f00f7SBram Moolenaar 	term_props[TPR_CURSOR_STYLE].tpr_status = value;
4643517f00f7SBram Moolenaar 	term_props[TPR_CURSOR_BLINK].tpr_status = value;
4644218cb0fbSBram Moolenaar     }
4645218cb0fbSBram Moolenaar }
4646218cb0fbSBram Moolenaar 
4647218cb0fbSBram Moolenaar /*
4648517f00f7SBram Moolenaar  * Handle a response to T_CRV: {lead}{first}{x};{vers};{y}c
46498e7d6223SBram Moolenaar  * Xterm and alike use '>' for {first}.
4650517f00f7SBram Moolenaar  * Rxvt sends "{lead}?1;2c".
4651218cb0fbSBram Moolenaar  */
4652218cb0fbSBram Moolenaar     static void
handle_version_response(int first,int * arg,int argc,char_u * tp)4653218cb0fbSBram Moolenaar handle_version_response(int first, int *arg, int argc, char_u *tp)
4654218cb0fbSBram Moolenaar {
4655517f00f7SBram Moolenaar     // The xterm version.  It is set to zero when it can't be an actual xterm
4656517f00f7SBram Moolenaar     // version.
4657218cb0fbSBram Moolenaar     int version = arg[1];
4658218cb0fbSBram Moolenaar 
4659218cb0fbSBram Moolenaar     LOG_TR(("Received CRV response: %s", tp));
4660218cb0fbSBram Moolenaar     crv_status.tr_progress = STATUS_GOT;
4661218cb0fbSBram Moolenaar     did_cursorhold = TRUE;
4662218cb0fbSBram Moolenaar 
4663517f00f7SBram Moolenaar     // Reset terminal properties that are set based on the termresponse.
4664517f00f7SBram Moolenaar     // Mainly useful for tests that send the termresponse multiple times.
46650c0eddd3SBram Moolenaar     // For testing all props can be reset.
4666142499deSBram Moolenaar     init_term_props(
4667142499deSBram Moolenaar #ifdef FEAT_EVAL
4668142499deSBram Moolenaar 	    reset_term_props_on_termresponse
4669142499deSBram Moolenaar #else
4670142499deSBram Moolenaar 	    FALSE
4671142499deSBram Moolenaar #endif
4672142499deSBram Moolenaar 	    );
4673517f00f7SBram Moolenaar 
4674218cb0fbSBram Moolenaar     // If this code starts with CSI, you can bet that the
4675218cb0fbSBram Moolenaar     // terminal uses 8-bit codes.
4676218cb0fbSBram Moolenaar     if (tp[0] == CSI)
4677218cb0fbSBram Moolenaar 	switch_to_8bit();
4678218cb0fbSBram Moolenaar 
4679218cb0fbSBram Moolenaar     // Screen sends 40500.
4680218cb0fbSBram Moolenaar     // rxvt sends its version number: "20703" is 2.7.3.
4681218cb0fbSBram Moolenaar     // Ignore it for when the user has set 'term' to xterm,
4682218cb0fbSBram Moolenaar     // even though it's an rxvt.
4683218cb0fbSBram Moolenaar     if (version > 20000)
4684218cb0fbSBram Moolenaar 	version = 0;
4685218cb0fbSBram Moolenaar 
4686517f00f7SBram Moolenaar     // Figure out more if the reeponse is CSI > 99 ; 99 ; 99 c
4687218cb0fbSBram Moolenaar     if (first == '>' && argc == 3)
4688218cb0fbSBram Moolenaar     {
4689218cb0fbSBram Moolenaar 	int need_flush = FALSE;
4690218cb0fbSBram Moolenaar 
4691218cb0fbSBram Moolenaar 	// mintty 2.9.5 sends 77;20905;0c.
4692218cb0fbSBram Moolenaar 	// (77 is ASCII 'M' for mintty.)
4693218cb0fbSBram Moolenaar 	if (arg[0] == 77)
4694517f00f7SBram Moolenaar 	{
4695517f00f7SBram Moolenaar 	    // mintty can do SGR mouse reporting
4696517f00f7SBram Moolenaar 	    term_props[TPR_MOUSE].tpr_status = TPR_MOUSE_SGR;
4697517f00f7SBram Moolenaar 	}
4698218cb0fbSBram Moolenaar 
4699517f00f7SBram Moolenaar 	// If xterm version >= 141 try to get termcap codes.  For other
4700517f00f7SBram Moolenaar 	// terminals the request should be ignored.
4701218cb0fbSBram Moolenaar 	if (version >= 141)
4702218cb0fbSBram Moolenaar 	{
4703218cb0fbSBram Moolenaar 	    LOG_TR(("Enable checking for XT codes"));
4704218cb0fbSBram Moolenaar 	    check_for_codes = TRUE;
4705218cb0fbSBram Moolenaar 	    need_gather = TRUE;
4706218cb0fbSBram Moolenaar 	    req_codes_from_term();
4707218cb0fbSBram Moolenaar 	}
4708218cb0fbSBram Moolenaar 
4709218cb0fbSBram Moolenaar 	// libvterm sends 0;100;0
4710218cb0fbSBram Moolenaar 	if (version == 100 && arg[0] == 0 && arg[2] == 0)
4711218cb0fbSBram Moolenaar 	{
4712218cb0fbSBram Moolenaar 	    // If run from Vim $COLORS is set to the number of
4713218cb0fbSBram Moolenaar 	    // colors the terminal supports.  Otherwise assume
4714218cb0fbSBram Moolenaar 	    // 256, libvterm supports even more.
4715218cb0fbSBram Moolenaar 	    if (mch_getenv((char_u *)"COLORS") == NULL)
4716218cb0fbSBram Moolenaar 		may_adjust_color_count(256);
4717218cb0fbSBram Moolenaar 	    // Libvterm can handle SGR mouse reporting.
4718517f00f7SBram Moolenaar 	    term_props[TPR_MOUSE].tpr_status = TPR_MOUSE_SGR;
4719218cb0fbSBram Moolenaar 	}
4720218cb0fbSBram Moolenaar 
4721218cb0fbSBram Moolenaar 	if (version == 95)
4722218cb0fbSBram Moolenaar 	{
4723218cb0fbSBram Moolenaar 	    // Mac Terminal.app sends 1;95;0
4724218cb0fbSBram Moolenaar 	    if (arg[0] == 1 && arg[2] == 0)
4725218cb0fbSBram Moolenaar 	    {
4726517f00f7SBram Moolenaar 		term_props[TPR_UNDERLINE_RGB].tpr_status = TPR_YES;
4727517f00f7SBram Moolenaar 		term_props[TPR_MOUSE].tpr_status = TPR_MOUSE_SGR;
4728218cb0fbSBram Moolenaar 	    }
4729218cb0fbSBram Moolenaar 	    // iTerm2 sends 0;95;0
4730218cb0fbSBram Moolenaar 	    else if (arg[0] == 0 && arg[2] == 0)
4731517f00f7SBram Moolenaar 	    {
4732517f00f7SBram Moolenaar 		// iTerm2 can do SGR mouse reporting
4733517f00f7SBram Moolenaar 		term_props[TPR_MOUSE].tpr_status = TPR_MOUSE_SGR;
4734517f00f7SBram Moolenaar 	    }
4735218cb0fbSBram Moolenaar 	    // old iTerm2 sends 0;95;
4736218cb0fbSBram Moolenaar 	    else if (arg[0] == 0 && arg[2] == -1)
4737517f00f7SBram Moolenaar 		term_props[TPR_UNDERLINE_RGB].tpr_status = TPR_YES;
4738218cb0fbSBram Moolenaar 	}
4739218cb0fbSBram Moolenaar 
4740218cb0fbSBram Moolenaar 	// screen sends 83;40500;0 83 is 'S' in ASCII.
4741218cb0fbSBram Moolenaar 	if (arg[0] == 83)
4742218cb0fbSBram Moolenaar 	{
4743517f00f7SBram Moolenaar 	    // screen supports SGR mouse codes since 4.7.0
4744517f00f7SBram Moolenaar 	    if (arg[1] >= 40700)
4745517f00f7SBram Moolenaar 		term_props[TPR_MOUSE].tpr_status = TPR_MOUSE_SGR;
4746517f00f7SBram Moolenaar 	    else
4747517f00f7SBram Moolenaar 		term_props[TPR_MOUSE].tpr_status = TPR_MOUSE_XTERM;
4748517f00f7SBram Moolenaar 	}
4749517f00f7SBram Moolenaar 
4750517f00f7SBram Moolenaar 	// If no recognized terminal has set mouse behavior, assume xterm.
4751517f00f7SBram Moolenaar 	if (term_props[TPR_MOUSE].tpr_status == TPR_UNKNOWN)
4752517f00f7SBram Moolenaar 	{
4753517f00f7SBram Moolenaar 	    // Xterm version 277 supports SGR.
4754517f00f7SBram Moolenaar 	    // Xterm version >= 95 supports mouse dragging.
4755517f00f7SBram Moolenaar 	    if (version >= 277)
4756517f00f7SBram Moolenaar 		term_props[TPR_MOUSE].tpr_status = TPR_MOUSE_SGR;
4757218cb0fbSBram Moolenaar 	    else if (version >= 95)
4758517f00f7SBram Moolenaar 		term_props[TPR_MOUSE].tpr_status = TPR_MOUSE_XTERM2;
4759218cb0fbSBram Moolenaar 	}
4760218cb0fbSBram Moolenaar 
4761218cb0fbSBram Moolenaar 	// Detect terminals that set $TERM to something like
4762218cb0fbSBram Moolenaar 	// "xterm-256color" but are not fully xterm compatible.
4763517f00f7SBram Moolenaar 	//
4764218cb0fbSBram Moolenaar 	// Gnome terminal sends 1;3801;0, 1;4402;0 or 1;2501;0.
47658dff4cbfSBram Moolenaar 	// Newer Gnome-terminal sends 65;6001;1.
4766218cb0fbSBram Moolenaar 	// xfce4-terminal sends 1;2802;0.
4767218cb0fbSBram Moolenaar 	// screen sends 83;40500;0
4768218cb0fbSBram Moolenaar 	// Assuming any version number over 2500 is not an
4769218cb0fbSBram Moolenaar 	// xterm (without the limit for rxvt and screen).
4770218cb0fbSBram Moolenaar 	if (arg[1] >= 2500)
4771517f00f7SBram Moolenaar 	    term_props[TPR_UNDERLINE_RGB].tpr_status = TPR_YES;
4772218cb0fbSBram Moolenaar 
4773218cb0fbSBram Moolenaar 	else if (version == 136 && arg[2] == 0)
4774218cb0fbSBram Moolenaar 	{
4775517f00f7SBram Moolenaar 	    term_props[TPR_UNDERLINE_RGB].tpr_status = TPR_YES;
4776218cb0fbSBram Moolenaar 
4777517f00f7SBram Moolenaar 	    // PuTTY sends 0;136;0
4778517f00f7SBram Moolenaar 	    if (arg[0] == 0)
4779517f00f7SBram Moolenaar 	    {
4780517f00f7SBram Moolenaar 		// supports sgr-like mouse reporting.
4781517f00f7SBram Moolenaar 		term_props[TPR_MOUSE].tpr_status = TPR_MOUSE_SGR;
4782517f00f7SBram Moolenaar 	    }
4783517f00f7SBram Moolenaar 	    // vandyke SecureCRT sends 1;136;0
4784218cb0fbSBram Moolenaar 	}
4785218cb0fbSBram Moolenaar 
4786218cb0fbSBram Moolenaar 	// Konsole sends 0;115;0
4787218cb0fbSBram Moolenaar 	else if (version == 115 && arg[0] == 0 && arg[2] == 0)
4788517f00f7SBram Moolenaar 	    term_props[TPR_UNDERLINE_RGB].tpr_status = TPR_YES;
4789218cb0fbSBram Moolenaar 
4790218cb0fbSBram Moolenaar 	// GNU screen sends 83;30600;0, 83;40500;0, etc.
4791517f00f7SBram Moolenaar 	// 30600/40500 is a version number of GNU screen. DA2 support is added
4792517f00f7SBram Moolenaar 	// on 3.6.  DCS string has a special meaning to GNU screen, but xterm
4793517f00f7SBram Moolenaar 	// compatibility checking does not detect GNU screen.
4794517f00f7SBram Moolenaar 	if (arg[0] == 83 && arg[1] >= 30600)
4795517f00f7SBram Moolenaar 	{
4796517f00f7SBram Moolenaar 	    term_props[TPR_CURSOR_STYLE].tpr_status = TPR_NO;
4797517f00f7SBram Moolenaar 	    term_props[TPR_CURSOR_BLINK].tpr_status = TPR_NO;
4798517f00f7SBram Moolenaar 	}
4799218cb0fbSBram Moolenaar 
4800218cb0fbSBram Moolenaar 	// Xterm first responded to this request at patch level
4801517f00f7SBram Moolenaar 	// 95, so assume anything below 95 is not xterm and hopefully supports
4802517f00f7SBram Moolenaar 	// the underline RGB color sequence.
4803218cb0fbSBram Moolenaar 	if (version < 95)
4804517f00f7SBram Moolenaar 	    term_props[TPR_UNDERLINE_RGB].tpr_status = TPR_YES;
4805218cb0fbSBram Moolenaar 
4806517f00f7SBram Moolenaar 	// Getting the cursor style is only supported properly by xterm since
4807517f00f7SBram Moolenaar 	// version 279 (otherwise it returns 0x18).
4808517f00f7SBram Moolenaar 	if (version < 279)
4809517f00f7SBram Moolenaar 	    term_props[TPR_CURSOR_STYLE].tpr_status = TPR_NO;
4810517f00f7SBram Moolenaar 
4811517f00f7SBram Moolenaar 	/*
4812517f00f7SBram Moolenaar 	 * Take action on the detected properties.
4813517f00f7SBram Moolenaar 	 */
4814517f00f7SBram Moolenaar 
4815517f00f7SBram Moolenaar 	// Unless the underline RGB color is expected to work, disable "t_8u".
4816517f00f7SBram Moolenaar 	// It does not work for the real Xterm, it resets the background color.
48178dff4cbfSBram Moolenaar 	if (term_props[TPR_UNDERLINE_RGB].tpr_status != TPR_YES && *T_8U != NUL)
48188e20f75eSBram Moolenaar 	    set_string_option_direct((char_u *)"t_8u", -1, (char_u *)"",
48198e20f75eSBram Moolenaar 								  OPT_FREE, 0);
4820218cb0fbSBram Moolenaar 
4821517f00f7SBram Moolenaar 	// Only set 'ttymouse' automatically if it was not set
4822517f00f7SBram Moolenaar 	// by the user already.
4823517f00f7SBram Moolenaar 	if (!option_was_set((char_u *)"ttym")
4824517f00f7SBram Moolenaar 		&& (term_props[TPR_MOUSE].tpr_status == TPR_MOUSE_XTERM2
4825517f00f7SBram Moolenaar 		    || term_props[TPR_MOUSE].tpr_status == TPR_MOUSE_SGR))
4826517f00f7SBram Moolenaar 	{
4827517f00f7SBram Moolenaar 	    set_option_value((char_u *)"ttym", 0L,
4828517f00f7SBram Moolenaar 		    term_props[TPR_MOUSE].tpr_status == TPR_MOUSE_SGR
4829517f00f7SBram Moolenaar 				    ? (char_u *)"sgr" : (char_u *)"xterm2", 0);
4830517f00f7SBram Moolenaar 	}
4831517f00f7SBram Moolenaar 
4832218cb0fbSBram Moolenaar 	// Only request the cursor style if t_SH and t_RS are
4833218cb0fbSBram Moolenaar 	// set. Only supported properly by xterm since version
4834218cb0fbSBram Moolenaar 	// 279 (otherwise it returns 0x18).
4835517f00f7SBram Moolenaar 	// Only when getting the cursor style was detected to work.
4836218cb0fbSBram Moolenaar 	// Not for Terminal.app, it can't handle t_RS, it
4837218cb0fbSBram Moolenaar 	// echoes the characters to the screen.
4838218cb0fbSBram Moolenaar 	if (rcs_status.tr_progress == STATUS_GET
4839517f00f7SBram Moolenaar 		&& term_props[TPR_CURSOR_STYLE].tpr_status == TPR_YES
4840218cb0fbSBram Moolenaar 		&& *T_CSH != NUL
4841218cb0fbSBram Moolenaar 		&& *T_CRS != NUL)
4842218cb0fbSBram Moolenaar 	{
484386394aa9SBram Moolenaar #ifdef FEAT_JOB_CHANNEL
484486394aa9SBram Moolenaar 	    ch_log_output = TRUE;
484586394aa9SBram Moolenaar #endif
4846218cb0fbSBram Moolenaar 	    LOG_TR(("Sending cursor style request"));
4847218cb0fbSBram Moolenaar 	    out_str(T_CRS);
4848218cb0fbSBram Moolenaar 	    termrequest_sent(&rcs_status);
4849218cb0fbSBram Moolenaar 	    need_flush = TRUE;
4850218cb0fbSBram Moolenaar 	}
4851218cb0fbSBram Moolenaar 
4852218cb0fbSBram Moolenaar 	// Only request the cursor blink mode if t_RC set. Not
4853218cb0fbSBram Moolenaar 	// for Gnome terminal, it can't handle t_RC, it
4854218cb0fbSBram Moolenaar 	// echoes the characters to the screen.
4855517f00f7SBram Moolenaar 	// Only when getting the cursor style was detected to work.
4856218cb0fbSBram Moolenaar 	if (rbm_status.tr_progress == STATUS_GET
4857517f00f7SBram Moolenaar 		&& term_props[TPR_CURSOR_BLINK].tpr_status == TPR_YES
4858218cb0fbSBram Moolenaar 		&& *T_CRC != NUL)
4859218cb0fbSBram Moolenaar 	{
486086394aa9SBram Moolenaar #ifdef FEAT_JOB_CHANNEL
486186394aa9SBram Moolenaar 	    ch_log_output = TRUE;
486286394aa9SBram Moolenaar #endif
4863218cb0fbSBram Moolenaar 	    LOG_TR(("Sending cursor blink mode request"));
4864218cb0fbSBram Moolenaar 	    out_str(T_CRC);
4865218cb0fbSBram Moolenaar 	    termrequest_sent(&rbm_status);
4866218cb0fbSBram Moolenaar 	    need_flush = TRUE;
4867218cb0fbSBram Moolenaar 	}
4868218cb0fbSBram Moolenaar 
4869218cb0fbSBram Moolenaar 	if (need_flush)
4870218cb0fbSBram Moolenaar 	    out_flush();
4871218cb0fbSBram Moolenaar     }
4872218cb0fbSBram Moolenaar }
4873218cb0fbSBram Moolenaar 
4874218cb0fbSBram Moolenaar /*
4875218cb0fbSBram Moolenaar  * Handle a sequence with key and modifier, one of:
4876218cb0fbSBram Moolenaar  *	{lead}27;{modifier};{key}~
4877218cb0fbSBram Moolenaar  *	{lead}{key};{modifier}u
4878218cb0fbSBram Moolenaar  * Returns the difference in length.
4879218cb0fbSBram Moolenaar  */
4880218cb0fbSBram Moolenaar     static int
handle_key_with_modifier(int * arg,int trail,int csi_len,int offset,char_u * buf,int bufsize,int * buflen)4881218cb0fbSBram Moolenaar handle_key_with_modifier(
4882218cb0fbSBram Moolenaar 	int	*arg,
4883218cb0fbSBram Moolenaar 	int	trail,
4884218cb0fbSBram Moolenaar 	int	csi_len,
4885218cb0fbSBram Moolenaar 	int	offset,
4886218cb0fbSBram Moolenaar 	char_u	*buf,
4887218cb0fbSBram Moolenaar 	int	bufsize,
4888218cb0fbSBram Moolenaar 	int	*buflen)
4889218cb0fbSBram Moolenaar {
4890218cb0fbSBram Moolenaar     int	    key;
4891218cb0fbSBram Moolenaar     int	    modifiers;
4892218cb0fbSBram Moolenaar     int	    new_slen;
4893218cb0fbSBram Moolenaar     char_u  string[MAX_KEY_CODE_LEN + 1];
4894218cb0fbSBram Moolenaar 
4895218cb0fbSBram Moolenaar     seenModifyOtherKeys = TRUE;
4896218cb0fbSBram Moolenaar     if (trail == 'u')
4897218cb0fbSBram Moolenaar 	key = arg[0];
4898218cb0fbSBram Moolenaar     else
4899218cb0fbSBram Moolenaar 	key = arg[2];
4900218cb0fbSBram Moolenaar 
4901218cb0fbSBram Moolenaar     modifiers = decode_modifiers(arg[1]);
4902218cb0fbSBram Moolenaar 
49034e2114e9SBram Moolenaar     // Some keys need adjustment when the Ctrl modifier is used.
49044e2114e9SBram Moolenaar     key = may_adjust_key_for_ctrl(modifiers, key);
49054e2114e9SBram Moolenaar 
4906ef6746f6SBram Moolenaar     // May remove the shift modifier if it's already included in the key.
4907ef6746f6SBram Moolenaar     modifiers = may_remove_shift_modifier(modifiers, key);
4908218cb0fbSBram Moolenaar 
4909218cb0fbSBram Moolenaar     // insert modifiers with KS_MODIFIER
4910218cb0fbSBram Moolenaar     new_slen = modifiers2keycode(modifiers, &key, string);
4911218cb0fbSBram Moolenaar 
4912749bc952SBram Moolenaar     if (IS_SPECIAL(key))
4913749bc952SBram Moolenaar     {
4914749bc952SBram Moolenaar 	string[new_slen++] = K_SPECIAL;
4915749bc952SBram Moolenaar 	string[new_slen++] = KEY2TERMCAP0(key);
4916749bc952SBram Moolenaar 	string[new_slen++] = KEY2TERMCAP1(key);
4917749bc952SBram Moolenaar     }
4918749bc952SBram Moolenaar     else if (has_mbyte)
4919218cb0fbSBram Moolenaar 	new_slen += (*mb_char2bytes)(key, string + new_slen);
4920218cb0fbSBram Moolenaar     else
4921218cb0fbSBram Moolenaar 	string[new_slen++] = key;
4922218cb0fbSBram Moolenaar 
4923218cb0fbSBram Moolenaar     if (put_string_in_typebuf(offset, csi_len, string, new_slen,
4924218cb0fbSBram Moolenaar 						 buf, bufsize, buflen) == FAIL)
4925218cb0fbSBram Moolenaar 	return -1;
4926218cb0fbSBram Moolenaar     return new_slen - csi_len + offset;
4927218cb0fbSBram Moolenaar }
4928218cb0fbSBram Moolenaar 
4929218cb0fbSBram Moolenaar /*
4930218cb0fbSBram Moolenaar  * Handle a CSI escape sequence.
4931517f00f7SBram Moolenaar  * - Xterm version string.
4932218cb0fbSBram Moolenaar  *
4933218cb0fbSBram Moolenaar  * - Cursor position report: {lead}{row};{col}R
4934218cb0fbSBram Moolenaar  *   The final byte must be 'R'. It is used for checking the
4935218cb0fbSBram Moolenaar  *   ambiguous-width character state.
4936218cb0fbSBram Moolenaar  *
4937218cb0fbSBram Moolenaar  * - window position reply: {lead}3;{x};{y}t
4938218cb0fbSBram Moolenaar  *
4939218cb0fbSBram Moolenaar  * - key with modifiers when modifyOtherKeys is enabled:
4940218cb0fbSBram Moolenaar  *	    {lead}27;{modifier};{key}~
4941218cb0fbSBram Moolenaar  *	    {lead}{key};{modifier}u
4942218cb0fbSBram Moolenaar  * Return 0 for no match, -1 for partial match, > 0 for full match.
4943218cb0fbSBram Moolenaar  */
4944218cb0fbSBram Moolenaar     static int
handle_csi(char_u * tp,int len,char_u * argp,int offset,char_u * buf,int bufsize,int * buflen,char_u * key_name,int * slen)4945218cb0fbSBram Moolenaar handle_csi(
4946218cb0fbSBram Moolenaar 	char_u	*tp,
4947218cb0fbSBram Moolenaar 	int	len,
4948218cb0fbSBram Moolenaar 	char_u	*argp,
4949218cb0fbSBram Moolenaar 	int	offset,
4950218cb0fbSBram Moolenaar 	char_u  *buf,
4951218cb0fbSBram Moolenaar 	int	bufsize,
4952218cb0fbSBram Moolenaar 	int	*buflen,
4953218cb0fbSBram Moolenaar 	char_u	*key_name,
4954218cb0fbSBram Moolenaar 	int	*slen)
4955218cb0fbSBram Moolenaar {
4956218cb0fbSBram Moolenaar     int		first = -1;  // optional char right after {lead}
4957218cb0fbSBram Moolenaar     int		trail;	     // char that ends CSI sequence
4958218cb0fbSBram Moolenaar     int		arg[3] = {-1, -1, -1};	// argument numbers
4959218cb0fbSBram Moolenaar     int		argc;			// number of arguments
4960218cb0fbSBram Moolenaar     char_u	*ap = argp;
4961218cb0fbSBram Moolenaar     int		csi_len;
4962218cb0fbSBram Moolenaar 
4963218cb0fbSBram Moolenaar     // Check for non-digit after CSI.
4964218cb0fbSBram Moolenaar     if (!VIM_ISDIGIT(*ap))
4965218cb0fbSBram Moolenaar 	first = *ap++;
4966218cb0fbSBram Moolenaar 
4967218cb0fbSBram Moolenaar     // Find up to three argument numbers.
4968218cb0fbSBram Moolenaar     for (argc = 0; argc < 3; )
4969218cb0fbSBram Moolenaar     {
4970218cb0fbSBram Moolenaar 	if (ap >= tp + len)
4971218cb0fbSBram Moolenaar 	    return -1;
4972218cb0fbSBram Moolenaar 	if (*ap == ';')
4973218cb0fbSBram Moolenaar 	    arg[argc++] = -1;  // omitted number
4974218cb0fbSBram Moolenaar 	else if (VIM_ISDIGIT(*ap))
4975218cb0fbSBram Moolenaar 	{
4976218cb0fbSBram Moolenaar 	    arg[argc] = 0;
4977218cb0fbSBram Moolenaar 	    for (;;)
4978218cb0fbSBram Moolenaar 	    {
4979218cb0fbSBram Moolenaar 		if (ap >= tp + len)
4980218cb0fbSBram Moolenaar 		    return -1;
4981218cb0fbSBram Moolenaar 		if (!VIM_ISDIGIT(*ap))
4982218cb0fbSBram Moolenaar 		    break;
4983218cb0fbSBram Moolenaar 		arg[argc] = arg[argc] * 10 + (*ap - '0');
4984218cb0fbSBram Moolenaar 		++ap;
4985218cb0fbSBram Moolenaar 	    }
4986218cb0fbSBram Moolenaar 	    ++argc;
4987218cb0fbSBram Moolenaar 	}
4988218cb0fbSBram Moolenaar 	if (*ap == ';')
4989218cb0fbSBram Moolenaar 	    ++ap;
4990218cb0fbSBram Moolenaar 	else
4991218cb0fbSBram Moolenaar 	    break;
4992218cb0fbSBram Moolenaar     }
4993218cb0fbSBram Moolenaar 
4994218cb0fbSBram Moolenaar     // mrxvt has been reported to have "+" in the version. Assume
4995218cb0fbSBram Moolenaar     // the escape sequence ends with a letter or one of "{|}~".
4996218cb0fbSBram Moolenaar     while (ap < tp + len
4997218cb0fbSBram Moolenaar 	    && !(*ap >= '{' && *ap <= '~')
4998218cb0fbSBram Moolenaar 	    && !ASCII_ISALPHA(*ap))
4999218cb0fbSBram Moolenaar 	++ap;
5000218cb0fbSBram Moolenaar     if (ap >= tp + len)
5001218cb0fbSBram Moolenaar 	return -1;
5002218cb0fbSBram Moolenaar     trail = *ap;
5003218cb0fbSBram Moolenaar     csi_len = (int)(ap - tp) + 1;
5004218cb0fbSBram Moolenaar 
5005218cb0fbSBram Moolenaar     // Cursor position report: Eat it when there are 2 arguments
5006218cb0fbSBram Moolenaar     // and it ends in 'R'. Also when u7_status is not "sent", it
5007218cb0fbSBram Moolenaar     // may be from a previous Vim that just exited.  But not for
5008218cb0fbSBram Moolenaar     // <S-F3>, it sends something similar, check for row and column
5009218cb0fbSBram Moolenaar     // to make sense.
5010218cb0fbSBram Moolenaar     if (first == -1 && argc == 2 && trail == 'R')
5011218cb0fbSBram Moolenaar     {
5012218cb0fbSBram Moolenaar 	handle_u7_response(arg, tp, csi_len);
5013218cb0fbSBram Moolenaar 
5014218cb0fbSBram Moolenaar 	key_name[0] = (int)KS_EXTRA;
5015218cb0fbSBram Moolenaar 	key_name[1] = (int)KE_IGNORE;
5016218cb0fbSBram Moolenaar 	*slen = csi_len;
5017218cb0fbSBram Moolenaar     }
5018218cb0fbSBram Moolenaar 
5019218cb0fbSBram Moolenaar     // Version string: Eat it when there is at least one digit and
5020218cb0fbSBram Moolenaar     // it ends in 'c'
5021218cb0fbSBram Moolenaar     else if (*T_CRV != NUL && ap > argp + 1 && trail == 'c')
5022218cb0fbSBram Moolenaar     {
5023218cb0fbSBram Moolenaar 	handle_version_response(first, arg, argc, tp);
5024218cb0fbSBram Moolenaar 
5025218cb0fbSBram Moolenaar 	*slen = csi_len;
5026218cb0fbSBram Moolenaar # ifdef FEAT_EVAL
5027218cb0fbSBram Moolenaar 	set_vim_var_string(VV_TERMRESPONSE, tp, *slen);
5028218cb0fbSBram Moolenaar # endif
5029218cb0fbSBram Moolenaar 	apply_autocmds(EVENT_TERMRESPONSE,
5030218cb0fbSBram Moolenaar 					NULL, NULL, FALSE, curbuf);
5031218cb0fbSBram Moolenaar 	key_name[0] = (int)KS_EXTRA;
5032218cb0fbSBram Moolenaar 	key_name[1] = (int)KE_IGNORE;
5033218cb0fbSBram Moolenaar     }
5034218cb0fbSBram Moolenaar 
5035218cb0fbSBram Moolenaar     // Check blinking cursor from xterm:
5036218cb0fbSBram Moolenaar     // {lead}?12;1$y       set
5037218cb0fbSBram Moolenaar     // {lead}?12;2$y       not set
5038218cb0fbSBram Moolenaar     //
5039218cb0fbSBram Moolenaar     // {lead} can be <Esc>[ or CSI
5040218cb0fbSBram Moolenaar     else if (rbm_status.tr_progress == STATUS_SENT
5041218cb0fbSBram Moolenaar 	    && first == '?'
5042218cb0fbSBram Moolenaar 	    && ap == argp + 6
5043218cb0fbSBram Moolenaar 	    && arg[0] == 12
5044218cb0fbSBram Moolenaar 	    && ap[-1] == '$'
5045218cb0fbSBram Moolenaar 	    && trail == 'y')
5046218cb0fbSBram Moolenaar     {
5047218cb0fbSBram Moolenaar 	initial_cursor_blink = (arg[1] == '1');
5048218cb0fbSBram Moolenaar 	rbm_status.tr_progress = STATUS_GOT;
5049218cb0fbSBram Moolenaar 	LOG_TR(("Received cursor blinking mode response: %s", tp));
5050218cb0fbSBram Moolenaar 	key_name[0] = (int)KS_EXTRA;
5051218cb0fbSBram Moolenaar 	key_name[1] = (int)KE_IGNORE;
5052218cb0fbSBram Moolenaar 	*slen = csi_len;
5053218cb0fbSBram Moolenaar # ifdef FEAT_EVAL
5054218cb0fbSBram Moolenaar 	set_vim_var_string(VV_TERMBLINKRESP, tp, *slen);
5055218cb0fbSBram Moolenaar # endif
5056218cb0fbSBram Moolenaar     }
5057218cb0fbSBram Moolenaar 
5058218cb0fbSBram Moolenaar     // Check for a window position response from the terminal:
5059218cb0fbSBram Moolenaar     //       {lead}3;{x};{y}t
5060218cb0fbSBram Moolenaar     else if (did_request_winpos && argc == 3 && arg[0] == 3
5061218cb0fbSBram Moolenaar 						   && trail == 't')
5062218cb0fbSBram Moolenaar     {
5063218cb0fbSBram Moolenaar 	winpos_x = arg[1];
5064218cb0fbSBram Moolenaar 	winpos_y = arg[2];
5065218cb0fbSBram Moolenaar 	// got finished code: consume it
5066218cb0fbSBram Moolenaar 	key_name[0] = (int)KS_EXTRA;
5067218cb0fbSBram Moolenaar 	key_name[1] = (int)KE_IGNORE;
5068218cb0fbSBram Moolenaar 	*slen = csi_len;
5069218cb0fbSBram Moolenaar 
5070218cb0fbSBram Moolenaar 	if (--did_request_winpos <= 0)
5071218cb0fbSBram Moolenaar 	    winpos_status.tr_progress = STATUS_GOT;
5072218cb0fbSBram Moolenaar     }
5073218cb0fbSBram Moolenaar 
5074218cb0fbSBram Moolenaar     // Key with modifier:
5075218cb0fbSBram Moolenaar     //	{lead}27;{modifier};{key}~
5076218cb0fbSBram Moolenaar     //	{lead}{key};{modifier}u
5077218cb0fbSBram Moolenaar     else if ((arg[0] == 27 && argc == 3 && trail == '~')
5078218cb0fbSBram Moolenaar 	    || (argc == 2 && trail == 'u'))
5079218cb0fbSBram Moolenaar     {
5080218cb0fbSBram Moolenaar 	return len + handle_key_with_modifier(arg, trail,
5081218cb0fbSBram Moolenaar 			    csi_len, offset, buf, bufsize, buflen);
5082218cb0fbSBram Moolenaar     }
5083218cb0fbSBram Moolenaar 
5084218cb0fbSBram Moolenaar     // else: Unknown CSI sequence.  We could drop it, but then the
5085218cb0fbSBram Moolenaar     // user can't create a map for it.
5086218cb0fbSBram Moolenaar     return 0;
5087218cb0fbSBram Moolenaar }
5088218cb0fbSBram Moolenaar 
5089218cb0fbSBram Moolenaar /*
5090218cb0fbSBram Moolenaar  * Handle an OSC sequence, fore/background color response from the terminal:
5091218cb0fbSBram Moolenaar  *
5092218cb0fbSBram Moolenaar  *       {lead}{code};rgb:{rrrr}/{gggg}/{bbbb}{tail}
5093218cb0fbSBram Moolenaar  * or    {lead}{code};rgb:{rr}/{gg}/{bb}{tail}
5094218cb0fbSBram Moolenaar  *
5095218cb0fbSBram Moolenaar  * {code} is 10 for foreground, 11 for background
5096218cb0fbSBram Moolenaar  * {lead} can be <Esc>] or OSC
5097218cb0fbSBram Moolenaar  * {tail} can be '\007', <Esc>\ or STERM.
5098218cb0fbSBram Moolenaar  *
5099218cb0fbSBram Moolenaar  * Consume any code that starts with "{lead}11;", it's also
5100218cb0fbSBram Moolenaar  * possible that "rgba" is following.
5101218cb0fbSBram Moolenaar  */
5102218cb0fbSBram Moolenaar     static int
handle_osc(char_u * tp,char_u * argp,int len,char_u * key_name,int * slen)5103218cb0fbSBram Moolenaar handle_osc(char_u *tp, char_u *argp, int len, char_u *key_name, int *slen)
5104218cb0fbSBram Moolenaar {
5105218cb0fbSBram Moolenaar     int		i, j;
5106218cb0fbSBram Moolenaar 
5107218cb0fbSBram Moolenaar     j = 1 + (tp[0] == ESC);
5108218cb0fbSBram Moolenaar     if (len >= j + 3 && (argp[0] != '1'
5109218cb0fbSBram Moolenaar 			     || (argp[1] != '1' && argp[1] != '0')
5110218cb0fbSBram Moolenaar 			     || argp[2] != ';'))
5111218cb0fbSBram Moolenaar 	i = 0; // no match
5112218cb0fbSBram Moolenaar     else
5113218cb0fbSBram Moolenaar 	for (i = j; i < len; ++i)
5114218cb0fbSBram Moolenaar 	    if (tp[i] == '\007' || (tp[0] == OSC ? tp[i] == STERM
5115218cb0fbSBram Moolenaar 			: (tp[i] == ESC && i + 1 < len && tp[i + 1] == '\\')))
5116218cb0fbSBram Moolenaar 	    {
5117218cb0fbSBram Moolenaar 		int is_bg = argp[1] == '1';
5118218cb0fbSBram Moolenaar 		int is_4digit = i - j >= 21 && tp[j + 11] == '/'
5119218cb0fbSBram Moolenaar 						  && tp[j + 16] == '/';
5120218cb0fbSBram Moolenaar 
5121218cb0fbSBram Moolenaar 		if (i - j >= 15 && STRNCMP(tp + j + 3, "rgb:", 4) == 0
5122218cb0fbSBram Moolenaar 			    && (is_4digit
5123218cb0fbSBram Moolenaar 				   || (tp[j + 9] == '/' && tp[i + 12 == '/'])))
5124218cb0fbSBram Moolenaar 		{
5125218cb0fbSBram Moolenaar 		    char_u *tp_r = tp + j + 7;
5126218cb0fbSBram Moolenaar 		    char_u *tp_g = tp + j + (is_4digit ? 12 : 10);
5127218cb0fbSBram Moolenaar 		    char_u *tp_b = tp + j + (is_4digit ? 17 : 13);
5128218cb0fbSBram Moolenaar # ifdef FEAT_TERMINAL
5129218cb0fbSBram Moolenaar 		    int rval, gval, bval;
5130218cb0fbSBram Moolenaar 
5131218cb0fbSBram Moolenaar 		    rval = hexhex2nr(tp_r);
5132218cb0fbSBram Moolenaar 		    gval = hexhex2nr(tp_b);
5133218cb0fbSBram Moolenaar 		    bval = hexhex2nr(tp_g);
5134218cb0fbSBram Moolenaar # endif
5135218cb0fbSBram Moolenaar 		    if (is_bg)
5136218cb0fbSBram Moolenaar 		    {
5137218cb0fbSBram Moolenaar 			char *new_bg_val = (3 * '6' < *tp_r + *tp_g +
5138218cb0fbSBram Moolenaar 					     *tp_b) ? "light" : "dark";
5139218cb0fbSBram Moolenaar 
5140218cb0fbSBram Moolenaar 			LOG_TR(("Received RBG response: %s", tp));
5141218cb0fbSBram Moolenaar 			rbg_status.tr_progress = STATUS_GOT;
5142218cb0fbSBram Moolenaar # ifdef FEAT_TERMINAL
5143218cb0fbSBram Moolenaar 			bg_r = rval;
5144218cb0fbSBram Moolenaar 			bg_g = gval;
5145218cb0fbSBram Moolenaar 			bg_b = bval;
5146218cb0fbSBram Moolenaar # endif
5147218cb0fbSBram Moolenaar 			if (!option_was_set((char_u *)"bg")
5148218cb0fbSBram Moolenaar 				      && STRCMP(p_bg, new_bg_val) != 0)
5149218cb0fbSBram Moolenaar 			{
5150218cb0fbSBram Moolenaar 			    // value differs, apply it
5151218cb0fbSBram Moolenaar 			    set_option_value((char_u *)"bg", 0L,
5152218cb0fbSBram Moolenaar 					      (char_u *)new_bg_val, 0);
5153218cb0fbSBram Moolenaar 			    reset_option_was_set((char_u *)"bg");
5154218cb0fbSBram Moolenaar 			    redraw_asap(CLEAR);
5155218cb0fbSBram Moolenaar 			}
5156218cb0fbSBram Moolenaar 		    }
5157218cb0fbSBram Moolenaar # ifdef FEAT_TERMINAL
5158218cb0fbSBram Moolenaar 		    else
5159218cb0fbSBram Moolenaar 		    {
5160218cb0fbSBram Moolenaar 			LOG_TR(("Received RFG response: %s", tp));
5161218cb0fbSBram Moolenaar 			rfg_status.tr_progress = STATUS_GOT;
5162218cb0fbSBram Moolenaar 			fg_r = rval;
5163218cb0fbSBram Moolenaar 			fg_g = gval;
5164218cb0fbSBram Moolenaar 			fg_b = bval;
5165218cb0fbSBram Moolenaar 		    }
5166218cb0fbSBram Moolenaar # endif
5167218cb0fbSBram Moolenaar 		}
5168218cb0fbSBram Moolenaar 
5169218cb0fbSBram Moolenaar 		// got finished code: consume it
5170218cb0fbSBram Moolenaar 		key_name[0] = (int)KS_EXTRA;
5171218cb0fbSBram Moolenaar 		key_name[1] = (int)KE_IGNORE;
5172218cb0fbSBram Moolenaar 		*slen = i + 1 + (tp[i] == ESC);
5173218cb0fbSBram Moolenaar # ifdef FEAT_EVAL
5174218cb0fbSBram Moolenaar 		set_vim_var_string(is_bg ? VV_TERMRBGRESP
5175218cb0fbSBram Moolenaar 						  : VV_TERMRFGRESP, tp, *slen);
5176218cb0fbSBram Moolenaar # endif
5177218cb0fbSBram Moolenaar 		break;
5178218cb0fbSBram Moolenaar 	    }
5179218cb0fbSBram Moolenaar     if (i == len)
5180218cb0fbSBram Moolenaar     {
5181218cb0fbSBram Moolenaar 	LOG_TR(("not enough characters for RB"));
5182218cb0fbSBram Moolenaar 	return FAIL;
5183218cb0fbSBram Moolenaar     }
5184218cb0fbSBram Moolenaar     return OK;
5185218cb0fbSBram Moolenaar }
5186218cb0fbSBram Moolenaar 
5187218cb0fbSBram Moolenaar /*
5188218cb0fbSBram Moolenaar  * Check for key code response from xterm:
5189218cb0fbSBram Moolenaar  * {lead}{flag}+r<hex bytes><{tail}
5190218cb0fbSBram Moolenaar  *
5191218cb0fbSBram Moolenaar  * {lead} can be <Esc>P or DCS
5192218cb0fbSBram Moolenaar  * {flag} can be '0' or '1'
5193218cb0fbSBram Moolenaar  * {tail} can be Esc>\ or STERM
5194218cb0fbSBram Moolenaar  *
5195218cb0fbSBram Moolenaar  * Check for cursor shape response from xterm:
5196218cb0fbSBram Moolenaar  * {lead}1$r<digit> q{tail}
5197218cb0fbSBram Moolenaar  *
5198218cb0fbSBram Moolenaar  * {lead} can be <Esc>P or DCS
5199218cb0fbSBram Moolenaar  * {tail} can be <Esc>\ or STERM
5200218cb0fbSBram Moolenaar  *
5201218cb0fbSBram Moolenaar  * Consume any code that starts with "{lead}.+r" or "{lead}.$r".
5202218cb0fbSBram Moolenaar  */
5203218cb0fbSBram Moolenaar     static int
handle_dcs(char_u * tp,char_u * argp,int len,char_u * key_name,int * slen)5204218cb0fbSBram Moolenaar handle_dcs(char_u *tp, char_u *argp, int len, char_u *key_name, int *slen)
5205218cb0fbSBram Moolenaar {
5206218cb0fbSBram Moolenaar     int i, j;
5207218cb0fbSBram Moolenaar 
5208218cb0fbSBram Moolenaar     j = 1 + (tp[0] == ESC);
5209218cb0fbSBram Moolenaar     if (len < j + 3)
5210218cb0fbSBram Moolenaar 	i = len; // need more chars
5211218cb0fbSBram Moolenaar     else if ((argp[1] != '+' && argp[1] != '$') || argp[2] != 'r')
5212218cb0fbSBram Moolenaar 	i = 0; // no match
5213218cb0fbSBram Moolenaar     else if (argp[1] == '+')
5214218cb0fbSBram Moolenaar 	// key code response
5215218cb0fbSBram Moolenaar 	for (i = j; i < len; ++i)
5216218cb0fbSBram Moolenaar 	{
5217218cb0fbSBram Moolenaar 	    if ((tp[i] == ESC && i + 1 < len && tp[i + 1] == '\\')
5218218cb0fbSBram Moolenaar 		    || tp[i] == STERM)
5219218cb0fbSBram Moolenaar 	    {
5220218cb0fbSBram Moolenaar 		if (i - j >= 3)
5221218cb0fbSBram Moolenaar 		    got_code_from_term(tp + j, i);
5222218cb0fbSBram Moolenaar 		key_name[0] = (int)KS_EXTRA;
5223218cb0fbSBram Moolenaar 		key_name[1] = (int)KE_IGNORE;
5224218cb0fbSBram Moolenaar 		*slen = i + 1 + (tp[i] == ESC);
5225218cb0fbSBram Moolenaar 		break;
5226218cb0fbSBram Moolenaar 	    }
5227218cb0fbSBram Moolenaar 	}
5228218cb0fbSBram Moolenaar     else
5229218cb0fbSBram Moolenaar     {
5230218cb0fbSBram Moolenaar 	// Probably the cursor shape response.  Make sure that "i"
5231218cb0fbSBram Moolenaar 	// is equal to "len" when there are not sufficient
5232218cb0fbSBram Moolenaar 	// characters.
5233218cb0fbSBram Moolenaar 	for (i = j + 3; i < len; ++i)
5234218cb0fbSBram Moolenaar 	{
5235218cb0fbSBram Moolenaar 	    if (i - j == 3 && !isdigit(tp[i]))
5236218cb0fbSBram Moolenaar 		break;
5237218cb0fbSBram Moolenaar 	    if (i - j == 4 && tp[i] != ' ')
5238218cb0fbSBram Moolenaar 		break;
5239218cb0fbSBram Moolenaar 	    if (i - j == 5 && tp[i] != 'q')
5240218cb0fbSBram Moolenaar 		break;
5241218cb0fbSBram Moolenaar 	    if (i - j == 6 && tp[i] != ESC && tp[i] != STERM)
5242218cb0fbSBram Moolenaar 		break;
5243218cb0fbSBram Moolenaar 	    if ((i - j == 6 && tp[i] == STERM)
5244218cb0fbSBram Moolenaar 	     || (i - j == 7 && tp[i] == '\\'))
5245218cb0fbSBram Moolenaar 	    {
5246218cb0fbSBram Moolenaar 		int number = argp[3] - '0';
5247218cb0fbSBram Moolenaar 
5248218cb0fbSBram Moolenaar 		// 0, 1 = block blink, 2 = block
5249218cb0fbSBram Moolenaar 		// 3 = underline blink, 4 = underline
5250218cb0fbSBram Moolenaar 		// 5 = vertical bar blink, 6 = vertical bar
5251218cb0fbSBram Moolenaar 		number = number == 0 ? 1 : number;
5252218cb0fbSBram Moolenaar 		initial_cursor_shape = (number + 1) / 2;
5253218cb0fbSBram Moolenaar 		// The blink flag is actually inverted, compared to
5254218cb0fbSBram Moolenaar 		// the value set with T_SH.
5255218cb0fbSBram Moolenaar 		initial_cursor_shape_blink =
5256218cb0fbSBram Moolenaar 				       (number & 1) ? FALSE : TRUE;
5257218cb0fbSBram Moolenaar 		rcs_status.tr_progress = STATUS_GOT;
5258218cb0fbSBram Moolenaar 		LOG_TR(("Received cursor shape response: %s", tp));
5259218cb0fbSBram Moolenaar 
5260218cb0fbSBram Moolenaar 		key_name[0] = (int)KS_EXTRA;
5261218cb0fbSBram Moolenaar 		key_name[1] = (int)KE_IGNORE;
5262218cb0fbSBram Moolenaar 		*slen = i + 1;
5263218cb0fbSBram Moolenaar # ifdef FEAT_EVAL
5264218cb0fbSBram Moolenaar 		set_vim_var_string(VV_TERMSTYLERESP, tp, *slen);
5265218cb0fbSBram Moolenaar # endif
5266218cb0fbSBram Moolenaar 		break;
5267218cb0fbSBram Moolenaar 	    }
5268218cb0fbSBram Moolenaar 	}
5269218cb0fbSBram Moolenaar     }
5270218cb0fbSBram Moolenaar 
5271218cb0fbSBram Moolenaar     if (i == len)
5272218cb0fbSBram Moolenaar     {
5273218cb0fbSBram Moolenaar 	// These codes arrive many together, each code can be
5274218cb0fbSBram Moolenaar 	// truncated at any point.
5275218cb0fbSBram Moolenaar 	LOG_TR(("not enough characters for XT"));
5276218cb0fbSBram Moolenaar 	return FAIL;
5277218cb0fbSBram Moolenaar     }
5278218cb0fbSBram Moolenaar     return OK;
5279218cb0fbSBram Moolenaar }
52800ca8b5baSBram Moolenaar #endif // FEAT_TERMRESPONSE
5281218cb0fbSBram Moolenaar 
52826a0299d8SBram Moolenaar /*
5283071d4279SBram Moolenaar  * Check if typebuf.tb_buf[] contains a terminal key code.
5284071d4279SBram Moolenaar  * Check from typebuf.tb_buf[typebuf.tb_off] to typebuf.tb_buf[typebuf.tb_off
5285975a880aSBram Moolenaar  * + "max_offset"].
5286071d4279SBram Moolenaar  * Return 0 for no match, -1 for partial match, > 0 for full match.
5287946ffd46SBram Moolenaar  * Return KEYLEN_REMOVED when a key code was deleted.
5288071d4279SBram Moolenaar  * With a match, the match is removed, the replacement code is inserted in
5289071d4279SBram Moolenaar  * typebuf.tb_buf[] and the number of characters in typebuf.tb_buf[] is
5290071d4279SBram Moolenaar  * returned.
5291a8c8a688SBram Moolenaar  * When "buf" is not NULL, buf[bufsize] is used instead of typebuf.tb_buf[].
5292a8c8a688SBram Moolenaar  * "buflen" is then the length of the string in buf[] and is updated for
5293a8c8a688SBram Moolenaar  * inserts and deletes.
5294071d4279SBram Moolenaar  */
5295071d4279SBram Moolenaar     int
check_termcode(int max_offset,char_u * buf,int bufsize,int * buflen)5296764b23c8SBram Moolenaar check_termcode(
5297764b23c8SBram Moolenaar     int		max_offset,
5298764b23c8SBram Moolenaar     char_u	*buf,
5299764b23c8SBram Moolenaar     int		bufsize,
5300764b23c8SBram Moolenaar     int		*buflen)
5301071d4279SBram Moolenaar {
5302071d4279SBram Moolenaar     char_u	*tp;
5303071d4279SBram Moolenaar     char_u	*p;
53040d6f5d97SBram Moolenaar     int		slen = 0;	// init for GCC
5305bc7aa85dSBram Moolenaar     int		modslen;
5306071d4279SBram Moolenaar     int		len;
5307946ffd46SBram Moolenaar     int		retval = 0;
5308071d4279SBram Moolenaar     int		offset;
5309071d4279SBram Moolenaar     char_u	key_name[2];
5310bc7aa85dSBram Moolenaar     int		modifiers;
5311090209bfSBram Moolenaar     char_u	*modifiers_start = NULL;
5312bc7aa85dSBram Moolenaar     int		key;
53136a0299d8SBram Moolenaar     int		new_slen;   // Length of what will replace the termcode
5314071d4279SBram Moolenaar     char_u	string[MAX_KEY_CODE_LEN + 1];
5315071d4279SBram Moolenaar     int		i, j;
5316071d4279SBram Moolenaar     int		idx = 0;
5317071d4279SBram Moolenaar     int		cpo_koffset;
5318071d4279SBram Moolenaar 
5319071d4279SBram Moolenaar     cpo_koffset = (vim_strchr(p_cpo, CPO_KOFFSET) != NULL);
5320071d4279SBram Moolenaar 
5321071d4279SBram Moolenaar     /*
5322071d4279SBram Moolenaar      * Speed up the checks for terminal codes by gathering all first bytes
5323071d4279SBram Moolenaar      * used in termleader[].  Often this is just a single <Esc>.
5324071d4279SBram Moolenaar      */
5325071d4279SBram Moolenaar     if (need_gather)
5326071d4279SBram Moolenaar 	gather_termleader();
5327071d4279SBram Moolenaar 
5328071d4279SBram Moolenaar     /*
5329071d4279SBram Moolenaar      * Check at several positions in typebuf.tb_buf[], to catch something like
5330071d4279SBram Moolenaar      * "x<Up>" that can be mapped. Stop at max_offset, because characters
5331071d4279SBram Moolenaar      * after that cannot be used for mapping, and with @r commands
5332e533bbe0SBram Moolenaar      * typebuf.tb_buf[] can become very long.
5333071d4279SBram Moolenaar      * This is used often, KEEP IT FAST!
5334071d4279SBram Moolenaar      */
5335071d4279SBram Moolenaar     for (offset = 0; offset < max_offset; ++offset)
5336071d4279SBram Moolenaar     {
5337071d4279SBram Moolenaar 	if (buf == NULL)
5338071d4279SBram Moolenaar 	{
5339071d4279SBram Moolenaar 	    if (offset >= typebuf.tb_len)
5340071d4279SBram Moolenaar 		break;
5341071d4279SBram Moolenaar 	    tp = typebuf.tb_buf + typebuf.tb_off + offset;
53420d6f5d97SBram Moolenaar 	    len = typebuf.tb_len - offset;	// length of the input
5343071d4279SBram Moolenaar 	}
5344071d4279SBram Moolenaar 	else
5345071d4279SBram Moolenaar 	{
5346a8c8a688SBram Moolenaar 	    if (offset >= *buflen)
5347071d4279SBram Moolenaar 		break;
5348071d4279SBram Moolenaar 	    tp = buf + offset;
5349a8c8a688SBram Moolenaar 	    len = *buflen - offset;
5350071d4279SBram Moolenaar 	}
5351071d4279SBram Moolenaar 
5352071d4279SBram Moolenaar 	/*
5353071d4279SBram Moolenaar 	 * Don't check characters after K_SPECIAL, those are already
5354071d4279SBram Moolenaar 	 * translated terminal chars (avoid translating ~@^Hx).
5355071d4279SBram Moolenaar 	 */
5356071d4279SBram Moolenaar 	if (*tp == K_SPECIAL)
5357071d4279SBram Moolenaar 	{
53580d6f5d97SBram Moolenaar 	    offset += 2;	// there are always 2 extra characters
5359071d4279SBram Moolenaar 	    continue;
5360071d4279SBram Moolenaar 	}
5361071d4279SBram Moolenaar 
5362071d4279SBram Moolenaar 	/*
5363071d4279SBram Moolenaar 	 * Skip this position if the character does not appear as the first
5364071d4279SBram Moolenaar 	 * character in term_strings. This speeds up a lot, since most
5365071d4279SBram Moolenaar 	 * termcodes start with the same character (ESC or CSI).
5366071d4279SBram Moolenaar 	 */
5367071d4279SBram Moolenaar 	i = *tp;
5368071d4279SBram Moolenaar 	for (p = termleader; *p && *p != i; ++p)
5369071d4279SBram Moolenaar 	    ;
5370071d4279SBram Moolenaar 	if (*p == NUL)
5371071d4279SBram Moolenaar 	    continue;
5372071d4279SBram Moolenaar 
5373071d4279SBram Moolenaar 	/*
5374071d4279SBram Moolenaar 	 * Skip this position if p_ek is not set and tp[0] is an ESC and we
5375071d4279SBram Moolenaar 	 * are in Insert mode.
5376071d4279SBram Moolenaar 	 */
5377071d4279SBram Moolenaar 	if (*tp == ESC && !p_ek && (State & INSERT))
5378071d4279SBram Moolenaar 	    continue;
5379071d4279SBram Moolenaar 
53800d6f5d97SBram Moolenaar 	key_name[0] = NUL;	// no key name found yet
53810d6f5d97SBram Moolenaar 	key_name[1] = NUL;	// no key name found yet
53820d6f5d97SBram Moolenaar 	modifiers = 0;		// no modifiers yet
5383071d4279SBram Moolenaar 
5384071d4279SBram Moolenaar #ifdef FEAT_GUI
5385071d4279SBram Moolenaar 	if (gui.in_use)
5386071d4279SBram Moolenaar 	{
5387071d4279SBram Moolenaar 	    /*
5388071d4279SBram Moolenaar 	     * GUI special key codes are all of the form [CSI xx].
5389071d4279SBram Moolenaar 	     */
53900d6f5d97SBram Moolenaar 	    if (*tp == CSI)	    // Special key from GUI
5391071d4279SBram Moolenaar 	    {
5392071d4279SBram Moolenaar 		if (len < 3)
53930d6f5d97SBram Moolenaar 		    return -1;	    // Shouldn't happen
5394071d4279SBram Moolenaar 		slen = 3;
5395071d4279SBram Moolenaar 		key_name[0] = tp[1];
5396071d4279SBram Moolenaar 		key_name[1] = tp[2];
5397071d4279SBram Moolenaar 	    }
5398071d4279SBram Moolenaar 	}
5399071d4279SBram Moolenaar 	else
54000d6f5d97SBram Moolenaar #endif // FEAT_GUI
5401071d4279SBram Moolenaar 	{
540292e5df80SBram Moolenaar 	    int  mouse_index_found = -1;
540392e5df80SBram Moolenaar 
5404071d4279SBram Moolenaar 	    for (idx = 0; idx < tc_len; ++idx)
5405071d4279SBram Moolenaar 	    {
5406071d4279SBram Moolenaar 		/*
5407071d4279SBram Moolenaar 		 * Ignore the entry if we are not at the start of
5408071d4279SBram Moolenaar 		 * typebuf.tb_buf[]
5409071d4279SBram Moolenaar 		 * and there are not enough characters to make a match.
5410071d4279SBram Moolenaar 		 * But only when the 'K' flag is in 'cpoptions'.
5411071d4279SBram Moolenaar 		 */
5412071d4279SBram Moolenaar 		slen = termcodes[idx].len;
5413a529ce06SBram Moolenaar 		modifiers_start = NULL;
5414071d4279SBram Moolenaar 		if (cpo_koffset && offset && len < slen)
5415071d4279SBram Moolenaar 		    continue;
5416071d4279SBram Moolenaar 		if (STRNCMP(termcodes[idx].code, tp,
5417071d4279SBram Moolenaar 				     (size_t)(slen > len ? len : slen)) == 0)
5418071d4279SBram Moolenaar 		{
54190d6f5d97SBram Moolenaar 		    if (len < slen)		// got a partial sequence
54200d6f5d97SBram Moolenaar 			return -1;		// need to get more chars
5421071d4279SBram Moolenaar 
5422071d4279SBram Moolenaar 		    /*
5423071d4279SBram Moolenaar 		     * When found a keypad key, check if there is another key
5424071d4279SBram Moolenaar 		     * that matches and use that one.  This makes <Home> to be
5425071d4279SBram Moolenaar 		     * found instead of <kHome> when they produce the same
5426071d4279SBram Moolenaar 		     * key code.
5427071d4279SBram Moolenaar 		     */
5428071d4279SBram Moolenaar 		    if (termcodes[idx].name[0] == 'K'
5429071d4279SBram Moolenaar 				       && VIM_ISDIGIT(termcodes[idx].name[1]))
5430071d4279SBram Moolenaar 		    {
5431071d4279SBram Moolenaar 			for (j = idx + 1; j < tc_len; ++j)
5432071d4279SBram Moolenaar 			    if (termcodes[j].len == slen &&
5433071d4279SBram Moolenaar 				    STRNCMP(termcodes[idx].code,
5434071d4279SBram Moolenaar 					    termcodes[j].code, slen) == 0)
5435071d4279SBram Moolenaar 			    {
5436071d4279SBram Moolenaar 				idx = j;
5437071d4279SBram Moolenaar 				break;
5438071d4279SBram Moolenaar 			    }
5439071d4279SBram Moolenaar 		    }
5440071d4279SBram Moolenaar 
544192e5df80SBram Moolenaar 		    // The mouse termcode "ESC [" is also the prefix of
544292e5df80SBram Moolenaar 		    // "ESC [ I" (focus gained).  Only use it when there is
544392e5df80SBram Moolenaar 		    // no other match.  Do use it when a digit is following to
544492e5df80SBram Moolenaar 		    // avoid waiting for more bytes.
544592e5df80SBram Moolenaar 		    if (slen == 2 && len > 2
544692e5df80SBram Moolenaar 			    && termcodes[idx].code[0] == ESC
544792e5df80SBram Moolenaar 			    && termcodes[idx].code[1] == '['
544892e5df80SBram Moolenaar 			    && !isdigit(tp[2]))
544992e5df80SBram Moolenaar 		    {
545092e5df80SBram Moolenaar 			if (mouse_index_found < 0)
545192e5df80SBram Moolenaar 			    mouse_index_found = idx;
545292e5df80SBram Moolenaar 		    }
545392e5df80SBram Moolenaar 		    else
545492e5df80SBram Moolenaar 		    {
5455071d4279SBram Moolenaar 			key_name[0] = termcodes[idx].name[0];
5456071d4279SBram Moolenaar 			key_name[1] = termcodes[idx].name[1];
5457071d4279SBram Moolenaar 			break;
5458071d4279SBram Moolenaar 		    }
545992e5df80SBram Moolenaar 		}
546019a09a18SBram Moolenaar 
546119a09a18SBram Moolenaar 		/*
546219a09a18SBram Moolenaar 		 * Check for code with modifier, like xterm uses:
5463bc7aa85dSBram Moolenaar 		 * <Esc>[123;*X  (modslen == slen - 3)
54644d8c96d4SBram Moolenaar 		 * <Esc>[@;*X    (matches <Esc>[X and <Esc>[1;9X )
5465bc7aa85dSBram Moolenaar 		 * Also <Esc>O*X and <M-O>*X (modslen == slen - 2).
5466bc7aa85dSBram Moolenaar 		 * When there is a modifier the * matches a number.
5467bc7aa85dSBram Moolenaar 		 * When there is no modifier the ;* or * is omitted.
546819a09a18SBram Moolenaar 		 */
546992e5df80SBram Moolenaar 		if (termcodes[idx].modlen > 0 && mouse_index_found < 0)
547019a09a18SBram Moolenaar 		{
54714d8c96d4SBram Moolenaar 		    int at_code;
54724d8c96d4SBram Moolenaar 
5473bc7aa85dSBram Moolenaar 		    modslen = termcodes[idx].modlen;
5474bc7aa85dSBram Moolenaar 		    if (cpo_koffset && offset && len < modslen)
547519a09a18SBram Moolenaar 			continue;
54764d8c96d4SBram Moolenaar 		    at_code = termcodes[idx].code[modslen] == '@';
547719a09a18SBram Moolenaar 		    if (STRNCMP(termcodes[idx].code, tp,
5478bc7aa85dSBram Moolenaar 				(size_t)(modslen > len ? len : modslen)) == 0)
547919a09a18SBram Moolenaar 		    {
548019a09a18SBram Moolenaar 			int	    n;
548119a09a18SBram Moolenaar 
54820d6f5d97SBram Moolenaar 			if (len <= modslen)	// got a partial sequence
54830d6f5d97SBram Moolenaar 			    return -1;		// need to get more chars
548419a09a18SBram Moolenaar 
5485bc7aa85dSBram Moolenaar 			if (tp[modslen] == termcodes[idx].code[slen - 1])
54864d8c96d4SBram Moolenaar 			    // no modifiers
54874d8c96d4SBram Moolenaar 			    slen = modslen + 1;
5488bc7aa85dSBram Moolenaar 			else if (tp[modslen] != ';' && modslen == slen - 3)
54894d8c96d4SBram Moolenaar 			    // no match for "code;*X" with "code;"
54904d8c96d4SBram Moolenaar 			    continue;
54914d8c96d4SBram Moolenaar 			else if (at_code && tp[modslen] != '1')
54924d8c96d4SBram Moolenaar 			    // no match for "<Esc>[@" with "<Esc>[1"
54934d8c96d4SBram Moolenaar 			    continue;
549419a09a18SBram Moolenaar 			else
549519a09a18SBram Moolenaar 			{
5496bb7e1b4bSBram Moolenaar 			    // Skip over the digits, the final char must
5497bb7e1b4bSBram Moolenaar 			    // follow. URXVT can use a negative value, thus
5498bb7e1b4bSBram Moolenaar 			    // also accept '-'.
54993eee06e7SBram Moolenaar 			    for (j = slen - 2; j < len && (isdigit(tp[j])
5500bb7e1b4bSBram Moolenaar 				       || tp[j] == '-' || tp[j] == ';'); ++j)
550119a09a18SBram Moolenaar 				;
550219a09a18SBram Moolenaar 			    ++j;
55030d6f5d97SBram Moolenaar 			    if (len < j)	// got a partial sequence
55040d6f5d97SBram Moolenaar 				return -1;	// need to get more chars
5505bc7aa85dSBram Moolenaar 			    if (tp[j - 1] != termcodes[idx].code[slen - 1])
55060d6f5d97SBram Moolenaar 				continue;	// no match
550719a09a18SBram Moolenaar 
5508a529ce06SBram Moolenaar 			    modifiers_start = tp + slen - 2;
5509a529ce06SBram Moolenaar 
55106a0299d8SBram Moolenaar 			    // Match!  Convert modifier bits.
55116a0299d8SBram Moolenaar 			    n = atoi((char *)modifiers_start);
55126a0299d8SBram Moolenaar 			    modifiers |= decode_modifiers(n);
551319a09a18SBram Moolenaar 
551419a09a18SBram Moolenaar 			    slen = j;
551519a09a18SBram Moolenaar 			}
551619a09a18SBram Moolenaar 			key_name[0] = termcodes[idx].name[0];
551719a09a18SBram Moolenaar 			key_name[1] = termcodes[idx].name[1];
551819a09a18SBram Moolenaar 			break;
551919a09a18SBram Moolenaar 		    }
552019a09a18SBram Moolenaar 		}
5521071d4279SBram Moolenaar 	    }
552292e5df80SBram Moolenaar 	    if (idx == tc_len && mouse_index_found >= 0)
552392e5df80SBram Moolenaar 	    {
552492e5df80SBram Moolenaar 		key_name[0] = termcodes[mouse_index_found].name[0];
552592e5df80SBram Moolenaar 		key_name[1] = termcodes[mouse_index_found].name[1];
552692e5df80SBram Moolenaar 	    }
5527071d4279SBram Moolenaar 	}
5528071d4279SBram Moolenaar 
5529071d4279SBram Moolenaar #ifdef FEAT_TERMRESPONSE
55301dff76bcSBram Moolenaar 	if (key_name[0] == NUL
55310d6f5d97SBram Moolenaar 	    // Mouse codes of DEC and pterm start with <ESC>[.  When
55320d6f5d97SBram Moolenaar 	    // detecting the start of these mouse codes they might as well be
55330d6f5d97SBram Moolenaar 	    // another key code or terminal response.
55344e067c89SBram Moolenaar # ifdef FEAT_MOUSE_DEC
55354e067c89SBram Moolenaar 	    || key_name[0] == KS_DEC_MOUSE
55364e067c89SBram Moolenaar # endif
55374e067c89SBram Moolenaar # ifdef FEAT_MOUSE_PTERM
55384e067c89SBram Moolenaar 	    || key_name[0] == KS_PTERM_MOUSE
55394e067c89SBram Moolenaar # endif
5540e533bbe0SBram Moolenaar 	   )
5541071d4279SBram Moolenaar 	{
5542c3e555b2SBram Moolenaar 	    char_u *argp = tp[0] == ESC ? tp + 2 : tp + 1;
5543c3e555b2SBram Moolenaar 
5544c3e555b2SBram Moolenaar 	    /*
5545c3e555b2SBram Moolenaar 	     * Check for responses from the terminal starting with {lead}:
5546c3e555b2SBram Moolenaar 	     * "<Esc>[" or CSI followed by [0-9>?]
55479584b31aSBram Moolenaar 	     *
5548c3e555b2SBram Moolenaar 	     * - Xterm version string: {lead}>{x};{vers};{y}c
55499584b31aSBram Moolenaar 	     *   Also eat other possible responses to t_RV, rxvt returns
5550c3e555b2SBram Moolenaar 	     *   "{lead}?1;2c".
55519584b31aSBram Moolenaar 	     *
5552c3e555b2SBram Moolenaar 	     * - Cursor position report: {lead}{row};{col}R
55534e067c89SBram Moolenaar 	     *   The final byte must be 'R'. It is used for checking the
55549584b31aSBram Moolenaar 	     *   ambiguous-width character state.
5555ba6ec182SBram Moolenaar 	     *
5556c3e555b2SBram Moolenaar 	     * - window position reply: {lead}3;{x};{y}t
5557c3e555b2SBram Moolenaar 	     *
5558c3e555b2SBram Moolenaar 	     * - key with modifiers when modifyOtherKeys is enabled:
5559c3e555b2SBram Moolenaar 	     *	    {lead}27;{modifier};{key}~
5560c3e555b2SBram Moolenaar 	     *	    {lead}{key};{modifier}u
55619584b31aSBram Moolenaar 	     */
5562c3e555b2SBram Moolenaar 	    if (((tp[0] == ESC && len >= 3 && tp[1] == '[')
556346a7561fSBram Moolenaar 			    || (tp[0] == CSI && len >= 2))
5564b5c32655SBram Moolenaar 		    && (VIM_ISDIGIT(*argp) || *argp == '>' || *argp == '?'))
5565071d4279SBram Moolenaar 	    {
5566218cb0fbSBram Moolenaar 		int resp = handle_csi(tp, len, argp, offset, buf,
5567218cb0fbSBram Moolenaar 					     bufsize, buflen, key_name, &slen);
5568218cb0fbSBram Moolenaar 		if (resp != 0)
55699c8c8c5dSBram Moolenaar 		{
55702951b77eSBram Moolenaar # ifdef DEBUG_TERMRESPONSE
5571218cb0fbSBram Moolenaar 		    if (resp == -1)
5572218cb0fbSBram Moolenaar 			LOG_TR(("Not enough characters for CSI sequence"));
55732951b77eSBram Moolenaar # endif
5574218cb0fbSBram Moolenaar 		    return resp;
55752951b77eSBram Moolenaar 		}
55764e067c89SBram Moolenaar 	    }
5577a45551a5SBram Moolenaar 
5578218cb0fbSBram Moolenaar 	    // Check for fore/background color response from the terminal,
5579218cb0fbSBram Moolenaar 	    // starting} with <Esc>] or OSC
558065e4c4f6SBram Moolenaar 	    else if ((*T_RBG != NUL || *T_RFG != NUL)
558146fd4df7SBram Moolenaar 			&& ((tp[0] == ESC && len >= 2 && tp[1] == ']')
558246fd4df7SBram Moolenaar 			    || tp[0] == OSC))
5583b5c32655SBram Moolenaar 	    {
5584218cb0fbSBram Moolenaar 		if (handle_osc(tp, argp, len, key_name, &slen) == FAIL)
558546fd4df7SBram Moolenaar 		    return -1;
5586b5c32655SBram Moolenaar 	    }
5587071d4279SBram Moolenaar 
5588218cb0fbSBram Moolenaar 	    // Check for key code response from xterm,
5589218cb0fbSBram Moolenaar 	    // starting with <Esc>P or DCS
5590afd78266SBram Moolenaar 	    else if ((check_for_codes || rcs_status.tr_progress == STATUS_SENT)
559146fd4df7SBram Moolenaar 		    && ((tp[0] == ESC && len >= 2 && tp[1] == 'P')
5592071d4279SBram Moolenaar 			|| tp[0] == DCS))
5593071d4279SBram Moolenaar 	    {
5594218cb0fbSBram Moolenaar 		if (handle_dcs(tp, argp, len, key_name, &slen) == FAIL)
559546fd4df7SBram Moolenaar 		    return -1;
5596071d4279SBram Moolenaar 	    }
5597071d4279SBram Moolenaar 	}
5598071d4279SBram Moolenaar #endif
5599071d4279SBram Moolenaar 
5600071d4279SBram Moolenaar 	if (key_name[0] == NUL)
56010d6f5d97SBram Moolenaar 	    continue;	    // No match at this position, try next one
5602071d4279SBram Moolenaar 
56030d6f5d97SBram Moolenaar 	// We only get here when we have a complete termcode match
5604071d4279SBram Moolenaar 
5605071d4279SBram Moolenaar #ifdef FEAT_GUI
5606071d4279SBram Moolenaar 	/*
5607071d4279SBram Moolenaar 	 * Only in the GUI: Fetch the pointer coordinates of the scroll event
5608071d4279SBram Moolenaar 	 * so that we know which window to scroll later.
5609071d4279SBram Moolenaar 	 */
5610071d4279SBram Moolenaar 	if (gui.in_use
5611071d4279SBram Moolenaar 		&& key_name[0] == (int)KS_EXTRA
5612071d4279SBram Moolenaar 		&& (key_name[1] == (int)KE_X1MOUSE
5613071d4279SBram Moolenaar 		    || key_name[1] == (int)KE_X2MOUSE
5614445f11d5SBram Moolenaar 		    || key_name[1] == (int)KE_MOUSEMOVE_XY
56158d9b40e7SBram Moolenaar 		    || key_name[1] == (int)KE_MOUSELEFT
56168d9b40e7SBram Moolenaar 		    || key_name[1] == (int)KE_MOUSERIGHT
5617071d4279SBram Moolenaar 		    || key_name[1] == (int)KE_MOUSEDOWN
5618071d4279SBram Moolenaar 		    || key_name[1] == (int)KE_MOUSEUP))
5619071d4279SBram Moolenaar 	{
5620b8ff5c27SBram Moolenaar 	    char_u	bytes[6];
5621b8ff5c27SBram Moolenaar 	    int		num_bytes = get_bytes_from_buf(tp + slen, bytes, 4);
5622b8ff5c27SBram Moolenaar 
5623b8ff5c27SBram Moolenaar 	    if (num_bytes == -1)	// not enough coordinates
5624071d4279SBram Moolenaar 		return -1;
5625071d4279SBram Moolenaar 	    mouse_col = 128 * (bytes[0] - ' ' - 1) + bytes[1] - ' ' - 1;
5626071d4279SBram Moolenaar 	    mouse_row = 128 * (bytes[2] - ' ' - 1) + bytes[3] - ' ' - 1;
5627071d4279SBram Moolenaar 	    slen += num_bytes;
5628445f11d5SBram Moolenaar 	    // equal to K_MOUSEMOVE
5629445f11d5SBram Moolenaar 	    if (key_name[1] == (int)KE_MOUSEMOVE_XY)
5630445f11d5SBram Moolenaar 		key_name[1] = (int)KE_MOUSEMOVE;
5631071d4279SBram Moolenaar 	}
5632071d4279SBram Moolenaar 	else
5633071d4279SBram Moolenaar #endif
5634071d4279SBram Moolenaar 	/*
5635071d4279SBram Moolenaar 	 * If it is a mouse click, get the coordinates.
5636071d4279SBram Moolenaar 	 */
56372b9578f0SBram Moolenaar 	if (key_name[0] == KS_MOUSE
5638bedf091aSBram Moolenaar #ifdef FEAT_MOUSE_GPM
5639bedf091aSBram Moolenaar 		|| key_name[0] == KS_GPM_MOUSE
5640bedf091aSBram Moolenaar #endif
5641071d4279SBram Moolenaar #ifdef FEAT_MOUSE_JSB
56422b9578f0SBram Moolenaar 		|| key_name[0] == KS_JSBTERM_MOUSE
5643071d4279SBram Moolenaar #endif
5644071d4279SBram Moolenaar #ifdef FEAT_MOUSE_NET
56452b9578f0SBram Moolenaar 		|| key_name[0] == KS_NETTERM_MOUSE
5646071d4279SBram Moolenaar #endif
5647071d4279SBram Moolenaar #ifdef FEAT_MOUSE_DEC
56482b9578f0SBram Moolenaar 		|| key_name[0] == KS_DEC_MOUSE
5649071d4279SBram Moolenaar #endif
5650071d4279SBram Moolenaar #ifdef FEAT_MOUSE_PTERM
56512b9578f0SBram Moolenaar 		|| key_name[0] == KS_PTERM_MOUSE
5652071d4279SBram Moolenaar #endif
56531dff76bcSBram Moolenaar #ifdef FEAT_MOUSE_URXVT
56542b9578f0SBram Moolenaar 		|| key_name[0] == KS_URXVT_MOUSE
56552b9578f0SBram Moolenaar #endif
56562b9578f0SBram Moolenaar 		|| key_name[0] == KS_SGR_MOUSE
56572ace1bd6SBram Moolenaar 		|| key_name[0] == KS_SGR_MOUSE_RELEASE)
5658071d4279SBram Moolenaar 	{
5659b8ff5c27SBram Moolenaar 	    if (check_termcode_mouse(tp, &slen, key_name, modifiers_start, idx,
5660b8ff5c27SBram Moolenaar 							     &modifiers) == -1)
5661071d4279SBram Moolenaar 		return -1;
5662071d4279SBram Moolenaar 	}
5663071d4279SBram Moolenaar 
5664071d4279SBram Moolenaar #ifdef FEAT_GUI
5665071d4279SBram Moolenaar 	/*
5666071d4279SBram Moolenaar 	 * If using the GUI, then we get menu and scrollbar events.
5667071d4279SBram Moolenaar 	 *
5668071d4279SBram Moolenaar 	 * A menu event is encoded as K_SPECIAL, KS_MENU, KE_FILLER followed by
5669071d4279SBram Moolenaar 	 * four bytes which are to be taken as a pointer to the vimmenu_T
5670071d4279SBram Moolenaar 	 * structure.
5671071d4279SBram Moolenaar 	 *
5672cf0dfa2fSBram Moolenaar 	 * A tab line event is encoded as K_SPECIAL KS_TABLINE nr, where "nr"
567332466aa2SBram Moolenaar 	 * is one byte with the tab index.
567432466aa2SBram Moolenaar 	 *
5675071d4279SBram Moolenaar 	 * A scrollbar event is K_SPECIAL, KS_VER_SCROLLBAR, KE_FILLER followed
5676071d4279SBram Moolenaar 	 * by one byte representing the scrollbar number, and then four bytes
5677071d4279SBram Moolenaar 	 * representing a long_u which is the new value of the scrollbar.
5678071d4279SBram Moolenaar 	 *
5679071d4279SBram Moolenaar 	 * A horizontal scrollbar event is K_SPECIAL, KS_HOR_SCROLLBAR,
5680071d4279SBram Moolenaar 	 * KE_FILLER followed by four bytes representing a long_u which is the
5681071d4279SBram Moolenaar 	 * new value of the scrollbar.
5682071d4279SBram Moolenaar 	 */
5683071d4279SBram Moolenaar # ifdef FEAT_MENU
5684071d4279SBram Moolenaar 	else if (key_name[0] == (int)KS_MENU)
5685071d4279SBram Moolenaar 	{
5686071d4279SBram Moolenaar 	    long_u	val;
5687b8ff5c27SBram Moolenaar 	    int		num_bytes = get_long_from_buf(tp + slen, &val);
5688071d4279SBram Moolenaar 
5689071d4279SBram Moolenaar 	    if (num_bytes == -1)
5690071d4279SBram Moolenaar 		return -1;
5691071d4279SBram Moolenaar 	    current_menu = (vimmenu_T *)val;
5692071d4279SBram Moolenaar 	    slen += num_bytes;
5693968bbbe4SBram Moolenaar 
56940d6f5d97SBram Moolenaar 	    // The menu may have been deleted right after it was used, check
56950d6f5d97SBram Moolenaar 	    // for that.
5696968bbbe4SBram Moolenaar 	    if (check_menu_pointer(root_menu, current_menu) == FAIL)
5697968bbbe4SBram Moolenaar 	    {
5698968bbbe4SBram Moolenaar 		key_name[0] = KS_EXTRA;
5699968bbbe4SBram Moolenaar 		key_name[1] = (int)KE_IGNORE;
5700968bbbe4SBram Moolenaar 	    }
5701071d4279SBram Moolenaar 	}
5702071d4279SBram Moolenaar # endif
570332466aa2SBram Moolenaar # ifdef FEAT_GUI_TABLINE
570432466aa2SBram Moolenaar 	else if (key_name[0] == (int)KS_TABLINE)
570532466aa2SBram Moolenaar 	{
5706b8ff5c27SBram Moolenaar 	    // Selecting tabline tab or using its menu.
5707b8ff5c27SBram Moolenaar 	    char_u	bytes[6];
5708b8ff5c27SBram Moolenaar 	    int		num_bytes = get_bytes_from_buf(tp + slen, bytes, 1);
5709b8ff5c27SBram Moolenaar 
571032466aa2SBram Moolenaar 	    if (num_bytes == -1)
571132466aa2SBram Moolenaar 		return -1;
571232466aa2SBram Moolenaar 	    current_tab = (int)bytes[0];
57130d6f5d97SBram Moolenaar 	    if (current_tab == 255)	// -1 in a byte gives 255
571407354547SBram Moolenaar 		current_tab = -1;
571532466aa2SBram Moolenaar 	    slen += num_bytes;
571632466aa2SBram Moolenaar 	}
57175c8837f9SBram Moolenaar 	else if (key_name[0] == (int)KS_TABMENU)
57185c8837f9SBram Moolenaar 	{
5719b8ff5c27SBram Moolenaar 	    // Selecting tabline tab or using its menu.
5720b8ff5c27SBram Moolenaar 	    char_u	bytes[6];
5721b8ff5c27SBram Moolenaar 	    int		num_bytes = get_bytes_from_buf(tp + slen, bytes, 2);
5722b8ff5c27SBram Moolenaar 
57235c8837f9SBram Moolenaar 	    if (num_bytes == -1)
57245c8837f9SBram Moolenaar 		return -1;
57255c8837f9SBram Moolenaar 	    current_tab = (int)bytes[0];
57265c8837f9SBram Moolenaar 	    current_tabmenu = (int)bytes[1];
57275c8837f9SBram Moolenaar 	    slen += num_bytes;
57285c8837f9SBram Moolenaar 	}
572932466aa2SBram Moolenaar # endif
5730071d4279SBram Moolenaar # ifndef USE_ON_FLY_SCROLL
5731071d4279SBram Moolenaar 	else if (key_name[0] == (int)KS_VER_SCROLLBAR)
5732071d4279SBram Moolenaar 	{
5733071d4279SBram Moolenaar 	    long_u	val;
5734b8ff5c27SBram Moolenaar 	    char_u	bytes[6];
5735b8ff5c27SBram Moolenaar 	    int		num_bytes;
5736071d4279SBram Moolenaar 
57370d6f5d97SBram Moolenaar 	    // Get the last scrollbar event in the queue of the same type
5738071d4279SBram Moolenaar 	    j = 0;
5739071d4279SBram Moolenaar 	    for (i = 0; tp[j] == CSI && tp[j + 1] == KS_VER_SCROLLBAR
5740071d4279SBram Moolenaar 						     && tp[j + 2] != NUL; ++i)
5741071d4279SBram Moolenaar 	    {
5742071d4279SBram Moolenaar 		j += 3;
5743071d4279SBram Moolenaar 		num_bytes = get_bytes_from_buf(tp + j, bytes, 1);
5744071d4279SBram Moolenaar 		if (num_bytes == -1)
5745071d4279SBram Moolenaar 		    break;
5746071d4279SBram Moolenaar 		if (i == 0)
5747071d4279SBram Moolenaar 		    current_scrollbar = (int)bytes[0];
5748071d4279SBram Moolenaar 		else if (current_scrollbar != (int)bytes[0])
5749071d4279SBram Moolenaar 		    break;
5750071d4279SBram Moolenaar 		j += num_bytes;
5751071d4279SBram Moolenaar 		num_bytes = get_long_from_buf(tp + j, &val);
5752071d4279SBram Moolenaar 		if (num_bytes == -1)
5753071d4279SBram Moolenaar 		    break;
5754071d4279SBram Moolenaar 		scrollbar_value = val;
5755071d4279SBram Moolenaar 		j += num_bytes;
5756071d4279SBram Moolenaar 		slen = j;
5757071d4279SBram Moolenaar 	    }
57580d6f5d97SBram Moolenaar 	    if (i == 0)		// not enough characters to make one
5759071d4279SBram Moolenaar 		return -1;
5760071d4279SBram Moolenaar 	}
5761071d4279SBram Moolenaar 	else if (key_name[0] == (int)KS_HOR_SCROLLBAR)
5762071d4279SBram Moolenaar 	{
5763071d4279SBram Moolenaar 	    long_u	val;
5764b8ff5c27SBram Moolenaar 	    int		num_bytes;
5765071d4279SBram Moolenaar 
57660d6f5d97SBram Moolenaar 	    // Get the last horiz. scrollbar event in the queue
5767071d4279SBram Moolenaar 	    j = 0;
5768071d4279SBram Moolenaar 	    for (i = 0; tp[j] == CSI && tp[j + 1] == KS_HOR_SCROLLBAR
5769071d4279SBram Moolenaar 						     && tp[j + 2] != NUL; ++i)
5770071d4279SBram Moolenaar 	    {
5771071d4279SBram Moolenaar 		j += 3;
5772071d4279SBram Moolenaar 		num_bytes = get_long_from_buf(tp + j, &val);
5773071d4279SBram Moolenaar 		if (num_bytes == -1)
5774071d4279SBram Moolenaar 		    break;
5775071d4279SBram Moolenaar 		scrollbar_value = val;
5776071d4279SBram Moolenaar 		j += num_bytes;
5777071d4279SBram Moolenaar 		slen = j;
5778071d4279SBram Moolenaar 	    }
57790d6f5d97SBram Moolenaar 	    if (i == 0)		// not enough characters to make one
5780071d4279SBram Moolenaar 		return -1;
5781071d4279SBram Moolenaar 	}
57820d6f5d97SBram Moolenaar # endif // !USE_ON_FLY_SCROLL
57830d6f5d97SBram Moolenaar #endif // FEAT_GUI
5784071d4279SBram Moolenaar 
5785681fc3faSBram Moolenaar #if (defined(UNIX) || defined(VMS))
5786681fc3faSBram Moolenaar 	/*
5787681fc3faSBram Moolenaar 	 * Handle FocusIn/FocusOut event sequences reported by XTerm.
5788681fc3faSBram Moolenaar 	 * (CSI I/CSI O)
5789681fc3faSBram Moolenaar 	 */
5790681fc3faSBram Moolenaar 	if (focus_mode
5791681fc3faSBram Moolenaar # ifdef FEAT_GUI
5792681fc3faSBram Moolenaar 		&& !gui.in_use
5793681fc3faSBram Moolenaar # endif
5794681fc3faSBram Moolenaar 		&& key_name[0] == KS_EXTRA
5795681fc3faSBram Moolenaar 	    )
5796681fc3faSBram Moolenaar 	{
5797d44cc593SBram Moolenaar 	    if (key_name[1] == KE_FOCUSGAINED)
5798d44cc593SBram Moolenaar 	    {
5799d44cc593SBram Moolenaar 		if (!focus_state)
5800681fc3faSBram Moolenaar 		{
5801fadd55bdSBram Moolenaar 		    ui_focus_change(TRUE);
5802681fc3faSBram Moolenaar 		    did_cursorhold = TRUE;
5803681fc3faSBram Moolenaar 		    focus_state = TRUE;
5804d44cc593SBram Moolenaar 		}
5805681fc3faSBram Moolenaar 		key_name[1] = (int)KE_IGNORE;
5806681fc3faSBram Moolenaar 	    }
5807d44cc593SBram Moolenaar 	    else if (key_name[1] == KE_FOCUSLOST)
5808d44cc593SBram Moolenaar 	    {
5809d44cc593SBram Moolenaar 		if (focus_state)
5810681fc3faSBram Moolenaar 		{
5811fadd55bdSBram Moolenaar 		    ui_focus_change(FALSE);
5812681fc3faSBram Moolenaar 		    did_cursorhold = TRUE;
5813681fc3faSBram Moolenaar 		    focus_state = FALSE;
5814d44cc593SBram Moolenaar 		}
5815681fc3faSBram Moolenaar 		key_name[1] = (int)KE_IGNORE;
5816681fc3faSBram Moolenaar 	    }
5817681fc3faSBram Moolenaar 	}
5818681fc3faSBram Moolenaar #endif
5819681fc3faSBram Moolenaar 
5820bc7aa85dSBram Moolenaar 	/*
5821bc7aa85dSBram Moolenaar 	 * Change <xHome> to <Home>, <xUp> to <Up>, etc.
5822bc7aa85dSBram Moolenaar 	 */
5823bc7aa85dSBram Moolenaar 	key = handle_x_keys(TERMCAP2KEY(key_name[0], key_name[1]));
5824bc7aa85dSBram Moolenaar 
5825bc7aa85dSBram Moolenaar 	/*
5826bc7aa85dSBram Moolenaar 	 * Add any modifier codes to our string.
5827bc7aa85dSBram Moolenaar 	 */
58286a0299d8SBram Moolenaar 	new_slen = modifiers2keycode(modifiers, &key, string);
5829bc7aa85dSBram Moolenaar 
58300d6f5d97SBram Moolenaar 	// Finally, add the special key code to our string
5831bc7aa85dSBram Moolenaar 	key_name[0] = KEY2TERMCAP0(key);
5832bc7aa85dSBram Moolenaar 	key_name[1] = KEY2TERMCAP1(key);
5833071d4279SBram Moolenaar 	if (key_name[0] == KS_KEY)
58346768a330SBram Moolenaar 	{
58350d6f5d97SBram Moolenaar 	    // from ":set <M-b>=xx"
58366768a330SBram Moolenaar 	    if (has_mbyte)
58376768a330SBram Moolenaar 		new_slen += (*mb_char2bytes)(key_name[1], string + new_slen);
58386768a330SBram Moolenaar 	    else
58396768a330SBram Moolenaar 		string[new_slen++] = key_name[1];
58406768a330SBram Moolenaar 	}
5841946ffd46SBram Moolenaar 	else if (new_slen == 0 && key_name[0] == KS_EXTRA
5842946ffd46SBram Moolenaar 						  && key_name[1] == KE_IGNORE)
5843946ffd46SBram Moolenaar 	{
58440d6f5d97SBram Moolenaar 	    // Do not put K_IGNORE into the buffer, do return KEYLEN_REMOVED
58450d6f5d97SBram Moolenaar 	    // to indicate what happened.
5846946ffd46SBram Moolenaar 	    retval = KEYLEN_REMOVED;
5847946ffd46SBram Moolenaar 	}
5848071d4279SBram Moolenaar 	else
5849071d4279SBram Moolenaar 	{
5850071d4279SBram Moolenaar 	    string[new_slen++] = K_SPECIAL;
5851071d4279SBram Moolenaar 	    string[new_slen++] = key_name[0];
5852071d4279SBram Moolenaar 	    string[new_slen++] = key_name[1];
5853071d4279SBram Moolenaar 	}
58546a0299d8SBram Moolenaar 	if (put_string_in_typebuf(offset, slen, string, new_slen,
58556a0299d8SBram Moolenaar 						 buf, bufsize, buflen) == FAIL)
5856a8c8a688SBram Moolenaar 	    return -1;
58576a0299d8SBram Moolenaar 	return retval == 0 ? (len + new_slen - slen + offset) : retval;
5858071d4279SBram Moolenaar     }
5859071d4279SBram Moolenaar 
58602951b77eSBram Moolenaar #ifdef FEAT_TERMRESPONSE
5861b255b905SBram Moolenaar     LOG_TR(("normal character"));
58622951b77eSBram Moolenaar #endif
58632951b77eSBram Moolenaar 
58640d6f5d97SBram Moolenaar     return 0;			    // no match found
5865071d4279SBram Moolenaar }
5866071d4279SBram Moolenaar 
58679377df3eSBram Moolenaar #if (defined(FEAT_TERMINAL) && defined(FEAT_TERMRESPONSE)) || defined(PROTO)
586865e4c4f6SBram Moolenaar /*
586965e4c4f6SBram Moolenaar  * Get the text foreground color, if known.
587065e4c4f6SBram Moolenaar  */
587165e4c4f6SBram Moolenaar     void
term_get_fg_color(char_u * r,char_u * g,char_u * b)587200ce63dcSBram Moolenaar term_get_fg_color(char_u *r, char_u *g, char_u *b)
587365e4c4f6SBram Moolenaar {
5874afd78266SBram Moolenaar     if (rfg_status.tr_progress == STATUS_GOT)
587565e4c4f6SBram Moolenaar     {
587665e4c4f6SBram Moolenaar 	*r = fg_r;
587765e4c4f6SBram Moolenaar 	*g = fg_g;
587865e4c4f6SBram Moolenaar 	*b = fg_b;
587965e4c4f6SBram Moolenaar     }
588065e4c4f6SBram Moolenaar }
588165e4c4f6SBram Moolenaar 
588265e4c4f6SBram Moolenaar /*
588365e4c4f6SBram Moolenaar  * Get the text background color, if known.
588465e4c4f6SBram Moolenaar  */
588565e4c4f6SBram Moolenaar     void
term_get_bg_color(char_u * r,char_u * g,char_u * b)588600ce63dcSBram Moolenaar term_get_bg_color(char_u *r, char_u *g, char_u *b)
588765e4c4f6SBram Moolenaar {
5888afd78266SBram Moolenaar     if (rbg_status.tr_progress == STATUS_GOT)
588965e4c4f6SBram Moolenaar     {
589065e4c4f6SBram Moolenaar 	*r = bg_r;
589165e4c4f6SBram Moolenaar 	*g = bg_g;
589265e4c4f6SBram Moolenaar 	*b = bg_b;
589365e4c4f6SBram Moolenaar     }
589465e4c4f6SBram Moolenaar }
589565e4c4f6SBram Moolenaar #endif
589665e4c4f6SBram Moolenaar 
5897071d4279SBram Moolenaar /*
5898071d4279SBram Moolenaar  * Replace any terminal code strings in from[] with the equivalent internal
5899071d4279SBram Moolenaar  * vim representation.	This is used for the "from" and "to" part of a
5900071d4279SBram Moolenaar  * mapping, and the "to" part of a menu command.
5901071d4279SBram Moolenaar  * Any strings like "<C-UP>" are also replaced, unless 'cpoptions' contains
5902071d4279SBram Moolenaar  * '<'.
5903071d4279SBram Moolenaar  * K_SPECIAL by itself is replaced by K_SPECIAL KS_SPECIAL KE_FILLER.
5904071d4279SBram Moolenaar  *
5905071d4279SBram Moolenaar  * The replacement is done in result[] and finally copied into allocated
5906071d4279SBram Moolenaar  * memory. If this all works well *bufp is set to the allocated memory and a
5907071d4279SBram Moolenaar  * pointer to it is returned. If something fails *bufp is set to NULL and from
5908071d4279SBram Moolenaar  * is returned.
5909071d4279SBram Moolenaar  *
5910459fd785SBram Moolenaar  * CTRL-V characters are removed.  When "flags" has REPTERM_FROM_PART, a
5911459fd785SBram Moolenaar  * trailing CTRL-V is included, otherwise it is removed (for ":map xx ^V", maps
5912459fd785SBram Moolenaar  * xx to nothing).  When 'cpoptions' does not contain 'B', a backslash can be
5913459fd785SBram Moolenaar  * used instead of a CTRL-V.
5914459fd785SBram Moolenaar  *
5915459fd785SBram Moolenaar  * Flags:
5916459fd785SBram Moolenaar  *  REPTERM_FROM_PART	see above
5917459fd785SBram Moolenaar  *  REPTERM_DO_LT	also translate <lt>
5918459fd785SBram Moolenaar  *  REPTERM_SPECIAL	always accept <key> notation
5919459fd785SBram Moolenaar  *  REPTERM_NO_SIMPLIFY	do not simplify <C-H> to 0x08 and set 8th bit for <A-x>
5920459fd785SBram Moolenaar  *
5921459fd785SBram Moolenaar  * "did_simplify" is set when some <C-H> or <A-x> code was simplified, unless
5922459fd785SBram Moolenaar  * it is NULL.
5923071d4279SBram Moolenaar  */
5924071d4279SBram Moolenaar     char_u *
replace_termcodes(char_u * from,char_u ** bufp,int flags,int * did_simplify)5925764b23c8SBram Moolenaar replace_termcodes(
5926764b23c8SBram Moolenaar     char_u	*from,
5927764b23c8SBram Moolenaar     char_u	**bufp,
5928459fd785SBram Moolenaar     int		flags,
5929459fd785SBram Moolenaar     int		*did_simplify)
5930071d4279SBram Moolenaar {
5931071d4279SBram Moolenaar     int		i;
5932071d4279SBram Moolenaar     int		slen;
5933071d4279SBram Moolenaar     int		key;
5934071d4279SBram Moolenaar     int		dlen = 0;
5935071d4279SBram Moolenaar     char_u	*src;
59360d6f5d97SBram Moolenaar     int		do_backslash;	// backslash is a special character
59370d6f5d97SBram Moolenaar     int		do_special;	// recognize <> key codes
59380d6f5d97SBram Moolenaar     int		do_key_code;	// recognize raw key codes
59390d6f5d97SBram Moolenaar     char_u	*result;	// buffer for resulting string
5940071d4279SBram Moolenaar 
5941071d4279SBram Moolenaar     do_backslash = (vim_strchr(p_cpo, CPO_BSLASH) == NULL);
5942459fd785SBram Moolenaar     do_special = (vim_strchr(p_cpo, CPO_SPECI) == NULL)
5943459fd785SBram Moolenaar 						  || (flags & REPTERM_SPECIAL);
5944071d4279SBram Moolenaar     do_key_code = (vim_strchr(p_cpo, CPO_KEYCODE) == NULL);
5945071d4279SBram Moolenaar 
5946071d4279SBram Moolenaar     /*
5947071d4279SBram Moolenaar      * Allocate space for the translation.  Worst case a single character is
5948071d4279SBram Moolenaar      * replaced by 6 bytes (shifted special key), plus a NUL at the end.
5949071d4279SBram Moolenaar      */
5950964b3746SBram Moolenaar     result = alloc(STRLEN(from) * 6 + 1);
59510d6f5d97SBram Moolenaar     if (result == NULL)		// out of memory
5952071d4279SBram Moolenaar     {
5953071d4279SBram Moolenaar 	*bufp = NULL;
5954071d4279SBram Moolenaar 	return from;
5955071d4279SBram Moolenaar     }
5956071d4279SBram Moolenaar 
5957071d4279SBram Moolenaar     src = from;
5958071d4279SBram Moolenaar 
5959071d4279SBram Moolenaar     /*
5960071d4279SBram Moolenaar      * Check for #n at start only: function key n
5961071d4279SBram Moolenaar      */
5962459fd785SBram Moolenaar     if ((flags & REPTERM_FROM_PART) && src[0] == '#' && VIM_ISDIGIT(src[1]))
5963071d4279SBram Moolenaar     {
5964071d4279SBram Moolenaar 	result[dlen++] = K_SPECIAL;
5965071d4279SBram Moolenaar 	result[dlen++] = 'k';
5966071d4279SBram Moolenaar 	if (src[1] == '0')
59670d6f5d97SBram Moolenaar 	    result[dlen++] = ';';	// #0 is F10 is "k;"
5968071d4279SBram Moolenaar 	else
59690d6f5d97SBram Moolenaar 	    result[dlen++] = src[1];	// #3 is F3 is "k3"
5970071d4279SBram Moolenaar 	src += 2;
5971071d4279SBram Moolenaar     }
5972071d4279SBram Moolenaar 
5973071d4279SBram Moolenaar     /*
5974071d4279SBram Moolenaar      * Copy each byte from *from to result[dlen]
5975071d4279SBram Moolenaar      */
5976071d4279SBram Moolenaar     while (*src != NUL)
5977071d4279SBram Moolenaar     {
5978071d4279SBram Moolenaar 	/*
5979071d4279SBram Moolenaar 	 * If 'cpoptions' does not contain '<', check for special key codes,
59808d9b40e7SBram Moolenaar 	 * like "<C-S-LeftMouse>"
5981071d4279SBram Moolenaar 	 */
5982459fd785SBram Moolenaar 	if (do_special && ((flags & REPTERM_DO_LT)
5983459fd785SBram Moolenaar 					      || STRNCMP(src, "<lt>", 4) != 0))
5984071d4279SBram Moolenaar 	{
5985071d4279SBram Moolenaar #ifdef FEAT_EVAL
5986071d4279SBram Moolenaar 	    /*
5987071d4279SBram Moolenaar 	     * Replace <SID> by K_SNR <script-nr> _.
5988071d4279SBram Moolenaar 	     * (room: 5 * 6 = 30 bytes; needed: 3 + <nr> + 1 <= 14)
5989071d4279SBram Moolenaar 	     */
5990071d4279SBram Moolenaar 	    if (STRNICMP(src, "<SID>", 5) == 0)
5991071d4279SBram Moolenaar 	    {
5992f29c1c6aSBram Moolenaar 		if (current_sctx.sc_sid <= 0)
5993f9e3e09fSBram Moolenaar 		    emsg(_(e_usingsid));
5994071d4279SBram Moolenaar 		else
5995071d4279SBram Moolenaar 		{
5996071d4279SBram Moolenaar 		    src += 5;
5997071d4279SBram Moolenaar 		    result[dlen++] = K_SPECIAL;
5998071d4279SBram Moolenaar 		    result[dlen++] = (int)KS_EXTRA;
5999071d4279SBram Moolenaar 		    result[dlen++] = (int)KE_SNR;
6000f29c1c6aSBram Moolenaar 		    sprintf((char *)result + dlen, "%ld",
6001f29c1c6aSBram Moolenaar 						    (long)current_sctx.sc_sid);
6002071d4279SBram Moolenaar 		    dlen += (int)STRLEN(result + dlen);
6003071d4279SBram Moolenaar 		    result[dlen++] = '_';
6004071d4279SBram Moolenaar 		    continue;
6005071d4279SBram Moolenaar 		}
6006071d4279SBram Moolenaar 	    }
6007071d4279SBram Moolenaar #endif
6008071d4279SBram Moolenaar 
6009ebe9d34aSBram Moolenaar 	    slen = trans_special(&src, result + dlen, FSK_KEYCODE
6010ebe9d34aSBram Moolenaar 			  | ((flags & REPTERM_NO_SIMPLIFY) ? 0 : FSK_SIMPLIFY),
6011ebe9d34aSBram Moolenaar 								 did_simplify);
6012071d4279SBram Moolenaar 	    if (slen)
6013071d4279SBram Moolenaar 	    {
6014071d4279SBram Moolenaar 		dlen += slen;
6015071d4279SBram Moolenaar 		continue;
6016071d4279SBram Moolenaar 	    }
6017071d4279SBram Moolenaar 	}
6018071d4279SBram Moolenaar 
6019071d4279SBram Moolenaar 	/*
6020071d4279SBram Moolenaar 	 * If 'cpoptions' does not contain 'k', see if it's an actual key-code.
6021071d4279SBram Moolenaar 	 * Note that this is also checked after replacing the <> form.
6022071d4279SBram Moolenaar 	 * Single character codes are NOT replaced (e.g. ^H or DEL), because
6023071d4279SBram Moolenaar 	 * it could be a character in the file.
6024071d4279SBram Moolenaar 	 */
6025071d4279SBram Moolenaar 	if (do_key_code)
6026071d4279SBram Moolenaar 	{
6027071d4279SBram Moolenaar 	    i = find_term_bykeys(src);
6028071d4279SBram Moolenaar 	    if (i >= 0)
6029071d4279SBram Moolenaar 	    {
6030071d4279SBram Moolenaar 		result[dlen++] = K_SPECIAL;
6031071d4279SBram Moolenaar 		result[dlen++] = termcodes[i].name[0];
6032071d4279SBram Moolenaar 		result[dlen++] = termcodes[i].name[1];
6033071d4279SBram Moolenaar 		src += termcodes[i].len;
60340d6f5d97SBram Moolenaar 		// If terminal code matched, continue after it.
6035071d4279SBram Moolenaar 		continue;
6036071d4279SBram Moolenaar 	    }
6037071d4279SBram Moolenaar 	}
6038071d4279SBram Moolenaar 
6039071d4279SBram Moolenaar #ifdef FEAT_EVAL
6040071d4279SBram Moolenaar 	if (do_special)
6041071d4279SBram Moolenaar 	{
6042071d4279SBram Moolenaar 	    char_u	*p, *s, len;
6043071d4279SBram Moolenaar 
6044071d4279SBram Moolenaar 	    /*
6045071d4279SBram Moolenaar 	     * Replace <Leader> by the value of "mapleader".
6046071d4279SBram Moolenaar 	     * Replace <LocalLeader> by the value of "maplocalleader".
6047071d4279SBram Moolenaar 	     * If "mapleader" or "maplocalleader" isn't set use a backslash.
6048071d4279SBram Moolenaar 	     */
6049071d4279SBram Moolenaar 	    if (STRNICMP(src, "<Leader>", 8) == 0)
6050071d4279SBram Moolenaar 	    {
6051071d4279SBram Moolenaar 		len = 8;
6052071d4279SBram Moolenaar 		p = get_var_value((char_u *)"g:mapleader");
6053071d4279SBram Moolenaar 	    }
6054071d4279SBram Moolenaar 	    else if (STRNICMP(src, "<LocalLeader>", 13) == 0)
6055071d4279SBram Moolenaar 	    {
6056071d4279SBram Moolenaar 		len = 13;
6057071d4279SBram Moolenaar 		p = get_var_value((char_u *)"g:maplocalleader");
6058071d4279SBram Moolenaar 	    }
6059071d4279SBram Moolenaar 	    else
6060071d4279SBram Moolenaar 	    {
6061071d4279SBram Moolenaar 		len = 0;
6062071d4279SBram Moolenaar 		p = NULL;
6063071d4279SBram Moolenaar 	    }
6064071d4279SBram Moolenaar 	    if (len != 0)
6065071d4279SBram Moolenaar 	    {
60660d6f5d97SBram Moolenaar 		// Allow up to 8 * 6 characters for "mapleader".
6067071d4279SBram Moolenaar 		if (p == NULL || *p == NUL || STRLEN(p) > 8 * 6)
6068071d4279SBram Moolenaar 		    s = (char_u *)"\\";
6069071d4279SBram Moolenaar 		else
6070071d4279SBram Moolenaar 		    s = p;
6071071d4279SBram Moolenaar 		while (*s != NUL)
6072071d4279SBram Moolenaar 		    result[dlen++] = *s++;
6073071d4279SBram Moolenaar 		src += len;
6074071d4279SBram Moolenaar 		continue;
6075071d4279SBram Moolenaar 	    }
6076071d4279SBram Moolenaar 	}
6077071d4279SBram Moolenaar #endif
6078071d4279SBram Moolenaar 
6079071d4279SBram Moolenaar 	/*
6080071d4279SBram Moolenaar 	 * Remove CTRL-V and ignore the next character.
6081071d4279SBram Moolenaar 	 * For "from" side the CTRL-V at the end is included, for the "to"
6082071d4279SBram Moolenaar 	 * part it is removed.
6083071d4279SBram Moolenaar 	 * If 'cpoptions' does not contain 'B', also accept a backslash.
6084071d4279SBram Moolenaar 	 */
6085071d4279SBram Moolenaar 	key = *src;
6086071d4279SBram Moolenaar 	if (key == Ctrl_V || (do_backslash && key == '\\'))
6087071d4279SBram Moolenaar 	{
60880d6f5d97SBram Moolenaar 	    ++src;				// skip CTRL-V or backslash
6089071d4279SBram Moolenaar 	    if (*src == NUL)
6090071d4279SBram Moolenaar 	    {
6091459fd785SBram Moolenaar 		if (flags & REPTERM_FROM_PART)
6092071d4279SBram Moolenaar 		    result[dlen++] = key;
6093071d4279SBram Moolenaar 		break;
6094071d4279SBram Moolenaar 	    }
6095071d4279SBram Moolenaar 	}
6096071d4279SBram Moolenaar 
60970d6f5d97SBram Moolenaar 	// skip multibyte char correctly
60980fa313a7SBram Moolenaar 	for (i = (*mb_ptr2len)(src); i > 0; --i)
6099071d4279SBram Moolenaar 	{
6100071d4279SBram Moolenaar 	    /*
6101071d4279SBram Moolenaar 	     * If the character is K_SPECIAL, replace it with K_SPECIAL
6102071d4279SBram Moolenaar 	     * KS_SPECIAL KE_FILLER.
6103071d4279SBram Moolenaar 	     * If compiled with the GUI replace CSI with K_CSI.
6104071d4279SBram Moolenaar 	     */
6105071d4279SBram Moolenaar 	    if (*src == K_SPECIAL)
6106071d4279SBram Moolenaar 	    {
6107071d4279SBram Moolenaar 		result[dlen++] = K_SPECIAL;
6108071d4279SBram Moolenaar 		result[dlen++] = KS_SPECIAL;
6109071d4279SBram Moolenaar 		result[dlen++] = KE_FILLER;
6110071d4279SBram Moolenaar 	    }
6111071d4279SBram Moolenaar # ifdef FEAT_GUI
6112071d4279SBram Moolenaar 	    else if (*src == CSI)
6113071d4279SBram Moolenaar 	    {
6114071d4279SBram Moolenaar 		result[dlen++] = K_SPECIAL;
6115071d4279SBram Moolenaar 		result[dlen++] = KS_EXTRA;
6116071d4279SBram Moolenaar 		result[dlen++] = (int)KE_CSI;
6117071d4279SBram Moolenaar 	    }
6118071d4279SBram Moolenaar # endif
6119071d4279SBram Moolenaar 	    else
6120071d4279SBram Moolenaar 		result[dlen++] = *src;
6121071d4279SBram Moolenaar 	    ++src;
6122071d4279SBram Moolenaar 	}
6123071d4279SBram Moolenaar     }
6124071d4279SBram Moolenaar     result[dlen] = NUL;
6125071d4279SBram Moolenaar 
6126071d4279SBram Moolenaar     /*
6127071d4279SBram Moolenaar      * Copy the new string to allocated memory.
6128071d4279SBram Moolenaar      * If this fails, just return from.
6129071d4279SBram Moolenaar      */
6130071d4279SBram Moolenaar     if ((*bufp = vim_strsave(result)) != NULL)
6131071d4279SBram Moolenaar 	from = *bufp;
6132071d4279SBram Moolenaar     vim_free(result);
6133071d4279SBram Moolenaar     return from;
6134071d4279SBram Moolenaar }
6135071d4279SBram Moolenaar 
6136071d4279SBram Moolenaar /*
6137071d4279SBram Moolenaar  * Find a termcode with keys 'src' (must be NUL terminated).
6138071d4279SBram Moolenaar  * Return the index in termcodes[], or -1 if not found.
6139071d4279SBram Moolenaar  */
61405843f5f3SBram Moolenaar     static int
find_term_bykeys(char_u * src)6141764b23c8SBram Moolenaar find_term_bykeys(char_u *src)
6142071d4279SBram Moolenaar {
6143071d4279SBram Moolenaar     int		i;
614438f5f952SBram Moolenaar     int		slen = (int)STRLEN(src);
6145071d4279SBram Moolenaar 
6146071d4279SBram Moolenaar     for (i = 0; i < tc_len; ++i)
6147071d4279SBram Moolenaar     {
61485af7d712SBram Moolenaar 	if (slen == termcodes[i].len
61495af7d712SBram Moolenaar 			&& STRNCMP(termcodes[i].code, src, (size_t)slen) == 0)
6150071d4279SBram Moolenaar 	    return i;
6151071d4279SBram Moolenaar     }
6152071d4279SBram Moolenaar     return -1;
6153071d4279SBram Moolenaar }
6154071d4279SBram Moolenaar 
6155071d4279SBram Moolenaar /*
6156071d4279SBram Moolenaar  * Gather the first characters in the terminal key codes into a string.
6157071d4279SBram Moolenaar  * Used to speed up check_termcode().
6158071d4279SBram Moolenaar  */
6159071d4279SBram Moolenaar     static void
gather_termleader(void)6160764b23c8SBram Moolenaar gather_termleader(void)
6161071d4279SBram Moolenaar {
6162071d4279SBram Moolenaar     int	    i;
6163071d4279SBram Moolenaar     int	    len = 0;
6164071d4279SBram Moolenaar 
6165071d4279SBram Moolenaar #ifdef FEAT_GUI
6166071d4279SBram Moolenaar     if (gui.in_use)
61670d6f5d97SBram Moolenaar 	termleader[len++] = CSI;    // the GUI codes are not in termcodes[]
6168071d4279SBram Moolenaar #endif
6169071d4279SBram Moolenaar #ifdef FEAT_TERMRESPONSE
61703eee06e7SBram Moolenaar     if (check_for_codes || *T_CRS != NUL)
61710d6f5d97SBram Moolenaar 	termleader[len++] = DCS;    // the termcode response starts with DCS
61720d6f5d97SBram Moolenaar 				    // in 8-bit mode
6173071d4279SBram Moolenaar #endif
6174071d4279SBram Moolenaar     termleader[len] = NUL;
6175071d4279SBram Moolenaar 
6176071d4279SBram Moolenaar     for (i = 0; i < tc_len; ++i)
6177071d4279SBram Moolenaar 	if (vim_strchr(termleader, termcodes[i].code[0]) == NULL)
6178071d4279SBram Moolenaar 	{
6179071d4279SBram Moolenaar 	    termleader[len++] = termcodes[i].code[0];
6180071d4279SBram Moolenaar 	    termleader[len] = NUL;
6181071d4279SBram Moolenaar 	}
6182071d4279SBram Moolenaar 
6183071d4279SBram Moolenaar     need_gather = FALSE;
6184071d4279SBram Moolenaar }
6185071d4279SBram Moolenaar 
6186071d4279SBram Moolenaar /*
6187071d4279SBram Moolenaar  * Show all termcodes (for ":set termcap")
6188071d4279SBram Moolenaar  * This code looks a lot like showoptions(), but is different.
6189071d4279SBram Moolenaar  */
6190071d4279SBram Moolenaar     void
show_termcodes(void)6191764b23c8SBram Moolenaar show_termcodes(void)
6192071d4279SBram Moolenaar {
6193071d4279SBram Moolenaar     int		col;
6194071d4279SBram Moolenaar     int		*items;
6195071d4279SBram Moolenaar     int		item_count;
6196071d4279SBram Moolenaar     int		run;
6197071d4279SBram Moolenaar     int		row, rows;
6198071d4279SBram Moolenaar     int		cols;
6199071d4279SBram Moolenaar     int		i;
6200071d4279SBram Moolenaar     int		len;
6201071d4279SBram Moolenaar 
62020d6f5d97SBram Moolenaar #define INC3 27	    // try to make three columns
62030d6f5d97SBram Moolenaar #define INC2 40	    // try to make two columns
62040d6f5d97SBram Moolenaar #define GAP 2	    // spaces between columns
6205071d4279SBram Moolenaar 
62060d6f5d97SBram Moolenaar     if (tc_len == 0)	    // no terminal codes (must be GUI)
6207071d4279SBram Moolenaar 	return;
6208c799fe20SBram Moolenaar     items = ALLOC_MULT(int, tc_len);
6209071d4279SBram Moolenaar     if (items == NULL)
6210071d4279SBram Moolenaar 	return;
6211071d4279SBram Moolenaar 
62120d6f5d97SBram Moolenaar     // Highlight title
621332526b3cSBram Moolenaar     msg_puts_title(_("\n--- Terminal keys ---"));
6214071d4279SBram Moolenaar 
6215071d4279SBram Moolenaar     /*
6216071d4279SBram Moolenaar      * do the loop two times:
6217071d4279SBram Moolenaar      * 1. display the short items (non-strings and short strings)
6218bc7aa85dSBram Moolenaar      * 2. display the medium items (medium length strings)
6219bc7aa85dSBram Moolenaar      * 3. display the long items (remaining strings)
6220071d4279SBram Moolenaar      */
6221bc7aa85dSBram Moolenaar     for (run = 1; run <= 3 && !got_int; ++run)
6222071d4279SBram Moolenaar     {
6223071d4279SBram Moolenaar 	/*
6224071d4279SBram Moolenaar 	 * collect the items in items[]
6225071d4279SBram Moolenaar 	 */
6226071d4279SBram Moolenaar 	item_count = 0;
6227071d4279SBram Moolenaar 	for (i = 0; i < tc_len; i++)
6228071d4279SBram Moolenaar 	{
6229071d4279SBram Moolenaar 	    len = show_one_termcode(termcodes[i].name,
6230071d4279SBram Moolenaar 						    termcodes[i].code, FALSE);
6231bc7aa85dSBram Moolenaar 	    if (len <= INC3 - GAP ? run == 1
6232bc7aa85dSBram Moolenaar 			: len <= INC2 - GAP ? run == 2
6233bc7aa85dSBram Moolenaar 			: run == 3)
6234071d4279SBram Moolenaar 		items[item_count++] = i;
6235071d4279SBram Moolenaar 	}
6236071d4279SBram Moolenaar 
6237071d4279SBram Moolenaar 	/*
6238071d4279SBram Moolenaar 	 * display the items
6239071d4279SBram Moolenaar 	 */
6240bc7aa85dSBram Moolenaar 	if (run <= 2)
6241071d4279SBram Moolenaar 	{
6242bc7aa85dSBram Moolenaar 	    cols = (Columns + GAP) / (run == 1 ? INC3 : INC2);
6243071d4279SBram Moolenaar 	    if (cols == 0)
6244071d4279SBram Moolenaar 		cols = 1;
6245071d4279SBram Moolenaar 	    rows = (item_count + cols - 1) / cols;
6246071d4279SBram Moolenaar 	}
62470d6f5d97SBram Moolenaar 	else	// run == 3
6248071d4279SBram Moolenaar 	    rows = item_count;
6249071d4279SBram Moolenaar 	for (row = 0; row < rows && !got_int; ++row)
6250071d4279SBram Moolenaar 	{
62510d6f5d97SBram Moolenaar 	    msg_putchar('\n');			// go to next line
62520d6f5d97SBram Moolenaar 	    if (got_int)			// 'q' typed in more
6253071d4279SBram Moolenaar 		break;
6254071d4279SBram Moolenaar 	    col = 0;
6255071d4279SBram Moolenaar 	    for (i = row; i < item_count; i += rows)
6256071d4279SBram Moolenaar 	    {
62570d6f5d97SBram Moolenaar 		msg_col = col;			// make columns
6258071d4279SBram Moolenaar 		show_one_termcode(termcodes[items[i]].name,
6259071d4279SBram Moolenaar 					      termcodes[items[i]].code, TRUE);
6260bc7aa85dSBram Moolenaar 		if (run == 2)
6261bc7aa85dSBram Moolenaar 		    col += INC2;
6262bc7aa85dSBram Moolenaar 		else
6263bc7aa85dSBram Moolenaar 		    col += INC3;
6264071d4279SBram Moolenaar 	    }
6265071d4279SBram Moolenaar 	    out_flush();
6266071d4279SBram Moolenaar 	    ui_breakcheck();
6267071d4279SBram Moolenaar 	}
6268071d4279SBram Moolenaar     }
6269071d4279SBram Moolenaar     vim_free(items);
6270071d4279SBram Moolenaar }
6271071d4279SBram Moolenaar 
6272071d4279SBram Moolenaar /*
6273071d4279SBram Moolenaar  * Show one termcode entry.
6274071d4279SBram Moolenaar  * Output goes into IObuff[]
6275071d4279SBram Moolenaar  */
6276071d4279SBram Moolenaar     int
show_one_termcode(char_u * name,char_u * code,int printit)6277764b23c8SBram Moolenaar show_one_termcode(char_u *name, char_u *code, int printit)
6278071d4279SBram Moolenaar {
6279071d4279SBram Moolenaar     char_u	*p;
6280071d4279SBram Moolenaar     int		len;
6281071d4279SBram Moolenaar 
6282071d4279SBram Moolenaar     if (name[0] > '~')
6283071d4279SBram Moolenaar     {
6284071d4279SBram Moolenaar 	IObuff[0] = ' ';
6285071d4279SBram Moolenaar 	IObuff[1] = ' ';
6286071d4279SBram Moolenaar 	IObuff[2] = ' ';
6287071d4279SBram Moolenaar 	IObuff[3] = ' ';
6288071d4279SBram Moolenaar     }
6289071d4279SBram Moolenaar     else
6290071d4279SBram Moolenaar     {
6291071d4279SBram Moolenaar 	IObuff[0] = 't';
6292071d4279SBram Moolenaar 	IObuff[1] = '_';
6293071d4279SBram Moolenaar 	IObuff[2] = name[0];
6294071d4279SBram Moolenaar 	IObuff[3] = name[1];
6295071d4279SBram Moolenaar     }
6296071d4279SBram Moolenaar     IObuff[4] = ' ';
6297071d4279SBram Moolenaar 
6298071d4279SBram Moolenaar     p = get_special_key_name(TERMCAP2KEY(name[0], name[1]), 0);
6299071d4279SBram Moolenaar     if (p[1] != 't')
6300071d4279SBram Moolenaar 	STRCPY(IObuff + 5, p);
6301071d4279SBram Moolenaar     else
6302071d4279SBram Moolenaar 	IObuff[5] = NUL;
6303071d4279SBram Moolenaar     len = (int)STRLEN(IObuff);
6304071d4279SBram Moolenaar     do
6305071d4279SBram Moolenaar 	IObuff[len++] = ' ';
6306071d4279SBram Moolenaar     while (len < 17);
6307071d4279SBram Moolenaar     IObuff[len] = NUL;
6308071d4279SBram Moolenaar     if (code == NULL)
6309071d4279SBram Moolenaar 	len += 4;
6310071d4279SBram Moolenaar     else
6311071d4279SBram Moolenaar 	len += vim_strsize(code);
6312071d4279SBram Moolenaar 
6313071d4279SBram Moolenaar     if (printit)
6314071d4279SBram Moolenaar     {
631532526b3cSBram Moolenaar 	msg_puts((char *)IObuff);
6316071d4279SBram Moolenaar 	if (code == NULL)
631732526b3cSBram Moolenaar 	    msg_puts("NULL");
6318071d4279SBram Moolenaar 	else
6319071d4279SBram Moolenaar 	    msg_outtrans(code);
6320071d4279SBram Moolenaar     }
6321071d4279SBram Moolenaar     return len;
6322071d4279SBram Moolenaar }
6323071d4279SBram Moolenaar 
6324071d4279SBram Moolenaar #if defined(FEAT_TERMRESPONSE) || defined(PROTO)
6325071d4279SBram Moolenaar /*
6326071d4279SBram Moolenaar  * For Xterm >= 140 compiled with OPT_TCAP_QUERY: Obtain the actually used
6327071d4279SBram Moolenaar  * termcap codes from the terminal itself.
6328071d4279SBram Moolenaar  * We get them one by one to avoid a very long response string.
6329071d4279SBram Moolenaar  */
63304e067c89SBram Moolenaar static int xt_index_in = 0;
63314e067c89SBram Moolenaar static int xt_index_out = 0;
63324e067c89SBram Moolenaar 
6333071d4279SBram Moolenaar     static void
req_codes_from_term(void)6334764b23c8SBram Moolenaar req_codes_from_term(void)
6335071d4279SBram Moolenaar {
6336071d4279SBram Moolenaar     xt_index_out = 0;
6337071d4279SBram Moolenaar     xt_index_in = 0;
6338071d4279SBram Moolenaar     req_more_codes_from_term();
6339071d4279SBram Moolenaar }
6340071d4279SBram Moolenaar 
6341071d4279SBram Moolenaar     static void
req_more_codes_from_term(void)6342764b23c8SBram Moolenaar req_more_codes_from_term(void)
6343071d4279SBram Moolenaar {
6344071d4279SBram Moolenaar     char	buf[11];
6345071d4279SBram Moolenaar     int		old_idx = xt_index_out;
6346071d4279SBram Moolenaar 
63470d6f5d97SBram Moolenaar     // Don't do anything when going to exit.
6348071d4279SBram Moolenaar     if (exiting)
6349071d4279SBram Moolenaar 	return;
6350071d4279SBram Moolenaar 
63510d6f5d97SBram Moolenaar     // Send up to 10 more requests out than we received.  Avoid sending too
63520d6f5d97SBram Moolenaar     // many, there can be a buffer overflow somewhere.
6353071d4279SBram Moolenaar     while (xt_index_out < xt_index_in + 10 && key_names[xt_index_out] != NULL)
6354071d4279SBram Moolenaar     {
6355b255b905SBram Moolenaar 	char *key_name = key_names[xt_index_out];
63562951b77eSBram Moolenaar 
635786394aa9SBram Moolenaar #ifdef FEAT_JOB_CHANNEL
635886394aa9SBram Moolenaar 	ch_log_output = TRUE;
635986394aa9SBram Moolenaar #endif
6360b255b905SBram Moolenaar 	LOG_TR(("Requesting XT %d: %s", xt_index_out, key_name));
6361b255b905SBram Moolenaar 	sprintf(buf, "\033P+q%02x%02x\033\\", key_name[0], key_name[1]);
6362071d4279SBram Moolenaar 	out_str_nf((char_u *)buf);
6363071d4279SBram Moolenaar 	++xt_index_out;
6364071d4279SBram Moolenaar     }
6365071d4279SBram Moolenaar 
63660d6f5d97SBram Moolenaar     // Send the codes out right away.
6367071d4279SBram Moolenaar     if (xt_index_out != old_idx)
6368071d4279SBram Moolenaar 	out_flush();
6369071d4279SBram Moolenaar }
6370071d4279SBram Moolenaar 
6371071d4279SBram Moolenaar /*
6372071d4279SBram Moolenaar  * Decode key code response from xterm: '<Esc>P1+r<name>=<string><Esc>\'.
6373071d4279SBram Moolenaar  * A "0" instead of the "1" indicates a code that isn't supported.
6374071d4279SBram Moolenaar  * Both <name> and <string> are encoded in hex.
6375071d4279SBram Moolenaar  * "code" points to the "0" or "1".
6376071d4279SBram Moolenaar  */
6377071d4279SBram Moolenaar     static void
got_code_from_term(char_u * code,int len)6378764b23c8SBram Moolenaar got_code_from_term(char_u *code, int len)
6379071d4279SBram Moolenaar {
6380071d4279SBram Moolenaar #define XT_LEN 100
6381071d4279SBram Moolenaar     char_u	name[3];
6382071d4279SBram Moolenaar     char_u	str[XT_LEN];
6383071d4279SBram Moolenaar     int		i;
6384071d4279SBram Moolenaar     int		j = 0;
6385071d4279SBram Moolenaar     int		c;
6386071d4279SBram Moolenaar 
63870d6f5d97SBram Moolenaar     // A '1' means the code is supported, a '0' means it isn't.
63880d6f5d97SBram Moolenaar     // When half the length is > XT_LEN we can't use it.
63890d6f5d97SBram Moolenaar     // Our names are currently all 2 characters.
6390071d4279SBram Moolenaar     if (code[0] == '1' && code[7] == '=' && len / 2 < XT_LEN)
6391071d4279SBram Moolenaar     {
63920d6f5d97SBram Moolenaar 	// Get the name from the response and find it in the table.
6393071d4279SBram Moolenaar 	name[0] = hexhex2nr(code + 3);
6394071d4279SBram Moolenaar 	name[1] = hexhex2nr(code + 5);
6395071d4279SBram Moolenaar 	name[2] = NUL;
6396071d4279SBram Moolenaar 	for (i = 0; key_names[i] != NULL; ++i)
6397071d4279SBram Moolenaar 	{
6398071d4279SBram Moolenaar 	    if (STRCMP(key_names[i], name) == 0)
6399071d4279SBram Moolenaar 	    {
6400071d4279SBram Moolenaar 		xt_index_in = i;
6401071d4279SBram Moolenaar 		break;
6402071d4279SBram Moolenaar 	    }
6403071d4279SBram Moolenaar 	}
64042951b77eSBram Moolenaar 
6405b255b905SBram Moolenaar 	LOG_TR(("Received XT %d: %s", xt_index_in, (char *)name));
6406b255b905SBram Moolenaar 
6407071d4279SBram Moolenaar 	if (key_names[i] != NULL)
6408071d4279SBram Moolenaar 	{
6409071d4279SBram Moolenaar 	    for (i = 8; (c = hexhex2nr(code + i)) >= 0; i += 2)
6410071d4279SBram Moolenaar 		str[j++] = c;
6411071d4279SBram Moolenaar 	    str[j] = NUL;
6412071d4279SBram Moolenaar 	    if (name[0] == 'C' && name[1] == 'o')
6413071d4279SBram Moolenaar 	    {
64140d6f5d97SBram Moolenaar 		// Color count is not a key code.
6415071d4279SBram Moolenaar 		i = atoi((char *)str);
6416b7a8dfebSBram Moolenaar 		may_adjust_color_count(i);
6417071d4279SBram Moolenaar 	    }
6418071d4279SBram Moolenaar 	    else
6419071d4279SBram Moolenaar 	    {
64200d6f5d97SBram Moolenaar 		// First delete any existing entry with the same code.
6421071d4279SBram Moolenaar 		i = find_term_bykeys(str);
6422071d4279SBram Moolenaar 		if (i >= 0)
6423071d4279SBram Moolenaar 		    del_termcode_idx(i);
6424bc7aa85dSBram Moolenaar 		add_termcode(name, str, ATC_FROM_TERM);
6425071d4279SBram Moolenaar 	    }
6426071d4279SBram Moolenaar 	}
6427071d4279SBram Moolenaar     }
6428071d4279SBram Moolenaar 
64290d6f5d97SBram Moolenaar     // May request more codes now that we received one.
6430071d4279SBram Moolenaar     ++xt_index_in;
6431071d4279SBram Moolenaar     req_more_codes_from_term();
6432071d4279SBram Moolenaar }
6433071d4279SBram Moolenaar 
6434071d4279SBram Moolenaar /*
6435071d4279SBram Moolenaar  * Check if there are any unanswered requests and deal with them.
6436071d4279SBram Moolenaar  * This is called before starting an external program or getting direct
6437071d4279SBram Moolenaar  * keyboard input.  We don't want responses to be send to that program or
6438071d4279SBram Moolenaar  * handled as typed text.
6439071d4279SBram Moolenaar  */
6440071d4279SBram Moolenaar     static void
check_for_codes_from_term(void)6441764b23c8SBram Moolenaar check_for_codes_from_term(void)
6442071d4279SBram Moolenaar {
6443071d4279SBram Moolenaar     int		c;
6444071d4279SBram Moolenaar 
64450d6f5d97SBram Moolenaar     // If no codes requested or all are answered, no need to wait.
6446071d4279SBram Moolenaar     if (xt_index_out == 0 || xt_index_out == xt_index_in)
6447071d4279SBram Moolenaar 	return;
6448071d4279SBram Moolenaar 
64490d6f5d97SBram Moolenaar     // Vgetc() will check for and handle any response.
64500d6f5d97SBram Moolenaar     // Keep calling vpeekc() until we don't get any responses.
6451071d4279SBram Moolenaar     ++no_mapping;
6452071d4279SBram Moolenaar     ++allow_keys;
6453071d4279SBram Moolenaar     for (;;)
6454071d4279SBram Moolenaar     {
6455071d4279SBram Moolenaar 	c = vpeekc();
64560d6f5d97SBram Moolenaar 	if (c == NUL)	    // nothing available
6457071d4279SBram Moolenaar 	    break;
6458071d4279SBram Moolenaar 
64590d6f5d97SBram Moolenaar 	// If a response is recognized it's replaced with K_IGNORE, must read
64600d6f5d97SBram Moolenaar 	// it from the input stream.  If there is no K_IGNORE we can't do
64610d6f5d97SBram Moolenaar 	// anything, break here (there might be some responses further on, but
64620d6f5d97SBram Moolenaar 	// we don't want to throw away any typed chars).
6463071d4279SBram Moolenaar 	if (c != K_SPECIAL && c != K_IGNORE)
6464071d4279SBram Moolenaar 	    break;
6465071d4279SBram Moolenaar 	c = vgetc();
6466071d4279SBram Moolenaar 	if (c != K_IGNORE)
6467071d4279SBram Moolenaar 	{
6468071d4279SBram Moolenaar 	    vungetc(c);
6469071d4279SBram Moolenaar 	    break;
6470071d4279SBram Moolenaar 	}
6471071d4279SBram Moolenaar     }
6472071d4279SBram Moolenaar     --no_mapping;
6473071d4279SBram Moolenaar     --allow_keys;
6474071d4279SBram Moolenaar }
6475071d4279SBram Moolenaar #endif
6476071d4279SBram Moolenaar 
6477afde13b6SBram Moolenaar #if (defined(MSWIN) && (!defined(FEAT_GUI) || defined(VIMDLL))) || defined(PROTO)
6478071d4279SBram Moolenaar static char ksme_str[20];
6479071d4279SBram Moolenaar static char ksmr_str[20];
6480071d4279SBram Moolenaar static char ksmd_str[20];
6481071d4279SBram Moolenaar 
6482071d4279SBram Moolenaar /*
6483071d4279SBram Moolenaar  * For Win32 console: update termcap codes for existing console attributes.
6484071d4279SBram Moolenaar  */
6485071d4279SBram Moolenaar     void
update_tcap(int attr)6486764b23c8SBram Moolenaar update_tcap(int attr)
6487071d4279SBram Moolenaar {
6488071d4279SBram Moolenaar     struct builtin_term *p;
6489071d4279SBram Moolenaar 
6490071d4279SBram Moolenaar     p = find_builtin_term(DEFAULT_TERM);
6491071d4279SBram Moolenaar     sprintf(ksme_str, IF_EB("\033|%dm", ESC_STR "|%dm"), attr);
6492071d4279SBram Moolenaar     sprintf(ksmd_str, IF_EB("\033|%dm", ESC_STR "|%dm"),
64930d6f5d97SBram Moolenaar 				     attr | 0x08);  // FOREGROUND_INTENSITY
6494071d4279SBram Moolenaar     sprintf(ksmr_str, IF_EB("\033|%dm", ESC_STR "|%dm"),
6495071d4279SBram Moolenaar 				 ((attr & 0x0F) << 4) | ((attr & 0xF0) >> 4));
6496071d4279SBram Moolenaar 
6497071d4279SBram Moolenaar     while (p->bt_string != NULL)
6498071d4279SBram Moolenaar     {
6499071d4279SBram Moolenaar       if (p->bt_entry == (int)KS_ME)
6500071d4279SBram Moolenaar 	  p->bt_string = &ksme_str[0];
6501071d4279SBram Moolenaar       else if (p->bt_entry == (int)KS_MR)
6502071d4279SBram Moolenaar 	  p->bt_string = &ksmr_str[0];
6503071d4279SBram Moolenaar       else if (p->bt_entry == (int)KS_MD)
6504071d4279SBram Moolenaar 	  p->bt_string = &ksmd_str[0];
6505071d4279SBram Moolenaar       ++p;
6506071d4279SBram Moolenaar     }
6507071d4279SBram Moolenaar }
6508cafafb38SBram Moolenaar 
6509cc0f2be8SBram Moolenaar # ifdef FEAT_TERMGUICOLORS
6510c5cd8855SBram Moolenaar #  define KSSIZE 20
6511cafafb38SBram Moolenaar struct ks_tbl_s
6512cafafb38SBram Moolenaar {
6513d4f73438SBram Moolenaar     int  code;		// value of KS_
6514d4f73438SBram Moolenaar     char *vtp;		// code in vtp mode
6515d4f73438SBram Moolenaar     char *vtp2;		// code in vtp2 mode
6516d4f73438SBram Moolenaar     char buf[KSSIZE];   // save buffer in non-vtp mode
6517d4f73438SBram Moolenaar     char vbuf[KSSIZE];  // save buffer in vtp mode
6518d4f73438SBram Moolenaar     char v2buf[KSSIZE]; // save buffer in vtp2 mode
6519d4f73438SBram Moolenaar     char arr[KSSIZE];   // real buffer
6520cafafb38SBram Moolenaar };
6521cafafb38SBram Moolenaar 
6522cafafb38SBram Moolenaar static struct ks_tbl_s ks_tbl[] =
6523cafafb38SBram Moolenaar {
6524d4f73438SBram Moolenaar     {(int)KS_ME,  "\033|0m",  "\033|0m"},   // normal
6525d4f73438SBram Moolenaar     {(int)KS_MR,  "\033|7m",  "\033|7m"},   // reverse
6526d4f73438SBram Moolenaar     {(int)KS_MD,  "\033|1m",  "\033|1m"},   // bold
6527d4f73438SBram Moolenaar     {(int)KS_SO,  "\033|91m", "\033|91m"},  // standout: bright red text
6528d4f73438SBram Moolenaar     {(int)KS_SE,  "\033|39m", "\033|39m"},  // standout end: default color
6529d4f73438SBram Moolenaar     {(int)KS_CZH, "\033|95m", "\033|95m"},  // italic: bright magenta text
6530d4f73438SBram Moolenaar     {(int)KS_CZR, "\033|0m",  "\033|0m"},   // italic end
6531d4f73438SBram Moolenaar     {(int)KS_US,  "\033|4m",  "\033|4m"},   // underscore
6532d4f73438SBram Moolenaar     {(int)KS_UE,  "\033|24m", "\033|24m"},  // underscore end
6533c5cd8855SBram Moolenaar #  ifdef TERMINFO
6534d4f73438SBram Moolenaar     {(int)KS_CAB, "\033|%p1%db", "\033|%p14%dm"}, // set background color
6535d4f73438SBram Moolenaar     {(int)KS_CAF, "\033|%p1%df", "\033|%p13%dm"}, // set foreground color
65366982f42fSBram Moolenaar     {(int)KS_CS,  "\033|%p1%d;%p2%dR", "\033|%p1%d;%p2%dR"},
65376982f42fSBram Moolenaar     {(int)KS_CSV, "\033|%p1%d;%p2%dV", "\033|%p1%d;%p2%dV"},
6538c5cd8855SBram Moolenaar #  else
6539d4f73438SBram Moolenaar     {(int)KS_CAB, "\033|%db", "\033|4%dm"}, // set background color
6540d4f73438SBram Moolenaar     {(int)KS_CAF, "\033|%df", "\033|3%dm"}, // set foreground color
65416982f42fSBram Moolenaar     {(int)KS_CS,  "\033|%d;%dR", "\033|%d;%dR"},
65426982f42fSBram Moolenaar     {(int)KS_CSV, "\033|%d;%dV", "\033|%d;%dV"},
6543c5cd8855SBram Moolenaar #  endif
6544d4f73438SBram Moolenaar     {(int)KS_CCO, "256", "256"},	    // colors
6545d4f73438SBram Moolenaar     {(int)KS_NAME}			    // terminator
6546cafafb38SBram Moolenaar };
6547cafafb38SBram Moolenaar 
6548cafafb38SBram Moolenaar     static struct builtin_term *
find_first_tcap(char_u * name,int code)6549cafafb38SBram Moolenaar find_first_tcap(
6550cafafb38SBram Moolenaar     char_u *name,
6551cafafb38SBram Moolenaar     int	    code)
6552cafafb38SBram Moolenaar {
6553cafafb38SBram Moolenaar     struct builtin_term *p;
6554cafafb38SBram Moolenaar 
6555cc0f2be8SBram Moolenaar     for (p = find_builtin_term(name); p->bt_string != NULL; ++p)
6556cafafb38SBram Moolenaar 	if (p->bt_entry == code)
6557cafafb38SBram Moolenaar 	    return p;
6558cafafb38SBram Moolenaar     return NULL;
6559cafafb38SBram Moolenaar }
6560cc0f2be8SBram Moolenaar # endif
6561cafafb38SBram Moolenaar 
6562cafafb38SBram Moolenaar /*
6563cafafb38SBram Moolenaar  * For Win32 console: replace the sequence immediately after termguicolors.
6564cafafb38SBram Moolenaar  */
6565cafafb38SBram Moolenaar     void
swap_tcap(void)6566cafafb38SBram Moolenaar swap_tcap(void)
6567cafafb38SBram Moolenaar {
6568cafafb38SBram Moolenaar # ifdef FEAT_TERMGUICOLORS
6569cc0f2be8SBram Moolenaar     static int		init_done = FALSE;
6570c5cd8855SBram Moolenaar     static int		curr_mode;
6571cafafb38SBram Moolenaar     struct ks_tbl_s	*ks;
6572cafafb38SBram Moolenaar     struct builtin_term *bt;
6573c5cd8855SBram Moolenaar     int			mode;
6574c5cd8855SBram Moolenaar     enum
6575c5cd8855SBram Moolenaar     {
6576c5cd8855SBram Moolenaar 	CMODEINDEX,
6577c5cd8855SBram Moolenaar 	CMODE24,
6578c5cd8855SBram Moolenaar 	CMODE256
6579c5cd8855SBram Moolenaar     };
6580cafafb38SBram Moolenaar 
65810d6f5d97SBram Moolenaar     // buffer initialization
6582cc0f2be8SBram Moolenaar     if (!init_done)
6583cafafb38SBram Moolenaar     {
6584c5cd8855SBram Moolenaar 	for (ks = ks_tbl; ks->code != (int)KS_NAME; ks++)
6585cafafb38SBram Moolenaar 	{
6586cafafb38SBram Moolenaar 	    bt = find_first_tcap(DEFAULT_TERM, ks->code);
6587cc0f2be8SBram Moolenaar 	    if (bt != NULL)
6588cc0f2be8SBram Moolenaar 	    {
6589c5cd8855SBram Moolenaar 		STRNCPY(ks->buf, bt->bt_string, KSSIZE);
6590c5cd8855SBram Moolenaar 		STRNCPY(ks->vbuf, ks->vtp, KSSIZE);
6591c5cd8855SBram Moolenaar 		STRNCPY(ks->v2buf, ks->vtp2, KSSIZE);
6592c5cd8855SBram Moolenaar 
6593c5cd8855SBram Moolenaar 		STRNCPY(ks->arr, bt->bt_string, KSSIZE);
6594c5cd8855SBram Moolenaar 		bt->bt_string = &ks->arr[0];
6595cafafb38SBram Moolenaar 	    }
6596cc0f2be8SBram Moolenaar 	}
6597cc0f2be8SBram Moolenaar 	init_done = TRUE;
6598c5cd8855SBram Moolenaar 	curr_mode = CMODEINDEX;
6599cafafb38SBram Moolenaar     }
6600cafafb38SBram Moolenaar 
6601cafafb38SBram Moolenaar     if (p_tgc)
6602c5cd8855SBram Moolenaar 	mode = CMODE24;
6603c5cd8855SBram Moolenaar     else if (t_colors >= 256)
6604c5cd8855SBram Moolenaar 	mode = CMODE256;
6605cafafb38SBram Moolenaar     else
6606c5cd8855SBram Moolenaar 	mode = CMODEINDEX;
6607c5cd8855SBram Moolenaar 
6608c5cd8855SBram Moolenaar     for (ks = ks_tbl; ks->code != (int)KS_NAME; ks++)
6609cafafb38SBram Moolenaar     {
6610cafafb38SBram Moolenaar 	bt = find_first_tcap(DEFAULT_TERM, ks->code);
6611cc0f2be8SBram Moolenaar 	if (bt != NULL)
6612cc0f2be8SBram Moolenaar 	{
6613c5cd8855SBram Moolenaar 	    switch (curr_mode)
6614c5cd8855SBram Moolenaar 	    {
6615c5cd8855SBram Moolenaar 	    case CMODEINDEX:
6616c5cd8855SBram Moolenaar 		STRNCPY(&ks->buf[0], bt->bt_string, KSSIZE);
6617c5cd8855SBram Moolenaar 		break;
6618c5cd8855SBram Moolenaar 	    case CMODE24:
6619c5cd8855SBram Moolenaar 		STRNCPY(&ks->vbuf[0], bt->bt_string, KSSIZE);
6620c5cd8855SBram Moolenaar 		break;
6621c5cd8855SBram Moolenaar 	    default:
6622c5cd8855SBram Moolenaar 		STRNCPY(&ks->v2buf[0], bt->bt_string, KSSIZE);
6623cc0f2be8SBram Moolenaar 	    }
6624cafafb38SBram Moolenaar 	}
6625cafafb38SBram Moolenaar     }
6626cafafb38SBram Moolenaar 
6627c5cd8855SBram Moolenaar     if (mode != curr_mode)
6628c5cd8855SBram Moolenaar     {
6629c5cd8855SBram Moolenaar 	for (ks = ks_tbl; ks->code != (int)KS_NAME; ks++)
6630c5cd8855SBram Moolenaar 	{
6631c5cd8855SBram Moolenaar 	    bt = find_first_tcap(DEFAULT_TERM, ks->code);
6632c5cd8855SBram Moolenaar 	    if (bt != NULL)
6633c5cd8855SBram Moolenaar 	    {
6634c5cd8855SBram Moolenaar 		switch (mode)
6635c5cd8855SBram Moolenaar 		{
6636c5cd8855SBram Moolenaar 		case CMODEINDEX:
6637c5cd8855SBram Moolenaar 		    STRNCPY(bt->bt_string, &ks->buf[0], KSSIZE);
6638c5cd8855SBram Moolenaar 		    break;
6639c5cd8855SBram Moolenaar 		case CMODE24:
6640c5cd8855SBram Moolenaar 		    STRNCPY(bt->bt_string, &ks->vbuf[0], KSSIZE);
6641c5cd8855SBram Moolenaar 		    break;
6642c5cd8855SBram Moolenaar 		default:
6643c5cd8855SBram Moolenaar 		    STRNCPY(bt->bt_string, &ks->v2buf[0], KSSIZE);
6644c5cd8855SBram Moolenaar 		}
6645c5cd8855SBram Moolenaar 	    }
6646c5cd8855SBram Moolenaar 	}
6647c5cd8855SBram Moolenaar 
6648c5cd8855SBram Moolenaar 	curr_mode = mode;
6649cafafb38SBram Moolenaar     }
6650cafafb38SBram Moolenaar # endif
6651cafafb38SBram Moolenaar }
6652cafafb38SBram Moolenaar 
6653071d4279SBram Moolenaar #endif
6654ab302219SBram Moolenaar 
6655c5cd8855SBram Moolenaar 
6656afde13b6SBram Moolenaar #if (defined(MSWIN) && (!defined(FEAT_GUI_MSWIN) || defined(VIMDLL))) || defined(FEAT_TERMINAL) \
6657c5cd8855SBram Moolenaar 	|| defined(PROTO)
6658c5cd8855SBram Moolenaar static int cube_value[] = {
6659c5cd8855SBram Moolenaar     0x00, 0x5F, 0x87, 0xAF, 0xD7, 0xFF
6660c5cd8855SBram Moolenaar };
6661c5cd8855SBram Moolenaar 
6662c5cd8855SBram Moolenaar static int grey_ramp[] = {
6663c5cd8855SBram Moolenaar     0x08, 0x12, 0x1C, 0x26, 0x30, 0x3A, 0x44, 0x4E, 0x58, 0x62, 0x6C, 0x76,
6664c5cd8855SBram Moolenaar     0x80, 0x8A, 0x94, 0x9E, 0xA8, 0xB2, 0xBC, 0xC6, 0xD0, 0xDA, 0xE4, 0xEE
6665c5cd8855SBram Moolenaar };
6666c5cd8855SBram Moolenaar 
66679894e394SBram Moolenaar static char_u ansi_table[16][4] = {
6668c5cd8855SBram Moolenaar //   R    G    B   idx
6669c5cd8855SBram Moolenaar   {  0,   0,   0,  1}, // black
6670c5cd8855SBram Moolenaar   {224,   0,   0,  2}, // dark red
6671c5cd8855SBram Moolenaar   {  0, 224,   0,  3}, // dark green
6672c5cd8855SBram Moolenaar   {224, 224,   0,  4}, // dark yellow / brown
6673c5cd8855SBram Moolenaar   {  0,   0, 224,  5}, // dark blue
6674c5cd8855SBram Moolenaar   {224,   0, 224,  6}, // dark magenta
6675c5cd8855SBram Moolenaar   {  0, 224, 224,  7}, // dark cyan
6676c5cd8855SBram Moolenaar   {224, 224, 224,  8}, // light grey
6677c5cd8855SBram Moolenaar 
6678c5cd8855SBram Moolenaar   {128, 128, 128,  9}, // dark grey
6679c5cd8855SBram Moolenaar   {255,  64,  64, 10}, // light red
6680c5cd8855SBram Moolenaar   { 64, 255,  64, 11}, // light green
6681c5cd8855SBram Moolenaar   {255, 255,  64, 12}, // yellow
6682c5cd8855SBram Moolenaar   { 64,  64, 255, 13}, // light blue
6683c5cd8855SBram Moolenaar   {255,  64, 255, 14}, // light magenta
6684c5cd8855SBram Moolenaar   { 64, 255, 255, 15}, // light cyan
6685c5cd8855SBram Moolenaar   {255, 255, 255, 16}, // white
6686c5cd8855SBram Moolenaar };
6687c5cd8855SBram Moolenaar 
6688e5886ccbSBram Moolenaar #define ANSI_INDEX_NONE 0
6689e5886ccbSBram Moolenaar 
6690c5cd8855SBram Moolenaar     void
cterm_color2rgb(int nr,char_u * r,char_u * g,char_u * b,char_u * ansi_idx)66919894e394SBram Moolenaar cterm_color2rgb(int nr, char_u *r, char_u *g, char_u *b, char_u *ansi_idx)
6692c5cd8855SBram Moolenaar {
6693c5cd8855SBram Moolenaar     int idx;
6694c5cd8855SBram Moolenaar 
6695c5cd8855SBram Moolenaar     if (nr < 16)
6696c5cd8855SBram Moolenaar     {
6697c5cd8855SBram Moolenaar 	*r = ansi_table[nr][0];
6698c5cd8855SBram Moolenaar 	*g = ansi_table[nr][1];
6699c5cd8855SBram Moolenaar 	*b = ansi_table[nr][2];
6700c5cd8855SBram Moolenaar 	*ansi_idx = ansi_table[nr][3];
6701c5cd8855SBram Moolenaar     }
6702c5cd8855SBram Moolenaar     else if (nr < 232)
6703c5cd8855SBram Moolenaar     {
67040d6f5d97SBram Moolenaar 	// 216 color cube
6705c5cd8855SBram Moolenaar 	idx = nr - 16;
6706c5cd8855SBram Moolenaar 	*r = cube_value[idx / 36 % 6];
6707c5cd8855SBram Moolenaar 	*g = cube_value[idx / 6  % 6];
6708c5cd8855SBram Moolenaar 	*b = cube_value[idx      % 6];
6709e5886ccbSBram Moolenaar 	*ansi_idx = ANSI_INDEX_NONE;
6710c5cd8855SBram Moolenaar     }
6711c5cd8855SBram Moolenaar     else if (nr < 256)
6712c5cd8855SBram Moolenaar     {
67130d6f5d97SBram Moolenaar 	// 24 grey scale ramp
6714c5cd8855SBram Moolenaar 	idx = nr - 232;
6715c5cd8855SBram Moolenaar 	*r = grey_ramp[idx];
6716c5cd8855SBram Moolenaar 	*g = grey_ramp[idx];
6717c5cd8855SBram Moolenaar 	*b = grey_ramp[idx];
6718e5886ccbSBram Moolenaar 	*ansi_idx = ANSI_INDEX_NONE;
6719c5cd8855SBram Moolenaar     }
6720c5cd8855SBram Moolenaar     else
6721c5cd8855SBram Moolenaar     {
6722c5cd8855SBram Moolenaar 	*r = 0;
6723c5cd8855SBram Moolenaar 	*g = 0;
6724c5cd8855SBram Moolenaar 	*b = 0;
6725e5886ccbSBram Moolenaar 	*ansi_idx = ANSI_INDEX_NONE;
6726c5cd8855SBram Moolenaar     }
6727c5cd8855SBram Moolenaar }
6728c5cd8855SBram Moolenaar #endif
67294f97475dSBram Moolenaar 
6730f4140488SBram Moolenaar /*
6731f4140488SBram Moolenaar  * Replace K_BS by <BS> and K_DEL by <DEL>
6732f4140488SBram Moolenaar  */
6733f4140488SBram Moolenaar     void
term_replace_bs_del_keycode(char_u * ta_buf,int ta_len,int len)6734f4140488SBram Moolenaar term_replace_bs_del_keycode(char_u *ta_buf, int ta_len, int len)
6735f4140488SBram Moolenaar {
6736f4140488SBram Moolenaar     int		i;
6737f4140488SBram Moolenaar     int		c;
6738f4140488SBram Moolenaar 
6739f4140488SBram Moolenaar     for (i = ta_len; i < ta_len + len; ++i)
6740f4140488SBram Moolenaar     {
6741f4140488SBram Moolenaar 	if (ta_buf[i] == CSI && len - i > 2)
6742f4140488SBram Moolenaar 	{
6743f4140488SBram Moolenaar 	    c = TERMCAP2KEY(ta_buf[i + 1], ta_buf[i + 2]);
6744f4140488SBram Moolenaar 	    if (c == K_DEL || c == K_KDEL || c == K_BS)
6745f4140488SBram Moolenaar 	    {
6746f4140488SBram Moolenaar 		mch_memmove(ta_buf + i + 1, ta_buf + i + 3,
6747f4140488SBram Moolenaar 			(size_t)(len - i - 2));
6748f4140488SBram Moolenaar 		if (c == K_DEL || c == K_KDEL)
6749f4140488SBram Moolenaar 		    ta_buf[i] = DEL;
6750f4140488SBram Moolenaar 		else
6751f4140488SBram Moolenaar 		    ta_buf[i] = Ctrl_H;
6752f4140488SBram Moolenaar 		len -= 2;
6753f4140488SBram Moolenaar 	    }
6754f4140488SBram Moolenaar 	}
6755f4140488SBram Moolenaar 	else if (ta_buf[i] == '\r')
6756f4140488SBram Moolenaar 	    ta_buf[i] = '\n';
6757f4140488SBram Moolenaar 	if (has_mbyte)
6758f4140488SBram Moolenaar 	    i += (*mb_ptr2len_len)(ta_buf + i, ta_len + len - i) - 1;
6759f4140488SBram Moolenaar     }
6760f4140488SBram Moolenaar }
6761