[BACK]Return to term.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / vim

Annotation of src/usr.bin/vim/term.c, Revision 1.1.1.1

1.1       downsj      1: /* $OpenBSD$   */
                      2: /* vi:set ts=4 sw=4:
                      3:  *
                      4:  * VIM - Vi IMproved       by Bram Moolenaar
                      5:  *
                      6:  * Do ":help uganda"  in Vim to read copying and usage conditions.
                      7:  * Do ":help credits" in Vim to see a list of people who contributed.
                      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: #include "globals.h"
                     29: #include "option.h"
                     30: #include "proto.h"
                     31:
                     32: #ifdef HAVE_TGETENT
                     33: # ifdef HAVE_TERMCAP_H
                     34: #  include <termcap.h>
                     35: # endif
                     36:
                     37: /*
                     38:  * A few linux systems define outfuntype in termcap.h to be used as the third
                     39:  * argument for tputs().
                     40:  */
                     41: # ifdef VMS
                     42: #  define TPUTSFUNCAST
                     43: # else
                     44: #  ifdef HAVE_OUTFUNTYPE
                     45: #   define TPUTSFUNCAST (outfuntype)
                     46: #  else
                     47: #   define TPUTSFUNCAST (int (*)())
                     48: #  endif
                     49: # endif
                     50: #endif
                     51:
                     52: #undef tgetstr
                     53:
                     54: /*
                     55:  * Here are the builtin termcap entries.  They are not stored as complete
                     56:  * Tcarr structures, as such a structure is too big.
                     57:  *
                     58:  * The entries are compact, therefore they normally are included even when
                     59:  * HAVE_TGETENT is defined.    When HAVE_TGETENT is defined, the builtin entries
                     60:  * can be accessed with "builtin_amiga", "builtin_ansi", "builtin_debug", etc.
                     61:  *
                     62:  * Each termcap is a list of builtin_term structures. It always starts with
                     63:  * KS_NAME, which separates the entries.  See parse_builtin_tcap() for all
                     64:  * details.
                     65:  * bt_entry is either a KS_xxx code (< 0x100), or a K_xxx code.
                     66:  */
                     67: struct builtin_term
                     68: {
                     69:    int         bt_entry;
                     70:    char        *bt_string;
                     71: };
                     72:
                     73: /* start of keys that are not directly used by Vim but can be mapped */
                     74: #define BT_EXTRA_KEYS  0x101
                     75:
                     76: static struct builtin_term *find_builtin_term __ARGS((char_u *name));
                     77: static void parse_builtin_tcap __ARGS((char_u *s));
                     78: static void gather_termleader __ARGS((void));
                     79: static int get_bytes_from_buf __ARGS((char_u *, char_u *, int));
                     80: static int is_builtin_term __ARGS((char_u *));
                     81:
                     82: #ifdef HAVE_TGETENT
                     83: static char_u *tgetent_error __ARGS((char_u *, char_u *));
                     84:
                     85: /*
                     86:  * Here is our own prototype for tgetstr(), any prototypes from the include
                     87:  * files have been disabled by the define at the start of this file.
                     88:  */
                     89: char           *tgetstr __PARMS((char *, char **));
                     90:
                     91: /*
                     92:  * Don't declare these variables if termcap.h contains them.
                     93:  * Autoconf checks if these variables should be declared extern (not all
                     94:  * systems have them).
                     95:  * Some versions define ospeed to be speed_t, but that is incompatible with
                     96:  * BSD, where ospeed is short and speed_t is long.
                     97:  */
                     98: # ifndef HAVE_OSPEED
                     99: #  ifdef OSPEED_EXTERN
                    100: extern short ospeed;
                    101: #   else
                    102: short ospeed;
                    103: #   endif
                    104: # endif
                    105: # ifndef HAVE_UP_BC_PC
                    106: #  ifdef UP_BC_PC_EXTERN
                    107: extern char *UP, *BC, PC;
                    108: #  else
                    109: char *UP, *BC, PC;
                    110: #  endif
                    111: # endif
                    112:
                    113: # define TGETSTR(s, p) (char_u *)tgetstr((s), (char **)(p))
                    114: # define TGETENT(b, t) tgetent((char *)(b), (char *)(t))
                    115:
                    116: #endif /* HAVE_TGETENT */
                    117:
                    118: struct builtin_term builtin_termcaps[] =
                    119: {
                    120:
                    121: #if defined(USE_GUI)
                    122: /*
                    123:  * Motif/Athena pseudo term-cap.
                    124:  */
                    125:    {KS_NAME,       "gui"},
                    126:    {KS_CE,         "\033|$"},
                    127:    {KS_AL,         "\033|i"},
                    128: # ifdef TERMINFO
                    129:    {KS_CAL,        "\033|%p1%dI"},
                    130: # else
                    131:    {KS_CAL,        "\033|%dI"},
                    132: # endif
                    133:    {KS_DL,         "\033|d"},
                    134: # ifdef TERMINFO
                    135:    {KS_CDL,        "\033|%p1%dD"},
                    136:    {KS_CS,         "\033|%p1%d;%p2%dR"},
                    137: # else
                    138:    {KS_CDL,        "\033|%dD"},
                    139:    {KS_CS,         "\033|%d;%dR"},
                    140: # endif
                    141:    {KS_CL,         "\033|C"},
                    142:    {KS_ME,         "\033|63H"},    /* 63 = HL_ALL,         H = off */
                    143:    {KS_MR,         "\033|1h"},     /* 1  = HL_INVERSE,     h = on */
                    144:    {KS_MD,         "\033|2h"},     /* 2  = HL_BOLD,        h = on */
                    145:    {KS_SE,         "\033|16H"},    /* 16 = HL_STANDOUT,    H = off */
                    146:    {KS_SO,         "\033|16h"},    /* 16 = HL_STANDOUT,    h = on */
                    147:    {KS_UE,         "\033|8H"},     /* 8  = HL_UNDERLINE,   H = off */
                    148:    {KS_US,         "\033|8h"},     /* 8  = HL_UNDERLINE,   h = on */
                    149:    {KS_CZR,        "\033|4H"},     /* 4  = HL_ITAL,        H = off */
                    150:    {KS_CZH,        "\033|4h"},     /* 4  = HL_ITAL,        h = on */
                    151:    {KS_VB,         "\033|f"},
                    152: # ifdef TERMINFO
                    153:    {KS_CM,         "\033|%p1%d;%p2%dM"},
                    154: # else
                    155:    {KS_CM,         "\033|%d;%dM"},
                    156: # endif
                    157:        /* there are no key sequences here, the GUI sequences are recognized
                    158:         * in check_termcodes() */
                    159: #endif
                    160:
                    161: #ifndef NO_BUILTIN_TCAPS
                    162:
                    163: # if defined(AMIGA) || defined(ALL_BUILTIN_TCAPS)
                    164: /*
                    165:  * Amiga console window, default for Amiga
                    166:  */
                    167:    {KS_NAME,       "amiga"},
                    168:    {KS_CE,         "\033[K"},
                    169:    {KS_CD,         "\033[J"},
                    170:    {KS_AL,         "\033[L"},
                    171: #  ifdef TERMINFO
                    172:    {KS_CAL,        "\033[%p1%dL"},
                    173: #  else
                    174:    {KS_CAL,        "\033[%dL"},
                    175: #  endif
                    176:    {KS_DL,         "\033[M"},
                    177: #  ifdef TERMINFO
                    178:    {KS_CDL,        "\033[%p1%dM"},
                    179: #  else
                    180:    {KS_CDL,        "\033[%dM"},
                    181: #  endif
                    182:    {KS_CL,         "\014"},
                    183:    {KS_VI,         "\033[0 p"},
                    184:    {KS_VE,         "\033[1 p"},
                    185:    {KS_ME,         "\033[0m"},
                    186:    {KS_MR,         "\033[7m"},
                    187:    {KS_MD,         "\033[1m"},
                    188:    {KS_SE,         "\033[0m"},
                    189:    {KS_SO,         "\033[33m"},
                    190:    {KS_US,         "\033[4m"},
                    191:    {KS_UE,         "\033[0m"},
                    192:    {KS_CZH,        "\033[3m"},
                    193:    {KS_CZR,        "\033[0m"},
                    194:    {KS_MS,         "\001"},
                    195: #  ifdef TERMINFO
                    196:    {KS_CM,         "\033[%i%p1%d;%p2%dH"},
                    197: #  else
                    198:    {KS_CM,         "\033[%i%d;%dH"},
                    199: #  endif
                    200: #  ifdef TERMINFO
                    201:    {KS_CRI,        "\033[%p1%dC"},
                    202: #  else
                    203:    {KS_CRI,        "\033[%dC"},
                    204: #  endif
                    205:    {K_UP,          "\233A"},
                    206:    {K_DOWN,        "\233B"},
                    207:    {K_LEFT,        "\233D"},
                    208:    {K_RIGHT,       "\233C"},
                    209:    {K_S_UP,        "\233T"},
                    210:    {K_S_DOWN,      "\233S"},
                    211:    {K_S_LEFT,      "\233 A"},
                    212:    {K_S_RIGHT,     "\233 @"},
                    213:    {K_S_TAB,       "\233Z"},
                    214:    {K_F1,          "\233\060~"},/* some compilers don't understand "\2330" */
                    215:    {K_F2,          "\233\061~"},
                    216:    {K_F3,          "\233\062~"},
                    217:    {K_F4,          "\233\063~"},
                    218:    {K_F5,          "\233\064~"},
                    219:    {K_F6,          "\233\065~"},
                    220:    {K_F7,          "\233\066~"},
                    221:    {K_F8,          "\233\067~"},
                    222:    {K_F9,          "\233\070~"},
                    223:    {K_F10,         "\233\071~"},
                    224:    {K_S_F1,        "\233\061\060~"},
                    225:    {K_S_F2,        "\233\061\061~"},
                    226:    {K_S_F3,        "\233\061\062~"},
                    227:    {K_S_F4,        "\233\061\063~"},
                    228:    {K_S_F5,        "\233\061\064~"},
                    229:    {K_S_F6,        "\233\061\065~"},
                    230:    {K_S_F7,        "\233\061\066~"},
                    231:    {K_S_F8,        "\233\061\067~"},
                    232:    {K_S_F9,        "\233\061\070~"},
                    233:    {K_S_F10,       "\233\061\071~"},
                    234:    {K_HELP,        "\233?~"},
                    235:    {K_INS,         "\233\064\060~"},   /* 101 key keyboard */
                    236:    {K_PAGEUP,      "\233\064\061~"},   /* 101 key keyboard */
                    237:    {K_PAGEDOWN,    "\233\064\062~"},   /* 101 key keyboard */
                    238:    {K_HOME,        "\233\064\064~"},   /* 101 key keyboard */
                    239:    {K_END,         "\233\064\065~"},   /* 101 key keyboard */
                    240:
                    241:    {BT_EXTRA_KEYS, ""},
                    242:    {TERMCAP2KEY('#', '2'), "\233\065\064~"},   /* shifted home key */
                    243:    {TERMCAP2KEY('#', '3'), "\233\065\060~"},   /* shifted insert key */
                    244:    {TERMCAP2KEY('*', '7'), "\233\065\065~"},   /* shifted end key */
                    245: # endif
                    246:
                    247: # if defined(UNIX) || defined(ALL_BUILTIN_TCAPS) || defined(SOME_BUILTIN_TCAPS) || defined(__EMX__)
                    248: /*
                    249:  * standard ANSI terminal, default for unix
                    250:  */
                    251:    {KS_NAME,       "ansi"},
                    252:    {KS_CE,         "\033[K"},
                    253:    {KS_AL,         "\033[L"},
                    254: #  ifdef TERMINFO
                    255:    {KS_CAL,        "\033[%p1%dL"},
                    256: #  else
                    257:    {KS_CAL,        "\033[%dL"},
                    258: #  endif
                    259:    {KS_DL,         "\033[M"},
                    260: #  ifdef TERMINFO
                    261:    {KS_CDL,        "\033[%p1%dM"},
                    262: #  else
                    263:    {KS_CDL,        "\033[%dM"},
                    264: #  endif
                    265:    {KS_CL,         "\033[H\033[2J"},
                    266:    {KS_ME,         "\033[0m"},
                    267:    {KS_MR,         "\033[7m"},
                    268:    {KS_MS,         "\001"},
                    269: #  ifdef TERMINFO
                    270:    {KS_CM,         "\033[%i%p1%d;%p2%dH"},
                    271: #  else
                    272:    {KS_CM,         "\033[%i%d;%dH"},
                    273: #  endif
                    274: #  ifdef TERMINFO
                    275:    {KS_CRI,        "\033[%p1%dC"},
                    276: #  else
                    277:    {KS_CRI,        "\033[%dC"},
                    278: #  endif
                    279: # endif
                    280:
                    281: # if defined(MSDOS) || defined(ALL_BUILTIN_TCAPS) || defined(__EMX__)
                    282: /*
                    283:  * These codes are valid when nansi.sys or equivalent has been installed.
                    284:  * Function keys on a PC are preceded with a NUL. These are converted into
                    285:  * K_NUL '\316' in mch_inchar(), because we cannot handle NULs in key codes.
                    286:  * CTRL-arrow is used instead of SHIFT-arrow.
                    287:  */
                    288: #ifdef __EMX__
                    289:    {KS_NAME,       "os2ansi"},
                    290: #else
                    291:    {KS_NAME,       "pcansi"},
                    292:    {KS_DL,         "\033[M"},
                    293:    {KS_AL,         "\033[L"},
                    294: #endif
                    295:    {KS_CE,         "\033[K"},
                    296:    {KS_CL,         "\033[2J"},
                    297:    {KS_ME,         "\033[0m"},
                    298:    {KS_MR,         "\033[7m"},
                    299:    {KS_MS,         "\001"},
                    300: #  ifdef TERMINFO
                    301:    {KS_CM,         "\033[%i%p1%d;%p2%dH"},
                    302: #  else
                    303:    {KS_CM,         "\033[%i%d;%dH"},
                    304: #  endif
                    305: #  ifdef TERMINFO
                    306:    {KS_CRI,        "\033[%p1%dC"},
                    307: #  else
                    308:    {KS_CRI,        "\033[%dC"},
                    309: #  endif
                    310:    {K_UP,          "\316H"},
                    311:    {K_DOWN,        "\316P"},
                    312:    {K_LEFT,        "\316K"},
                    313:    {K_RIGHT,       "\316M"},
                    314:    {K_S_LEFT,      "\316s"},
                    315:    {K_S_RIGHT,     "\316t"},
                    316:    {K_F1,          "\316;"},
                    317:    {K_F2,          "\316<"},
                    318:    {K_F3,          "\316="},
                    319:    {K_F4,          "\316>"},
                    320:    {K_F5,          "\316?"},
                    321:    {K_F6,          "\316@"},
                    322:    {K_F7,          "\316A"},
                    323:    {K_F8,          "\316B"},
                    324:    {K_F9,          "\316C"},
                    325:    {K_F10,         "\316D"},
                    326:    {K_F11,         "\316\205"},    /* guessed */
                    327:    {K_F12,         "\316\206"},    /* guessed */
                    328:    {K_S_F1,        "\316T"},
                    329:    {K_S_F2,        "\316U"},
                    330:    {K_S_F3,        "\316V"},
                    331:    {K_S_F4,        "\316W"},
                    332:    {K_S_F5,        "\316X"},
                    333:    {K_S_F6,        "\316Y"},
                    334:    {K_S_F7,        "\316Z"},
                    335:    {K_S_F8,        "\316["},
                    336:    {K_S_F9,        "\316\\"},
                    337:    {K_S_F10,       "\316]"},
                    338:    {K_S_F11,       "\316\207"},    /* guessed */
                    339:    {K_S_F12,       "\316\210"},    /* guessed */
                    340:    {K_INS,         "\316R"},
                    341:    {K_DEL,         "\316S"},
                    342:    {K_HOME,        "\316G"},
                    343:    {K_END,         "\316O"},
                    344:    {K_PAGEDOWN,    "\316Q"},
                    345:    {K_PAGEUP,      "\316I"},
                    346: # endif
                    347:
                    348: # if defined(MSDOS)
                    349: /*
                    350:  * These codes are valid for the pc video. The entries that start with ESC |
                    351:  * are translated into conio calls in msdos.c. Default for MSDOS.
                    352:  */
                    353:    {KS_NAME,       "pcterm"},
                    354:    {KS_CE,         "\033|K"},
                    355:    {KS_AL,         "\033|L"},
                    356:    {KS_DL,         "\033|M"},
                    357: #  ifdef TERMINFO
                    358:    {KS_CS,         "\033|%i%p1%d;%p2%dr"},
                    359: #  else
                    360:    {KS_CS,         "\033|%i%d;%dr"},
                    361: #  endif
                    362:    {KS_CL,         "\033|J"},
                    363:    {KS_ME,         "\033|0m"},
                    364:    {KS_MR,         "\033|112m"},
                    365:    {KS_MD,         "\033|63m"},
                    366:    {KS_SE,         "\033|0m"},
                    367:    {KS_SO,         "\033|31m"},
                    368:    {KS_MS,         "\001"},
                    369: #  ifdef TERMINFO
                    370:    {KS_CM,         "\033|%i%p1%d;%p2%dH"},
                    371: #  else
                    372:    {KS_CM,         "\033|%i%d;%dH"},
                    373: #  endif
                    374:    {K_UP,          "\316H"},
                    375:    {K_DOWN,        "\316P"},
                    376:    {K_LEFT,        "\316K"},
                    377:    {K_RIGHT,       "\316M"},
                    378:    {K_S_LEFT,      "\316s"},
                    379:    {K_S_RIGHT,     "\316t"},
                    380:    {K_S_TAB,       "\316\017"},
                    381:    {K_F1,          "\316;"},
                    382:    {K_F2,          "\316<"},
                    383:    {K_F3,          "\316="},
                    384:    {K_F4,          "\316>"},
                    385:    {K_F5,          "\316?"},
                    386:    {K_F6,          "\316@"},
                    387:    {K_F7,          "\316A"},
                    388:    {K_F8,          "\316B"},
                    389:    {K_F9,          "\316C"},
                    390:    {K_F10,         "\316D"},
                    391:    {K_F11,         "\316\205"},    /* only when nobioskey */
                    392:    {K_F12,         "\316\206"},    /* only when nobioskey */
                    393:    {K_S_F1,        "\316T"},
                    394:    {K_S_F2,        "\316U"},
                    395:    {K_S_F3,        "\316V"},
                    396:    {K_S_F4,        "\316W"},
                    397:    {K_S_F5,        "\316X"},
                    398:    {K_S_F6,        "\316Y"},
                    399:    {K_S_F7,        "\316Z"},
                    400:    {K_S_F8,        "\316["},
                    401:    {K_S_F9,        "\316\\"},
                    402:    {K_S_F10,       "\316]"},
                    403:    {K_S_F11,       "\316\207"},    /* only when nobioskey */
                    404:    {K_S_F12,       "\316\210"},    /* only when nobioskey */
                    405:    {K_INS,         "\316R"},
                    406:    {K_DEL,         "\316S"},
                    407:    {K_HOME,        "\316G"},
                    408:    {K_END,         "\316O"},
                    409:    {K_PAGEDOWN,    "\316Q"},
                    410:    {K_PAGEUP,      "\316I"},
                    411: # endif
                    412:
                    413: # if defined(WIN32) || defined(ALL_BUILTIN_TCAPS) || defined(__EMX__)
                    414: /*
                    415:  * These codes are valid for the Win32 Console .  The entries that start with
                    416:  * ESC | are translated into console calls in win32.c.  The function keys
                    417:  * are also translated in win32.c.
                    418:  */
                    419:    {KS_NAME,       "win32"},
                    420:    {KS_CE,         "\033|K"},      /* clear to end of line */
                    421:    {KS_AL,         "\033|L"},      /* add new blank line */
                    422: #  ifdef TERMINFO
                    423:    {KS_CAL,        "\033|%p1%dL"}, /* add number of new blank lines */
                    424: #  else
                    425:    {KS_CAL,        "\033|%dL"},    /* add number of new blank lines */
                    426: #  endif
                    427:    {KS_DL,         "\033|M"},      /* delete line */
                    428: #  ifdef TERMINFO
                    429:    {KS_CDL,        "\033|%p1%dM"}, /* delete number of lines */
                    430: #  else
                    431:    {KS_CDL,        "\033|%dM"},    /* delete number of lines */
                    432: #  endif
                    433:    {KS_CL,         "\033|J"},      /* clear screen */
                    434:    {KS_CD,         "\033|j"},      /* clear to end of display */
                    435:    {KS_VI,         "\033|v"},      /* cursor invisible */
                    436:    {KS_VE,         "\033|V"},      /* cursor visible */
                    437:
                    438:    {KS_ME,         "\033|0m"},     /* normal mode */
                    439:    {KS_MR,         "\033|112m"},   /* reverse mode: black text on lightgray */
                    440:    {KS_MD,         "\033|63m"},    /* bold mode: white text on cyan */
                    441: #if 1
                    442:    {KS_SO,         "\033|31m"},    /* standout mode: white text on blue */
                    443:    {KS_SE,         "\033|0m"},     /* standout mode end */
                    444: #else
                    445:    {KS_SO,         "\033|F"},      /* standout mode: high intensity text */
                    446:    {KS_SE,         "\033|f"},      /* standout mode end */
                    447: #endif
                    448:    {KS_CZH,        "\033|225m"},   /* italic mode: blue text on yellow */
                    449:    {KS_CZR,        "\033|0m"},     /* italic mode end */
                    450:    {KS_US,         "\033|67m"},    /* underscore mode: cyan text on red */
                    451:    {KS_UE,         "\033|0m"},     /* underscore mode end */
                    452:
                    453:    {KS_MS,         "\001"},        /* save to move cur in reverse mode */
                    454: #  ifdef TERMINFO
                    455:    {KS_CM,         "\033|%i%p1%d;%p2%dH"}, /* cursor motion */
                    456: #  else
                    457:    {KS_CM,         "\033|%i%d;%dH"},       /* cursor motion */
                    458: #  endif
                    459:    {KS_VB,         "\033|B"},      /* visual bell */
                    460:    {KS_TI,         "\033|S"},      /* put terminal in termcap mode */
                    461:    {KS_TE,         "\033|E"},      /* out of termcap mode */
                    462:    {KS_CS,         "\033|%i%d;%dr"},   /* scroll region */
                    463:
                    464:    {K_UP,          "\316H"},
                    465:    {K_DOWN,        "\316P"},
                    466:    {K_LEFT,        "\316K"},
                    467:    {K_RIGHT,       "\316M"},
                    468:    {K_S_UP,        "\316\304"},
                    469:    {K_S_DOWN,      "\316\317"},
                    470:    {K_S_LEFT,      "\316\311"},
                    471:    {K_S_RIGHT,     "\316\313"},
                    472:    {K_S_TAB,       "\316\017"},
                    473:    {K_F1,          "\316;"},
                    474:    {K_F2,          "\316<"},
                    475:    {K_F3,          "\316="},
                    476:    {K_F4,          "\316>"},
                    477:    {K_F5,          "\316?"},
                    478:    {K_F6,          "\316@"},
                    479:    {K_F7,          "\316A"},
                    480:    {K_F8,          "\316B"},
                    481:    {K_F9,          "\316C"},
                    482:    {K_F10,         "\316D"},
                    483:    {K_F11,         "\316\205"},
                    484:    {K_F12,         "\316\206"},
                    485:    {K_S_F1,        "\316T"},
                    486:    {K_S_F2,        "\316U"},
                    487:    {K_S_F3,        "\316V"},
                    488:    {K_S_F4,        "\316W"},
                    489:    {K_S_F5,        "\316X"},
                    490:    {K_S_F6,        "\316Y"},
                    491:    {K_S_F7,        "\316Z"},
                    492:    {K_S_F8,        "\316["},
                    493:    {K_S_F9,        "\316\\"},
                    494:    {K_S_F10,       "\316]"},
                    495:    {K_S_F11,       "\316\207"},
                    496:    {K_S_F12,       "\316\210"},
                    497:    {K_INS,         "\316R"},
                    498:    {K_DEL,         "\316S"},
                    499:    {K_HOME,        "\316G"},
                    500:    {K_END,         "\316O"},
                    501:    {K_PAGEDOWN,    "\316Q"},
                    502:    {K_PAGEUP,      "\316I"},
                    503: # endif
                    504:
                    505: # if defined(ALL_BUILTIN_TCAPS) || defined(MINT)
                    506: /*
                    507:  * Ordinary vt52
                    508:  */
                    509:    {KS_NAME,       "vt52"},
                    510:    {KS_CE,         "\033K"},
                    511:    {KS_CD,         "\033J"},
                    512:    {KS_CM,         "\033Y%+ %+ "},
                    513: #  ifdef MINT
                    514:    {KS_AL,         "\033L"},
                    515:    {KS_DL,         "\033M"},
                    516:    {KS_CL,         "\033E"},
                    517:    {KS_SR,         "\033I"},
                    518:    {KS_VE,         "\033e"},
                    519:    {KS_VI,         "\033f"},
                    520:    {KS_SO,         "\033p"},
                    521:    {KS_SE,         "\033q"},
                    522:    {K_UP,          "\033A"},
                    523:    {K_DOWN,        "\033B"},
                    524:    {K_LEFT,        "\033D"},
                    525:    {K_RIGHT,       "\033C"},
                    526:    {K_S_UP,        "\033a"},
                    527:    {K_S_DOWN,      "\033b"},
                    528:    {K_S_LEFT,      "\033d"},
                    529:    {K_S_RIGHT,     "\033c"},
                    530:    {K_F1,          "\033P"},
                    531:    {K_F2,          "\033Q"},
                    532:    {K_F3,          "\033R"},
                    533:    {K_F4,          "\033S"},
                    534:    {K_F5,          "\033T"},
                    535:    {K_F6,          "\033U"},
                    536:    {K_F7,          "\033V"},
                    537:    {K_F8,          "\033W"},
                    538:    {K_F9,          "\033X"},
                    539:    {K_F10,         "\033Y"},
                    540:    {K_S_F1,        "\033p"},
                    541:    {K_S_F2,        "\033q"},
                    542:    {K_S_F3,        "\033r"},
                    543:    {K_S_F4,        "\033s"},
                    544:    {K_S_F5,        "\033t"},
                    545:    {K_S_F6,        "\033u"},
                    546:    {K_S_F7,        "\033v"},
                    547:    {K_S_F8,        "\033w"},
                    548:    {K_S_F9,        "\033x"},
                    549:    {K_S_F10,       "\033y"},
                    550:    {K_INS,         "\033I"},
                    551:    {K_HOME,        "\033E"},
                    552:    {K_PAGEDOWN,    "\033b"},
                    553:    {K_PAGEUP,      "\033a"},
                    554: #  else
                    555:    {KS_AL,         "\033T"},
                    556:    {KS_DL,         "\033U"},
                    557:    {KS_CL,         "\033H\033J"},
                    558:    {KS_ME,         "\033SO"},
                    559:    {KS_MR,         "\033S2"},
                    560:    {KS_MS,         "\001"},
                    561: #  endif
                    562: # endif
                    563:
                    564: # if defined(UNIX) || defined(ALL_BUILTIN_TCAPS) || defined(SOME_BUILTIN_TCAPS) || defined(__EMX__)
                    565: /*
                    566:  * The xterm termcap is missing F14 and F15, because they send the same
                    567:  * codes as the undo and help key, although they don't work on all keyboards.
                    568:  */
                    569:    {KS_NAME,       "xterm"},
                    570:    {KS_CE,         "\033[K"},
                    571:    {KS_AL,         "\033[L"},
                    572: #  ifdef TERMINFO
                    573:    {KS_CAL,        "\033[%p1%dL"},
                    574: #  else
                    575:    {KS_CAL,        "\033[%dL"},
                    576: #  endif
                    577:    {KS_DL,         "\033[M"},
                    578: #  ifdef TERMINFO
                    579:    {KS_CDL,        "\033[%p1%dM"},
                    580: #  else
                    581:    {KS_CDL,        "\033[%dM"},
                    582: #  endif
                    583: #  ifdef TERMINFO
                    584:    {KS_CS,         "\033[%i%p1%d;%p2%dr"},
                    585: #  else
                    586:    {KS_CS,         "\033[%i%d;%dr"},
                    587: #  endif
                    588:    {KS_CL,         "\033[H\033[2J"},
                    589:    {KS_CD,         "\033[J"},
                    590:    {KS_ME,         "\033[m"},
                    591:    {KS_MR,         "\033[7m"},
                    592:    {KS_MD,         "\033[1m"},
                    593:    {KS_UE,         "\033[m"},
                    594:    {KS_US,         "\033[4m"},
                    595:    {KS_MS,         "\001"},
                    596: #  ifdef TERMINFO
                    597:    {KS_CM,         "\033[%i%p1%d;%p2%dH"},
                    598: #  else
                    599:    {KS_CM,         "\033[%i%d;%dH"},
                    600: #  endif
                    601:    {KS_SR,         "\033M"},
                    602: #  ifdef TERMINFO
                    603:    {KS_CRI,        "\033[%p1%dC"},
                    604: #  else
                    605:    {KS_CRI,        "\033[%dC"},
                    606: #  endif
                    607:    {KS_KS,         "\033[?1h\033="},
                    608:    {KS_KE,         "\033[?1l\033>"},
                    609: #  ifdef SAVE_XTERM_SCREEN
                    610:    {KS_TI,         "\0337\033[?47h"},
                    611:    {KS_TE,         "\033[2J\033[?47l\0338"},
                    612: #  endif
                    613:    {K_UP,          "\033OA"},
                    614:    {K_DOWN,        "\033OB"},
                    615:    {K_LEFT,        "\033OD"},
                    616:    {K_RIGHT,       "\033OC"},
                    617:    {K_S_UP,        "\033Ox"},
                    618:    {K_S_DOWN,      "\033Or"},
                    619:    {K_S_LEFT,      "\033Ot"},
                    620:    {K_S_RIGHT,     "\033Ov"},
                    621:    {K_F1,          "\033[11~"},
                    622:    {K_F2,          "\033[12~"},
                    623:    {K_F3,          "\033[13~"},
                    624:    {K_F4,          "\033[14~"},
                    625:    {K_F5,          "\033[15~"},
                    626:    {K_F6,          "\033[17~"},
                    627:    {K_F7,          "\033[18~"},
                    628:    {K_F8,          "\033[19~"},
                    629:    {K_F9,          "\033[20~"},
                    630:    {K_F10,         "\033[21~"},
                    631:    {K_F11,         "\033[23~"},
                    632:    {K_F12,         "\033[24~"},
                    633:    {K_HELP,        "\033[28~"},
                    634:    {K_UNDO,        "\033[26~"},
                    635:    {K_INS,         "\033[2~"},
                    636:    {K_HOME,        "\033[7~"},     /* also seen: "\033[1~" */
                    637:    {K_END,         "\033[8~"},     /* also seen: "\033[4~" */
                    638:    {K_PAGEUP,      "\033[5~"},
                    639:    {K_PAGEDOWN,    "\033[6~"},
                    640:    /* {K_DEL,          "\033[3~"}, not used */
                    641:
                    642:    {BT_EXTRA_KEYS, ""},
                    643:    {TERMCAP2KEY('k', '0'), "\033[10~"},    /* F0 */
                    644:    {TERMCAP2KEY('F', '3'), "\033[25~"},    /* F13 */
                    645:    {TERMCAP2KEY('F', '6'), "\033[29~"},    /* F16 */
                    646:    {TERMCAP2KEY('F', '7'), "\033[31~"},    /* F17 */
                    647:    {TERMCAP2KEY('F', '8'), "\033[32~"},    /* F18 */
                    648:    {TERMCAP2KEY('F', '9'), "\033[33~"},    /* F19 */
                    649:    {TERMCAP2KEY('F', 'A'), "\033[34~"},    /* F20 */
                    650: # endif
                    651:
                    652: # if defined(UNIX) || defined(ALL_BUILTIN_TCAPS)
                    653: /*
                    654:  * iris-ansi for Silicon Graphics machines.
                    655:  */
                    656:    {KS_NAME,       "iris-ansi"},
                    657:    {KS_CE,         "\033[K"},
                    658:    {KS_CD,         "\033[J"},
                    659:    {KS_AL,         "\033[L"},
                    660: #  ifdef TERMINFO
                    661:    {KS_CAL,        "\033[%p1%dL"},
                    662: #  else
                    663:    {KS_CAL,        "\033[%dL"},
                    664: #  endif
                    665:    {KS_DL,         "\033[M"},
                    666: #  ifdef TERMINFO
                    667:    {KS_CDL,        "\033[%p1%dM"},
                    668: #  else
                    669:    {KS_CDL,        "\033[%dM"},
                    670: #  endif
                    671: /*
                    672:  * This "cs" is not working correctly. What is the right one?
                    673:  */
                    674: #if 0
                    675: #  ifdef TERMINFO
                    676:    {KS_CS,         "\033[%i%p1%d;%p2%dr"},
                    677: #  else
                    678:     {KS_CS,        "\033[%i%d;%dr"},
                    679: #  endif
                    680: #endif
                    681:    {KS_CL,         "\033[H\033[2J"},
                    682:    {KS_VE,         "\033[9/y\033[12/y\033[=6l"},
                    683:    {KS_VS,         "\033[10/y\033[=1h\033[=2l\033[=6h"},
                    684:    {KS_SE,         "\033[m"},
                    685:    {KS_SO,         "\033[1;7m"},
                    686:    {KS_ME,         "\033[m"},
                    687:    {KS_MR,         "\033[7m"},
                    688:    {KS_MD,         "\033[1m"},
                    689:    {KS_UE,         "\033[m"},
                    690:    {KS_US,         "\033[4m"},
                    691:    {KS_MS,         "\001"}, /* does this really work? */
                    692: #  ifdef TERMINFO
                    693:    {KS_CM,         "\033[%i%p1%d;%p2%dH"},
                    694: #  else
                    695:    {KS_CM,         "\033[%i%d;%dH"},
                    696: #  endif
                    697:    {KS_SR,         "\033M"},
                    698: #  ifdef TERMINFO
                    699:    {KS_CRI,        "\033[%p1%dC"},
                    700: #  else
                    701:    {KS_CRI,        "\033[%dC"},
                    702: #  endif
                    703:    {K_UP,          "\033[A"},
                    704:    {K_DOWN,        "\033[B"},
                    705:    {K_LEFT,        "\033[D"},
                    706:    {K_RIGHT,       "\033[C"},
                    707:    {K_S_UP,        "\033[161q"},
                    708:    {K_S_DOWN,      "\033[164q"},
                    709:    {K_S_LEFT,      "\033[158q"},
                    710:    {K_S_RIGHT,     "\033[167q"},
                    711:    {K_F1,          "\033[001q"},
                    712:    {K_F2,          "\033[002q"},
                    713:    {K_F3,          "\033[003q"},
                    714:    {K_F4,          "\033[004q"},
                    715:    {K_F5,          "\033[005q"},
                    716:    {K_F6,          "\033[006q"},
                    717:    {K_F7,          "\033[007q"},
                    718:    {K_F8,          "\033[008q"},
                    719:    {K_F9,          "\033[009q"},
                    720:    {K_F10,         "\033[010q"},
                    721:    {K_F11,         "\033[011q"},
                    722:    {K_F12,         "\033[012q"},
                    723:    {K_S_F1,        "\033[013q"},
                    724:    {K_S_F2,        "\033[014q"},
                    725:    {K_S_F3,        "\033[015q"},
                    726:    {K_S_F4,        "\033[016q"},
                    727:    {K_S_F5,        "\033[017q"},
                    728:    {K_S_F6,        "\033[018q"},
                    729:    {K_S_F7,        "\033[019q"},
                    730:    {K_S_F8,        "\033[020q"},
                    731:    {K_S_F9,        "\033[021q"},
                    732:    {K_S_F10,       "\033[022q"},
                    733:    {K_S_F11,       "\033[023q"},
                    734:    {K_S_F12,       "\033[024q"},
                    735:    {K_INS,         "\033[139q"},
                    736:    {K_HOME,        "\033[H"},
                    737:    {K_END,         "\033[146q"},
                    738:    {K_PAGEUP,      "\033[150q"},
                    739:    {K_PAGEDOWN,    "\033[154q"},
                    740: # endif
                    741:
                    742: # if defined(DEBUG) || defined(ALL_BUILTIN_TCAPS)
                    743: /*
                    744:  * for debugging
                    745:  */
                    746:    {KS_NAME,       "debug"},
                    747:    {KS_CE,         "[CE]"},
                    748:    {KS_CD,         "[CD]"},
                    749:    {KS_AL,         "[AL]"},
                    750: #  ifdef TERMINFO
                    751:    {KS_CAL,        "[CAL%p1%d]"},
                    752: #  else
                    753:    {KS_CAL,        "[CAL%d]"},
                    754: #  endif
                    755:    {KS_DL,         "[DL]"},
                    756: #  ifdef TERMINFO
                    757:    {KS_CDL,        "[CDL%p1%d]"},
                    758: #  else
                    759:    {KS_CDL,        "[CDL%d]"},
                    760: #  endif
                    761: #  ifdef TERMINFO
                    762:    {KS_CS,         "[%dCS%p1%d]"},
                    763: #  else
                    764:    {KS_CS,         "[%dCS%d]"},
                    765: #  endif
                    766:    {KS_CL,         "[CL]"},
                    767:    {KS_VI,         "[VI]"},
                    768:    {KS_VE,         "[VE]"},
                    769:    {KS_VS,         "[VS]"},
                    770:    {KS_ME,         "[ME]"},
                    771:    {KS_MR,         "[MR]"},
                    772:    {KS_MD,         "[MD]"},
                    773:    {KS_SE,         "[SE]"},
                    774:    {KS_SO,         "[SO]"},
                    775:    {KS_UE,         "[UE]"},
                    776:    {KS_US,         "[US]"},
                    777:    {KS_MS,         "[MS]"},
                    778: #  ifdef TERMINFO
                    779:    {KS_CM,         "[%p1%dCM%p2%d]"},
                    780: #  else
                    781:    {KS_CM,         "[%dCM%d]"},
                    782: #  endif
                    783:    {KS_SR,         "[SR]"},
                    784: #  ifdef TERMINFO
                    785:    {KS_CRI,        "[CRI%p1%d]"},
                    786: #  else
                    787:    {KS_CRI,        "[CRI%d]"},
                    788: #  endif
                    789:    {KS_VB,         "[VB]"},
                    790:    {KS_KS,         "[KS]"},
                    791:    {KS_KE,         "[KE]"},
                    792:    {KS_TI,         "[TI]"},
                    793:    {KS_TE,         "[TE]"},
                    794:    {K_UP,          "[KU]"},
                    795:    {K_DOWN,        "[KD]"},
                    796:    {K_LEFT,        "[KL]"},
                    797:    {K_RIGHT,       "[KR]"},
                    798:    {K_S_UP,        "[S-KU]"},
                    799:    {K_S_DOWN,      "[S-KD]"},
                    800:    {K_S_LEFT,      "[S-KL]"},
                    801:    {K_S_RIGHT,     "[S-KR]"},
                    802:    {K_F1,          "[F1]"},
                    803:    {K_F2,          "[F2]"},
                    804:    {K_F3,          "[F3]"},
                    805:    {K_F4,          "[F4]"},
                    806:    {K_F5,          "[F5]"},
                    807:    {K_F6,          "[F6]"},
                    808:    {K_F7,          "[F7]"},
                    809:    {K_F8,          "[F8]"},
                    810:    {K_F9,          "[F9]"},
                    811:    {K_F10,         "[F10]"},
                    812:    {K_F11,         "[F11]"},
                    813:    {K_F12,         "[F12]"},
                    814:    {K_S_F1,        "[S-F1]"},
                    815:    {K_S_F2,        "[S-F2]"},
                    816:    {K_S_F3,        "[S-F3]"},
                    817:    {K_S_F4,        "[S-F4]"},
                    818:    {K_S_F5,        "[S-F5]"},
                    819:    {K_S_F6,        "[S-F6]"},
                    820:    {K_S_F7,        "[S-F7]"},
                    821:    {K_S_F8,        "[S-F8]"},
                    822:    {K_S_F9,        "[S-F9]"},
                    823:    {K_S_F10,       "[S-F10]"},
                    824:    {K_S_F11,       "[S-F11]"},
                    825:    {K_S_F12,       "[S-F12]"},
                    826:    {K_HELP,        "[HELP]"},
                    827:    {K_UNDO,        "[UNDO]"},
                    828:    {K_BS,          "[BS]"},
                    829:    {K_INS,         "[INS]"},
                    830:    {K_DEL,         "[DEL]"},
                    831:    {K_HOME,        "[HOME]"},
                    832:    {K_END,         "[END]"},
                    833:    {K_PAGEUP,      "[PAGEUP]"},
                    834:    {K_PAGEDOWN,    "[PAGEDOWN]"},
                    835:    {K_MOUSE,       "[MOUSE]"},
                    836: # endif
                    837:
                    838: #endif /* NO_BUILTIN_TCAPS */
                    839:
                    840: /*
                    841:  * The most minimal terminal: only clear screen and cursor positioning
                    842:  * Always included.
                    843:  */
                    844:    {KS_NAME,       "dumb"},
                    845:    {KS_CL,         "\014"},
                    846: #ifdef TERMINFO
                    847:    {KS_CM,         "\033[%i%p1%d;%p2%dH"},
                    848: #else
                    849:    {KS_CM,         "\033[%i%d;%dH"},
                    850: #endif
                    851:
                    852: /*
                    853:  * end marker
                    854:  */
                    855:    {KS_NAME,       NULL}
                    856:
                    857: };     /* end of builtin_termcaps */
                    858:
                    859: /*
                    860:  * DEFAULT_TERM is used, when no terminal is specified with -T option or $TERM.
                    861:  */
                    862: #ifdef AMIGA
                    863: # define DEFAULT_TERM  (char_u *)"amiga"
                    864: #endif /* AMIGA */
                    865:
                    866: #ifdef WIN32
                    867: # define DEFAULT_TERM  (char_u *)"win32"
                    868: #endif /* WIN32 */
                    869:
                    870: #ifdef MSDOS
                    871: # define DEFAULT_TERM  (char_u *)"pcterm"
                    872: #endif /* MSDOS */
                    873:
                    874: #if defined(UNIX) && !defined(MINT)
                    875: # define DEFAULT_TERM  (char_u *)"ansi"
                    876: #endif /* UNIX */
                    877:
                    878: #ifdef MINT
                    879: # define DEFAULT_TERM  (char_u *)"vt52"
                    880: #endif /* MINT */
                    881:
                    882: #ifdef __EMX__
                    883: # define DEFAULT_TERM  (char_u *)"os2ansi"
                    884: #endif /* __EMX__ */
                    885:
                    886: #ifdef VMS
                    887: # define DEFAULT_TERM  (char_u *)"ansi"
                    888: #endif /* VMS */
                    889:
                    890: /*
                    891:  * Term_strings contains currently used terminal output strings.
                    892:  * It is initialized with the default values by parse_builtin_tcap().
                    893:  * The values can be changed by setting the option with the same name.
                    894:  */
                    895: char_u *(term_strings[KS_LAST + 1]);
                    896:
                    897: static int     need_gather = FALSE;            /* need to fill termleader[] */
                    898: static char_u  termleader[256 + 1];            /* for check_termcode() */
                    899:
                    900:    static struct builtin_term *
                    901: find_builtin_term(term)
                    902:    char_u      *term;
                    903: {
                    904:    struct builtin_term *p;
                    905:
                    906:    p = builtin_termcaps;
                    907:    while (p->bt_string != NULL)
                    908:    {
                    909:        if (p->bt_entry == KS_NAME)
                    910:        {
                    911: #ifdef UNIX
                    912:            if (STRCMP(p->bt_string, "iris-ansi") == 0 && is_iris_ansi(term))
                    913:                return p;
                    914:            else if (STRCMP(p->bt_string, "xterm") == 0 && is_xterm(term))
                    915:                return p;
                    916:            else
                    917: #endif
                    918:                if (STRCMP(term, p->bt_string) == 0)
                    919:                    return p;
                    920:        }
                    921:        ++p;
                    922:    }
                    923:    return p;
                    924: }
                    925:
                    926: /*
                    927:  * Parsing of the builtin termcap entries.
                    928:  * Caller should check if 'name' is a valid builtin term.
                    929:  * The terminal's name is not set, as this is already done in termcapinit().
                    930:  */
                    931:    static void
                    932: parse_builtin_tcap(term)
                    933:    char_u  *term;
                    934: {
                    935:    struct builtin_term     *p;
                    936:    char_u                  name[2];
                    937:
                    938:    p = find_builtin_term(term);
                    939:    for (++p; p->bt_entry != KS_NAME && p->bt_entry != BT_EXTRA_KEYS; ++p)
                    940:    {
                    941:        if (p->bt_entry < 0x100)    /* KS_xx entry */
                    942:        {
                    943:            if (term_strings[p->bt_entry] == NULL ||
                    944:                                    term_strings[p->bt_entry] == empty_option)
                    945:                term_strings[p->bt_entry] = (char_u *)p->bt_string;
                    946:        }
                    947:        else
                    948:        {
                    949:            name[0] = KEY2TERMCAP0(p->bt_entry);
                    950:            name[1] = KEY2TERMCAP1(p->bt_entry);
                    951:            if (find_termcode(name) == NULL)
                    952:                add_termcode(name, (char_u *)p->bt_string);
                    953:        }
                    954:    }
                    955: }
                    956:
                    957: /*
                    958:  * Set terminal options for terminal "term".
                    959:  * Return OK if terminal 'term' was found in a termcap, FAIL otherwise.
                    960:  *
                    961:  * While doing this, until ttest(), some options may be NULL, be careful.
                    962:  */
                    963:    int
                    964: set_termname(term)
                    965:    char_u *term;
                    966: {
                    967:    struct builtin_term *termp;
                    968: #ifdef HAVE_TGETENT
                    969:    int         builtin_first = p_tbi;
                    970:    int         try;
                    971:    int         termcap_cleared = FALSE;
                    972: #endif
                    973:    int         width = 0, height = 0;
                    974:    char_u      *error_msg = NULL;
                    975:    char_u      *bs_p, *del_p;
                    976:
                    977:    if (is_builtin_term(term))
                    978:    {
                    979:        term += 8;
                    980: #ifdef HAVE_TGETENT
                    981:        builtin_first = 1;
                    982: #endif
                    983:    }
                    984:
                    985: /*
                    986:  * If HAVE_TGETENT is not defined, only the builtin termcap is used, otherwise:
                    987:  *   If builtin_first is TRUE:
                    988:  *     0. try builtin termcap
                    989:  *     1. try external termcap
                    990:  *     2. if both fail default to a builtin terminal
                    991:  *   If builtin_first is FALSE:
                    992:  *     1. try external termcap
                    993:  *     2. try builtin termcap, if both fail default to a builtin terminal
                    994:  */
                    995: #ifdef HAVE_TGETENT
                    996:    for (try = builtin_first ? 0 : 1; try < 3; ++try)
                    997:    {
                    998:        /*
                    999:         * Use external termcap
                   1000:         */
                   1001:        if (try == 1)
                   1002:        {
                   1003:            char_u          *p;
                   1004:            static char_u   tstrbuf[TBUFSZ];
                   1005:            int             i;
                   1006:            char_u          tbuf[TBUFSZ];
                   1007:            char_u          *tp = tstrbuf;
                   1008:            static char     *(key_names[]) =
                   1009:                            {
                   1010:                            "ku", "kd", "kr",   /* "kl" is a special case */
                   1011: # ifdef ARCHIE
                   1012:                            "su", "sd",         /* Termcap code made up! */
                   1013: # endif
                   1014:                            "#4", "%i",
                   1015:                            "k1", "k2", "k3", "k4", "k5", "k6",
                   1016:                            "k7", "k8", "k9", "k;", "F1", "F2",
                   1017:                            "%1", "&8", "kb", "kI", "kD", "kh",
                   1018:                            "@7", "kP", "kN",
                   1019:                            NULL
                   1020:                            };
                   1021:            static struct {
                   1022:                            int dest;       /* index in term_strings[] */
                   1023:                            char *name;     /* termcap name for string */
                   1024:                          } string_names[] =
                   1025:                            {   {KS_CE, "ce"}, {KS_AL, "al"}, {KS_CAL, "AL"},
                   1026:                                {KS_DL, "dl"}, {KS_CDL, "DL"}, {KS_CS, "cs"},
                   1027:                                {KS_CL, "cl"}, {KS_CD, "cd"},
                   1028:                                {KS_VI, "vi"}, {KS_VE, "ve"},
                   1029:                                {KS_VS, "vs"}, {KS_ME, "me"}, {KS_MR, "mr"},
                   1030:                                {KS_MD, "md"}, {KS_SE, "se"}, {KS_SO, "so"},
                   1031:                                {KS_CZH, "ZH"}, {KS_CZR, "ZR"}, {KS_UE, "ue"},
                   1032:                                {KS_US, "us"}, {KS_CM, "cm"}, {KS_SR, "sr"},
                   1033:                                {KS_CRI, "RI"}, {KS_VB, "vb"}, {KS_KS, "ks"},
                   1034:                                {KS_KE, "ke"}, {KS_TI, "ti"}, {KS_TE, "te"},
                   1035:                                {0, NULL}
                   1036:                            };
                   1037:
                   1038:            /*
                   1039:             * If the external termcap does not have a matching entry, try the
                   1040:             * builtin ones.
                   1041:             */
                   1042:            if ((error_msg = tgetent_error(tbuf, term)) == NULL)
                   1043:            {
                   1044:                if (!termcap_cleared)
                   1045:                {
                   1046:                    clear_termoptions();        /* clear old options */
                   1047:                    termcap_cleared = TRUE;
                   1048:                }
                   1049:
                   1050:            /* get output strings */
                   1051:                for (i = 0; string_names[i].name != NULL; ++i)
                   1052:                {
                   1053:                    if (term_strings[string_names[i].dest] == NULL ||
                   1054:                               term_strings[string_names[i].dest] == empty_option)
                   1055:                        term_strings[string_names[i].dest] =
                   1056:                                               TGETSTR(string_names[i].name, &tp);
                   1057:                }
                   1058:
                   1059:                if ((T_MS == NULL || T_MS == empty_option) && tgetflag("ms"))
                   1060:                    T_MS = (char_u *)"yes";
                   1061:                if ((T_DB == NULL || T_DB == empty_option) && tgetflag("db"))
                   1062:                    T_DB = (char_u *)"yes";
                   1063:                if ((T_DA == NULL || T_DA == empty_option) && tgetflag("da"))
                   1064:                    T_DA = (char_u *)"yes";
                   1065:
                   1066:
                   1067:            /* get key codes */
                   1068:
                   1069:                for (i = 0; key_names[i] != NULL; ++i)
                   1070:                {
                   1071:                    if (find_termcode((char_u *)key_names[i]) == NULL)
                   1072:                        add_termcode((char_u *)key_names[i],
                   1073:                                                      TGETSTR(key_names[i], &tp));
                   1074:                }
                   1075:
                   1076:                    /* if cursor-left == backspace, ignore it (televideo 925) */
                   1077:                if (find_termcode((char_u *)"kl") == NULL)
                   1078:                {
                   1079:                    p = TGETSTR("kl", &tp);
                   1080:                    if (p != NULL && *p != Ctrl('H'))
                   1081:                        add_termcode((char_u *)"kl", p);
                   1082:                }
                   1083:
                   1084:                if (height == 0)
                   1085:                    height = tgetnum("li");
                   1086:                if (width == 0)
                   1087:                    width = tgetnum("co");
                   1088:
                   1089: # ifndef hpux
                   1090:                BC = (char *)TGETSTR("bc", &tp);
                   1091:                UP = (char *)TGETSTR("up", &tp);
                   1092:                p = TGETSTR("pc", &tp);
                   1093:                if (p)
                   1094:                    PC = *p;
                   1095: # endif /* hpux */
                   1096:            }
                   1097:        }
                   1098:        else        /* try == 0 || try == 2 */
                   1099: #endif /* HAVE_TGETENT */
                   1100:        /*
                   1101:         * Use builtin termcap
                   1102:         */
                   1103:        {
                   1104: #ifdef HAVE_TGETENT
                   1105:            /*
                   1106:             * If builtin termcap was already used, there is no need to search
                   1107:             * for the builtin termcap again, quit now.
                   1108:             */
                   1109:            if (try == 2 && builtin_first && termcap_cleared)
                   1110:                break;
                   1111: #endif
                   1112:            /*
                   1113:             * search for 'term' in builtin_termcaps[]
                   1114:             */
                   1115:            termp = find_builtin_term(term);
                   1116:            if (termp->bt_string == NULL)       /* did not find it */
                   1117:            {
                   1118: #ifdef HAVE_TGETENT
                   1119:                /*
                   1120:                 * If try == 0, first try the external termcap. If that is not
                   1121:                 * found we'll get back here with try == 2.
                   1122:                 * If termcap_cleared is set we used the external termcap,
                   1123:                 * don't complain about not finding the term in the builtin
                   1124:                 * termcap.
                   1125:                 */
                   1126:                if (try == 0)                   /* try external one */
                   1127:                    continue;
                   1128:                if (termcap_cleared)            /* found in external termcap */
                   1129:                    break;
                   1130: #endif
                   1131:
                   1132:                fprintf(stderr, "\r\n");
                   1133:                if (error_msg != NULL)
                   1134:                {
                   1135:                    fprintf(stderr, (char *)error_msg);
                   1136:                    fprintf(stderr, "\r\n");
                   1137:                }
                   1138:                fprintf(stderr, "'%s' not known. Available builtin terminals are:\r\n", term);
                   1139:                for (termp = &(builtin_termcaps[0]); termp->bt_string != NULL;
                   1140:                                                                      ++termp)
                   1141:                {
                   1142:                    if (termp->bt_entry == KS_NAME)
                   1143: #ifdef HAVE_TGETENT
                   1144:                        fprintf(stderr, "    builtin_%s\r\n", termp->bt_string);
                   1145: #else
                   1146:                        fprintf(stderr, "    %s\r\n", termp->bt_string);
                   1147: #endif
                   1148:                }
                   1149:                if (!starting)  /* when user typed :set term=xxx, quit here */
                   1150:                {
                   1151:                    screen_start();     /* don't know where cursor is now */
                   1152:                    wait_return(TRUE);
                   1153:                    return FAIL;
                   1154:                }
                   1155:                term = DEFAULT_TERM;
                   1156:                fprintf(stderr, "defaulting to '%s'\r\n", term);
                   1157:                screen_start();         /* don't know where cursor is now */
                   1158:                mch_delay(2000L, TRUE);
                   1159:                set_string_option((char_u *)"term", -1, term, TRUE);
                   1160:            }
                   1161:            flushbuf();
                   1162: #ifdef HAVE_TGETENT
                   1163:            if (!termcap_cleared)
                   1164:            {
                   1165: #endif
                   1166:                clear_termoptions();        /* clear old options */
                   1167: #ifdef HAVE_TGETENT
                   1168:                termcap_cleared = TRUE;
                   1169:            }
                   1170: #endif
                   1171:            parse_builtin_tcap(term);
                   1172: #ifdef USE_GUI
                   1173:            if (STRCMP(term, "gui") == 0)
                   1174:            {
                   1175:                flushbuf();
                   1176:                settmode(0);
                   1177:                gui_init();
                   1178:                if (!gui.in_use)        /* failed to start GUI */
                   1179:                    settmode(1);
                   1180:            }
                   1181: #endif /* USE_GUI */
                   1182:        }
                   1183: #ifdef HAVE_TGETENT
                   1184:    }
                   1185: #endif
                   1186:
                   1187: /*
                   1188:  * special: There is no info in the termcap about whether the cursor
                   1189:  * positioning is relative to the start of the screen or to the start of the
                   1190:  * scrolling region.  We just guess here. Only msdos pcterm is known to do it
                   1191:  * relative.
                   1192:  */
                   1193:    if (STRCMP(term, "pcterm") == 0)
                   1194:        T_CSC = (char_u *)"yes";
                   1195:    else
                   1196:        T_CSC = empty_option;
                   1197:
                   1198: #ifdef UNIX
                   1199: /*
                   1200:  * Any "stty" settings override the default for t_kb from the termcap.
                   1201:  * This is in unix.c, because it depends a lot on the version of unix that is
                   1202:  * being used.
                   1203:  * Don't do this when the GUI is active, it uses "t_kb" and "t_kD" directly.
                   1204:  */
                   1205: #ifdef USE_GUI
                   1206:    if (!gui.in_use)
                   1207: #endif
                   1208:        get_stty();
                   1209: #endif
                   1210:
                   1211: /*
                   1212:  * If the termcap has no entry for 'bs' and/or 'del' and the ioctl() also
                   1213:  * didn't work, use the default CTRL-H
                   1214:  * The default for t_kD is DEL, unless t_kb is DEL.
                   1215:  * The strsave'd strings are probably lost forever, well it's only two bytes.
                   1216:  * Don't do this when the GUI is active, it uses "t_kb" and "t_kD" directly.
                   1217:  */
                   1218: #ifdef USE_GUI
                   1219:    if (!gui.in_use)
                   1220: #endif
                   1221:    {
                   1222:        bs_p = find_termcode((char_u *)"kb");
                   1223:        del_p = find_termcode((char_u *)"kD");
                   1224:        if (bs_p == NULL || *bs_p == NUL)
                   1225:            add_termcode((char_u *)"kb", (bs_p = (char_u *)"\010"));
                   1226:        if ((del_p == NULL || *del_p == NUL) &&
                   1227:                                            (bs_p == NULL || *bs_p != '\177'))
                   1228:            add_termcode((char_u *)"kD", (char_u *)"\177");
                   1229:    }
                   1230:
                   1231: #ifdef USE_MOUSE
                   1232:    /*
                   1233:     * recognize mouse events in the input stream for xterm, msdos and win32
                   1234:     */
                   1235:    {
                   1236:        char_u  name[2];
                   1237:
                   1238:        name[0] = KS_MOUSE;
                   1239:        name[1] = K_FILLER;
                   1240: # ifdef UNIX
                   1241:        if (is_xterm(term))
                   1242:            add_termcode(name, (char_u *)"\033[M");
                   1243: # else
                   1244:        add_termcode(name, (char_u *)"\233M");
                   1245: # endif
                   1246:    }
                   1247: #endif
                   1248:
                   1249: #if defined(AMIGA) || defined(MSDOS) || defined(WIN32) || defined(OS2)
                   1250:        /* DEFAULT_TERM indicates that it is the machine console. */
                   1251:    if (STRCMP(term, DEFAULT_TERM))
                   1252:        term_console = FALSE;
                   1253:    else
                   1254:    {
                   1255:        term_console = TRUE;
                   1256: # ifdef AMIGA
                   1257:        win_resize_on();        /* enable window resizing reports */
                   1258: # endif
                   1259:    }
                   1260: #endif
                   1261:
                   1262: #ifdef UNIX
                   1263: /*
                   1264:  * 'ttyfast' is default on for xterm, iris-ansi and a few others.
                   1265:  */
                   1266:    if (is_fastterm(term))
                   1267:        p_tf = TRUE;
                   1268: #endif
                   1269: #if defined(AMIGA) || defined(MSDOS) || defined(WIN32) || defined(OS2)
                   1270: /*
                   1271:  * 'ttyfast' is default on Amiga, MSDOS, Win32, and OS/2 consoles
                   1272:  */
                   1273:    if (term_console)
                   1274:        p_tf = TRUE;
                   1275: #endif
                   1276:
                   1277:    ttest(TRUE);        /* make sure we have a valid set of terminal codes */
                   1278:    set_term_defaults();    /* use current values as defaults */
                   1279:
                   1280:    /*
                   1281:     * Initialize the terminal with the appropriate termcap codes.
                   1282:     * Set the mouse and window title if possible.
                   1283:     * Don't do this when starting, need to parse the .vimrc first, because it
                   1284:     * may redefine t_TI etc.
                   1285:     */
                   1286:    if (!starting)
                   1287:    {
                   1288:        starttermcap();         /* may change terminal mode */
                   1289: #ifdef USE_MOUSE
                   1290:        setmouse();             /* may start using the mouse */
                   1291: #endif
                   1292:        maketitle();            /* may display window title */
                   1293:    }
                   1294:
                   1295:        /* display initial screen after ttest() checking. jw. */
                   1296:    if (width <= 0 || height <= 0)
                   1297:    {
                   1298:        /* termcap failed to report size */
                   1299:        /* set defaults, in case mch_get_winsize also fails */
                   1300:        width = 80;
                   1301: #if defined MSDOS  ||  defined WIN32
                   1302:        height = 25;        /* console is often 25 lines */
                   1303: #else
                   1304:        height = 24;        /* most terminals are 24 lines */
                   1305: #endif
                   1306:    }
                   1307:    set_winsize(width, height, FALSE);  /* may change Rows */
                   1308:    if (!starting)
                   1309:    {
                   1310:        if (scroll_region)
                   1311:            scroll_region_reset();          /* In case Rows changed */
                   1312:        check_map_keycodes();   /* check mappings for terminal codes used */
                   1313:    }
                   1314:
                   1315:    return OK;
                   1316: }
                   1317:
                   1318: #ifdef HAVE_TGETENT
                   1319: /*
                   1320:  * Call tgetent()
                   1321:  * Return error message if it fails, NULL if it's OK.
                   1322:  */
                   1323:    static char_u *
                   1324: tgetent_error(tbuf, term)
                   1325:    char_u  *tbuf;
                   1326:    char_u  *term;
                   1327: {
                   1328:    int     i;
                   1329:
                   1330:    i = TGETENT(tbuf, term);
                   1331:    if (i == -1)
                   1332:        return (char_u *)"Cannot open termcap file";
                   1333:    if (i == 0)
                   1334: #ifdef TERMINFO
                   1335:        return (char_u *)"Terminal entry not found in terminfo";
                   1336: #else
                   1337:        return (char_u *)"Terminal entry not found in termcap";
                   1338: #endif
                   1339:    return NULL;
                   1340: }
                   1341: #endif /* HAVE_TGETENT */
                   1342:
                   1343: #if defined(HAVE_TGETENT) && (defined(UNIX) || defined(__EMX__))
                   1344: /*
                   1345:  * Get Columns and Rows from the termcap. Used after a window signal if the
                   1346:  * ioctl() fails. It doesn't make sense to call tgetent each time if the "co"
                   1347:  * and "li" entries never change. But on some systems this works.
                   1348:  * Errors while getting the entries are ignored.
                   1349:  */
                   1350:    void
                   1351: getlinecol()
                   1352: {
                   1353:    char_u          tbuf[TBUFSZ];
                   1354:
                   1355:    if (term_strings[KS_NAME] != NULL && TGETENT(tbuf, term_strings[KS_NAME]) > 0)
                   1356:    {
                   1357:        if (Columns == 0)
                   1358:            Columns = tgetnum("co");
                   1359:        if (Rows == 0)
                   1360:            Rows = tgetnum("li");
                   1361:    }
                   1362: }
                   1363: #endif /* defined(HAVE_TGETENT) && defined(UNIX) */
                   1364:
                   1365: /*
                   1366:  * Get a string entry from the termcap and add it to the list of termcodes.
                   1367:  * Used for <t_xx> special keys.
                   1368:  * Give an error message for failure when not sourcing.
                   1369:  * If force given, replace an existing entry.
                   1370:  * Return FAIL if the entry was not found, OK if the entry was added.
                   1371:  */
                   1372:    int
                   1373: add_termcap_entry(name, force)
                   1374:    char_u  *name;
                   1375:    int     force;
                   1376: {
                   1377:    char_u  *term;
                   1378:    int     key;
                   1379:    struct builtin_term *termp;
                   1380: #ifdef HAVE_TGETENT
                   1381:    char_u  *string;
                   1382:    int     i;
                   1383:    int     builtin_first;
                   1384:    char_u  tbuf[TBUFSZ];
                   1385:    char_u  tstrbuf[TBUFSZ];
                   1386:    char_u  *tp = tstrbuf;
                   1387:    char_u  *error_msg = NULL;
                   1388: #endif
                   1389:
                   1390: /*
                   1391:  * If the GUI is running or will start in a moment, we only support the keys
                   1392:  * that the GUI can produce.
                   1393:  */
                   1394: #ifdef USE_GUI
                   1395:    if (gui.in_use || gui.starting)
                   1396:        return gui_mch_haskey(name);
                   1397: #endif
                   1398:
                   1399:    if (!force && find_termcode(name) != NULL)      /* it's already there */
                   1400:        return OK;
                   1401:
                   1402:    term = term_strings[KS_NAME];
                   1403:    if (term == NULL)                       /* just in case */
                   1404:        return FAIL;
                   1405:
                   1406:    if (is_builtin_term(term))              /* name starts with "builtin_" */
                   1407:    {
                   1408:        term += 8;
                   1409: #ifdef HAVE_TGETENT
                   1410:        builtin_first = TRUE;
                   1411: #endif
                   1412:    }
                   1413: #ifdef HAVE_TGETENT
                   1414:    else
                   1415:        builtin_first = p_tbi;
                   1416: #endif
                   1417:
                   1418: #ifdef HAVE_TGETENT
                   1419: /*
                   1420:  * We can get the entry from the builtin termcap and from the external one.
                   1421:  * If 'ttybuiltin' is on or the terminal name starts with "builtin_", try
                   1422:  * builtin termcap first.
                   1423:  * If 'ttybuiltin' is off, try external termcap first.
                   1424:  */
                   1425:    for (i = 0; i < 2; ++i)
                   1426:    {
                   1427:        if (!builtin_first == i)
                   1428: #endif
                   1429:        /*
                   1430:         * Search in builtin termcap
                   1431:         */
                   1432:        {
                   1433:            termp = find_builtin_term(term);
                   1434:            if (termp->bt_string != NULL)       /* found it */
                   1435:            {
                   1436:                key = TERMCAP2KEY(name[0], name[1]);
                   1437:                while (termp->bt_entry != KS_NAME)
                   1438:                {
                   1439:                    if (termp->bt_entry == key)
                   1440:                    {
                   1441:                        add_termcode(name, (char_u *)termp->bt_string);
                   1442:                        return OK;
                   1443:                    }
                   1444:                    ++termp;
                   1445:                }
                   1446:            }
                   1447:        }
                   1448: #ifdef HAVE_TGETENT
                   1449:        else
                   1450:        /*
                   1451:         * Search in external termcap
                   1452:         */
                   1453:        {
                   1454:            error_msg = tgetent_error(tbuf, term);
                   1455:            if (error_msg == NULL)
                   1456:            {
                   1457:                string = TGETSTR((char *)name, &tp);
                   1458:                if (string != NULL && *string != NUL)
                   1459:                {
                   1460:                    add_termcode(name, string);
                   1461:                    return OK;
                   1462:                }
                   1463:            }
                   1464:        }
                   1465:    }
                   1466: #endif
                   1467:
                   1468:    if (sourcing_name == NULL)
                   1469:    {
                   1470: #ifdef HAVE_TGETENT
                   1471:        if (error_msg != NULL)
                   1472:            EMSG(error_msg);
                   1473:        else
                   1474: #endif
                   1475:            EMSG2("No \"%s\" entry in termcap", name);
                   1476:    }
                   1477:    return FAIL;
                   1478: }
                   1479:
                   1480:    static int
                   1481: is_builtin_term(name)
                   1482:    char_u  *name;
                   1483: {
                   1484:    return (STRNCMP(name, "builtin_", (size_t)8) == 0);
                   1485: }
                   1486:
                   1487: static char_u *tltoa __PARMS((unsigned long));
                   1488:
                   1489:    static char_u *
                   1490: tltoa(i)
                   1491:    unsigned long i;
                   1492: {
                   1493:    static char_u buf[16];
                   1494:    char_u      *p;
                   1495:
                   1496:    p = buf + 15;
                   1497:    *p = '\0';
                   1498:    do
                   1499:    {
                   1500:        --p;
                   1501:        *p = (char_u) (i % 10 + '0');
                   1502:        i /= 10;
                   1503:    }
                   1504:    while (i > 0 && p > buf);
                   1505:    return p;
                   1506: }
                   1507:
                   1508: #ifndef HAVE_TGETENT
                   1509:
                   1510: /*
                   1511:  * minimal tgoto() implementation.
                   1512:  * no padding and we only parse for %i %d and %+char
                   1513:  */
                   1514: char *tgoto __ARGS((char *, int, int));
                   1515:
                   1516:    char *
                   1517: tgoto(cm, x, y)
                   1518:    char *cm;
                   1519:    int x, y;
                   1520: {
                   1521:    static char buf[30];
                   1522:    char *p, *s, *e;
                   1523:
                   1524:    if (!cm)
                   1525:        return "OOPS";
                   1526:    e = buf + 29;
                   1527:    for (s = buf; s < e && *cm; cm++)
                   1528:    {
                   1529:        if (*cm != '%')
                   1530:        {
                   1531:            *s++ = *cm;
                   1532:            continue;
                   1533:        }
                   1534:        switch (*++cm)
                   1535:        {
                   1536:        case 'd':
                   1537:            p = (char *)tltoa((unsigned long)y);
                   1538:            y = x;
                   1539:            while (*p)
                   1540:                *s++ = *p++;
                   1541:            break;
                   1542:        case 'i':
                   1543:            x++;
                   1544:            y++;
                   1545:            break;
                   1546:        case '+':
                   1547:            *s++ = (char)(*++cm + y);
                   1548:            y = x;
                   1549:            break;
                   1550:        case '%':
                   1551:            *s++ = *cm;
                   1552:            break;
                   1553:        default:
                   1554:            return "OOPS";
                   1555:        }
                   1556:    }
                   1557:    *s = '\0';
                   1558:    return buf;
                   1559: }
                   1560:
                   1561: #endif /* HAVE_TGETENT */
                   1562:
                   1563: /*
                   1564:  * Set the terminal name to "term" and initialize the terminal options.
                   1565:  * If "term" is NULL or empty, get the terminal name from the environment.
                   1566:  * If that fails, use the default terminal name.
                   1567:  */
                   1568:    void
                   1569: termcapinit(term)
                   1570:    char_u *term;
                   1571: {
                   1572:    if (!term || !*term)
                   1573:        term = vim_getenv((char_u *)"TERM");
                   1574:    if (!term || !*term)
                   1575:        term = DEFAULT_TERM;
                   1576:    set_string_option((char_u *)"term", -1, term, TRUE);
                   1577:    /*
                   1578:     * Avoid using "term" here, because the next vim_getenv() may overwrite it.
                   1579:     */
                   1580:    set_termname(term_strings[KS_NAME] != NULL ? term_strings[KS_NAME] : term);
                   1581: }
                   1582:
                   1583: /*
                   1584:  * the number of calls to mch_write is reduced by using the buffer "outbuf"
                   1585:  */
                   1586: #undef BSIZE           /* hpux has BSIZE in sys/option.h */
                   1587: #define BSIZE  2048
                   1588: static char_u          outbuf[BSIZE];
                   1589: static int             bpos = 0;       /* number of chars in outbuf */
                   1590:
                   1591: /*
                   1592:  * flushbuf(): flush the output buffer
                   1593:  */
                   1594:    void
                   1595: flushbuf()
                   1596: {
                   1597:    if (bpos != 0)
                   1598:    {
                   1599:        mch_write(outbuf, bpos);
                   1600:        bpos = 0;
                   1601:    }
                   1602: }
                   1603:
                   1604: #ifdef USE_GUI
                   1605: /*
                   1606:  * trash_output_buf(): Throw away the contents of the output buffer
                   1607:  */
                   1608:    void
                   1609: trash_output_buf()
                   1610: {
                   1611:    bpos = 0;
                   1612: }
                   1613: #endif
                   1614:
                   1615: /*
                   1616:  * outchar(c): put a character into the output buffer.
                   1617:  *            Flush it if it becomes full.
                   1618:  * This should not be used for outputting text on the screen (use functions like
                   1619:  * msg_outstr() and screen_outchar() for that).
                   1620:  */
                   1621:    void
                   1622: outchar(c)
                   1623:    unsigned    c;
                   1624: {
                   1625: #if defined(UNIX) || defined(VMS) || defined(AMIGA)
                   1626:    if (c == '\n')      /* turn LF into CR-LF (CRMOD doesn't seem to do this) */
                   1627:        outchar('\r');
                   1628: #endif
                   1629:
                   1630:    outbuf[bpos++] = c;
                   1631:
                   1632:    /* For testing we flush each time. */
                   1633:    if (bpos >= BSIZE || p_wd)
                   1634:        flushbuf();
                   1635: }
                   1636:
                   1637: static void outchar_nf __ARGS((unsigned));
                   1638:
                   1639: /*
                   1640:  * outchar_nf(c): like outchar(), but don't flush when p_wd is set
                   1641:  */
                   1642:    static void
                   1643: outchar_nf(c)
                   1644:    unsigned    c;
                   1645: {
                   1646: #if defined(UNIX) || defined(VMS) || defined(AMIGA)
                   1647:    if (c == '\n')      /* turn LF into CR-LF (CRMOD doesn't seem to do this) */
                   1648:        outchar_nf('\r');
                   1649: #endif
                   1650:
                   1651:    outbuf[bpos++] = c;
                   1652:
                   1653:    /* For testing we flush each time. */
                   1654:    if (bpos >= BSIZE)
                   1655:        flushbuf();
                   1656: }
                   1657:
                   1658: /*
                   1659:  * a never-padding outstr.
                   1660:  * use this whenever you don't want to run the string through tputs.
                   1661:  * tputs above is harmless, but tputs from the termcap library
                   1662:  * is likely to strip off leading digits, that it mistakes for padding
                   1663:  * information. (jw)
                   1664:  * This should only be used for writing terminal codes, not for outputting
                   1665:  * normal text (use functions like msg_outstr() and screen_outchar() for that).
                   1666:  */
                   1667:    void
                   1668: outstrn(s)
                   1669:    char_u *s;
                   1670: {
                   1671:    if (bpos > BSIZE - 20)      /* avoid terminal strings being split up */
                   1672:        flushbuf();
                   1673:    while (*s)
                   1674:        outchar_nf(*s++);
                   1675:
                   1676:    /* For testing we write one string at a time. */
                   1677:    if (p_wd)
                   1678:        flushbuf();
                   1679: }
                   1680:
                   1681: /*
                   1682:  * outstr(s): put a string character at a time into the output buffer.
                   1683:  * If HAVE_TGETENT is defined use the termcap parser. (jw)
                   1684:  * This should only be used for writing terminal codes, not for outputting
                   1685:  * normal text (use functions like msg_outstr() and screen_outchar() for that).
                   1686:  */
                   1687:    void
                   1688: outstr(s)
                   1689:    register char_u          *s;
                   1690: {
                   1691:    if (bpos > BSIZE - 20)      /* avoid terminal strings being split up */
                   1692:        flushbuf();
                   1693:    if (s)
                   1694: #ifdef HAVE_TGETENT
                   1695:        tputs((char *)s, 1, TPUTSFUNCAST outchar_nf);
                   1696: #else
                   1697:        while (*s)
                   1698:            outchar_nf(*s++);
                   1699: #endif
                   1700:
                   1701:    /* For testing we write one string at a time. */
                   1702:    if (p_wd)
                   1703:        flushbuf();
                   1704: }
                   1705:
                   1706: /*
                   1707:  * cursor positioning using termcap parser. (jw)
                   1708:  */
                   1709:    void
                   1710: windgoto(row, col)
                   1711:    int     row;
                   1712:    int     col;
                   1713: {
                   1714:    if (col != screen_cur_col || row != screen_cur_row)
                   1715:    {
                   1716:        /*
                   1717:         * When positioning on the same row, column 0, use CR, it's just one
                   1718:         * character.  Don't do this when the cursor has moved past the end of
                   1719:         * the line, the cursor position is undefined then.
                   1720:         */
                   1721:        if (row == screen_cur_row && col == 0 && screen_cur_col < Columns)
                   1722:        {
                   1723:            outchar('\r');
                   1724:            screen_cur_col = 0;
                   1725:        }
                   1726:        else
                   1727:        {
                   1728:            OUTSTR(tgoto((char *)T_CM, col, row));
                   1729:            screen_cur_col = col;
                   1730:            screen_cur_row = row;
                   1731:        }
                   1732:    }
                   1733: }
                   1734:
                   1735: /*
                   1736:  * Set cursor to current position.
                   1737:  */
                   1738:
                   1739:    void
                   1740: setcursor()
                   1741: {
                   1742:    if (!RedrawingDisabled)
                   1743:        windgoto(curwin->w_winpos + curwin->w_row,
                   1744: #ifdef RIGHTLEFT
                   1745:                curwin->w_p_rl ? (int)Columns - 1 - curwin->w_col :
                   1746: #endif
                   1747:                                                            curwin->w_col);
                   1748: }
                   1749:
                   1750: /*
                   1751:  * Make sure we have a valid set or terminal options.
                   1752:  * Replace all entries that are NULL by empty_option
                   1753:  */
                   1754:    void
                   1755: ttest(pairs)
                   1756:    int pairs;
                   1757: {
                   1758:    char *t = NULL;
                   1759:
                   1760:    check_options();                /* make sure no options are NULL */
                   1761:
                   1762:   /* hard requirements */
                   1763:    if (*T_CL == NUL)               /* erase display */
                   1764:        t = "cl";
                   1765:    if (*T_CM == NUL)               /* cursor motion */
                   1766:        t = "cm";
                   1767:
                   1768:    if (t)
                   1769:        EMSG2("terminal capability %s required", t);
                   1770:
                   1771: /*
                   1772:  * if "cs" defined, use a scroll region, it's faster.
                   1773:  */
                   1774:    if (*T_CS != NUL)
                   1775:        scroll_region = TRUE;
                   1776:    else
                   1777:        scroll_region = FALSE;
                   1778:
                   1779:    if (pairs)
                   1780:    {
                   1781:      /* optional pairs */
                   1782:            /* TP goes to normal mode for TI (invert) and TB (bold) */
                   1783:        if (*T_ME == NUL)
                   1784:            T_ME = T_MR = T_MD = empty_option;
                   1785:        if (*T_SO == NUL || *T_SE == NUL)
                   1786:            T_SO = T_SE = empty_option;
                   1787:        if (*T_US == NUL || *T_UE == NUL)
                   1788:            T_US = T_UE = empty_option;
                   1789:        if (*T_CZH == NUL || *T_CZR == NUL)
                   1790:            T_CZH = T_CZR = empty_option;
                   1791:            /* T_VE is needed even though T_VI is not defined */
                   1792:        if (*T_VE == NUL)
                   1793:            T_VI = empty_option;
                   1794:            /* if 'mr' or 'me' is not defined use 'so' and 'se' */
                   1795:        if (*T_ME == NUL)
                   1796:        {
                   1797:            T_ME = T_SE;
                   1798:            T_MR = T_SO;
                   1799:            T_MD = T_SO;
                   1800:        }
                   1801:            /* if 'so' or 'se' is not defined use 'mr' and 'me' */
                   1802:        if (*T_SO == NUL)
                   1803:        {
                   1804:            T_SE = T_ME;
                   1805:            if (*T_MR == NUL)
                   1806:                T_SO = T_MD;
                   1807:            else
                   1808:                T_SO = T_MR;
                   1809:        }
                   1810:            /* if 'ZH' or 'ZR' is not defined use 'mr' and 'me' */
                   1811:        if (*T_CZH == NUL)
                   1812:        {
                   1813:            T_CZR = T_ME;
                   1814:            if (*T_MR == NUL)
                   1815:                T_CZH = T_MD;
                   1816:            else
                   1817:                T_CZH = T_MR;
                   1818:        }
                   1819:    }
                   1820:    need_gather = TRUE;
                   1821: }
                   1822:
                   1823: /*
                   1824:  * Represent the given long_u as individual bytes, with the most significant
                   1825:  * byte first, and store them in dst.
                   1826:  */
                   1827:    void
                   1828: add_long_to_buf(val, dst)
                   1829:    long_u  val;
                   1830:    char_u  *dst;
                   1831: {
                   1832:    int     i;
                   1833:    int     shift;
                   1834:
                   1835:    for (i = 1; i <= sizeof(long_u); i++)
                   1836:    {
                   1837:        shift = 8 * (sizeof(long_u) - i);
                   1838:        dst[i - 1] = (char_u) ((val >> shift) & 0xff);
                   1839:    }
                   1840: }
                   1841:
                   1842: /*
                   1843:  * Interpret the next string of bytes in buf as a long integer, with the most
                   1844:  * significant byte first. Note that it is assumed that buf has been through
                   1845:  * inchar(), so that NUL and K_SPECIAL will be represented as three bytes each.
                   1846:  * Puts result in val, and returns the number of bytes read from buf
                   1847:  * (between sizeof(long_u) and 2 * sizeof(long_u)), or -1 if not enough bytes
                   1848:  * were present.
                   1849:  */
                   1850:    int
                   1851: get_long_from_buf(buf, val)
                   1852:    char_u  *buf;
                   1853:    long_u  *val;
                   1854: {
                   1855:    int     len;
                   1856:    char_u  bytes[sizeof(long_u)];
                   1857:    int     i;
                   1858:    int     shift;
                   1859:
                   1860:    *val = 0;
                   1861:    len = get_bytes_from_buf(buf, bytes, (int)sizeof(long_u));
                   1862:    if (len != -1)
                   1863:    {
                   1864:        for (i = 0; i < sizeof(long_u); i++)
                   1865:        {
                   1866:            shift = 8 * (sizeof(long_u) - 1 - i);
                   1867:            *val += (long_u)bytes[i] << shift;
                   1868:        }
                   1869:    }
                   1870:    return len;
                   1871: }
                   1872:
                   1873: /*
                   1874:  * Read the next num_bytes bytes from buf, and store them in bytes.  Assume
                   1875:  * that buf has been through inchar(). Returns the actual number of bytes used
                   1876:  * from buf (between num_bytes and num_bytes*2), or -1 if not enough bytes were
                   1877:  * available.
                   1878:  */
                   1879:    static int
                   1880: get_bytes_from_buf(buf, bytes, num_bytes)
                   1881:    char_u  *buf;
                   1882:    char_u  *bytes;
                   1883:    int     num_bytes;
                   1884: {
                   1885:    int     len = 0;
                   1886:    int     i;
                   1887:    char_u  c;
                   1888:
                   1889:    for (i = 0; i < num_bytes; i++)
                   1890:    {
                   1891:        if ((c = buf[len++]) == NUL)
                   1892:            return -1;
                   1893:        if (c == K_SPECIAL)
                   1894:        {
                   1895:            if (buf[len] == NUL || buf[len + 1] == NUL)     /* cannot happen? */
                   1896:                return -1;
                   1897:            if (buf[len++] == KS_ZERO)
                   1898:                c = NUL;
                   1899:            ++len;      /* skip K_FILLER */
                   1900:            /* else it should be KS_SPECIAL, and c already equals K_SPECIAL */
                   1901:        }
                   1902:        bytes[i] = c;
                   1903:    }
                   1904:    return len;
                   1905: }
                   1906:
                   1907: /*
                   1908:  * outnum - output a (big) number fast
                   1909:  */
                   1910:    void
                   1911: outnum(n)
                   1912:    register long n;
                   1913: {
                   1914:    OUTSTRN(tltoa((unsigned long)n));
                   1915: }
                   1916:
                   1917:    void
                   1918: check_winsize()
                   1919: {
                   1920:    static int  old_Rows = 0;
                   1921:
                   1922:    if (Columns < MIN_COLUMNS)
                   1923:        Columns = MIN_COLUMNS;
                   1924:    if (Rows < min_rows())      /* need room for one window and command line */
                   1925:        Rows = min_rows();
                   1926:
                   1927:    if (old_Rows != Rows)
                   1928:    {
                   1929:        old_Rows = Rows;
                   1930:        screen_new_rows();          /* may need to update window sizes */
                   1931:    }
                   1932: }
                   1933:
                   1934: /*
                   1935:  * set window size
                   1936:  * If 'mustset' is TRUE, we must set Rows and Columns, do not get real
                   1937:  * window size (this is used for the :win command).
                   1938:  * If 'mustset' is FALSE, we may try to get the real window size and if
                   1939:  * it fails use 'width' and 'height'.
                   1940:  */
                   1941:    void
                   1942: set_winsize(width, height, mustset)
                   1943:    int     width, height;
                   1944:    int     mustset;
                   1945: {
                   1946:    register int        tmp;
                   1947:
                   1948:    if (width < 0 || height < 0)    /* just checking... */
                   1949:        return;
                   1950:
                   1951:                                    /* postpone the resizing */
                   1952:    if (State == HITRETURN || State == SETWSIZE)
                   1953:    {
                   1954:        State = SETWSIZE;
                   1955:        return;
                   1956:    }
                   1957:    if (State != ASKMORE && State != EXTERNCMD)
                   1958:        screenclear();
                   1959:    else
                   1960:        screen_start();                 /* don't know where cursor is now */
                   1961: #ifdef AMIGA
                   1962:    flushbuf();         /* must do this before mch_get_winsize for some
                   1963:                            obscure reason */
                   1964: #endif /* AMIGA */
                   1965:    if (mustset || (mch_get_winsize() == FAIL && height != 0))
                   1966:    {
                   1967:        Rows = height;
                   1968:        Columns = width;
                   1969:        check_winsize();        /* always check, to get p_scroll right */
                   1970:        mch_set_winsize();
                   1971:    }
                   1972:    else
                   1973:        check_winsize();        /* always check, to get p_scroll right */
                   1974:    if (!starting)
                   1975:    {
                   1976:        comp_Botline_all();
                   1977:        if (State == ASKMORE || State == EXTERNCMD)
                   1978:        {
                   1979:            screenalloc(FALSE); /* don't redraw, just adjust screen size */
                   1980:            if (State == ASKMORE)
                   1981:            {
                   1982:                msg_moremsg(FALSE); /* display --more-- message again */
                   1983:                msg_row = Rows - 1;
                   1984:            }
                   1985:            else
                   1986:                windgoto(msg_row, msg_col); /* put cursor back */
                   1987:        }
                   1988:        else
                   1989:        {
                   1990:            tmp = RedrawingDisabled;
                   1991:            RedrawingDisabled = FALSE;
                   1992:            updateScreen(CURSUPD);
                   1993:            RedrawingDisabled = tmp;
                   1994:            if (State == CMDLINE)
                   1995:                redrawcmdline();
                   1996:            else
                   1997:                setcursor();
                   1998:        }
                   1999:    }
                   2000:    flushbuf();
                   2001: }
                   2002:
                   2003:    void
                   2004: settmode(raw)
                   2005:    int  raw;
                   2006: {
                   2007:    static int  oldraw = FALSE;
                   2008:
                   2009: #ifdef USE_GUI
                   2010:    /* don't set the term where gvim was started in raw mode */
                   2011:    if (gui.in_use)
                   2012:        return;
                   2013: #endif
                   2014:    if (full_screen)
                   2015:    {
                   2016:        /*
                   2017:         * When returning after calling a shell we want to really set the
                   2018:         * terminal to raw mode, even though we think it already is, because
                   2019:         * the shell program may have reset the terminal mode.
                   2020:         * When we think the terminal is not-raw, don't try to set it to
                   2021:         * not-raw again, because that causes problems (logout!) on some
                   2022:         * machines.
                   2023:         */
                   2024:        if (raw || oldraw)
                   2025:        {
                   2026:            flushbuf();
                   2027:            mch_settmode(raw);  /* machine specific function */
                   2028: #ifdef USE_MOUSE
                   2029:            if (!raw)
                   2030:                mch_setmouse(FALSE);            /* switch mouse off */
                   2031:            else
                   2032:                setmouse();                     /* may switch mouse on */
                   2033: #endif
                   2034:            flushbuf();
                   2035:            oldraw = raw;
                   2036:        }
                   2037:    }
                   2038: }
                   2039:
                   2040:    void
                   2041: starttermcap()
                   2042: {
                   2043:    if (full_screen && !termcap_active)
                   2044:    {
                   2045:        outstr(T_TI);                   /* start termcap mode */
                   2046:        outstr(T_KS);                   /* start "keypad transmit" mode */
                   2047:        flushbuf();
                   2048:        termcap_active = TRUE;
                   2049:        screen_start();                 /* don't know where cursor is now */
                   2050:    }
                   2051: }
                   2052:
                   2053:    void
                   2054: stoptermcap()
                   2055: {
                   2056:    if (full_screen && termcap_active)
                   2057:    {
                   2058:        outstr(T_KE);                   /* stop "keypad transmit" mode */
                   2059:        flushbuf();
                   2060:        termcap_active = FALSE;
                   2061:        cursor_on();                    /* just in case it is still off */
                   2062:        outstr(T_TE);                   /* stop termcap mode */
                   2063:        screen_start();                 /* don't know where cursor is now */
                   2064:    }
                   2065: }
                   2066:
                   2067: #ifdef USE_MOUSE
                   2068: /*
                   2069:  * setmouse() - switch mouse on/off depending on current mode and 'mouse'
                   2070:  */
                   2071:    void
                   2072: setmouse()
                   2073: {
                   2074:    int     checkfor;
                   2075:
                   2076: # ifdef USE_GUI
                   2077:    if (gui.in_use)
                   2078:        return;
                   2079: # endif
                   2080:    if (*p_mouse == NUL)            /* be quick when mouse is off */
                   2081:        return;
                   2082:
                   2083:    if (VIsual_active)
                   2084:        checkfor = MOUSE_VISUAL;
                   2085:    else if (State == HITRETURN)
                   2086:        checkfor = MOUSE_RETURN;
                   2087:    else if (State & INSERT)
                   2088:        checkfor = MOUSE_INSERT;
                   2089:    else if (State & CMDLINE)
                   2090:        checkfor = MOUSE_COMMAND;
                   2091:    else
                   2092:        checkfor = MOUSE_NORMAL;                /* assume normal mode */
                   2093:
                   2094:    if (mouse_has(checkfor))
                   2095:        mch_setmouse(TRUE);
                   2096:    else
                   2097:        mch_setmouse(FALSE);
                   2098: }
                   2099:
                   2100: /*
                   2101:  * Return TRUE if
                   2102:  * - "c" is in 'mouse', or
                   2103:  * - 'a' is in 'mouse' and "c" is in MOUSE_A, or
                   2104:  * - the current buffer is a help file and 'h' is in 'mouse' and we are in a
                   2105:  *   normal editing mode (not at hit-return message).
                   2106:  */
                   2107:    int
                   2108: mouse_has(c)
                   2109:    int     c;
                   2110: {
                   2111:    return (vim_strchr(p_mouse, c) != NULL ||
                   2112:                    (vim_strchr(p_mouse, 'a') != NULL &&
                   2113:                                  vim_strchr((char_u *)MOUSE_A, c) != NULL) ||
                   2114:                    (c != MOUSE_RETURN && curbuf->b_help &&
                   2115:                                            vim_strchr(p_mouse, MOUSE_HELP)));
                   2116: }
                   2117: #endif
                   2118:
                   2119: /*
                   2120:  * By outputting the 'cursor very visible' termcap code, for some windowed
                   2121:  * terminals this makes the screen scrolled to the correct position.
                   2122:  * Used when starting Vim or returning from a shell.
                   2123:  */
                   2124:    void
                   2125: scroll_start()
                   2126: {
                   2127:    if (*T_VS != NUL)
                   2128:    {
                   2129:        outstr(T_VS);
                   2130:        outstr(T_VE);
                   2131:        screen_start();                 /* don't know where cursor is now */
                   2132:    }
                   2133: }
                   2134:
                   2135: /*
                   2136:  * enable cursor, unless in Visual mode or no inversion possible
                   2137:  */
                   2138: static int cursor_is_off = FALSE;
                   2139:
                   2140:    void
                   2141: cursor_on()
                   2142: {
                   2143:    if (full_screen)
                   2144:    {
                   2145:        if (cursor_is_off && (!VIsual_active || highlight == NULL))
                   2146:        {
                   2147:            outstr(T_VE);
                   2148:            cursor_is_off = FALSE;
                   2149:        }
                   2150:    }
                   2151: }
                   2152:
                   2153:    void
                   2154: cursor_off()
                   2155: {
                   2156:    if (full_screen)
                   2157:    {
                   2158:        if (!cursor_is_off)
                   2159:            outstr(T_VI);           /* disable cursor */
                   2160:        cursor_is_off = TRUE;
                   2161:    }
                   2162: }
                   2163:
                   2164: /*
                   2165:  * Set scrolling region for window 'wp'.
                   2166:  * The region starts 'off' lines from the start of the window.
                   2167:  */
                   2168:    void
                   2169: scroll_region_set(wp, off)
                   2170:    WIN     *wp;
                   2171:    int     off;
                   2172: {
                   2173:    OUTSTR(tgoto((char *)T_CS, wp->w_winpos + wp->w_height - 1,
                   2174:                                                         wp->w_winpos + off));
                   2175:    screen_start();                 /* don't know where cursor is now */
                   2176: }
                   2177:
                   2178: /*
                   2179:  * Reset scrolling region to the whole screen.
                   2180:  */
                   2181:    void
                   2182: scroll_region_reset()
                   2183: {
                   2184:    OUTSTR(tgoto((char *)T_CS, (int)Rows - 1, 0));
                   2185:    screen_start();                 /* don't know where cursor is now */
                   2186: }
                   2187:
                   2188:
                   2189: /*
                   2190:  * List of terminal codes that are currently recognized.
                   2191:  */
                   2192:
                   2193: struct termcode
                   2194: {
                   2195:    char_u  name[2];        /* termcap name of entry */
                   2196:    char_u  *code;          /* terminal code (in allocated memory) */
                   2197:    int     len;            /* STRLEN(code) */
                   2198: } *termcodes = NULL;
                   2199:
                   2200: static int tc_max_len = 0; /* number of entries that termcodes[] can hold */
                   2201: static int tc_len = 0;     /* current number of entries in termcodes[] */
                   2202:
                   2203:    void
                   2204: clear_termcodes()
                   2205: {
                   2206:    while (tc_len > 0)
                   2207:        vim_free(termcodes[--tc_len].code);
                   2208:    vim_free(termcodes);
                   2209:    termcodes = NULL;
                   2210:    tc_max_len = 0;
                   2211:
                   2212: #ifdef HAVE_TGETENT
                   2213:    BC = (char *)empty_option;
                   2214:    UP = (char *)empty_option;
                   2215:    PC = ' ';                   /* set pad character to space */
                   2216:    ospeed = 0;
                   2217: #endif
                   2218:
                   2219:    need_gather = TRUE;         /* need to fill termleader[] */
                   2220: }
                   2221:
                   2222: /*
                   2223:  * Add a new entry to the list of terminal codes.
                   2224:  * The list is kept alphabetical for ":set termcap"
                   2225:  */
                   2226:    void
                   2227: add_termcode(name, string)
                   2228:    char_u  *name;
                   2229:    char_u  *string;
                   2230: {
                   2231:    struct termcode *new_tc;
                   2232:    int             i, j;
                   2233:    char_u          *s;
                   2234:
                   2235:    if (string == NULL || *string == NUL)
                   2236:    {
                   2237:        del_termcode(name);
                   2238:        return;
                   2239:    }
                   2240:
                   2241:    s = strsave(string);
                   2242:    if (s == NULL)
                   2243:        return;
                   2244:
                   2245:    need_gather = TRUE;         /* need to fill termleader[] */
                   2246:
                   2247:    /*
                   2248:     * need to make space for more entries
                   2249:     */
                   2250:    if (tc_len == tc_max_len)
                   2251:    {
                   2252:        tc_max_len += 20;
                   2253:        new_tc = (struct termcode *)alloc(
                   2254:                            (unsigned)(tc_max_len * sizeof(struct termcode)));
                   2255:        if (new_tc == NULL)
                   2256:        {
                   2257:            tc_max_len -= 20;
                   2258:            return;
                   2259:        }
                   2260:        for (i = 0; i < tc_len; ++i)
                   2261:            new_tc[i] = termcodes[i];
                   2262:        vim_free(termcodes);
                   2263:        termcodes = new_tc;
                   2264:    }
                   2265:
                   2266:    /*
                   2267:     * Look for existing entry with the same name, it is replaced.
                   2268:     * Look for an existing entry that is alphabetical higher, the new entry
                   2269:     * is inserted in front of it.
                   2270:     */
                   2271:    for (i = 0; i < tc_len; ++i)
                   2272:    {
                   2273:        if (termcodes[i].name[0] < name[0])
                   2274:            continue;
                   2275:        if (termcodes[i].name[0] == name[0])
                   2276:        {
                   2277:            if (termcodes[i].name[1] < name[1])
                   2278:                continue;
                   2279:            /*
                   2280:             * Exact match: Replace old code.
                   2281:             */
                   2282:            if (termcodes[i].name[1] == name[1])
                   2283:            {
                   2284:                vim_free(termcodes[i].code);
                   2285:                --tc_len;
                   2286:                break;
                   2287:            }
                   2288:        }
                   2289:        /*
                   2290:         * Found alphabetical larger entry, move rest to insert new entry
                   2291:         */
                   2292:        for (j = tc_len; j > i; --j)
                   2293:            termcodes[j] = termcodes[j - 1];
                   2294:        break;
                   2295:    }
                   2296:
                   2297:    termcodes[i].name[0] = name[0];
                   2298:    termcodes[i].name[1] = name[1];
                   2299:    termcodes[i].code = s;
                   2300:    termcodes[i].len = STRLEN(s);
                   2301:    ++tc_len;
                   2302: }
                   2303:
                   2304:    char_u  *
                   2305: find_termcode(name)
                   2306:    char_u  *name;
                   2307: {
                   2308:    int     i;
                   2309:
                   2310:    for (i = 0; i < tc_len; ++i)
                   2311:        if (termcodes[i].name[0] == name[0] && termcodes[i].name[1] == name[1])
                   2312:            return termcodes[i].code;
                   2313:    return NULL;
                   2314: }
                   2315:
                   2316:    char_u *
                   2317: get_termcode(i)
                   2318:    int     i;
                   2319: {
                   2320:    if (i >= tc_len)
                   2321:        return NULL;
                   2322:    return &termcodes[i].name[0];
                   2323: }
                   2324:
                   2325:    void
                   2326: del_termcode(name)
                   2327:    char_u  *name;
                   2328: {
                   2329:    int     i;
                   2330:
                   2331:    if (termcodes == NULL)      /* nothing there yet */
                   2332:        return;
                   2333:
                   2334:    need_gather = TRUE;         /* need to fill termleader[] */
                   2335:
                   2336:    for (i = 0; i < tc_len; ++i)
                   2337:        if (termcodes[i].name[0] == name[0] && termcodes[i].name[1] == name[1])
                   2338:        {
                   2339:            vim_free(termcodes[i].code);
                   2340:            --tc_len;
                   2341:            while (i < tc_len)
                   2342:            {
                   2343:                termcodes[i] = termcodes[i + 1];
                   2344:                ++i;
                   2345:            }
                   2346:            return;
                   2347:        }
                   2348:    /* not found. Give error message? */
                   2349: }
                   2350:
                   2351: /*
                   2352:  * Check if typebuf[] contains a terminal key code.
                   2353:  * Check from typebuf[typeoff] to typebuf[typeoff + max_offset].
                   2354:  * Return 0 for no match, -1 for partial match, > 0 for full match.
                   2355:  * With a match, the match is removed, the replacement code is inserted in
                   2356:  * typebuf[] and the number of characters in typebuf[] is returned.
                   2357:  */
                   2358:    int
                   2359: check_termcode(max_offset)
                   2360:    int     max_offset;
                   2361: {
                   2362:    register char_u     *tp;
                   2363:    register char_u     *p;
                   2364:    int         slen = 0;       /* init for GCC */
                   2365:    int         len;
                   2366:    int         offset;
                   2367:    char_u      key_name[2];
                   2368:    int         new_slen;
                   2369:    int         extra;
                   2370:    char_u      string[MAX_KEY_CODE_LEN + 1];
                   2371:    int         i;
                   2372: #ifdef USE_GUI
                   2373:    long_u      val;
                   2374: #endif
                   2375: #ifdef USE_MOUSE
                   2376:    char_u      bytes[3];
                   2377:    int         num_bytes;
                   2378:    int         mouse_code;
                   2379:    int         modifiers;
                   2380:    int         is_click, is_drag;
                   2381:    int         current_button;
                   2382:    static int  held_button = MOUSE_RELEASE;
                   2383:    static int  orig_num_clicks = 1;
                   2384:    static int  orig_mouse_code = 0x0;
                   2385: # if defined(UNIX) && defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H)
                   2386:    static int  orig_mouse_col = 0;
                   2387:    static int  orig_mouse_row = 0;
                   2388:    static linenr_t orig_topline = 0;
                   2389:    static struct timeval  orig_mouse_time = {0, 0};
                   2390:                                        /* time of previous mouse click */
                   2391:    struct timeval  mouse_time;         /* time of current mouse click */
                   2392:    long        timediff;               /* elapsed time in msec */
                   2393: # endif
                   2394: #endif
                   2395:
                   2396:    /*
                   2397:     * Speed up the checks for terminal codes by gathering all first bytes
                   2398:     * used in termleader[].  Often this is just a single <Esc>.
                   2399:     */
                   2400:    if (need_gather)
                   2401:        gather_termleader();
                   2402:
                   2403:    /*
                   2404:     * Check at several positions in typebuf[], to catch something like
                   2405:     * "x<Up>" that can be mapped. Stop at max_offset, because characters
                   2406:     * after that cannot be used for mapping, and with @r commands typebuf[]
                   2407:     * can become very long.
                   2408:     * This is used often, KEEP IT FAST!
                   2409:     */
                   2410:    for (offset = 0; offset < typelen && offset < max_offset; ++offset)
                   2411:    {
                   2412:        tp = typebuf + typeoff + offset;
                   2413:
                   2414:        /*
                   2415:         * Don't check characters after K_SPECIAL, those are already
                   2416:         * translated terminal chars (avoid translating ~@^Hx).
                   2417:         */
                   2418:        if (*tp == K_SPECIAL)
                   2419:        {
                   2420:            offset += 2;        /* there are always 2 extra characters */
                   2421:            continue;
                   2422:        }
                   2423:
                   2424:        /*
                   2425:         * Skip this position if the character does not appear as the first
                   2426:         * character in term_strings. This speeds up a lot, since most
                   2427:         * termcodes start with the same character (ESC or CSI).
                   2428:         */
                   2429:        i = *tp;
                   2430:        for (p = termleader; *p && *p != i; ++p)
                   2431:            ;
                   2432:        if (*p == NUL)
                   2433:            continue;
                   2434:
                   2435:        /*
                   2436:         * Skip this position if p_ek is not set and
                   2437:         * typebuf[typeoff + offset] is an ESC and we are in insert mode
                   2438:         */
                   2439:        if (*tp == ESC && !p_ek && (State & INSERT))
                   2440:            continue;
                   2441:
                   2442:        len = typelen - offset; /* length of the input */
                   2443:        new_slen = 0;           /* Length of what will replace the termcode */
                   2444:        key_name[0] = NUL;      /* no key name found yet */
                   2445:
                   2446: #ifdef USE_GUI
                   2447:        if (gui.in_use)
                   2448:        {
                   2449:            /*
                   2450:             * GUI special key codes are all of the form [CSI xx].
                   2451:             */
                   2452:            if (*tp == CSI)         /* Special key from GUI */
                   2453:            {
                   2454:                if (len < 3)
                   2455:                    return -1;      /* Shouldn't happen */
                   2456:                slen = 3;
                   2457:                key_name[0] = tp[1];
                   2458:                key_name[1] = tp[2];
                   2459:            }
                   2460:        }
                   2461:        else
                   2462: #endif /* USE_GUI */
                   2463:        {
                   2464:            for (i = 0; i < tc_len; ++i)
                   2465:            {
                   2466:                /*
                   2467:                 * Ignore the entry if we are not at the start of typebuf[]
                   2468:                 * and there are not enough characters to make a match.
                   2469:                 */
                   2470:                slen = termcodes[i].len;
                   2471:                if (offset && len < slen)
                   2472:                    continue;
                   2473:                if (STRNCMP(termcodes[i].code, tp,
                   2474:                                     (size_t)(slen > len ? len : slen)) == 0)
                   2475:                {
                   2476:                    if (len < slen)             /* got a partial sequence */
                   2477:                        return -1;              /* need to get more chars */
                   2478:
                   2479:                    key_name[0] = termcodes[i].name[0];
                   2480:                    key_name[1] = termcodes[i].name[1];
                   2481:
                   2482:                    /*
                   2483:                     * If it's a shifted special key, then include the SHIFT
                   2484:                     * modifier
                   2485:                     */
                   2486:                    if (unshift_special_key(&key_name[0]))
                   2487:                    {
                   2488:                        string[new_slen++] = K_SPECIAL;
                   2489:                        string[new_slen++] = KS_MODIFIER;
                   2490:                        string[new_slen++] = MOD_MASK_SHIFT;
                   2491:                    }
                   2492:                    break;
                   2493:                }
                   2494:            }
                   2495:        }
                   2496:
                   2497:        if (key_name[0] == NUL)
                   2498:            continue;       /* No match at this position, try next one */
                   2499:
                   2500:        /* We only get here when we have a complete termcode match */
                   2501:
                   2502: #ifdef USE_MOUSE
                   2503:        /*
                   2504:         * If it is a mouse click, get the coordinates.
                   2505:         * we get "<t_mouse>scr", where
                   2506:         *  s == encoded mouse button state (0x20 = left, 0x22 = right, etc)
                   2507:         *  c == column + ' ' + 1 == column + 33
                   2508:         *  r == row + ' ' + 1 == row + 33
                   2509:         *
                   2510:         * The coordinates are passed on through global variables. Ugly,
                   2511:         * but this avoids trouble with mouse clicks at an unexpected
                   2512:         * moment and allows for mapping them.
                   2513:         */
                   2514:        if (key_name[0] == KS_MOUSE)
                   2515:        {
                   2516:            num_bytes = get_bytes_from_buf(tp + slen, bytes, 3);
                   2517:            if (num_bytes == -1)    /* not enough coordinates */
                   2518:                return -1;
                   2519:            mouse_code = bytes[0];
                   2520:            mouse_col = bytes[1] - ' ' - 1;
                   2521:            mouse_row = bytes[2] - ' ' - 1;
                   2522:            slen += num_bytes;
                   2523:
                   2524:            /* Interpret the mouse code */
                   2525:            is_click = is_drag = FALSE;
                   2526:            current_button = (mouse_code & MOUSE_CLICK_MASK);
                   2527:            if (current_button == MOUSE_RELEASE)
                   2528:            {
                   2529:                /*
                   2530:                 * If we get a mouse drag or release event when
                   2531:                 * there is no mouse button held down (held_button ==
                   2532:                 * MOUSE_RELEASE), produce a K_IGNORE below.
                   2533:                 * (can happen when you hold down two buttons
                   2534:                 * and then let them go, or click in the menu bar, but not
                   2535:                 * on a menu, and drag into the text).
                   2536:                 */
                   2537:                if ((mouse_code & MOUSE_DRAG) == MOUSE_DRAG)
                   2538:                    is_drag = TRUE;
                   2539:                current_button = held_button;
                   2540:            }
                   2541:            else
                   2542:            {
                   2543: #if defined(UNIX) && defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H)
                   2544: # ifdef USE_GUI
                   2545:                /*
                   2546:                 * Only for Unix, when GUI is not active, we handle
                   2547:                 * multi-clicks here.
                   2548:                 */
                   2549:                if (!gui.in_use)
                   2550: # endif
                   2551:                {
                   2552:                    /*
                   2553:                     * Compute the time elapsed since the previous mouse click.
                   2554:                     */
                   2555:                    gettimeofday(&mouse_time, NULL);
                   2556:                    timediff = (mouse_time.tv_usec -
                   2557:                                              orig_mouse_time.tv_usec) / 1000;
                   2558:                    if (timediff < 0)
                   2559:                        --orig_mouse_time.tv_sec;
                   2560:                    timediff += (mouse_time.tv_sec -
                   2561:                                               orig_mouse_time.tv_sec) * 1000;
                   2562:                    orig_mouse_time = mouse_time;
                   2563:                    if (mouse_code == orig_mouse_code &&
                   2564:                            timediff < p_mouset &&
                   2565:                            orig_num_clicks != 4 &&
                   2566:                            orig_mouse_col == mouse_col &&
                   2567:                            orig_mouse_row == mouse_row &&
                   2568:                            orig_topline == curwin->w_topline)
                   2569:                        ++orig_num_clicks;
                   2570:                    else
                   2571:                        orig_num_clicks = 1;
                   2572:                    orig_mouse_col = mouse_col;
                   2573:                    orig_mouse_row = mouse_row;
                   2574:                    orig_topline = curwin->w_topline;
                   2575:                }
                   2576: # ifdef USE_GUI
                   2577:                else
                   2578:                    orig_num_clicks = NUM_MOUSE_CLICKS(mouse_code);
                   2579: # endif
                   2580: #else
                   2581:                orig_num_clicks = NUM_MOUSE_CLICKS(mouse_code);
                   2582: #endif
                   2583:                is_click = TRUE;
                   2584:                orig_mouse_code = mouse_code;
                   2585:            }
                   2586:            if (!is_drag)
                   2587:                held_button = mouse_code & MOUSE_CLICK_MASK;
                   2588:
                   2589:            /*
                   2590:             * Translate the actual mouse event into a pseudo mouse event.
                   2591:             * First work out what modifiers are to be used.
                   2592:             */
                   2593:            modifiers = 0x0;
                   2594:            if (orig_mouse_code & MOUSE_SHIFT)
                   2595:                modifiers |= MOD_MASK_SHIFT;
                   2596:            if (orig_mouse_code & MOUSE_CTRL)
                   2597:                modifiers |= MOD_MASK_CTRL;
                   2598:            if (orig_mouse_code & MOUSE_ALT)
                   2599:                modifiers |= MOD_MASK_ALT;
                   2600:            if (orig_num_clicks == 2)
                   2601:                modifiers |= MOD_MASK_2CLICK;
                   2602:            else if (orig_num_clicks == 3)
                   2603:                modifiers |= MOD_MASK_3CLICK;
                   2604:            else if (orig_num_clicks == 4)
                   2605:                modifiers |= MOD_MASK_4CLICK;
                   2606:
                   2607:            /* Add the modifier codes to our string */
                   2608:            if (modifiers != 0)
                   2609:            {
                   2610:                string[new_slen++] = K_SPECIAL;
                   2611:                string[new_slen++] = KS_MODIFIER;
                   2612:                string[new_slen++] = modifiers;
                   2613:            }
                   2614:
                   2615:            /* Work out our pseudo mouse event */
                   2616:            key_name[0] = KS_EXTRA;
                   2617:            key_name[1] = get_pseudo_mouse_code(current_button,
                   2618:                                                           is_click, is_drag);
                   2619:        }
                   2620: #endif /* USE_MOUSE */
                   2621: #ifdef USE_GUI
                   2622:        /*
                   2623:         * If using the GUI, then we get menu and scrollbar events.
                   2624:         *
                   2625:         * A menu event is encoded as K_SPECIAL, KS_MENU, K_FILLER followed by
                   2626:         * four bytes which are to be taken as a pointer to the GuiMenu
                   2627:         * structure.
                   2628:         *
                   2629:         * A scrollbar event is K_SPECIAL, KS_SCROLLBAR, K_FILLER followed by
                   2630:         * one byte representing the scrollbar number, and then four bytes
                   2631:         * representing a long_u which is the new value of the scrollbar.
                   2632:         *
                   2633:         * A horizontal scrollbar event is K_SPECIAL, KS_HORIZ_SCROLLBAR,
                   2634:         * K_FILLER followed by four bytes representing a long_u which is the
                   2635:         * new value of the scrollbar.
                   2636:         */
                   2637:        else if (key_name[0] == KS_MENU)
                   2638:        {
                   2639:            num_bytes = get_long_from_buf(tp + slen, &val);
                   2640:            if (num_bytes == -1)
                   2641:                return -1;
                   2642:            current_menu = (GuiMenu *)val;
                   2643:            slen += num_bytes;
                   2644:        }
                   2645:        else if (key_name[0] == KS_SCROLLBAR)
                   2646:        {
                   2647:            num_bytes = get_bytes_from_buf(tp + slen, bytes, 1);
                   2648:            if (num_bytes == -1)
                   2649:                return -1;
                   2650:            current_scrollbar = (int)bytes[0];
                   2651:            slen += num_bytes;
                   2652:            num_bytes = get_long_from_buf(tp + slen, &val);
                   2653:            if (num_bytes == -1)
                   2654:                return -1;
                   2655:            scrollbar_value = val;
                   2656:            slen += num_bytes;
                   2657:        }
                   2658:        else if (key_name[0] == KS_HORIZ_SCROLLBAR)
                   2659:        {
                   2660:            num_bytes = get_long_from_buf(tp + slen, &val);
                   2661:            if (num_bytes == -1)
                   2662:                return -1;
                   2663:            scrollbar_value = val;
                   2664:            slen += num_bytes;
                   2665:        }
                   2666: #endif /* USE_GUI */
                   2667:        /* Finally, add the special key code to our string */
                   2668:        string[new_slen++] = K_SPECIAL;
                   2669:        string[new_slen++] = key_name[0];
                   2670:        string[new_slen++] = key_name[1];
                   2671:        string[new_slen] = NUL;
                   2672:        extra = new_slen - slen;
                   2673:        if (extra < 0)
                   2674:                /* remove matched chars, taking care of noremap */
                   2675:            del_typebuf(-extra, offset);
                   2676:        else if (extra > 0)
                   2677:                /* insert the extra space we need */
                   2678:            ins_typebuf(string + slen, FALSE, offset, FALSE);
                   2679:
                   2680:        /*
                   2681:         * Careful: del_typebuf() and ins_typebuf() may have
                   2682:         * reallocated typebuf[]
                   2683:         */
                   2684:        vim_memmove(typebuf + typeoff + offset, string, (size_t)new_slen);
                   2685:        return (len + extra + offset);
                   2686:    }
                   2687:    return 0;                       /* no match found */
                   2688: }
                   2689:
                   2690: /*
                   2691:  * Replace any terminal code strings in from[] with the equivalent internal
                   2692:  * vim representation. This is used for the "from" and "to" part of a
                   2693:  * mapping, and the "to" part of a menu command.
                   2694:  * Any strings like "<C_UP>" are also replaced, unless 'cpoptions' contains
                   2695:  * '<'.  Also unshifts shifted special keys.
                   2696:  * K_SPECIAL by itself is replaced by K_SPECIAL KS_SPECIAL K_FILLER.
                   2697:  *
                   2698:  * The replacement is done in result[] and finally copied into allocated
                   2699:  * memory. If this all works well *bufp is set to the allocated memory and a
                   2700:  * pointer to it is returned. If something fails *bufp is set to NULL and from
                   2701:  * is returned.
                   2702:  *
                   2703:  * CTRL-V characters are removed.  When "from_part" is TRUE, a trailing CTRL-V
                   2704:  * is included, otherwise it is removed (for ":map xx ^V", maps xx to
                   2705:  * nothing).  When 'cpoptions' does not contain 'B', a backslash can be used
                   2706:  * instead of a CTRL-V.
                   2707:  */
                   2708:    char_u  *
                   2709: replace_termcodes(from, bufp, from_part)
                   2710:    char_u  *from;
                   2711:    char_u  **bufp;
                   2712:    int     from_part;
                   2713: {
                   2714:    int     i;
                   2715:    char_u  key_name[2];
                   2716:    char_u  *bp;
                   2717:    char_u  *last_dash;
                   2718:    char_u  *end_of_name;
                   2719:    int     slen;
                   2720:    int     modifiers;
                   2721:    int     bit;
                   2722:    int     key;
                   2723:    int     dlen = 0;
                   2724:    char_u  *src;
                   2725:    int     do_backslash;       /* backslash is a special character */
                   2726:    int     do_special;         /* recognize <> key codes */
                   2727:    int     do_key_code;        /* recognize raw key codes */
                   2728:    char_u  *result;            /* buffer for resulting string */
                   2729:
                   2730:    do_backslash = (vim_strchr(p_cpo, CPO_BSLASH) == NULL);
                   2731:    do_special = (vim_strchr(p_cpo, CPO_SPECI) == NULL);
                   2732:    do_key_code = (vim_strchr(p_cpo, CPO_KEYCODE) == NULL);
                   2733:
                   2734:    /*
                   2735:     * Allocate space for the translation.  Worst case a single character is
                   2736:     * replaced by 6 bytes (shifted special key), plus a NUL at the end.
                   2737:     */
                   2738:    result = alloc((unsigned)STRLEN(from) * 6 + 1);
                   2739:    if (result == NULL)         /* out of memory */
                   2740:    {
                   2741:        *bufp = NULL;
                   2742:        return from;
                   2743:    }
                   2744:
                   2745:    src = from;
                   2746:
                   2747:    /*
                   2748:     * Check for #n at start only: function key n
                   2749:     */
                   2750:    if (from_part && src[0] == '#' && isdigit(src[1]))      /* function key */
                   2751:    {
                   2752:        result[dlen++] = K_SPECIAL;
                   2753:        result[dlen++] = 'k';
                   2754:        if (src[1] == '0')
                   2755:            result[dlen++] = ';';       /* #0 is F10 is "k;" */
                   2756:        else
                   2757:            result[dlen++] = src[1];    /* #3 is F3 is "k3" */
                   2758:        src += 2;
                   2759:    }
                   2760:
                   2761:    /*
                   2762:     * Copy each byte from *from to result[dlen]
                   2763:     */
                   2764:    while (*src != NUL)
                   2765:    {
                   2766:        /*
                   2767:         * If 'cpoptions' does not contain '<', check for special key codes.
                   2768:         */
                   2769:        if (do_special)
                   2770:        {
                   2771:            /*
                   2772:             * See if it's a string like "<C-S-MouseLeft>"
                   2773:             */
                   2774:            if (src[0] == '<')
                   2775:            {
                   2776:                /* Find end of modifier list */
                   2777:                last_dash = src;
                   2778:                for (bp = src + 1; *bp == '-' || isidchar(*bp); bp++)
                   2779:                {
                   2780:                    if (*bp == '-')
                   2781:                    {
                   2782:                        last_dash = bp;
                   2783:                        if (bp[1] != NUL && bp[2] == '>')
                   2784:                            ++bp;   /* anything accepted, like <C-?> */
                   2785:                    }
                   2786:                    if (bp[0] == 't' && bp[1] == '_' && bp[2] && bp[3])
                   2787:                        bp += 3;    /* skip t_xx, xx may be '-' or '>' */
                   2788:                }
                   2789:
                   2790:                if (*bp == '>')     /* found matching '>' */
                   2791:                {
                   2792:                    end_of_name = bp + 1;
                   2793:
                   2794:                    /* Which modifiers are given? */
                   2795:                    modifiers = 0x0;
                   2796:                    for (bp = src + 1; bp < last_dash; bp++)
                   2797:                    {
                   2798:                        if (*bp != '-')
                   2799:                        {
                   2800:                            bit = name_to_mod_mask(*bp);
                   2801:                            if (bit == 0x0)
                   2802:                                break;      /* Illegal modifier name */
                   2803:                            modifiers |= bit;
                   2804:                        }
                   2805:                    }
                   2806:
                   2807:                    /*
                   2808:                     * Legal modifier name.
                   2809:                     */
                   2810:                    if (bp >= last_dash)
                   2811:                    {
                   2812:                        /*
                   2813:                         * Modifier with single letter
                   2814:                         */
                   2815:                        if (modifiers != 0 && last_dash[2] == '>')
                   2816:                        {
                   2817:                            key = last_dash[1];
                   2818:                            if (modifiers & MOD_MASK_SHIFT)
                   2819:                                key = TO_UPPER(key);
                   2820:                            if (modifiers & MOD_MASK_CTRL)
                   2821:                                key &= 0x1f;
                   2822:                            if (modifiers & MOD_MASK_ALT)
                   2823:                                key |= 0x80;
                   2824:                            src = end_of_name;
                   2825:                            result[dlen++] = key;
                   2826:                            continue;
                   2827:                        }
                   2828:
                   2829:                        /*
                   2830:                         * Key name with or without modifier.
                   2831:                         */
                   2832:                        else if ((key = get_special_key_code(last_dash + 1))
                   2833:                                                                         != 0)
                   2834:                        {
                   2835:                            /* Put the appropriate modifier in a string */
                   2836:                            if (modifiers != 0)
                   2837:                            {
                   2838:                                result[dlen++] = K_SPECIAL;
                   2839:                                result[dlen++] = KS_MODIFIER;
                   2840:                                result[dlen++] = modifiers;
                   2841:                                /*
                   2842:                                 * Special trick: for <S-TAB>  K_TAB is used
                   2843:                                 * instead of TAB (there are two keys for the
                   2844:                                 * same thing).
                   2845:                                 */
                   2846:                                if (key == TAB)
                   2847:                                    key = K_TAB;
                   2848:                            }
                   2849:
                   2850:                            if (IS_SPECIAL(key))
                   2851:                            {
                   2852:                                result[dlen++] = K_SPECIAL;
                   2853:                                result[dlen++] = KEY2TERMCAP0(key);
                   2854:                                result[dlen++] = KEY2TERMCAP1(key);
                   2855:                            }
                   2856:                            else
                   2857:                                result[dlen++] = key;       /* only modifiers */
                   2858:                            src = end_of_name;
                   2859:                            continue;
                   2860:                        }
                   2861:                    }
                   2862:                }
                   2863:            }
                   2864:        }
                   2865:
                   2866:        /*
                   2867:         * If 'cpoptions' does not contain 'k', see if it's an actual key-code.
                   2868:         * Note that this is also checked after replacing the <> form.
                   2869:         */
                   2870:        if (do_key_code)
                   2871:        {
                   2872:            for (i = 0; i < tc_len; ++i)
                   2873:            {
                   2874:                slen = termcodes[i].len;
                   2875:                if (STRNCMP(termcodes[i].code, src, (size_t)slen) == 0)
                   2876:                {
                   2877:                    key_name[0] = termcodes[i].name[0];
                   2878:                    key_name[1] = termcodes[i].name[1];
                   2879:
                   2880:                    /*
                   2881:                     * If it's a shifted special key, then include the SHIFT
                   2882:                     * modifier
                   2883:                     */
                   2884:                    if (unshift_special_key(&key_name[0]))
                   2885:                    {
                   2886:                        result[dlen++] = K_SPECIAL;
                   2887:                        result[dlen++] = KS_MODIFIER;
                   2888:                        result[dlen++] = MOD_MASK_SHIFT;
                   2889:                    }
                   2890:                    result[dlen++] = K_SPECIAL;
                   2891:                    result[dlen++] = key_name[0];
                   2892:                    result[dlen++] = key_name[1];
                   2893:                    src += slen;
                   2894:                    break;
                   2895:                }
                   2896:            }
                   2897:
                   2898:            /*
                   2899:             * If terminal code matched, continue after it.
                   2900:             * If no terminal code matched and the character is K_SPECIAL,
                   2901:             * replace it with K_SPECIAL KS_SPECIAL K_FILLER
                   2902:             */
                   2903:            if (i != tc_len)
                   2904:                continue;
                   2905:        }
                   2906:
                   2907:        if (*src == K_SPECIAL)
                   2908:        {
                   2909:            result[dlen++] = K_SPECIAL;
                   2910:            result[dlen++] = KS_SPECIAL;
                   2911:            result[dlen++] = K_FILLER;
                   2912:            ++src;
                   2913:            continue;
                   2914:        }
                   2915:
                   2916:        /*
                   2917:         * Remove CTRL-V and ignore the next character.
                   2918:         * For "from" side the CTRL-V at the end is included, for the "to"
                   2919:         * part it is removed.
                   2920:         * If 'cpoptions' does not contain 'B', also accept a backslash.
                   2921:         */
                   2922:        key = *src;
                   2923:        if (key == Ctrl('V') || (do_backslash && key == '\\'))
                   2924:        {
                   2925:            ++src;                              /* skip CTRL-V or backslash */
                   2926:            if (*src == NUL)
                   2927:            {
                   2928:                if (from_part)
                   2929:                    result[dlen++] = key;
                   2930:                break;
                   2931:            }
                   2932:        }
                   2933:        result[dlen++] = *src++;
                   2934:    }
                   2935:    result[dlen] = NUL;
                   2936:
                   2937:    /*
                   2938:     * Copy the new string to allocated memory.
                   2939:     * If this fails, just return from.
                   2940:     */
                   2941:    if ((*bufp = strsave(result)) != NULL)
                   2942:        from = *bufp;
                   2943:    vim_free(result);
                   2944:    return from;
                   2945: }
                   2946:
                   2947: /*
                   2948:  * Gather the first characters in the terminal key codes into a string.
                   2949:  * Used to speed up check_termcode().
                   2950:  */
                   2951:    static void
                   2952: gather_termleader()
                   2953: {
                   2954:    int     i;
                   2955:    int     len = 0;
                   2956:
                   2957: #ifdef USE_GUI
                   2958:    if (gui.in_use)
                   2959:        termleader[len++] = CSI;    /* the GUI codes are not in termcodes[] */
                   2960: #endif
                   2961:    termleader[len] = NUL;
                   2962:
                   2963:    for (i = 0; i < tc_len; ++i)
                   2964:        if (vim_strchr(termleader, termcodes[i].code[0]) == NULL)
                   2965:        {
                   2966:            termleader[len++] = termcodes[i].code[0];
                   2967:            termleader[len] = NUL;
                   2968:        }
                   2969:
                   2970:    need_gather = FALSE;
                   2971: }
                   2972:
                   2973: /*
                   2974:  * Show all termcodes (for ":set termcap")
                   2975:  * This code looks a lot like showoptions(), but is different.
                   2976:  */
                   2977:    void
                   2978: show_termcodes()
                   2979: {
                   2980:    int             col;
                   2981:    int             *items;
                   2982:    int             item_count;
                   2983:    int             run;
                   2984:    int             row, rows;
                   2985:    int             cols;
                   2986:    int             i;
                   2987:    int             len;
                   2988:
                   2989: #define INC    27      /* try to make three columns */
                   2990: #define GAP 2      /* spaces between columns */
                   2991:
                   2992:    if (tc_len == 0)        /* no terminal codes (must be GUI) */
                   2993:        return;
                   2994:    items = (int *)alloc((unsigned)(sizeof(int) * tc_len));
                   2995:    if (items == NULL)
                   2996:        return;
                   2997:
                   2998:    set_highlight('t');     /* Highlight title */
                   2999:    start_highlight();
                   3000:    MSG_OUTSTR("\n--- Terminal keys ---");
                   3001:    stop_highlight();
                   3002:
                   3003:    /*
                   3004:     * do the loop two times:
                   3005:     * 1. display the short items (non-strings and short strings)
                   3006:     * 2. display the long items (strings)
                   3007:     */
                   3008:    for (run = 1; run <= 2 && !got_int; ++run)
                   3009:    {
                   3010:        /*
                   3011:         * collect the items in items[]
                   3012:         */
                   3013:        item_count = 0;
                   3014:        for (i = 0; i < tc_len; i++)
                   3015:        {
                   3016:            len = show_one_termcode(termcodes[i].name,
                   3017:                                                    termcodes[i].code, FALSE);
                   3018:            if ((len <= INC - GAP && run == 1) || (len > INC - GAP && run == 2))
                   3019:                items[item_count++] = i;
                   3020:        }
                   3021:
                   3022:        /*
                   3023:         * display the items
                   3024:         */
                   3025:        if (run == 1)
                   3026:        {
                   3027:            cols = (Columns + GAP) / INC;
                   3028:            if (cols == 0)
                   3029:                cols = 1;
                   3030:            rows = (item_count + cols - 1) / cols;
                   3031:        }
                   3032:        else    /* run == 2 */
                   3033:            rows = item_count;
                   3034:        for (row = 0; row < rows && !got_int; ++row)
                   3035:        {
                   3036:            msg_outchar('\n');                      /* go to next line */
                   3037:            if (got_int)                            /* 'q' typed in more */
                   3038:                break;
                   3039:            col = 0;
                   3040:            for (i = row; i < item_count; i += rows)
                   3041:            {
                   3042:                msg_pos(-1, col);                   /* make columns */
                   3043:                show_one_termcode(termcodes[items[i]].name,
                   3044:                                              termcodes[items[i]].code, TRUE);
                   3045:                col += INC;
                   3046:            }
                   3047:            flushbuf();
                   3048:            mch_breakcheck();
                   3049:        }
                   3050:    }
                   3051:    vim_free(items);
                   3052: }
                   3053:
                   3054: /*
                   3055:  * Show one termcode entry.
                   3056:  * Output goes into IObuff[]
                   3057:  */
                   3058:    int
                   3059: show_one_termcode(name, code, printit)
                   3060:    char_u  *name;
                   3061:    char_u  *code;
                   3062:    int     printit;
                   3063: {
                   3064:    char_u      *p;
                   3065:    int         len;
                   3066:
                   3067:    if (name[0] > '~')
                   3068:    {
                   3069:        IObuff[0] = ' ';
                   3070:        IObuff[1] = ' ';
                   3071:        IObuff[2] = ' ';
                   3072:        IObuff[3] = ' ';
                   3073:    }
                   3074:    else
                   3075:    {
                   3076:        IObuff[0] = 't';
                   3077:        IObuff[1] = '_';
                   3078:        IObuff[2] = name[0];
                   3079:        IObuff[3] = name[1];
                   3080:    }
                   3081:    IObuff[4] = ' ';
                   3082:
                   3083:    p = get_special_key_name(TERMCAP2KEY(name[0], name[1]), 0);
                   3084:    if (p[1] != 't')
                   3085:        STRCPY(IObuff + 5, p);
                   3086:    else
                   3087:        IObuff[5] = NUL;
                   3088:    len = STRLEN(IObuff);
                   3089:    do
                   3090:        IObuff[len++] = ' ';
                   3091:    while (len < 17);
                   3092:    IObuff[len] = NUL;
                   3093:    if (code == NULL)
                   3094:        len += 4;
                   3095:    else
                   3096:        len += strsize(code);
                   3097:
                   3098:    if (printit)
                   3099:    {
                   3100:        msg_outstr(IObuff);
                   3101:        if (code == NULL)
                   3102:            msg_outstr((char_u *)"NULL");
                   3103:        else
                   3104:            msg_outtrans(code);
                   3105:    }
                   3106:    return len;
                   3107: }