home *** CD-ROM | disk | FTP | other *** search
/ vim.ftp.fu-berlin.de / 2015-02-03.vim.ftp.fu-berlin.de.tar / vim.ftp.fu-berlin.de / amiga / vim46src.lha / vim-4.6 / src / term.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-03-06  |  72.0 KB  |  3,147 lines

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