1 /* $Header: /src/pub/tcsh/vms.termcap.c,v 1.8 2005/03/03 16:49:16 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.8 2005/03/03 16:49:16 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 #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 47 int 48 tgetent(bp, name) 49 char *bp; 50 char *name; 51 { 52 FILE *fp; 53 char *termfile; 54 char *cp, 55 *ptr, /* temporary pointer */ 56 tmp[1024]; /* buffer for terminal name */ 57 short len = strlen(name); 58 59 capab = bp; 60 61 /* Use TERMCAP to override default. */ 62 63 termfile = getenv("TERMCAP"); 64 if (termfile == NULL ) termfile = "/etc/termcap"; 65 66 if ((fp = fopen(termfile, "r")) == (FILE *) NULL) { 67 fprintf(stderr, CGETS(31, 1, 68 "Can't open TERMCAP: [%s]\n"), termfile); 69 fprintf(stderr, CGETS(31, 2, "Can't open %s.\n"), termfile); 70 sleep(1); 71 return(-1); 72 } 73 74 while (fgets(bp, 1024, fp) != NULL) { 75 /* Any line starting with # or NL is skipped as a comment */ 76 if ((*bp == '#') || (*bp == '\n')) continue; 77 78 /* Look for lines which end with two backslashes, 79 and then append the next line. */ 80 while (*(cp = &bp[strlen(bp) - 2]) == '\\') 81 fgets(cp, 1024, fp); 82 83 /* Skip over any spaces or tabs */ 84 for (++cp ; ISSPACE(*cp) ; cp++); 85 86 /* Make sure "name" matches exactly (efth) */ 87 88 /* Here we might want to look at any aliases as well. We'll use 89 sscanf to look at aliases. These are delimited by '|'. */ 90 91 sscanf(bp,"%[^|]",tmp); 92 if (strncmp(name, tmp, len) == 0) { 93 fclose(fp); 94 #ifdef DEBUG 95 fprintf(stderr, CGETS(31, 3, "Found %s in %s.\n"), name, termfile); 96 sleep(1); 97 #endif /* DEBUG */ 98 return(1); 99 } 100 ptr = bp; 101 while ((ptr = strchr(ptr,'|')) != NULL) { 102 ptr++; 103 if (strchr(ptr,'|') == NULL) break; 104 sscanf(ptr,"%[^|]",tmp); 105 if (strncmp(name, tmp, len) == 0) { 106 fclose(fp); 107 #ifdef DEBUG 108 fprintf(stderr,CGETS(31, 3, "Found %s in %s.\n"), name, termfile); 109 sleep(1); 110 #endif /* DEBUG */ 111 return(1); 112 } 113 } 114 } 115 /* If we get here, then we haven't found a match. */ 116 fclose(fp); 117 #ifdef DEBUG 118 fprintf(stderr,CGETS(31, 4, "No match found for %s in file %s\n"), 119 name, termfile); 120 sleep(1); 121 #endif /* DEBUG */ 122 return(0); 123 124 } 125 126 /* 127 * tgetnum - get the numeric terminal capability corresponding 128 * to id. Returns the value, -1 if invalid. 129 */ 130 int 131 tgetnum(id) 132 char *id; 133 { 134 char *cp; 135 int ret; 136 137 if ((cp = capab) == NULL || id == NULL) 138 return(-1); 139 while (*++cp != ':') 140 ; 141 for (++cp ; *cp ; cp++) { 142 while (ISSPACE(*cp)) 143 cp++; 144 if (strncmp(cp, id, CAPABLEN) == 0) { 145 while (*cp && *cp != ':' && *cp != '#') 146 cp++; 147 if (*cp != '#') 148 return(-1); 149 for (ret = 0, cp++ ; *cp && ISDIGIT(*cp) ; cp++) 150 ret = ret * 10 + *cp - '0'; 151 return(ret); 152 } 153 while (*cp && *cp != ':') 154 cp++; 155 } 156 return(-1); 157 } 158 159 /* 160 * tgetflag - get the boolean flag corresponding to id. Returns -1 161 * if invalid, 0 if the flag is not in termcap entry, or 1 if it is 162 * present. 163 */ 164 int 165 tgetflag(id) 166 char *id; 167 { 168 char *cp; 169 170 if ((cp = capab) == NULL || id == NULL) 171 return(-1); 172 while (*++cp != ':') 173 ; 174 for (++cp ; *cp ; cp++) { 175 while (ISSPACE(*cp)) 176 cp++; 177 if (strncmp(cp, id, CAPABLEN) == 0) 178 return(1); 179 while (*cp && *cp != ':') 180 cp++; 181 } 182 return(0); 183 } 184 185 /* 186 * tgetstr - get the string capability corresponding to id and place 187 * it in area (advancing area at same time). Expand escape sequences 188 * etc. Returns the string, or NULL if it can't do it. 189 */ 190 char * 191 tgetstr(id, area) 192 char *id; 193 char **area; 194 { 195 char *cp; 196 char *ret; 197 int i; 198 199 if ((cp = capab) == NULL || id == NULL) 200 return(NULL); 201 while (*++cp != ':') 202 ; 203 for (++cp ; *cp ; cp++) { 204 while (ISSPACE(*cp)) 205 cp++; 206 if (strncmp(cp, id, CAPABLEN) == 0) { 207 while (*cp && *cp != ':' && *cp != '=') 208 cp++; 209 if (*cp != '=') 210 return(NULL); 211 for (ret = *area, cp++; *cp && *cp != ':' ; 212 (*area)++, cp++) 213 switch(*cp) { 214 case '^' : 215 **area = *++cp - '@'; /* fix (efth)*/ 216 break; 217 case '\\' : 218 switch(*++cp) { 219 case 'E' : 220 **area = CTL_ESC('\033'); 221 break; 222 case 'n' : 223 **area = '\n'; 224 break; 225 case 'r' : 226 **area = '\r'; 227 break; 228 case 't' : 229 **area = '\t'; 230 break; 231 case 'b' : 232 **area = '\b'; 233 break; 234 case 'f' : 235 **area = '\f'; 236 break; 237 case '0' : 238 case '1' : 239 case '2' : 240 case '3' : 241 for (i=0 ; *cp && ISDIGIT(*cp) ; 242 cp++) 243 i = i * 8 + *cp - '0'; 244 **area = i; 245 cp--; 246 break; 247 case '^' : 248 case '\\' : 249 **area = *cp; 250 break; 251 } 252 break; 253 default : 254 **area = *cp; 255 } 256 *(*area)++ = '\0'; 257 return(ret); 258 } 259 while (*cp && *cp != ':') 260 cp++; 261 } 262 return(NULL); 263 } 264 265 /* 266 * tgoto - given the cursor motion string cm, make up the string 267 * for the cursor to go to (destcol, destline), and return the string. 268 * Returns "OOPS" if something's gone wrong, or the string otherwise. 269 */ 270 char * 271 tgoto(cm, destcol, destline) 272 char *cm; 273 int destcol; 274 int destline; 275 { 276 char *rp; 277 static char ret[24]; 278 int incr = 0; 279 int argno = 0, numval; 280 281 for (rp = ret ; *cm ; cm++) { 282 switch(*cm) { 283 case '%' : 284 switch(*++cm) { 285 case '+' : 286 numval = (argno == 0 ? destline : destcol); 287 argno = 1 - argno; 288 *rp++ = numval + incr + *++cm; 289 break; 290 291 case '%' : 292 *rp++ = '%'; 293 break; 294 295 case 'i' : 296 incr = 1; 297 break; 298 299 case 'd' : 300 numval = (argno == 0 ? destline : destcol); 301 numval += incr; 302 argno = 1 - argno; 303 *rp++ = '0' + (numval/10); 304 *rp++ = '0' + (numval%10); 305 break; 306 307 case 'r' : 308 argno = 1; 309 break; 310 } 311 312 break; 313 default : 314 *rp++ = *cm; 315 } 316 } 317 *rp = '\0'; 318 return(ret); 319 } 320 321 /* 322 * tputs - put the string cp out onto the terminal, using the function 323 * outc. This should do padding for the terminal, but I can't find a 324 * terminal that needs padding at the moment... 325 */ 326 int 327 tputs(cp, affcnt, outc) 328 char *cp; 329 int affcnt; 330 int (*outc)(); 331 { 332 unsigned long delay = 0; 333 334 if (cp == NULL) 335 return(1); 336 /* do any padding interpretation - left null for MINIX just now */ 337 for (delay = 0; *cp && ISDIGIT(*cp) ; cp++) 338 delay = delay * 10 + *cp - '0'; 339 while (*cp) 340 (*outc)(*cp++); 341 #ifdef _OSD_POSIX 342 usleep(delay*100); /* strictly spoken, it should be *1000 */ 343 #endif 344 return(1); 345 } 346 #endif /* _VMS_POSIX || _OSD_POSIX */ 347