blob: 3097cc324d9c1c9fcba16c27af645b523288f95b [file] [log] [blame]
Bram Moolenaar071d4272004-06-13 20:20:40 +00001/* vi:set ts=8 sts=4 sw=4:
2 *
3 * VIM - Vi IMproved by Bram Moolenaar
4 *
5 * Do ":help uganda" in Vim to read copying and usage conditions.
6 * Do ":help credits" in Vim to see a list of people who contributed.
7 * See README.txt for an overview of the Vim source code.
8 */
9/*
10 *
11 * term.c: functions for controlling the terminal
12 *
13 * primitive termcap support for Amiga, MSDOS, and Win32 included
14 *
15 * NOTE: padding and variable substitution is not performed,
16 * when compiling without HAVE_TGETENT, we use tputs() and tgoto() dummies.
17 */
18
19/*
20 * Some systems have a prototype for tgetstr() with (char *) instead of
21 * (char **). This define removes that prototype. We include our own prototype
22 * below.
23 */
24
25#define tgetstr tgetstr_defined_wrong
26#include "vim.h"
27
28#ifdef HAVE_TGETENT
29# ifdef HAVE_TERMIOS_H
30# include <termios.h> /* seems to be required for some Linux */
31# endif
32# ifdef HAVE_TERMCAP_H
33# include <termcap.h>
34# endif
35
36/*
37 * A few linux systems define outfuntype in termcap.h to be used as the third
38 * argument for tputs().
39 */
40# ifdef VMS
41# define TPUTSFUNCAST
42# else
43# ifdef HAVE_OUTFUNTYPE
44# define TPUTSFUNCAST (outfuntype)
45# else
46# define TPUTSFUNCAST (int (*)())
47# endif
48# endif
49#endif
50
51#undef tgetstr
52
53/*
54 * Here are the builtin termcap entries. They are not stored as complete
55 * Tcarr structures, as such a structure is too big.
56 *
57 * The entries are compact, therefore they normally are included even when
58 * HAVE_TGETENT is defined. When HAVE_TGETENT is defined, the builtin entries
59 * can be accessed with "builtin_amiga", "builtin_ansi", "builtin_debug", etc.
60 *
61 * Each termcap is a list of builtin_term structures. It always starts with
62 * KS_NAME, which separates the entries. See parse_builtin_tcap() for all
63 * details.
64 * bt_entry is either a KS_xxx code (>= 0), or a K_xxx code.
65 *
66 * Entries marked with "guessed" may be wrong.
67 */
68struct builtin_term
69{
70 int bt_entry;
71 char *bt_string;
72};
73
74/* start of keys that are not directly used by Vim but can be mapped */
75#define BT_EXTRA_KEYS 0x101
76
77static struct builtin_term *find_builtin_term __ARGS((char_u *name));
78static void parse_builtin_tcap __ARGS((char_u *s));
79static void term_color __ARGS((char_u *s, int n));
80static void gather_termleader __ARGS((void));
81#ifdef FEAT_TERMRESPONSE
82static void req_codes_from_term __ARGS((void));
83static void req_more_codes_from_term __ARGS((void));
84static void got_code_from_term __ARGS((char_u *code, int len));
85static void check_for_codes_from_term __ARGS((void));
86#endif
87#if defined(FEAT_GUI) \
88 || (defined(FEAT_MOUSE) && (!defined(UNIX) || defined(FEAT_MOUSE_XTERM)))
89static int get_bytes_from_buf __ARGS((char_u *, char_u *, int));
90#endif
91#ifdef FEAT_TERMRESPONSE
92static void may_req_termresponse __ARGS((void));
93#endif
94static void del_termcode_idx __ARGS((int idx));
95static int term_is_builtin __ARGS((char_u *name));
96static int term_7to8bit __ARGS((char_u *p));
97#ifdef FEAT_TERMRESPONSE
98static void switch_to_8bit __ARGS((void));
99#endif
100
101#ifdef HAVE_TGETENT
102static char_u *tgetent_error __ARGS((char_u *, char_u *));
103
104/*
105 * Here is our own prototype for tgetstr(), any prototypes from the include
106 * files have been disabled by the define at the start of this file.
107 */
108char *tgetstr __ARGS((char *, char **));
109
110# ifdef FEAT_TERMRESPONSE
111/* Request Terminal Version status: */
112# define CRV_GET 1 /* send T_CRV when switched to RAW mode */
113# define CRV_SENT 2 /* did send T_CRV, waiting for answer */
114# define CRV_GOT 3 /* received T_CRV response */
115static int crv_status = CRV_GET;
116# endif
117
118/*
119 * Don't declare these variables if termcap.h contains them.
120 * Autoconf checks if these variables should be declared extern (not all
121 * systems have them).
122 * Some versions define ospeed to be speed_t, but that is incompatible with
123 * BSD, where ospeed is short and speed_t is long.
124 */
125# ifndef HAVE_OSPEED
126# ifdef OSPEED_EXTERN
127extern short ospeed;
128# else
129short ospeed;
130# endif
131# endif
132# ifndef HAVE_UP_BC_PC
133# ifdef UP_BC_PC_EXTERN
134extern char *UP, *BC, PC;
135# else
136char *UP, *BC, PC;
137# endif
138# endif
139
140# define TGETSTR(s, p) vim_tgetstr((s), (p))
141# define TGETENT(b, t) tgetent((char *)(b), (char *)(t))
142static char_u *vim_tgetstr __ARGS((char *s, char_u **pp));
143#endif /* HAVE_TGETENT */
144
145static int detected_8bit = FALSE; /* detected 8-bit terminal */
146
147struct builtin_term builtin_termcaps[] =
148{
149
150#if defined(FEAT_GUI)
151/*
152 * GUI pseudo term-cap.
153 */
154 {(int)KS_NAME, "gui"},
155 {(int)KS_CE, IF_EB("\033|$", ESC_STR "|$")},
156 {(int)KS_AL, IF_EB("\033|i", ESC_STR "|i")},
157# ifdef TERMINFO
158 {(int)KS_CAL, IF_EB("\033|%p1%dI", ESC_STR "|%p1%dI")},
159# else
160 {(int)KS_CAL, IF_EB("\033|%dI", ESC_STR "|%dI")},
161# endif
162 {(int)KS_DL, IF_EB("\033|d", ESC_STR "|d")},
163# ifdef TERMINFO
164 {(int)KS_CDL, IF_EB("\033|%p1%dD", ESC_STR "|%p1%dD")},
165 {(int)KS_CS, IF_EB("\033|%p1%d;%p2%dR", ESC_STR "|%p1%d;%p2%dR")},
166# ifdef FEAT_VERTSPLIT
167 {(int)KS_CSV, IF_EB("\033|%p1%d;%p2%dV", ESC_STR "|%p1%d;%p2%dV")},
168# endif
169# else
170 {(int)KS_CDL, IF_EB("\033|%dD", ESC_STR "|%dD")},
171 {(int)KS_CS, IF_EB("\033|%d;%dR", ESC_STR "|%d;%dR")},
172# ifdef FEAT_VERTSPLIT
173 {(int)KS_CSV, IF_EB("\033|%d;%dV", ESC_STR "|%d;%dV")},
174# endif
175# endif
176 {(int)KS_CL, IF_EB("\033|C", ESC_STR "|C")},
177 /* attributes switched on with 'h', off with * 'H' */
178 {(int)KS_ME, IF_EB("\033|31H", ESC_STR "|31H")}, /* HL_ALL */
179 {(int)KS_MR, IF_EB("\033|1h", ESC_STR "|1h")}, /* HL_INVERSE */
180 {(int)KS_MD, IF_EB("\033|2h", ESC_STR "|2h")}, /* HL_BOLD */
181 {(int)KS_SE, IF_EB("\033|16H", ESC_STR "|16H")}, /* HL_STANDOUT */
182 {(int)KS_SO, IF_EB("\033|16h", ESC_STR "|16h")}, /* HL_STANDOUT */
183 {(int)KS_UE, IF_EB("\033|8H", ESC_STR "|8H")}, /* HL_UNDERLINE */
184 {(int)KS_US, IF_EB("\033|8h", ESC_STR "|8h")}, /* HL_UNDERLINE */
185 {(int)KS_CZR, IF_EB("\033|4H", ESC_STR "|4H")}, /* HL_ITALIC */
186 {(int)KS_CZH, IF_EB("\033|4h", ESC_STR "|4h")}, /* HL_ITALIC */
187 {(int)KS_VB, IF_EB("\033|f", ESC_STR "|f")},
188 {(int)KS_MS, "y"},
189 {(int)KS_UT, "y"},
190 {(int)KS_LE, "\b"}, /* cursor-left = BS */
191 {(int)KS_ND, "\014"}, /* cursor-right = CTRL-L */
192# ifdef TERMINFO
193 {(int)KS_CM, IF_EB("\033|%p1%d;%p2%dM", ESC_STR "|%p1%d;%p2%dM")},
194# else
195 {(int)KS_CM, IF_EB("\033|%d;%dM", ESC_STR "|%d;%dM")},
196# endif
197 /* there are no key sequences here, the GUI sequences are recognized
198 * in check_termcodes() */
199#endif
200
201#ifndef NO_BUILTIN_TCAPS
202# if defined(RISCOS) || defined(ALL_BUILTIN_TCAPS)
203/*
204 * Default for the Acorn.
205 */
206 {(int)KS_NAME, "riscos"},
207 {(int)KS_CL, "\014"}, /* Cls and Home Cursor */
208 {(int)KS_CM, "\001%d\001%d\002"}, /* Position cursor */
209
210 {(int)KS_CCO, "16"}, /* Allow 16 colors */
211
212 {(int)KS_CAF, "\001%d\021"}, /* Set foreground colour */
213 {(int)KS_CAB, "\001%d\022"}, /* Set background colour */
214
215
216 {(int)KS_ME, "\004"}, /* Normal mode */
217 {(int)KS_MR, "\005"}, /* Reverse */
218
219 {(int)KS_VI, "\016"}, /* Cursor invisible */
220 {(int)KS_VE, "\017"}, /* Cursor visible */
221 {(int)KS_VS, "\020"}, /* Cursor very visible */
222
223 {(int)KS_CS, "\001%d\001%d\003"}, /* Set scroll region */
224 {(int)KS_SR, "\023"}, /* Scroll text down */
225 {K_UP, "\217"},
226 {K_DOWN, "\216"},
227 {K_LEFT, "\214"},
228 {K_RIGHT, "\215"},
229 {K_S_UP, "\237"},
230 {K_S_DOWN, "\236"},
231 {K_S_LEFT, "\234"},
232 {K_S_RIGHT, "\235"},
233
234 {K_F1, "\201"},
235 {K_F2, "\202"},
236 {K_F3, "\203"},
237 {K_F4, "\204"},
238 {K_F5, "\205"},
239 {K_F6, "\206"},
240 {K_F7, "\207"},
241 {K_F8, "\210"},
242 {K_F9, "\211"},
243 {K_F10, "\312"},
244 {K_F11, "\313"},
245 {K_F12, "\314"},
246 {K_S_F1, "\221"},
247 {K_S_F2, "\222"},
248 {K_S_F3, "\223"},
249 {K_S_F4, "\224"},
250 {K_S_F5, "\225"},
251 {K_S_F6, "\226"},
252 {K_S_F7, "\227"},
253 {K_S_F8, "\230"},
254 {K_S_F9, "\231"},
255 {K_S_F10, "\332"},
256 {K_S_F11, "\333"},
257 {K_S_F12, "\334"},
258 {K_BS, "\010"},
259 {K_INS, "\315"},
260 {K_DEL, "\177"},
261 {K_HOME, "\036"},
262 {K_END, "\213"},
263 {K_PAGEUP, "\237"},
264 {K_PAGEDOWN, "\236"},
265# endif /* Acorn terminal */
266
267
268# if defined(AMIGA) || defined(ALL_BUILTIN_TCAPS)
269/*
270 * Amiga console window, default for Amiga
271 */
272 {(int)KS_NAME, "amiga"},
273 {(int)KS_CE, "\033[K"},
274 {(int)KS_CD, "\033[J"},
275 {(int)KS_AL, "\033[L"},
276# ifdef TERMINFO
277 {(int)KS_CAL, "\033[%p1%dL"},
278# else
279 {(int)KS_CAL, "\033[%dL"},
280# endif
281 {(int)KS_DL, "\033[M"},
282# ifdef TERMINFO
283 {(int)KS_CDL, "\033[%p1%dM"},
284# else
285 {(int)KS_CDL, "\033[%dM"},
286# endif
287 {(int)KS_CL, "\014"},
288 {(int)KS_VI, "\033[0 p"},
289 {(int)KS_VE, "\033[1 p"},
290 {(int)KS_ME, "\033[0m"},
291 {(int)KS_MR, "\033[7m"},
292 {(int)KS_MD, "\033[1m"},
293 {(int)KS_SE, "\033[0m"},
294 {(int)KS_SO, "\033[33m"},
295 {(int)KS_US, "\033[4m"},
296 {(int)KS_UE, "\033[0m"},
297 {(int)KS_CZH, "\033[3m"},
298 {(int)KS_CZR, "\033[0m"},
299#if defined(__MORPHOS__) || defined(__AROS__)
300 {(int)KS_CCO, "8"}, /* allow 8 colors */
301# ifdef TERMINFO
302 {(int)KS_CAB, "\033[4%p1%dm"},/* set background color */
303 {(int)KS_CAF, "\033[3%p1%dm"},/* set foreground color */
304# else
305 {(int)KS_CAB, "\033[4%dm"}, /* set background color */
306 {(int)KS_CAF, "\033[3%dm"}, /* set foreground color */
307# endif
308 {(int)KS_OP, "\033[m"}, /* reset colors */
309#endif
310 {(int)KS_MS, "y"},
311 {(int)KS_UT, "y"}, /* guessed */
312 {(int)KS_LE, "\b"},
313# ifdef TERMINFO
314 {(int)KS_CM, "\033[%i%p1%d;%p2%dH"},
315# else
316 {(int)KS_CM, "\033[%i%d;%dH"},
317# endif
318#if defined(__MORPHOS__)
319 {(int)KS_SR, "\033M"},
320#endif
321# ifdef TERMINFO
322 {(int)KS_CRI, "\033[%p1%dC"},
323# else
324 {(int)KS_CRI, "\033[%dC"},
325# endif
326 {K_UP, "\233A"},
327 {K_DOWN, "\233B"},
328 {K_LEFT, "\233D"},
329 {K_RIGHT, "\233C"},
330 {K_S_UP, "\233T"},
331 {K_S_DOWN, "\233S"},
332 {K_S_LEFT, "\233 A"},
333 {K_S_RIGHT, "\233 @"},
334 {K_S_TAB, "\233Z"},
335 {K_F1, "\233\060~"},/* some compilers don't dig "\2330" */
336 {K_F2, "\233\061~"},
337 {K_F3, "\233\062~"},
338 {K_F4, "\233\063~"},
339 {K_F5, "\233\064~"},
340 {K_F6, "\233\065~"},
341 {K_F7, "\233\066~"},
342 {K_F8, "\233\067~"},
343 {K_F9, "\233\070~"},
344 {K_F10, "\233\071~"},
345 {K_S_F1, "\233\061\060~"},
346 {K_S_F2, "\233\061\061~"},
347 {K_S_F3, "\233\061\062~"},
348 {K_S_F4, "\233\061\063~"},
349 {K_S_F5, "\233\061\064~"},
350 {K_S_F6, "\233\061\065~"},
351 {K_S_F7, "\233\061\066~"},
352 {K_S_F8, "\233\061\067~"},
353 {K_S_F9, "\233\061\070~"},
354 {K_S_F10, "\233\061\071~"},
355 {K_HELP, "\233?~"},
356 {K_INS, "\233\064\060~"}, /* 101 key keyboard */
357 {K_PAGEUP, "\233\064\061~"}, /* 101 key keyboard */
358 {K_PAGEDOWN, "\233\064\062~"}, /* 101 key keyboard */
359 {K_HOME, "\233\064\064~"}, /* 101 key keyboard */
360 {K_END, "\233\064\065~"}, /* 101 key keyboard */
361
362 {BT_EXTRA_KEYS, ""},
363 {TERMCAP2KEY('#', '2'), "\233\065\064~"}, /* shifted home key */
364 {TERMCAP2KEY('#', '3'), "\233\065\060~"}, /* shifted insert key */
365 {TERMCAP2KEY('*', '7'), "\233\065\065~"}, /* shifted end key */
366# endif
367
368# if defined(__BEOS__) || defined(ALL_BUILTIN_TCAPS)
369/*
370 * almost standard ANSI terminal, default for bebox
371 */
372 {(int)KS_NAME, "beos-ansi"},
373 {(int)KS_CE, "\033[K"},
374 {(int)KS_CD, "\033[J"},
375 {(int)KS_AL, "\033[L"},
376# ifdef TERMINFO
377 {(int)KS_CAL, "\033[%p1%dL"},
378# else
379 {(int)KS_CAL, "\033[%dL"},
380# endif
381 {(int)KS_DL, "\033[M"},
382# ifdef TERMINFO
383 {(int)KS_CDL, "\033[%p1%dM"},
384# else
385 {(int)KS_CDL, "\033[%dM"},
386# endif
387#ifdef BEOS_PR_OR_BETTER
388# ifdef TERMINFO
389 {(int)KS_CS, "\033[%i%p1%d;%p2%dr"},
390# else
391 {(int)KS_CS, "\033[%i%d;%dr"}, /* scroll region */
392# endif
393#endif
394 {(int)KS_CL, "\033[H\033[2J"},
395#ifdef notyet
396 {(int)KS_VI, "[VI]"}, /* cursor invisible, VT320: CSI ? 25 l */
397 {(int)KS_VE, "[VE]"}, /* cursor visible, VT320: CSI ? 25 h */
398#endif
399 {(int)KS_ME, "\033[m"}, /* normal mode */
400 {(int)KS_MR, "\033[7m"}, /* reverse */
401 {(int)KS_MD, "\033[1m"}, /* bold */
402 {(int)KS_SO, "\033[31m"}, /* standout mode: red */
403 {(int)KS_SE, "\033[m"}, /* standout end */
404 {(int)KS_CZH, "\033[35m"}, /* italic: purple */
405 {(int)KS_CZR, "\033[m"}, /* italic end */
406 {(int)KS_US, "\033[4m"}, /* underscore mode */
407 {(int)KS_UE, "\033[m"}, /* underscore end */
408 {(int)KS_CCO, "8"}, /* allow 8 colors */
409# ifdef TERMINFO
410 {(int)KS_CAB, "\033[4%p1%dm"},/* set background color */
411 {(int)KS_CAF, "\033[3%p1%dm"},/* set foreground color */
412# else
413 {(int)KS_CAB, "\033[4%dm"}, /* set background color */
414 {(int)KS_CAF, "\033[3%dm"}, /* set foreground color */
415# endif
416 {(int)KS_OP, "\033[m"}, /* reset colors */
417 {(int)KS_MS, "y"}, /* safe to move cur in reverse mode */
418 {(int)KS_UT, "y"}, /* guessed */
419 {(int)KS_LE, "\b"},
420# ifdef TERMINFO
421 {(int)KS_CM, "\033[%i%p1%d;%p2%dH"},
422# else
423 {(int)KS_CM, "\033[%i%d;%dH"},
424# endif
425 {(int)KS_SR, "\033M"},
426# ifdef TERMINFO
427 {(int)KS_CRI, "\033[%p1%dC"},
428# else
429 {(int)KS_CRI, "\033[%dC"},
430# endif
431#if defined(BEOS_DR8)
432 {(int)KS_DB, ""}, /* hack! see screen.c */
433#endif
434
435 {K_UP, "\033[A"},
436 {K_DOWN, "\033[B"},
437 {K_LEFT, "\033[D"},
438 {K_RIGHT, "\033[C"},
439# endif
440
441# if defined(UNIX) || defined(ALL_BUILTIN_TCAPS) || defined(SOME_BUILTIN_TCAPS) || defined(__EMX__)
442/*
443 * standard ANSI terminal, default for unix
444 */
445 {(int)KS_NAME, "ansi"},
446 {(int)KS_CE, IF_EB("\033[K", ESC_STR "[K")},
447 {(int)KS_AL, IF_EB("\033[L", ESC_STR "[L")},
448# ifdef TERMINFO
449 {(int)KS_CAL, IF_EB("\033[%p1%dL", ESC_STR "[%p1%dL")},
450# else
451 {(int)KS_CAL, IF_EB("\033[%dL", ESC_STR "[%dL")},
452# endif
453 {(int)KS_DL, IF_EB("\033[M", ESC_STR "[M")},
454# ifdef TERMINFO
455 {(int)KS_CDL, IF_EB("\033[%p1%dM", ESC_STR "[%p1%dM")},
456# else
457 {(int)KS_CDL, IF_EB("\033[%dM", ESC_STR "[%dM")},
458# endif
459 {(int)KS_CL, IF_EB("\033[H\033[2J", ESC_STR "[H" ESC_STR_nc "[2J")},
460 {(int)KS_ME, IF_EB("\033[0m", ESC_STR "[0m")},
461 {(int)KS_MR, IF_EB("\033[7m", ESC_STR "[7m")},
462 {(int)KS_MS, "y"},
463 {(int)KS_UT, "y"}, /* guessed */
464 {(int)KS_LE, "\b"},
465# ifdef TERMINFO
466 {(int)KS_CM, IF_EB("\033[%i%p1%d;%p2%dH", ESC_STR "[%i%p1%d;%p2%dH")},
467# else
468 {(int)KS_CM, IF_EB("\033[%i%d;%dH", ESC_STR "[%i%d;%dH")},
469# endif
470# ifdef TERMINFO
471 {(int)KS_CRI, IF_EB("\033[%p1%dC", ESC_STR "[%p1%dC")},
472# else
473 {(int)KS_CRI, IF_EB("\033[%dC", ESC_STR "[%dC")},
474# endif
475# endif
476
477# if defined(MSDOS) || defined(ALL_BUILTIN_TCAPS) || defined(__EMX__)
478/*
479 * These codes are valid when nansi.sys or equivalent has been installed.
480 * Function keys on a PC are preceded with a NUL. These are converted into
481 * K_NUL '\316' in mch_inchar(), because we cannot handle NULs in key codes.
482 * CTRL-arrow is used instead of SHIFT-arrow.
483 */
484#ifdef __EMX__
485 {(int)KS_NAME, "os2ansi"},
486#else
487 {(int)KS_NAME, "pcansi"},
488 {(int)KS_DL, "\033[M"},
489 {(int)KS_AL, "\033[L"},
490#endif
491 {(int)KS_CE, "\033[K"},
492 {(int)KS_CL, "\033[2J"},
493 {(int)KS_ME, "\033[0m"},
494 {(int)KS_MR, "\033[5m"}, /* reverse: black on lightgrey */
495 {(int)KS_MD, "\033[1m"}, /* bold: white text */
496 {(int)KS_SE, "\033[0m"}, /* standout end */
497 {(int)KS_SO, "\033[31m"}, /* standout: white on blue */
498 {(int)KS_CZH, "\033[34;43m"}, /* italic mode: blue text on yellow */
499 {(int)KS_CZR, "\033[0m"}, /* italic mode end */
500 {(int)KS_US, "\033[36;41m"}, /* underscore mode: cyan text on red */
501 {(int)KS_UE, "\033[0m"}, /* underscore mode end */
502 {(int)KS_CCO, "8"}, /* allow 8 colors */
503# ifdef TERMINFO
504 {(int)KS_CAB, "\033[4%p1%dm"},/* set background color */
505 {(int)KS_CAF, "\033[3%p1%dm"},/* set foreground color */
506# else
507 {(int)KS_CAB, "\033[4%dm"}, /* set background color */
508 {(int)KS_CAF, "\033[3%dm"}, /* set foreground color */
509# endif
510 {(int)KS_OP, "\033[0m"}, /* reset colors */
511 {(int)KS_MS, "y"},
512 {(int)KS_UT, "y"}, /* guessed */
513 {(int)KS_LE, "\b"},
514# ifdef TERMINFO
515 {(int)KS_CM, "\033[%i%p1%d;%p2%dH"},
516# else
517 {(int)KS_CM, "\033[%i%d;%dH"},
518# endif
519# ifdef TERMINFO
520 {(int)KS_CRI, "\033[%p1%dC"},
521# else
522 {(int)KS_CRI, "\033[%dC"},
523# endif
524 {K_UP, "\316H"},
525 {K_DOWN, "\316P"},
526 {K_LEFT, "\316K"},
527 {K_RIGHT, "\316M"},
528 {K_S_LEFT, "\316s"},
529 {K_S_RIGHT, "\316t"},
530 {K_F1, "\316;"},
531 {K_F2, "\316<"},
532 {K_F3, "\316="},
533 {K_F4, "\316>"},
534 {K_F5, "\316?"},
535 {K_F6, "\316@"},
536 {K_F7, "\316A"},
537 {K_F8, "\316B"},
538 {K_F9, "\316C"},
539 {K_F10, "\316D"},
540 {K_F11, "\316\205"}, /* guessed */
541 {K_F12, "\316\206"}, /* guessed */
542 {K_S_F1, "\316T"},
543 {K_S_F2, "\316U"},
544 {K_S_F3, "\316V"},
545 {K_S_F4, "\316W"},
546 {K_S_F5, "\316X"},
547 {K_S_F6, "\316Y"},
548 {K_S_F7, "\316Z"},
549 {K_S_F8, "\316["},
550 {K_S_F9, "\316\\"},
551 {K_S_F10, "\316]"},
552 {K_S_F11, "\316\207"}, /* guessed */
553 {K_S_F12, "\316\210"}, /* guessed */
554 {K_INS, "\316R"},
555 {K_DEL, "\316S"},
556 {K_HOME, "\316G"},
557 {K_END, "\316O"},
558 {K_PAGEDOWN, "\316Q"},
559 {K_PAGEUP, "\316I"},
560# endif
561
562# if defined(MSDOS)
563/*
564 * These codes are valid for the pc video. The entries that start with ESC |
565 * are translated into conio calls in os_msdos.c. Default for MSDOS.
566 */
567 {(int)KS_NAME, "pcterm"},
568 {(int)KS_CE, "\033|K"},
569 {(int)KS_AL, "\033|L"},
570 {(int)KS_DL, "\033|M"},
571# ifdef TERMINFO
572 {(int)KS_CS, "\033|%i%p1%d;%p2%dr"},
573# ifdef FEAT_VERTSPLIT
574 {(int)KS_CSV, "\033|%i%p1%d;%p2%dV"},
575# endif
576# else
577 {(int)KS_CS, "\033|%i%d;%dr"},
578# ifdef FEAT_VERTSPLIT
579 {(int)KS_CSV, "\033|%i%d;%dV"},
580# endif
581# endif
582 {(int)KS_CL, "\033|J"},
583 {(int)KS_ME, "\033|0m"}, /* normal */
584 {(int)KS_MR, "\033|112m"}, /* reverse: black on lightgrey */
585 {(int)KS_MD, "\033|15m"}, /* bold: white text */
586 {(int)KS_SE, "\033|0m"}, /* standout end */
587 {(int)KS_SO, "\033|31m"}, /* standout: white on blue */
588 {(int)KS_CZH, "\033|225m"}, /* italic mode: blue text on yellow */
589 {(int)KS_CZR, "\033|0m"}, /* italic mode end */
590 {(int)KS_US, "\033|67m"}, /* underscore mode: cyan text on red */
591 {(int)KS_UE, "\033|0m"}, /* underscore mode end */
592 {(int)KS_CCO, "16"}, /* allow 16 colors */
593# ifdef TERMINFO
594 {(int)KS_CAB, "\033|%p1%db"}, /* set background color */
595 {(int)KS_CAF, "\033|%p1%df"}, /* set foreground color */
596# else
597 {(int)KS_CAB, "\033|%db"}, /* set background color */
598 {(int)KS_CAF, "\033|%df"}, /* set foreground color */
599# endif
600 {(int)KS_MS, "y"},
601 {(int)KS_UT, "y"},
602 {(int)KS_LE, "\b"},
603# ifdef TERMINFO
604 {(int)KS_CM, "\033|%i%p1%d;%p2%dH"},
605# else
606 {(int)KS_CM, "\033|%i%d;%dH"},
607# endif
608#ifdef DJGPP
609 {(int)KS_VB, "\033|B"}, /* visual bell */
610#endif
611 {K_UP, "\316H"},
612 {K_DOWN, "\316P"},
613 {K_LEFT, "\316K"},
614 {K_RIGHT, "\316M"},
615 {K_S_LEFT, "\316s"},
616 {K_S_RIGHT, "\316t"},
617 {K_S_TAB, "\316\017"},
618 {K_F1, "\316;"},
619 {K_F2, "\316<"},
620 {K_F3, "\316="},
621 {K_F4, "\316>"},
622 {K_F5, "\316?"},
623 {K_F6, "\316@"},
624 {K_F7, "\316A"},
625 {K_F8, "\316B"},
626 {K_F9, "\316C"},
627 {K_F10, "\316D"},
628 {K_F11, "\316\205"},
629 {K_F12, "\316\206"},
630 {K_S_F1, "\316T"},
631 {K_S_F2, "\316U"},
632 {K_S_F3, "\316V"},
633 {K_S_F4, "\316W"},
634 {K_S_F5, "\316X"},
635 {K_S_F6, "\316Y"},
636 {K_S_F7, "\316Z"},
637 {K_S_F8, "\316["},
638 {K_S_F9, "\316\\"},
639 {K_S_F10, "\316]"},
640 {K_S_F11, "\316\207"},
641 {K_S_F12, "\316\210"},
642 {K_INS, "\316R"},
643 {K_DEL, "\316S"},
644 {K_HOME, "\316G"},
645 {K_END, "\316O"},
646 {K_PAGEDOWN, "\316Q"},
647 {K_PAGEUP, "\316I"},
648 {K_KPLUS, "\316N"},
649 {K_KMINUS, "\316J"},
650 {K_KMULTIPLY, "\3167"},
651 {K_K0, "\316\332"},
652 {K_K1, "\316\336"},
653 {K_K2, "\316\342"},
654 {K_K3, "\316\346"},
655 {K_K4, "\316\352"},
656 {K_K5, "\316\356"},
657 {K_K6, "\316\362"},
658 {K_K7, "\316\366"},
659 {K_K8, "\316\372"},
660 {K_K9, "\316\376"},
661# endif
662
663# if defined(WIN3264) || defined(ALL_BUILTIN_TCAPS) || defined(__EMX__)
664/*
665 * These codes are valid for the Win32 Console . The entries that start with
666 * ESC | are translated into console calls in os_win32.c. The function keys
667 * are also translated in os_win32.c.
668 */
669 {(int)KS_NAME, "win32"},
670 {(int)KS_CE, "\033|K"}, /* clear to end of line */
671 {(int)KS_AL, "\033|L"}, /* add new blank line */
672# ifdef TERMINFO
673 {(int)KS_CAL, "\033|%p1%dL"}, /* add number of new blank lines */
674# else
675 {(int)KS_CAL, "\033|%dL"}, /* add number of new blank lines */
676# endif
677 {(int)KS_DL, "\033|M"}, /* delete line */
678# ifdef TERMINFO
679 {(int)KS_CDL, "\033|%p1%dM"}, /* delete number of lines */
680# else
681 {(int)KS_CDL, "\033|%dM"}, /* delete number of lines */
682# endif
683 {(int)KS_CL, "\033|J"}, /* clear screen */
684 {(int)KS_CD, "\033|j"}, /* clear to end of display */
685 {(int)KS_VI, "\033|v"}, /* cursor invisible */
686 {(int)KS_VE, "\033|V"}, /* cursor visible */
687
688 {(int)KS_ME, "\033|0m"}, /* normal */
689 {(int)KS_MR, "\033|112m"}, /* reverse: black on lightgray */
690 {(int)KS_MD, "\033|15m"}, /* bold: white on black */
691#if 1
692 {(int)KS_SO, "\033|31m"}, /* standout: white on blue */
693 {(int)KS_SE, "\033|0m"}, /* standout end */
694#else
695 {(int)KS_SO, "\033|F"}, /* standout: high intensity */
696 {(int)KS_SE, "\033|f"}, /* standout end */
697#endif
698 {(int)KS_CZH, "\033|225m"}, /* italic: blue text on yellow */
699 {(int)KS_CZR, "\033|0m"}, /* italic end */
700 {(int)KS_US, "\033|67m"}, /* underscore: cyan text on red */
701 {(int)KS_UE, "\033|0m"}, /* underscore end */
702 {(int)KS_CCO, "16"}, /* allow 16 colors */
703# ifdef TERMINFO
704 {(int)KS_CAB, "\033|%p1%db"}, /* set background color */
705 {(int)KS_CAF, "\033|%p1%df"}, /* set foreground color */
706# else
707 {(int)KS_CAB, "\033|%db"}, /* set background color */
708 {(int)KS_CAF, "\033|%df"}, /* set foreground color */
709# endif
710
711 {(int)KS_MS, "y"}, /* save to move cur in reverse mode */
712 {(int)KS_UT, "y"},
713 {(int)KS_LE, "\b"},
714# ifdef TERMINFO
715 {(int)KS_CM, "\033|%i%p1%d;%p2%dH"},/* cursor motion */
716# else
717 {(int)KS_CM, "\033|%i%d;%dH"},/* cursor motion */
718# endif
719 {(int)KS_VB, "\033|B"}, /* visual bell */
720 {(int)KS_TI, "\033|S"}, /* put terminal in termcap mode */
721 {(int)KS_TE, "\033|E"}, /* out of termcap mode */
722# ifdef TERMINFO
723 {(int)KS_CS, "\033|%i%p1%d;%p2%dr"},/* scroll region */
724# else
725 {(int)KS_CS, "\033|%i%d;%dr"},/* scroll region */
726# endif
727
728 {K_UP, "\316H"},
729 {K_DOWN, "\316P"},
730 {K_LEFT, "\316K"},
731 {K_RIGHT, "\316M"},
732 {K_S_UP, "\316\304"},
733 {K_S_DOWN, "\316\317"},
734 {K_S_LEFT, "\316\311"},
735 {K_C_LEFT, "\316s"},
736 {K_S_RIGHT, "\316\313"},
737 {K_C_RIGHT, "\316t"},
738 {K_S_TAB, "\316\017"},
739 {K_F1, "\316;"},
740 {K_F2, "\316<"},
741 {K_F3, "\316="},
742 {K_F4, "\316>"},
743 {K_F5, "\316?"},
744 {K_F6, "\316@"},
745 {K_F7, "\316A"},
746 {K_F8, "\316B"},
747 {K_F9, "\316C"},
748 {K_F10, "\316D"},
749 {K_F11, "\316\205"},
750 {K_F12, "\316\206"},
751 {K_S_F1, "\316T"},
752 {K_S_F2, "\316U"},
753 {K_S_F3, "\316V"},
754 {K_S_F4, "\316W"},
755 {K_S_F5, "\316X"},
756 {K_S_F6, "\316Y"},
757 {K_S_F7, "\316Z"},
758 {K_S_F8, "\316["},
759 {K_S_F9, "\316\\"},
760 {K_S_F10, "\316]"},
761 {K_S_F11, "\316\207"},
762 {K_S_F12, "\316\210"},
763 {K_INS, "\316R"},
764 {K_DEL, "\316S"},
765 {K_HOME, "\316G"},
766 {K_S_HOME, "\316\302"},
767 {K_C_HOME, "\316w"},
768 {K_END, "\316O"},
769 {K_S_END, "\316\315"},
770 {K_C_END, "\316u"},
771 {K_PAGEDOWN, "\316Q"},
772 {K_PAGEUP, "\316I"},
773 {K_KPLUS, "\316N"},
774 {K_KMINUS, "\316J"},
775 {K_KMULTIPLY, "\316\067"},
776 {K_K0, "\316\332"},
777 {K_K1, "\316\336"},
778 {K_K2, "\316\342"},
779 {K_K3, "\316\346"},
780 {K_K4, "\316\352"},
781 {K_K5, "\316\356"},
782 {K_K6, "\316\362"},
783 {K_K7, "\316\366"},
784 {K_K8, "\316\372"},
785 {K_K9, "\316\376"},
786# endif
787
788# if defined(VMS) || defined(ALL_BUILTIN_TCAPS)
789/*
790 * VT320 is working as an ANSI terminal compatible DEC terminal.
791 * (it covers VT1x0, VT2x0 and VT3x0 up to VT320 on VMS as well)
792 * Note: K_F1...K_F5 are for internal use, should not be defined.
793 * TODO:- rewrite ESC[ codes to CSI
794 * - keyboard languages (CSI ? 26 n)
795 */
796 {(int)KS_NAME, "vt320"},
797 {(int)KS_CE, IF_EB("\033[K", ESC_STR "[K")},
798 {(int)KS_AL, IF_EB("\033[L", ESC_STR "[L")},
799# ifdef TERMINFO
800 {(int)KS_CAL, IF_EB("\033[%p1%dL", ESC_STR "[%p1%dL")},
801# else
802 {(int)KS_CAL, IF_EB("\033[%dL", ESC_STR "[%dL")},
803# endif
804 {(int)KS_DL, IF_EB("\033[M", ESC_STR "[M")},
805# ifdef TERMINFO
806 {(int)KS_CDL, IF_EB("\033[%p1%dM", ESC_STR "[%p1%dM")},
807# else
808 {(int)KS_CDL, IF_EB("\033[%dM", ESC_STR "[%dM")},
809# endif
810 {(int)KS_CL, IF_EB("\033[H\033[2J", ESC_STR "[H" ESC_STR_nc "[2J")},
Bram Moolenaard4755bb2004-09-02 19:12:26 +0000811 {(int)KS_CD, IF_EB("\033[J", ESC_STR "[J")},
812 {(int)KS_CCO, "8"}, /* allow 8 colors */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000813 {(int)KS_ME, IF_EB("\033[0m", ESC_STR "[0m")},
814 {(int)KS_MR, IF_EB("\033[7m", ESC_STR "[7m")},
Bram Moolenaard4755bb2004-09-02 19:12:26 +0000815 {(int)KS_MD, IF_EB("\033[1m", ESC_STR "[1m")}, /* bold mode */
816 {(int)KS_SE, IF_EB("\033[22m", ESC_STR "[22m")},/* normal mode */
817 {(int)KS_UE, IF_EB("\033[24m", ESC_STR "[24m")},/* exit underscore mode */
818 {(int)KS_US, IF_EB("\033[4m", ESC_STR "[4m")}, /* underscore mode */
819 {(int)KS_CZH, IF_EB("\033[34;43m", ESC_STR "[34;43m" )}, /* italic mode: blue text on yellow */
820 {(int)KS_CZR, IF_EB("\033[0m", ESC_STR "[0m")}, /* italic mode end */
821 {(int)KS_CAB, IF_EB("\033[4%dm", ESC_STR "[4%dm" )}, /* set background color (ANSI) */
822 {(int)KS_CAF, IF_EB("\033[3%dm", ESC_STR "[3%dm" )}, /* set foreground color (ANSI) */
823 {(int)KS_CSB, IF_EB("\033[102;%dm", ESC_STR "[102;%dm" )}, /* set screen background color */
824 {(int)KS_CSF, IF_EB("\033[101;%dm", ESC_STR "[101;%dm" )}, /* set screen foreground color */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000825 {(int)KS_MS, "y"},
826 {(int)KS_UT, "y"},
827 {(int)KS_LE, "\b"},
828# ifdef TERMINFO
829 {(int)KS_CM, IF_EB("\033[%i%p1%d;%p2%dH",
830 ESC_STR "[%i%p1%d;%p2%dH")},
831# else
832 {(int)KS_CM, IF_EB("\033[%i%d;%dH", ESC_STR "[%i%d;%dH")},
833# endif
834# ifdef TERMINFO
835 {(int)KS_CRI, IF_EB("\033[%p1%dC", ESC_STR "[%p1%dC")},
836# else
837 {(int)KS_CRI, IF_EB("\033[%dC", ESC_STR "[%dC")},
838# endif
839 {K_UP, IF_EB("\033[A", ESC_STR "[A")},
840 {K_DOWN, IF_EB("\033[B", ESC_STR "[B")},
841 {K_RIGHT, IF_EB("\033[C", ESC_STR "[C")},
842 {K_LEFT, IF_EB("\033[D", ESC_STR "[D")},
843 {K_F6, IF_EB("\033[17~", ESC_STR "[17~")},
844 {K_F7, IF_EB("\033[18~", ESC_STR "[18~")},
845 {K_F8, IF_EB("\033[19~", ESC_STR "[19~")},
846 {K_F9, IF_EB("\033[20~", ESC_STR "[20~")},
847 {K_F10, IF_EB("\033[21~", ESC_STR "[21~")},
848/* {K_F11, IF_EB("\033[23~", ESC_STR "[23~")},
849 * (ESC) should not define, sometimes does not work */
850 {K_F12, IF_EB("\033[24~", ESC_STR "[24~")},
851 {K_F13, IF_EB("\033[25~", ESC_STR "[25~")},
852 {K_F14, IF_EB("\033[26~", ESC_STR "[26~")},
853 {K_F15, IF_EB("\033[28~", ESC_STR "[28~")}, /* Help */
854 {K_F16, IF_EB("\033[29~", ESC_STR "[29~")}, /* Select */
855 {K_F17, IF_EB("\033[31~", ESC_STR "[31~")},
856 {K_F18, IF_EB("\033[32~", ESC_STR "[32~")},
857 {K_F19, IF_EB("\033[33~", ESC_STR "[33~")},
858 {K_F20, IF_EB("\033[34~", ESC_STR "[34~")},
859 {K_INS, IF_EB("\033[2~", ESC_STR "[2~")},
860 {K_DEL, IF_EB("\033[3~", ESC_STR "[3~")},
861 {K_HOME, IF_EB("\033[1~", ESC_STR "[1~")},
862 {K_END, IF_EB("\033[4~", ESC_STR "[4~")},
863 {K_PAGEUP, IF_EB("\033[5~", ESC_STR "[5~")},
864 {K_PAGEDOWN, IF_EB("\033[6~", ESC_STR "[6~")},
865 {K_KPLUS, IF_EB("\033Ok", ESC_STR "Ok")}, /* keypad plus */
866 {K_KMINUS, IF_EB("\033Om", ESC_STR "Om")}, /* keypad minus */
867 {K_KDIVIDE, IF_EB("\033Oo", ESC_STR "Oo")}, /* keypad / */
868 {K_KMULTIPLY, IF_EB("\033Oj", ESC_STR "Oj")}, /* keypad * */
869 {K_KENTER, IF_EB("\033OM", ESC_STR "OM")}, /* keypad Enter */
870 {K_BS, "\x7f"}, /* for some reason 0177 doesn't work */
871# endif
872
873# if defined(ALL_BUILTIN_TCAPS) || defined(__MINT__)
874/*
875 * Ordinary vt52
876 */
877 {(int)KS_NAME, "vt52"},
878 {(int)KS_CE, IF_EB("\033K", ESC_STR "K")},
879 {(int)KS_CD, IF_EB("\033J", ESC_STR "J")},
880 {(int)KS_CM, IF_EB("\033Y%+ %+ ", ESC_STR "Y%+ %+ ")},
881 {(int)KS_LE, "\b"},
882# ifdef __MINT__
883 {(int)KS_AL, IF_EB("\033L", ESC_STR "L")},
884 {(int)KS_DL, IF_EB("\033M", ESC_STR "M")},
885 {(int)KS_CL, IF_EB("\033E", ESC_STR "E")},
886 {(int)KS_SR, IF_EB("\033I", ESC_STR "I")},
887 {(int)KS_VE, IF_EB("\033e", ESC_STR "e")},
888 {(int)KS_VI, IF_EB("\033f", ESC_STR "f")},
889 {(int)KS_SO, IF_EB("\033p", ESC_STR "p")},
890 {(int)KS_SE, IF_EB("\033q", ESC_STR "q")},
891 {K_UP, IF_EB("\033A", ESC_STR "A")},
892 {K_DOWN, IF_EB("\033B", ESC_STR "B")},
893 {K_LEFT, IF_EB("\033D", ESC_STR "D")},
894 {K_RIGHT, IF_EB("\033C", ESC_STR "C")},
895 {K_S_UP, IF_EB("\033a", ESC_STR "a")},
896 {K_S_DOWN, IF_EB("\033b", ESC_STR "b")},
897 {K_S_LEFT, IF_EB("\033d", ESC_STR "d")},
898 {K_S_RIGHT, IF_EB("\033c", ESC_STR "c")},
899 {K_F1, IF_EB("\033P", ESC_STR "P")},
900 {K_F2, IF_EB("\033Q", ESC_STR "Q")},
901 {K_F3, IF_EB("\033R", ESC_STR "R")},
902 {K_F4, IF_EB("\033S", ESC_STR "S")},
903 {K_F5, IF_EB("\033T", ESC_STR "T")},
904 {K_F6, IF_EB("\033U", ESC_STR "U")},
905 {K_F7, IF_EB("\033V", ESC_STR "V")},
906 {K_F8, IF_EB("\033W", ESC_STR "W")},
907 {K_F9, IF_EB("\033X", ESC_STR "X")},
908 {K_F10, IF_EB("\033Y", ESC_STR "Y")},
909 {K_S_F1, IF_EB("\033p", ESC_STR "p")},
910 {K_S_F2, IF_EB("\033q", ESC_STR "q")},
911 {K_S_F3, IF_EB("\033r", ESC_STR "r")},
912 {K_S_F4, IF_EB("\033s", ESC_STR "s")},
913 {K_S_F5, IF_EB("\033t", ESC_STR "t")},
914 {K_S_F6, IF_EB("\033u", ESC_STR "u")},
915 {K_S_F7, IF_EB("\033v", ESC_STR "v")},
916 {K_S_F8, IF_EB("\033w", ESC_STR "w")},
917 {K_S_F9, IF_EB("\033x", ESC_STR "x")},
918 {K_S_F10, IF_EB("\033y", ESC_STR "y")},
919 {K_INS, IF_EB("\033I", ESC_STR "I")},
920 {K_HOME, IF_EB("\033E", ESC_STR "E")},
921 {K_PAGEDOWN, IF_EB("\033b", ESC_STR "b")},
922 {K_PAGEUP, IF_EB("\033a", ESC_STR "a")},
923# else
924 {(int)KS_AL, IF_EB("\033T", ESC_STR "T")},
925 {(int)KS_DL, IF_EB("\033U", ESC_STR "U")},
926 {(int)KS_CL, IF_EB("\033H\033J", ESC_STR "H" ESC_STR_nc "J")},
927 {(int)KS_ME, IF_EB("\033SO", ESC_STR "SO")},
928 {(int)KS_MR, IF_EB("\033S2", ESC_STR "S2")},
929 {(int)KS_MS, "y"},
930# endif
931# endif
932
933# if defined(UNIX) || defined(ALL_BUILTIN_TCAPS) || defined(SOME_BUILTIN_TCAPS) || defined(__EMX__)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000934 {(int)KS_NAME, "xterm"},
935 {(int)KS_CE, IF_EB("\033[K", ESC_STR "[K")},
936 {(int)KS_AL, IF_EB("\033[L", ESC_STR "[L")},
937# ifdef TERMINFO
938 {(int)KS_CAL, IF_EB("\033[%p1%dL", ESC_STR "[%p1%dL")},
939# else
940 {(int)KS_CAL, IF_EB("\033[%dL", ESC_STR "[%dL")},
941# endif
942 {(int)KS_DL, IF_EB("\033[M", ESC_STR "[M")},
943# ifdef TERMINFO
944 {(int)KS_CDL, IF_EB("\033[%p1%dM", ESC_STR "[%p1%dM")},
945# else
946 {(int)KS_CDL, IF_EB("\033[%dM", ESC_STR "[%dM")},
947# endif
948# ifdef TERMINFO
949 {(int)KS_CS, IF_EB("\033[%i%p1%d;%p2%dr",
950 ESC_STR "[%i%p1%d;%p2%dr")},
951# else
952 {(int)KS_CS, IF_EB("\033[%i%d;%dr", ESC_STR "[%i%d;%dr")},
953# endif
954 {(int)KS_CL, IF_EB("\033[H\033[2J", ESC_STR "[H" ESC_STR_nc "[2J")},
955 {(int)KS_CD, IF_EB("\033[J", ESC_STR "[J")},
956 {(int)KS_ME, IF_EB("\033[m", ESC_STR "[m")},
957 {(int)KS_MR, IF_EB("\033[7m", ESC_STR "[7m")},
958 {(int)KS_MD, IF_EB("\033[1m", ESC_STR "[1m")},
959 {(int)KS_UE, IF_EB("\033[m", ESC_STR "[m")},
960 {(int)KS_US, IF_EB("\033[4m", ESC_STR "[4m")},
961 {(int)KS_MS, "y"},
962 {(int)KS_UT, "y"},
963 {(int)KS_LE, "\b"},
964# ifdef TERMINFO
965 {(int)KS_CM, IF_EB("\033[%i%p1%d;%p2%dH",
966 ESC_STR "[%i%p1%d;%p2%dH")},
967# else
968 {(int)KS_CM, IF_EB("\033[%i%d;%dH", ESC_STR "[%i%d;%dH")},
969# endif
970 {(int)KS_SR, IF_EB("\033M", ESC_STR "M")},
971# ifdef TERMINFO
972 {(int)KS_CRI, IF_EB("\033[%p1%dC", ESC_STR "[%p1%dC")},
973# else
974 {(int)KS_CRI, IF_EB("\033[%dC", ESC_STR "[%dC")},
975# endif
976 {(int)KS_KS, IF_EB("\033[?1h\033=", ESC_STR "[?1h" ESC_STR_nc "=")},
977 {(int)KS_KE, IF_EB("\033[?1l\033>", ESC_STR "[?1l" ESC_STR_nc ">")},
978# ifdef FEAT_XTERM_SAVE
979 {(int)KS_TI, IF_EB("\0337\033[?47h", ESC_STR "7" ESC_STR_nc "[?47h")},
980 {(int)KS_TE, IF_EB("\033[2J\033[?47l\0338",
981 ESC_STR "[2J" ESC_STR_nc "[?47l" ESC_STR_nc "8")},
982# endif
983 {(int)KS_CIS, IF_EB("\033]1;", ESC_STR "]1;")},
984 {(int)KS_CIE, "\007"},
985 {(int)KS_TS, IF_EB("\033]2;", ESC_STR "]2;")},
986 {(int)KS_FS, "\007"},
987# ifdef TERMINFO
988 {(int)KS_CWS, IF_EB("\033[8;%p1%d;%p2%dt",
989 ESC_STR "[8;%p1%d;%p2%dt")},
990 {(int)KS_CWP, IF_EB("\033[3;%p1%d;%p2%dt",
991 ESC_STR "[3;%p1%d;%p2%dt")},
992# else
993 {(int)KS_CWS, IF_EB("\033[8;%d;%dt", ESC_STR "[8;%d;%dt")},
994 {(int)KS_CWP, IF_EB("\033[3;%d;%dt", ESC_STR "[3;%d;%dt")},
995# endif
996 {(int)KS_CRV, IF_EB("\033[>c", ESC_STR "[>c")},
997 {K_UP, IF_EB("\033OA", ESC_STR "OA")},
998 {K_DOWN, IF_EB("\033OB", ESC_STR "OB")},
999 {K_RIGHT, IF_EB("\033OC", ESC_STR "OC")},
1000 {K_LEFT, IF_EB("\033OD", ESC_STR "OD")},
1001 {K_S_UP, IF_EB("\033O2A", ESC_STR "O2A")},
1002 {K_S_DOWN, IF_EB("\033O2B", ESC_STR "O2B")},
1003 {K_S_RIGHT, IF_EB("\033O2C", ESC_STR "O2C")},
1004 {K_C_RIGHT, IF_EB("\033O5C", ESC_STR "O5C")},
1005 {K_S_LEFT, IF_EB("\033O2D", ESC_STR "O2D")},
1006 {K_C_LEFT, IF_EB("\033O5D", ESC_STR "O5D")},
1007 /* An extra set of function keys for vt100 mode */
1008 {K_XF1, IF_EB("\033OP", ESC_STR "OP")},
1009 {K_XF2, IF_EB("\033OQ", ESC_STR "OQ")},
1010 {K_XF3, IF_EB("\033OR", ESC_STR "OR")},
1011 {K_XF4, IF_EB("\033OS", ESC_STR "OS")},
Bram Moolenaar19a09a12005-03-04 23:39:37 +00001012 {K_F1, IF_EB("\033[11;*~", ESC_STR "[11;*~")},
1013 {K_F2, IF_EB("\033[12;*~", ESC_STR "[12;*~")},
1014 {K_F3, IF_EB("\033[13;*~", ESC_STR "[13;*~")},
1015 {K_F4, IF_EB("\033[14;*~", ESC_STR "[14;*~")},
1016 {K_F5, IF_EB("\033[15;*~", ESC_STR "[15;*~")},
1017 {K_F6, IF_EB("\033[17;*~", ESC_STR "[17;*~")},
1018 {K_F7, IF_EB("\033[18;*~", ESC_STR "[18;*~")},
1019 {K_F8, IF_EB("\033[19;*~", ESC_STR "[19;*~")},
1020 {K_F9, IF_EB("\033[20;*~", ESC_STR "[20;*~")},
1021 {K_F10, IF_EB("\033[21;*~", ESC_STR "[21;*~")},
1022 {K_F11, IF_EB("\033[23;*~", ESC_STR "[23;*~")},
1023 {K_F12, IF_EB("\033[24;*~", ESC_STR "[24;*~")},
Bram Moolenaar071d4272004-06-13 20:20:40 +00001024 {K_S_XF1, IF_EB("\033O2P", ESC_STR "O2P")},
1025 {K_S_XF2, IF_EB("\033O2Q", ESC_STR "O2Q")},
1026 {K_S_XF3, IF_EB("\033O2R", ESC_STR "O2R")},
1027 {K_S_XF4, IF_EB("\033O2S", ESC_STR "O2S")},
Bram Moolenaar071d4272004-06-13 20:20:40 +00001028 {K_S_TAB, IF_EB("\033[Z", ESC_STR "[Z")},
Bram Moolenaar19a09a12005-03-04 23:39:37 +00001029 {K_HELP, IF_EB("\033[28;*~", ESC_STR "[28;*~")},
1030 {K_UNDO, IF_EB("\033[26;*~", ESC_STR "[26;*~")},
1031 {K_INS, IF_EB("\033[2;*~", ESC_STR "[2;*~")},
1032 {K_HOME, IF_EB("\033[1;*H", ESC_STR "[1;*H")},
Bram Moolenaar071d4272004-06-13 20:20:40 +00001033 {K_S_HOME, IF_EB("\033O2H", ESC_STR "O2H")},
1034 {K_C_HOME, IF_EB("\033O5H", ESC_STR "O5H")},
Bram Moolenaar19a09a12005-03-04 23:39:37 +00001035 {K_KHOME, IF_EB("\033[7;*~", ESC_STR "[7;*~")},
Bram Moolenaar071d4272004-06-13 20:20:40 +00001036 {K_XHOME, IF_EB("\033OH", ESC_STR "OH")}, /* alternate Home */
Bram Moolenaar19a09a12005-03-04 23:39:37 +00001037 {K_END, IF_EB("\033[1;*F", ESC_STR "[1;*F")},
Bram Moolenaar071d4272004-06-13 20:20:40 +00001038 {K_S_END, IF_EB("\033O2F", ESC_STR "O2F")},
1039 {K_C_END, IF_EB("\033O5F", ESC_STR "O5F")},
Bram Moolenaar19a09a12005-03-04 23:39:37 +00001040 {K_KEND, IF_EB("\033[4;*~", ESC_STR "[4;*~")},
Bram Moolenaar071d4272004-06-13 20:20:40 +00001041 {K_XEND, IF_EB("\033OF", ESC_STR "OF")}, /* alternate End */
Bram Moolenaar19a09a12005-03-04 23:39:37 +00001042 {K_PAGEUP, IF_EB("\033[5;*~", ESC_STR "[5;*~")},
1043 {K_PAGEDOWN, IF_EB("\033[6;*~", ESC_STR "[6;*~")},
Bram Moolenaar071d4272004-06-13 20:20:40 +00001044 {K_KPLUS, IF_EB("\033Ok", ESC_STR "Ok")}, /* keypad plus */
1045 {K_KMINUS, IF_EB("\033Om", ESC_STR "Om")}, /* keypad minus */
1046 {K_KDIVIDE, IF_EB("\033Oo", ESC_STR "Oo")}, /* keypad / */
1047 {K_KMULTIPLY, IF_EB("\033Oj", ESC_STR "Oj")}, /* keypad * */
1048 {K_KENTER, IF_EB("\033OM", ESC_STR "OM")}, /* keypad Enter */
Bram Moolenaar19a09a12005-03-04 23:39:37 +00001049 {K_KPOINT, IF_EB("\033On", ESC_STR "On")}, /* keypad . */
1050 {K_KDEL, IF_EB("\033[3;*~", ESC_STR "[3;*~")}, /* keypad Del */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001051
1052 {BT_EXTRA_KEYS, ""},
Bram Moolenaar19a09a12005-03-04 23:39:37 +00001053 {TERMCAP2KEY('k', '0'), IF_EB("\033[10;*~", ESC_STR "[10;*~")}, /* F0 */
1054 {TERMCAP2KEY('F', '3'), IF_EB("\033[25;*~", ESC_STR "[25;*~")}, /* F13 */
1055 /* F14 and F15 are missing, because they send the same codes as the undo
1056 * and help key, although they don't work on all keyboards. */
1057 {TERMCAP2KEY('F', '6'), IF_EB("\033[29;*~", ESC_STR "[29;*~")}, /* F16 */
1058 {TERMCAP2KEY('F', '7'), IF_EB("\033[31;*~", ESC_STR "[31;*~")}, /* F17 */
1059 {TERMCAP2KEY('F', '8'), IF_EB("\033[32;*~", ESC_STR "[32;*~")}, /* F18 */
1060 {TERMCAP2KEY('F', '9'), IF_EB("\033[33;*~", ESC_STR "[33;*~")}, /* F19 */
1061 {TERMCAP2KEY('F', 'A'), IF_EB("\033[34;*~", ESC_STR "[34;*~")}, /* F20 */
1062
1063 {TERMCAP2KEY('F', 'B'), IF_EB("\033[42;*~", ESC_STR "[42;*~")}, /* F21 */
1064 {TERMCAP2KEY('F', 'C'), IF_EB("\033[43;*~", ESC_STR "[43;*~")}, /* F22 */
1065 {TERMCAP2KEY('F', 'D'), IF_EB("\033[44;*~", ESC_STR "[44;*~")}, /* F23 */
1066 {TERMCAP2KEY('F', 'E'), IF_EB("\033[45;*~", ESC_STR "[45;*~")}, /* F24 */
1067 {TERMCAP2KEY('F', 'F'), IF_EB("\033[46;*~", ESC_STR "[46;*~")}, /* F25 */
1068 {TERMCAP2KEY('F', 'G'), IF_EB("\033[47;*~", ESC_STR "[47;*~")}, /* F26 */
1069 {TERMCAP2KEY('F', 'H'), IF_EB("\033[48;*~", ESC_STR "[48;*~")}, /* F27 */
1070 {TERMCAP2KEY('F', 'I'), IF_EB("\033[49;*~", ESC_STR "[49;*~")}, /* F28 */
1071 {TERMCAP2KEY('F', 'J'), IF_EB("\033[50;*~", ESC_STR "[50;*~")}, /* F29 */
1072 {TERMCAP2KEY('F', 'K'), IF_EB("\033[51;*~", ESC_STR "[51;*~")}, /* F30 */
1073
1074 {TERMCAP2KEY('F', 'L'), IF_EB("\033[52;*~", ESC_STR "[52;*~")}, /* F31 */
1075 {TERMCAP2KEY('F', 'M'), IF_EB("\033[53;*~", ESC_STR "[53;*~")}, /* F32 */
1076 {TERMCAP2KEY('F', 'N'), IF_EB("\033[54;*~", ESC_STR "[54;*~")}, /* F33 */
1077 {TERMCAP2KEY('F', 'O'), IF_EB("\033[55;*~", ESC_STR "[55;*~")}, /* F34 */
1078 {TERMCAP2KEY('F', 'P'), IF_EB("\033[56;*~", ESC_STR "[56;*~")}, /* F35 */
1079 {TERMCAP2KEY('F', 'Q'), IF_EB("\033[57;*~", ESC_STR "[57;*~")}, /* F36 */
1080 {TERMCAP2KEY('F', 'R'), IF_EB("\033[58;*~", ESC_STR "[58;*~")}, /* F37 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001081# endif
1082
1083# if defined(UNIX) || defined(ALL_BUILTIN_TCAPS)
1084/*
1085 * iris-ansi for Silicon Graphics machines.
1086 */
1087 {(int)KS_NAME, "iris-ansi"},
1088 {(int)KS_CE, "\033[K"},
1089 {(int)KS_CD, "\033[J"},
1090 {(int)KS_AL, "\033[L"},
1091# ifdef TERMINFO
1092 {(int)KS_CAL, "\033[%p1%dL"},
1093# else
1094 {(int)KS_CAL, "\033[%dL"},
1095# endif
1096 {(int)KS_DL, "\033[M"},
1097# ifdef TERMINFO
1098 {(int)KS_CDL, "\033[%p1%dM"},
1099# else
1100 {(int)KS_CDL, "\033[%dM"},
1101# endif
1102#if 0 /* The scroll region is not working as Vim expects. */
1103# ifdef TERMINFO
1104 {(int)KS_CS, "\033[%i%p1%d;%p2%dr"},
1105# else
1106 {(int)KS_CS, "\033[%i%d;%dr"},
1107# endif
1108#endif
1109 {(int)KS_CL, "\033[H\033[2J"},
1110 {(int)KS_VE, "\033[9/y\033[12/y"}, /* These aren't documented */
1111 {(int)KS_VS, "\033[10/y\033[=1h\033[=2l"}, /* These aren't documented */
1112 {(int)KS_TI, "\033[=6h"},
1113 {(int)KS_TE, "\033[=6l"},
1114 {(int)KS_SE, "\033[21;27m"},
1115 {(int)KS_SO, "\033[1;7m"},
1116 {(int)KS_ME, "\033[m"},
1117 {(int)KS_MR, "\033[7m"},
1118 {(int)KS_MD, "\033[1m"},
1119 {(int)KS_CCO, "8"}, /* allow 8 colors */
1120 {(int)KS_CZH, "\033[3m"}, /* italic mode on */
1121 {(int)KS_CZR, "\033[23m"}, /* italic mode off */
1122 {(int)KS_US, "\033[4m"}, /* underline on */
1123 {(int)KS_UE, "\033[24m"}, /* underline off */
1124# ifdef TERMINFO
1125 {(int)KS_CAB, "\033[4%p1%dm"}, /* set background color (ANSI) */
1126 {(int)KS_CAF, "\033[3%p1%dm"}, /* set foreground color (ANSI) */
1127 {(int)KS_CSB, "\033[102;%p1%dm"}, /* set screen background color */
1128 {(int)KS_CSF, "\033[101;%p1%dm"}, /* set screen foreground color */
1129# else
1130 {(int)KS_CAB, "\033[4%dm"}, /* set background color (ANSI) */
1131 {(int)KS_CAF, "\033[3%dm"}, /* set foreground color (ANSI) */
1132 {(int)KS_CSB, "\033[102;%dm"}, /* set screen background color */
1133 {(int)KS_CSF, "\033[101;%dm"}, /* set screen foreground color */
1134# endif
1135 {(int)KS_MS, "y"}, /* guessed */
1136 {(int)KS_UT, "y"}, /* guessed */
1137 {(int)KS_LE, "\b"},
1138# ifdef TERMINFO
1139 {(int)KS_CM, "\033[%i%p1%d;%p2%dH"},
1140# else
1141 {(int)KS_CM, "\033[%i%d;%dH"},
1142# endif
1143 {(int)KS_SR, "\033M"},
1144# ifdef TERMINFO
1145 {(int)KS_CRI, "\033[%p1%dC"},
1146# else
1147 {(int)KS_CRI, "\033[%dC"},
1148# endif
1149 {(int)KS_CIS, "\033P3.y"},
1150 {(int)KS_CIE, "\234"}, /* ST "String Terminator" */
1151 {(int)KS_TS, "\033P1.y"},
1152 {(int)KS_FS, "\234"}, /* ST "String Terminator" */
1153# ifdef TERMINFO
1154 {(int)KS_CWS, "\033[203;%p1%d;%p2%d/y"},
1155 {(int)KS_CWP, "\033[205;%p1%d;%p2%d/y"},
1156# else
1157 {(int)KS_CWS, "\033[203;%d;%d/y"},
1158 {(int)KS_CWP, "\033[205;%d;%d/y"},
1159# endif
1160 {K_UP, "\033[A"},
1161 {K_DOWN, "\033[B"},
1162 {K_LEFT, "\033[D"},
1163 {K_RIGHT, "\033[C"},
1164 {K_S_UP, "\033[161q"},
1165 {K_S_DOWN, "\033[164q"},
1166 {K_S_LEFT, "\033[158q"},
1167 {K_S_RIGHT, "\033[167q"},
1168 {K_F1, "\033[001q"},
1169 {K_F2, "\033[002q"},
1170 {K_F3, "\033[003q"},
1171 {K_F4, "\033[004q"},
1172 {K_F5, "\033[005q"},
1173 {K_F6, "\033[006q"},
1174 {K_F7, "\033[007q"},
1175 {K_F8, "\033[008q"},
1176 {K_F9, "\033[009q"},
1177 {K_F10, "\033[010q"},
1178 {K_F11, "\033[011q"},
1179 {K_F12, "\033[012q"},
1180 {K_S_F1, "\033[013q"},
1181 {K_S_F2, "\033[014q"},
1182 {K_S_F3, "\033[015q"},
1183 {K_S_F4, "\033[016q"},
1184 {K_S_F5, "\033[017q"},
1185 {K_S_F6, "\033[018q"},
1186 {K_S_F7, "\033[019q"},
1187 {K_S_F8, "\033[020q"},
1188 {K_S_F9, "\033[021q"},
1189 {K_S_F10, "\033[022q"},
1190 {K_S_F11, "\033[023q"},
1191 {K_S_F12, "\033[024q"},
1192 {K_INS, "\033[139q"},
1193 {K_HOME, "\033[H"},
1194 {K_END, "\033[146q"},
1195 {K_PAGEUP, "\033[150q"},
1196 {K_PAGEDOWN, "\033[154q"},
1197# endif
1198
1199# if defined(DEBUG) || defined(ALL_BUILTIN_TCAPS)
1200/*
1201 * for debugging
1202 */
1203 {(int)KS_NAME, "debug"},
1204 {(int)KS_CE, "[CE]"},
1205 {(int)KS_CD, "[CD]"},
1206 {(int)KS_AL, "[AL]"},
1207# ifdef TERMINFO
1208 {(int)KS_CAL, "[CAL%p1%d]"},
1209# else
1210 {(int)KS_CAL, "[CAL%d]"},
1211# endif
1212 {(int)KS_DL, "[DL]"},
1213# ifdef TERMINFO
1214 {(int)KS_CDL, "[CDL%p1%d]"},
1215# else
1216 {(int)KS_CDL, "[CDL%d]"},
1217# endif
1218# ifdef TERMINFO
1219 {(int)KS_CS, "[%p1%dCS%p2%d]"},
1220# else
1221 {(int)KS_CS, "[%dCS%d]"},
1222# endif
1223# ifdef FEAT_VERTSPLIT
1224# ifdef TERMINFO
1225 {(int)KS_CSV, "[%p1%dCSV%p2%d]"},
1226# else
1227 {(int)KS_CSV, "[%dCSV%d]"},
1228# endif
1229# endif
1230# ifdef TERMINFO
1231 {(int)KS_CAB, "[CAB%p1%d]"},
1232 {(int)KS_CAF, "[CAF%p1%d]"},
1233 {(int)KS_CSB, "[CSB%p1%d]"},
1234 {(int)KS_CSF, "[CSF%p1%d]"},
1235# else
1236 {(int)KS_CAB, "[CAB%d]"},
1237 {(int)KS_CAF, "[CAF%d]"},
1238 {(int)KS_CSB, "[CSB%d]"},
1239 {(int)KS_CSF, "[CSF%d]"},
1240# endif
1241 {(int)KS_OP, "[OP]"},
1242 {(int)KS_LE, "[LE]"},
1243 {(int)KS_CL, "[CL]"},
1244 {(int)KS_VI, "[VI]"},
1245 {(int)KS_VE, "[VE]"},
1246 {(int)KS_VS, "[VS]"},
1247 {(int)KS_ME, "[ME]"},
1248 {(int)KS_MR, "[MR]"},
1249 {(int)KS_MB, "[MB]"},
1250 {(int)KS_MD, "[MD]"},
1251 {(int)KS_SE, "[SE]"},
1252 {(int)KS_SO, "[SO]"},
1253 {(int)KS_UE, "[UE]"},
1254 {(int)KS_US, "[US]"},
1255 {(int)KS_MS, "[MS]"},
1256 {(int)KS_UT, "[UT]"},
1257# ifdef TERMINFO
1258 {(int)KS_CM, "[%p1%dCM%p2%d]"},
1259# else
1260 {(int)KS_CM, "[%dCM%d]"},
1261# endif
1262 {(int)KS_SR, "[SR]"},
1263# ifdef TERMINFO
1264 {(int)KS_CRI, "[CRI%p1%d]"},
1265# else
1266 {(int)KS_CRI, "[CRI%d]"},
1267# endif
1268 {(int)KS_VB, "[VB]"},
1269 {(int)KS_KS, "[KS]"},
1270 {(int)KS_KE, "[KE]"},
1271 {(int)KS_TI, "[TI]"},
1272 {(int)KS_TE, "[TE]"},
1273 {(int)KS_CIS, "[CIS]"},
1274 {(int)KS_CIE, "[CIE]"},
1275 {(int)KS_TS, "[TS]"},
1276 {(int)KS_FS, "[FS]"},
1277# ifdef TERMINFO
1278 {(int)KS_CWS, "[%p1%dCWS%p2%d]"},
1279 {(int)KS_CWP, "[%p1%dCWP%p2%d]"},
1280# else
1281 {(int)KS_CWS, "[%dCWS%d]"},
1282 {(int)KS_CWP, "[%dCWP%d]"},
1283# endif
1284 {(int)KS_CRV, "[CRV]"},
1285 {K_UP, "[KU]"},
1286 {K_DOWN, "[KD]"},
1287 {K_LEFT, "[KL]"},
1288 {K_RIGHT, "[KR]"},
1289 {K_S_UP, "[S-KU]"},
1290 {K_S_DOWN, "[S-KD]"},
1291 {K_S_LEFT, "[S-KL]"},
1292 {K_C_LEFT, "[C-KL]"},
1293 {K_S_RIGHT, "[S-KR]"},
1294 {K_C_RIGHT, "[C-KR]"},
1295 {K_F1, "[F1]"},
1296 {K_XF1, "[xF1]"},
1297 {K_F2, "[F2]"},
1298 {K_XF2, "[xF2]"},
1299 {K_F3, "[F3]"},
1300 {K_XF3, "[xF3]"},
1301 {K_F4, "[F4]"},
1302 {K_XF4, "[xF4]"},
1303 {K_F5, "[F5]"},
1304 {K_F6, "[F6]"},
1305 {K_F7, "[F7]"},
1306 {K_F8, "[F8]"},
1307 {K_F9, "[F9]"},
1308 {K_F10, "[F10]"},
1309 {K_F11, "[F11]"},
1310 {K_F12, "[F12]"},
1311 {K_S_F1, "[S-F1]"},
1312 {K_S_XF1, "[S-xF1]"},
1313 {K_S_F2, "[S-F2]"},
1314 {K_S_XF2, "[S-xF2]"},
1315 {K_S_F3, "[S-F3]"},
1316 {K_S_XF3, "[S-xF3]"},
1317 {K_S_F4, "[S-F4]"},
1318 {K_S_XF4, "[S-xF4]"},
1319 {K_S_F5, "[S-F5]"},
1320 {K_S_F6, "[S-F6]"},
1321 {K_S_F7, "[S-F7]"},
1322 {K_S_F8, "[S-F8]"},
1323 {K_S_F9, "[S-F9]"},
1324 {K_S_F10, "[S-F10]"},
1325 {K_S_F11, "[S-F11]"},
1326 {K_S_F12, "[S-F12]"},
1327 {K_HELP, "[HELP]"},
1328 {K_UNDO, "[UNDO]"},
1329 {K_BS, "[BS]"},
1330 {K_INS, "[INS]"},
1331 {K_KINS, "[KINS]"},
1332 {K_DEL, "[DEL]"},
1333 {K_KDEL, "[KDEL]"},
1334 {K_HOME, "[HOME]"},
1335 {K_S_HOME, "[C-HOME]"},
1336 {K_C_HOME, "[C-HOME]"},
1337 {K_KHOME, "[KHOME]"},
1338 {K_XHOME, "[XHOME]"},
1339 {K_END, "[END]"},
1340 {K_S_END, "[C-END]"},
1341 {K_C_END, "[C-END]"},
1342 {K_KEND, "[KEND]"},
1343 {K_XEND, "[XEND]"},
1344 {K_PAGEUP, "[PAGEUP]"},
1345 {K_PAGEDOWN, "[PAGEDOWN]"},
1346 {K_KPAGEUP, "[KPAGEUP]"},
1347 {K_KPAGEDOWN, "[KPAGEDOWN]"},
1348 {K_MOUSE, "[MOUSE]"},
1349 {K_KPLUS, "[KPLUS]"},
1350 {K_KMINUS, "[KMINUS]"},
1351 {K_KDIVIDE, "[KDIVIDE]"},
1352 {K_KMULTIPLY, "[KMULTIPLY]"},
1353 {K_KENTER, "[KENTER]"},
1354 {K_KPOINT, "[KPOINT]"},
1355 {K_K0, "[K0]"},
1356 {K_K1, "[K1]"},
1357 {K_K2, "[K2]"},
1358 {K_K3, "[K3]"},
1359 {K_K4, "[K4]"},
1360 {K_K5, "[K5]"},
1361 {K_K6, "[K6]"},
1362 {K_K7, "[K7]"},
1363 {K_K8, "[K8]"},
1364 {K_K9, "[K9]"},
1365# endif
1366
1367#endif /* NO_BUILTIN_TCAPS */
1368
1369/*
1370 * The most minimal terminal: only clear screen and cursor positioning
1371 * Always included.
1372 */
1373 {(int)KS_NAME, "dumb"},
1374 {(int)KS_CL, "\014"},
1375#ifdef TERMINFO
1376 {(int)KS_CM, IF_EB("\033[%i%p1%d;%p2%dH",
1377 ESC_STR "[%i%p1%d;%p2%dH")},
1378#else
1379 {(int)KS_CM, IF_EB("\033[%i%d;%dH", ESC_STR "[%i%d;%dH")},
1380#endif
1381
1382/*
1383 * end marker
1384 */
1385 {(int)KS_NAME, NULL}
1386
1387}; /* end of builtin_termcaps */
1388
1389/*
1390 * DEFAULT_TERM is used, when no terminal is specified with -T option or $TERM.
1391 */
1392#ifdef RISCOS
1393# define DEFAULT_TERM (char_u *)"riscos"
1394#endif
1395
1396#ifdef AMIGA
1397# define DEFAULT_TERM (char_u *)"amiga"
1398#endif
1399
1400#ifdef MSWIN
1401# define DEFAULT_TERM (char_u *)"win32"
1402#endif
1403
1404#ifdef MSDOS
1405# define DEFAULT_TERM (char_u *)"pcterm"
1406#endif
1407
1408#if defined(UNIX) && !defined(__MINT__)
1409# define DEFAULT_TERM (char_u *)"ansi"
1410#endif
1411
1412#ifdef __MINT__
1413# define DEFAULT_TERM (char_u *)"vt52"
1414#endif
1415
1416#ifdef __EMX__
1417# define DEFAULT_TERM (char_u *)"os2ansi"
1418#endif
1419
1420#ifdef VMS
1421# define DEFAULT_TERM (char_u *)"vt320"
1422#endif
1423
1424#ifdef __BEOS__
1425# undef DEFAULT_TERM
1426# define DEFAULT_TERM (char_u *)"beos-ansi"
1427#endif
1428
1429#ifndef DEFAULT_TERM
1430# define DEFAULT_TERM (char_u *)"dumb"
1431#endif
1432
1433/*
1434 * Term_strings contains currently used terminal output strings.
1435 * It is initialized with the default values by parse_builtin_tcap().
1436 * The values can be changed by setting the option with the same name.
1437 */
1438char_u *(term_strings[(int)KS_LAST + 1]);
1439
1440static int need_gather = FALSE; /* need to fill termleader[] */
1441static char_u termleader[256 + 1]; /* for check_termcode() */
1442#ifdef FEAT_TERMRESPONSE
1443static int check_for_codes = FALSE; /* check for key code reponse */
1444#endif
1445
1446 static struct builtin_term *
1447find_builtin_term(term)
1448 char_u *term;
1449{
1450 struct builtin_term *p;
1451
1452 p = builtin_termcaps;
1453 while (p->bt_string != NULL)
1454 {
1455 if (p->bt_entry == (int)KS_NAME)
1456 {
1457#ifdef UNIX
1458 if (STRCMP(p->bt_string, "iris-ansi") == 0 && vim_is_iris(term))
1459 return p;
1460 else if (STRCMP(p->bt_string, "xterm") == 0 && vim_is_xterm(term))
1461 return p;
1462 else
1463#endif
1464#ifdef VMS
1465 if (STRCMP(p->bt_string, "vt320") == 0 && vim_is_vt300(term))
1466 return p;
1467 else
1468#endif
1469 if (STRCMP(term, p->bt_string) == 0)
1470 return p;
1471 }
1472 ++p;
1473 }
1474 return p;
1475}
1476
1477/*
1478 * Parsing of the builtin termcap entries.
1479 * Caller should check if 'name' is a valid builtin term.
1480 * The terminal's name is not set, as this is already done in termcapinit().
1481 */
1482 static void
1483parse_builtin_tcap(term)
1484 char_u *term;
1485{
1486 struct builtin_term *p;
1487 char_u name[2];
1488 int term_8bit;
1489
1490 p = find_builtin_term(term);
1491 term_8bit = term_is_8bit(term);
1492
1493 /* Do not parse if builtin term not found */
1494 if (p->bt_string == NULL)
1495 return;
1496
1497 for (++p; p->bt_entry != (int)KS_NAME && p->bt_entry != BT_EXTRA_KEYS; ++p)
1498 {
1499 if ((int)p->bt_entry >= 0) /* KS_xx entry */
1500 {
1501 /* Only set the value if it wasn't set yet. */
1502 if (term_strings[p->bt_entry] == NULL
1503 || term_strings[p->bt_entry] == empty_option)
1504 {
1505 /* 8bit terminal: use CSI instead of <Esc>[ */
1506 if (term_8bit && term_7to8bit((char_u *)p->bt_string) != 0)
1507 {
1508 char_u *s, *t;
1509
1510 s = vim_strsave((char_u *)p->bt_string);
1511 if (s != NULL)
1512 {
1513 for (t = s; *t; ++t)
1514 if (term_7to8bit(t))
1515 {
1516 *t = term_7to8bit(t);
1517 STRCPY(t + 1, t + 2);
1518 }
1519 term_strings[p->bt_entry] = s;
1520 set_term_option_alloced(&term_strings[p->bt_entry]);
1521 }
1522 }
1523 else
1524 term_strings[p->bt_entry] = (char_u *)p->bt_string;
1525 }
1526 }
1527 else
1528 {
1529 name[0] = KEY2TERMCAP0((int)p->bt_entry);
1530 name[1] = KEY2TERMCAP1((int)p->bt_entry);
1531 if (find_termcode(name) == NULL)
1532 add_termcode(name, (char_u *)p->bt_string, term_8bit);
1533 }
1534 }
1535}
1536#if defined(HAVE_TGETENT) || defined(FEAT_TERMRESPONSE)
1537static void set_color_count __ARGS((int nr));
1538
1539/*
1540 * Set number of colors.
1541 * Store it as a number in t_colors.
1542 * Store it as a string in T_CCO (using nr_colors[]).
1543 */
1544 static void
1545set_color_count(nr)
1546 int nr;
1547{
1548 char_u nr_colors[20]; /* string for number of colors */
1549
1550 t_colors = nr;
1551 if (t_colors > 1)
1552 sprintf((char *)nr_colors, "%d", t_colors);
1553 else
1554 *nr_colors = NUL;
1555 set_string_option_direct((char_u *)"t_Co", -1, nr_colors, OPT_FREE);
1556}
1557#endif
1558
1559#ifdef HAVE_TGETENT
1560static char *(key_names[]) =
1561{
1562#ifdef FEAT_TERMRESPONSE
1563 /* Do this one first, it may cause a screen redraw. */
1564 "Co",
1565#endif
1566 "ku", "kd", "kr", "kl",
1567# ifdef ARCHIE
1568 "su", "sd", /* Termcap code made up! */
1569# endif
1570 "#2", "#4", "%i", "*7",
1571 "k1", "k2", "k3", "k4", "k5", "k6",
1572 "k7", "k8", "k9", "k;", "F1", "F2",
Bram Moolenaar19a09a12005-03-04 23:39:37 +00001573 "F3", "F4", "F5", "F6", "F7", "F8",
1574 "F9", "FA", "FB", "FC", "FD", "FE",
1575 "FF", "FG", "FH", "FI", "FJ", "FK",
1576 "FL", "FM", "FN", "FO", "FP", "FQ", "FR",
Bram Moolenaar071d4272004-06-13 20:20:40 +00001577 "%1", "&8", "kb", "kI", "kD", "kh",
1578 "@7", "kP", "kN", "K1", "K3", "K4", "K5", "kB",
1579 NULL
1580};
1581#endif
1582
1583/*
1584 * Set terminal options for terminal "term".
1585 * Return OK if terminal 'term' was found in a termcap, FAIL otherwise.
1586 *
1587 * While doing this, until ttest(), some options may be NULL, be careful.
1588 */
1589 int
1590set_termname(term)
1591 char_u *term;
1592{
1593 struct builtin_term *termp;
1594#ifdef HAVE_TGETENT
1595 int builtin_first = p_tbi;
1596 int try;
1597 int termcap_cleared = FALSE;
1598#endif
1599 int width = 0, height = 0;
1600 char_u *error_msg = NULL;
1601 char_u *bs_p, *del_p;
1602
Bram Moolenaar26a60b42005-02-22 08:49:11 +00001603 /* In silect mode (ex -s) we don't use the 'term' option. */
1604 if (silent_mode)
1605 return OK;
1606
Bram Moolenaar071d4272004-06-13 20:20:40 +00001607 detected_8bit = FALSE; /* reset 8-bit detection */
1608
1609 if (term_is_builtin(term))
1610 {
1611 term += 8;
1612#ifdef HAVE_TGETENT
1613 builtin_first = 1;
1614#endif
1615 }
1616
1617/*
1618 * If HAVE_TGETENT is not defined, only the builtin termcap is used, otherwise:
1619 * If builtin_first is TRUE:
1620 * 0. try builtin termcap
1621 * 1. try external termcap
1622 * 2. if both fail default to a builtin terminal
1623 * If builtin_first is FALSE:
1624 * 1. try external termcap
1625 * 2. try builtin termcap, if both fail default to a builtin terminal
1626 */
1627#ifdef HAVE_TGETENT
1628 for (try = builtin_first ? 0 : 1; try < 3; ++try)
1629 {
1630 /*
1631 * Use external termcap
1632 */
1633 if (try == 1)
1634 {
1635 char_u *p;
1636 static char_u tstrbuf[TBUFSZ];
1637 int i;
1638 char_u tbuf[TBUFSZ];
1639 char_u *tp;
1640 static struct {
1641 enum SpecialKey dest; /* index in term_strings[] */
1642 char *name; /* termcap name for string */
1643 } string_names[] =
1644 { {KS_CE, "ce"}, {KS_AL, "al"}, {KS_CAL,"AL"},
1645 {KS_DL, "dl"}, {KS_CDL,"DL"}, {KS_CS, "cs"},
1646 {KS_CL, "cl"}, {KS_CD, "cd"},
1647 {KS_VI, "vi"}, {KS_VE, "ve"}, {KS_MB, "mb"},
1648 {KS_VS, "vs"}, {KS_ME, "me"}, {KS_MR, "mr"},
1649 {KS_MD, "md"}, {KS_SE, "se"}, {KS_SO, "so"},
1650 {KS_CZH,"ZH"}, {KS_CZR,"ZR"}, {KS_UE, "ue"},
1651 {KS_US, "us"}, {KS_CM, "cm"}, {KS_SR, "sr"},
1652 {KS_CRI,"RI"}, {KS_VB, "vb"}, {KS_KS, "ks"},
1653 {KS_KE, "ke"}, {KS_TI, "ti"}, {KS_TE, "te"},
1654 {KS_BC, "bc"}, {KS_CSB,"Sb"}, {KS_CSF,"Sf"},
1655 {KS_CAB,"AB"}, {KS_CAF,"AF"}, {KS_LE, "le"},
1656 {KS_ND, "nd"}, {KS_OP, "op"}, {KS_CRV, "RV"},
1657 {KS_CIS, "IS"}, {KS_CIE, "IE"},
1658 {KS_TS, "ts"}, {KS_FS, "fs"},
1659 {KS_CWP, "WP"}, {KS_CWS, "WS"},
Bram Moolenaar293ee4d2004-12-09 21:34:53 +00001660 {KS_CSI, "SI"}, {KS_CEI, "EI"},
Bram Moolenaar071d4272004-06-13 20:20:40 +00001661 {(enum SpecialKey)0, NULL}
1662 };
1663
1664 /*
1665 * If the external termcap does not have a matching entry, try the
1666 * builtin ones.
1667 */
1668 if ((error_msg = tgetent_error(tbuf, term)) == NULL)
1669 {
1670 tp = tstrbuf;
1671 if (!termcap_cleared)
1672 {
1673 clear_termoptions(); /* clear old options */
1674 termcap_cleared = TRUE;
1675 }
1676
1677 /* get output strings */
1678 for (i = 0; string_names[i].name != NULL; ++i)
1679 {
1680 if (term_str(string_names[i].dest) == NULL
1681 || term_str(string_names[i].dest) == empty_option)
1682 term_str(string_names[i].dest) =
1683 TGETSTR(string_names[i].name, &tp);
1684 }
1685
1686 /* tgetflag() returns 1 if the flag is present, 0 if not and
1687 * possibly -1 if the flag doesn't exist. */
1688 if ((T_MS == NULL || T_MS == empty_option)
1689 && tgetflag("ms") > 0)
1690 T_MS = (char_u *)"y";
1691 if ((T_XS == NULL || T_XS == empty_option)
1692 && tgetflag("xs") > 0)
1693 T_XS = (char_u *)"y";
1694 if ((T_DB == NULL || T_DB == empty_option)
1695 && tgetflag("db") > 0)
1696 T_DB = (char_u *)"y";
1697 if ((T_DA == NULL || T_DA == empty_option)
1698 && tgetflag("da") > 0)
1699 T_DA = (char_u *)"y";
1700 if ((T_UT == NULL || T_UT == empty_option)
1701 && tgetflag("ut") > 0)
1702 T_UT = (char_u *)"y";
1703
1704
1705 /*
1706 * get key codes
1707 */
1708 for (i = 0; key_names[i] != NULL; ++i)
1709 {
1710 if (find_termcode((char_u *)key_names[i]) == NULL)
1711 {
1712 p = TGETSTR(key_names[i], &tp);
1713 /* if cursor-left == backspace, ignore it (televideo
1714 * 925) */
1715 if (p != NULL
1716 && (*p != Ctrl_H
1717 || key_names[i][0] != 'k'
1718 || key_names[i][1] != 'l'))
1719 add_termcode((char_u *)key_names[i], p, FALSE);
1720 }
1721 }
1722
1723 if (height == 0)
1724 height = tgetnum("li");
1725 if (width == 0)
1726 width = tgetnum("co");
1727
1728 /*
1729 * Get number of colors (if not done already).
1730 */
1731 if (term_str(KS_CCO) == NULL
1732 || term_str(KS_CCO) == empty_option)
1733 set_color_count(tgetnum("Co"));
1734
1735# ifndef hpux
1736 BC = (char *)TGETSTR("bc", &tp);
1737 UP = (char *)TGETSTR("up", &tp);
1738 p = TGETSTR("pc", &tp);
1739 if (p)
1740 PC = *p;
1741# endif /* hpux */
1742 }
1743 }
1744 else /* try == 0 || try == 2 */
1745#endif /* HAVE_TGETENT */
1746 /*
1747 * Use builtin termcap
1748 */
1749 {
1750#ifdef HAVE_TGETENT
1751 /*
1752 * If builtin termcap was already used, there is no need to search
1753 * for the builtin termcap again, quit now.
1754 */
1755 if (try == 2 && builtin_first && termcap_cleared)
1756 break;
1757#endif
1758 /*
1759 * search for 'term' in builtin_termcaps[]
1760 */
1761 termp = find_builtin_term(term);
1762 if (termp->bt_string == NULL) /* did not find it */
1763 {
1764#ifdef HAVE_TGETENT
1765 /*
1766 * If try == 0, first try the external termcap. If that is not
1767 * found we'll get back here with try == 2.
1768 * If termcap_cleared is set we used the external termcap,
1769 * don't complain about not finding the term in the builtin
1770 * termcap.
1771 */
1772 if (try == 0) /* try external one */
1773 continue;
1774 if (termcap_cleared) /* found in external termcap */
1775 break;
1776#endif
1777
1778 mch_errmsg("\r\n");
1779 if (error_msg != NULL)
1780 {
1781 mch_errmsg((char *)error_msg);
1782 mch_errmsg("\r\n");
1783 }
1784 mch_errmsg("'");
1785 mch_errmsg((char *)term);
1786 mch_errmsg(_("' not known. Available builtin terminals are:"));
1787 mch_errmsg("\r\n");
1788 for (termp = &(builtin_termcaps[0]); termp->bt_string != NULL;
1789 ++termp)
1790 {
1791 if (termp->bt_entry == (int)KS_NAME)
1792 {
1793#ifdef HAVE_TGETENT
1794 mch_errmsg(" builtin_");
1795#else
1796 mch_errmsg(" ");
1797#endif
1798 mch_errmsg(termp->bt_string);
1799 mch_errmsg("\r\n");
1800 }
1801 }
1802 /* when user typed :set term=xxx, quit here */
1803 if (starting != NO_SCREEN)
1804 {
1805 screen_start(); /* don't know where cursor is now */
1806 wait_return(TRUE);
1807 return FAIL;
1808 }
1809 term = DEFAULT_TERM;
1810 mch_errmsg(_("defaulting to '"));
1811 mch_errmsg((char *)term);
1812 mch_errmsg("'\r\n");
1813 if (emsg_silent == 0)
1814 {
1815 screen_start(); /* don't know where cursor is now */
1816 out_flush();
1817 ui_delay(2000L, TRUE);
1818 }
1819 set_string_option_direct((char_u *)"term", -1, term, OPT_FREE);
1820 display_errors();
1821 }
1822 out_flush();
1823#ifdef HAVE_TGETENT
1824 if (!termcap_cleared)
1825 {
1826#endif
1827 clear_termoptions(); /* clear old options */
1828#ifdef HAVE_TGETENT
1829 termcap_cleared = TRUE;
1830 }
1831#endif
1832 parse_builtin_tcap(term);
1833#ifdef FEAT_GUI
1834 if (term_is_gui(term))
1835 {
1836 out_flush();
1837 gui_init();
1838 /* If starting the GUI failed, don't do any of the other
1839 * things for this terminal */
1840 if (!gui.in_use)
1841 return FAIL;
1842#ifdef HAVE_TGETENT
1843 break; /* don't try using external termcap */
1844#endif
1845 }
1846#endif /* FEAT_GUI */
1847 }
1848#ifdef HAVE_TGETENT
1849 }
1850#endif
1851
1852/*
1853 * special: There is no info in the termcap about whether the cursor
1854 * positioning is relative to the start of the screen or to the start of the
1855 * scrolling region. We just guess here. Only msdos pcterm is known to do it
1856 * relative.
1857 */
1858 if (STRCMP(term, "pcterm") == 0)
1859 T_CCS = (char_u *)"yes";
1860 else
1861 T_CCS = empty_option;
1862
1863#ifdef UNIX
1864/*
1865 * Any "stty" settings override the default for t_kb from the termcap.
1866 * This is in os_unix.c, because it depends a lot on the version of unix that
1867 * is being used.
1868 * Don't do this when the GUI is active, it uses "t_kb" and "t_kD" directly.
1869 */
1870#ifdef FEAT_GUI
1871 if (!gui.in_use)
1872#endif
1873 get_stty();
1874#endif
1875
1876/*
1877 * If the termcap has no entry for 'bs' and/or 'del' and the ioctl() also
1878 * didn't work, use the default CTRL-H
1879 * The default for t_kD is DEL, unless t_kb is DEL.
1880 * The vim_strsave'd strings are probably lost forever, well it's only two
1881 * bytes. Don't do this when the GUI is active, it uses "t_kb" and "t_kD"
1882 * directly.
1883 */
1884#ifdef FEAT_GUI
1885 if (!gui.in_use)
1886#endif
1887 {
1888 bs_p = find_termcode((char_u *)"kb");
1889 del_p = find_termcode((char_u *)"kD");
1890 if (bs_p == NULL || *bs_p == NUL)
1891 add_termcode((char_u *)"kb", (bs_p = (char_u *)CTRL_H_STR), FALSE);
1892 if ((del_p == NULL || *del_p == NUL) &&
1893 (bs_p == NULL || *bs_p != DEL))
1894 add_termcode((char_u *)"kD", (char_u *)DEL_STR, FALSE);
1895 }
1896
1897#if defined(UNIX) || defined(VMS)
1898 term_is_xterm = vim_is_xterm(term);
1899#endif
1900
1901#ifdef FEAT_MOUSE
1902# if defined(UNIX) || defined(VMS)
1903# ifdef FEAT_MOUSE_TTY
1904 /*
1905 * For Unix, set the 'ttymouse' option to the type of mouse to be used.
1906 * The termcode for the mouse is added as a side effect in option.c.
1907 */
1908 {
1909 char_u *p;
1910
1911 p = (char_u *)"";
1912# ifdef FEAT_MOUSE_XTERM
1913# ifdef FEAT_CLIPBOARD
1914# ifdef FEAT_GUI
1915 if (!gui.in_use)
1916# endif
1917 clip_init(FALSE);
1918# endif
1919 if (term_is_xterm)
1920 {
1921 if (use_xterm_mouse())
1922 p = NULL; /* keep existing value, might be "xterm2" */
1923 else
1924 p = (char_u *)"xterm";
1925 }
1926# endif
1927 if (p != NULL)
1928 set_option_value((char_u *)"ttym", 0L, p, 0);
1929 if (p == NULL
1930# ifdef FEAT_GUI
1931 || gui.in_use
1932# endif
1933 )
1934 check_mouse_termcode(); /* set mouse termcode anyway */
1935 }
1936# endif
1937# else
1938 set_mouse_termcode(KS_MOUSE, (char_u *)"\233M");
1939# endif
1940#endif /* FEAT_MOUSE */
1941
1942#ifdef FEAT_SNIFF
1943 {
1944 char_u name[2];
1945
1946 name[0] = (int)KS_EXTRA;
1947 name[1] = (int)KE_SNIFF;
1948 add_termcode(name, (char_u *)"\233sniff", FALSE);
1949 }
1950#endif
1951
1952#ifdef USE_TERM_CONSOLE
1953 /* DEFAULT_TERM indicates that it is the machine console. */
1954 if (STRCMP(term, DEFAULT_TERM) != 0)
1955 term_console = FALSE;
1956 else
1957 {
1958 term_console = TRUE;
1959# ifdef AMIGA
1960 win_resize_on(); /* enable window resizing reports */
1961# endif
1962 }
1963#endif
1964
1965#if defined(UNIX) || defined(VMS)
1966 /*
1967 * 'ttyfast' is default on for xterm, iris-ansi and a few others.
1968 */
1969 if (vim_is_fastterm(term))
1970 p_tf = TRUE;
1971#endif
1972#ifdef USE_TERM_CONSOLE
1973 /*
1974 * 'ttyfast' is default on consoles
1975 */
1976 if (term_console)
1977 p_tf = TRUE;
1978#endif
1979
1980 ttest(TRUE); /* make sure we have a valid set of terminal codes */
1981
1982 full_screen = TRUE; /* we can use termcap codes from now on */
1983 set_term_defaults(); /* use current values as defaults */
1984#ifdef FEAT_TERMRESPONSE
1985 crv_status = CRV_GET; /* Get terminal version later */
1986#endif
1987
1988 /*
1989 * Initialize the terminal with the appropriate termcap codes.
1990 * Set the mouse and window title if possible.
1991 * Don't do this when starting, need to parse the .vimrc first, because it
1992 * may redefine t_TI etc.
1993 */
1994 if (starting != NO_SCREEN)
1995 {
1996 starttermcap(); /* may change terminal mode */
1997#ifdef FEAT_MOUSE
1998 setmouse(); /* may start using the mouse */
1999#endif
2000#ifdef FEAT_TITLE
2001 maketitle(); /* may display window title */
2002#endif
2003 }
2004
2005 /* display initial screen after ttest() checking. jw. */
2006 if (width <= 0 || height <= 0)
2007 {
2008 /* termcap failed to report size */
2009 /* set defaults, in case ui_get_shellsize() also fails */
2010 width = 80;
2011#if defined(MSDOS) || defined(WIN3264)
2012 height = 25; /* console is often 25 lines */
2013#else
2014 height = 24; /* most terminals are 24 lines */
2015#endif
2016 }
2017 set_shellsize(width, height, FALSE); /* may change Rows */
2018 if (starting != NO_SCREEN)
2019 {
2020 if (scroll_region)
2021 scroll_region_reset(); /* In case Rows changed */
2022 check_map_keycodes(); /* check mappings for terminal codes used */
2023
2024#ifdef FEAT_AUTOCMD
2025 {
2026 buf_T *old_curbuf;
2027
2028 /*
2029 * Execute the TermChanged autocommands for each buffer that is
2030 * loaded.
2031 */
2032 old_curbuf = curbuf;
2033 for (curbuf = firstbuf; curbuf != NULL; curbuf = curbuf->b_next)
2034 {
2035 if (curbuf->b_ml.ml_mfp != NULL)
2036 apply_autocmds(EVENT_TERMCHANGED, NULL, NULL, FALSE,
2037 curbuf);
2038 }
2039 if (buf_valid(old_curbuf))
2040 curbuf = old_curbuf;
2041 }
2042#endif
2043 }
2044
2045#ifdef FEAT_TERMRESPONSE
2046 may_req_termresponse();
2047#endif
2048
2049 return OK;
2050}
2051
2052#if defined(FEAT_MOUSE) || defined(PROTO)
2053
2054# ifdef FEAT_MOUSE_TTY
2055# define HMT_NORMAL 1
2056# define HMT_NETTERM 2
2057# define HMT_DEC 4
2058# define HMT_JSBTERM 8
2059# define HMT_PTERM 16
2060static int has_mouse_termcode = 0;
2061# endif
2062
2063# if (!defined(UNIX) || defined(FEAT_MOUSE_XTERM) || defined(FEAT_MOUSE_NET) \
2064 || defined(FEAT_MOUSE_DEC)) || defined(FEAT_MOUSE_JSB) \
2065 || defined(FEAT_MOUSE_PTERM) || defined(PROTO)
2066 void
2067set_mouse_termcode(n, s)
2068 int n; /* KS_MOUSE, KS_NETTERM_MOUSE or KS_DEC_MOUSE */
2069 char_u *s;
2070{
2071 char_u name[2];
2072
2073 name[0] = n;
2074 name[1] = KE_FILLER;
2075 add_termcode(name, s, FALSE);
2076# ifdef FEAT_MOUSE_TTY
2077# ifdef FEAT_MOUSE_JSB
2078 if (n == KS_JSBTERM_MOUSE)
2079 has_mouse_termcode |= HMT_JSBTERM;
2080 else
2081# endif
2082# ifdef FEAT_MOUSE_NET
2083 if (n == KS_NETTERM_MOUSE)
2084 has_mouse_termcode |= HMT_NETTERM;
2085 else
2086# endif
2087# ifdef FEAT_MOUSE_DEC
2088 if (n == KS_DEC_MOUSE)
2089 has_mouse_termcode |= HMT_DEC;
2090 else
2091# endif
2092# ifdef FEAT_MOUSE_PTERM
2093 if (n == KS_PTERM_MOUSE)
2094 has_mouse_termcode |= HMT_PTERM;
2095 else
2096# endif
2097 has_mouse_termcode |= HMT_NORMAL;
2098# endif
2099}
2100# endif
2101
2102# if ((defined(UNIX) || defined(VMS) || defined(OS2)) \
2103 && (defined(FEAT_MOUSE_XTERM) || defined(FEAT_MOUSE_DEC) \
2104 || defined(FEAT_MOUSE_GPM) || defined(FEAT_MOUSE_PTERM))) \
2105 || defined(PROTO)
2106 void
2107del_mouse_termcode(n)
2108 int n; /* KS_MOUSE, KS_NETTERM_MOUSE or KS_DEC_MOUSE */
2109{
2110 char_u name[2];
2111
2112 name[0] = n;
2113 name[1] = KE_FILLER;
2114 del_termcode(name);
2115# ifdef FEAT_MOUSE_TTY
2116# ifdef FEAT_MOUSE_JSB
2117 if (n == KS_JSBTERM_MOUSE)
2118 has_mouse_termcode &= ~HMT_JSBTERM;
2119 else
2120# endif
2121# ifdef FEAT_MOUSE_NET
2122 if (n == KS_NETTERM_MOUSE)
2123 has_mouse_termcode &= ~HMT_NETTERM;
2124 else
2125# endif
2126# ifdef FEAT_MOUSE_DEC
2127 if (n == KS_DEC_MOUSE)
2128 has_mouse_termcode &= ~HMT_DEC;
2129 else
2130# endif
2131# ifdef FEAT_MOUSE_PTERM
2132 if (n == KS_PTERM_MOUSE)
2133 has_mouse_termcode &= ~HMT_PTERM;
2134 else
2135# endif
2136 has_mouse_termcode &= ~HMT_NORMAL;
2137# endif
2138}
2139# endif
2140#endif
2141
2142#ifdef HAVE_TGETENT
2143/*
2144 * Call tgetent()
2145 * Return error message if it fails, NULL if it's OK.
2146 */
2147 static char_u *
2148tgetent_error(tbuf, term)
2149 char_u *tbuf;
2150 char_u *term;
2151{
2152 int i;
2153
2154 i = TGETENT(tbuf, term);
2155 if (i < 0 /* -1 is always an error */
2156# ifdef TGETENT_ZERO_ERR
2157 || i == 0 /* sometimes zero is also an error */
2158# endif
2159 )
2160 {
2161 /* On FreeBSD tputs() gets a SEGV after a tgetent() which fails. Call
2162 * tgetent() with the always existing "dumb" entry to avoid a crash or
2163 * hang. */
2164 (void)TGETENT(tbuf, "dumb");
2165
2166 if (i < 0)
2167# ifdef TGETENT_ZERO_ERR
2168 return (char_u *)_("E557: Cannot open termcap file");
2169 if (i == 0)
2170# endif
2171#ifdef TERMINFO
2172 return (char_u *)_("E558: Terminal entry not found in terminfo");
2173#else
2174 return (char_u *)_("E559: Terminal entry not found in termcap");
2175#endif
2176 }
2177 return NULL;
2178}
2179
2180/*
2181 * Some versions of tgetstr() have been reported to return -1 instead of NULL.
2182 * Fix that here.
2183 */
2184 static char_u *
2185vim_tgetstr(s, pp)
2186 char *s;
2187 char_u **pp;
2188{
2189 char *p;
2190
2191 p = tgetstr(s, (char **)pp);
2192 if (p == (char *)-1)
2193 p = NULL;
2194 return (char_u *)p;
2195}
2196#endif /* HAVE_TGETENT */
2197
2198#if defined(HAVE_TGETENT) && (defined(UNIX) || defined(__EMX__) || defined(VMS) || defined(MACOS_X))
2199/*
2200 * Get Columns and Rows from the termcap. Used after a window signal if the
2201 * ioctl() fails. It doesn't make sense to call tgetent each time if the "co"
2202 * and "li" entries never change. But on some systems this works.
2203 * Errors while getting the entries are ignored.
2204 */
2205 void
2206getlinecol(cp, rp)
2207 long *cp; /* pointer to columns */
2208 long *rp; /* pointer to rows */
2209{
2210 char_u tbuf[TBUFSZ];
2211
2212 if (T_NAME != NULL && *T_NAME != NUL && tgetent_error(tbuf, T_NAME) == NULL)
2213 {
2214 if (*cp == 0)
2215 *cp = tgetnum("co");
2216 if (*rp == 0)
2217 *rp = tgetnum("li");
2218 }
2219}
2220#endif /* defined(HAVE_TGETENT) && defined(UNIX) */
2221
2222/*
2223 * Get a string entry from the termcap and add it to the list of termcodes.
2224 * Used for <t_xx> special keys.
2225 * Give an error message for failure when not sourcing.
2226 * If force given, replace an existing entry.
2227 * Return FAIL if the entry was not found, OK if the entry was added.
2228 */
2229 int
2230add_termcap_entry(name, force)
2231 char_u *name;
2232 int force;
2233{
2234 char_u *term;
2235 int key;
2236 struct builtin_term *termp;
2237#ifdef HAVE_TGETENT
2238 char_u *string;
2239 int i;
2240 int builtin_first;
2241 char_u tbuf[TBUFSZ];
2242 char_u tstrbuf[TBUFSZ];
2243 char_u *tp = tstrbuf;
2244 char_u *error_msg = NULL;
2245#endif
2246
2247/*
2248 * If the GUI is running or will start in a moment, we only support the keys
2249 * that the GUI can produce.
2250 */
2251#ifdef FEAT_GUI
2252 if (gui.in_use || gui.starting)
2253 return gui_mch_haskey(name);
2254#endif
2255
2256 if (!force && find_termcode(name) != NULL) /* it's already there */
2257 return OK;
2258
2259 term = T_NAME;
2260 if (term == NULL || *term == NUL) /* 'term' not defined yet */
2261 return FAIL;
2262
2263 if (term_is_builtin(term)) /* name starts with "builtin_" */
2264 {
2265 term += 8;
2266#ifdef HAVE_TGETENT
2267 builtin_first = TRUE;
2268#endif
2269 }
2270#ifdef HAVE_TGETENT
2271 else
2272 builtin_first = p_tbi;
2273#endif
2274
2275#ifdef HAVE_TGETENT
2276/*
2277 * We can get the entry from the builtin termcap and from the external one.
2278 * If 'ttybuiltin' is on or the terminal name starts with "builtin_", try
2279 * builtin termcap first.
2280 * If 'ttybuiltin' is off, try external termcap first.
2281 */
2282 for (i = 0; i < 2; ++i)
2283 {
2284 if (!builtin_first == i)
2285#endif
2286 /*
2287 * Search in builtin termcap
2288 */
2289 {
2290 termp = find_builtin_term(term);
2291 if (termp->bt_string != NULL) /* found it */
2292 {
2293 key = TERMCAP2KEY(name[0], name[1]);
2294 while (termp->bt_entry != (int)KS_NAME)
2295 {
2296 if ((int)termp->bt_entry == key)
2297 {
2298 add_termcode(name, (char_u *)termp->bt_string,
2299 term_is_8bit(term));
2300 return OK;
2301 }
2302 ++termp;
2303 }
2304 }
2305 }
2306#ifdef HAVE_TGETENT
2307 else
2308 /*
2309 * Search in external termcap
2310 */
2311 {
2312 error_msg = tgetent_error(tbuf, term);
2313 if (error_msg == NULL)
2314 {
2315 string = TGETSTR((char *)name, &tp);
2316 if (string != NULL && *string != NUL)
2317 {
2318 add_termcode(name, string, FALSE);
2319 return OK;
2320 }
2321 }
2322 }
2323 }
2324#endif
2325
2326 if (sourcing_name == NULL)
2327 {
2328#ifdef HAVE_TGETENT
2329 if (error_msg != NULL)
2330 EMSG(error_msg);
2331 else
2332#endif
2333 EMSG2(_("E436: No \"%s\" entry in termcap"), name);
2334 }
2335 return FAIL;
2336}
2337
2338 static int
2339term_is_builtin(name)
2340 char_u *name;
2341{
2342 return (STRNCMP(name, "builtin_", (size_t)8) == 0);
2343}
2344
2345/*
2346 * Return TRUE if terminal "name" uses CSI instead of <Esc>[.
2347 * Assume that the terminal is using 8-bit controls when the name contains
2348 * "8bit", like in "xterm-8bit".
2349 */
2350 int
2351term_is_8bit(name)
2352 char_u *name;
2353{
2354 return (detected_8bit || strstr((char *)name, "8bit") != NULL);
2355}
2356
2357/*
2358 * Translate terminal control chars from 7-bit to 8-bit:
2359 * <Esc>[ -> CSI
2360 * <Esc>] -> <M-C-]>
2361 * <Esc>O -> <M-C-O>
2362 */
2363 static int
2364term_7to8bit(p)
2365 char_u *p;
2366{
2367 if (*p == ESC)
2368 {
2369 if (p[1] == '[')
2370 return CSI;
2371 if (p[1] == ']')
2372 return 0x9d;
2373 if (p[1] == 'O')
2374 return 0x8f;
2375 }
2376 return 0;
2377}
2378
2379#ifdef FEAT_GUI
2380 int
2381term_is_gui(name)
2382 char_u *name;
2383{
2384 return (STRCMP(name, "builtin_gui") == 0 || STRCMP(name, "gui") == 0);
2385}
2386#endif
2387
2388#if !defined(HAVE_TGETENT) || defined(AMIGA) || defined(PROTO)
2389
2390 char_u *
2391tltoa(i)
2392 unsigned long i;
2393{
2394 static char_u buf[16];
2395 char_u *p;
2396
2397 p = buf + 15;
2398 *p = '\0';
2399 do
2400 {
2401 --p;
2402 *p = (char_u) (i % 10 + '0');
2403 i /= 10;
2404 }
2405 while (i > 0 && p > buf);
2406 return p;
2407}
2408#endif
2409
2410#ifndef HAVE_TGETENT
2411
2412/*
2413 * minimal tgoto() implementation.
2414 * no padding and we only parse for %i %d and %+char
2415 */
2416char *tgoto __ARGS((char *, int, int));
2417
2418 char *
2419tgoto(cm, x, y)
2420 char *cm;
2421 int x, y;
2422{
2423 static char buf[30];
2424 char *p, *s, *e;
2425
2426 if (!cm)
2427 return "OOPS";
2428 e = buf + 29;
2429 for (s = buf; s < e && *cm; cm++)
2430 {
2431 if (*cm != '%')
2432 {
2433 *s++ = *cm;
2434 continue;
2435 }
2436 switch (*++cm)
2437 {
2438 case 'd':
2439 p = (char *)tltoa((unsigned long)y);
2440 y = x;
2441 while (*p)
2442 *s++ = *p++;
2443 break;
2444 case 'i':
2445 x++;
2446 y++;
2447 break;
2448 case '+':
2449 *s++ = (char)(*++cm + y);
2450 y = x;
2451 break;
2452 case '%':
2453 *s++ = *cm;
2454 break;
2455 default:
2456 return "OOPS";
2457 }
2458 }
2459 *s = '\0';
2460 return buf;
2461}
2462
2463#endif /* HAVE_TGETENT */
2464
2465/*
2466 * Set the terminal name and initialize the terminal options.
2467 * If "name" is NULL or empty, get the terminal name from the environment.
2468 * If that fails, use the default terminal name.
2469 */
2470 void
2471termcapinit(name)
2472 char_u *name;
2473{
2474 char_u *term;
2475
2476 if (name != NULL && *name == NUL)
2477 name = NULL; /* empty name is equal to no name */
2478 term = name;
2479
2480#ifdef __BEOS__
2481 /*
2482 * TERM environment variable is normally set to 'ansi' on the Bebox;
2483 * Since the BeBox doesn't quite support full ANSI yet, we use our
2484 * own custom 'ansi-beos' termcap instead, unless the -T option has
2485 * been given on the command line.
2486 */
2487 if (term == NULL
2488 && strcmp((char *)mch_getenv((char_u *)"TERM"), "ansi") == 0)
2489 term = DEFAULT_TERM;
2490#endif
2491#ifndef MSWIN
2492 if (term == NULL)
2493 term = mch_getenv((char_u *)"TERM");
2494#endif
2495 if (term == NULL || *term == NUL)
2496 term = DEFAULT_TERM;
2497 set_string_option_direct((char_u *)"term", -1, term, OPT_FREE);
2498
2499 /* Set the default terminal name. */
2500 set_string_default("term", term);
2501 set_string_default("ttytype", term);
2502
2503 /*
2504 * Avoid using "term" here, because the next mch_getenv() may overwrite it.
2505 */
2506 set_termname(T_NAME != NULL ? T_NAME : term);
2507}
2508
2509/*
2510 * the number of calls to ui_write is reduced by using the buffer "out_buf"
2511 */
2512#ifdef DOS16
2513# define OUT_SIZE 255 /* only have 640K total... */
2514#else
2515# ifdef FEAT_GUI_W16
2516# define OUT_SIZE 1023 /* Save precious 1K near data */
2517# else
2518# define OUT_SIZE 2047
2519# endif
2520#endif
2521 /* Add one to allow mch_write() in os_win32.c to append a NUL */
2522static char_u out_buf[OUT_SIZE + 1];
2523static int out_pos = 0; /* number of chars in out_buf */
2524
2525/*
2526 * out_flush(): flush the output buffer
2527 */
2528 void
2529out_flush()
2530{
2531 int len;
2532
2533 if (out_pos != 0)
2534 {
2535 /* set out_pos to 0 before ui_write, to avoid recursiveness */
2536 len = out_pos;
2537 out_pos = 0;
2538 ui_write(out_buf, len);
2539 }
2540}
2541
2542#if defined(FEAT_MBYTE) || defined(PROTO)
2543/*
2544 * Sometimes a byte out of a multi-byte character is written with out_char().
2545 * To avoid flushing half of the character, call this function first.
2546 */
2547 void
2548out_flush_check()
2549{
2550 if (enc_dbcs != 0 && out_pos >= OUT_SIZE - MB_MAXBYTES)
2551 out_flush();
2552}
2553#endif
2554
2555#ifdef FEAT_GUI
2556/*
2557 * out_trash(): Throw away the contents of the output buffer
2558 */
2559 void
2560out_trash()
2561{
2562 out_pos = 0;
2563}
2564#endif
2565
2566/*
2567 * out_char(c): put a byte into the output buffer.
2568 * Flush it if it becomes full.
2569 * This should not be used for outputting text on the screen (use functions
2570 * like msg_puts() and screen_putchar() for that).
2571 */
2572 void
2573out_char(c)
2574 unsigned c;
2575{
2576#if defined(UNIX) || defined(VMS) || defined(AMIGA) || defined(MACOS_X_UNIX)
2577 if (c == '\n') /* turn LF into CR-LF (CRMOD doesn't seem to do this) */
2578 out_char('\r');
2579#endif
2580
2581 out_buf[out_pos++] = c;
2582
2583 /* For testing we flush each time. */
2584 if (out_pos >= OUT_SIZE || p_wd)
2585 out_flush();
2586}
2587
2588static void out_char_nf __ARGS((unsigned));
2589
2590/*
2591 * out_char_nf(c): like out_char(), but don't flush when p_wd is set
2592 */
2593 static void
2594out_char_nf(c)
2595 unsigned c;
2596{
2597#if defined(UNIX) || defined(VMS) || defined(AMIGA) || defined(MACOS_X_UNIX)
2598 if (c == '\n') /* turn LF into CR-LF (CRMOD doesn't seem to do this) */
2599 out_char_nf('\r');
2600#endif
2601
2602 out_buf[out_pos++] = c;
2603
2604 if (out_pos >= OUT_SIZE)
2605 out_flush();
2606}
2607
2608/*
2609 * A never-padding out_str.
2610 * use this whenever you don't want to run the string through tputs.
2611 * tputs above is harmless, but tputs from the termcap library
2612 * is likely to strip off leading digits, that it mistakes for padding
2613 * information, and "%i", "%d", etc.
2614 * This should only be used for writing terminal codes, not for outputting
2615 * normal text (use functions like msg_puts() and screen_putchar() for that).
2616 */
2617 void
2618out_str_nf(s)
2619 char_u *s;
2620{
2621 if (out_pos > OUT_SIZE - 20) /* avoid terminal strings being split up */
2622 out_flush();
2623 while (*s)
2624 out_char_nf(*s++);
2625
2626 /* For testing we write one string at a time. */
2627 if (p_wd)
2628 out_flush();
2629}
2630
2631/*
2632 * out_str(s): Put a character string a byte at a time into the output buffer.
2633 * If HAVE_TGETENT is defined use the termcap parser. (jw)
2634 * This should only be used for writing terminal codes, not for outputting
2635 * normal text (use functions like msg_puts() and screen_putchar() for that).
2636 */
2637 void
2638out_str(s)
2639 char_u *s;
2640{
2641 if (s != NULL && *s)
2642 {
2643#ifdef FEAT_GUI
2644 /* Don't use tputs() when GUI is used, ncurses crashes. */
2645 if (gui.in_use)
2646 {
2647 out_str_nf(s);
2648 return;
2649 }
2650#endif
2651 /* avoid terminal strings being split up */
2652 if (out_pos > OUT_SIZE - 20)
2653 out_flush();
2654#ifdef HAVE_TGETENT
2655 tputs((char *)s, 1, TPUTSFUNCAST out_char_nf);
2656#else
2657 while (*s)
2658 out_char_nf(*s++);
2659#endif
2660
2661 /* For testing we write one string at a time. */
2662 if (p_wd)
2663 out_flush();
2664 }
2665}
2666
2667/*
2668 * cursor positioning using termcap parser. (jw)
2669 */
2670 void
2671term_windgoto(row, col)
2672 int row;
2673 int col;
2674{
2675 OUT_STR(tgoto((char *)T_CM, col, row));
2676}
2677
2678 void
2679term_cursor_right(i)
2680 int i;
2681{
2682 OUT_STR(tgoto((char *)T_CRI, 0, i));
2683}
2684
2685 void
2686term_append_lines(line_count)
2687 int line_count;
2688{
2689 OUT_STR(tgoto((char *)T_CAL, 0, line_count));
2690}
2691
2692 void
2693term_delete_lines(line_count)
2694 int line_count;
2695{
2696 OUT_STR(tgoto((char *)T_CDL, 0, line_count));
2697}
2698
2699#if defined(HAVE_TGETENT) || defined(PROTO)
2700 void
2701term_set_winpos(x, y)
2702 int x;
2703 int y;
2704{
2705 /* Can't handle a negative value here */
2706 if (x < 0)
2707 x = 0;
2708 if (y < 0)
2709 y = 0;
2710 OUT_STR(tgoto((char *)T_CWP, y, x));
2711}
2712
2713 void
2714term_set_winsize(width, height)
2715 int width;
2716 int height;
2717{
2718 OUT_STR(tgoto((char *)T_CWS, height, width));
2719}
2720#endif
2721
2722 void
2723term_fg_color(n)
2724 int n;
2725{
2726 /* Use "AF" termcap entry if present, "Sf" entry otherwise */
2727 if (*T_CAF)
2728 term_color(T_CAF, n);
2729 else if (*T_CSF)
2730 term_color(T_CSF, n);
2731}
2732
2733 void
2734term_bg_color(n)
2735 int n;
2736{
2737 /* Use "AB" termcap entry if present, "Sb" entry otherwise */
2738 if (*T_CAB)
2739 term_color(T_CAB, n);
2740 else if (*T_CSB)
2741 term_color(T_CSB, n);
2742}
2743
2744 static void
2745term_color(s, n)
2746 char_u *s;
2747 int n;
2748{
2749 char buf[20];
2750 int i = 2; /* index in s[] just after <Esc>[ or CSI */
2751
2752 /* Special handling of 16 colors, because termcap can't handle it */
2753 /* Also accept "\e[3%dm" for TERMINFO, it is sometimes used */
2754 /* Also accept CSI instead of <Esc>[ */
2755 if (n >= 8 && t_colors >= 16
2756 && ((s[0] == ESC && s[1] == '[') || (s[0] == CSI && (i = 1) == 1))
2757 && s[i] != NUL
2758 && (STRCMP(s + i + 1, "%p1%dm") == 0
2759 || STRCMP(s + i + 1, "%dm") == 0)
2760 && (s[i] == '3' || s[i] == '4'))
2761 {
2762 sprintf(buf,
2763#ifdef TERMINFO
2764 "%s%s%%p1%%dm",
2765#else
2766 "%s%s%%dm",
2767#endif
2768 i == 2 ? IF_EB("\033[", ESC_STR "[") : "\233",
2769 s[i] == '3' ? (n >= 16 ? "38;5;" : "9")
2770 : (n >= 16 ? "48;5;" : "10"));
2771 OUT_STR(tgoto(buf, 0, n >= 16 ? n : n - 8));
2772 }
2773 else
2774 OUT_STR(tgoto((char *)s, 0, n));
2775}
2776
2777#if (defined(FEAT_TITLE) && (defined(UNIX) || defined(OS2) || defined(VMS) || defined(MACOS_X))) || defined(PROTO)
2778/*
2779 * Generic function to set window title, using t_ts and t_fs.
2780 */
2781 void
2782term_settitle(title)
2783 char_u *title;
2784{
2785 /* t_ts takes one argument: column in status line */
2786 OUT_STR(tgoto((char *)T_TS, 0, 0)); /* set title start */
2787 out_str_nf(title);
2788 out_str(T_FS); /* set title end */
2789 out_flush();
2790}
2791#endif
2792
2793/*
2794 * Make sure we have a valid set or terminal options.
2795 * Replace all entries that are NULL by empty_option
2796 */
2797 void
2798ttest(pairs)
2799 int pairs;
2800{
2801 check_options(); /* make sure no options are NULL */
2802
2803 /*
2804 * MUST have "cm": cursor motion.
2805 */
2806 if (*T_CM == NUL)
2807 EMSG(_("E437: terminal capability \"cm\" required"));
2808
2809 /*
2810 * if "cs" defined, use a scroll region, it's faster.
2811 */
2812 if (*T_CS != NUL)
2813 scroll_region = TRUE;
2814 else
2815 scroll_region = FALSE;
2816
2817 if (pairs)
2818 {
2819 /*
2820 * optional pairs
2821 */
2822 /* TP goes to normal mode for TI (invert) and TB (bold) */
2823 if (*T_ME == NUL)
2824 T_ME = T_MR = T_MD = T_MB = empty_option;
2825 if (*T_SO == NUL || *T_SE == NUL)
2826 T_SO = T_SE = empty_option;
2827 if (*T_US == NUL || *T_UE == NUL)
2828 T_US = T_UE = empty_option;
2829 if (*T_CZH == NUL || *T_CZR == NUL)
2830 T_CZH = T_CZR = empty_option;
2831
2832 /* T_VE is needed even though T_VI is not defined */
2833 if (*T_VE == NUL)
2834 T_VI = empty_option;
2835
2836 /* if 'mr' or 'me' is not defined use 'so' and 'se' */
2837 if (*T_ME == NUL)
2838 {
2839 T_ME = T_SE;
2840 T_MR = T_SO;
2841 T_MD = T_SO;
2842 }
2843
2844 /* if 'so' or 'se' is not defined use 'mr' and 'me' */
2845 if (*T_SO == NUL)
2846 {
2847 T_SE = T_ME;
2848 if (*T_MR == NUL)
2849 T_SO = T_MD;
2850 else
2851 T_SO = T_MR;
2852 }
2853
2854 /* if 'ZH' or 'ZR' is not defined use 'mr' and 'me' */
2855 if (*T_CZH == NUL)
2856 {
2857 T_CZR = T_ME;
2858 if (*T_MR == NUL)
2859 T_CZH = T_MD;
2860 else
2861 T_CZH = T_MR;
2862 }
2863
2864 /* "Sb" and "Sf" come in pairs */
2865 if (*T_CSB == NUL || *T_CSF == NUL)
2866 {
2867 T_CSB = empty_option;
2868 T_CSF = empty_option;
2869 }
2870
2871 /* "AB" and "AF" come in pairs */
2872 if (*T_CAB == NUL || *T_CAF == NUL)
2873 {
2874 T_CAB = empty_option;
2875 T_CAF = empty_option;
2876 }
2877
2878 /* if 'Sb' and 'AB' are not defined, reset "Co" */
2879 if (*T_CSB == NUL && *T_CAB == NUL)
2880 T_CCO = empty_option;
2881
2882 /* Set 'weirdinvert' according to value of 't_xs' */
2883 p_wiv = (*T_XS != NUL);
2884 }
2885 need_gather = TRUE;
2886
2887 /* Set t_colors to the value of t_Co. */
2888 t_colors = atoi((char *)T_CCO);
2889}
2890
2891#if (defined(FEAT_GUI) && (defined(FEAT_MENU) || !defined(USE_ON_FLY_SCROLL))) \
2892 || defined(PROTO)
2893/*
2894 * Represent the given long_u as individual bytes, with the most significant
2895 * byte first, and store them in dst.
2896 */
2897 void
2898add_long_to_buf(val, dst)
2899 long_u val;
2900 char_u *dst;
2901{
2902 int i;
2903 int shift;
2904
2905 for (i = 1; i <= sizeof(long_u); i++)
2906 {
2907 shift = 8 * (sizeof(long_u) - i);
2908 dst[i - 1] = (char_u) ((val >> shift) & 0xff);
2909 }
2910}
2911
2912static int get_long_from_buf __ARGS((char_u *buf, long_u *val));
2913
2914/*
2915 * Interpret the next string of bytes in buf as a long integer, with the most
2916 * significant byte first. Note that it is assumed that buf has been through
2917 * inchar(), so that NUL and K_SPECIAL will be represented as three bytes each.
2918 * Puts result in val, and returns the number of bytes read from buf
2919 * (between sizeof(long_u) and 2 * sizeof(long_u)), or -1 if not enough bytes
2920 * were present.
2921 */
2922 static int
2923get_long_from_buf(buf, val)
2924 char_u *buf;
2925 long_u *val;
2926{
2927 int len;
2928 char_u bytes[sizeof(long_u)];
2929 int i;
2930 int shift;
2931
2932 *val = 0;
2933 len = get_bytes_from_buf(buf, bytes, (int)sizeof(long_u));
2934 if (len != -1)
2935 {
2936 for (i = 0; i < sizeof(long_u); i++)
2937 {
2938 shift = 8 * (sizeof(long_u) - 1 - i);
2939 *val += (long_u)bytes[i] << shift;
2940 }
2941 }
2942 return len;
2943}
2944#endif
2945
2946#if defined(FEAT_GUI) \
2947 || (defined(FEAT_MOUSE) && (!defined(UNIX) || defined(FEAT_MOUSE_XTERM)))
2948/*
2949 * Read the next num_bytes bytes from buf, and store them in bytes. Assume
2950 * that buf has been through inchar(). Returns the actual number of bytes used
2951 * from buf (between num_bytes and num_bytes*2), or -1 if not enough bytes were
2952 * available.
2953 */
2954 static int
2955get_bytes_from_buf(buf, bytes, num_bytes)
2956 char_u *buf;
2957 char_u *bytes;
2958 int num_bytes;
2959{
2960 int len = 0;
2961 int i;
2962 char_u c;
2963
2964 for (i = 0; i < num_bytes; i++)
2965 {
2966 if ((c = buf[len++]) == NUL)
2967 return -1;
2968 if (c == K_SPECIAL)
2969 {
2970 if (buf[len] == NUL || buf[len + 1] == NUL) /* cannot happen? */
2971 return -1;
2972 if (buf[len++] == (int)KS_ZERO)
2973 c = NUL;
2974 ++len; /* skip KE_FILLER */
2975 /* else it should be KS_SPECIAL, and c already equals K_SPECIAL */
2976 }
2977 bytes[i] = c;
2978 }
2979 return len;
2980}
2981#endif
2982
2983/*
2984 * Check if the new shell size is valid, correct it if it's too small.
2985 */
2986 void
2987check_shellsize()
2988{
2989 if (Columns < MIN_COLUMNS)
2990 Columns = MIN_COLUMNS;
2991 if (Rows < min_rows()) /* need room for one window and command line */
2992 Rows = min_rows();
2993}
2994
Bram Moolenaar86b68352004-12-27 21:59:20 +00002995/*
2996 * Invoked just before the screen structures are going to be (re)allocated.
2997 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002998 void
2999win_new_shellsize()
3000{
3001 static int old_Rows = 0;
3002 static int old_Columns = 0;
3003
3004 if (old_Rows != Rows || old_Columns != Columns)
3005 ui_new_shellsize();
3006 if (old_Rows != Rows)
3007 {
Bram Moolenaar4399ef42005-02-12 14:29:27 +00003008 /* if 'window' uses the whole screen, keep it using that */
Bram Moolenaar19a09a12005-03-04 23:39:37 +00003009 if (p_window == old_Rows - 1 || old_Rows == 0)
Bram Moolenaar4399ef42005-02-12 14:29:27 +00003010 p_window = Rows - 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003011 old_Rows = Rows;
3012 shell_new_rows(); /* update window sizes */
3013 }
3014 if (old_Columns != Columns)
3015 {
3016 old_Columns = Columns;
3017#ifdef FEAT_VERTSPLIT
3018 shell_new_columns(); /* update window sizes */
3019#endif
3020 }
3021}
3022
3023/*
3024 * Call this function when the Vim shell has been resized in any way.
3025 * Will obtain the current size and redraw (also when size didn't change).
3026 */
3027 void
3028shell_resized()
3029{
3030 set_shellsize(0, 0, FALSE);
3031}
3032
3033/*
3034 * Check if the shell size changed. Handle a resize.
3035 * When the size didn't change, nothing happens.
3036 */
3037 void
3038shell_resized_check()
3039{
3040 int old_Rows = Rows;
3041 int old_Columns = Columns;
3042
3043 (void)ui_get_shellsize();
3044 check_shellsize();
3045 if (old_Rows != Rows || old_Columns != Columns)
3046 shell_resized();
3047}
3048
3049/*
3050 * Set size of the Vim shell.
3051 * If 'mustset' is TRUE, we must set Rows and Columns, do not get the real
3052 * window size (this is used for the :win command).
3053 * If 'mustset' is FALSE, we may try to get the real window size and if
3054 * it fails use 'width' and 'height'.
3055 */
3056 void
3057set_shellsize(width, height, mustset)
3058 int width, height;
3059 int mustset;
3060{
3061 static int busy = FALSE;
3062
3063 /*
3064 * Avoid recursiveness, can happen when setting the window size causes
3065 * another window-changed signal.
3066 */
3067 if (busy)
3068 return;
3069
3070 if (width < 0 || height < 0) /* just checking... */
3071 return;
3072
3073 if (State == HITRETURN || State == SETWSIZE) /* postpone the resizing */
3074 {
3075 State = SETWSIZE;
3076 return;
3077 }
3078
3079 ++busy;
3080
3081#ifdef AMIGA
3082 out_flush(); /* must do this before mch_get_shellsize() for
3083 some obscure reason */
3084#endif
3085
3086 if (mustset || (ui_get_shellsize() == FAIL && height != 0))
3087 {
3088 Rows = height;
3089 Columns = width;
3090 check_shellsize();
3091 ui_set_shellsize(mustset);
3092 }
3093 else
3094 check_shellsize();
3095
3096 /* The window layout used to be adjusted here, but it now happens in
3097 * screenalloc() (also invoked from screenclear()). That is because the
3098 * "busy" check above may skip this, but not screenalloc(). */
3099
3100 if (State != ASKMORE && State != EXTERNCMD && State != CONFIRM)
3101 screenclear();
3102 else
3103 screen_start(); /* don't know where cursor is now */
3104
3105 if (starting != NO_SCREEN)
3106 {
3107#ifdef FEAT_TITLE
3108 maketitle();
3109#endif
3110 changed_line_abv_curs();
3111 invalidate_botline();
3112
3113 /*
3114 * We only redraw when it's needed:
3115 * - While at the more prompt or executing an external command, don't
3116 * redraw, but position the cursor.
3117 * - While editing the command line, only redraw that.
3118 * - in Ex mode, don't redraw anything.
3119 * - Otherwise, redraw right now, and position the cursor.
3120 * Always need to call update_screen() or screenalloc(), to make
3121 * sure Rows/Columns and the size of ScreenLines[] is correct!
3122 */
3123 if (State == ASKMORE || State == EXTERNCMD || State == CONFIRM
3124 || exmode_active)
3125 {
3126 screenalloc(FALSE);
3127 repeat_message();
3128 }
3129 else if (State & CMDLINE)
3130 {
3131 update_screen(NOT_VALID);
3132 redrawcmdline();
3133 }
3134 else
3135 {
3136 update_topline();
3137 update_screen(NOT_VALID);
3138 if (redrawing())
3139 setcursor();
3140 }
3141 cursor_on(); /* redrawing may have switched it off */
3142 }
3143 out_flush();
3144 --busy;
3145}
3146
3147/*
3148 * Set the terminal to TMODE_RAW (for Normal mode) or TMODE_COOK (for external
3149 * commands and Ex mode).
3150 */
3151 void
3152settmode(tmode)
3153 int tmode;
3154{
3155#ifdef FEAT_GUI
3156 /* don't set the term where gvim was started to any mode */
3157 if (gui.in_use)
3158 return;
3159#endif
3160
3161 if (full_screen)
3162 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00003163 /*
3164 * When returning after calling a shell we want to really set the
3165 * terminal to raw mode, even though we think it already is, because
3166 * the shell program may have reset the terminal mode.
3167 * When we think the terminal is normal, don't try to set it to
3168 * normal again, because that causes problems (logout!) on some
3169 * machines.
3170 */
3171 if (tmode != TMODE_COOK || cur_tmode != TMODE_COOK)
3172 {
3173#ifdef FEAT_TERMRESPONSE
3174 /* May need to check for T_CRV response and termcodes, it doesn't
3175 * work in Cooked mode, an external program may get them. */
3176 if (tmode != TMODE_RAW && crv_status == CRV_SENT)
3177 (void)vpeekc_nomap();
3178 check_for_codes_from_term();
3179#endif
3180#ifdef FEAT_MOUSE_TTY
3181 if (tmode != TMODE_RAW)
3182 mch_setmouse(FALSE); /* switch mouse off */
3183#endif
3184 out_flush();
3185 mch_settmode(tmode); /* machine specific function */
3186 cur_tmode = tmode;
3187#ifdef FEAT_MOUSE
3188 if (tmode == TMODE_RAW)
3189 setmouse(); /* may switch mouse on */
3190#endif
3191 out_flush();
3192 }
3193#ifdef FEAT_TERMRESPONSE
3194 may_req_termresponse();
3195#endif
3196 }
3197}
3198
3199 void
3200starttermcap()
3201{
3202 if (full_screen && !termcap_active)
3203 {
3204 out_str(T_TI); /* start termcap mode */
3205 out_str(T_KS); /* start "keypad transmit" mode */
3206 out_flush();
3207 termcap_active = TRUE;
3208 screen_start(); /* don't know where cursor is now */
3209#ifdef FEAT_TERMRESPONSE
3210 may_req_termresponse();
3211 /* Immediately check for a response. If t_Co changes, we don't want
3212 * to redraw with wrong colors first. */
3213 check_for_codes_from_term();
3214#endif
3215 }
3216}
3217
3218 void
3219stoptermcap()
3220{
3221 screen_stop_highlight();
3222 reset_cterm_colors();
3223 if (termcap_active)
3224 {
3225#ifdef FEAT_TERMRESPONSE
3226 /* May need to check for T_CRV response. */
3227 if (crv_status == CRV_SENT)
3228 (void)vpeekc_nomap();
3229 /* Check for termcodes first, otherwise an external program may get
3230 * them. */
3231 check_for_codes_from_term();
3232#endif
3233 out_str(T_KE); /* stop "keypad transmit" mode */
3234 out_flush();
3235 termcap_active = FALSE;
3236 cursor_on(); /* just in case it is still off */
3237 out_str(T_TE); /* stop termcap mode */
3238 screen_start(); /* don't know where cursor is now */
3239 out_flush();
3240 }
3241}
3242
3243#ifdef FEAT_TERMRESPONSE
3244/*
3245 * Request version string (for xterm) when needed.
3246 * Only do this after switching to raw mode, otherwise the result will be
3247 * echoed.
3248 * Only do this after termcap mode has been started, otherwise the codes for
3249 * the cursor keys may be wrong.
Bram Moolenaar4399ef42005-02-12 14:29:27 +00003250 * On Unix only do it when both output and input are a tty (avoid writing
3251 * request to terminal while reading from a file).
Bram Moolenaar071d4272004-06-13 20:20:40 +00003252 * The result is caught in check_termcode().
3253 */
3254 static void
3255may_req_termresponse()
3256{
3257 if (crv_status == CRV_GET
3258 && cur_tmode == TMODE_RAW
3259 && termcap_active
3260#ifdef UNIX
3261 && isatty(1)
Bram Moolenaar4399ef42005-02-12 14:29:27 +00003262 && isatty(read_cmd_fd)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003263#endif
3264 && *T_CRV != NUL)
3265 {
3266 out_str(T_CRV);
3267 crv_status = CRV_SENT;
3268 /* check for the characters now, otherwise they might be eaten by
3269 * get_keystroke() */
3270 out_flush();
3271 (void)vpeekc_nomap();
3272 }
3273}
3274#endif
3275
3276/*
3277 * Return TRUE when saving and restoring the screen.
3278 */
3279 int
3280swapping_screen()
3281{
3282 return (full_screen && *T_TI != NUL);
3283}
3284
3285#ifdef FEAT_MOUSE
3286/*
3287 * setmouse() - switch mouse on/off depending on current mode and 'mouse'
3288 */
3289 void
3290setmouse()
3291{
3292# ifdef FEAT_MOUSE_TTY
3293 int checkfor;
3294# endif
3295
3296# ifdef FEAT_MOUSESHAPE
3297 update_mouseshape(-1);
3298# endif
3299
3300# ifdef FEAT_MOUSE_TTY /* Should be outside proc, but may break MOUSESHAPE */
3301# ifdef FEAT_GUI
3302 /* In the GUI the mouse is always enabled. */
3303 if (gui.in_use)
3304 return;
3305# endif
3306 /* be quick when mouse is off */
3307 if (*p_mouse == NUL || has_mouse_termcode == 0)
3308 return;
3309
3310 /* don't switch mouse on when not in raw mode (Ex mode) */
3311 if (cur_tmode != TMODE_RAW)
3312 {
3313 mch_setmouse(FALSE);
3314 return;
3315 }
3316
3317# ifdef FEAT_VISUAL
3318 if (VIsual_active)
3319 checkfor = MOUSE_VISUAL;
3320 else
3321# endif
3322 if (State == HITRETURN || State == ASKMORE || State == SETWSIZE)
3323 checkfor = MOUSE_RETURN;
3324 else if (State & INSERT)
3325 checkfor = MOUSE_INSERT;
3326 else if (State & CMDLINE)
3327 checkfor = MOUSE_COMMAND;
3328 else if (State == CONFIRM || State == EXTERNCMD)
3329 checkfor = ' '; /* don't use mouse for ":confirm" or ":!cmd" */
3330 else
3331 checkfor = MOUSE_NORMAL; /* assume normal mode */
3332
3333 if (mouse_has(checkfor))
3334 mch_setmouse(TRUE);
3335 else
3336 mch_setmouse(FALSE);
3337# endif
3338}
3339
3340/*
3341 * Return TRUE if
3342 * - "c" is in 'mouse', or
3343 * - 'a' is in 'mouse' and "c" is in MOUSE_A, or
3344 * - the current buffer is a help file and 'h' is in 'mouse' and we are in a
3345 * normal editing mode (not at hit-return message).
3346 */
3347 int
3348mouse_has(c)
3349 int c;
3350{
3351 char_u *p;
3352
3353 for (p = p_mouse; *p; ++p)
3354 switch (*p)
3355 {
3356 case 'a': if (vim_strchr((char_u *)MOUSE_A, c) != NULL)
3357 return TRUE;
3358 break;
3359 case MOUSE_HELP: if (c != MOUSE_RETURN && curbuf->b_help)
3360 return TRUE;
3361 break;
3362 default: if (c == *p) return TRUE; break;
3363 }
3364 return FALSE;
3365}
3366
3367/*
3368 * Return TRUE when 'mousemodel' is set to "popup" or "popup_setpos".
3369 */
3370 int
3371mouse_model_popup()
3372{
3373 return (p_mousem[0] == 'p');
3374}
3375#endif
3376
3377/*
3378 * By outputting the 'cursor very visible' termcap code, for some windowed
3379 * terminals this makes the screen scrolled to the correct position.
3380 * Used when starting Vim or returning from a shell.
3381 */
3382 void
3383scroll_start()
3384{
3385 if (*T_VS != NUL)
3386 {
3387 out_str(T_VS);
3388 out_str(T_VE);
3389 screen_start(); /* don't know where cursor is now */
3390 }
3391}
3392
3393static int cursor_is_off = FALSE;
3394
3395/*
3396 * Enable the cursor.
3397 */
3398 void
3399cursor_on()
3400{
3401 if (cursor_is_off)
3402 {
3403 out_str(T_VE);
3404 cursor_is_off = FALSE;
3405 }
3406}
3407
3408/*
3409 * Disable the cursor.
3410 */
3411 void
3412cursor_off()
3413{
3414 if (full_screen)
3415 {
3416 if (!cursor_is_off)
3417 out_str(T_VI); /* disable cursor */
3418 cursor_is_off = TRUE;
3419 }
3420}
3421
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00003422#if defined(CURSOR_SHAPE) || defined(PROTO)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003423/*
Bram Moolenaar293ee4d2004-12-09 21:34:53 +00003424 * Set cursor shape to match Insert mode.
3425 */
3426 void
3427term_cursor_shape()
3428{
3429 static int showing_insert_mode = MAYBE;
3430
3431 if (!full_screen || *T_CSI == NUL || *T_CEI == NUL)
3432 return;
3433
3434 if (State & INSERT)
3435 {
3436 if (showing_insert_mode != TRUE)
3437 out_str(T_CSI); /* disable cursor */
3438 showing_insert_mode = TRUE;
3439 }
3440 else
3441 {
3442 if (showing_insert_mode != FALSE)
3443 out_str(T_CEI); /* disable cursor */
3444 showing_insert_mode = FALSE;
3445 }
3446}
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00003447#endif
Bram Moolenaar293ee4d2004-12-09 21:34:53 +00003448
3449/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00003450 * Set scrolling region for window 'wp'.
3451 * The region starts 'off' lines from the start of the window.
3452 * Also set the vertical scroll region for a vertically split window. Always
3453 * the full width of the window, excluding the vertical separator.
3454 */
3455 void
3456scroll_region_set(wp, off)
3457 win_T *wp;
3458 int off;
3459{
3460 OUT_STR(tgoto((char *)T_CS, W_WINROW(wp) + wp->w_height - 1,
3461 W_WINROW(wp) + off));
3462#ifdef FEAT_VERTSPLIT
3463 if (*T_CSV != NUL && wp->w_width != Columns)
3464 OUT_STR(tgoto((char *)T_CSV, W_WINCOL(wp) + wp->w_width - 1,
3465 W_WINCOL(wp)));
3466#endif
3467 screen_start(); /* don't know where cursor is now */
3468}
3469
3470/*
3471 * Reset scrolling region to the whole screen.
3472 */
3473 void
3474scroll_region_reset()
3475{
3476 OUT_STR(tgoto((char *)T_CS, (int)Rows - 1, 0));
3477#ifdef FEAT_VERTSPLIT
3478 if (*T_CSV != NUL)
3479 OUT_STR(tgoto((char *)T_CSV, (int)Columns - 1, 0));
3480#endif
3481 screen_start(); /* don't know where cursor is now */
3482}
3483
3484
3485/*
3486 * List of terminal codes that are currently recognized.
3487 */
3488
3489struct termcode
3490{
3491 char_u name[2]; /* termcap name of entry */
3492 char_u *code; /* terminal code (in allocated memory) */
3493 int len; /* STRLEN(code) */
Bram Moolenaar19a09a12005-03-04 23:39:37 +00003494 int modlen; /* length of part before ";*~". */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003495} *termcodes = NULL;
3496
3497static int tc_max_len = 0; /* number of entries that termcodes[] can hold */
3498static int tc_len = 0; /* current number of entries in termcodes[] */
3499
3500 void
3501clear_termcodes()
3502{
3503 while (tc_len > 0)
3504 vim_free(termcodes[--tc_len].code);
3505 vim_free(termcodes);
3506 termcodes = NULL;
3507 tc_max_len = 0;
3508
3509#ifdef HAVE_TGETENT
3510 BC = (char *)empty_option;
3511 UP = (char *)empty_option;
3512 PC = NUL; /* set pad character to NUL */
3513 ospeed = 0;
3514#endif
3515
3516 need_gather = TRUE; /* need to fill termleader[] */
3517}
3518
3519/*
3520 * Add a new entry to the list of terminal codes.
3521 * The list is kept alphabetical for ":set termcap"
3522 */
3523 void
3524add_termcode(name, string, use_8bit)
3525 char_u *name;
3526 char_u *string;
3527 int use_8bit; /* replace 7-bit control by 8-bit one */
3528{
3529 struct termcode *new_tc;
3530 int i, j;
3531 char_u *s;
Bram Moolenaar19a09a12005-03-04 23:39:37 +00003532 int len;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003533
3534 if (string == NULL || *string == NUL)
3535 {
3536 del_termcode(name);
3537 return;
3538 }
3539
3540 s = vim_strsave(string);
3541 if (s == NULL)
3542 return;
3543
3544 /* Change leading <Esc>[ to CSI, change <Esc>O to <M-O>. */
3545 if (use_8bit && term_7to8bit(string) != 0)
3546 {
3547 mch_memmove(s, s + 1, STRLEN(s));
3548 s[0] = term_7to8bit(string);
3549 }
Bram Moolenaar19a09a12005-03-04 23:39:37 +00003550 len = (int)STRLEN(s);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003551
3552 need_gather = TRUE; /* need to fill termleader[] */
3553
3554 /*
3555 * need to make space for more entries
3556 */
3557 if (tc_len == tc_max_len)
3558 {
3559 tc_max_len += 20;
3560 new_tc = (struct termcode *)alloc(
3561 (unsigned)(tc_max_len * sizeof(struct termcode)));
3562 if (new_tc == NULL)
3563 {
3564 tc_max_len -= 20;
3565 return;
3566 }
3567 for (i = 0; i < tc_len; ++i)
3568 new_tc[i] = termcodes[i];
3569 vim_free(termcodes);
3570 termcodes = new_tc;
3571 }
3572
3573 /*
3574 * Look for existing entry with the same name, it is replaced.
3575 * Look for an existing entry that is alphabetical higher, the new entry
3576 * is inserted in front of it.
3577 */
3578 for (i = 0; i < tc_len; ++i)
3579 {
3580 if (termcodes[i].name[0] < name[0])
3581 continue;
3582 if (termcodes[i].name[0] == name[0])
3583 {
3584 if (termcodes[i].name[1] < name[1])
3585 continue;
3586 /*
3587 * Exact match: Replace old code.
Bram Moolenaar19a09a12005-03-04 23:39:37 +00003588 * But don't replace ESC[123;*X with another.
Bram Moolenaar071d4272004-06-13 20:20:40 +00003589 */
3590 if (termcodes[i].name[1] == name[1])
3591 {
Bram Moolenaar19a09a12005-03-04 23:39:37 +00003592 if (termcodes[i].len >= 4
3593 && STRNCMP(termcodes[i].code + termcodes[i].len - 3,
3594 ";*", 2) == 0)
3595 {
3596 /* if they are equal but for the ";*" don't add it */
3597 if (len == termcodes[i].len - 2
3598 && STRNCMP(s, termcodes[i].code, len - 1) == 0
3599 && s[len - 1] == termcodes[i].code[len + 1])
3600 {
3601 vim_free(s);
3602 return;
3603 }
3604 }
3605 else
3606 {
3607 vim_free(termcodes[i].code);
3608 --tc_len;
3609 break;
3610 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003611 }
3612 }
3613 /*
3614 * Found alphabetical larger entry, move rest to insert new entry
3615 */
3616 for (j = tc_len; j > i; --j)
3617 termcodes[j] = termcodes[j - 1];
3618 break;
3619 }
3620
3621 termcodes[i].name[0] = name[0];
3622 termcodes[i].name[1] = name[1];
3623 termcodes[i].code = s;
Bram Moolenaar19a09a12005-03-04 23:39:37 +00003624 termcodes[i].len = len;
3625 /* recognize special code like "ESC[42;*X" that accepts modifiers */
3626 if (len >= 5 && STRNCMP(s + len - 3, ";*", 2) == 0)
3627 termcodes[i].modlen = len - 3;
3628 else
3629 termcodes[i].modlen = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003630 ++tc_len;
3631}
3632
3633 char_u *
3634find_termcode(name)
3635 char_u *name;
3636{
3637 int i;
3638
3639 for (i = 0; i < tc_len; ++i)
3640 if (termcodes[i].name[0] == name[0] && termcodes[i].name[1] == name[1])
3641 return termcodes[i].code;
3642 return NULL;
3643}
3644
3645#if defined(FEAT_CMDL_COMPL) || defined(PROTO)
3646 char_u *
3647get_termcode(i)
3648 int i;
3649{
3650 if (i >= tc_len)
3651 return NULL;
3652 return &termcodes[i].name[0];
3653}
3654#endif
3655
3656 void
3657del_termcode(name)
3658 char_u *name;
3659{
3660 int i;
3661
3662 if (termcodes == NULL) /* nothing there yet */
3663 return;
3664
3665 need_gather = TRUE; /* need to fill termleader[] */
3666
3667 for (i = 0; i < tc_len; ++i)
3668 if (termcodes[i].name[0] == name[0] && termcodes[i].name[1] == name[1])
3669 {
3670 del_termcode_idx(i);
3671 return;
3672 }
3673 /* not found. Give error message? */
3674}
3675
3676 static void
3677del_termcode_idx(idx)
3678 int idx;
3679{
3680 int i;
3681
3682 vim_free(termcodes[idx].code);
3683 --tc_len;
3684 for (i = idx; i < tc_len; ++i)
3685 termcodes[i] = termcodes[i + 1];
3686}
3687
3688#ifdef FEAT_TERMRESPONSE
3689/*
3690 * Called when detected that the terminal sends 8-bit codes.
3691 * Convert all 7-bit codes to their 8-bit equivalent.
3692 */
3693 static void
3694switch_to_8bit()
3695{
3696 int i;
3697 int c;
3698
3699 /* Only need to do something when not already using 8-bit codes. */
3700 if (!term_is_8bit(T_NAME))
3701 {
3702 for (i = 0; i < tc_len; ++i)
3703 {
3704 c = term_7to8bit(termcodes[i].code);
3705 if (c != 0)
3706 {
3707 mch_memmove(termcodes[i].code + 1, termcodes[i].code + 2,
3708 STRLEN(termcodes[i].code + 1));
3709 termcodes[i].code[0] = c;
3710 }
3711 }
3712 need_gather = TRUE; /* need to fill termleader[] */
3713 }
3714 detected_8bit = TRUE;
3715}
3716#endif
3717
3718#ifdef CHECK_DOUBLE_CLICK
3719static linenr_T orig_topline = 0;
3720# ifdef FEAT_DIFF
3721static int orig_topfill = 0;
3722# endif
3723#endif
3724#if (defined(FEAT_WINDOWS) && defined(CHECK_DOUBLE_CLICK)) || defined(PROTO)
3725/*
3726 * Checking for double clicks ourselves.
3727 * "orig_topline" is used to avoid detecting a double-click when the window
3728 * contents scrolled (e.g., when 'scrolloff' is non-zero).
3729 */
3730/*
3731 * Set orig_topline. Used when jumping to another window, so that a double
3732 * click still works.
3733 */
3734 void
3735set_mouse_topline(wp)
3736 win_T *wp;
3737{
3738 orig_topline = wp->w_topline;
3739# ifdef FEAT_DIFF
3740 orig_topfill = wp->w_topfill;
3741# endif
3742}
3743#endif
3744
3745/*
3746 * Check if typebuf.tb_buf[] contains a terminal key code.
3747 * Check from typebuf.tb_buf[typebuf.tb_off] to typebuf.tb_buf[typebuf.tb_off
3748 * + max_offset].
3749 * Return 0 for no match, -1 for partial match, > 0 for full match.
3750 * With a match, the match is removed, the replacement code is inserted in
3751 * typebuf.tb_buf[] and the number of characters in typebuf.tb_buf[] is
3752 * returned.
3753 * When "buf" is not NULL, it is used instead of typebuf.tb_buf[]. "buflen" is
3754 * then the length of the string in buf[].
3755 */
3756 int
3757check_termcode(max_offset, buf, buflen)
3758 int max_offset;
3759 char_u *buf;
3760 int buflen;
3761{
3762 char_u *tp;
3763 char_u *p;
3764 int slen = 0; /* init for GCC */
3765 int len;
3766 int offset;
3767 char_u key_name[2];
3768 int new_slen;
3769 int extra;
3770 char_u string[MAX_KEY_CODE_LEN + 1];
3771 int i, j;
3772 int idx = 0;
3773#ifdef FEAT_MOUSE
3774# if !defined(UNIX) || defined(FEAT_MOUSE_XTERM) || defined(FEAT_GUI)
3775 char_u bytes[6];
3776 int num_bytes;
3777# endif
3778 int mouse_code = 0; /* init for GCC */
3779 int modifiers;
3780 int is_click, is_drag;
3781 int wheel_code = 0;
3782 int current_button;
3783 static int held_button = MOUSE_RELEASE;
3784 static int orig_num_clicks = 1;
3785 static int orig_mouse_code = 0x0;
3786# ifdef CHECK_DOUBLE_CLICK
3787 static int orig_mouse_col = 0;
3788 static int orig_mouse_row = 0;
3789 static struct timeval orig_mouse_time = {0, 0};
3790 /* time of previous mouse click */
3791 struct timeval mouse_time; /* time of current mouse click */
3792 long timediff; /* elapsed time in msec */
3793# endif
3794#endif
3795 int cpo_koffset;
3796#ifdef FEAT_MOUSE_GPM
3797 extern int gpm_flag; /* gpm library variable */
3798#endif
3799
3800 cpo_koffset = (vim_strchr(p_cpo, CPO_KOFFSET) != NULL);
3801
3802 /*
3803 * Speed up the checks for terminal codes by gathering all first bytes
3804 * used in termleader[]. Often this is just a single <Esc>.
3805 */
3806 if (need_gather)
3807 gather_termleader();
3808
3809 /*
3810 * Check at several positions in typebuf.tb_buf[], to catch something like
3811 * "x<Up>" that can be mapped. Stop at max_offset, because characters
3812 * after that cannot be used for mapping, and with @r commands
3813 * typebuf.tb_buf[]
3814 * can become very long.
3815 * This is used often, KEEP IT FAST!
3816 */
3817 for (offset = 0; offset < max_offset; ++offset)
3818 {
3819 if (buf == NULL)
3820 {
3821 if (offset >= typebuf.tb_len)
3822 break;
3823 tp = typebuf.tb_buf + typebuf.tb_off + offset;
3824 len = typebuf.tb_len - offset; /* length of the input */
3825 }
3826 else
3827 {
3828 if (offset >= buflen)
3829 break;
3830 tp = buf + offset;
3831 len = buflen - offset;
3832 }
3833
3834 /*
3835 * Don't check characters after K_SPECIAL, those are already
3836 * translated terminal chars (avoid translating ~@^Hx).
3837 */
3838 if (*tp == K_SPECIAL)
3839 {
3840 offset += 2; /* there are always 2 extra characters */
3841 continue;
3842 }
3843
3844 /*
3845 * Skip this position if the character does not appear as the first
3846 * character in term_strings. This speeds up a lot, since most
3847 * termcodes start with the same character (ESC or CSI).
3848 */
3849 i = *tp;
3850 for (p = termleader; *p && *p != i; ++p)
3851 ;
3852 if (*p == NUL)
3853 continue;
3854
3855 /*
3856 * Skip this position if p_ek is not set and tp[0] is an ESC and we
3857 * are in Insert mode.
3858 */
3859 if (*tp == ESC && !p_ek && (State & INSERT))
3860 continue;
3861
3862 new_slen = 0; /* Length of what will replace the termcode */
3863 key_name[0] = NUL; /* no key name found yet */
3864
3865#ifdef FEAT_GUI
3866 if (gui.in_use)
3867 {
3868 /*
3869 * GUI special key codes are all of the form [CSI xx].
3870 */
3871 if (*tp == CSI) /* Special key from GUI */
3872 {
3873 if (len < 3)
3874 return -1; /* Shouldn't happen */
3875 slen = 3;
3876 key_name[0] = tp[1];
3877 key_name[1] = tp[2];
3878 }
3879 }
3880 else
3881#endif /* FEAT_GUI */
3882 {
3883 for (idx = 0; idx < tc_len; ++idx)
3884 {
3885 /*
3886 * Ignore the entry if we are not at the start of
3887 * typebuf.tb_buf[]
3888 * and there are not enough characters to make a match.
3889 * But only when the 'K' flag is in 'cpoptions'.
3890 */
3891 slen = termcodes[idx].len;
3892 if (cpo_koffset && offset && len < slen)
3893 continue;
3894 if (STRNCMP(termcodes[idx].code, tp,
3895 (size_t)(slen > len ? len : slen)) == 0)
3896 {
3897 if (len < slen) /* got a partial sequence */
3898 return -1; /* need to get more chars */
3899
3900 /*
3901 * When found a keypad key, check if there is another key
3902 * that matches and use that one. This makes <Home> to be
3903 * found instead of <kHome> when they produce the same
3904 * key code.
3905 */
3906 if (termcodes[idx].name[0] == 'K'
3907 && VIM_ISDIGIT(termcodes[idx].name[1]))
3908 {
3909 for (j = idx + 1; j < tc_len; ++j)
3910 if (termcodes[j].len == slen &&
3911 STRNCMP(termcodes[idx].code,
3912 termcodes[j].code, slen) == 0)
3913 {
3914 idx = j;
3915 break;
3916 }
3917 }
3918
3919 key_name[0] = termcodes[idx].name[0];
3920 key_name[1] = termcodes[idx].name[1];
3921
3922 break;
3923 }
Bram Moolenaar19a09a12005-03-04 23:39:37 +00003924
3925 /*
3926 * Check for code with modifier, like xterm uses:
3927 * ESC[123;2X (shift) ESC[123;3X (alt), etc.
3928 */
3929 if (termcodes[idx].modlen > 0)
3930 {
3931 slen = termcodes[idx].modlen;
3932 if (cpo_koffset && offset && len < slen)
3933 continue;
3934 if (STRNCMP(termcodes[idx].code, tp,
3935 (size_t)(slen > len ? len : slen)) == 0)
3936 {
3937 int n;
3938 int mod;
3939
3940 if (len <= slen) /* got a partial sequence */
3941 return -1; /* need to get more chars */
3942
3943 if (tp[slen] == termcodes[idx].code[slen + 2])
3944 ++slen; /* no modifiers */
3945 else if (tp[slen] != ';')
3946 continue; /* no match */
3947 else
3948 {
3949 /* Skip over the digits, the final char must
3950 * follow. */
3951 for (j = slen + 1; j < len && isdigit(tp[j]); ++j)
3952 ;
3953 ++j;
3954 if (len < j) /* got a partial sequence */
3955 return -1; /* need to get more chars */
3956 if (tp[j - 1] != termcodes[idx].code[slen + 2])
3957 continue;
3958
3959 /* Match! Convert modifier bits. */
3960 n = atoi((char *)tp + slen + 1) - 1;
3961 mod = 0x0;
3962 if (n & 1)
3963 mod |= MOD_MASK_SHIFT;
3964 if (n & 2)
3965 mod |= MOD_MASK_ALT;
3966 if (n & 4)
3967 mod |= MOD_MASK_CTRL;
3968 if (n & 8)
3969 mod |= MOD_MASK_META;
3970
3971 /* Add the modifier codes to our string */
3972 if (mod != 0)
3973 {
3974 string[new_slen++] = K_SPECIAL;
3975 string[new_slen++] = (int)KS_MODIFIER;
3976 string[new_slen++] = mod;
3977 }
3978
3979 slen = j;
3980 }
3981 key_name[0] = termcodes[idx].name[0];
3982 key_name[1] = termcodes[idx].name[1];
3983
3984 break;
3985 }
3986 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003987 }
3988 }
3989
3990#ifdef FEAT_TERMRESPONSE
3991 if (key_name[0] == NUL)
3992 {
3993 /* Check for xterm version string: "<Esc>[>{x};{vers};{y}c". Also
3994 * eat other possible responses to t_RV, rxvt returns
3995 * "<Esc>[?1;2c". Also accept CSI instead of <Esc>[. */
3996 if (*T_CRV != NUL && ((tp[0] == ESC && tp[1] == '[' && len >= 3)
3997 || (tp[0] == CSI && len >= 2)))
3998 {
3999 j = 0;
4000 extra = 0;
4001 for (i = 2 + (tp[0] != CSI);
4002 i < len && (VIM_ISDIGIT(tp[i])
4003 || tp[i] == ';' || tp[i] == '.'); ++i)
4004 if (tp[i] == ';' && ++j == 1)
4005 extra = atoi((char *)tp + i + 1);
4006 if (i == len)
4007 return -1; /* not enough characters */
4008
4009 /* eat it when at least one digit and ending in 'c' */
4010 if (i > 2 + (tp[0] != CSI) && tp[i] == 'c')
4011 {
4012 crv_status = CRV_GOT;
4013
4014 /* If this code starts with CSI, you can bet that the
4015 * terminal uses 8-bit codes. */
4016 if (tp[0] == CSI)
4017 switch_to_8bit();
4018
4019 /* rxvt sends its version number: "20703" is 2.7.3.
4020 * Ignore it for when the user has set 'term' to xterm,
4021 * even though it's an rxvt. */
4022 if (extra > 20000)
4023 extra = 0;
4024
4025 if (tp[1 + (tp[0] != CSI)] == '>' && j == 2)
4026 {
4027 /* if xterm version >= 95 use mouse dragging */
4028 if (extra >= 95)
4029 set_option_value((char_u *)"ttym", 0L,
4030 (char_u *)"xterm2", 0);
4031 /* if xterm version >= 141 try to get termcap codes */
4032 if (extra >= 141)
4033 {
4034 check_for_codes = TRUE;
4035 need_gather = TRUE;
4036 req_codes_from_term();
4037 }
4038 }
4039# ifdef FEAT_EVAL
4040 set_vim_var_string(VV_TERMRESPONSE, tp, i + 1);
4041# endif
4042# ifdef FEAT_AUTOCMD
4043 apply_autocmds(EVENT_TERMRESPONSE,
4044 NULL, NULL, FALSE, curbuf);
4045# endif
4046 key_name[0] = (int)KS_EXTRA;
4047 key_name[1] = (int)KE_IGNORE;
4048 slen = i + 1;
4049 }
4050 }
4051
4052 /* Check for '<Esc>P1+r<hex bytes><Esc>\'. A "0" instead of the
4053 * "1" means an invalid request. */
4054 else if (check_for_codes
4055 && ((tp[0] == ESC && tp[1] == 'P' && len >= 2)
4056 || tp[0] == DCS))
4057 {
4058 j = 1 + (tp[0] != DCS);
4059 for (i = j; i < len; ++i)
4060 if ((tp[i] == ESC && tp[i + 1] == '\\' && i + 1 < len)
4061 || tp[i] == STERM)
4062 {
4063 if (i - j >= 3 && tp[j + 1] == '+' && tp[j + 2] == 'r')
4064 got_code_from_term(tp + j, i);
4065 key_name[0] = (int)KS_EXTRA;
4066 key_name[1] = (int)KE_IGNORE;
4067 slen = i + 1 + (tp[i] == ESC);
4068 break;
4069 }
4070
4071 if (i == len)
4072 return -1; /* not enough characters */
4073 }
4074 }
4075#endif
4076
4077 if (key_name[0] == NUL)
4078 continue; /* No match at this position, try next one */
4079
4080 /* We only get here when we have a complete termcode match */
4081
4082#ifdef FEAT_MOUSE
4083# ifdef FEAT_GUI
4084 /*
4085 * Only in the GUI: Fetch the pointer coordinates of the scroll event
4086 * so that we know which window to scroll later.
4087 */
4088 if (gui.in_use
4089 && key_name[0] == (int)KS_EXTRA
4090 && (key_name[1] == (int)KE_X1MOUSE
4091 || key_name[1] == (int)KE_X2MOUSE
4092 || key_name[1] == (int)KE_MOUSEDOWN
4093 || key_name[1] == (int)KE_MOUSEUP))
4094 {
4095 num_bytes = get_bytes_from_buf(tp + slen, bytes, 4);
4096 if (num_bytes == -1) /* not enough coordinates */
4097 return -1;
4098 mouse_col = 128 * (bytes[0] - ' ' - 1) + bytes[1] - ' ' - 1;
4099 mouse_row = 128 * (bytes[2] - ' ' - 1) + bytes[3] - ' ' - 1;
4100 slen += num_bytes;
4101 }
4102 else
4103# endif
4104 /*
4105 * If it is a mouse click, get the coordinates.
4106 */
4107 if (key_name[0] == (int)KS_MOUSE
4108# ifdef FEAT_MOUSE_JSB
4109 || key_name[0] == (int)KS_JSBTERM_MOUSE
4110# endif
4111# ifdef FEAT_MOUSE_NET
4112 || key_name[0] == (int)KS_NETTERM_MOUSE
4113# endif
4114# ifdef FEAT_MOUSE_DEC
4115 || key_name[0] == (int)KS_DEC_MOUSE
4116# endif
4117# ifdef FEAT_MOUSE_PTERM
4118 || key_name[0] == (int)KS_PTERM_MOUSE
4119# endif
4120 )
4121 {
4122 is_click = is_drag = FALSE;
4123
4124# if !defined(UNIX) || defined(FEAT_MOUSE_XTERM) || defined(FEAT_GUI)
4125 if (key_name[0] == (int)KS_MOUSE)
4126 {
4127 /*
4128 * For xterm and MSDOS we get "<t_mouse>scr", where
4129 * s == encoded button state:
4130 * 0x20 = left button down
4131 * 0x21 = middle button down
4132 * 0x22 = right button down
4133 * 0x23 = any button release
4134 * 0x60 = button 4 down (scroll wheel down)
4135 * 0x61 = button 5 down (scroll wheel up)
4136 * add 0x04 for SHIFT
4137 * add 0x08 for ALT
4138 * add 0x10 for CTRL
4139 * add 0x20 for mouse drag (0x40 is drag with left button)
4140 * c == column + ' ' + 1 == column + 33
4141 * r == row + ' ' + 1 == row + 33
4142 *
4143 * The coordinates are passed on through global variables.
4144 * Ugly, but this avoids trouble with mouse clicks at an
4145 * unexpected moment and allows for mapping them.
4146 */
4147 for (;;)
4148 {
4149#ifdef FEAT_GUI
4150 if (gui.in_use)
4151 {
4152 /* GUI uses more bits for columns > 223 */
4153 num_bytes = get_bytes_from_buf(tp + slen, bytes, 5);
4154 if (num_bytes == -1) /* not enough coordinates */
4155 return -1;
4156 mouse_code = bytes[0];
4157 mouse_col = 128 * (bytes[1] - ' ' - 1)
4158 + bytes[2] - ' ' - 1;
4159 mouse_row = 128 * (bytes[3] - ' ' - 1)
4160 + bytes[4] - ' ' - 1;
4161 }
4162 else
4163#endif
4164 {
4165 num_bytes = get_bytes_from_buf(tp + slen, bytes, 3);
4166 if (num_bytes == -1) /* not enough coordinates */
4167 return -1;
4168 mouse_code = bytes[0];
4169 mouse_col = bytes[1] - ' ' - 1;
4170 mouse_row = bytes[2] - ' ' - 1;
4171 }
4172 slen += num_bytes;
4173
4174 /* If the following bytes is also a mouse code and it has
4175 * the same code, dump this one and get the next. This
4176 * makes dragging a whole lot faster. */
4177#ifdef FEAT_GUI
4178 if (gui.in_use)
4179 j = 3;
4180 else
4181#endif
4182 j = termcodes[idx].len;
4183 if (STRNCMP(tp, tp + slen, (size_t)j) == 0
4184 && tp[slen + j] == mouse_code
4185 && tp[slen + j + 1] != NUL
4186 && tp[slen + j + 2] != NUL
4187#ifdef FEAT_GUI
4188 && (!gui.in_use
4189 || (tp[slen + j + 3] != NUL
4190 && tp[slen + j + 4] != NUL))
4191#endif
4192 )
4193 slen += j;
4194 else
4195 break;
4196 }
4197
4198# if !defined(MSWIN) && !defined(MSDOS)
4199 /*
4200 * Handle mouse events.
4201 * Recognize the xterm mouse wheel, but not in the GUI, the
4202 * Linux console with GPM and the MS-DOS or Win32 console
4203 * (multi-clicks use >= 0x60).
4204 */
4205 if (mouse_code >= MOUSEWHEEL_LOW
4206# ifdef FEAT_GUI
4207 && !gui.in_use
4208# endif
4209# ifdef FEAT_MOUSE_GPM
4210 && gpm_flag == 0
4211# endif
4212 )
4213 {
4214 /* Keep the mouse_code before it's changed, so that we
4215 * remember that it was a mouse wheel click. */
4216 wheel_code = mouse_code;
4217 }
4218# ifdef FEAT_MOUSE_XTERM
4219 else if (held_button == MOUSE_RELEASE
4220# ifdef FEAT_GUI
4221 && !gui.in_use
4222# endif
4223 && (mouse_code == 0x23 || mouse_code == 0x24))
4224 {
4225 /* Apparently used by rxvt scroll wheel. */
4226 wheel_code = mouse_code - 0x23 + MOUSEWHEEL_LOW;
4227 }
4228# endif
4229
4230# if defined(UNIX) && defined(FEAT_MOUSE_TTY)
4231 else if (use_xterm_mouse() > 1)
4232 {
4233 if (mouse_code & MOUSE_DRAG_XTERM)
4234 mouse_code |= MOUSE_DRAG;
4235 }
4236# endif
4237# ifdef FEAT_XCLIPBOARD
4238 else if (!(mouse_code & MOUSE_DRAG & ~MOUSE_CLICK_MASK))
4239 {
4240 if ((mouse_code & MOUSE_RELEASE) == MOUSE_RELEASE)
4241 stop_xterm_trace();
4242 else
4243 start_xterm_trace(mouse_code);
4244 }
4245# endif
4246# endif
4247 }
4248# endif /* !UNIX || FEAT_MOUSE_XTERM */
4249# ifdef FEAT_MOUSE_NET
4250 if (key_name[0] == (int)KS_NETTERM_MOUSE)
4251 {
4252 int mc, mr;
4253
4254 /* expect a rather limited sequence like: balancing {
4255 * \033}6,45\r
4256 * '6' is the row, 45 is the column
4257 */
4258 p = tp + slen;
4259 mr = getdigits(&p);
4260 if (*p++ != ',')
4261 return -1;
4262 mc = getdigits(&p);
4263 if (*p++ != '\r')
4264 return -1;
4265
4266 mouse_col = mc - 1;
4267 mouse_row = mr - 1;
4268 mouse_code = MOUSE_LEFT;
4269 slen += (int)(p - (tp + slen));
4270 }
4271# endif /* FEAT_MOUSE_NET */
4272# ifdef FEAT_MOUSE_JSB
4273 if (key_name[0] == (int)KS_JSBTERM_MOUSE)
4274 {
4275 int mult, val, iter, button, status;
4276
4277 /* JSBTERM Input Model
4278 * \033[0~zw uniq escape sequence
4279 * (L-x) Left button pressed - not pressed x not reporting
4280 * (M-x) Middle button pressed - not pressed x not reporting
4281 * (R-x) Right button pressed - not pressed x not reporting
4282 * (SDmdu) Single , Double click, m mouse move d button down
4283 * u button up
4284 * ### X cursor position padded to 3 digits
4285 * ### Y cursor position padded to 3 digits
4286 * (s-x) SHIFT key pressed - not pressed x not reporting
4287 * (c-x) CTRL key pressed - not pressed x not reporting
4288 * \033\\ terminateing sequence
4289 */
4290
4291 p = tp + slen;
4292 button = mouse_code = 0;
4293 switch (*p++)
4294 {
4295 case 'L': button = 1; break;
4296 case '-': break;
4297 case 'x': break; /* ignore sequence */
4298 default: return -1; /* Unknown Result */
4299 }
4300 switch (*p++)
4301 {
4302 case 'M': button |= 2; break;
4303 case '-': break;
4304 case 'x': break; /* ignore sequence */
4305 default: return -1; /* Unknown Result */
4306 }
4307 switch (*p++)
4308 {
4309 case 'R': button |= 4; break;
4310 case '-': break;
4311 case 'x': break; /* ignore sequence */
4312 default: return -1; /* Unknown Result */
4313 }
4314 status = *p++;
4315 for (val = 0, mult = 100, iter = 0; iter < 3; iter++,
4316 mult /= 10, p++)
4317 if (*p >= '0' && *p <= '9')
4318 val += (*p - '0') * mult;
4319 else
4320 return -1;
4321 mouse_col = val;
4322 for (val = 0, mult = 100, iter = 0; iter < 3; iter++,
4323 mult /= 10, p++)
4324 if (*p >= '0' && *p <= '9')
4325 val += (*p - '0') * mult;
4326 else
4327 return -1;
4328 mouse_row = val;
4329 switch (*p++)
4330 {
4331 case 's': button |= 8; break; /* SHIFT key Pressed */
4332 case '-': break; /* Not Pressed */
4333 case 'x': break; /* Not Reporting */
4334 default: return -1; /* Unknown Result */
4335 }
4336 switch (*p++)
4337 {
4338 case 'c': button |= 16; break; /* CTRL key Pressed */
4339 case '-': break; /* Not Pressed */
4340 case 'x': break; /* Not Reporting */
4341 default: return -1; /* Unknown Result */
4342 }
4343 if (*p++ != '\033')
4344 return -1;
4345 if (*p++ != '\\')
4346 return -1;
4347 switch (status)
4348 {
4349 case 'D': /* Double Click */
4350 case 'S': /* Single Click */
4351 if (button & 1) mouse_code |= MOUSE_LEFT;
4352 if (button & 2) mouse_code |= MOUSE_MIDDLE;
4353 if (button & 4) mouse_code |= MOUSE_RIGHT;
4354 if (button & 8) mouse_code |= MOUSE_SHIFT;
4355 if (button & 16) mouse_code |= MOUSE_CTRL;
4356 break;
4357 case 'm': /* Mouse move */
4358 if (button & 1) mouse_code |= MOUSE_LEFT;
4359 if (button & 2) mouse_code |= MOUSE_MIDDLE;
4360 if (button & 4) mouse_code |= MOUSE_RIGHT;
4361 if (button & 8) mouse_code |= MOUSE_SHIFT;
4362 if (button & 16) mouse_code |= MOUSE_CTRL;
4363 if ((button & 7) != 0)
4364 {
4365 held_button = mouse_code;
4366 mouse_code |= MOUSE_DRAG;
4367 }
4368 is_drag = TRUE;
4369 showmode();
4370 break;
4371 case 'd': /* Button Down */
4372 if (button & 1) mouse_code |= MOUSE_LEFT;
4373 if (button & 2) mouse_code |= MOUSE_MIDDLE;
4374 if (button & 4) mouse_code |= MOUSE_RIGHT;
4375 if (button & 8) mouse_code |= MOUSE_SHIFT;
4376 if (button & 16) mouse_code |= MOUSE_CTRL;
4377 break;
4378 case 'u': /* Button Up */
4379 if (button & 1)
4380 mouse_code |= MOUSE_LEFT | MOUSE_RELEASE;
4381 if (button & 2)
4382 mouse_code |= MOUSE_MIDDLE | MOUSE_RELEASE;
4383 if (button & 4)
4384 mouse_code |= MOUSE_RIGHT | MOUSE_RELEASE;
4385 if (button & 8)
4386 mouse_code |= MOUSE_SHIFT;
4387 if (button & 16)
4388 mouse_code |= MOUSE_CTRL;
4389 break;
4390 default: return -1; /* Unknown Result */
4391 }
4392
4393 slen += (p - (tp + slen));
4394 }
4395# endif /* FEAT_MOUSE_JSB */
4396# ifdef FEAT_MOUSE_DEC
4397 if (key_name[0] == (int)KS_DEC_MOUSE)
4398 {
4399 /* The DEC Locator Input Model
4400 * Netterm delivers the code sequence:
4401 * \033[2;4;24;80&w (left button down)
4402 * \033[3;0;24;80&w (left button up)
4403 * \033[6;1;24;80&w (right button down)
4404 * \033[7;0;24;80&w (right button up)
4405 * CSI Pe ; Pb ; Pr ; Pc ; Pp & w
4406 * Pe is the event code
4407 * Pb is the button code
4408 * Pr is the row coordinate
4409 * Pc is the column coordinate
4410 * Pp is the third coordinate (page number)
4411 * Pe, the event code indicates what event caused this report
4412 * The following event codes are defined:
4413 * 0 - request, the terminal received an explicit request
4414 * for a locator report, but the locator is unavailable
4415 * 1 - request, the terminal received an explicit request
4416 * for a locator report
4417 * 2 - left button down
4418 * 3 - left button up
4419 * 4 - middle button down
4420 * 5 - middle button up
4421 * 6 - right button down
4422 * 7 - right button up
4423 * 8 - fourth button down
4424 * 9 - fourth button up
4425 * 10 - locator outside filter rectangle
4426 * Pb, the button code, ASCII decimal 0-15 indicating which
4427 * buttons are down if any. The state of the four buttons
4428 * on the locator correspond to the low four bits of the
4429 * decimal value,
4430 * "1" means button depressed
4431 * 0 - no buttons down,
4432 * 1 - right,
4433 * 2 - middle,
4434 * 4 - left,
4435 * 8 - fourth
4436 * Pr is the row coordinate of the locator position in the page,
4437 * encoded as an ASCII decimal value.
4438 * If Pr is omitted, the locator position is undefined
4439 * (outside the terminal window for example).
4440 * Pc is the column coordinate of the locator position in the
4441 * page, encoded as an ASCII decimal value.
4442 * If Pc is omitted, the locator position is undefined
4443 * (outside the terminal window for example).
4444 * Pp is the page coordinate of the locator position
4445 * encoded as an ASCII decimal value.
4446 * The page coordinate may be omitted if the locator is on
4447 * page one (the default). We ignore it anyway.
4448 */
4449 int Pe, Pb, Pr, Pc;
4450
4451 p = tp + slen;
4452
4453 /* get event status */
4454 Pe = getdigits(&p);
4455 if (*p++ != ';')
4456 return -1;
4457
4458 /* get button status */
4459 Pb = getdigits(&p);
4460 if (*p++ != ';')
4461 return -1;
4462
4463 /* get row status */
4464 Pr = getdigits(&p);
4465 if (*p++ != ';')
4466 return -1;
4467
4468 /* get column status */
4469 Pc = getdigits(&p);
4470
4471 /* the page parameter is optional */
4472 if (*p == ';')
4473 {
4474 p++;
4475 (void)getdigits(&p);
4476 }
4477 if (*p++ != '&')
4478 return -1;
4479 if (*p++ != 'w')
4480 return -1;
4481
4482 mouse_code = 0;
4483 switch (Pe)
4484 {
4485 case 0: return -1; /* position request while unavailable */
4486 case 1: /* a response to a locator position request includes
4487 the status of all buttons */
4488 Pb &= 7; /* mask off and ignore fourth button */
4489 if (Pb & 4)
4490 mouse_code = MOUSE_LEFT;
4491 if (Pb & 2)
4492 mouse_code = MOUSE_MIDDLE;
4493 if (Pb & 1)
4494 mouse_code = MOUSE_RIGHT;
4495 if (Pb)
4496 {
4497 held_button = mouse_code;
4498 mouse_code |= MOUSE_DRAG;
4499 WantQueryMouse = 1;
4500 }
4501 is_drag = TRUE;
4502 showmode();
4503 break;
4504 case 2: mouse_code = MOUSE_LEFT;
4505 WantQueryMouse = 1;
4506 break;
4507 case 3: mouse_code = MOUSE_RELEASE | MOUSE_LEFT;
4508 break;
4509 case 4: mouse_code = MOUSE_MIDDLE;
4510 WantQueryMouse = 1;
4511 break;
4512 case 5: mouse_code = MOUSE_RELEASE | MOUSE_MIDDLE;
4513 break;
4514 case 6: mouse_code = MOUSE_RIGHT;
4515 WantQueryMouse = 1;
4516 break;
4517 case 7: mouse_code = MOUSE_RELEASE | MOUSE_RIGHT;
4518 break;
4519 case 8: return -1; /* fourth button down */
4520 case 9: return -1; /* fourth button up */
4521 case 10: return -1; /* mouse outside of filter rectangle */
4522 default: return -1; /* should never occur */
4523 }
4524
4525 mouse_col = Pc - 1;
4526 mouse_row = Pr - 1;
4527
4528 slen += (int)(p - (tp + slen));
4529 }
4530# endif /* FEAT_MOUSE_DEC */
4531# ifdef FEAT_MOUSE_PTERM
4532 if (key_name[0] == (int)KS_PTERM_MOUSE)
4533 {
4534 int button, num_clicks, action, mc, mr;
4535
4536 p = tp + slen;
4537
4538 action = getdigits(&p);
4539 if (*p++ != ';')
4540 return -1;
4541
4542 mouse_row = getdigits(&p);
4543 if (*p++ != ';')
4544 return -1;
4545 mouse_col = getdigits(&p);
4546 if (*p++ != ';')
4547 return -1;
4548
4549 button = getdigits(&p);
4550 mouse_code = 0;
4551
4552 switch( button )
4553 {
4554 case 4: mouse_code = MOUSE_LEFT; break;
4555 case 1: mouse_code = MOUSE_RIGHT; break;
4556 case 2: mouse_code = MOUSE_MIDDLE; break;
4557 default: return -1;
4558 }
4559
4560 switch( action )
4561 {
4562 case 31: /* Initial press */
4563 if (*p++ != ';')
4564 return -1;
4565
4566 num_clicks = getdigits(&p); /* Not used */
4567 break;
4568
4569 case 32: /* Release */
4570 mouse_code |= MOUSE_RELEASE;
4571 break;
4572
4573 case 33: /* Drag */
4574 held_button = mouse_code;
4575 mouse_code |= MOUSE_DRAG;
4576 break;
4577
4578 default:
4579 return -1;
4580 }
4581
4582 if (*p++ != 't')
4583 return -1;
4584
4585 slen += (p - (tp + slen));
4586 }
4587# endif /* FEAT_MOUSE_PTERM */
4588
4589 /* Interpret the mouse code */
4590 current_button = (mouse_code & MOUSE_CLICK_MASK);
4591 if (current_button == MOUSE_RELEASE
4592# ifdef FEAT_MOUSE_XTERM
4593 && wheel_code == 0
4594# endif
4595 )
4596 {
4597 /*
4598 * If we get a mouse drag or release event when
4599 * there is no mouse button held down (held_button ==
4600 * MOUSE_RELEASE), produce a K_IGNORE below.
4601 * (can happen when you hold down two buttons
4602 * and then let them go, or click in the menu bar, but not
4603 * on a menu, and drag into the text).
4604 */
4605 if ((mouse_code & MOUSE_DRAG) == MOUSE_DRAG)
4606 is_drag = TRUE;
4607 current_button = held_button;
4608 }
4609 else if (wheel_code == 0)
4610 {
4611# ifdef CHECK_DOUBLE_CLICK
4612# ifdef FEAT_MOUSE_GPM
4613# ifdef FEAT_GUI
4614 /*
4615 * Only for Unix, when GUI or gpm is not active, we handle
4616 * multi-clicks here.
4617 */
4618 if (gpm_flag == 0 && !gui.in_use)
4619# else
4620 if (gpm_flag == 0)
4621# endif
4622# else
4623# ifdef FEAT_GUI
4624 if (!gui.in_use)
4625# endif
4626# endif
4627 {
4628 /*
4629 * Compute the time elapsed since the previous mouse click.
4630 */
4631 gettimeofday(&mouse_time, NULL);
4632 timediff = (mouse_time.tv_usec
4633 - orig_mouse_time.tv_usec) / 1000;
4634 if (timediff < 0)
4635 --orig_mouse_time.tv_sec;
4636 timediff += (mouse_time.tv_sec
4637 - orig_mouse_time.tv_sec) * 1000;
4638 orig_mouse_time = mouse_time;
4639 if (mouse_code == orig_mouse_code
4640 && timediff < p_mouset
4641 && orig_num_clicks != 4
4642 && orig_mouse_col == mouse_col
4643 && orig_mouse_row == mouse_row
4644#ifdef FEAT_DIFF
4645 && orig_topfill == curwin->w_topfill
4646#endif
4647 && orig_topline == curwin->w_topline)
4648 ++orig_num_clicks;
4649 else
4650 orig_num_clicks = 1;
4651 orig_mouse_col = mouse_col;
4652 orig_mouse_row = mouse_row;
4653 orig_topline = curwin->w_topline;
4654#ifdef FEAT_DIFF
4655 orig_topfill = curwin->w_topfill;
4656#endif
4657 }
4658# if defined(FEAT_GUI) || defined(FEAT_MOUSE_GPM)
4659 else
4660 orig_num_clicks = NUM_MOUSE_CLICKS(mouse_code);
4661# endif
4662# else
4663 orig_num_clicks = NUM_MOUSE_CLICKS(mouse_code);
4664# endif
4665 is_click = TRUE;
4666 orig_mouse_code = mouse_code;
4667 }
4668 if (!is_drag)
4669 held_button = mouse_code & MOUSE_CLICK_MASK;
4670
4671 /*
4672 * Translate the actual mouse event into a pseudo mouse event.
4673 * First work out what modifiers are to be used.
4674 */
4675 modifiers = 0x0;
4676 if (orig_mouse_code & MOUSE_SHIFT)
4677 modifiers |= MOD_MASK_SHIFT;
4678 if (orig_mouse_code & MOUSE_CTRL)
4679 modifiers |= MOD_MASK_CTRL;
4680 if (orig_mouse_code & MOUSE_ALT)
4681 modifiers |= MOD_MASK_ALT;
4682 if (orig_num_clicks == 2)
4683 modifiers |= MOD_MASK_2CLICK;
4684 else if (orig_num_clicks == 3)
4685 modifiers |= MOD_MASK_3CLICK;
4686 else if (orig_num_clicks == 4)
4687 modifiers |= MOD_MASK_4CLICK;
4688
4689 /* Add the modifier codes to our string */
4690 if (modifiers != 0)
4691 {
4692 string[new_slen++] = K_SPECIAL;
4693 string[new_slen++] = (int)KS_MODIFIER;
4694 string[new_slen++] = modifiers;
4695 }
4696
4697 /* Work out our pseudo mouse event */
4698 key_name[0] = (int)KS_EXTRA;
4699 if (wheel_code != 0)
4700 key_name[1] = (wheel_code & 1)
4701 ? (int)KE_MOUSEUP : (int)KE_MOUSEDOWN;
4702 else
4703 key_name[1] = get_pseudo_mouse_code(current_button,
4704 is_click, is_drag);
4705 }
4706#endif /* FEAT_MOUSE */
4707
4708#ifdef FEAT_GUI
4709 /*
4710 * If using the GUI, then we get menu and scrollbar events.
4711 *
4712 * A menu event is encoded as K_SPECIAL, KS_MENU, KE_FILLER followed by
4713 * four bytes which are to be taken as a pointer to the vimmenu_T
4714 * structure.
4715 *
4716 * A scrollbar event is K_SPECIAL, KS_VER_SCROLLBAR, KE_FILLER followed
4717 * by one byte representing the scrollbar number, and then four bytes
4718 * representing a long_u which is the new value of the scrollbar.
4719 *
4720 * A horizontal scrollbar event is K_SPECIAL, KS_HOR_SCROLLBAR,
4721 * KE_FILLER followed by four bytes representing a long_u which is the
4722 * new value of the scrollbar.
4723 */
4724# ifdef FEAT_MENU
4725 else if (key_name[0] == (int)KS_MENU)
4726 {
4727 long_u val;
4728
4729 num_bytes = get_long_from_buf(tp + slen, &val);
4730 if (num_bytes == -1)
4731 return -1;
4732 current_menu = (vimmenu_T *)val;
4733 slen += num_bytes;
4734 }
4735# endif
4736# ifndef USE_ON_FLY_SCROLL
4737 else if (key_name[0] == (int)KS_VER_SCROLLBAR)
4738 {
4739 long_u val;
4740
4741 /* Get the last scrollbar event in the queue of the same type */
4742 j = 0;
4743 for (i = 0; tp[j] == CSI && tp[j + 1] == KS_VER_SCROLLBAR
4744 && tp[j + 2] != NUL; ++i)
4745 {
4746 j += 3;
4747 num_bytes = get_bytes_from_buf(tp + j, bytes, 1);
4748 if (num_bytes == -1)
4749 break;
4750 if (i == 0)
4751 current_scrollbar = (int)bytes[0];
4752 else if (current_scrollbar != (int)bytes[0])
4753 break;
4754 j += num_bytes;
4755 num_bytes = get_long_from_buf(tp + j, &val);
4756 if (num_bytes == -1)
4757 break;
4758 scrollbar_value = val;
4759 j += num_bytes;
4760 slen = j;
4761 }
4762 if (i == 0) /* not enough characters to make one */
4763 return -1;
4764 }
4765 else if (key_name[0] == (int)KS_HOR_SCROLLBAR)
4766 {
4767 long_u val;
4768
4769 /* Get the last horiz. scrollbar event in the queue */
4770 j = 0;
4771 for (i = 0; tp[j] == CSI && tp[j + 1] == KS_HOR_SCROLLBAR
4772 && tp[j + 2] != NUL; ++i)
4773 {
4774 j += 3;
4775 num_bytes = get_long_from_buf(tp + j, &val);
4776 if (num_bytes == -1)
4777 break;
4778 scrollbar_value = val;
4779 j += num_bytes;
4780 slen = j;
4781 }
4782 if (i == 0) /* not enough characters to make one */
4783 return -1;
4784 }
4785# endif /* !USE_ON_FLY_SCROLL */
4786#endif /* FEAT_GUI */
4787
4788 /* Finally, add the special key code to our string */
4789 if (key_name[0] == KS_KEY)
4790 string[new_slen++] = key_name[1]; /* from ":set <M-b>=xx" */
4791 else
4792 {
4793 string[new_slen++] = K_SPECIAL;
4794 string[new_slen++] = key_name[0];
4795 string[new_slen++] = key_name[1];
4796 }
4797 string[new_slen] = NUL;
4798 extra = new_slen - slen;
4799 if (buf == NULL)
4800 {
4801 if (extra < 0)
4802 /* remove matched chars, taking care of noremap */
4803 del_typebuf(-extra, offset);
4804 else if (extra > 0)
4805 /* insert the extra space we need */
4806 ins_typebuf(string + slen, REMAP_YES, offset, FALSE, FALSE);
4807
4808 /*
4809 * Careful: del_typebuf() and ins_typebuf() may have reallocated
4810 * typebuf.tb_buf[]!
4811 */
4812 mch_memmove(typebuf.tb_buf + typebuf.tb_off + offset, string,
4813 (size_t)new_slen);
4814 }
4815 else
4816 {
4817 if (extra < 0)
4818 /* remove matched characters */
4819 mch_memmove(buf + offset, buf + offset - extra,
4820 (size_t)(buflen + offset + extra));
4821 else if (extra > 0)
4822 /* insert the extra space we need */
4823 mch_memmove(buf + offset + extra, buf + offset,
4824 (size_t)(buflen - offset));
4825 mch_memmove(buf + offset, string, (size_t)new_slen);
4826 }
4827 return (len + extra + offset);
4828 }
4829
4830 return 0; /* no match found */
4831}
4832
4833/*
4834 * Replace any terminal code strings in from[] with the equivalent internal
4835 * vim representation. This is used for the "from" and "to" part of a
4836 * mapping, and the "to" part of a menu command.
4837 * Any strings like "<C-UP>" are also replaced, unless 'cpoptions' contains
4838 * '<'.
4839 * K_SPECIAL by itself is replaced by K_SPECIAL KS_SPECIAL KE_FILLER.
4840 *
4841 * The replacement is done in result[] and finally copied into allocated
4842 * memory. If this all works well *bufp is set to the allocated memory and a
4843 * pointer to it is returned. If something fails *bufp is set to NULL and from
4844 * is returned.
4845 *
4846 * CTRL-V characters are removed. When "from_part" is TRUE, a trailing CTRL-V
4847 * is included, otherwise it is removed (for ":map xx ^V", maps xx to
4848 * nothing). When 'cpoptions' does not contain 'B', a backslash can be used
4849 * instead of a CTRL-V.
4850 */
4851 char_u *
4852replace_termcodes(from, bufp, from_part, do_lt)
4853 char_u *from;
4854 char_u **bufp;
4855 int from_part;
4856 int do_lt; /* also translate <lt> */
4857{
4858 int i;
4859 int slen;
4860 int key;
4861 int dlen = 0;
4862 char_u *src;
4863 int do_backslash; /* backslash is a special character */
4864 int do_special; /* recognize <> key codes */
4865 int do_key_code; /* recognize raw key codes */
4866 char_u *result; /* buffer for resulting string */
4867
4868 do_backslash = (vim_strchr(p_cpo, CPO_BSLASH) == NULL);
4869 do_special = (vim_strchr(p_cpo, CPO_SPECI) == NULL);
4870 do_key_code = (vim_strchr(p_cpo, CPO_KEYCODE) == NULL);
4871
4872 /*
4873 * Allocate space for the translation. Worst case a single character is
4874 * replaced by 6 bytes (shifted special key), plus a NUL at the end.
4875 */
4876 result = alloc((unsigned)STRLEN(from) * 6 + 1);
4877 if (result == NULL) /* out of memory */
4878 {
4879 *bufp = NULL;
4880 return from;
4881 }
4882
4883 src = from;
4884
4885 /*
4886 * Check for #n at start only: function key n
4887 */
4888 if (from_part && src[0] == '#' && VIM_ISDIGIT(src[1])) /* function key */
4889 {
4890 result[dlen++] = K_SPECIAL;
4891 result[dlen++] = 'k';
4892 if (src[1] == '0')
4893 result[dlen++] = ';'; /* #0 is F10 is "k;" */
4894 else
4895 result[dlen++] = src[1]; /* #3 is F3 is "k3" */
4896 src += 2;
4897 }
4898
4899 /*
4900 * Copy each byte from *from to result[dlen]
4901 */
4902 while (*src != NUL)
4903 {
4904 /*
4905 * If 'cpoptions' does not contain '<', check for special key codes,
4906 * like "<C-S-MouseLeft>"
4907 */
4908 if (do_special && (do_lt || STRNCMP(src, "<lt>", 4) != 0))
4909 {
4910#ifdef FEAT_EVAL
4911 /*
4912 * Replace <SID> by K_SNR <script-nr> _.
4913 * (room: 5 * 6 = 30 bytes; needed: 3 + <nr> + 1 <= 14)
4914 */
4915 if (STRNICMP(src, "<SID>", 5) == 0)
4916 {
4917 if (current_SID <= 0)
4918 EMSG(_(e_usingsid));
4919 else
4920 {
4921 src += 5;
4922 result[dlen++] = K_SPECIAL;
4923 result[dlen++] = (int)KS_EXTRA;
4924 result[dlen++] = (int)KE_SNR;
4925 sprintf((char *)result + dlen, "%ld", (long)current_SID);
4926 dlen += (int)STRLEN(result + dlen);
4927 result[dlen++] = '_';
4928 continue;
4929 }
4930 }
4931#endif
4932
4933 slen = trans_special(&src, result + dlen, TRUE);
4934 if (slen)
4935 {
4936 dlen += slen;
4937 continue;
4938 }
4939 }
4940
4941 /*
4942 * If 'cpoptions' does not contain 'k', see if it's an actual key-code.
4943 * Note that this is also checked after replacing the <> form.
4944 * Single character codes are NOT replaced (e.g. ^H or DEL), because
4945 * it could be a character in the file.
4946 */
4947 if (do_key_code)
4948 {
4949 i = find_term_bykeys(src);
4950 if (i >= 0)
4951 {
4952 result[dlen++] = K_SPECIAL;
4953 result[dlen++] = termcodes[i].name[0];
4954 result[dlen++] = termcodes[i].name[1];
4955 src += termcodes[i].len;
4956 /* If terminal code matched, continue after it. */
4957 continue;
4958 }
4959 }
4960
4961#ifdef FEAT_EVAL
4962 if (do_special)
4963 {
4964 char_u *p, *s, len;
4965
4966 /*
4967 * Replace <Leader> by the value of "mapleader".
4968 * Replace <LocalLeader> by the value of "maplocalleader".
4969 * If "mapleader" or "maplocalleader" isn't set use a backslash.
4970 */
4971 if (STRNICMP(src, "<Leader>", 8) == 0)
4972 {
4973 len = 8;
4974 p = get_var_value((char_u *)"g:mapleader");
4975 }
4976 else if (STRNICMP(src, "<LocalLeader>", 13) == 0)
4977 {
4978 len = 13;
4979 p = get_var_value((char_u *)"g:maplocalleader");
4980 }
4981 else
4982 {
4983 len = 0;
4984 p = NULL;
4985 }
4986 if (len != 0)
4987 {
4988 /* Allow up to 8 * 6 characters for "mapleader". */
4989 if (p == NULL || *p == NUL || STRLEN(p) > 8 * 6)
4990 s = (char_u *)"\\";
4991 else
4992 s = p;
4993 while (*s != NUL)
4994 result[dlen++] = *s++;
4995 src += len;
4996 continue;
4997 }
4998 }
4999#endif
5000
5001 /*
5002 * Remove CTRL-V and ignore the next character.
5003 * For "from" side the CTRL-V at the end is included, for the "to"
5004 * part it is removed.
5005 * If 'cpoptions' does not contain 'B', also accept a backslash.
5006 */
5007 key = *src;
5008 if (key == Ctrl_V || (do_backslash && key == '\\'))
5009 {
5010 ++src; /* skip CTRL-V or backslash */
5011 if (*src == NUL)
5012 {
5013 if (from_part)
5014 result[dlen++] = key;
5015 break;
5016 }
5017 }
5018
5019#ifdef FEAT_MBYTE
5020 /* skip multibyte char correctly */
5021 for (i = (*mb_ptr2len_check)(src); i > 0; --i)
5022#endif
5023 {
5024 /*
5025 * If the character is K_SPECIAL, replace it with K_SPECIAL
5026 * KS_SPECIAL KE_FILLER.
5027 * If compiled with the GUI replace CSI with K_CSI.
5028 */
5029 if (*src == K_SPECIAL)
5030 {
5031 result[dlen++] = K_SPECIAL;
5032 result[dlen++] = KS_SPECIAL;
5033 result[dlen++] = KE_FILLER;
5034 }
5035# ifdef FEAT_GUI
5036 else if (*src == CSI)
5037 {
5038 result[dlen++] = K_SPECIAL;
5039 result[dlen++] = KS_EXTRA;
5040 result[dlen++] = (int)KE_CSI;
5041 }
5042# endif
5043 else
5044 result[dlen++] = *src;
5045 ++src;
5046 }
5047 }
5048 result[dlen] = NUL;
5049
5050 /*
5051 * Copy the new string to allocated memory.
5052 * If this fails, just return from.
5053 */
5054 if ((*bufp = vim_strsave(result)) != NULL)
5055 from = *bufp;
5056 vim_free(result);
5057 return from;
5058}
5059
5060/*
5061 * Find a termcode with keys 'src' (must be NUL terminated).
5062 * Return the index in termcodes[], or -1 if not found.
5063 */
5064 int
5065find_term_bykeys(src)
5066 char_u *src;
5067{
5068 int i;
5069 int slen;
5070
5071 for (i = 0; i < tc_len; ++i)
5072 {
5073 slen = termcodes[i].len;
5074 if (slen > 1 && STRNCMP(termcodes[i].code, src, (size_t)slen) == 0)
5075 return i;
5076 }
5077 return -1;
5078}
5079
5080/*
5081 * Gather the first characters in the terminal key codes into a string.
5082 * Used to speed up check_termcode().
5083 */
5084 static void
5085gather_termleader()
5086{
5087 int i;
5088 int len = 0;
5089
5090#ifdef FEAT_GUI
5091 if (gui.in_use)
5092 termleader[len++] = CSI; /* the GUI codes are not in termcodes[] */
5093#endif
5094#ifdef FEAT_TERMRESPONSE
5095 if (check_for_codes)
5096 termleader[len++] = DCS; /* the termcode response starts with DCS
5097 in 8-bit mode */
5098#endif
5099 termleader[len] = NUL;
5100
5101 for (i = 0; i < tc_len; ++i)
5102 if (vim_strchr(termleader, termcodes[i].code[0]) == NULL)
5103 {
5104 termleader[len++] = termcodes[i].code[0];
5105 termleader[len] = NUL;
5106 }
5107
5108 need_gather = FALSE;
5109}
5110
5111/*
5112 * Show all termcodes (for ":set termcap")
5113 * This code looks a lot like showoptions(), but is different.
5114 */
5115 void
5116show_termcodes()
5117{
5118 int col;
5119 int *items;
5120 int item_count;
5121 int run;
5122 int row, rows;
5123 int cols;
5124 int i;
5125 int len;
5126
5127#define INC 27 /* try to make three columns */
5128#define GAP 2 /* spaces between columns */
5129
5130 if (tc_len == 0) /* no terminal codes (must be GUI) */
5131 return;
5132 items = (int *)alloc((unsigned)(sizeof(int) * tc_len));
5133 if (items == NULL)
5134 return;
5135
5136 /* Highlight title */
5137 MSG_PUTS_TITLE(_("\n--- Terminal keys ---"));
5138
5139 /*
5140 * do the loop two times:
5141 * 1. display the short items (non-strings and short strings)
5142 * 2. display the long items (strings)
5143 */
5144 for (run = 1; run <= 2 && !got_int; ++run)
5145 {
5146 /*
5147 * collect the items in items[]
5148 */
5149 item_count = 0;
5150 for (i = 0; i < tc_len; i++)
5151 {
5152 len = show_one_termcode(termcodes[i].name,
5153 termcodes[i].code, FALSE);
5154 if ((len <= INC - GAP && run == 1) || (len > INC - GAP && run == 2))
5155 items[item_count++] = i;
5156 }
5157
5158 /*
5159 * display the items
5160 */
5161 if (run == 1)
5162 {
5163 cols = (Columns + GAP) / INC;
5164 if (cols == 0)
5165 cols = 1;
5166 rows = (item_count + cols - 1) / cols;
5167 }
5168 else /* run == 2 */
5169 rows = item_count;
5170 for (row = 0; row < rows && !got_int; ++row)
5171 {
5172 msg_putchar('\n'); /* go to next line */
5173 if (got_int) /* 'q' typed in more */
5174 break;
5175 col = 0;
5176 for (i = row; i < item_count; i += rows)
5177 {
5178 msg_col = col; /* make columns */
5179 show_one_termcode(termcodes[items[i]].name,
5180 termcodes[items[i]].code, TRUE);
5181 col += INC;
5182 }
5183 out_flush();
5184 ui_breakcheck();
5185 }
5186 }
5187 vim_free(items);
5188}
5189
5190/*
5191 * Show one termcode entry.
5192 * Output goes into IObuff[]
5193 */
5194 int
5195show_one_termcode(name, code, printit)
5196 char_u *name;
5197 char_u *code;
5198 int printit;
5199{
5200 char_u *p;
5201 int len;
5202
5203 if (name[0] > '~')
5204 {
5205 IObuff[0] = ' ';
5206 IObuff[1] = ' ';
5207 IObuff[2] = ' ';
5208 IObuff[3] = ' ';
5209 }
5210 else
5211 {
5212 IObuff[0] = 't';
5213 IObuff[1] = '_';
5214 IObuff[2] = name[0];
5215 IObuff[3] = name[1];
5216 }
5217 IObuff[4] = ' ';
5218
5219 p = get_special_key_name(TERMCAP2KEY(name[0], name[1]), 0);
5220 if (p[1] != 't')
5221 STRCPY(IObuff + 5, p);
5222 else
5223 IObuff[5] = NUL;
5224 len = (int)STRLEN(IObuff);
5225 do
5226 IObuff[len++] = ' ';
5227 while (len < 17);
5228 IObuff[len] = NUL;
5229 if (code == NULL)
5230 len += 4;
5231 else
5232 len += vim_strsize(code);
5233
5234 if (printit)
5235 {
5236 msg_puts(IObuff);
5237 if (code == NULL)
5238 msg_puts((char_u *)"NULL");
5239 else
5240 msg_outtrans(code);
5241 }
5242 return len;
5243}
5244
5245#if defined(FEAT_TERMRESPONSE) || defined(PROTO)
5246/*
5247 * For Xterm >= 140 compiled with OPT_TCAP_QUERY: Obtain the actually used
5248 * termcap codes from the terminal itself.
5249 * We get them one by one to avoid a very long response string.
5250 */
5251static int xt_index_in = 0;
5252static int xt_index_out = 0;
5253
5254 static void
5255req_codes_from_term()
5256{
5257 xt_index_out = 0;
5258 xt_index_in = 0;
5259 req_more_codes_from_term();
5260}
5261
5262 static void
5263req_more_codes_from_term()
5264{
5265 char buf[11];
5266 int old_idx = xt_index_out;
5267
5268 /* Don't do anything when going to exit. */
5269 if (exiting)
5270 return;
5271
5272 /* Send up to 10 more requests out than we received. Avoid sending too
5273 * many, there can be a buffer overflow somewhere. */
5274 while (xt_index_out < xt_index_in + 10 && key_names[xt_index_out] != NULL)
5275 {
5276 sprintf(buf, "\033P+q%02x%02x\033\\",
5277 key_names[xt_index_out][0], key_names[xt_index_out][1]);
5278 out_str_nf((char_u *)buf);
5279 ++xt_index_out;
5280 }
5281
5282 /* Send the codes out right away. */
5283 if (xt_index_out != old_idx)
5284 out_flush();
5285}
5286
5287/*
5288 * Decode key code response from xterm: '<Esc>P1+r<name>=<string><Esc>\'.
5289 * A "0" instead of the "1" indicates a code that isn't supported.
5290 * Both <name> and <string> are encoded in hex.
5291 * "code" points to the "0" or "1".
5292 */
5293 static void
5294got_code_from_term(code, len)
5295 char_u *code;
5296 int len;
5297{
5298#define XT_LEN 100
5299 char_u name[3];
5300 char_u str[XT_LEN];
5301 int i;
5302 int j = 0;
5303 int c;
5304
5305 /* A '1' means the code is supported, a '0' means it isn't.
5306 * When half the length is > XT_LEN we can't use it.
5307 * Our names are currently all 2 characters. */
5308 if (code[0] == '1' && code[7] == '=' && len / 2 < XT_LEN)
5309 {
5310 /* Get the name from the response and find it in the table. */
5311 name[0] = hexhex2nr(code + 3);
5312 name[1] = hexhex2nr(code + 5);
5313 name[2] = NUL;
5314 for (i = 0; key_names[i] != NULL; ++i)
5315 {
5316 if (STRCMP(key_names[i], name) == 0)
5317 {
5318 xt_index_in = i;
5319 break;
5320 }
5321 }
5322 if (key_names[i] != NULL)
5323 {
5324 for (i = 8; (c = hexhex2nr(code + i)) >= 0; i += 2)
5325 str[j++] = c;
5326 str[j] = NUL;
5327 if (name[0] == 'C' && name[1] == 'o')
5328 {
5329 /* Color count is not a key code. */
5330 i = atoi((char *)str);
5331 if (i != t_colors)
5332 {
5333 /* Nr of colors changed, initialize highlighting and
5334 * redraw everything. */
5335 set_color_count(i);
5336 init_highlight(TRUE, FALSE);
5337 redraw_later(CLEAR);
5338 }
5339 }
5340 else
5341 {
5342 /* First delete any existing entry with the same code. */
5343 i = find_term_bykeys(str);
5344 if (i >= 0)
5345 del_termcode_idx(i);
5346 add_termcode(name, str, FALSE);
5347 }
5348 }
5349 }
5350
5351 /* May request more codes now that we received one. */
5352 ++xt_index_in;
5353 req_more_codes_from_term();
5354}
5355
5356/*
5357 * Check if there are any unanswered requests and deal with them.
5358 * This is called before starting an external program or getting direct
5359 * keyboard input. We don't want responses to be send to that program or
5360 * handled as typed text.
5361 */
5362 static void
5363check_for_codes_from_term()
5364{
5365 int c;
5366
5367 /* If no codes requested or all are answered, no need to wait. */
5368 if (xt_index_out == 0 || xt_index_out == xt_index_in)
5369 return;
5370
5371 /* Vgetc() will check for and handle any response.
5372 * Keep calling vpeekc() until we don't get any responses. */
5373 ++no_mapping;
5374 ++allow_keys;
5375 for (;;)
5376 {
5377 c = vpeekc();
5378 if (c == NUL) /* nothing available */
5379 break;
5380
5381 /* If a response is recognized it's replaced with K_IGNORE, must read
5382 * it from the input stream. If there is no K_IGNORE we can't do
5383 * anything, break here (there might be some responses further on, but
5384 * we don't want to throw away any typed chars). */
5385 if (c != K_SPECIAL && c != K_IGNORE)
5386 break;
5387 c = vgetc();
5388 if (c != K_IGNORE)
5389 {
5390 vungetc(c);
5391 break;
5392 }
5393 }
5394 --no_mapping;
5395 --allow_keys;
5396}
5397#endif
5398
5399#if defined(FEAT_CMDL_COMPL) || defined(PROTO)
5400/*
5401 * Translate an internal mapping/abbreviation representation into the
5402 * corresponding external one recognized by :map/:abbrev commands;
5403 * respects the current B/k/< settings of 'cpoption'.
5404 *
5405 * This function is called when expanding mappings/abbreviations on the
5406 * command-line, and for building the "Ambiguous mapping..." error messæge.
5407 *
5408 * It uses a growarray to build the translation string since the
5409 * latter can be wider than the original description. The caller has to
5410 * free the string afterwards.
5411 *
5412 * Returns NULL when there is a problem.
5413 */
5414 char_u *
5415translate_mapping(str, expmap)
5416 char_u *str;
5417 int expmap; /* TRUE when expanding mappings on command-line */
5418{
5419 garray_T ga;
5420 int c;
5421 int modifiers;
5422 int cpo_bslash;
5423 int cpo_special;
5424 int cpo_keycode;
5425
5426 ga_init(&ga);
5427 ga.ga_itemsize = 1;
5428 ga.ga_growsize = 40;
5429
5430 cpo_bslash = (vim_strchr(p_cpo, CPO_BSLASH) != NULL);
5431 cpo_special = (vim_strchr(p_cpo, CPO_SPECI) != NULL);
5432 cpo_keycode = (vim_strchr(p_cpo, CPO_KEYCODE) == NULL);
5433
5434 for (; *str; ++str)
5435 {
5436 c = *str;
5437 if (c == K_SPECIAL && str[1] != NUL && str[2] != NUL)
5438 {
5439 modifiers = 0;
5440 if (str[1] == KS_MODIFIER)
5441 {
5442 str++;
5443 modifiers = *++str;
5444 c = *++str;
5445 }
5446 if (cpo_special && cpo_keycode && c == K_SPECIAL && !modifiers)
5447 {
5448 int i;
5449
5450 /* try to find special key in termcodes */
5451 for (i = 0; i < tc_len; ++i)
5452 if (termcodes[i].name[0] == str[1]
5453 && termcodes[i].name[1] == str[2])
5454 break;
5455 if (i < tc_len)
5456 {
5457 ga_concat(&ga, termcodes[i].code);
5458 str += 2;
5459 continue; /* for (str) */
5460 }
5461 }
5462 if (c == K_SPECIAL && str[1] != NUL && str[2] != NUL)
5463 {
5464 if (expmap && cpo_special)
5465 {
5466 ga_clear(&ga);
5467 return NULL;
5468 }
5469 c = TO_SPECIAL(str[1], str[2]);
5470 if (c == K_ZERO) /* display <Nul> as ^@ */
5471 c = NUL;
5472 str += 2;
5473 }
5474 if (IS_SPECIAL(c) || modifiers) /* special key */
5475 {
5476 if (expmap && cpo_special)
5477 {
5478 ga_clear(&ga);
5479 return NULL;
5480 }
5481 ga_concat(&ga, get_special_key_name(c, modifiers));
5482 continue; /* for (str) */
5483 }
5484 }
5485 if (c == ' ' || c == '\t' || c == Ctrl_J || c == Ctrl_V
5486 || (c == '<' && !cpo_special) || (c == '\\' && !cpo_bslash))
5487 ga_append(&ga, cpo_bslash ? Ctrl_V : '\\');
5488 if (c)
5489 ga_append(&ga, c);
5490 }
5491 ga_append(&ga, NUL);
5492 return (char_u *)(ga.ga_data);
5493}
5494#endif
5495
5496#if (defined(WIN3264) && !defined(FEAT_GUI)) || defined(PROTO)
5497static char ksme_str[20];
5498static char ksmr_str[20];
5499static char ksmd_str[20];
5500
5501/*
5502 * For Win32 console: update termcap codes for existing console attributes.
5503 */
5504 void
5505update_tcap(attr)
5506 int attr;
5507{
5508 struct builtin_term *p;
5509
5510 p = find_builtin_term(DEFAULT_TERM);
5511 sprintf(ksme_str, IF_EB("\033|%dm", ESC_STR "|%dm"), attr);
5512 sprintf(ksmd_str, IF_EB("\033|%dm", ESC_STR "|%dm"),
5513 attr | 0x08); /* FOREGROUND_INTENSITY */
5514 sprintf(ksmr_str, IF_EB("\033|%dm", ESC_STR "|%dm"),
5515 ((attr & 0x0F) << 4) | ((attr & 0xF0) >> 4));
5516
5517 while (p->bt_string != NULL)
5518 {
5519 if (p->bt_entry == (int)KS_ME)
5520 p->bt_string = &ksme_str[0];
5521 else if (p->bt_entry == (int)KS_MR)
5522 p->bt_string = &ksmr_str[0];
5523 else if (p->bt_entry == (int)KS_MD)
5524 p->bt_string = &ksmd_str[0];
5525 ++p;
5526 }
5527}
5528#endif