1 /* $Header: /p/tcsh/cvsroot/tcsh/vms.termcap.c,v 1.11 2006/03/02 18:46:45 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.11 2006/03/02 18:46:45 christos 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(char *bp, char *name) 49 { 50 FILE *fp; 51 char *termfile; 52 char *cp, 53 *ptr, /* temporary pointer */ 54 tmp[1024]; /* buffer for terminal name *//*FIXBUF*/ 55 size_t 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 * tgetnum - get the numeric terminal capability corresponding 125 * to id. Returns the value, -1 if invalid. 126 */ 127 int 128 tgetnum(char *id) 129 { 130 char *cp; 131 int ret; 132 133 if ((cp = capab) == NULL || id == NULL) 134 return(-1); 135 while (*++cp != ':') 136 ; 137 for (++cp ; *cp ; cp++) { 138 while (ISSPACE(*cp)) 139 cp++; 140 if (strncmp(cp, id, CAPABLEN) == 0) { 141 while (*cp && *cp != ':' && *cp != '#') 142 cp++; 143 if (*cp != '#') 144 return(-1); 145 for (ret = 0, cp++ ; *cp && ISDIGIT(*cp) ; cp++) 146 ret = ret * 10 + *cp - '0'; 147 return(ret); 148 } 149 while (*cp && *cp != ':') 150 cp++; 151 } 152 return(-1); 153 } 154 155 /* 156 * tgetflag - get the boolean flag corresponding to id. Returns -1 157 * if invalid, 0 if the flag is not in termcap entry, or 1 if it is 158 * present. 159 */ 160 int 161 tgetflag(char *id) 162 { 163 char *cp; 164 165 if ((cp = capab) == NULL || id == NULL) 166 return(-1); 167 while (*++cp != ':') 168 ; 169 for (++cp ; *cp ; cp++) { 170 while (ISSPACE(*cp)) 171 cp++; 172 if (strncmp(cp, id, CAPABLEN) == 0) 173 return(1); 174 while (*cp && *cp != ':') 175 cp++; 176 } 177 return(0); 178 } 179 180 /* 181 * tgetstr - get the string capability corresponding to id and place 182 * it in area (advancing area at same time). Expand escape sequences 183 * etc. Returns the string, or NULL if it can't do it. 184 */ 185 char * 186 tgetstr(char *id, char **area) 187 { 188 char *cp; 189 char *ret; 190 int i; 191 192 if ((cp = capab) == NULL || id == NULL) 193 return(NULL); 194 while (*++cp != ':') 195 ; 196 for (++cp ; *cp ; cp++) { 197 while (ISSPACE(*cp)) 198 cp++; 199 if (strncmp(cp, id, CAPABLEN) == 0) { 200 while (*cp && *cp != ':' && *cp != '=') 201 cp++; 202 if (*cp != '=') 203 return(NULL); 204 for (ret = *area, cp++; *cp && *cp != ':' ; 205 (*area)++, cp++) 206 switch(*cp) { 207 case '^' : 208 **area = *++cp - '@'; /* fix (efth)*/ 209 break; 210 case '\\' : 211 switch(*++cp) { 212 case 'E' : 213 **area = CTL_ESC('\033'); 214 break; 215 case 'n' : 216 **area = '\n'; 217 break; 218 case 'r' : 219 **area = '\r'; 220 break; 221 case 't' : 222 **area = '\t'; 223 break; 224 case 'b' : 225 **area = '\b'; 226 break; 227 case 'f' : 228 **area = '\f'; 229 break; 230 case '0' : 231 case '1' : 232 case '2' : 233 case '3' : 234 for (i=0 ; *cp && ISDIGIT(*cp) ; 235 cp++) 236 i = i * 8 + *cp - '0'; 237 **area = i; 238 cp--; 239 break; 240 case '^' : 241 case '\\' : 242 **area = *cp; 243 break; 244 } 245 break; 246 default : 247 **area = *cp; 248 } 249 *(*area)++ = '\0'; 250 return(ret); 251 } 252 while (*cp && *cp != ':') 253 cp++; 254 } 255 return(NULL); 256 } 257 258 /* 259 * tgoto - given the cursor motion string cm, make up the string 260 * for the cursor to go to (destcol, destline), and return the string. 261 * Returns "OOPS" if something's gone wrong, or the string otherwise. 262 */ 263 char * 264 tgoto(char *cm, int destcol, int destline) 265 { 266 char *rp; 267 static char ret[24]; 268 int incr = 0; 269 int argno = 0, numval; 270 271 for (rp = ret ; *cm ; cm++) { 272 switch(*cm) { 273 case '%' : 274 switch(*++cm) { 275 case '+' : 276 numval = (argno == 0 ? destline : destcol); 277 argno = 1 - argno; 278 *rp++ = numval + incr + *++cm; 279 break; 280 281 case '%' : 282 *rp++ = '%'; 283 break; 284 285 case 'i' : 286 incr = 1; 287 break; 288 289 case 'd' : 290 numval = (argno == 0 ? destline : destcol); 291 numval += incr; 292 argno = 1 - argno; 293 *rp++ = '0' + (numval/10); 294 *rp++ = '0' + (numval%10); 295 break; 296 297 case 'r' : 298 argno = 1; 299 break; 300 } 301 302 break; 303 default : 304 *rp++ = *cm; 305 } 306 } 307 *rp = '\0'; 308 return(ret); 309 } 310 311 /* 312 * tputs - put the string cp out onto the terminal, using the function 313 * outc. This should do padding for the terminal, but I can't find a 314 * terminal that needs padding at the moment... 315 */ 316 int 317 tputs(char *cp, int affcnt, int (*outc)()) 318 { 319 unsigned long delay = 0; 320 321 if (cp == NULL) 322 return(1); 323 /* do any padding interpretation - left null for MINIX just now */ 324 for (delay = 0; *cp && ISDIGIT(*cp) ; cp++) 325 delay = delay * 10 + *cp - '0'; 326 while (*cp) 327 (*outc)(*cp++); 328 #ifdef _OSD_POSIX 329 usleep(delay*100); /* strictly spoken, it should be *1000 */ 330 #endif 331 return(1); 332 } 333 #endif /* _VMS_POSIX || _OSD_POSIX */ 334