| [9] | 1 | /*
 | 
|---|
 | 2 |  *      termcap.c       1.1     20/7/87         agc     Joypace Ltd
 | 
|---|
 | 3 |  *
 | 
|---|
 | 4 |  *      Copyright Joypace Ltd, London, UK, 1987. All rights reserved.
 | 
|---|
 | 5 |  *      This file may be freely distributed provided that this notice
 | 
|---|
 | 6 |  *      remains attached.
 | 
|---|
 | 7 |  *
 | 
|---|
 | 8 |  *      A public domain implementation of the termcap(3) routines.
 | 
|---|
 | 9 |  *
 | 
|---|
 | 10 |  *      Made fully functional by Ceriel J.H. Jacobs.
 | 
|---|
 | 11 |  *
 | 
|---|
 | 12 |  * BUGS:
 | 
|---|
 | 13 |  *      - does not check termcap entry sizes
 | 
|---|
 | 14 |  *      - not fully tested
 | 
|---|
 | 15 |  */
 | 
|---|
 | 16 | 
 | 
|---|
 | 17 | #define CAPABLEN        2
 | 
|---|
 | 18 | 
 | 
|---|
 | 19 | #define ISSPACE(c)      ((c) == ' ' || (c) == '\t' || (c) == '\r' || (c) == '\n')
 | 
|---|
 | 20 | #define ISDIGIT(x)      ((x) >= '0' && (x) <= '9')
 | 
|---|
 | 21 | 
 | 
|---|
 | 22 | short   ospeed = 0;             /* output speed */
 | 
|---|
 | 23 | char    PC = 0;                 /* padding character */
 | 
|---|
 | 24 | char    *BC = 0;                /* back cursor movement */
 | 
|---|
 | 25 | char    *UP = 0;                /* up cursor movement */
 | 
|---|
 | 26 | 
 | 
|---|
 | 27 | static char     *capab = 0;             /* the capability itself */
 | 
|---|
 | 28 | static int      check_for_tc();
 | 
|---|
 | 29 | static int      match_name();
 | 
|---|
 | 30 | 
 | 
|---|
 | 31 | #define NULL    0
 | 
|---|
 | 32 | 
 | 
|---|
 | 33 | /* Some things from C-library, needed here because the C-library is not
 | 
|---|
 | 34 |    loaded with Modula-2 programs
 | 
|---|
 | 35 | */
 | 
|---|
 | 36 | 
 | 
|---|
 | 37 | static char *
 | 
|---|
 | 38 | strcat(s1, s2)
 | 
|---|
 | 39 | register char *s1, *s2;
 | 
|---|
 | 40 | {
 | 
|---|
 | 41 |   /* Append s2 to the end of s1. */
 | 
|---|
 | 42 | 
 | 
|---|
 | 43 |   char *original = s1;
 | 
|---|
 | 44 | 
 | 
|---|
 | 45 |   /* Find the end of s1. */
 | 
|---|
 | 46 |   while (*s1 != 0) s1++;
 | 
|---|
 | 47 | 
 | 
|---|
 | 48 |   /* Now copy s2 to the end of s1. */
 | 
|---|
 | 49 |   while (*s1++ = *s2++) /* nothing */ ;
 | 
|---|
 | 50 |   return(original);
 | 
|---|
 | 51 | }
 | 
|---|
 | 52 | 
 | 
|---|
 | 53 | static char *
 | 
|---|
 | 54 | strcpy(s1, s2)
 | 
|---|
 | 55 | register char *s1, *s2;
 | 
|---|
 | 56 | {
 | 
|---|
 | 57 | /* Copy s2 to s1. */
 | 
|---|
 | 58 |   char *original = s1;
 | 
|---|
 | 59 | 
 | 
|---|
 | 60 |   while (*s1++ = *s2++) /* nothing */;
 | 
|---|
 | 61 |   return(original);
 | 
|---|
 | 62 | }
 | 
|---|
 | 63 | 
 | 
|---|
 | 64 | static int
 | 
|---|
 | 65 | strlen(s)
 | 
|---|
 | 66 | char *s;
 | 
|---|
 | 67 | {
 | 
|---|
 | 68 | /* Return length of s. */
 | 
|---|
 | 69 | 
 | 
|---|
 | 70 |   char *original = s;
 | 
|---|
 | 71 | 
 | 
|---|
 | 72 |   while (*s != 0) s++;
 | 
|---|
 | 73 |   return(s - original);
 | 
|---|
 | 74 | }
 | 
