2 * termcap.c 1.1 20/7/87 agc Joypace Ltd
4 * Copyright Joypace Ltd, London, UK, 1987. All rights reserved.
5 * This file may be freely distributed provided that this notice
8 * A public domain implementation of the termcap(3) routines.
12 #if defined(_VMS_POSIX) || defined(_OSD_POSIX) || defined(__ANDROID__)
15 - Correct when TERM != name and TERMCAP is defined [tgetent]
16 - Correct the comparison for the terminal name [tgetent]
17 - Correct the value of ^x escapes [tgetstr]
18 - Added %r to reverse row/column [tgoto]
20 Paul Gillingwater <paul@actrix.gen.nz> July 1992
21 - Modified to allow terminal aliases in termcap file
22 - Uses TERMCAP environment variable for file only
30 #define ISSPACE(c) ((c) == ' ' || (c) == '\t' || (c) == '\r' || (c) == '\n')
31 #define ISDIGIT(x) ((x) >= '0' && (x) <= '9')
33 char *capab; /* the capability itself */
35 extern char *getenv(); /* new, improved getenv */
37 extern FILE *fopen(); /* old fopen */
41 * tgetent - get the termcap entry for terminal name, and put it
42 * in bp (which must be an array of 1024 chars). Returns 1 if
43 * termcap entry found, 0 if not found, and -1 if file not found.
46 tgetent(char *bp, char *name)
49 /* Use static termcap entry since termcap file usually doesn't exist. */
52 "linux|linux console:"
55 ":AL=\\E[%dL:DC=\\E[%dP:DL=\\E[%dM:IC=\\E[%d@:K2=\\E[G:al=\\E[L:"
56 ":bl=^G:cd=\\E[J:ce=\\E[K:cl=\\E[H\\E[J:cm=\\E[%i%d;%dH:cr=^M:"
57 ":cs=\\E[%i%d;%dr:ct=\\E[3g:dc=\\E[P:dl=\\E[M:do=^J:ec=\\E[%dX:"
58 ":ei=\\E[4l:ho=\\E[H:ic=\\E[@:im=\\E[4h:k1=\\E[[A:k2=\\E[[B:"
59 ":k3=\\E[[C:k4=\\E[[D:k5=\\E[[E:k6=\\E[17~:k7=\\E[18~:k8=\\E[19~:"
60 ":k9=\\E[20~:kD=\\E[3~:kI=\\E[2~:kN=\\E[6~:kP=\\E[5~:kb=\\177:"
61 ":kd=\\E[B:kh=\\E[1~:kl=\\E[D:kr=\\E[C:ku=\\E[A:le=^H:mb=\\E[5m:"
62 ":md=\\E[1m:me=\\E[0m:mh=\\E[2m:mr=\\E[7m:nd=\\E[C:nw=^M^J:"
63 ":rc=\\E8:sc=\\E7:se=\\E[27m:sf=^J:so=\\E[7m:sr=\\EM:st=\\EH:ta=^I:"
64 ":ue=\\E[24m:up=\\E[A:us=\\E[4m:vb=200\\E[?5h\\E[?5l:"
65 ":ve=\\E[?25h\\E[?0c:vi=\\E[?25l\\E[?1c:vs=\\E[?25h\\E[?0c:"
72 *ptr, /* temporary pointer */
73 tmp[1024]; /* buffer for terminal name *//*FIXBUF*/
74 size_t len = strlen(name);
78 /* Use TERMCAP to override default. */
80 termfile = getenv("TERMCAP");
81 if (termfile == NULL ) termfile = "/etc/termcap";
83 if ((fp = fopen(termfile, "r")) == (FILE *) NULL) {
84 fprintf(stderr, CGETS(31, 1,
85 "Can't open TERMCAP: [%s]\n"), termfile);
86 fprintf(stderr, CGETS(31, 2, "Can't open %s.\n"), termfile);
91 while (fgets(bp, 1024, fp) != NULL) {
92 /* Any line starting with # or NL is skipped as a comment */
93 if ((*bp == '#') || (*bp == '\n')) continue;
95 /* Look for lines which end with two backslashes,
96 and then append the next line. */
97 while (*(cp = &bp[strlen(bp) - 2]) == '\\')
100 /* Skip over any spaces or tabs */
101 for (++cp ; ISSPACE(*cp) ; cp++);
103 /* Make sure "name" matches exactly (efth) */
105 /* Here we might want to look at any aliases as well. We'll use
106 sscanf to look at aliases. These are delimited by '|'. */
108 sscanf(bp,"%[^|]",tmp);
109 if (strncmp(name, tmp, len) == 0) {
112 fprintf(stderr, CGETS(31, 3, "Found %s in %s.\n"), name, termfile);
118 while ((ptr = strchr(ptr,'|')) != NULL) {
120 if (strchr(ptr,'|') == NULL) break;
121 sscanf(ptr,"%[^|]",tmp);
122 if (strncmp(name, tmp, len) == 0) {
125 fprintf(stderr,CGETS(31, 3, "Found %s in %s.\n"), name, termfile);
132 /* If we get here, then we haven't found a match. */
135 fprintf(stderr,CGETS(31, 4, "No match found for %s in file %s\n"),
144 * tgetnum - get the numeric terminal capability corresponding
145 * to id. Returns the value, -1 if invalid.
153 if ((cp = capab) == NULL || id == NULL)
157 for (++cp ; *cp ; cp++) {
160 if (strncmp(cp, id, CAPABLEN) == 0) {
161 while (*cp && *cp != ':' && *cp != '#')
165 for (ret = 0, cp++ ; *cp && ISDIGIT(*cp) ; cp++)
166 ret = ret * 10 + *cp - '0';
169 while (*cp && *cp != ':')
176 * tgetflag - get the boolean flag corresponding to id. Returns -1
177 * if invalid, 0 if the flag is not in termcap entry, or 1 if it is
185 if ((cp = capab) == NULL || id == NULL)
189 for (++cp ; *cp ; cp++) {
192 if (strncmp(cp, id, CAPABLEN) == 0)
194 while (*cp && *cp != ':')
201 * tgetstr - get the string capability corresponding to id and place
202 * it in area (advancing area at same time). Expand escape sequences
203 * etc. Returns the string, or NULL if it can't do it.
206 tgetstr(char *id, char **area)
212 if ((cp = capab) == NULL || id == NULL)
216 for (++cp ; *cp ; cp++) {
219 if (strncmp(cp, id, CAPABLEN) == 0) {
220 while (*cp && *cp != ':' && *cp != '=')
224 for (ret = *area, cp++; *cp && *cp != ':' ;
228 **area = *++cp - '@'; /* fix (efth)*/
233 **area = CTL_ESC('\033');
254 for (i=0 ; *cp && ISDIGIT(*cp) ;
256 i = i * 8 + *cp - '0';
272 while (*cp && *cp != ':')
279 * tgoto - given the cursor motion string cm, make up the string
280 * for the cursor to go to (destcol, destline), and return the string.
281 * Returns "OOPS" if something's gone wrong, or the string otherwise.
284 tgoto(char *cm, int destcol, int destline)
289 int argno = 0, numval;
291 for (rp = ret ; *cm ; cm++) {
296 numval = (argno == 0 ? destline : destcol);
298 *rp++ = numval + incr + *++cm;
310 numval = (argno == 0 ? destline : destcol);
313 *rp++ = '0' + (numval/10);
314 *rp++ = '0' + (numval%10);
332 * tputs - put the string cp out onto the terminal, using the function
333 * outc. This should do padding for the terminal, but I can't find a
334 * terminal that needs padding at the moment...
337 tputs(char *cp, int affcnt, int (*outc)())
339 unsigned long delay = 0;
343 /* do any padding interpretation - left null for MINIX just now */
344 for (delay = 0; *cp && ISDIGIT(*cp) ; cp++)
345 delay = delay * 10 + *cp - '0';
349 usleep(delay*100); /* strictly spoken, it should be *1000 */
353 #endif /* _VMS_POSIX || _OSD_POSIX */