[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.2

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