Added termcap.c
authorceriel <none@none>
Tue, 26 Apr 1988 18:23:40 +0000 (18:23 +0000)
committerceriel <none@none>
Tue, 26 Apr 1988 18:23:40 +0000 (18:23 +0000)
lang/cem/libcc/stdio/LIST
lang/cem/libcc/stdio/termcap.c [new file with mode: 0644]

index 98d3ee2..a9249f2 100644 (file)
@@ -1,4 +1,5 @@
 tail_cc.1s.a
+termcap.c
 clearerr.c
 fgetc.c
 fgets.c
diff --git a/lang/cem/libcc/stdio/termcap.c b/lang/cem/libcc/stdio/termcap.c
new file mode 100644 (file)
index 0000000..835e50b
--- /dev/null
@@ -0,0 +1,432 @@
+/*
+ *     termcap.c       1.1     20/7/87         agc     Joypace Ltd
+ *
+ *     Copyright Joypace Ltd, London, UK, 1987. All rights reserved.
+ *     This file may be freely distributed provided that this notice
+ *     remains attached.
+ *
+ *     A public domain implementation of the termcap(3) routines.
+ *
+ *     Made fully functional by Ceriel J.H. Jacobs.
+ *
+ * BUGS:
+ *     - does not check termcap entry sizes
+ *     - not fully tested
+ */
+#include <stdio.h>
+
+#define CAPABLEN       2
+
+#define ISSPACE(c)     ((c) == ' ' || (c) == '\t' || (c) == '\r' || (c) == '\n')
+#define ISDIGIT(x)     ((x) >= '0' && (x) <= '9')
+
+short  ospeed;         /* output speed */
+char   PC;             /* padding character */
+char   *BC;            /* back cursor movement */
+char   *UP;            /* up cursor movement */
+
+static char    *capab;         /* the capability itself */
+static int     check_for_tc();
+static int     match_name();
+
+extern char    *getenv();      /* new, improved getenv */
+extern FILE    *fopen();       /* old fopen */
+
+/*
+ *     tgetent - get the termcap entry for terminal name, and put it
+ *     in bp (which must be an array of 1024 chars). Returns 1 if
+ *     termcap entry found, 0 if not found, and -1 if file not found.
+ */
+int
+tgetent(bp, name)
+char   *bp;
+char   *name;
+{
+       FILE    *fp;
+       char    *file;
+       char    *cp;
+       short   len = strlen(name);
+       char    buf[1024];
+
+       capab = bp;
+       if ((file = getenv("TERMCAP")) != (char *) NULL) {
+               if (*file != '/' &&
+                   (cp = getenv("TERM")) != NULL && strcmp(name, cp) == 0) {
+                       (void) strcpy(bp, file);
+                       return(1);
+               }
+       } else
+               file = "/etc/termcap";
+       if ((fp = fopen(file, "r")) == (FILE *) NULL)
+               return(-1); 
+       while (fgets(buf, 1024, fp) != NULL) {
+               if (buf[0] == '#') continue;
+               while (*(cp = &buf[strlen(buf) - 2]) == '\\')
+                       if (fgets(cp, 1024, fp) == NULL)
+                               return (0);
+               if (match_name(buf, name)) {
+                       strcpy(bp, buf);
+                       fclose(fp);
+                       return(check_for_tc());
+               }
+       }
+       fclose(fp);
+       return(0);
+}
+
+/*
+ *     Compare the terminal name with each termcap entry name; Return 1 if a
+ *     match is found.
+ */
+static int
+match_name(buf, name)
+       char    *buf;
+       char    *name;
+{
+       register char   *tp = buf;
+       register char   *np;
+
+       for (;;) {
+               for (np = name; *np && *tp == *np; np++, tp++) { }
+               if (*np == 0 && (*tp == '|' || *tp == ':' || *tp == 0))
+                       return(1);
+               while (*tp != 0 && *tp != '|' && *tp != ':') tp++;
+               if (*tp++ != '|') return (0);
+       }
+}
+
+/*
+ *     Handle tc= definitions recursively.
+ */
+static int
+check_for_tc()
+{
+       static int      count = 0;
+       char            *savcapab = capab;
+       char            buf[1024];
+       char            terminalname[128];
+       register char   *p = capab + strlen(capab) - 2, *q;
+
+       while (*p != ':')
+               if (--p < capab)
+                       return(0);      /* no : in termcap entry */
+       if (p[1] != 't' || p[2] != 'c')
+               return(1);
+       if (++count > 16) return(0);    /* recursion in tc= definitions */
+       strcpy(terminalname, &p[4]);
+       q = terminalname;
+       while (*q && *q != ':') q++;
+       *q = 0;
+       if (tgetent(buf, terminalname) != 1) return(0);
+       for (q = buf; *q && *q != ':'; q++) { }
+       strcpy(p, q);
+       capab = savcapab;
+       return(1);
+}
+
+/*
+ *     tgetnum - get the numeric terminal capability corresponding
+ *     to id. Returns the value, -1 if invalid.
+ */
+int
+tgetnum(id)
+char   *id;
+{
+       char    *cp;
+       int     ret;
+
+       if ((cp = capab) == NULL || id == NULL)
+               return(-1);
+       while (*++cp != ':')
+               ;
+       for (++cp ; *cp ; cp++) {
+               while (ISSPACE(*cp))
+                       cp++;
+               if (strncmp(cp, id, CAPABLEN) == 0) {
+                       while (*cp && *cp != ':' && *cp != '#')
+                               cp++;
+                       if (*cp != '#')
+                               return(-1);
+                       for (ret = 0, cp++ ; *cp && ISDIGIT(*cp) ; cp++)
+                               ret = ret * 10 + *cp - '0';
+                       return(ret);
+               }
+               while (*cp && *cp != ':')
+                       cp++;
+       }
+       return(-1);
+}
+
+/*
+ *     tgetflag - get the boolean flag corresponding to id. Returns -1
+ *     if invalid, 0 if the flag is not in termcap entry, or 1 if it is
+ *     present.
+ */
+int
+tgetflag(id)
+char   *id;
+{
+       char    *cp;
+
+       if ((cp = capab) == NULL || id == NULL)
+               return(-1);
+       while (*++cp != ':')
+               ;
+       for (++cp ; *cp ; cp++) {
+               while (ISSPACE(*cp))
+                       cp++;
+               if (strncmp(cp, id, CAPABLEN) == 0)
+                       return(1);
+               while (*cp && *cp != ':')
+                       cp++;
+       }
+       return(0);
+}
+
+/*
+ *     tgetstr - get the string capability corresponding to id and place
+ *     it in area (advancing area at same time). Expand escape sequences
+ *     etc. Returns the string, or NULL if it can't do it.
+ */
+char *
+tgetstr(id, area)
+char   *id;
+char   **area;
+{
+       char    *cp;
+       char    *ret;
+       int     i;
+
+       if ((cp = capab) == NULL || id == NULL)
+               return(NULL);
+       while (*++cp != ':')
+               ;
+       for (++cp ; *cp ; cp++) {
+               while (ISSPACE(*cp))
+                       cp++;
+               if (strncmp(cp, id, CAPABLEN) == 0) {
+                       while (*cp && *cp != ':' && *cp != '=')
+                               cp++;
+                       if (*cp != '=')
+                               return(NULL);
+                       for (ret = *area, cp++; *cp && *cp != ':' ; (*area)++, cp++)
+                               switch(*cp) {
+                               case '^' :
+                                       **area = *++cp - 'A' + 1;
+                                       break;
+                               case '\\' :
+                                       switch(*++cp) {
+                                       case 'E' :
+                                               **area = '\033';
+                                               break;
+                                       case 'n' :
+                                               **area = '\n';
+                                               break;
+                                       case 'r' :
+                                               **area = '\r';
+                                               break;
+                                       case 't' :
+                                               **area = '\t';
+                                               break;
+                                       case 'b' :
+                                               **area = '\b';
+                                               break;
+                                       case 'f' :
+                                               **area = '\f';
+                                               break;
+                                       case '0' :
+                                       case '1' :
+                                       case '2' :
+                                       case '3' :
+                                               for (i=0 ; *cp && ISDIGIT(*cp) ; cp++)
+                                                       i = i * 8 + *cp - '0';
+                                               **area = i;
+                                               cp--;
+                                               break;
+                                       case '^' :
+                                       case '\\' :
+                                               **area = *cp;
+                                               break;
+                                       }
+                                       break;
+                               default :
+                                       **area = *cp;
+                               }
+                       *(*area)++ = '\0';
+                       return(ret);
+               }
+               while (*cp && *cp != ':')
+                       cp++;
+       }
+       return(NULL);
+}
+
+/*
+ *     tgoto - given the cursor motion string cm, make up the string
+ *     for the cursor to go to (destcol, destline), and return the string.
+ *     Returns "OOPS" if something's gone wrong, or the string otherwise.
+ */
+char *
+tgoto(cm, destcol, destline)
+char   *cm;
+int    destcol;
+int    destline;
+{
+       register char   *rp;
+       static char     ret[24];
+       char            added[16];
+       int             *dp = &destline;
+       int             numval;
+       int             swapped = 0;
+
+       added[0] = 0;
+       for (rp = ret ; *cm ; cm++) {
+               if (*cm == '%') {
+                       switch(*++cm) {
+                       case '>' :
+                               if (dp == NULL)
+                                       return("OOPS");
+                               cm++;
+                               if (*dp > *cm++) {
+                                       *dp += *cm;
+                               }
+                               break;
+                       case '+' :
+                       case '.' :
+                               if (dp == NULL)
+                                       return("OOPS");
+                               if (*cm == '+') *dp = *dp + *++cm;
+                               for (;;) {
+                                   switch(*dp) {
+                                   case 0:
+                                   case 04:
+                                   case '\t':
+                                   case '\n':
+                                       /* filter these out */
+                                       if (dp == &destcol || swapped || UP) {
+                                               strcat(added, dp == &destcol || swapped ?
+                                                       (BC ? BC : "\b") :
+                                                       UP);
+                                               (*dp)++;
+                                               continue;
+                                       }
+                                   }
+                                   break;
+                               }
+                               *rp++ = *dp;
+                               dp = (dp == &destline) ? &destcol : NULL;
+                               break;
+
+                       case 'r' : {
+                               int tmp = destline;
+
+                               destline = destcol;
+                               destcol = tmp;
+                               swapped = 1 - swapped;
+                               break;
+                       }
+                       case 'n' :
+                               destcol ^= 0140;
+                               destline ^= 0140;
+                               break;
+
+                       case '%' :
+                               *rp++ = '%';
+                               break;
+
+                       case 'i' :
+                               destcol++;
+                               destline++;
+                               break;
+
+                       case 'B' :
+                               if (dp == NULL)
+                                       return("OOPS");
+                               *dp = 16 * (*dp / 10) + *dp % 10;
+                               break;
+
+                       case 'D' :
+                               if (dp == NULL)
+                                       return("OOPS");
+                               *dp = *dp - 2 * (*dp % 16);
+                               break;
+
+                       case 'd' :
+                       case '2' :
+                       case '3' :
+                               if (dp == NULL)
+                                       return("OOPS");
+                               numval = *dp;
+                               dp = (dp == &destline) ? &destcol : NULL;
+                               if (numval >= 100) {
+                                       *rp++ = '0' + numval / 100;
+                               }
+                               else if (*cm == '3') {
+                                       *rp++ = ' ';
+                               }
+                               if (numval >= 10) {
+                                       *rp++ = '0' + ((numval%100)/10);
+                               }
+                               else if (*cm == '3' || *cm == '2') {
+                                       *rp++ = ' ';
+                               }
+                               *rp++ = '0' + (numval%10);
+                               break;
+                       default :
+                               return("OOPS");
+                       }
+               }
+               else *rp++ = *cm;
+       }
+       *rp = '\0';
+       strcpy(rp, added);
+       return(ret);
+}
+
+static int tens_of_ms_p_char[] = {     /* index as returned by gtty */
+                                       /* assume 10 bits per char */
+       0, 2000, 1333, 909, 743, 666, 500, 333, 166, 83, 55, 41, 20, 10, 5, 2
+};
+/*
+ *     tputs - put the string cp out onto the terminal, using the function
+ *     outc. Also handle padding.
+ */
+int
+tputs(cp, affcnt, outc)
+register char  *cp;
+int            affcnt;
+int            (*outc)();
+{
+       int delay = 0;
+       if (cp == NULL)
+               return(1);
+       while (ISDIGIT(*cp)) {
+               delay = delay * 10 + (*cp++ - '0');
+       }
+       delay *= 10;
+       if (*cp == '.') {
+               cp++;
+               if (ISDIGIT(*cp)) {
+                       delay += *cp++ - '0';
+               }
+               while (ISDIGIT(*cp)) cp++;
+       }
+       if (*cp == '*') {
+               delay *= affcnt;
+               cp++;
+       }
+       while (*cp)
+               (*outc)(*cp++);
+       if (delay != 0 &&
+           ospeed > 0 &&
+           ospeed < (sizeof tens_of_ms_p_char / sizeof tens_of_ms_p_char[0])) {
+               delay = (delay + tens_of_ms_p_char[ospeed] - 1) / 
+                                 tens_of_ms_p_char[ospeed];
+               while (delay--) (*outc)(PC);
+       }
+       return(1);
+}
+
+/*
+ *     That's all, folks...
+ */