[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 | */
|
---|