|---|
 | 75 | 
 | 
|---|
 | 76 | static int
 | 
|---|
 | 77 | strcmp(s1, s2)
 | 
|---|
 | 78 | register char *s1, *s2;
 | 
|---|
 | 79 | {
 | 
|---|
 | 80 | /* Compare 2 strings. */
 | 
|---|
 | 81 | 
 | 
|---|
 | 82 |   for(;;) {
 | 
|---|
 | 83 |         if (*s1 != *s2) {
 | 
|---|
 | 84 |                 if (!*s1) return -1;
 | 
|---|
 | 85 |                 if (!*s2) return 1;
 | 
|---|
 | 86 |                 return(*s1 - *s2);
 | 
|---|
 | 87 |         }
 | 
|---|
 | 88 |         if (*s1++ == 0) return(0);
 | 
|---|
 | 89 |         s2++;
 | 
|---|
 | 90 |   }
 | 
|---|
 | 91 | }
 | 
|---|
 | 92 | 
 | 
|---|
 | 93 | static int
 | 
|---|
 | 94 | strncmp(s1, s2, n)
 | 
|---|
 | 95 |         register char *s1, *s2;
 | 
|---|
 | 96 |         int n;
 | 
|---|
 | 97 | {
 | 
|---|
 | 98 | /* Compare two strings, but at most n characters. */
 | 
|---|
 | 99 | 
 | 
|---|
 | 100 |   while (n-- > 0) {
 | 
|---|
 | 101 |         if (*s1 != *s2) {
 | 
|---|
 | 102 |                 if (!*s1) return -1;
 | 
|---|
 | 103 |                 if (!*s2) return 1;
 | 
|---|
 | 104 |                 return(*s1 - *s2);
 | 
|---|
 | 105 |         }
 | 
|---|
 | 106 |         if (*s1++ == 0) break;
 | 
|---|
 | 107 |         s2++;
 | 
|---|
 | 108 |   }
 | 
|---|
 | 109 |   return 0;
 | 
|---|
 | 110 | }
 | 
|---|
 | 111 | 
 | 
|---|
 | 112 | static char *
 | 
|---|
 | 113 | getenv(name)
 | 
|---|
 | 114 | register char *name;
 | 
|---|
 | 115 | {
 | 
|---|
 | 116 |   extern char ***_penviron;
 | 
|---|
 | 117 |   register char **v = *_penviron, *p, *q;
 | 
|---|
 | 118 | 
 | 
|---|
 | 119 |   if (v == 0 || name == 0) return 0;
 | 
|---|
 | 120 |   while ((p = *v++) != 0) {
 | 
|---|
 | 121 |         q = name;
 | 
|---|
 | 122 |         while (*q && *q++ == *p++) /* nothing */ ;
 | 
|---|
 | 123 |         if (*q || *p != '=') continue;
 | 
|---|
 | 124 |         return(p+1);
 | 
|---|
 | 125 |   }
 | 
|---|
 | 126 |   return(0);
 | 
|---|
 | 127 | }
 | 
|---|
 | 128 | 
 | 
|---|
 | 129 | static char *
 | 
|---|
 | 130 | fgets(buf, count, fd)
 | 
|---|
 | 131 |         char *buf;
 | 
|---|
 | 132 | {
 | 
|---|
 | 133 |         static char bf[1024];
 | 
|---|
 | 134 |         static int cnt = 0;
 | 
|---|
 | 135 |         static char *pbf = &bf[0];
 | 
|---|
 | 136 |         register char *c = buf;
 | 
|---|
 | 137 | 
 | 
|---|
 | 138 | 
 | 
|---|
 | 139 |         while (--count) {
 | 
|---|
 | 140 |                 if (pbf >= &bf[cnt]) {
 | 
|---|
 | 141 |                         if ((cnt = read(fd, bf, 1024)) <= 0) {
 | 
|---|
 | 142 |                                 if (c == buf) return (char *) NULL;
 | 
|---|
 | 143 |                                 *c = 0;
 | 
|---|
 | 144 |                                 return buf;
 | 
|---|
 | 145 |                         }
 | 
|---|
 | 146 |                         pbf = &bf[0];
 | 
|---|
 | 147 |                 }
 | 
|---|
 | 148 |                 *c = *pbf++;
 | 
|---|
 | 149 |                 if (*c++ == '\n') {
 | 
|---|
 | 150 |                         *c = 0;
 | 
|---|
 | 151 |                         return buf;
 | 
|---|
 | 152 |                 }
 | 
|---|
 | 153 |         }
 | 
|---|
 | 154 |         *c = 0;
 | 
|---|
 | 155 |         return buf;
 | 
|---|
 | 156 | }
 | 
