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