2 * termcap.c V1.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 * Klamer Schutte V1.2 Nov. 1988
14 * - Can match multiple terminal names [tgetent]
15 * - Removal of **area assignments [tgetstr]
17 * Terrence W. Holm V1.3 May, Sep, Oct. 1988
19 * - Correct when TERM != name and TERMCAP is defined [tgetent]
20 * - Correct the comparison for the terminal name [tgetent]
21 * - Correct the value of ^x escapes [tgetstr]
22 * - Added %r to reverse row/column [tgoto]
23 * - Fixed end of definition test [tgetnum/flag/str]
25 * Terrence W. Holm V1.4 Jan. 1989
27 * - Incorporated Klamer's V1.2 fixes into V1.3
28 * - Added %d, (old %d is now %2) [tgoto]
29 * - Allow '#' comments in definition file [tgetent]
39 char *capab
= (char *)NULL
; /* the capability itself */
42 /* The following are not yet used. */
43 extern short ospeed
; /* output speed */
44 extern char PC
; /* padding character */
45 extern char *BC
; /* back cursor movement */
46 extern char *UP
; /* up cursor movement */
50 * tgetent - get the termcap entry for terminal name, and put it
51 * in bp (which must be an array of 1024 chars). Returns 1 if
52 * termcap entry found, 0 if not found, and -1 if file not found.
62 short len
= strlen(name
);
66 /* If TERMCAP begins with a '/' then use TERMCAP as the path */
67 /* Name of the termcap definitions file. If TERMCAP is a */
68 /* Definition and TERM equals "name" then use TERMCAP as the */
69 /* Definition. Otherwise use "/etc/termcap" as the path name. */
71 if ((file
= getenv("TERMCAP")) == (char *)NULL
)
72 file
= "/etc/termcap";
73 else if (*file
!= '/')
74 if ((term
= getenv("TERM")) != (char *)NULL
&& strcmp(term
, name
) == 0) {
76 strncat(bp
, file
, 1023);
79 file
= "/etc/termcap";
81 if ((fp
= fopen(file
, "r")) == (FILE *) NULL
) {
82 capab
= (char *)NULL
; /* no valid termcap */
86 /* Read in each definition */
91 if (fgets(&bp
[def_len
], (unsigned int)(1024 - def_len
), fp
) == (char *)NULL
) {
93 capab
= (char *)NULL
; /* no valid termcap */
96 def_len
= strlen(bp
) - 2;
97 } while (bp
[def_len
] == '\\');
99 while (isspace(*cp
)) cp
++;
101 /* Comment lines start with a '#' */
102 if (*cp
== '#') continue;
104 /* See if any of the terminal names in this definition */
108 if (strncmp(name
, cp
, len
) == 0 &&
109 (cp
[len
] == '|' || cp
[len
] == ':')) {
113 while ((*cp
) && (*cp
!= '|') && (*cp
!= ':')) cp
++;
114 } while (*cp
++ == '|');
120 * tgetnum - get the numeric terminal capability corresponding
121 * to id. Returns the value, -1 if invalid.
127 register char *cp
= capab
;
129 if (cp
== (char *)NULL
|| id
== (char *)NULL
) return(-1);
133 if (cp
[-1] == '\0') return(-1);
135 while (isspace(*cp
)) cp
++;
137 if (strncmp(cp
, id
, 2) == 0 && cp
[2] == '#') return(atoi(cp
+ 3));
143 * tgetflag - get the boolean flag corresponding to id. Returns -1
144 * if invalid, 0 if the flag is not in termcap entry, or 1 if it is
151 register char *cp
= capab
;
153 if (cp
== (char *)NULL
|| id
== (char *)NULL
) return(-1);
157 if (cp
[-1] == '\0') return(0);
159 while (isspace(*cp
)) cp
++;
161 if (strncmp(cp
, id
, 2) == 0) return(1);
167 * tgetstr - get the string capability corresponding to id and place
168 * it in area (advancing area at same time). Expand escape sequences
169 * etc. Returns the string, or NULL if it can't do it.
172 char *tgetstr(id
, area
)
176 register char *cp
= capab
;
177 register char *wsp
= *area
; /* workspace pointer */
179 if (cp
== (char *)NULL
|| id
== (char *)NULL
) return((char *)NULL
);
183 if (cp
[-1] == '\0') return((char *)NULL
);
185 while (isspace(*cp
)) cp
++;
187 if (strncmp(cp
, id
, 2) == 0 && cp
[2] == '=') {
188 for (cp
+= 3; *cp
&& *cp
!= ':'; wsp
++, cp
++) switch (*cp
) {
221 isdigit(*cp
); ++i
, ++cp
)
222 t
= t
* 8 + *cp
- '0';
249 * tgoto - given the cursor motion string cm, make up the string
250 * for the cursor to go to (destcol, destline), and return the string.
251 * Returns "OOPS" if something's gone wrong, or the string otherwise.
254 char *tgoto(cm
, destcol
, destline
)
259 PRIVATE
char ret
[24];
268 case 'i': incr
= 1; break;
270 case 'r': argno
= 1; break;
273 numval
= (argno
== 0 ? destline
: destcol
);
274 *rp
++ = numval
+ incr
+ *++cm
;
279 numval
= (argno
== 0 ? destline
: destcol
);
280 numval
= (numval
+ incr
) % 100;
281 *rp
++ = '0' + (numval
/ 10);
282 *rp
++ = '0' + (numval
% 10);
287 numval
= (argno
== 0 ? destline
: destcol
);
288 numval
= (numval
+ incr
) % 1000;
289 if (numval
> 99) *rp
++ = '0' + (numval
/ 100);
290 if (numval
> 9) *rp
++ = '0' + (numval
/ 10) % 10;
291 *rp
++ = '0' + (numval
% 10);
295 case '%': *rp
++ = '%'; break;
297 default: return("OOPS");
311 * tputs - put the string cp out onto the terminal, using the function
312 * outc. This should do padding for the terminal, but I can't find a
313 * terminal that needs padding at the moment...
316 int tputs(cp
, affcnt
, outc
)
319 _PROTOTYPE( void (*outc
), (int ch
));
321 if (cp
== (char *)NULL
) return(1);
322 /* Do any padding interpretation - left null for MINIX just now */
323 while (*cp
) (*outc
) (*cp
++);