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.
10 * Made fully functional by Ceriel J.H. Jacobs.
13 * - does not check termcap entry sizes
19 #define ISSPACE(c) ((c) == ' ' || (c) == '\t' || (c) == '\r' || (c) == '\n')
20 #define ISDIGIT(x) ((x) >= '0' && (x) <= '9')
22 short ospeed
= 0; /* output speed */
23 char PC
= 0; /* padding character */
24 char *BC
= 0; /* back cursor movement */
25 char *UP
= 0; /* up cursor movement */
27 static char *capab
= 0; /* the capability itself */
28 static int check_for_tc();
29 static int match_name();
33 /* Some things from C-library, needed here because the C-library is not
34 loaded with Modula-2 programs
39 register char *s1
, *s2
;
41 /* Append s2 to the end of s1. */
45 /* Find the end of s1. */
46 while (*s1
!= 0) s1
++;
48 /* Now copy s2 to the end of s1. */
49 while (*s1
++ = *s2
++) /* nothing */ ;
55 register char *s1
, *s2
;
60 while (*s1
++ = *s2
++) /* nothing */;
68 /* Return length of s. */
78 register char *s1
, *s2
;
80 /* Compare 2 strings. */
88 if (*s1
++ == 0) return(0);
95 register char *s1
, *s2
;
98 /* Compare two strings, but at most n characters. */
106 if (*s1
++ == 0) break;
116 extern char ***_penviron
;
117 register char **v
= *_penviron
, *p
, *q
;
119 if (v
== 0 || name
== 0) return 0;
120 while ((p
= *v
++) != 0) {
122 while (*q
&& *q
++ == *p
++) /* nothing */ ;
123 if (*q
|| *p
!= '=') continue;
130 fgets(buf
, count
, fd
)
133 static char bf
[1024];
135 static char *pbf
= &bf
[0];
136 register char *c
= buf
;
140 if (pbf
>= &bf
[cnt
]) {
141 if ((cnt
= read(fd
, bf
, 1024)) <= 0) {
142 if (c
== buf
) return (char *) NULL
;
159 * tgetent - get the termcap entry for terminal name, and put it
160 * in bp (which must be an array of 1024 chars). Returns 1 if
161 * termcap entry found, 0 if not found, and -1 if file not found.
171 short len
= strlen(name
);
175 if ((file
= getenv("TERMCAP")) != (char *) NULL
) {
177 (cp
= getenv("TERM")) != NULL
&& strcmp(name
, cp
) == 0) {
178 (void) strcpy(bp
, file
);
181 else file
= "/etc/termcap";
183 file
= "/etc/termcap";
184 if ((fp
= open(file
, 0)) < 0) {
188 while (fgets(buf
, 1024, fp
) != NULL
) {
189 if (buf
[0] == '#') continue;
190 while (*(cp
= &buf
[strlen(buf
) - 2]) == '\\')
191 if (fgets(cp
, 1024, fp
) == NULL
)
193 if (match_name(buf
, name
)) {
196 if(check_for_tc() == 0) {
209 * Compare the terminal name with each termcap entry name; Return 1 if a
213 match_name(buf
, name
)
217 register char *tp
= buf
;
221 for (np
= name
; *np
&& *tp
== *np
; np
++, tp
++) { }
222 if (*np
== 0 && (*tp
== '|' || *tp
== ':' || *tp
== 0))
224 while (*tp
!= 0 && *tp
!= '|' && *tp
!= ':') tp
++;
225 if (*tp
++ != '|') return (0);
230 * Handle tc= definitions recursively.
235 static int count
= 0;
236 char *savcapab
= capab
;
238 char terminalname
[128];
239 register char *p
= capab
+ strlen(capab
) - 2, *q
;
243 return(0); /* no : in termcap entry */
244 if (p
[1] != 't' || p
[2] != 'c')
247 return(0); /* recursion in tc= definitions */
250 strcpy(terminalname
, &p
[4]);
252 while (*q
&& *q
!= ':') q
++;
254 if (tgetent(buf
, terminalname
) != 1) {
259 for (q
= buf
; *q
&& *q
!= ':'; q
++) { }
266 * tgetnum - get the numeric terminal capability corresponding
267 * to id. Returns the value, -1 if invalid.
276 if ((cp
= capab
) == NULL
|| id
== NULL
|| *cp
== 0)
278 while (*++cp
&& *cp
!= ':')
284 if (strncmp(cp
, id
, CAPABLEN
) == 0) {
285 while (*cp
&& *cp
!= ':' && *cp
!= '#')
289 for (ret
= 0, cp
++ ; *cp
&& ISDIGIT(*cp
) ; cp
++)
290 ret
= ret
* 10 + *cp
- '0';
293 while (*cp
&& *cp
!= ':')
300 * tgetflag - get the boolean flag corresponding to id. Returns -1
301 * if invalid, 0 if the flag is not in termcap entry, or 1 if it is
310 if ((cp
= capab
) == NULL
|| id
== NULL
|| *cp
== 0)
312 while (*++cp
&& *cp
!= ':')
318 if (strncmp(cp
, id
, CAPABLEN
) == 0)
320 while (*cp
&& *cp
!= ':')
327 * tgetstr - get the string capability corresponding to id and place
328 * it in area (advancing area at same time). Expand escape sequences
329 * etc. Returns the string, or NULL if it can't do it.
340 if ((cp
= capab
) == NULL
|| id
== NULL
|| *cp
== 0)
348 if (strncmp(cp
, id
, CAPABLEN
) == 0) {
349 while (*cp
&& *cp
!= ':' && *cp
!= '=')
353 for (ret
= *area
, cp
++; *cp
&& *cp
!= ':' ; (*area
)++, cp
++)
356 **area
= *++cp
- 'A' + 1;
382 for (i
=0 ; *cp
&& ISDIGIT(*cp
) ; cp
++)
383 i
= i
* 8 + *cp
- '0';
399 while (*cp
&& *cp
!= ':')
406 * tgoto - given the cursor motion string cm, make up the string
407 * for the cursor to go to (destcol, destline), and return the string.
408 * Returns "OOPS" if something's gone wrong, or the string otherwise.
411 tgoto(cm
, destcol
, destline
)
424 for (rp
= ret
; *cm
; cm
++) {
439 if (*cm
== '+') *dp
= *dp
+ *++cm
;
446 /* filter these out */
447 if (dp
== &destcol
|| swapped
|| UP
) {
448 strcat(added
, dp
== &destcol
|| swapped
?
458 dp
= (dp
== &destline
) ? &destcol
: NULL
;
466 swapped
= 1 - swapped
;
486 *dp
= 16 * (*dp
/ 10) + *dp
% 10;
492 *dp
= *dp
- 2 * (*dp
% 16);
501 dp
= (dp
== &destline
) ? &destcol
: NULL
;
503 *rp
++ = '0' + numval
/ 100;
505 else if (*cm
== '3') {
509 *rp
++ = '0' + ((numval
%100)/10);
511 else if (*cm
== '3' || *cm
== '2') {
514 *rp
++ = '0' + (numval
%10);
527 static int tens_of_ms_p_char
[] = { /* index as returned by gtty */
528 /* assume 10 bits per char */
529 0, 2000, 1333, 909, 743, 666, 500, 333, 166, 83, 55, 41, 20, 10, 5, 2
532 * tputs - put the string cp out onto the terminal, using the function
533 * outc. Also handle padding.
536 tputs(cp
, affcnt
, outc
)
544 while (ISDIGIT(*cp
)) {
545 delay
= delay
* 10 + (*cp
++ - '0');
551 delay
+= *cp
++ - '0';
553 while (ISDIGIT(*cp
)) cp
++;
563 ospeed
< (sizeof tens_of_ms_p_char
/ sizeof tens_of_ms_p_char
[0])) {
564 delay
= (delay
+ tens_of_ms_p_char
[ospeed
] - 1) /
565 tens_of_ms_p_char
[ospeed
];
566 while (delay
--) (*outc
)(PC
);
572 * That's all, folks...