|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1980 Regents of the University of California. ! 3: * All rights reserved. The Berkeley software License Agreement ! 4: * specifies the terms and conditions for redistribution. ! 5: */ ! 6: ! 7: #ifndef lint ! 8: char copyright[] = ! 9: "@(#) Copyright (c) 1980 Regents of the University of California.\n\ ! 10: All rights reserved.\n"; ! 11: #endif not lint ! 12: ! 13: #ifndef lint ! 14: static char sccsid[] = "@(#)ul.c 5.1 (Berkeley) 5/31/85"; ! 15: #endif not lint ! 16: ! 17: #include <stdio.h> ! 18: ! 19: #define IESC '\033' ! 20: #define SO '\016' ! 21: #define SI '\017' ! 22: #define HFWD '9' ! 23: #define HREV '8' ! 24: #define FREV '7' ! 25: #define MAXBUF 512 ! 26: ! 27: #define NORMAL 000 ! 28: #define ALTSET 001 /* Reverse */ ! 29: #define SUPERSC 002 /* Dim */ ! 30: #define SUBSC 004 /* Dim | Ul */ ! 31: #define UNDERL 010 /* Ul */ ! 32: #define BOLD 020 /* Bold */ ! 33: ! 34: int must_use_uc, must_overstrike; ! 35: char *CURS_UP, *CURS_RIGHT, *CURS_LEFT, ! 36: *ENTER_STANDOUT, *EXIT_STANDOUT, *ENTER_UNDERLINE, *EXIT_UNDERLINE, ! 37: *ENTER_DIM, *ENTER_BOLD, *ENTER_REVERSE, *UNDER_CHAR, *EXIT_ATTRIBUTES; ! 38: ! 39: struct CHAR { ! 40: char c_mode; ! 41: char c_char; ! 42: } ; ! 43: ! 44: struct CHAR obuf[MAXBUF]; ! 45: int col, maxcol; ! 46: int mode; ! 47: int halfpos; ! 48: int upln; ! 49: int iflag; ! 50: ! 51: main(argc, argv) ! 52: int argc; ! 53: char **argv; ! 54: { ! 55: int c; ! 56: char *cp, *termtype; ! 57: FILE *f; ! 58: char termcap[1024]; ! 59: char *getenv(); ! 60: extern int optind; ! 61: extern char *optarg; ! 62: ! 63: termtype = getenv("TERM"); ! 64: if (termtype == NULL || (argv[0][0] == 'c' && !isatty(1))) ! 65: termtype = "lpr"; ! 66: while ((c=getopt(argc, argv, "it:T:")) != EOF) ! 67: switch(c) { ! 68: ! 69: case 't': ! 70: case 'T': /* for nroff compatibility */ ! 71: termtype = optarg; ! 72: break; ! 73: case 'i': ! 74: iflag = 1; ! 75: break; ! 76: ! 77: default: ! 78: fprintf(stderr, ! 79: "Usage: %s [ -i ] [ -tTerm ] file...\n", ! 80: argv[0]); ! 81: exit(1); ! 82: } ! 83: ! 84: switch(tgetent(termcap, termtype)) { ! 85: ! 86: case 1: ! 87: break; ! 88: ! 89: default: ! 90: fprintf(stderr,"trouble reading termcap"); ! 91: /* fall through to ... */ ! 92: ! 93: case 0: ! 94: /* No such terminal type - assume dumb */ ! 95: strcpy(termcap, "dumb:os:col#80:cr=^M:sf=^J:am:"); ! 96: break; ! 97: } ! 98: initcap(); ! 99: if ( (tgetflag("os") && ENTER_BOLD==NULL ) || ! 100: (tgetflag("ul") && ENTER_UNDERLINE==NULL && UNDER_CHAR==NULL)) ! 101: must_overstrike = 1; ! 102: initbuf(); ! 103: if (optind == argc) ! 104: filter(stdin); ! 105: else for (; optind<argc; optind++) { ! 106: f = fopen(argv[optind],"r"); ! 107: if (f == NULL) { ! 108: perror(argv[optind]); ! 109: exit(1); ! 110: } else ! 111: filter(f); ! 112: } ! 113: exit(0); ! 114: } ! 115: ! 116: filter(f) ! 117: FILE *f; ! 118: { ! 119: register c; ! 120: ! 121: while((c = getc(f)) != EOF) switch(c) { ! 122: ! 123: case '\b': ! 124: if (col > 0) ! 125: col--; ! 126: continue; ! 127: ! 128: case '\t': ! 129: col = (col+8) & ~07; ! 130: if (col > maxcol) ! 131: maxcol = col; ! 132: continue; ! 133: ! 134: case '\r': ! 135: col = 0; ! 136: continue; ! 137: ! 138: case SO: ! 139: mode |= ALTSET; ! 140: continue; ! 141: ! 142: case SI: ! 143: mode &= ~ALTSET; ! 144: continue; ! 145: ! 146: case IESC: ! 147: switch (c = getc(f)) { ! 148: ! 149: case HREV: ! 150: if (halfpos == 0) { ! 151: mode |= SUPERSC; ! 152: halfpos--; ! 153: } else if (halfpos > 0) { ! 154: mode &= ~SUBSC; ! 155: halfpos--; ! 156: } else { ! 157: halfpos = 0; ! 158: reverse(); ! 159: } ! 160: continue; ! 161: ! 162: case HFWD: ! 163: if (halfpos == 0) { ! 164: mode |= SUBSC; ! 165: halfpos++; ! 166: } else if (halfpos < 0) { ! 167: mode &= ~SUPERSC; ! 168: halfpos++; ! 169: } else { ! 170: halfpos = 0; ! 171: fwd(); ! 172: } ! 173: continue; ! 174: ! 175: case FREV: ! 176: reverse(); ! 177: continue; ! 178: ! 179: default: ! 180: fprintf(stderr, ! 181: "Unknown escape sequence in input: %o, %o\n", ! 182: IESC, c); ! 183: exit(1); ! 184: } ! 185: continue; ! 186: ! 187: case '_': ! 188: if (obuf[col].c_char) ! 189: obuf[col].c_mode |= UNDERL | mode; ! 190: else ! 191: obuf[col].c_char = '_'; ! 192: case ' ': ! 193: col++; ! 194: if (col > maxcol) ! 195: maxcol = col; ! 196: continue; ! 197: ! 198: case '\n': ! 199: flushln(); ! 200: continue; ! 201: ! 202: default: ! 203: if (c < ' ') /* non printing */ ! 204: continue; ! 205: if (obuf[col].c_char == '\0') { ! 206: obuf[col].c_char = c; ! 207: obuf[col].c_mode = mode; ! 208: } else if (obuf[col].c_char == '_') { ! 209: obuf[col].c_char = c; ! 210: obuf[col].c_mode |= UNDERL|mode; ! 211: } else if (obuf[col].c_char == c) ! 212: obuf[col].c_mode |= BOLD|mode; ! 213: else { ! 214: obuf[col].c_mode = c; ! 215: obuf[col].c_mode = mode; ! 216: } ! 217: col++; ! 218: if (col > maxcol) ! 219: maxcol = col; ! 220: continue; ! 221: } ! 222: if (maxcol) ! 223: flushln(); ! 224: } ! 225: ! 226: flushln() ! 227: { ! 228: register lastmode; ! 229: register i; ! 230: int hadmodes = 0; ! 231: ! 232: lastmode = NORMAL; ! 233: for (i=0; i<maxcol; i++) { ! 234: if (obuf[i].c_mode != lastmode) { ! 235: hadmodes++; ! 236: setmode(obuf[i].c_mode); ! 237: lastmode = obuf[i].c_mode; ! 238: } ! 239: if (obuf[i].c_char == '\0') { ! 240: if (upln) { ! 241: puts(CURS_RIGHT); ! 242: } else ! 243: outc(' '); ! 244: } else ! 245: outc(obuf[i].c_char); ! 246: } ! 247: if (lastmode != NORMAL) { ! 248: setmode(0); ! 249: } ! 250: if (must_overstrike && hadmodes) ! 251: overstrike(); ! 252: putchar('\n'); ! 253: if (iflag && hadmodes) ! 254: iattr(); ! 255: fflush(stdout); ! 256: if (upln) ! 257: upln--; ! 258: initbuf(); ! 259: } ! 260: ! 261: /* ! 262: * For terminals that can overstrike, overstrike underlines and bolds. ! 263: * We don't do anything with halfline ups and downs, or Greek. ! 264: */ ! 265: overstrike() ! 266: { ! 267: register int i; ! 268: char lbuf[256]; ! 269: register char *cp = lbuf; ! 270: int hadbold=0; ! 271: ! 272: /* Set up overstrike buffer */ ! 273: for (i=0; i<maxcol; i++) ! 274: switch (obuf[i].c_mode) { ! 275: case NORMAL: ! 276: default: ! 277: *cp++ = ' '; ! 278: break; ! 279: case UNDERL: ! 280: *cp++ = '_'; ! 281: break; ! 282: case BOLD: ! 283: *cp++ = obuf[i].c_char; ! 284: hadbold=1; ! 285: break; ! 286: } ! 287: putchar('\r'); ! 288: for (*cp=' '; *cp==' '; cp--) ! 289: *cp = 0; ! 290: for (cp=lbuf; *cp; cp++) ! 291: putchar(*cp); ! 292: if (hadbold) { ! 293: putchar('\r'); ! 294: for (cp=lbuf; *cp; cp++) ! 295: putchar(*cp=='_' ? ' ' : *cp); ! 296: putchar('\r'); ! 297: for (cp=lbuf; *cp; cp++) ! 298: putchar(*cp=='_' ? ' ' : *cp); ! 299: } ! 300: } ! 301: ! 302: iattr() ! 303: { ! 304: register int i; ! 305: char lbuf[256]; ! 306: register char *cp = lbuf; ! 307: ! 308: for (i=0; i<maxcol; i++) ! 309: switch (obuf[i].c_mode) { ! 310: case NORMAL: *cp++ = ' '; break; ! 311: case ALTSET: *cp++ = 'g'; break; ! 312: case SUPERSC: *cp++ = '^'; break; ! 313: case SUBSC: *cp++ = 'v'; break; ! 314: case UNDERL: *cp++ = '_'; break; ! 315: case BOLD: *cp++ = '!'; break; ! 316: default: *cp++ = 'X'; break; ! 317: } ! 318: for (*cp=' '; *cp==' '; cp--) ! 319: *cp = 0; ! 320: for (cp=lbuf; *cp; cp++) ! 321: putchar(*cp); ! 322: putchar('\n'); ! 323: } ! 324: ! 325: initbuf() ! 326: { ! 327: ! 328: bzero(obuf, sizeof (obuf)); /* depends on NORMAL == 0 */ ! 329: col = 0; ! 330: maxcol = 0; ! 331: mode &= ALTSET; ! 332: } ! 333: ! 334: fwd() ! 335: { ! 336: register oldcol, oldmax; ! 337: ! 338: oldcol = col; ! 339: oldmax = maxcol; ! 340: flushln(); ! 341: col = oldcol; ! 342: maxcol = oldmax; ! 343: } ! 344: ! 345: reverse() ! 346: { ! 347: upln++; ! 348: fwd(); ! 349: puts(CURS_UP); ! 350: puts(CURS_UP); ! 351: upln++; ! 352: } ! 353: ! 354: initcap() ! 355: { ! 356: static char tcapbuf[512]; ! 357: char *termtype; ! 358: char *bp = tcapbuf; ! 359: char *getenv(), *tgetstr(); ! 360: ! 361: /* This nonsense attempts to work with both old and new termcap */ ! 362: CURS_UP = tgetstr("up", &bp); ! 363: CURS_RIGHT = tgetstr("ri", &bp); ! 364: if (CURS_RIGHT == NULL) ! 365: CURS_RIGHT = tgetstr("nd", &bp); ! 366: CURS_LEFT = tgetstr("le", &bp); ! 367: if (CURS_LEFT == NULL) ! 368: CURS_LEFT = tgetstr("bc", &bp); ! 369: if (CURS_LEFT == NULL && tgetflag("bs")) ! 370: CURS_LEFT = "\b"; ! 371: ! 372: ENTER_STANDOUT = tgetstr("so", &bp); ! 373: EXIT_STANDOUT = tgetstr("se", &bp); ! 374: ENTER_UNDERLINE = tgetstr("us", &bp); ! 375: EXIT_UNDERLINE = tgetstr("ue", &bp); ! 376: ENTER_DIM = tgetstr("mh", &bp); ! 377: ENTER_BOLD = tgetstr("md", &bp); ! 378: ENTER_REVERSE = tgetstr("mr", &bp); ! 379: EXIT_ATTRIBUTES = tgetstr("me", &bp); ! 380: ! 381: if (!ENTER_BOLD && ENTER_REVERSE) ! 382: ENTER_BOLD = ENTER_REVERSE; ! 383: if (!ENTER_BOLD && ENTER_STANDOUT) ! 384: ENTER_BOLD = ENTER_STANDOUT; ! 385: if (!ENTER_UNDERLINE && ENTER_STANDOUT) { ! 386: ENTER_UNDERLINE = ENTER_STANDOUT; ! 387: EXIT_UNDERLINE = EXIT_STANDOUT; ! 388: } ! 389: if (!ENTER_DIM && ENTER_STANDOUT) ! 390: ENTER_DIM = ENTER_STANDOUT; ! 391: if (!ENTER_REVERSE && ENTER_STANDOUT) ! 392: ENTER_REVERSE = ENTER_STANDOUT; ! 393: if (!EXIT_ATTRIBUTES && EXIT_STANDOUT) ! 394: EXIT_ATTRIBUTES = EXIT_STANDOUT; ! 395: ! 396: /* ! 397: * Note that we use REVERSE for the alternate character set, ! 398: * not the as/ae capabilities. This is because we are modelling ! 399: * the model 37 teletype (since that's what nroff outputs) and ! 400: * the typical as/ae is more of a graphics set, not the greek ! 401: * letters the 37 has. ! 402: */ ! 403: ! 404: UNDER_CHAR = tgetstr("uc", &bp); ! 405: must_use_uc = (UNDER_CHAR && !ENTER_UNDERLINE); ! 406: } ! 407: ! 408: outchar(c) ! 409: char c; ! 410: { ! 411: putchar(c&0177); ! 412: } ! 413: ! 414: puts(str) ! 415: char *str; ! 416: { ! 417: if (str) ! 418: tputs(str, 1, outchar); ! 419: } ! 420: ! 421: static curmode = 0; ! 422: outc(c) ! 423: char c; ! 424: { ! 425: putchar(c); ! 426: if (must_use_uc && (curmode&UNDERL)) { ! 427: puts(CURS_LEFT); ! 428: puts(UNDER_CHAR); ! 429: } ! 430: } ! 431: ! 432: setmode(newmode) ! 433: int newmode; ! 434: { ! 435: if (!iflag) ! 436: { ! 437: if (curmode != NORMAL && newmode != NORMAL) ! 438: setmode(NORMAL); ! 439: switch (newmode) { ! 440: case NORMAL: ! 441: switch(curmode) { ! 442: case NORMAL: ! 443: break; ! 444: case UNDERL: ! 445: puts(EXIT_UNDERLINE); ! 446: break; ! 447: default: ! 448: /* This includes standout */ ! 449: puts(EXIT_ATTRIBUTES); ! 450: break; ! 451: } ! 452: break; ! 453: case ALTSET: ! 454: puts(ENTER_REVERSE); ! 455: break; ! 456: case SUPERSC: ! 457: /* ! 458: * This only works on a few terminals. ! 459: * It should be fixed. ! 460: */ ! 461: puts(ENTER_UNDERLINE); ! 462: puts(ENTER_DIM); ! 463: break; ! 464: case SUBSC: ! 465: puts(ENTER_DIM); ! 466: break; ! 467: case UNDERL: ! 468: puts(ENTER_UNDERLINE); ! 469: break; ! 470: case BOLD: ! 471: puts(ENTER_BOLD); ! 472: break; ! 473: default: ! 474: /* ! 475: * We should have some provision here for multiple modes ! 476: * on at once. This will have to come later. ! 477: */ ! 478: puts(ENTER_STANDOUT); ! 479: break; ! 480: } ! 481: } ! 482: curmode = newmode; ! 483: } ! 484: /* @(#)getopt.c 3.2 */ ! 485: #define ERR(s, c) if(opterr){\ ! 486: fputs(argv[0], stderr);\ ! 487: fputs(s, stderr);\ ! 488: fputc(c, stderr);\ ! 489: fputc('\n', stderr);} ! 490: ! 491: int opterr = 1; ! 492: int optind = 1; ! 493: char *optarg; ! 494: char *index(); ! 495: ! 496: int ! 497: getopt (argc, argv, opts) ! 498: char **argv, *opts; ! 499: { ! 500: static int sp = 1; ! 501: char c; ! 502: char *cp; ! 503: ! 504: if (sp == 1) ! 505: if (optind >= argc || ! 506: argv[optind][0] != '-' || argv[optind][1] == '\0') ! 507: return EOF; ! 508: else if (strcmp(argv[optind], "--") == NULL) { ! 509: optind++; ! 510: return EOF; ! 511: } ! 512: else if (strcmp(argv[optind], "-?") == NULL) { ! 513: optind++; ! 514: return '?'; ! 515: } ! 516: c = argv[optind][sp]; ! 517: if (c == ':' || (cp=index(opts, c)) == NULL) { ! 518: ERR (": illegal option -- ", c); ! 519: if (argv[optind][++sp] == '\0') { ! 520: optind++; ! 521: sp = 1; ! 522: } ! 523: return '?'; ! 524: } ! 525: if (*++cp == ':') { ! 526: if (argv[optind][2] != '\0') ! 527: optarg = &argv[optind++][sp+1]; ! 528: else if (++optind >= argc) { ! 529: ERR (": option requires an argument -- ", c); ! 530: sp = 1; ! 531: return '?'; ! 532: } else ! 533: optarg = argv[optind++]; ! 534: sp = 1; ! 535: } ! 536: else if (argv[optind][++sp] == '\0') { ! 537: sp = 1; ! 538: optind++; ! 539: } ! 540: return c; ! 541: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.