|---|
 | 157 | 
 | 
|---|
 | 158 | /*
 | 
|---|
 | 159 |  *      tgetent - get the termcap entry for terminal name, and put it
 | 
|---|
 | 160 |  *      in bp (which must be an array of 1024 chars). Returns 1 if
 | 
|---|
 | 161 |  *      termcap entry found, 0 if not found, and -1 if file not found.
 | 
|---|
 | 162 |  */
 | 
|---|
 | 163 | int
 | 
|---|
 | 164 | tgetent(bp, name)
 | 
|---|
 | 165 | char    *bp;
 | 
|---|
 | 166 | char    *name;
 | 
|---|
 | 167 | {
 | 
|---|
 | 168 |         int     fp;
 | 
|---|
 | 169 |         char    *file;
 | 
|---|
 | 170 |         char    *cp;
 | 
|---|
 | 171 |         short   len = strlen(name);
 | 
|---|
 | 172 |         char    buf[1024];
 | 
|---|
 | 173 | 
 | 
|---|
 | 174 |         capab = bp;
 | 
|---|
 | 175 |         if ((file = getenv("TERMCAP")) != (char *) NULL) {
 | 
|---|
 | 176 |                 if (*file != '/' &&
 | 
|---|
 | 177 |                     (cp = getenv("TERM")) != NULL && strcmp(name, cp) == 0) {
 | 
|---|
 | 178 |                         (void) strcpy(bp, file);
 | 
|---|
 | 179 |                         return(1);
 | 
|---|
 | 180 |                 }
 | 
|---|
 | 181 |                 else file = "/etc/termcap";
 | 
|---|
 | 182 |         } else
 | 
|---|
 | 183 |                 file = "/etc/termcap";
 | 
|---|
 | 184 |         if ((fp = open(file, 0)) < 0) {
 | 
|---|
 | 185 |                 capab = 0;
 | 
|---|
 | 186 |                 return(-1); 
 | 
|---|
 | 187 |         }
 | 
|---|
 | 188 |         while (fgets(buf, 1024, fp) != NULL) {
 | 
|---|
 | 189 |                 if (buf[0] == '#') continue;
 | 
|---|
 | 190 |                 while (*(cp = &buf[strlen(buf) - 2]) == '\\')
 | 
|---|
 | 191 |                         if (fgets(cp, 1024, fp) == NULL)
 | 
|---|
 | 192 |                                 return (0);
 | 
|---|
 | 193 |                 if (match_name(buf, name)) {
 | 
|---|
 | 194 |                         strcpy(bp, buf);
 | 
|---|
 | 195 |                         close(fp);
 | 
|---|
 | 196 |                         if(check_for_tc() == 0) {
 | 
|---|
 | 197 |                                 capab = 0;
 | 
|---|
 | 198 |                                 return 0;
 | 
|---|
 | 199 |                         }
 | 
|---|
 | 200 |                         return 1;
 | 
|---|
 | 201 |                 }
 | 
|---|
 | 202 |         }
 | 
|---|
 | 203 |         capab = 0;
 | 
|---|
 | 204 |         close(fp);
 | 
|---|
 | 205 |         return(0);
 | 
|---|
 | 206 | }
 | 
|---|
 | 207 | 
 | 
|---|
 | 208 | /*
 | 
|---|
 | 209 |  *      Compare the terminal name with each termcap entry name; Return 1 if a
 | 
|---|
 | 210 |  *      match is found.
 | 
|---|
 | 211 |  */
 | 
|---|
 | 212 | static int
 | 
|---|
 | 213 | match_name(buf, name)
 | 
|---|
 | 214 |         char    *buf;
 | 
|---|
 | 215 |         char    *name;
 | 
