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