Annotation of 43BSDReno/usr.bin/ul/ul.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.