[BACK]Return to ul.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / ul

Annotation of src/usr.bin/ul/ul.c, Revision 1.1

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