122072Sdist /*
2*61366Sbostic * Copyright (c) 1980, 1993
3*61366Sbostic * The Regents of the University of California. All rights reserved.
436499Sbostic *
556241Selan * %sccs.include.redist.c%
622072Sdist */
722072Sdist
813300Ssam #ifndef lint
9*61366Sbostic static char sccsid[] = "@(#)termcap.c 8.1 (Berkeley) 06/04/93";
1036499Sbostic #endif /* not lint */
1113300Ssam
1232153Sjak #define PBUFSIZ 512 /* max length of filename path */
1332153Sjak #define PVECSIZ 32 /* max number of names in path */
1413300Ssam
1556138Selan #include <stdio.h>
1613300Ssam #include <ctype.h>
1754673Storek #include <stdlib.h>
1856138Selan #include <string.h>
1937833Sbostic #include "pathnames.h"
2037833Sbostic
2113300Ssam /*
2213300Ssam * termcap - routines for dealing with the terminal capability data base
2313300Ssam *
2413300Ssam * BUG: Should use a "last" pointer in tbuf, so that searching
2513300Ssam * for capabilities alphabetically would not be a n**2/2
2613300Ssam * process when large numbers of capabilities are given.
2713300Ssam * Note: If we add a last pointer now we will screw up the
2813300Ssam * tc capability. We really should compile termcap.
2913300Ssam *
3013300Ssam * Essentially all the work here is scanning and decoding escapes
3113300Ssam * in string capabilities. We don't use stdio because the editor
3213300Ssam * doesn't, and because living w/o it is not hard.
3313300Ssam */
3413300Ssam
3556138Selan static char *tbuf; /* termcap buffer */
3613300Ssam
3713300Ssam /*
3832153Sjak * Get an entry for terminal name in buffer bp from the termcap file.
3913300Ssam */
4056138Selan int
tgetent(bp,name)4113300Ssam tgetent(bp, name)
4213300Ssam char *bp, *name;
4313300Ssam {
4432153Sjak register char *p;
4513300Ssam register char *cp;
4656138Selan char *dummy;
4756138Selan char **fname;
4856138Selan char *home;
4956138Selan int i;
5056138Selan char pathbuf[PBUFSIZ]; /* holds raw path of filenames */
5156138Selan char *pathvec[PVECSIZ]; /* to point to names in pathbuf */
5256138Selan char **pvec; /* holds usable tail of path vector */
5356138Selan char *termpath;
5413300Ssam
5556138Selan fname = pathvec;
5632153Sjak pvec = pathvec;
5713300Ssam tbuf = bp;
5832153Sjak p = pathbuf;
5913300Ssam cp = getenv("TERMCAP");
6013300Ssam /*
6113300Ssam * TERMCAP can have one of two things in it. It can be the
6213300Ssam * name of a file to use instead of /etc/termcap. In this
6313300Ssam * case it better start with a "/". Or it can be an entry to
6413300Ssam * use so we don't have to read the file. In this case it
6532153Sjak * has to already have the newlines crunched out. If TERMCAP
6632153Sjak * does not hold a file name then a path of names is searched
6732153Sjak * instead. The path is found in the TERMPATH variable, or
6832153Sjak * becomes "$HOME/.termcap /etc/termcap" if no TERMPATH exists.
6913300Ssam */
7032153Sjak if (!cp || *cp != '/') { /* no TERMCAP or it holds an entry */
7132153Sjak if (termpath = getenv("TERMPATH"))
7232153Sjak strncpy(pathbuf, termpath, PBUFSIZ);
7332153Sjak else {
7432153Sjak if (home = getenv("HOME")) { /* set up default */
7532153Sjak p += strlen(home); /* path, looking in */
7632153Sjak strcpy(pathbuf, home); /* $HOME first */
7732153Sjak *p++ = '/';
7832153Sjak } /* if no $HOME look in current directory */
7937833Sbostic strncpy(p, _PATH_DEF, PBUFSIZ - (p - pathbuf));
8017676Sserge }
8113300Ssam }
8232153Sjak else /* user-defined name in TERMCAP */
8332153Sjak strncpy(pathbuf, cp, PBUFSIZ); /* still can be tokenized */
8437833Sbostic
8532153Sjak *fname++ = pathbuf; /* tokenize path into vector of names */
8632153Sjak while (*++p)
8732153Sjak if (*p == ' ' || *p == ':') {
8832153Sjak *p = '\0';
8932153Sjak while (*++p)
9032153Sjak if (*p != ' ' && *p != ':')
9132153Sjak break;
9232153Sjak if (*p == '\0')
9332153Sjak break;
9432153Sjak *fname++ = p;
9532153Sjak if (fname >= pathvec + PVECSIZ) {
9632153Sjak fname--;
9732153Sjak break;
9832153Sjak }
9932153Sjak }
10032153Sjak *fname = (char *) 0; /* mark end of vector */
10156138Selan if (cp && *cp && *cp != '/')
10256138Selan if (cgetset(cp) < 0)
10356138Selan return(-2);
10432153Sjak
10556138Selan i = cgetent(&dummy, pathvec, name);
10656138Selan
10756138Selan if (i == 0)
10856138Selan strcpy(bp, dummy);
10956138Selan
11056138Selan if (dummy)
11156138Selan free(dummy);
11256138Selan /* no tc reference loop return code in libterm XXX */
11356138Selan if (i == -3)
11456138Selan return(-1);
11556138Selan return(i + 1);
11613300Ssam }
11713300Ssam
11813300Ssam /*
11913300Ssam * Return the (numeric) option id.
12013300Ssam * Numeric options look like
12113300Ssam * li#80
12213300Ssam * i.e. the option string is separated from the numeric value by
12313300Ssam * a # character. If the option is not found we return -1.
12413300Ssam * Note that we handle octal numbers beginning with 0.
12513300Ssam */
12656138Selan int
tgetnum(id)12713300Ssam tgetnum(id)
12813300Ssam char *id;
12913300Ssam {
13056138Selan long num;
13113300Ssam
13256138Selan if (cgetnum(tbuf, id, &num) == 0)
13356138Selan return(num);
13456138Selan else
13556138Selan return(-1);
13613300Ssam }
13713300Ssam
13813300Ssam /*
13913300Ssam * Handle a flag option.
14013300Ssam * Flag options are given "naked", i.e. followed by a : or the end
14113300Ssam * of the buffer. Return 1 if we find the option, or 0 if it is
14213300Ssam * not given.
14313300Ssam */
14456138Selan int
tgetflag(id)14513300Ssam tgetflag(id)
14613300Ssam char *id;
14713300Ssam {
14856138Selan return(cgetcap(tbuf, id, ':') != NULL);
14913300Ssam }
15013300Ssam
15113300Ssam /*
15213300Ssam * Get a string valued option.
15313300Ssam * These are given as
15413300Ssam * cl=^Z
15513300Ssam * Much decoding is done on the strings, and the strings are
15613300Ssam * placed in area, which is a ref parameter which is updated.
15713300Ssam * No checking on area overflow.
15813300Ssam */
15913300Ssam char *
tgetstr(id,area)16013300Ssam tgetstr(id, area)
16113300Ssam char *id, **area;
16213300Ssam {
16356240Selan char ids[3];
16456138Selan char *s;
16513300Ssam int i;
16656138Selan
16756240Selan /*
16856240Selan * XXX
16956240Selan * This is for all the boneheaded programs that relied on tgetstr
17056240Selan * to look only at the first 2 characters of the string passed...
17156240Selan */
17256240Selan *ids = *id;
17356240Selan ids[1] = id[1];
17456240Selan ids[2] = '\0';
17556240Selan
17656240Selan if ((i = cgetstr(tbuf, ids, &s)) < 0)
17756138Selan return NULL;
17856138Selan
17956138Selan strcpy(*area, s);
18056138Selan *area += i + 1;
18156138Selan return(s);
18213300Ssam }
183