|---|
 | 216 | {
 | 
|---|
 | 217 |         register char   *tp = buf;
 | 
|---|
 | 218 |         register char   *np;
 | 
|---|
 | 219 | 
 | 
|---|
 | 220 |         for (;;) {
 | 
|---|
 | 221 |                 for (np = name; *np && *tp == *np; np++, tp++) { }
 | 
|---|
 | 222 |                 if (*np == 0 && (*tp == '|' || *tp == ':' || *tp == 0))
 | 
|---|
 | 223 |                         return(1);
 | 
|---|
 | 224 |                 while (*tp != 0 && *tp != '|' && *tp != ':') tp++;
 | 
|---|
 | 225 |                 if (*tp++ != '|') return (0);
 | 
|---|
 | 226 |         }
 | 
|---|
 | 227 | }
 | 
|---|
 | 228 | 
 | 
|---|
 | 229 | /*
 | 
|---|
 | 230 |  *      Handle tc= definitions recursively.
 | 
|---|
 | 231 |  */
 | 
|---|
 | 232 | static int
 | 
|---|
 | 233 | check_for_tc()
 | 
|---|
 | 234 | {
 | 
|---|
 | 235 |         static int      count = 0;
 | 
|---|
 | 236 |         char            *savcapab = capab;
 | 
|---|
 | 237 |         char            buf[1024];
 | 
|---|
 | 238 |         char            terminalname[128];
 | 
|---|
 | 239 |         register char   *p = capab + strlen(capab) - 2, *q;
 | 
|---|
 | 240 | 
 | 
|---|
 | 241 |         while (*p != ':')
 | 
|---|
 | 242 |                 if (--p < capab)
 | 
|---|
 | 243 |                         return(0);      /* no : in termcap entry */
 | 
|---|
 | 244 |         if (p[1] != 't' || p[2] != 'c')
 | 
|---|
 | 245 |                 return(1);
 | 
|---|
 | 246 |         if (count > 16) {
 | 
|---|
 | 247 |                 return(0);      /* recursion in tc= definitions */
 | 
|---|
 | 248 |         }
 | 
|---|
 | 249 |         count++;
 | 
|---|
 | 250 |         strcpy(terminalname, &p[4]);
 | 
|---|
 | 251 |         q = terminalname;
 | 
|---|
 | 252 |         while (*q && *q != ':') q++;
 | 
|---|
 | 253 |         *q = 0;
 | 
|---|
 | 254 |         if (tgetent(buf, terminalname) != 1) {
 | 
|---|
 | 255 |                 --count;
 | 
|---|
 | 256 |                 return(0);
 | 
|---|
 | 257 |         }
 | 
|---|
 | 258 |         --count;
 | 
|---|
 | 259 |         for (q = buf; *q && *q != ':'; q++) { }
 | 
|---|
 | 260 |         strcpy(p, q);
 | 
|---|
 | 261 |         capab = savcapab;
 | 
|---|
 | 262 |         return(1);
 | 
|---|
 | 263 | }
 | 
|---|
 | 264 | 
 | 
|---|
 | 265 | /*
 | 
|---|
 | 266 |  *      tgetnum - get the numeric terminal capability corresponding
 | 
|---|
 | 267 |  *      to id. Returns the value, -1 if invalid.
 | 
|---|
 | 268 |  */
 | 
|---|
 | 269 | int
 | 
|---|
 | 270 | tgetnum(id)
 | 
|---|
 | 271 | char    *id;
 | 
|---|
 | 272 | {
 | 
|---|
 | 273 |         char    *cp;
 | 
|---|
 | 274 |         int     ret;
 | 
|---|
 | 275 | 
 | 
|---|
 | 276 |         if ((cp = capab) == NULL || id == NULL || *cp == 0)
 | 
|---|
 | 277 |                 return(-1);
 | 
|---|
 | 278 |         while (*++cp && *cp != ':')
 | 
|---|
 | 279 |                 ;
 | 
|---|
 | 280 |         while (*cp) {
 | 
|---|
 | 281 |                 cp++;
 | 
|---|
 | 282 |                 while (ISSPACE(*cp))
 | 
|---|
 | 283 |                         cp++;
 | 
|---|
 | 284 |                 if (strncmp(cp, id, CAPABLEN) == 0) {
 | 
|---|
 | 285 |                         while (*cp && *cp != ':' && *cp != '#')
 | 
|---|
 | 286 |                                 cp++;
 | 
|---|
 | 287 |                         if (*cp != '#')
 | 
|---|
 | 288 |                                 return(-1);
 | 
|---|
 | 289 |                         for (ret = 0, cp++ ; *cp && ISDIGIT(*cp) ; cp++)
 | 
|---|
 | 290 |                                 ret = ret * 10 + *cp - '0';
 | 
|---|
 | 291 |                         return(ret);
 | 
|---|
 | 292 |                 }
 | 
|---|
 | 293 |                 while (*cp && *cp != ':')
 | 
|---|
 | 294 |                         cp++;
 | 
|---|
 | 295 |         }
 | 
|---|
 | 296 |         return(-1);
 | 
|---|
 | 297 | }
 | 
