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

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

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