home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume27 / screen-3.5.1 / part02 / termcap.c < prev   
C/C++ Source or Header  |  1993-08-08  |  15KB  |  745 lines

  1. /* Copyright (c) 1993
  2.  *      Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
  3.  *      Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
  4.  * Copyright (c) 1987 Oliver Laumann
  5.  *
  6.  * This program is free software; you can redistribute it and/or modify
  7.  * it under the terms of the GNU General Public License as published by
  8.  * the Free Software Foundation; either version 2, or (at your option)
  9.  * any later version.
  10.  *
  11.  * This program is distributed in the hope that it will be useful,
  12.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  * GNU General Public License for more details.
  15.  *
  16.  * You should have received a copy of the GNU General Public License
  17.  * along with this program (see the file COPYING); if not, write to the
  18.  * Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19.  *
  20.  ****************************************************************
  21.  */
  22.  
  23. #include "rcs.h"
  24. RCS_ID("$Id: termcap.c,v 1.3 1993/07/21 15:43:35 mlschroe Exp $ FAU")
  25.  
  26. #include <sys/types.h>
  27. #include "config.h"
  28. #include "screen.h"
  29. #include "extern.h"
  30.  
  31. extern struct display *display;
  32.  
  33. static void  AddCap __P((char *));
  34. static void  MakeString __P((char *, char *, int, char *));
  35. static char *findcap __P((char *, char **, int));
  36. static char *e_tgetstr __P((char *, char **));
  37. static int   e_tgetflag __P((char *));
  38. static int   e_tgetnum __P((char *));
  39.  
  40. extern struct term term[];    /* terminal capabilities */
  41. extern struct NewWindow nwin_undef, nwin_default, nwin_options;
  42. extern int force_vt, assume_LP;
  43. extern int Z0width, Z1width;
  44.  
  45. char Termcap[TERMCAP_BUFSIZE + 8];    /* new termcap +8:"TERMCAP=" */
  46. static int Termcaplen;
  47. static int tcLineLen;
  48. char Term[MAXSTR+5];        /* +5: "TERM=" */
  49. char screenterm[20];        /* new $TERM, usually "screen" */
  50.  
  51. char *extra_incap, *extra_outcap;
  52.  
  53. static const char TermcapConst[] = "\\\n\
  54. \t:DO=\\E[%dB:LE=\\E[%dD:RI=\\E[%dC:UP=\\E[%dA:bs:bt=\\E[Z:\\\n\
  55. \t:cd=\\E[J:ce=\\E[K:cl=\\E[H\\E[J:cm=\\E[%i%d;%dH:ct=\\E[3g:\\\n\
  56. \t:do=^J:nd=\\E[C:pt:rc=\\E8:rs=\\Ec:sc=\\E7:st=\\EH:up=\\EM:\\\n\
  57. \t:le=^H:bl=^G:cr=^M:it#8:ho=\\E[H:nw=\\EE:ta=^I:is=\\E)0:";
  58.  
  59. char *
  60. gettermcapstring(s)
  61. char *s;
  62. {
  63.   int i;
  64.  
  65.   if (display == 0 || s == 0)
  66.     return 0;
  67.   for (i = 0; i < T_N; i++)
  68.     {
  69.       if (term[i].type != T_STR)
  70.     continue;
  71.       if (strcmp(term[i].tcname, s) == 0)
  72.     return d_tcs[i].str;
  73.     }
  74.   return 0;
  75. }
  76.  
  77. int
  78. InitTermcap(wi, he)
  79. int wi;
  80. int he;
  81. {
  82.   register char *s;
  83.   int i;
  84.   char tbuf[TERMCAP_BUFSIZE], *tp;
  85.  
  86.   ASSERT(display);
  87.   bzero(tbuf, sizeof(tbuf));
  88.   debug1("InitTermcap: looking for tgetent('%s')\n", d_termname);
  89.   if (tgetent(tbuf, d_termname) != 1)
  90.     {
  91.       Msg(0, "Cannot find termcap entry for %s.", d_termname);
  92.       return -1;
  93.     }
  94.   debug1("got it:\n%s\n",tbuf);
  95. #ifdef DEBUG
  96.   if (extra_incap)
  97.     debug1("Extra incap: %s\n", extra_incap);
  98.   if (extra_outcap)
  99.     debug1("Extra outcap: %s\n", extra_outcap);
  100. #endif
  101.   tp = d_tentry;
  102.  
  103.   for (i = 0; i < T_N; i++)
  104.     {
  105.       switch(term[i].type)
  106.     {
  107.     case T_FLG:
  108.       d_tcs[i].flg = e_tgetflag(term[i].tcname);
  109.       break;
  110.     case T_NUM:
  111.       d_tcs[i].num = e_tgetnum(term[i].tcname);
  112.       break;
  113.     case T_STR:
  114.       d_tcs[i].str = e_tgetstr(term[i].tcname, &tp);
  115.       /* no empty strings, please */
  116.       if (d_tcs[i].str && *d_tcs[i].str == 0)
  117.         d_tcs[i].str = 0;
  118.       break;
  119.     default:
  120.       Panic(0, "Illegal tc type in entry #%d", i);
  121.       /*NOTREACHED*/
  122.     }
  123.     }
  124.   if (HC)
  125.     {
  126.       Msg(0, "You can't run screen on a hardcopy terminal.");
  127.       return -1;
  128.     }
  129.   if (OS)
  130.     {
  131.       Msg(0, "You can't run screen on a terminal that overstrikes.");
  132.       return -1;
  133.     }
  134.   if (NS)
  135.     {
  136.       Msg(0, "Terminal must support scrolling.");
  137.       return -1;
  138.     }
  139.   if (!CL)
  140.     {
  141.       Msg(0, "Clear screen capability required.");
  142.       return -1;
  143.     }
  144.   if (!CM)
  145.     {
  146.       Msg(0, "Addressable cursor capability required.");
  147.       return -1;
  148.     }
  149.   if ((s = getenv("COLUMNS")) && (i = atoi(s)) > 0)
  150.     CO = i;
  151.   if ((s = getenv("LINES")) && (i = atoi(s)) > 0)
  152.     LI = i;
  153.   if (wi)
  154.     CO = wi;
  155.   if (he)
  156.     LI = he;
  157.   if (CO <= 0)
  158.     CO = 80;
  159.   if (LI <= 0)
  160.     LI = 24;
  161.  
  162.   if (nwin_options.flowflag == nwin_undef.flowflag)
  163.     nwin_default.flowflag = CNF ? FLOW_NOW * 0 : 
  164.                 XO ? FLOW_NOW * 1 :
  165.                 FLOW_AUTOFLAG;
  166.   CLP |= assume_LP || !AM || XV || XN ||
  167.      (!extra_incap && !strncmp(d_termname, "vt", 2));
  168.   if (!(BL = e_tgetstr("bl", &tp)))
  169.   if (!BL)
  170.     BL = "\007";
  171.   if (!BC)
  172.     {
  173.       if (BS)
  174.     BC = "\b";
  175.       else
  176.     BC = LE;
  177.     }
  178.   if (!CR)
  179.     CR = "\r";
  180.   if (!NL)
  181.     NL = "\n";
  182.   if (SG <= 0 && UG <= 0)
  183.     {
  184.       /*
  185.        * Does ME also reverse the effect of SO and/or US?  This is not
  186.        * clearly specified by the termcap manual. Anyway, we should at
  187.        * least look whether ME and SE/UE are equal:
  188.        */
  189.       if (UE && ((SE && strcmp(SE, UE) == 0) || (ME && strcmp(ME, UE) == 0)))
  190.     UE = 0;
  191.       if (SE && (ME && strcmp(ME, SE) == 0))
  192.     SE = 0;
  193.  
  194.       for (i = 0; i < NATTR; i++)
  195.     d_attrtab[i] = d_tcs[T_ATTR + i].str;
  196.       /* Set up missing entries */
  197.       s = 0;
  198.       for (i = NATTR-1; i >= 0; i--)
  199.     if (d_attrtab[i])
  200.       s = d_attrtab[i];
  201.       for (i = 0; i < NATTR; i++)
  202.     {
  203.       if (d_attrtab[i] == 0)
  204.         d_attrtab[i] = s;
  205.       else
  206.         s = d_attrtab[i];
  207.     }
  208.     }
  209.   else
  210.     {
  211.       MS = 1;
  212.       for (i = 0; i < NATTR; i++)
  213.     d_attrtab[i] = d_tcs[T_ATTR + i].str = 0;
  214.     }
  215.   if (!DO)
  216.     DO = NL;
  217.   if (!SF)
  218.     SF = NL;
  219.   if (IN)
  220.     IC = IM = 0;
  221.   if (EI == 0)
  222.     IM = 0;
  223.   /* some strange termcap entries have IC == IM */
  224.   if (IC && IM && strcmp(IC, IM) == 0)
  225.     IC = 0;
  226.   if (KE == 0)
  227.     KS = 0;
  228.   if (CCE == 0)
  229.     CCS = 0;
  230.   if (CG0)
  231.     {
  232.       if (CS0 == 0)
  233. #ifdef TERMINFO
  234.         CS0 = "\033(%p1%c";
  235. #else
  236.         CS0 = "\033(%.";
  237. #endif
  238.       if (CE0 == 0)
  239.         CE0 = "\033(B";
  240.     }
  241.   else if (AS && AE)
  242.     {
  243.       CG0 = 1;
  244.       CS0 = AS;
  245.       CE0 = AE;
  246.       CC0 = AC;
  247.     }
  248.   else
  249.     {
  250.       CS0 = CE0 = "";
  251.       CC0 = "g.h.i'j-k-l-m-n+o~p\"q-r-s_t+u+v+w+x|y<z>";
  252.     }
  253.   for (i = 0; i < 256; i++)
  254.     d_c0_tab[i] = i;
  255.   if (CC0)
  256.     for (i = strlen(CC0) & ~1; i >= 0; i -= 2)
  257.       d_c0_tab[(unsigned int)CC0[i]] = CC0[i + 1];
  258.   debug1("ISO2022 = %d\n", CG0);
  259.   if (PF == 0)
  260.     PO = 0;
  261.   debug2("terminal size is %d, %d (says TERMCAP)\n", CO, LI);
  262.  
  263.   /* Termcap fields Z0 & Z1 contain width-changing sequences. */
  264.   if (CZ1 == 0)
  265.     CZ0 = 0;
  266.   Z0width = 132;
  267.   Z1width = 80;
  268.  
  269.   CheckScreenSize(0);
  270.  
  271.   if (TS == 0 || FS == 0 || DS == 0)
  272.     HS = 0;
  273.   if (HS)
  274.     {
  275.       debug("oy! we have a hardware status line, says termcap\n");
  276.       if (WS <= 0)
  277.         WS = d_width;
  278.     }
  279.  
  280.   d_UPcost = CalcCost(UP);
  281.   d_DOcost = CalcCost(DO);
  282.   d_NLcost = CalcCost(NL);
  283.   d_LEcost = CalcCost(BC);
  284.   d_NDcost = CalcCost(ND);
  285.   d_CRcost = CalcCost(CR);
  286.   d_IMcost = CalcCost(IM);
  287.   d_EIcost = CalcCost(EI);
  288.  
  289. #ifdef AUTO_NUKE
  290.   if (CAN)
  291.     {
  292.       debug("termcap has AN, setting autonuke\n");
  293.       d_auto_nuke = 1;
  294.     }
  295. #endif
  296.   if (COL > 0)
  297.     {
  298.       debug1("termcap has OL (%d), setting limit\n", COL);
  299.       d_obufmax = COL;
  300.     }
  301.  
  302.   d_tcinited = 1;
  303.   MakeTermcap(0);
  304.   return 0;
  305. }
  306.  
  307.  
  308. static void
  309. AddCap(s)
  310. char *s;
  311. {
  312.   register int n;
  313.  
  314.   if (tcLineLen + (n = strlen(s)) > 55 && Termcaplen < TERMCAP_BUFSIZE - 4)
  315.     {
  316.       strcpy(Termcap + Termcaplen, "\\\n\t:");
  317.       Termcaplen += 4;
  318.       tcLineLen = 0;
  319.     }
  320.   if (Termcaplen + n < TERMCAP_BUFSIZE)
  321.     {
  322.       strcpy(Termcap + Termcaplen, s);
  323.       Termcaplen += n;
  324.       tcLineLen += n;
  325.     }
  326.   else
  327.     Panic(0, "TERMCAP overflow - sorry.");
  328. }
  329.  
  330. char *
  331. MakeTermcap(aflag)
  332. int aflag;
  333. {
  334.   char buf[TERMCAP_BUFSIZE];
  335.   register char *p, *cp, *s, ch, *tname;
  336.   int i, wi, he;
  337.  
  338.   if (display)
  339.     {
  340.       wi = d_width;
  341.       he = d_height;
  342.       tname = d_termname;
  343.     }
  344.   else
  345.     {
  346.       wi = 80;
  347.       he = 24;
  348.       tname = "vt100";
  349.     }
  350.   debug1("MakeTermcap(%d)\n", aflag);
  351.   if ((s = getenv("SCREENCAP")) && strlen(s) < TERMCAP_BUFSIZE)
  352.     {
  353.       sprintf(Termcap, "TERMCAP=%s", s);     /* TERMCAP_BUFSIZE + ... ? XXX */
  354.       sprintf(Term, "TERM=screen");
  355.       debug("getenvSCREENCAP o.k.\n");
  356.       return Termcap;
  357.     }
  358.   Termcaplen = 0;
  359.   debug1("MakeTermcap screenterm='%s'\n", screenterm);
  360.   debug1("MakeTermcap termname='%s'\n", tname);
  361.   if (*screenterm == '\0')
  362.     {
  363.       debug("MakeTermcap sets screenterm=screen\n");
  364.       strcpy(screenterm, "screen");
  365.     }
  366.   do
  367.     {
  368.       sprintf(Term, "TERM=");
  369.       p = Term + 5;
  370.       if (!aflag && strlen(screenterm) + strlen(tname) < MAXSTR-1)
  371.     {
  372.       sprintf(p, "%s.%s", screenterm, tname);
  373.       if (tgetent(buf, p) == 1)
  374.         break;
  375.     }
  376.       if (wi >= 132)
  377.     {
  378.       sprintf(p, "%s-w", screenterm);
  379.           if (tgetent(buf, p) == 1)
  380.         break;
  381.     }
  382.       sprintf(p, "%s", screenterm);
  383.       if (tgetent(buf, p) == 1)
  384.     break;
  385.       sprintf(p, "vt100");
  386.     }
  387.   while (0);        /* Goto free programming... */
  388.   tcLineLen = 100;    /* Force NL */
  389.   sprintf(Termcap,
  390.       "TERMCAP=SC|%s|VT 100/ANSI X3.64 virtual terminal|", Term + 5);
  391.   Termcaplen = strlen(Termcap);
  392.   debug1("MakeTermcap decided '%s'\n", p);
  393.   if (extra_outcap && *extra_outcap)
  394.     {
  395.       for (cp = extra_outcap; (p = index(cp, ':')); cp = p)
  396.     {
  397.       ch = *++p;
  398.       *p = '\0';
  399.       AddCap(cp);
  400.       *p = ch;
  401.     }
  402.       tcLineLen = 100;    /* Force NL */
  403.     }
  404.   debug1("MakeTermcap after outcap '%s'\n", (char *)TermcapConst);
  405.   if (Termcaplen + strlen(TermcapConst) < TERMCAP_BUFSIZE)
  406.     {
  407.       strcpy(Termcap + Termcaplen, (char *)TermcapConst);
  408.       Termcaplen += strlen(TermcapConst);
  409.     }
  410.   sprintf(buf, "li#%d:co#%d:", he, wi);
  411.   AddCap(buf);
  412.   AddCap("am:");
  413.   if (aflag || (force_vt && !COP) || CLP || !AM)
  414.     {
  415.       AddCap("xn:");
  416.       AddCap("xv:");
  417.       AddCap("LP:");
  418.     }
  419.   if (aflag || (CS && SR) || AL || CAL)
  420.     {
  421.       AddCap("sr=\\EM:");
  422.       AddCap("al=\\E[L:");
  423.       AddCap("AL=\\E[%dL:");
  424.     }
  425.   else if (SR)
  426.     AddCap("sr=\\EM:");
  427.   if (aflag || CS)
  428.     AddCap("cs=\\E[%i%d;%dr:");
  429.   if (aflag || CS || DL || CDL)
  430.     {
  431.       AddCap("dl=\\E[M:");
  432.       AddCap("DL=\\E[%dM:");
  433.     }
  434.   if (aflag || DC || CDC)
  435.     {
  436.       AddCap("dc=\\E[P:");
  437.       AddCap("DC=\\E[%dP:");
  438.     }
  439.   if (aflag || CIC || IC || IM)
  440.     {
  441.       AddCap("im=\\E[4h:");
  442.       AddCap("ei=\\E[4l:");
  443.       AddCap("mi:");
  444.       AddCap("IC=\\E[%d@:");
  445.     }
  446.   if (display)
  447.     {
  448.       if (US)
  449.     {
  450.       AddCap("us=\\E[4m:");
  451.       AddCap("ue=\\E[24m:");
  452.     }
  453.       if (SO)
  454.     {
  455.       AddCap("so=\\E[3m:");
  456.       AddCap("se=\\E[23m:");
  457.     }
  458.       if (MB)
  459.     AddCap("mb=\\E[5m:");
  460.       if (MD)
  461.     AddCap("md=\\E[1m:");
  462.       if (MH)
  463.     AddCap("mh=\\E[2m:");
  464.       if (MR)
  465.     AddCap("mr=\\E[7m:");
  466.       if (MB || MD || MH || MR)
  467.     AddCap("me=\\E[m:ms:");
  468.       if (VB)
  469.     AddCap("vb=\\E[?5h\\E[?5l:");
  470.       if (KS)
  471.     {
  472.       AddCap("ks=\\E=:");
  473.       AddCap("ke=\\E>:");
  474.     }
  475.       if (CCS)
  476.     {
  477.       AddCap("CS=\\E[?1h:");
  478.       AddCap("CE=\\E[?1l:");
  479.     }
  480.       if (CG0)
  481.     {
  482.       AddCap("G0:");
  483.       AddCap("as=\\E(0:");
  484.       AddCap("ae=\\E(B:");
  485.     }
  486.       if (PO)
  487.     {
  488.       AddCap("po=\\E[5i:");
  489.       AddCap("pf=\\E[4i:");
  490.     }
  491.       if (CZ0)
  492.     {
  493.       AddCap("Z0=\\E[?3h:");
  494.       AddCap("Z1=\\E[?3l:");
  495.     }
  496.       if (CWS)
  497.     AddCap("WS=\\E[8;%d;%dt:");
  498.       for (i = T_CAPS; i < T_ECAPS; i++)
  499.     {
  500.       switch(term[i].type)
  501.         {
  502.         case T_STR:
  503.           if (d_tcs[i].str == 0)
  504.         break;
  505.           MakeString(term[i].tcname, buf, sizeof(buf), d_tcs[i].str);
  506.           AddCap(buf);
  507.           break;
  508.         case T_FLG:
  509.           if (d_tcs[i].flg == 0)
  510.         break;
  511.           sprintf(buf, "%s:", term[i].tcname);
  512.           AddCap(buf);
  513.           break;
  514.         default:
  515.           break;
  516.         }
  517.     }
  518.     }
  519.   debug("MakeTermcap: end\n");
  520.   return Termcap;
  521. }
  522.  
  523. static void
  524. MakeString(cap, buf, buflen, s)
  525. char *cap, *buf;
  526. int buflen;
  527. char *s;
  528. {
  529.   register char *p, *pmax;
  530.   register unsigned int c;
  531.  
  532.   p = buf;
  533.   pmax = p + buflen - (3+4+2);
  534.   *p++ = *cap++;
  535.   *p++ = *cap;
  536.   *p++ = '=';
  537.   while ((c = *s++) && (p < pmax))
  538.     {
  539.       switch (c)
  540.     {
  541.     case '\033':
  542.       *p++ = '\\';
  543.       *p++ = 'E';
  544.       break;
  545.     case ':':
  546.       sprintf(p, "\\072");
  547.       p += 4;
  548.       break;
  549.     case '^':
  550.     case '\\':
  551.       *p++ = '\\';
  552.       *p++ = c;
  553.       break;
  554.     default:
  555.       if (c >= 200)
  556.         {
  557.           sprintf(p, "\\%03o", c & 0377);
  558.           p += 4;
  559.         }
  560.       else if (c < ' ')
  561.         {
  562.           *p++ = '^';
  563.           *p++ = c + '@';
  564.         }
  565.       else
  566.         *p++ = c;
  567.     }
  568.     }
  569.   *p++ = ':';
  570.   *p = '\0';
  571. }
  572.  
  573.  
  574. /*
  575. **
  576. **  Termcap routines that use our extra_incap
  577. **
  578. */
  579.  
  580.  
  581. /* findcap:
  582.  *   cap = capability we are looking for
  583.  *   tepp = pointer to bufferpointer
  584.  *   n = size of buffer (0 = infinity)
  585.  */
  586.  
  587. static char *
  588. findcap(cap, tepp, n)
  589. char *cap;
  590. char **tepp;
  591. int n;
  592. {
  593.   char *tep;
  594.   char c, *p, *cp;
  595.   int mode;    /* mode: 0=LIT  1=^  2=\x  3,4,5=\nnn */
  596.   int num = 0, capl;
  597.  
  598.   if (!extra_incap)
  599.     return (0);
  600.   tep = *tepp;
  601.   capl = strlen(cap);
  602.   cp = 0;
  603.   mode = 0;
  604.   for (p = extra_incap; *p; )
  605.     {
  606.       if (strncmp(p, cap, capl) == 0)
  607.     {
  608.       p += capl;
  609.       c = *p;
  610.       if (c && c != ':' && c != '@')
  611.         p++;
  612.       if (c == 0 || c == '@' || c == '=' || c == ':' || c == '#')
  613.         cp = tep;
  614.     }
  615.       while ((c = *p))
  616.     {
  617.       p++;
  618.       if (mode == 0)
  619.         {
  620.           if (c == ':')
  621.             break;
  622.           if (c == '^')
  623.         mode = 1;
  624.           if (c == '\\')
  625.         mode = 2;
  626.         }
  627.       else if (mode == 1)
  628.         {
  629.           mode = 0;
  630.           c = c & 0x1f;
  631.         }
  632.       else if (mode == 2)
  633.         {
  634.           mode = 0;
  635.           switch(c)
  636.         {
  637.         case '0':
  638.         case '1':
  639.         case '2':
  640.         case '3':
  641.         case '4':
  642.         case '5':
  643.         case '6':
  644.         case '7':
  645.         case '8':
  646.         case '9':
  647.           mode = 3;
  648.           num = 0;
  649.           break;
  650.         case 'E':
  651.           c = 27;
  652.           break;
  653.         case 'n':
  654.           c = '\n';
  655.           break;
  656.         case 'r':
  657.           c = '\r';
  658.           break;
  659.         case 't':
  660.           c = '\t';
  661.           break;
  662.         case 'b':
  663.           c = '\b';
  664.           break;
  665.         case 'f':
  666.           c = '\f';
  667.           break;
  668.         }
  669.         }
  670.       if (mode > 2)
  671.         {
  672.           num = num * 8 + (c - '0');
  673.           if (mode++ == 5 || (*p < '0' || *p > '9'))
  674.         {
  675.           c = num;
  676.           mode = 0;
  677.         }
  678.         }
  679.       if (mode)
  680.         continue;
  681.  
  682.       if (cp && n != 1)
  683.         {
  684.           *cp++ = c;
  685.           n--;
  686.         }
  687.     }
  688.       if (cp)
  689.     {
  690.       *cp++ = 0;
  691.       *tepp = cp;
  692.       debug2("'%s' found in extra_incap -> %s\n", cap, tep);
  693.       return(tep);
  694.     }
  695.     }
  696.   return(0);
  697. }
  698.  
  699. static char *
  700. e_tgetstr(cap, tepp)
  701. char *cap;
  702. char **tepp;
  703. {
  704.   char *tep, *tgetstr();
  705.   if ((tep = findcap(cap, tepp, 0)))
  706.     return((*tep == '@') ? 0 : tep);
  707.   return (tgetstr(cap, tepp));
  708. }
  709.  
  710. static int
  711. e_tgetflag(cap)
  712. char *cap;
  713. {
  714.   char buf[2], *bufp;
  715.   char *tep;
  716.   bufp = buf;
  717.   if ((tep = findcap(cap, &bufp, 2)))
  718.     return((*tep == '@') ? 0 : 1);
  719.   return (tgetflag(cap));
  720. }
  721.  
  722. static int
  723. e_tgetnum(cap)
  724. char *cap;
  725. {
  726.   char buf[20], *bufp;
  727.   char *tep, c;
  728.   int res, base = 10;
  729.  
  730.   bufp = buf;
  731.   if ((tep = findcap(cap, &bufp, 20)))
  732.     {
  733.       c = *tep;
  734.       if (c == '@')
  735.     return(-1);
  736.       if (c == '0')
  737.     base = 8;
  738.       res = 0;
  739.       while ((c = *tep++) >= '0' && c <= '9')
  740.     res = res * base + (c - '0');
  741.       return(res);
  742.     }
  743.   return (tgetnum(cap));
  744. }
  745.