vms.termcap.c revision 69408
1230154Sjilles/* $Header: /src/pub/tcsh/vms.termcap.c,v 1.6 2000/06/10 23:32:42 kim Exp $ */
2230154Sjilles/*
3230154Sjilles *	termcap.c	1.1	20/7/87		agc	Joypace Ltd
4230154Sjilles *
5230154Sjilles *	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"
12RCSID("$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
34char		*capab;		/* the capability itself */
35
36extern char	*getenv();	/* new, improved getenv */
37extern 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
45int
46tgetent(bp, name)
47char	*bp;
48char	*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
87sscanf 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 */
128int
129tgetnum(id)
130char	*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 */
162int
163tgetflag(id)
164char	*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 */
188char *
189tgetstr(id, area)
190char	*id;
191char	**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 */
268char *
269tgoto(cm, destcol, destline)
270char	*cm;
271int	destcol;
272int	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 */
324int
325tputs(cp, affcnt, outc)
326register char	*cp;
327int		affcnt;
328int		(*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