|---|
 | 298 | 
 | 
|---|
 | 299 | /*
 | 
|---|
 | 300 |  *      tgetflag - get the boolean flag corresponding to id. Returns -1
 | 
|---|
 | 301 |  *      if invalid, 0 if the flag is not in termcap entry, or 1 if it is
 | 
|---|
 | 302 |  *      present.
 | 
|---|
 | 303 |  */
 | 
|---|
 | 304 | int
 | 
|---|
 | 305 | tgetflag(id)
 | 
|---|
 | 306 | char    *id;
 | 
|---|
 | 307 | {
 | 
|---|
 | 308 |         char    *cp;
 | 
|---|
 | 309 | 
 | 
|---|
 | 310 |         if ((cp = capab) == NULL || id == NULL || *cp == 0)
 | 
|---|
 | 311 |                 return(-1);
 | 
|---|
 | 312 |         while (*++cp && *cp != ':')
 | 
|---|
 | 313 |                 ;
 | 
|---|
 | 314 |         while (*cp) {
 | 
|---|
 | 315 |                 cp++;
 | 
|---|
 | 316 |                 while (ISSPACE(*cp))
 | 
|---|
 | 317 |                         cp++;
 | 
|---|
 | 318 |                 if (strncmp(cp, id, CAPABLEN) == 0)
 | 
|---|
 | 319 |                         return(1);
 | 
|---|
 | 320 |                 while (*cp && *cp != ':')
 | 
|---|
 | 321 |                         cp++;
 | 
|---|
 | 322 |         }
 | 
|---|
 | 323 |         return(0);
 | 
|---|
 | 324 | }
 | 
|---|
 | 325 | 
 | 
|---|
 | 326 | /*
 | 
|---|
 | 327 |  *      tgetstr - get the string capability corresponding to id and place
 | 
|---|
 | 328 |  *      it in area (advancing area at same time). Expand escape sequences
 | 
|---|
 | 329 |  *      etc. Returns the string, or NULL if it can't do it.
 | 
|---|
 | 330 |  */
 | 
|---|
 | 331 | char *
 | 
|---|
 | 332 | tgetstr(id, area)
 | 
|---|
 | 333 | char    *id;
 | 
|---|
 | 334 | char    **area;
 | 
