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