Deleted Added
full compact
vms.termcap.c (316957) vms.termcap.c (354195)
1/* $Header: /p/tcsh/cvsroot/tcsh/vms.termcap.c,v 1.12 2011/01/09 16:25:29 christos 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"
1/*
2 * termcap.c 1.1 20/7/87 agc Joypace Ltd
3 *
4 * Copyright Joypace Ltd, London, UK, 1987. All rights reserved.
5 * This file may be freely distributed provided that this notice
6 * remains attached.
7 *
8 * A public domain implementation of the termcap(3) routines.
9 */
10#include "sh.h"
12RCSID("$tcsh: vms.termcap.c,v 1.12 2011/01/09 16:25:29 christos Exp $")
11
13#if defined(_VMS_POSIX) || defined(_OSD_POSIX) || defined(__ANDROID__)
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 */
37#ifndef fopen
38extern FILE *fopen(); /* old fopen */
39#endif
40
41/*
42 * tgetent - get the termcap entry for terminal name, and put it
43 * in bp (which must be an array of 1024 chars). Returns 1 if
44 * termcap entry found, 0 if not found, and -1 if file not found.
45 */
46int
47tgetent(char *bp, char *name)
48{
49#ifdef __ANDROID__
50 /* Use static termcap entry since termcap file usually doesn't exist. */
51 capab = bp;
52 strcpy(bp,
53 "linux|linux console:"
54 ":am:eo:mi:ms:xn:xo:"
55 ":it#8:"
56 ":AL=\\E[%dL:DC=\\E[%dP:DL=\\E[%dM:IC=\\E[%d@:K2=\\E[G:al=\\E[L:"
57 ":bl=^G:cd=\\E[J:ce=\\E[K:cl=\\E[H\\E[J:cm=\\E[%i%d;%dH:cr=^M:"
58 ":cs=\\E[%i%d;%dr:ct=\\E[3g:dc=\\E[P:dl=\\E[M:do=^J:ec=\\E[%dX:"
59 ":ei=\\E[4l:ho=\\E[H:ic=\\E[@:im=\\E[4h:k1=\\E[[A:k2=\\E[[B:"
60 ":k3=\\E[[C:k4=\\E[[D:k5=\\E[[E:k6=\\E[17~:k7=\\E[18~:k8=\\E[19~:"
61 ":k9=\\E[20~:kD=\\E[3~:kI=\\E[2~:kN=\\E[6~:kP=\\E[5~:kb=\\177:"
62 ":kd=\\E[B:kh=\\E[1~:kl=\\E[D:kr=\\E[C:ku=\\E[A:le=^H:mb=\\E[5m:"
63 ":md=\\E[1m:me=\\E[0m:mh=\\E[2m:mr=\\E[7m:nd=\\E[C:nw=^M^J:"
64 ":rc=\\E8:sc=\\E7:se=\\E[27m:sf=^J:so=\\E[7m:sr=\\EM:st=\\EH:ta=^I:"
65 ":ue=\\E[24m:up=\\E[A:us=\\E[4m:vb=200\\E[?5h\\E[?5l:"
66 ":ve=\\E[?25h\\E[?0c:vi=\\E[?25l\\E[?1c:vs=\\E[?25h\\E[?0c:"
67 );
68 return(1);
69#else
70 FILE *fp;
71 char *termfile;
72 char *cp,
73 *ptr, /* temporary pointer */
74 tmp[1024]; /* buffer for terminal name *//*FIXBUF*/
75 size_t len = strlen(name);
76
77 capab = bp;
78
79 /* Use TERMCAP to override default. */
80
81 termfile = getenv("TERMCAP");
82 if (termfile == NULL ) termfile = "/etc/termcap";
83
84 if ((fp = fopen(termfile, "r")) == (FILE *) NULL) {
85 fprintf(stderr, CGETS(31, 1,
86 "Can't open TERMCAP: [%s]\n"), termfile);
87 fprintf(stderr, CGETS(31, 2, "Can't open %s.\n"), termfile);
88 sleep(1);
89 return(-1);
90 }
91
92 while (fgets(bp, 1024, fp) != NULL) {
93 /* Any line starting with # or NL is skipped as a comment */
94 if ((*bp == '#') || (*bp == '\n')) continue;
95
96 /* Look for lines which end with two backslashes,
97 and then append the next line. */
98 while (*(cp = &bp[strlen(bp) - 2]) == '\\')
99 fgets(cp, 1024, fp);
100
101 /* Skip over any spaces or tabs */
102 for (++cp ; ISSPACE(*cp) ; cp++);
103
104 /* Make sure "name" matches exactly (efth) */
105
106/* Here we might want to look at any aliases as well. We'll use
107sscanf to look at aliases. These are delimited by '|'. */
108
109 sscanf(bp,"%[^|]",tmp);
110 if (strncmp(name, tmp, len) == 0) {
111 fclose(fp);
112#ifdef DEBUG
113 fprintf(stderr, CGETS(31, 3, "Found %s in %s.\n"), name, termfile);
114 sleep(1);
115#endif /* DEBUG */
116 return(1);
117 }
118 ptr = bp;
119 while ((ptr = strchr(ptr,'|')) != NULL) {
120 ptr++;
121 if (strchr(ptr,'|') == NULL) break;
122 sscanf(ptr,"%[^|]",tmp);
123 if (strncmp(name, tmp, len) == 0) {
124 fclose(fp);
125#ifdef DEBUG
126 fprintf(stderr,CGETS(31, 3, "Found %s in %s.\n"), name, termfile);
127 sleep(1);
128#endif /* DEBUG */
129 return(1);
130 }
131 }
132 }
133 /* If we get here, then we haven't found a match. */
134 fclose(fp);
135#ifdef DEBUG
136 fprintf(stderr,CGETS(31, 4, "No match found for %s in file %s\n"),
137 name, termfile);
138 sleep(1);
139#endif /* DEBUG */
140 return(0);
141#endif /* ANDROID */
142}
143
144/*
145 * tgetnum - get the numeric terminal capability corresponding
146 * to id. Returns the value, -1 if invalid.
147 */
148int
149tgetnum(char *id)
150{
151 char *cp;
152 int ret;
153
154 if ((cp = capab) == NULL || id == NULL)
155 return(-1);
156 while (*++cp != ':')
157 ;
158 for (++cp ; *cp ; cp++) {
159 while (ISSPACE(*cp))
160 cp++;
161 if (strncmp(cp, id, CAPABLEN) == 0) {
162 while (*cp && *cp != ':' && *cp != '#')
163 cp++;
164 if (*cp != '#')
165 return(-1);
166 for (ret = 0, cp++ ; *cp && ISDIGIT(*cp) ; cp++)
167 ret = ret * 10 + *cp - '0';
168 return(ret);
169 }
170 while (*cp && *cp != ':')
171 cp++;
172 }
173 return(-1);
174}
175
176/*
177 * tgetflag - get the boolean flag corresponding to id. Returns -1
178 * if invalid, 0 if the flag is not in termcap entry, or 1 if it is
179 * present.
180 */
181int
182tgetflag(char *id)
183{
184 char *cp;
185
186 if ((cp = capab) == NULL || id == NULL)
187 return(-1);
188 while (*++cp != ':')
189 ;
190 for (++cp ; *cp ; cp++) {
191 while (ISSPACE(*cp))
192 cp++;
193 if (strncmp(cp, id, CAPABLEN) == 0)
194 return(1);
195 while (*cp && *cp != ':')
196 cp++;
197 }
198 return(0);
199}
200
201/*
202 * tgetstr - get the string capability corresponding to id and place
203 * it in area (advancing area at same time). Expand escape sequences
204 * etc. Returns the string, or NULL if it can't do it.
205 */
206char *
207tgetstr(char *id, char **area)
208{
209 char *cp;
210 char *ret;
211 int i;
212
213 if ((cp = capab) == NULL || id == NULL)
214 return(NULL);
215 while (*++cp != ':')
216 ;
217 for (++cp ; *cp ; cp++) {
218 while (ISSPACE(*cp))
219 cp++;
220 if (strncmp(cp, id, CAPABLEN) == 0) {
221 while (*cp && *cp != ':' && *cp != '=')
222 cp++;
223 if (*cp != '=')
224 return(NULL);
225 for (ret = *area, cp++; *cp && *cp != ':' ;
226 (*area)++, cp++)
227 switch(*cp) {
228 case '^' :
229 **area = *++cp - '@'; /* fix (efth)*/
230 break;
231 case '\\' :
232 switch(*++cp) {
233 case 'E' :
234 **area = CTL_ESC('\033');
235 break;
236 case 'n' :
237 **area = '\n';
238 break;
239 case 'r' :
240 **area = '\r';
241 break;
242 case 't' :
243 **area = '\t';
244 break;
245 case 'b' :
246 **area = '\b';
247 break;
248 case 'f' :
249 **area = '\f';
250 break;
251 case '0' :
252 case '1' :
253 case '2' :
254 case '3' :
255 for (i=0 ; *cp && ISDIGIT(*cp) ;
256 cp++)
257 i = i * 8 + *cp - '0';
258 **area = i;
259 cp--;
260 break;
261 case '^' :
262 case '\\' :
263 **area = *cp;
264 break;
265 }
266 break;
267 default :
268 **area = *cp;
269 }
270 *(*area)++ = '\0';
271 return(ret);
272 }
273 while (*cp && *cp != ':')
274 cp++;
275 }
276 return(NULL);
277}
278
279/*
280 * tgoto - given the cursor motion string cm, make up the string
281 * for the cursor to go to (destcol, destline), and return the string.
282 * Returns "OOPS" if something's gone wrong, or the string otherwise.
283 */
284char *
285tgoto(char *cm, int destcol, int destline)
286{
287 char *rp;
288 static char ret[24];
289 int incr = 0;
290 int argno = 0, numval;
291
292 for (rp = ret ; *cm ; cm++) {
293 switch(*cm) {
294 case '%' :
295 switch(*++cm) {
296 case '+' :
297 numval = (argno == 0 ? destline : destcol);
298 argno = 1 - argno;
299 *rp++ = numval + incr + *++cm;
300 break;
301
302 case '%' :
303 *rp++ = '%';
304 break;
305
306 case 'i' :
307 incr = 1;
308 break;
309
310 case 'd' :
311 numval = (argno == 0 ? destline : destcol);
312 numval += incr;
313 argno = 1 - argno;
314 *rp++ = '0' + (numval/10);
315 *rp++ = '0' + (numval%10);
316 break;
317
318 case 'r' :
319 argno = 1;
320 break;
321 }
322
323 break;
324 default :
325 *rp++ = *cm;
326 }
327 }
328 *rp = '\0';
329 return(ret);
330}
331
332/*
333 * tputs - put the string cp out onto the terminal, using the function
334 * outc. This should do padding for the terminal, but I can't find a
335 * terminal that needs padding at the moment...
336 */
337int
338tputs(char *cp, int affcnt, int (*outc)())
339{
340 unsigned long delay = 0;
341
342 if (cp == NULL)
343 return(1);
344 /* do any padding interpretation - left null for MINIX just now */
345 for (delay = 0; *cp && ISDIGIT(*cp) ; cp++)
346 delay = delay * 10 + *cp - '0';
347 while (*cp)
348 (*outc)(*cp++);
349#ifdef _OSD_POSIX
350 usleep(delay*100); /* strictly spoken, it should be *1000 */
351#endif
352 return(1);
353}
354#endif /* _VMS_POSIX || _OSD_POSIX */
12#if defined(_VMS_POSIX) || defined(_OSD_POSIX) || defined(__ANDROID__)
13/* efth 1988-Apr-29
14
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]
19
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
23*/
24
25#include <stdio.h>
26#include <string.h>
27
28#define CAPABLEN 2
29
30#define ISSPACE(c) ((c) == ' ' || (c) == '\t' || (c) == '\r' || (c) == '\n')
31#define ISDIGIT(x) ((x) >= '0' && (x) <= '9')
32
33char *capab; /* the capability itself */
34
35extern char *getenv(); /* new, improved getenv */
36#ifndef fopen
37extern FILE *fopen(); /* old fopen */
38#endif
39
40/*
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.
44 */
45int
46tgetent(char *bp, char *name)
47{
48#ifdef __ANDROID__
49 /* Use static termcap entry since termcap file usually doesn't exist. */
50 capab = bp;
51 strcpy(bp,
52 "linux|linux console:"
53 ":am:eo:mi:ms:xn:xo:"
54 ":it#8:"
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:"
66 );
67 return(1);
68#else
69 FILE *fp;
70 char *termfile;
71 char *cp,
72 *ptr, /* temporary pointer */
73 tmp[1024]; /* buffer for terminal name *//*FIXBUF*/
74 size_t len = strlen(name);
75
76 capab = bp;
77
78 /* Use TERMCAP to override default. */
79
80 termfile = getenv("TERMCAP");
81 if (termfile == NULL ) termfile = "/etc/termcap";
82
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);
87 sleep(1);
88 return(-1);
89 }
90
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;
94
95 /* Look for lines which end with two backslashes,
96 and then append the next line. */
97 while (*(cp = &bp[strlen(bp) - 2]) == '\\')
98 fgets(cp, 1024, fp);
99
100 /* Skip over any spaces or tabs */
101 for (++cp ; ISSPACE(*cp) ; cp++);
102
103 /* Make sure "name" matches exactly (efth) */
104
105/* Here we might want to look at any aliases as well. We'll use
106sscanf to look at aliases. These are delimited by '|'. */
107
108 sscanf(bp,"%[^|]",tmp);
109 if (strncmp(name, tmp, len) == 0) {
110 fclose(fp);
111#ifdef DEBUG
112 fprintf(stderr, CGETS(31, 3, "Found %s in %s.\n"), name, termfile);
113 sleep(1);
114#endif /* DEBUG */
115 return(1);
116 }
117 ptr = bp;
118 while ((ptr = strchr(ptr,'|')) != NULL) {
119 ptr++;
120 if (strchr(ptr,'|') == NULL) break;
121 sscanf(ptr,"%[^|]",tmp);
122 if (strncmp(name, tmp, len) == 0) {
123 fclose(fp);
124#ifdef DEBUG
125 fprintf(stderr,CGETS(31, 3, "Found %s in %s.\n"), name, termfile);
126 sleep(1);
127#endif /* DEBUG */
128 return(1);
129 }
130 }
131 }
132 /* If we get here, then we haven't found a match. */
133 fclose(fp);
134#ifdef DEBUG
135 fprintf(stderr,CGETS(31, 4, "No match found for %s in file %s\n"),
136 name, termfile);
137 sleep(1);
138#endif /* DEBUG */
139 return(0);
140#endif /* ANDROID */
141}
142
143/*
144 * tgetnum - get the numeric terminal capability corresponding
145 * to id. Returns the value, -1 if invalid.
146 */
147int
148tgetnum(char *id)
149{
150 char *cp;
151 int ret;
152
153 if ((cp = capab) == NULL || id == NULL)
154 return(-1);
155 while (*++cp != ':')
156 ;
157 for (++cp ; *cp ; cp++) {
158 while (ISSPACE(*cp))
159 cp++;
160 if (strncmp(cp, id, CAPABLEN) == 0) {
161 while (*cp && *cp != ':' && *cp != '#')
162 cp++;
163 if (*cp != '#')
164 return(-1);
165 for (ret = 0, cp++ ; *cp && ISDIGIT(*cp) ; cp++)
166 ret = ret * 10 + *cp - '0';
167 return(ret);
168 }
169 while (*cp && *cp != ':')
170 cp++;
171 }
172 return(-1);
173}
174
175/*
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
178 * present.
179 */
180int
181tgetflag(char *id)
182{
183 char *cp;
184
185 if ((cp = capab) == NULL || id == NULL)
186 return(-1);
187 while (*++cp != ':')
188 ;
189 for (++cp ; *cp ; cp++) {
190 while (ISSPACE(*cp))
191 cp++;
192 if (strncmp(cp, id, CAPABLEN) == 0)
193 return(1);
194 while (*cp && *cp != ':')
195 cp++;
196 }
197 return(0);
198}
199
200/*
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.
204 */
205char *
206tgetstr(char *id, char **area)
207{
208 char *cp;
209 char *ret;
210 int i;
211
212 if ((cp = capab) == NULL || id == NULL)
213 return(NULL);
214 while (*++cp != ':')
215 ;
216 for (++cp ; *cp ; cp++) {
217 while (ISSPACE(*cp))
218 cp++;
219 if (strncmp(cp, id, CAPABLEN) == 0) {
220 while (*cp && *cp != ':' && *cp != '=')
221 cp++;
222 if (*cp != '=')
223 return(NULL);
224 for (ret = *area, cp++; *cp && *cp != ':' ;
225 (*area)++, cp++)
226 switch(*cp) {
227 case '^' :
228 **area = *++cp - '@'; /* fix (efth)*/
229 break;
230 case '\\' :
231 switch(*++cp) {
232 case 'E' :
233 **area = CTL_ESC('\033');
234 break;
235 case 'n' :
236 **area = '\n';
237 break;
238 case 'r' :
239 **area = '\r';
240 break;
241 case 't' :
242 **area = '\t';
243 break;
244 case 'b' :
245 **area = '\b';
246 break;
247 case 'f' :
248 **area = '\f';
249 break;
250 case '0' :
251 case '1' :
252 case '2' :
253 case '3' :
254 for (i=0 ; *cp && ISDIGIT(*cp) ;
255 cp++)
256 i = i * 8 + *cp - '0';
257 **area = i;
258 cp--;
259 break;
260 case '^' :
261 case '\\' :
262 **area = *cp;
263 break;
264 }
265 break;
266 default :
267 **area = *cp;
268 }
269 *(*area)++ = '\0';
270 return(ret);
271 }
272 while (*cp && *cp != ':')
273 cp++;
274 }
275 return(NULL);
276}
277
278/*
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.
282 */
283char *
284tgoto(char *cm, int destcol, int destline)
285{
286 char *rp;
287 static char ret[24];
288 int incr = 0;
289 int argno = 0, numval;
290
291 for (rp = ret ; *cm ; cm++) {
292 switch(*cm) {
293 case '%' :
294 switch(*++cm) {
295 case '+' :
296 numval = (argno == 0 ? destline : destcol);
297 argno = 1 - argno;
298 *rp++ = numval + incr + *++cm;
299 break;
300
301 case '%' :
302 *rp++ = '%';
303 break;
304
305 case 'i' :
306 incr = 1;
307 break;
308
309 case 'd' :
310 numval = (argno == 0 ? destline : destcol);
311 numval += incr;
312 argno = 1 - argno;
313 *rp++ = '0' + (numval/10);
314 *rp++ = '0' + (numval%10);
315 break;
316
317 case 'r' :
318 argno = 1;
319 break;
320 }
321
322 break;
323 default :
324 *rp++ = *cm;
325 }
326 }
327 *rp = '\0';
328 return(ret);
329}
330
331/*
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...
335 */
336int
337tputs(char *cp, int affcnt, int (*outc)())
338{
339 unsigned long delay = 0;
340
341 if (cp == NULL)
342 return(1);
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';
346 while (*cp)
347 (*outc)(*cp++);
348#ifdef _OSD_POSIX
349 usleep(delay*100); /* strictly spoken, it should be *1000 */
350#endif
351 return(1);
352}
353#endif /* _VMS_POSIX || _OSD_POSIX */