]> CyberLeo.Net >> Repos - FreeBSD/stable/10.git/blob - contrib/tcsh/vms.termcap.c
MFC r368207,368607:
[FreeBSD/stable/10.git] / contrib / tcsh / vms.termcap.c
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"
12 RCSID("$tcsh: vms.termcap.c,v 1.12 2011/01/09 16:25:29 christos Exp $")
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
34 char            *capab;         /* the capability itself */
35
36 extern char     *getenv();      /* new, improved getenv */
37 #ifndef fopen
38 extern 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  */
46 int
47 tgetent(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
107 sscanf 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  */
148 int
149 tgetnum(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  */
181 int
182 tgetflag(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  */
206 char *
207 tgetstr(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  */
284 char *
285 tgoto(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  */
337 int
338 tputs(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 */