xref: /freebsd/contrib/tcsh/vms.termcap.c (revision 5521ff5a4d1929056e7ffc982fac3341ca54df7c)
1 /* $Header: /src/pub/tcsh/vms.termcap.c,v 1.6 2000/06/10 23:32:42 kim Exp $ */
2 /*
3  *	termcap.c	1.1	20/7/87		agc	Joypace Ltd
4  *
5  *	Copyright Joypace Ltd, London, UK, 1987. All rights reserved.
6  *	This file may be freely distributed provided that this notice
7  *	remains attached.
8  *
9  *	A public domain implementation of the termcap(3) routines.
10  */
11 #include "sh.h"
12 RCSID("$Id: vms.termcap.c,v 1.6 2000/06/10 23:32:42 kim Exp $")
13 #if defined(_VMS_POSIX) || defined(_OSD_POSIX)
14 /*    efth      1988-Apr-29
15 
16     - Correct when TERM != name and TERMCAP is defined   [tgetent]
17     - Correct the comparison for the terminal name       [tgetent]
18     - Correct the value of ^x escapes                    [tgetstr]
19     - Added %r to reverse row/column			 [tgoto]
20 
21      Paul Gillingwater <paul@actrix.gen.nz> July 1992
22 	- Modified to allow terminal aliases in termcap file
23 	- Uses TERMCAP environment variable for file only
24 */
25 
26 #include	<stdio.h>
27 #include	<string.h>
28 
29 #define CAPABLEN	2
30 
31 #define ISSPACE(c)  ((c) == ' ' || (c) == '\t' || (c) == '\r' || (c) == '\n')
32 #define ISDIGIT(x)  ((x) >= '0' && (x) <= '9')
33 
34 char		*capab;		/* the capability itself */
35 
36 extern char	*getenv();	/* new, improved getenv */
37 extern FILE	*fopen();	/* old fopen */
38 
39 /*
40  *	tgetent - get the termcap entry for terminal name, and put it
41  *	in bp (which must be an array of 1024 chars). Returns 1 if
42  *	termcap entry found, 0 if not found, and -1 if file not found.
43  */
44 
45 int
46 tgetent(bp, name)
47 char	*bp;
48 char	*name;
49 {
50 	FILE	*fp;
51 	char	*termfile;
52 	char	*cp,
53 		*ptr,		/* temporary pointer */
54 		tmp[1024];	/* buffer for terminal name */
55 	short	len = strlen(name);
56 
57 	capab = bp;
58 
59 	/* Use TERMCAP to override default. */
60 
61 	termfile = getenv("TERMCAP");
62 	if (termfile == NULL ) termfile = "/etc/termcap";
63 
64 	if ((fp = fopen(termfile, "r")) == (FILE *) NULL) {
65 		fprintf(stderr, CGETS(31, 1,
66 		        "Can't open TERMCAP: [%s]\n"), termfile);
67 		fprintf(stderr, CGETS(31, 2, "Can't open %s.\n"), termfile);
68 		sleep(1);
69 		return(-1);
70 	}
71 
72 	while (fgets(bp, 1024, fp) != NULL) {
73 		/* Any line starting with # or NL is skipped as a comment */
74 		if ((*bp == '#') || (*bp == '\n')) continue;
75 
76 		/* Look for lines which end with two backslashes,
77 		and then append the next line. */
78 		while (*(cp = &bp[strlen(bp) - 2]) == '\\')
79 			fgets(cp, 1024, fp);
80 
81 		/* Skip over any spaces or tabs */
82 		for (++cp ; ISSPACE(*cp) ; cp++);
83 
84 		/*  Make sure "name" matches exactly  (efth)  */
85 
86 /* Here we might want to look at any aliases as well.  We'll use
87 sscanf to look at aliases.  These are delimited by '|'. */
88 
89 		sscanf(bp,"%[^|]",tmp);
90 		if (strncmp(name, tmp, len) == 0) {
91 			fclose(fp);
92 #ifdef DEBUG
93 	fprintf(stderr, CGETS(31, 3, "Found %s in %s.\n"), name, termfile);
94 	sleep(1);
95 #endif /* DEBUG */
96 			return(1);
97 		}
98 		ptr = bp;
99 		while ((ptr = strchr(ptr,'|')) != NULL) {
100 			ptr++;
101 			if (strchr(ptr,'|') == NULL) break;
102 			sscanf(ptr,"%[^|]",tmp);
103 			if (strncmp(name, tmp, len) == 0) {
104 				fclose(fp);
105 #ifdef DEBUG
106 	fprintf(stderr,CGETS(31, 3, "Found %s in %s.\n"), name, termfile);
107 	sleep(1);
108 #endif /* DEBUG */
109 				return(1);
110 			}
111 		}
112 	}
113 	/* If we get here, then we haven't found a match. */
114 	fclose(fp);
115 #ifdef DEBUG
116 	fprintf(stderr,CGETS(31, 4, "No match found for %s in file %s\n"),
117 		name, termfile);
118 	sleep(1);
119 #endif /* DEBUG */
120 	return(0);
121 
122 }
123 
124 /*
125  *	tgetnum - get the numeric terminal capability corresponding
126  *	to id. Returns the value, -1 if invalid.
127  */
128 int
129 tgetnum(id)
130 char	*id;
131 {
132 	char	*cp;
133 	int	ret;
134 
135 	if ((cp = capab) == NULL || id == NULL)
136 		return(-1);
137 	while (*++cp != ':')
138 		;
139 	for (++cp ; *cp ; cp++) {
140 		while (ISSPACE(*cp))
141 			cp++;
142 		if (strncmp(cp, id, CAPABLEN) == 0) {
143 			while (*cp && *cp != ':' && *cp != '#')
144 				cp++;
145 			if (*cp != '#')
146 				return(-1);
147 			for (ret = 0, cp++ ; *cp && ISDIGIT(*cp) ; cp++)
148 				ret = ret * 10 + *cp - '0';
149 			return(ret);
150 		}
151 		while (*cp && *cp != ':')
152 			cp++;
153 	}
154 	return(-1);
155 }
156 
157 /*
158  *	tgetflag - get the boolean flag corresponding to id. Returns -1
159  *	if invalid, 0 if the flag is not in termcap entry, or 1 if it is
160  *	present.
161  */
162 int
163 tgetflag(id)
164 char	*id;
165 {
166 	char	*cp;
167 
168 	if ((cp = capab) == NULL || id == NULL)
169 		return(-1);
170 	while (*++cp != ':')
171 		;
172 	for (++cp ; *cp ; cp++) {
173 		while (ISSPACE(*cp))
174 			cp++;
175 		if (strncmp(cp, id, CAPABLEN) == 0)
176 			return(1);
177 		while (*cp && *cp != ':')
178 			cp++;
179 	}
180 	return(0);
181 }
182 
183 /*
184  *	tgetstr - get the string capability corresponding to id and place
185  *	it in area (advancing area at same time). Expand escape sequences
186  *	etc. Returns the string, or NULL if it can't do it.
187  */
188 char *
189 tgetstr(id, area)
190 char	*id;
191 char	**area;
192 {
193 	char	*cp;
194 	char	*ret;
195 	int	i;
196 
197 	if ((cp = capab) == NULL || id == NULL)
198 		return(NULL);
199 	while (*++cp != ':')
200 		;
201 	for (++cp ; *cp ; cp++) {
202 		while (ISSPACE(*cp))
203 			cp++;
204 		if (strncmp(cp, id, CAPABLEN) == 0) {
205 			while (*cp && *cp != ':' && *cp != '=')
206 				cp++;
207 			if (*cp != '=')
208 				return(NULL);
209 			for (ret = *area, cp++; *cp && *cp != ':' ;
210 				(*area)++, cp++)
211 				switch(*cp) {
212 				case '^' :
213 					**area = *++cp - '@'; /* fix (efth)*/
214 					break;
215 				case '\\' :
216 					switch(*++cp) {
217 					case 'E' :
218 						**area = CTL_ESC('\033');
219 						break;
220 					case 'n' :
221 						**area = '\n';
222 						break;
223 					case 'r' :
224 						**area = '\r';
225 						break;
226 					case 't' :
227 						**area = '\t';
228 						break;
229 					case 'b' :
230 						**area = '\b';
231 						break;
232 					case 'f' :
233 						**area = '\f';
234 						break;
235 					case '0' :
236 					case '1' :
237 					case '2' :
238 					case '3' :
239 						for (i=0 ; *cp && ISDIGIT(*cp) ;
240 							 cp++)
241 							i = i * 8 + *cp - '0';
242 						**area = i;
243 						cp--;
244 						break;
245 					case '^' :
246 					case '\\' :
247 						**area = *cp;
248 						break;
249 					}
250 					break;
251 				default :
252 					**area = *cp;
253 				}
254 			*(*area)++ = '\0';
255 			return(ret);
256 		}
257 		while (*cp && *cp != ':')
258 			cp++;
259 	}
260 	return(NULL);
261 }
262 
263 /*
264  *	tgoto - given the cursor motion string cm, make up the string
265  *	for the cursor to go to (destcol, destline), and return the string.
266  *	Returns "OOPS" if something's gone wrong, or the string otherwise.
267  */
268 char *
269 tgoto(cm, destcol, destline)
270 char	*cm;
271 int	destcol;
272 int	destline;
273 {
274 	register char	*rp;
275 	static char	ret[24];
276 	int		incr = 0;
277 	int 		argno = 0, numval;
278 
279 	for (rp = ret ; *cm ; cm++) {
280 		switch(*cm) {
281 		case '%' :
282 			switch(*++cm) {
283 			case '+' :
284 				numval = (argno == 0 ? destline : destcol);
285 				argno = 1 - argno;
286 				*rp++ = numval + incr + *++cm;
287 				break;
288 
289 			case '%' :
290 				*rp++ = '%';
291 				break;
292 
293 			case 'i' :
294 				incr = 1;
295 				break;
296 
297 			case 'd' :
298 				numval = (argno == 0 ? destline : destcol);
299 				numval += incr;
300 				argno = 1 - argno;
301 				*rp++ = '0' + (numval/10);
302 				*rp++ = '0' + (numval%10);
303 				break;
304 
305 			case 'r' :
306 				argno = 1;
307 				break;
308 			}
309 
310 			break;
311 		default :
312 			*rp++ = *cm;
313 		}
314 	}
315 	*rp = '\0';
316 	return(ret);
317 }
318 
319 /*
320  *	tputs - put the string cp out onto the terminal, using the function
321  *	outc. This should do padding for the terminal, but I can't find a
322  *	terminal that needs padding at the moment...
323  */
324 int
325 tputs(cp, affcnt, outc)
326 register char	*cp;
327 int		affcnt;
328 int		(*outc)();
329 {
330 	if (cp == NULL)
331 		return(1);
332 	/* do any padding interpretation - left null for MINIX just now */
333 	while (*cp)
334 		(*outc)(*cp++);
335 	return(1);
336 }
337 #endif /* _VMS_POSIX || _OSD_POSIX */
338