home *** CD-ROM | disk | FTP | other *** search
/ Frozen Fish 1: Amiga / FrozenFish-Apr94.iso / bbs / mar94 / util / edit / vim.lha / Vim / src / term.c < prev    next >
C/C++ Source or Header  |  1993-12-14  |  18KB  |  831 lines

  1. /* vi:sw=4:ts=4:
  2.  *
  3.  * term.c -- VIM - Vi IMproved
  4.  *
  5.  * primitive termcap support added
  6.  *
  7.  * NOTE: padding and variable substitution is not performed,
  8.  * when compiling without TERMCAP, we use tputs() and tgoto() dummies.
  9.  *
  10.  * 14.6.92
  11.  */
  12.  
  13. #include "vim.h"
  14. #include "globals.h"
  15. #include "param.h"
  16. #include "proto.h"
  17. #ifdef TERMCAP
  18. # ifdef linux
  19. #  include <termcap.h>
  20. #  define TPUTSFUNCAST (outfuntype)
  21. # else
  22. #  define TPUTSFUNCAST
  23. #  ifdef AMIGA
  24. #   include "proto/termlib.pro"
  25. #  endif
  26. # endif
  27. #endif
  28.  
  29. #ifdef DEBUG
  30. # define TTEST(a) debug1("%s: ", "a"); if (a) {debug2("%02x %s\n", *a, a + 1);} else debug("NULL\n");
  31. #endif
  32.  
  33. static void parse_builtin_tcap __ARGS((Tcarr *tc, char *s));
  34.  
  35. /*
  36.  * Builtin_tcaps must always contain DFLT_TCAP as the first entry!
  37.  * DFLT_TCAP is used, when no terminal is specified with -T option or $TERM.
  38.  * The entries are compact, therefore they normally are included even when
  39.  * TERMCAP is defined.
  40.  * When TERMCAP is defined, the builtin entries can be accessed with
  41.  * "builtin_amiga", "builtin_ansi", "builtin_debug", etc.
  42.  */
  43. static char *builtin_tcaps[] =
  44. {
  45. #ifndef NO_BUILTIN_TCAPS
  46.   DFLT_TCAP,        /* almost allways included */
  47. # if !defined(UNIX) && (defined(ALL_BUILTIN_TCAPS) || defined(SOME_BUILTIN_TCAPS))
  48.   ANSI_TCAP,        /* default for unix */
  49. # endif
  50. # if !defined(AMIGA) && (defined(ALL_BUILTIN_TCAPS) || defined(SOME_BUILTIN_TCAPS))
  51.   AMIGA_TCAP,        /* default for amiga */
  52. # endif
  53. # if !defined(MSDOS) && (defined(ALL_BUILTIN_TCAPS) || defined(SOME_BUILTIN_TCAPS))
  54.   PCTERM_TCAP,        /* default for MSdos */
  55. # endif
  56. # if defined(MSDOS) || defined(ALL_BUILTIN_TCAPS)
  57.   PCANSI_TCAP,
  58. # endif
  59. # if !defined(ATARI) && defined(ALL_BUILTIN_TCAPS)
  60.   ATARI_TCAP,        /* default for Atari */
  61. # endif
  62. # if defined(UNIX) || defined(ALL_BUILTIN_TCAPS) || defined(SOME_BUILTIN_TCAPS)
  63.   XTERM_TCAP,        /* always included on unix */
  64. # endif
  65. # ifdef ALL_BUILTIN_TCAPS
  66.   VT52_TCAP,
  67. # endif
  68. # if defined(DEBUG) || defined(ALL_BUILTIN_TCAPS)
  69.   DEBUG_TCAP,        /* always included when debugging */
  70. # endif
  71. #else /* NO_BUILTIN_TCAPS */
  72.   DUMB_TCAP,        /* minimal termcap, used when everything else fails */
  73. #endif /* NO_BUILTIN_TCAPS */
  74.   NULL,
  75. };
  76.  
  77. /*
  78.  * Term_strings contains currently used terminal strings.
  79.  * It is initialized with the default values by parse_builtin_tcap().
  80.  * The values can be changed by setting the parameter with the same name.
  81.  */
  82. Tcarr term_strings;
  83.  
  84. /*
  85.  * Parsing of the builtin termcap entries.
  86.  * The terminal's name is not set, as this is already done in termcapinit().
  87.  * Chop builtin termcaps, string entries are already '\0' terminated.
  88.  * not yet implemented:
  89.  *   boolean entries could be empty strings;
  90.  *   numeric entries would need a flag (e.g. high bit of the skip byte),
  91.  *   so that parse_builtin_tcap can handle them.
  92.  */
  93.     static void
  94. parse_builtin_tcap(tc, s)
  95.     Tcarr *tc;
  96.     char *s;
  97. {
  98.     char **p = &tc->t_name;
  99.  
  100.     p++;
  101.     for (;;)
  102.     {
  103.         while (*s++)
  104.             ;
  105.         p += *s++;
  106.         if (!*s)
  107.             return;
  108.         *p++ = s;
  109.     }
  110. }
  111.  
  112. #ifdef TERMCAP
  113. # ifndef linux        /* included in <termlib.h> */
  114. #  ifndef AMIGA        /* included in proto/termlib.pro */
  115. int                tgetent();
  116. int                tgetnum();
  117. char            *tgetstr();
  118. int                tputs();
  119. #  endif /* AMIGA */
  120. #  ifndef hpux
  121. extern short    ospeed;
  122. #  endif
  123. # endif /* linux */
  124. # ifndef hpux
  125. char        *UP, *BC, PC;        /* should be extern, but some don't have them */
  126. # endif
  127. #endif /* TERMCAP */
  128.  
  129.     void
  130. set_term(term)
  131.     char *term;
  132. {
  133.     char **p = builtin_tcaps;
  134. #ifdef TERMCAP
  135.     int builtin = 0;
  136. #endif
  137.     int width = 0, height = 0;
  138.  
  139.     if (!strncmp(term, "builtin_", (size_t)8))
  140.     {
  141.         term += 8;
  142. #ifdef TERMCAP
  143.         builtin = 1;
  144. #endif
  145.     }
  146. #ifdef TERMCAP
  147.     else
  148.     {
  149.         char            *p;
  150.         static char        tstrbuf[TBUFSZ];
  151.         char            tbuf[TBUFSZ];
  152.         char            *tp = tstrbuf;
  153.         int                i;
  154.  
  155.         i = tgetent(tbuf, term);
  156.         if (i == -1)
  157.         {
  158.             emsg("Cannot open termcap file");
  159.             builtin = 1;
  160.         }
  161.         else if (i == 0)
  162.         {
  163.             emsg("terminal entry not found");
  164.             builtin = 1;
  165.         }
  166.         else
  167.         {
  168.             clear_termparam();        /* clear old parameters */
  169.         /* output strings */
  170.             T_EL = tgetstr("ce", &tp);
  171.             T_IL = tgetstr("al", &tp);
  172.             T_CIL = tgetstr("AL", &tp);
  173.             T_DL = tgetstr("dl", &tp);
  174.             T_CDL = tgetstr("DL", &tp);
  175.             T_ED = tgetstr("cl", &tp);
  176.             T_CI = tgetstr("vi", &tp);
  177.             T_CV = tgetstr("ve", &tp);
  178.             T_TP = tgetstr("me", &tp);
  179.             T_TI = tgetstr("mr", &tp);
  180.                 /* if 'mr' or 'me' is not defined use 'so' and 'se' */
  181.             if (T_TP == NULL || *T_TP == NUL || T_TI == NULL || *T_TI == NUL)
  182.             {
  183.                 T_TP = tgetstr("se", &tp);
  184.                 T_TI = tgetstr("so", &tp);
  185.             }
  186.             T_CM = tgetstr("cm", &tp);
  187.             T_SR = tgetstr("sr", &tp);
  188.             T_CRI = tgetstr("RI", &tp);
  189.             T_VB = tgetstr("vb", &tp);
  190.             T_KS = tgetstr("ks", &tp);
  191.             T_KE = tgetstr("ke", &tp);
  192.             T_TS = tgetstr("ti", &tp);
  193.             T_TE = tgetstr("te", &tp);
  194.  
  195.         /* key codes */
  196.             term_strings.t_ku = tgetstr("ku", &tp);
  197.             term_strings.t_kd = tgetstr("kd", &tp);
  198.             term_strings.t_kl = tgetstr("kl", &tp);
  199.                 /* if cursor-left == backspace, ignore it (televideo 925) */
  200.             if (term_strings.t_kl != NULL && *term_strings.t_kl == Ctrl('H'))
  201.                 term_strings.t_kl = NULL;
  202.             term_strings.t_kr = tgetstr("kr", &tp);
  203.             /* term_strings.t_sku = tgetstr("", &tp); termcap code unknown */
  204.             /* term_strings.t_skd = tgetstr("", &tp); termcap code unknown */
  205.             term_strings.t_sku = NULL;
  206.             term_strings.t_skd = NULL;
  207.             term_strings.t_skl = tgetstr("#4", &tp);
  208.             term_strings.t_skr = tgetstr("%i", &tp);
  209.             term_strings.t_f1 = tgetstr("k1", &tp);
  210.             term_strings.t_f2 = tgetstr("k2", &tp);
  211.             term_strings.t_f3 = tgetstr("k3", &tp);
  212.             term_strings.t_f4 = tgetstr("k4", &tp);
  213.             term_strings.t_f5 = tgetstr("k5", &tp);
  214.             term_strings.t_f6 = tgetstr("k6", &tp);
  215.             term_strings.t_f7 = tgetstr("k7", &tp);
  216.             term_strings.t_f8 = tgetstr("k8", &tp);
  217.             term_strings.t_f9 = tgetstr("k9", &tp);
  218.             term_strings.t_f10 = tgetstr("k;", &tp);
  219.             term_strings.t_sf1 = tgetstr("F1", &tp);    /* really function keys 11-20 */
  220.             term_strings.t_sf2 = tgetstr("F2", &tp);
  221.             term_strings.t_sf3 = tgetstr("F3", &tp);
  222.             term_strings.t_sf4 = tgetstr("F4", &tp);
  223.             term_strings.t_sf5 = tgetstr("F5", &tp);
  224.             term_strings.t_sf6 = tgetstr("F6", &tp);
  225.             term_strings.t_sf7 = tgetstr("F7", &tp);
  226.             term_strings.t_sf8 = tgetstr("F8", &tp);
  227.             term_strings.t_sf9 = tgetstr("F9", &tp);
  228.             term_strings.t_sf10 = tgetstr("FA", &tp);
  229.             term_strings.t_help = tgetstr("%1", &tp);
  230.             term_strings.t_undo = tgetstr("&8", &tp);
  231.  
  232.             height = tgetnum("li");
  233.             width = tgetnum("co");
  234.  
  235. # ifndef hpux
  236.             BC = tgetstr("bc", &tp);
  237.             UP = tgetstr("up", &tp);
  238.             p = tgetstr("pc", &tp);
  239.             if (p)
  240.                 PC = *p;
  241.             ospeed = 0;
  242. # endif
  243.         }
  244.     }
  245.     if (builtin)
  246. #endif
  247.     {
  248.         while (*p && strcmp(term, *p))
  249.             p++;
  250.         if (!*p)
  251.         {
  252.             fprintf(stderr, "'%s' not builtin. Available terminals are:\r\n", term);
  253.             for (p = builtin_tcaps; *p; p++)
  254. #ifdef TERMCAP
  255.                 fprintf(stderr, "\tbuiltin_%s\r\n", *p);
  256. #else
  257.                 fprintf(stderr, "\t%s\r\n", *p);
  258. #endif
  259.             if (!starting)        /* when user typed :set term=xxx, quit here */
  260.             {
  261.                 wait_return(TRUE);
  262.                 return;
  263.             }
  264.             sleep(2);
  265.             fprintf(stderr, "defaulting to '%s'\r\n", *builtin_tcaps);
  266.             sleep(2);
  267.             p = builtin_tcaps;
  268.             free(term_strings.t_name);
  269.             term_strings.t_name = strsave(term = *p);
  270.         }
  271.         clear_termparam();        /* clear old parameters */
  272.         parse_builtin_tcap(&term_strings, *p);
  273.     }
  274. #if defined(AMIGA) || defined(MSDOS)
  275.         /* DFLT_TCAP indicates that it is the machine console. */
  276.     if (strcmp(term, *builtin_tcaps))
  277.         term_console = FALSE;
  278.     else
  279.     {
  280.         term_console = TRUE;
  281. # ifdef AMIGA
  282.         win_resize_on();        /* enable window resizing reports */
  283. # endif
  284.     }
  285. #endif
  286.     ttest(TRUE);
  287.         /* display initial screen after ttest() checking. jw. */
  288.     if (width <= 0 || height <= 0)
  289.     {
  290.         /* termcap failed to report size */
  291.         /* set defaults, in case mch_get_winsize also fails */
  292.         width = 80;
  293. #ifdef MSDOS
  294.         height = 25;        /* console is often 25 lines */
  295. #else
  296.         height = 24;        /* most terminals are 24 lines */
  297. #endif
  298.     }
  299.     Rows_max = Rows;        /* remember max. physical nr. of Rows */
  300.     set_winsize(width, height, FALSE);    /* may change Rows_max */
  301. }
  302.  
  303. #if defined(TERMCAP) && defined(UNIX)
  304. /*
  305.  * Get Columns and Rows from the termcap. Used after a window signal if the
  306.  * ioctl() fails. It doesn't make sense to call tgetent each time if the "co"
  307.  * and "li" entries never change. But this may happen on some systems.
  308.  */
  309.     void
  310. getlinecol()
  311. {
  312.     char            tbuf[TBUFSZ];
  313.  
  314.     if (term_strings.t_name && tgetent(tbuf, term_strings.t_name) > 0)
  315.     {
  316.         if (Columns == 0)
  317.             Columns = tgetnum("co");
  318.         if (Rows == 0)
  319.             Rows = tgetnum("li");
  320.     }
  321. }
  322. #endif
  323.  
  324. static char *tltoa __PARMS((unsigned long));
  325.  
  326.     static char *
  327. tltoa(i)
  328.     unsigned long i;
  329. {
  330.     static char buf[16];
  331.     char        *p;
  332.  
  333.     p = buf + 15;
  334.     *p = '\0';
  335.     do
  336.     {
  337.         --p;
  338.         *p = i % 10 + '0';
  339.         i /= 10;
  340.     }
  341.     while (i > 0 && p > buf);
  342.     return p;
  343. }
  344.  
  345. #ifndef TERMCAP
  346.  
  347. /*
  348.  * minimal tgoto() implementation.
  349.  * no padding and we only parse for %i %d and %+char
  350.  */
  351.  
  352.     char *
  353. tgoto(cm, x, y)
  354.     char *cm;
  355.     int x, y;
  356. {
  357.     static char buf[30];
  358.     char *p, *s, *e;
  359.  
  360.     if (!cm)
  361.         return "OOPS";
  362.     e = buf + 29;
  363.     for (s = buf; s < e && *cm; cm++)
  364.     {
  365.         if (*cm != '%')
  366.         {
  367.             *s++ = *cm;
  368.             continue;
  369.         }
  370.         switch (*++cm)
  371.         {
  372.         case 'd':
  373.             p = tltoa((unsigned long)y);
  374.             y = x;
  375.             while (*p)
  376.                 *s++ = *p++;
  377.             break;
  378.         case 'i':
  379.             x++;
  380.             y++;
  381.             break;
  382.         case '+':
  383.             *s++ = (char)(*++cm + y);
  384.             y = x;
  385.             break;
  386.         case '%':
  387.             *s++ = *cm;
  388.             break;
  389.         default:
  390.             return "OOPS";
  391.         }
  392.     }
  393.     *s = '\0';
  394.     return buf;
  395. }
  396.  
  397. #endif /* TERMCAP */
  398.  
  399. /*
  400.  * Termcapinit is called from main() to initialize the terminal.
  401.  * The optional argument is given with the -T command line option.
  402.  */
  403.     void
  404. termcapinit(term)
  405.     char *term;
  406. {
  407.     if (!term)
  408.         term = (char *)vimgetenv("TERM");
  409.     if (!term || !*term)
  410.         term = *builtin_tcaps;
  411.     term_strings.t_name = strsave(term);
  412.     set_term(term);
  413. }
  414.  
  415. /*
  416.  * the number of calls to mch_write is reduced by using the buffer "outbuf"
  417.  */
  418. #undef BSIZE            /* hpux has BSIZE in sys/param.h */
  419. #define BSIZE    2048
  420. static u_char            outbuf[BSIZE];
  421. static int                bpos = 0;        /* number of chars in outbuf */
  422.  
  423. /*
  424.  * flushbuf(): flush the output buffer
  425.  */
  426.     void
  427. flushbuf()
  428. {
  429.     if (bpos != 0)
  430.     {
  431.         mch_write((char *)outbuf, bpos);
  432.         bpos = 0;
  433.     }
  434. }
  435.  
  436. /*
  437.  * outchar(c): put a character into the output buffer.
  438.  *               Flush it if it becomes full.
  439.  */
  440.     void
  441. outchar(c)
  442.     unsigned    c;
  443. {
  444. #ifdef UNIX
  445.     if (c == '\n')        /* turn LF into CR-LF (CRMOD does not seem to do this) */
  446.         outchar('\r');
  447. #endif
  448.     outbuf[bpos] = c;
  449.     ++bpos;
  450.     if (bpos >= BSIZE)
  451.         flushbuf();
  452.     if (c == '\n')
  453.         char_count += Columns;
  454.     else
  455.         ++char_count;
  456. }
  457.  
  458. /*
  459.  * a never-padding outstr.
  460.  * use this whenever you don't want to run the string through tputs.
  461.  * tputs above is harmless, but tputs from the termcap library 
  462.  * is likely to strip off leading digits, that it mistakes for padding
  463.  * information. (jw)
  464.  */
  465.     void
  466. outstrn(s)
  467.     char *s;
  468. {
  469.     if (bpos > BSIZE - 20)        /* avoid terminal strings being split up */
  470.         flushbuf();
  471.     while (*s)
  472.         outchar(*s++);
  473. }
  474.  
  475. /*
  476.  * outstr(s): put a string character at a time into the output buffer.
  477.  * If TERMCAP is defined use the termcap parser. (jw)
  478.  */
  479.     void
  480. outstr(s)
  481.     register char             *s;
  482. {
  483.     if (bpos > BSIZE - 20)        /* avoid terminal strings being split up */
  484.         flushbuf();
  485.     if (s)
  486. #ifdef TERMCAP
  487.         tputs(s, 1, TPUTSFUNCAST outchar);
  488. #else
  489.         while (*s)
  490.             outchar(*s++);
  491. #endif
  492. }
  493.  
  494. /* 
  495.  * cursor positioning using termcap parser. (jw)
  496.  */
  497.     void
  498. windgoto(row, col)
  499.     int        row;
  500.     int        col;
  501. {
  502.     outstr(tgoto(T_CM, col, row));
  503. }
  504.  
  505. /*
  506.  * Set cursor to current position.
  507.  * Should be optimized for minimal terminal output.
  508.  */
  509.  
  510.     void
  511. setcursor()
  512. {
  513.     if (!RedrawingDisabled)
  514.         windgoto(Cursrow, Curscol);
  515. }
  516.  
  517.     void
  518. ttest(pairs)
  519.     int    pairs;
  520. {
  521.     char buf[70];
  522.     char *s = "terminal capability %s required.\n";
  523.     char *t = NULL;
  524.  
  525. #ifdef TTEST
  526.   TTEST(T_EL);
  527.   TTEST(T_IL);
  528.   TTEST(T_CIL);
  529.   TTEST(T_DL);
  530.   TTEST(T_CDL);
  531.   TTEST(T_ED);
  532.   TTEST(T_CI);
  533.   TTEST(T_CV);
  534.   TTEST(T_TP);
  535.   TTEST(T_TI);
  536.   TTEST(T_CM);
  537.   TTEST(T_SR);
  538.   TTEST(T_CRI);
  539. #endif /* TTEST */
  540.  
  541.   /* hard requirements */
  542.     if (!T_ED || !*T_ED)    /* erase display */
  543.         t = "cl";
  544.     if (!T_CM || !*T_CM)    /* cursor motion */
  545.         t = "cm";
  546.  
  547.     if (t)
  548.     {
  549.         sprintf(buf, s, t);
  550.         emsg(buf);
  551.     }
  552.  
  553.     if (pairs)
  554.     {
  555.       /* optional pairs */
  556.         if ((!T_TP || !*T_TP) ^ (!T_TI || !*T_TI))
  557.         {
  558.             debug2("cap :me=%s:mr=%s: ignored\n", T_TP, T_TI);
  559.             T_TP = T_TI = NULL;
  560.         }
  561.         if ((!T_CI || !*T_CI) ^ (!T_CV || !*T_CV))
  562.         {
  563.             debug2("cap :vi=%s:ve=%s: ignored\n", T_CI, T_CV);
  564.             T_CI = T_CV = NULL;
  565.         }
  566.     }
  567. }
  568.  
  569. /*
  570.  * inchar() - get one character from
  571.  *        1. a scriptfile
  572.  *        2. the keyboard
  573.  *
  574.  *  As much characters as we can get (upto 'maxlen') are put in buf and
  575.  *  NUL terminated (buffer length must be 'maxlen' + 1).
  576.  *
  577.  *    If we got an interrupt all input is read until none is available.
  578.  *
  579.  *  If time == 0  there is no waiting for the char.
  580.  *  If time == n  we wait for n msec for a character to arrive.
  581.  *  If time == -1 we wait forever for a character to arrive.
  582.  *
  583.  *  Return the number of obtained characters.
  584.  */
  585.  
  586.     int
  587. inchar(buf, maxlen, time)
  588.     char    *buf;
  589.     int        maxlen;
  590.     int        time;                        /* milli seconds */
  591. {
  592.     int                len;
  593.     int                retesc = FALSE;        /* return ESC with gotint */
  594.     register int     c;
  595.     register int    i;
  596.  
  597.     if (time == -1)                /* flush output before blocking */
  598.         flushbuf();
  599.     did_outofmem_msg = FALSE;    /* display out of memory message (again) */
  600.  
  601. /*
  602.  * first try script file
  603.  *    If interrupted: Stop reading script files.
  604.  */
  605. retry:
  606.     if (scriptin[curscript] != NULL)
  607.     {
  608.         if (got_int || (c = getc(scriptin[curscript])) < 0)    /* reached EOF */
  609.         {
  610.                 /* when reading script file is interrupted, return an ESC to
  611.                                     get back to normal mode */
  612.             if (got_int)
  613.                 retesc = TRUE;
  614.             fclose(scriptin[curscript]);
  615.             scriptin[curscript] = NULL;
  616.             if (curscript > 0)
  617.                 --curscript;
  618.                 /* recovery may be delayed till after reading a script file */
  619.             if (recoverymode)
  620.                 openrecover();
  621.             goto retry;        /* may read other script if this one was nested */
  622.         }
  623.         if (c == 0)
  624.             c = K_ZERO;        /* replace ^@ with special code */
  625.         *buf++ = c;
  626.         *buf = NUL;
  627.         return 1;
  628.     }
  629.  
  630. /*
  631.  * If we got an interrupt, skip all previously typed characters and
  632.  * return TRUE if quit reading script file.
  633.  */
  634.     if (got_int)            /* skip typed characters */
  635.     {
  636.         while (GetChars(buf, maxlen, T_PEEK))
  637.             ;
  638.         return retesc;
  639.     }
  640.     len = GetChars(buf, maxlen, time);
  641.  
  642.     for (i = len; --i >= 0; ++buf)
  643.         if (*buf == 0)
  644.             *(u_char *)buf = K_ZERO;        /* replace ^@ with special code */
  645.     *buf = NUL;                                /* add trailing NUL */
  646.     return len;
  647. }
  648.  
  649. /*
  650.  * Check if buf[] begins with a terminal key code.
  651.  * Return 0 for no match, -1 for partial match, > 0 for full match.
  652.  * With a match the replacement code is put in buf[0], the match is
  653.  * removed and the number characters in buf is returned.
  654.  */
  655.     int
  656. check_termcode(buf)
  657.     char    *buf;
  658. {
  659.     char     **p;
  660.     int        slen;
  661.     int        len;
  662.  
  663.     len = strlen(buf);
  664.     for (p = (char **)&term_strings.t_ku; p != (char **)&term_strings.t_undo + 1; ++p)
  665.     {
  666.         if (*p == NULL || (slen = strlen(*p)) == 0)        /* empty entry */
  667.             continue;
  668.         if (strncmp(*p, buf, (size_t)(slen > len ? len : slen)) == 0)
  669.         {
  670.             if (len >= slen)        /* got the complete sequence */
  671.             {
  672.                 len -= slen;
  673.                 memmove(buf + 1, buf + slen, (size_t)(len + 1));
  674.                     /* this relies on the Key numbers to be consecutive! */
  675.                 buf[0] = K_UARROW + (p - (char **)&term_strings.t_ku);
  676.                 return (len + 1);
  677.             }
  678.             return -1;                /* got a partial sequence */
  679.         }
  680.     }
  681.     return 0;                        /* no match found */
  682. }
  683.  
  684. /*
  685.  * outnum - output a (big) number fast
  686.  */
  687.     void
  688. outnum(n)
  689.     register long n;
  690. {
  691.     outstrn(tltoa((unsigned long)n));
  692. }
  693.  
  694. /*
  695.  * outnuml - output a (big) number fast and return the number of characters
  696.  */
  697.     int
  698. outnuml(n)
  699.     register long n;
  700. {
  701.     char *s;
  702.  
  703.     s = tltoa((unsigned long)n);
  704.     outstrn(s);
  705.     return (int)strlen(s);
  706. }
  707.  
  708.     void
  709. check_winsize()
  710. {
  711.     if (Columns < 5)
  712.         Columns = 5;
  713.     else if (Columns > MAX_COLUMNS)
  714.         Columns = MAX_COLUMNS;
  715.     if (Rows < 2)
  716.         Rows = 2;
  717.     p_scroll = Rows >> 1;
  718. }
  719.  
  720. /*
  721.  * set window size
  722.  * If 'mustset' is TRUE, we must set Rows and Columns, do not get real
  723.  * window size (this is used for the :win command during recovery).
  724.  * If 'mustset' is FALSE, we may try to get the real window size and if
  725.  * it fails use 'width' and 'height'.
  726.  */
  727.     void
  728. set_winsize(width, height, mustset)
  729.     int        width, height;
  730.     int        mustset;
  731. {
  732.     register int         tmp;
  733.  
  734.     if (width < 0 || height < 0)    /* just checking... */
  735.         return;
  736.  
  737.     if (State == HITRETURN || State == SETWSIZE)    /* postpone the resizing */
  738.     {
  739.         State = SETWSIZE;
  740.         return;
  741.     }
  742.     screenclear();
  743. #ifdef AMIGA
  744.     flushbuf();         /* must do this before mch_get_winsize for some obscure reason */
  745. #endif /* AMIGA */
  746.     if (mustset || mch_get_winsize())
  747.     {
  748.         debug("mch_get_win failed\n");
  749.         Rows = height;
  750.         Columns = width;
  751.         mch_set_winsize();
  752.     }
  753.     check_winsize();        /* always check, to get p_scroll right */
  754.     if (State == HELP)
  755.         redrawhelp();
  756.     else if (!starting)
  757.     {
  758.         tmp = RedrawingDisabled;
  759.         RedrawingDisabled = FALSE;
  760.         comp_Botline();
  761.         updateScreen(CURSUPD);
  762.         RedrawingDisabled = tmp;
  763.         if (State == CMDLINE)
  764.             redrawcmdline();
  765.         else
  766.             setcursor();
  767.     }
  768.     flushbuf();
  769. }
  770.  
  771. /*
  772.  * set active window height (for "z<number><CR>" command)
  773.  */
  774.     void
  775. set_winheight(height)
  776.     int        height;
  777. {
  778.     if (height > Rows_max)            /* can't make it larger */
  779.         height = Rows_max;
  780.     Rows = height;
  781.     check_winsize();
  782.     updateScreen(CLEAR);
  783. }
  784.  
  785.     void
  786. settmode(raw)
  787.     int     raw;
  788. {
  789.     static int        oldraw = FALSE;
  790.  
  791.     if (oldraw == raw)        /* skip if already in desired mode */
  792.         return;
  793.     oldraw = raw;
  794.  
  795.     mch_settmode(raw);    /* machine specific function */
  796. }
  797.  
  798.     void
  799. starttermcap()
  800. {
  801.     outstr(T_KS);    /* start "keypad transmit" mode */
  802.     outstr(T_TS);    /* start termcap mode */
  803.     flushbuf();
  804.     termcap_active = TRUE;
  805. }
  806.  
  807.     void
  808. stoptermcap()
  809. {
  810.     outstr(T_KE);    /* stop "keypad transmit" mode */
  811.     outstr(T_TE);    /* stop termcap mode */
  812.     flushbuf();
  813.     termcap_active = FALSE;
  814. }
  815.  
  816. /*
  817.  * enable cursor, unless in Visual mode or no inversion possible
  818.  */
  819.     void
  820. cursor_on()
  821. {
  822.     if (!Visual.lnum || T_TI == NULL || *T_TI == NUL)
  823.         outstr(T_CV);
  824. }
  825.  
  826.     void
  827. cursor_off()
  828. {
  829.     outstr(T_CI);            /* disable cursor */
  830. }
  831.