|---|
 | 335 | {
 | 
|---|
 | 336 |         char    *cp;
 | 
|---|
 | 337 |         char    *ret;
 | 
|---|
 | 338 |         int     i;
 | 
|---|
 | 339 | 
 | 
|---|
 | 340 |         if ((cp = capab) == NULL || id == NULL || *cp == 0)
 | 
|---|
 | 341 |                 return(NULL);
 | 
|---|
 | 342 |         while (*++cp != ':')
 | 
|---|
 | 343 |                 ;
 | 
|---|
 | 344 |         while (*cp) {
 | 
|---|
 | 345 |                 cp++;
 | 
|---|
 | 346 |                 while (ISSPACE(*cp))
 | 
|---|
 | 347 |                         cp++;
 | 
|---|
 | 348 |                 if (strncmp(cp, id, CAPABLEN) == 0) {
 | 
|---|
 | 349 |                         while (*cp && *cp != ':' && *cp != '=')
 | 
|---|
 | 350 |                                 cp++;
 | 
|---|
 | 351 |                         if (*cp != '=')
 | 
|---|
 | 352 |                                 return(NULL);
 | 
|---|
 | 353 |                         for (ret = *area, cp++; *cp && *cp != ':' ; (*area)++, cp++)
 | 
|---|
 | 354 |                                 switch(*cp) {
 | 
|---|
 | 355 |                                 case '^' :
 | 
|---|
 | 356 |                                         **area = *++cp - 'A' + 1;
 | 
|---|
 | 357 |                                         break;
 | 
|---|
 | 358 |                                 case '\\' :
 | 
|---|
 | 359 |                                         switch(*++cp) {
 | 
|---|
 | 360 |                                         case 'E' :
 | 
|---|
 | 361 |                                                 **area = '\033';
 | 
|---|
 | 362 |                                                 break;
 | 
|---|
 | 363 |                                         case 'n' :
 | 
|---|
 | 364 |                                                 **area = '\n';
 | 
|---|
 | 365 |                                                 break;
 | 
|---|
 | 366 |                                         case 'r' :
 | 
|---|
 | 367 |                                                 **area = '\r';
 | 
|---|
 | 368 |                                                 break;
 | 
|---|
 | 369 |                                         case 't' :
 | 
|---|
 | 370 |                                                 **area = '\t';
 | 
|---|
 | 371 |                                                 break;
 | 
|---|
 | 372 |                                         case 'b' :
 | 
|---|
 | 373 |                                                 **area = '\b';
 | 
|---|
 | 374 |                                                 break;
 | 
|---|
 | 375 |                                         case 'f' :
 | 
|---|
 | 376 |                                                 **area = '\f';
 | 
|---|
 | 377 |                                                 break;
 | 
|---|
 | 378 |                                         case '0' :
 | 
|---|
 | 379 |                                         case '1' :
 | 
|---|
 | 380 |                                         case '2' :
 | 
|---|
 | 381 |                                         case '3' :
 | 
|---|
 | 382 |                                                 for (i=0 ; *cp && ISDIGIT(*cp) ; cp++)
 | 
|---|
 | 383 |                                                         i = i * 8 + *cp - '0';
 | 
|---|
 | 384 |                                                 **area = i;
 | 
|---|
 | 385 |                                                 cp--;
 | 
|---|
 | 386 |                                                 break;
 | 
|---|
 | 387 |                                         case '^' :
 | 
|---|
 | 388 |                                         case '\\' :
 | 
|---|
 | 389 |                                                 **area = *cp;
 | 
|---|
 | 390 |                                                 break;
 | 
|---|
 | 391 |                                         }
 | 
|---|
 | 392 |                                         break;
 | 
|---|
 | 393 |                                 default :
 | 
|---|
 | 394 |                                         **area = *cp;
 | 
|---|
 | 395 |                                 }
 | 
|---|
 | 396 |                         *(*area)++ = '\0';
 | 
|---|
 | 397 |                         return(ret);
 | 
|---|
 | 398 |                 }
 | 
|---|
 | 399 |                 while (*cp && *cp != ':')
 | 
|---|
 | 400 |                         cp++;
 | 
|---|
 | 401 |         }
 | 
|---|
 | 402 |         return(NULL);
 | 
|---|
 | 403 | }
 | 
|---|
 | 404 | 
 | 
|---|
 | 405 | /*
 | 
|---|
 | 406 |  *      tgoto - given the cursor motion string cm, make up the string
 | 
|---|
 | 407 |  *      for the cursor to go to (destcol, destline), and return the string.
 | 
|---|
 | 408 |  *      Returns "OOPS" if something's gone wrong, or the string otherwise.
 | 
|---|
 | 409 |  */
 | 
|---|
 | 410 | char *
 | 
|---|
 | 411 | tgoto(cm, destcol, destline)
 | 
|---|
 | 412 | char    *cm;
 | 
|---|
 | 413 | int     destcol;
 | 
|---|
 | 414 | int     destline;
 | 
