home *** CD-ROM | disk | FTP | other *** search
/ minnie.tuhs.org / unixen.tar / unixen / PDP-11 / Distributions / ucb / spencer_2bsd.tar.gz / 2bsd.tar / src / termlib / termcap.c < prev    next >
C/C++ Source or Header  |  1980-02-17  |  5KB  |  248 lines

  1. /* Copyright (c) 1979 Regents of the University of California */
  2. #define    BUFSIZ    512
  3.  
  4. #include <ctype.h>
  5. /*
  6.  * termcap - routines for dealing with the terminal capability data base
  7.  *
  8.  * BUG:        Should use a "last" pointer in tbuf, so that searching
  9.  *        for capabilities alphabetically would not be a n**2/2
  10.  *        process when large numbers of capabilities are given.
  11.  *
  12.  * Essentially all the work here is scanning and decoding escapes
  13.  * in string capabilities.  We don't use stdio because the editor
  14.  * doesn't, and because living w/o it is not hard.
  15.  */
  16.  
  17. static    char *tbuf;
  18. char    *tskip();
  19. char    *tgetstr();
  20. char    *tdecode();
  21.  
  22. /*
  23.  * Get an entry for terminal name in buffer bp,
  24.  * from the termcap file.  Parse is very rudimentary;
  25.  * we just notice escaped newlines.
  26.  */
  27. tgetent(bp, name)
  28.     char *bp, *name;
  29. {
  30.     register char *cp;
  31.     register int c;
  32.     register int i = 0, cnt = 0;
  33.     char ibuf[BUFSIZ];
  34.     int tf;
  35.  
  36.     tbuf = bp;
  37. #ifndef V6
  38.     cp = getenv("TERMCAP");
  39.     tf = open(cp ? cp : "/etc/termcap", 0);
  40. #else
  41.     tf = open("/etc/termcap", 0);
  42. #endif
  43.     if (tf < 0)
  44.         return (-1);
  45.     for (;;) {
  46.         cp = bp;
  47.         for (;;) {
  48.             if (i == cnt) {
  49.                 cnt = read(tf, ibuf, BUFSIZ);
  50.                 if (cnt <= 0) {
  51.                     close(tf);
  52.                     return (0);
  53.                 }
  54.                 i = 0;
  55.             }
  56.             c = ibuf[i++];
  57.             if (c == '\n') {
  58.                 if (cp > bp && cp[-1] == '\\'){
  59.                     cp--;
  60.                     continue;
  61.                 }
  62.                 break;
  63.             }
  64.             *cp++ = c;
  65.         }
  66.         *cp = 0;
  67.  
  68.         /*
  69.          * The real work for the match.
  70.          */
  71.         if (tnamatch(name)) {
  72.             close(tf);
  73.             return (1);
  74.         }
  75.     }
  76. }
  77.  
  78. /*
  79.  * Tnamatch deals with name matching.  The first field of the termcap
  80.  * entry is a sequence of names separated by |'s, so we compare
  81.  * against each such name.  The normal : terminator after the last
  82.  * name (before the first field) stops us.
  83.  */
  84. tnamatch(np)
  85.     char *np;
  86. {
  87.     register char *Np, *Bp;
  88.  
  89.     Bp = tbuf;
  90.     for (;;) {
  91.         for (Np = np; *Np && *Bp == *Np; Bp++, Np++)
  92.             continue;
  93.         if (*Np == 0 && (*Bp == '|' || *Bp == ':' || *Bp == 0))
  94.             return (1);
  95.         while (*Bp && *Bp != ':' && *Bp != '|')
  96.             Bp++;
  97.         if (*Bp == 0 || *Bp == ':')
  98.             return (0);
  99.         Bp++;
  100.     }
  101. }
  102.  
  103. /*
  104.  * Skip to the next field.  Notice that this is very dumb, not
  105.  * knowing about \: escapes or any such.  If necessary, :'s can be put
  106.  * into the termcap file in octal.
  107.  */
  108. static char *
  109. tskip(bp)
  110.     register char *bp;
  111. {
  112.  
  113.     while (*bp && *bp != ':')
  114.         bp++;
  115.     if (*bp == ':')
  116.         bp++;
  117.     return (bp);
  118. }
  119.  
  120. /*
  121.  * Return the (numeric) option id.
  122.  * Numeric options look like
  123.  *    li#80
  124.  * i.e. the option string is separated from the numeric value by
  125.  * a # character.  If the option is not found we return -1.
  126.  * Note that we handle octal numbers beginning with 0.
  127.  */
  128. tgetnum(id)
  129.     char *id;
  130. {
  131.     register int i, base;
  132.     register char *bp = tbuf;
  133.  
  134.     for (;;) {
  135.         bp = tskip(bp);
  136.         if (*bp == 0)
  137.             return (-1);
  138.         if (*bp++ != id[0] || *bp == 0 || *bp++ != id[1])
  139.             continue;
  140.         if (*bp != '#')
  141.             continue;
  142.         bp++;
  143.         base = 10;
  144.         if (*bp == '0')
  145.             base = 8;
  146.         i = 0;
  147.         while (isdigit(*bp))
  148.             i *= base, i += *bp++ - '0';
  149.         return (i);
  150.     }
  151. }
  152.  
  153. /*
  154.  * Handle a flag option.
  155.  * Flag options are given "naked", i.e. followed by a : or the end
  156.  * of the buffer.  Return 1 if we find the option, or 0 if it is
  157.  * not given.
  158.  */
  159. tgetflag(id)
  160.     char *id;
  161. {
  162.     register char *bp = tbuf;
  163.  
  164.     for (;;) {
  165.         bp = tskip(bp);
  166.         if (!*bp)
  167.             return (0);
  168.         if (*bp++ == id[0] && *bp != 0 && *bp++ == id[1] && (!*bp || *bp == ':'))
  169.             return (1);
  170.     }
  171. }
  172.  
  173. /*
  174.  * Get a string valued option.
  175.  * These are given as
  176.  *    cl=^Z
  177.  * Much decoding is done on the strings, and the strings are
  178.  * placed in area, which is a ref parameter which is updated.
  179.  * No checking on area overflow.
  180.  */
  181. char *
  182. tgetstr(id, area)
  183.     char *id, **area;
  184. {
  185.     register char *bp = tbuf;
  186.  
  187.     for (;;) {
  188.         bp = tskip(bp);
  189.         if (!*bp)
  190.             return (0);
  191.         if (*bp++ != id[0] || *bp == 0 || *bp++ != id[1])
  192.             continue;
  193.         if (*bp != '=')
  194.             continue;
  195.         bp++;
  196.         return (tdecode(bp, area));
  197.     }
  198. }
  199.  
  200. /*
  201.  * Tdecode does the grung work to decode the
  202.  * string capability escapes.
  203.  */
  204. static char *
  205. tdecode(str, area)
  206.     register char *str;
  207.     char **area;
  208. {
  209.     register char *cp;
  210.     register int c;
  211.     register char *dp;
  212.     int i;
  213.  
  214.     cp = *area;
  215.     while ((c = *str++) && c != ':') {
  216.         switch (c) {
  217.  
  218.         case '^':
  219.             c = *str++ & 037;
  220.             break;
  221.  
  222.         case '\\':
  223.             dp = "E\033^^\\\\::n\nr\rt\tb\bf\f";
  224.             c = *str++;
  225. nextc:
  226.             if (*dp++ == c) {
  227.                 c = *dp++;
  228.                 break;
  229.             }
  230.             dp++;
  231.             if (*dp)
  232.                 goto nextc;
  233.             if (isdigit(c)) {
  234.                 c -= '0', i = 2;
  235.                 do
  236.                     c <<= 3, c |= *str++ - '0';
  237.                 while (--i && isdigit(*str));
  238.             }
  239.             break;
  240.         }
  241.         *cp++ = c;
  242.     }
  243.     *cp++ = 0;
  244.     str = *area;
  245.     *area = cp;
  246.     return (str);
  247. }
  248.