Merge from vendor branch LIBSTDC++:
[dragonfly.git] / contrib / tcsh / vms.termcap.c
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 */