|---|
 | 415 | {
 | 
|---|
 | 416 |         register char   *rp;
 | 
|---|
 | 417 |         static char     ret[32];
 | 
|---|
 | 418 |         char            added[16];
 | 
|---|
 | 419 |         int             *dp = &destline;
 | 
|---|
 | 420 |         int             numval;
 | 
|---|
 | 421 |         int             swapped = 0;
 | 
|---|
 | 422 | 
 | 
|---|
 | 423 |         added[0] = 0;
 | 
|---|
 | 424 |         for (rp = ret ; *cm ; cm++) {
 | 
|---|
 | 425 |                 if (*cm == '%') {
 | 
|---|
 | 426 |                         switch(*++cm) {
 | 
|---|
 | 427 |                         case '>' :
 | 
|---|
 | 428 |                                 if (dp == NULL)
 | 
|---|
 | 429 |                                         return("OOPS");
 | 
|---|
 | 430 |                                 cm++;
 | 
|---|
 | 431 |                                 if (*dp > *cm++) {
 | 
|---|
 | 432 |                                         *dp += *cm;
 | 
|---|
 | 433 |                                 }
 | 
|---|
 | 434 |                                 break;
 | 
|---|
 | 435 |                         case '+' :
 | 
|---|
 | 436 |                         case '.' :
 | 
|---|
 | 437 |                                 if (dp == NULL)
 | 
|---|
 | 438 |                                         return("OOPS");
 | 
|---|
 | 439 |                                 if (*cm == '+') *dp = *dp + *++cm;
 | 
|---|
 | 440 |                                 for (;;) {
 | 
|---|
 | 441 |                                     switch(*dp) {
 | 
|---|
 | 442 |                                     case 0:
 | 
|---|
 | 443 |                                     case 04:
 | 
|---|
 | 444 |                                     case '\t':
 | 
|---|
 | 445 |                                     case '\n':
 | 
|---|
 | 446 |                                         /* filter these out */
 | 
|---|
 | 447 |                                         if (dp == &destcol || swapped || UP) {
 | 
|---|
 | 448 |                                                 strcat(added, dp == &destcol || swapped ?
 | 
|---|
 | 449 |                                                         (BC ? BC : "\b") :
 | 
|---|
 | 450 |                                                         UP);
 | 
|---|
 | 451 |                                                 (*dp)++;
 | 
|---|
 | 452 |                                                 continue;
 | 
|---|
 | 453 |                                         }
 | 
|---|
 | 454 |                                     }
 | 
|---|
 | 455 |                                     break;
 | 
|---|
 | 456 |                                 }
 | 
|---|
 | 457 |                                 *rp++ = *dp;
 | 
|---|
 | 458 |                                 dp = (dp == &destline) ? &destcol : NULL;
 | 
|---|
 | 459 |                                 break;
 | 
|---|
 | 460 | 
 | 
|---|
 | 461 |                         case 'r' : {
 | 
|---|
 | 462 |                                 int tmp = destline;
 | 
|---|
 | 463 | 
 | 
|---|
 | 464 |                                 destline = destcol;
 | 
|---|
 | 465 |                                 destcol = tmp;
 | 
|---|
 | 466 |                                 swapped = 1 - swapped;
 | 
|---|
 | 467 |                                 break;
 | 
|---|
 | 468 |                         }
 | 
|---|
 | 469 |                         case 'n' :
 | 
|---|
 | 470 |                                 destcol ^= 0140;
 | 
|---|
 | 471 |                                 destline ^= 0140;
 | 
|---|
 | 472 |                                 break;
 | 
|---|
 | 473 | 
 | 
|---|
 | 474 |                         case '%' :
 | 
|---|
 | 475 |                                 *rp++ = '%';
 | 
|---|
 | 476 |                                 break;
 | 
|---|
 | 477 | 
 | 
|---|
 | 478 |                         case 'i' :
 | 
|---|
 | 479 |                                 destcol++;
 | 
|---|
 | 480 |                                 destline++;
 | 
|---|
 | 481 |                                 break;
 | 
|---|
 | 482 | 
 | 
|---|
 | 483 |                         case 'B' :
 | 
|---|
 | 484 |                                 if (dp == NULL)
 | 
|---|
 | 485 |                                         return("OOPS");
 | 
|---|
 | 486 |                                 *dp = 16 * (*dp / 10) + *dp % 10;
 | 
|---|
 | 487 |                                 break;
 | 
|---|
 | 488 | 
 | 
|---|
 | 489 |                         case 'D' :
 | 
|---|
 | 490 |                                 if (dp == NULL)
 | 
|---|
 | 491 |                                         return("OOPS");
 | 
|---|
 | 492 |                                 *dp = *dp - 2 * (*dp % 16);
 | 
|---|
 | 493 |                                 break;
 | 
|---|
 | 494 | 
 | 
|---|
 | 495 |                         case 'd' :
 | 
|---|
 | 496 |                         case '2' :
 | 
|---|
 | 497 |                         case '3' :
 | 
|---|
 | 498 |                                 if (dp == NULL)
 | 
|---|
 | 499 |                                         return("OOPS");
 | 
|---|
 | 500 |                                 numval = *dp;
 | 
|---|
 | 501 |                                 dp = (dp == &destline) ? &destcol : NULL;
 | 
|---|
 | 502 |                                 if (numval >= 100) {
 | 
|---|
 | 503 |                                         *rp++ = '0' + numval / 100;
 | 
|---|
 | 504 |                                 }
 | 
|---|
 | 505 |                                 else if (*cm == '3') {
 | 
|---|
 | 506 |                                         *rp++ = ' ';
 | 
|---|
 | 507 |                                 }
 | 
|---|
 | 508 |                                 if (numval >= 10) {
 | 
|---|
 | 509 |                                         *rp++ = '0' + ((numval%100)/10);
 | 
|---|
 | 510 |                                 }
 | 
|---|
 | 511 |                                 else if (*cm == '3' || *cm == '2') {
 | 
|---|
 | 512 |                                         *rp++ = ' ';
 | 
|---|
 | 513 |                                 }
 | 
|---|
 | 514 |                                 *rp++ = '0' + (numval%10);
 | 
|---|
 | 515 |                                 break;
 | 
|---|
 | 516 |                         default :
 | 
|---|
 | 517 |                                 return("OOPS");
 | 
|---|
 | 518 |                         }
 | 
|---|
 | 519 |                 }
 | 
|---|
 | 520 |                 else *rp++ = *cm;
 | 
|---|
 | 521 |         }
 | 
|---|
 | 522 |         *rp = '\0';
 | 
|---|
 | 523 |         strcpy(rp, added);
 | 
|---|
 | 524 |         return(ret);
 | 
|---|
 | 525 | }
 | 
|---|
 | 526 | 
 | 
|---|
 | 527 | static int tens_of_ms_p_char[] = {      /* index as returned by gtty */
 | 
|---|
 | 528 |                                         /* assume 10 bits per char */
 | 
|---|
 | 529 |         0, 2000, 1333, 909, 743, 666, 500, 333, 166, 83, 55, 41, 20, 10, 5, 2
 | 
|---|
 | 530 | };
 | 
|---|
 | 531 | /*
 | 
|---|
 | 532 |  *      tputs - put the string cp out onto the terminal, using the function
 | 
|---|
 | 533 |  *      outc. Also handle padding.
 | 
|---|
 | 534 |  */
 | 
|---|
 | 535 | int
 | 
|---|
 | 536 | tputs(cp, affcnt, outc)
 | 
|---|
 | 537 | register char   *cp;
 | 
|---|
 | 538 | int             affcnt;
 | 
|---|
 | 539 | int             (*outc)();
 | 
|---|
 | 540 | {
 | 
|---|
 | 541 |         int delay = 0;
 | 
|---|
 | 542 |         if (cp == NULL)
 | 
|---|
 | 543 |                 return(1);
 | 
|---|
 | 544 |         while (ISDIGIT(*cp)) {
 | 
|---|
 | 545 |                 delay = delay * 10 + (*cp++ - '0');
 | 
|---|
 | 546 |         }
 | 
|---|
 | 547 |         delay *= 10;
 | 
|---|
 | 548 |         if (*cp == '.') {
 | 
|---|
 | 549 |                 cp++;
 | 
|---|
 | 550 |                 if (ISDIGIT(*cp)) {
 | 
|---|
 | 551 |                         delay += *cp++ - '0';
 | 
|---|
 | 552 |                 }
 | 
|---|
 | 553 |                 while (ISDIGIT(*cp)) cp++;
 | 
|---|
 | 554 |         }
 | 
|---|
 | 555 |         if (*cp == '*') {
 | 
|---|
 | 556 |                 delay *= affcnt;
 | 
|---|
 | 557 |                 cp++;
 | 
|---|
 | 558 |         }
 | 
|---|
 | 559 |         while (*cp)
 | 
|---|
 | 560 |                 (*outc)(*cp++);
 | 
|---|
 | 561 |         if (delay != 0 &&
 | 
|---|
 | 562 |             ospeed > 0 &&
 | 
|---|
 | 563 |             ospeed < (sizeof tens_of_ms_p_char / sizeof tens_of_ms_p_char[0])) {
 | 
|---|
 | 564 |                 delay = (delay + tens_of_ms_p_char[ospeed] - 1) / 
 | 
|---|
 | 565 |                                   tens_of_ms_p_char[ospeed];
 | 
|---|
 | 566 |                 while (delay--) (*outc)(PC);
 | 
|---|
 | 567 |         }
 | 
|---|
 | 568 |         return(1);
 | 
|---|
 | 569 | }
 | 
|---|
 | 570 | 
 | 
|---|
 | 571 | /*
 | 
|---|
 | 572 |  *      That's all, folks...
 | 
|---|
 | 573 |  */
 | 
|---|