Annotation of 43BSDReno/old/vpr/vtools/fed/subr.c, revision 1.1

1.1     ! root        1: #ifndef lint
        !             2: static char sccsid[] = "@(#)subr.c     4.2 (Berkeley) 8/11/83";
        !             3: #endif
        !             4: 
        !             5: /*
        !             6:  * subr.c: general subroutines for fed.
        !             7:  */
        !             8: 
        !             9: #include "fed.h"
        !            10: 
        !            11: /*
        !            12:  * initialize: various one time initializations.
        !            13:  */
        !            14: initialize()
        !            15: {
        !            16:        register int i, j;
        !            17:        register char *cp;
        !            18: 
        !            19:        /* Initialize random variables */
        !            20:        curwind = -1;
        !            21:        pencolor = 1;
        !            22:        penweight = 0;
        !            23: 
        !            24:        /*
        !            25:         * Initialize value of sqrtmat.  This is a constant table
        !            26:         * so we don't have to redo all these square roots when the pen
        !            27:         * changes every time.
        !            28:         */
        !            29:        for (i=0; i<10; i++) {
        !            30:                for (j=0; j<10; j++) {
        !            31:                        sqrtmat[i][j] = sqrt((float) i*i + j*j);
        !            32:                }
        !            33:        }
        !            34: 
        !            35:        /* Initialize base locations on screen. These remain fixed. */
        !            36:        for (i=0; i<NROW; i++)
        !            37:                for (j=0; j<NCOL; j++) {
        !            38:                        base[NCOL*i+j].c = (GLCOL+GLPAD) * j + 1;
        !            39:                        base[NCOL*i+j].r = SCRHI - (GLROW+GLPAD+10) * i - GLROW - 3;
        !            40:                }
        !            41: 
        !            42:        setbuf(stdout, stoutbuf);
        !            43: 
        !            44:        curzoom = 1;    /* default is zoomed completely out */
        !            45:        ttyinit();
        !            46: }
        !            47: 
        !            48: /*
        !            49:  * showfont: Wipe clean the screen, display the font
        !            50:  * in a properly spaced fashion, wait for a char to be typed, if it's
        !            51:  * p print the font, then clear the screen and ungetc the char.
        !            52:  */
        !            53: showfont()
        !            54: {
        !            55:        register int i, cr, cc, nc;
        !            56:        int roff, coff;
        !            57:        char maxc, minc;
        !            58:        char nextcmd;
        !            59:        char tmpbuf[WINDSIZE];
        !            60: 
        !            61:        zoomout();
        !            62:        message("Show font from <char>");
        !            63:        minc = inchar();
        !            64:        sprintf(msgbuf, "Show font from %s to <char>", rdchar(minc));
        !            65:        message(msgbuf);
        !            66:        maxc = inchar();
        !            67: 
        !            68:        clearg();
        !            69:        zermat(tmpbuf, GLROW, GLCOL);
        !            70:        cr = SCRHI-GLROW; cc = 3;
        !            71:        for (i=minc; i<=maxc; i++) {
        !            72:                if (disptable[i].nbytes) {
        !            73:                        /*
        !            74:                         * We really should try to find out how far to the
        !            75:                         * left the glyph goes so we don't run off the left
        !            76:                         * end of the screen, but this is hard, so we fake it.
        !            77:                         * Usually glyphs don't run past the left so it's OK.
        !            78:                         */
        !            79:                        if (cc - disptable[i].left < 0)
        !            80:                                cc = disptable[i].left;
        !            81:                        nc = cc + disptable[i].width;
        !            82:                        if (nc >= SCRWID) {
        !            83:                                cc = 0;
        !            84:                                nc = disptable[i].width;
        !            85:                                cr -= 85; /* Should be GLROW but 4*100>360 */
        !            86:                                if (cr < 0)
        !            87:                                        break;  /* Screen full.  Just stop. */
        !            88:                        }
        !            89:                        dispmsg(rdchar(i), cc, cr, 2);
        !            90:                        placechar(i, cr+BASELINE, cc, tmpbuf);
        !            91:                        cc = nc;
        !            92:                }
        !            93:        }
        !            94:        for (;;) {
        !            95:                nextcmd = inchar();
        !            96:                if (nextcmd != 'p')
        !            97:                        break;
        !            98:                printg();
        !            99:        }
        !           100:        if (nextcmd != 'Q' && nextcmd != 'E' && nextcmd != 'N')
        !           101:                redraw();
        !           102:        else
        !           103:                clearg();
        !           104:        ungetc(nextcmd, stdin);
        !           105: }
        !           106: 
        !           107: /*
        !           108:  * typein: Like showfont but takes a line of text from the user
        !           109:  * and "typesets" it on the screen.
        !           110:  */
        !           111: typein()
        !           112: {
        !           113:        register int i, cr, cc, nc;
        !           114:        char *p;
        !           115:        int roff, coff;
        !           116:        char maxc, minc;
        !           117:        char nextcmd;
        !           118:        char tmpbuf[WINDSIZE];
        !           119:        char msgtype[100];
        !           120: 
        !           121:        zoomout();
        !           122:        readline("Input line to be typeset: ", msgtype, sizeof msgtype);
        !           123: 
        !           124:        clearg();
        !           125:        zermat(tmpbuf, GLROW, GLCOL);
        !           126:        cr = SCRHI-GLROW; cc = 3;
        !           127:        for (p=msgtype; *p; p++) {
        !           128:                i = *p;
        !           129:                if (disptable[i].nbytes) {
        !           130:                        if (cc - disptable[i].left < 0)
        !           131:                                cc = disptable[i].left;
        !           132:                        nc = cc + disptable[i].width;
        !           133:                        if (nc >= SCRWID) {
        !           134:                                cc = 0;
        !           135:                                nc = disptable[i].width;
        !           136:                                cr -= 85; /* Should be GLROW but 4*100>360 */
        !           137:                                if (cr < 0)
        !           138:                                        break;  /* Screen full.  Just stop. */
        !           139:                        }
        !           140:                        dispmsg(rdchar(i), cc, cr, 2);
        !           141:                        placechar(i, cr+BASELINE, cc, tmpbuf);
        !           142:                        cc = nc;
        !           143:                }
        !           144:        }
        !           145:        for (;;) {
        !           146:                nextcmd = inchar();
        !           147:                if (nextcmd != 'p')
        !           148:                        break;
        !           149:                printg();
        !           150:        }
        !           151:        if (nextcmd != 'Q' && nextcmd != 'E' && nextcmd != 'N')
        !           152:                redraw();
        !           153:        else
        !           154:                clearg();
        !           155:        ungetc(nextcmd, stdin);
        !           156: }
        !           157: 
        !           158: /*
        !           159:  * placechar: draw the character ch at position (llr, llc) on the screen.
        !           160:  * Position means the logical center of the character.  zero is a GLROW x GLCOL
        !           161:  * matrix of zeros which is needed for comparison, that is, we assume that
        !           162:  * the spot on the screen where this is going is blank, so the chars better
        !           163:  * not overlap.
        !           164:  */
        !           165: placechar(ch, llr, llc, zero)
        !           166: int ch;
        !           167: int llr, llc;
        !           168: bitmat zero;
        !           169: {
        !           170:        bitmat glbuf;
        !           171:        int roff, coff;
        !           172: 
        !           173:        glbuf = findbits(ch, GLROW, GLCOL, 0, 0, &roff, &coff);
        !           174:        if (glbuf == NULL)
        !           175:                return;
        !           176:        if (trace)
        !           177:                fprintf(trace, "placechar('%s'), roff=%d, coff=%d, llr=%d, llc=%d, down=%d, left=%d, r=%d, c=%d\n", rdchar(ch), roff, coff, llr, llc, disptable[ch].down, disptable[ch].left, llr-disptable[ch].down, llc-disptable[ch].left);
        !           178: 
        !           179:        update(zero, glbuf, GLROW, GLCOL, llr-GLROW+roff, llc-coff);
        !           180:        if (trace)
        !           181:                fprintf(trace, "placechar, free %x\n", glbuf);
        !           182:        free(glbuf);
        !           183: }
        !           184: 
        !           185: /*
        !           186:  * redraw: The screen has gotten screwed up somehow.
        !           187:  * Assume nothing but make it look right.
        !           188:  */
        !           189: redraw()
        !           190: {
        !           191:        register int i;
        !           192: 
        !           193:        zoomout();
        !           194:        clearg();
        !           195:        turnofrb();
        !           196:        for (i=0; i<NWIND; i++)
        !           197:                if (wind[i].onscreen != NULL) {
        !           198:                        zermat(wind[i].onscreen, GLROW, GLCOL);
        !           199:                        syncwind(i);
        !           200: 
        !           201:                        /* Print the char at the lower left of the window */
        !           202:                        sprintf(msgbuf, "%s", rdchar(wind[i].used));
        !           203:                        dispmsg(msgbuf, base[i].c, base[i].r-11, 2);
        !           204:                }
        !           205:        if (curwind >= 0)
        !           206:                drawbox(base[curwind].r-1, base[curwind].c-1, 1, GLROW+2, GLCOL+2);
        !           207: }
        !           208: 
        !           209: /*
        !           210:  * findbits: find the data bits of glyph c, wherever they are, and make
        !           211:  * nr x nc bitmat and put them in it, shifted by horoff and vertoff.
        !           212:  */
        !           213: bitmat
        !           214: findbits(c, nr, nc, horoff, vertoff, rcenter, ccenter)
        !           215: int c;
        !           216: int nr, nc;    /* the size of the dest */
        !           217: int horoff, vertoff;
        !           218: int *rcenter, *ccenter;
        !           219: {
        !           220:        register int i, j;
        !           221:        register int r1, r2, c1, c2;
        !           222:        bitmat retval, source;
        !           223:        int tr, tc;     /* the size of source */
        !           224:        char tmp[WINDSIZE];
        !           225: 
        !           226:        if (trace)
        !           227:                fprintf(trace, "findbits(c=%s, nr=%d, nc=%d, horoff=%d, vertoff=%d\n", rdchar(c), nr, nc, horoff, vertoff);
        !           228:        if (disptable[c].nbytes == 0)
        !           229:                return (NULL);
        !           230:        switch (cht[c].wherewind) {
        !           231:        case -2:
        !           232:                if (trace)
        !           233:                        fprintf(trace, "case -2, saved from prev place\n");
        !           234:                /* Saved from previous place */
        !           235:                source = cht[c].whereat;
        !           236: 
        !           237:                /* Ignore horoff/vertoff assuming they are already right */
        !           238:                *rcenter = cht[c].rcent;
        !           239:                *ccenter = cht[c].ccent;
        !           240:                /*
        !           241:                 * Small but important optimization: if the desired result is
        !           242:                 * a whole window and the source happens to be in a whole
        !           243:                 * window, just return the source pointer.  This saves
        !           244:                 * lots of memory copies and happens quite often.
        !           245:                 */
        !           246:                if (nr == GLROW && nc == GLCOL)
        !           247:                        return (source);
        !           248:                tr = GLROW; tc = GLCOL;
        !           249:                break;
        !           250:        case -1:
        !           251:                if (trace)
        !           252:                        fprintf(trace, "case -1: first time\n");
        !           253:                /* First time for this glyph: get it from font file */
        !           254:                fseek(fontdes, (long) fbase+disptable[c].addr, 0);
        !           255:                tr = cht[c].nrow; tc = cht[c].ncol;
        !           256:                if (tr > GLROW || tc > GLCOL || disptable[c].nbytes > WINDSIZE)
        !           257:                        error("glyph too large for window");
        !           258:                *rcenter = vertoff + disptable[c].up;
        !           259:                *ccenter = horoff  + disptable[c].left;
        !           260:                source = tmp;
        !           261:                fread(source, disptable[c].nbytes, 1, fontdes);
        !           262:                break;
        !           263:        default:
        !           264:                if (trace)
        !           265:                        fprintf(trace, "case default, in window %d", cht[c].wherewind);
        !           266:                source = wind[cht[c].wherewind].val;
        !           267:                tr = GLROW; tc = GLCOL;
        !           268:                *rcenter = vertoff + cht[c].rcent;
        !           269:                *ccenter = horoff  + cht[c].ccent;
        !           270:                break;
        !           271:        }
        !           272:        if (trace)
        !           273:                fprintf(trace, "curchar=%c=%d, tr=%d, tc=%d\n", curchar, curchar, tr, tc);
        !           274: 
        !           275:        dumpmat("before copy, source", source, tr, tc);
        !           276:        /* Copy in the bits into a bitmat of the right size */
        !           277:        retval = newmat(nr, nc);
        !           278:        r1 = max(0, -vertoff);
        !           279:        r2 = min(GLROW-vertoff-1, GLROW-1);
        !           280:        r2 = min(r2, tr-1);
        !           281:        c1 = max(0, -horoff);
        !           282:        c2 = min(GLCOL-horoff-1, GLCOL-1);
        !           283:        c2 = min(c2, tc-1);
        !           284:        if (trace)
        !           285:                fprintf(trace, "findbits copy: r1=%d, r2=%d, c1=%d, c2=%d, horoff=%d, vertoff=%d\n", r1, r2, c1, c2, horoff, vertoff);
        !           286:        for (i=r1; i<=r2; i++) {
        !           287:                for (j=c1; j<=c2; j++)
        !           288:                        setmat(retval, nr, nc, i+vertoff, j+horoff, mat(source, tr, tc, i, j, 6));
        !           289:        }
        !           290:        dumpmat("result of copy", retval, nr, nc);
        !           291:        return (retval);
        !           292: }
        !           293: 
        !           294: /*
        !           295:  * bufmod: called just before a buffer modifying command.
        !           296:  * Makes a backup copy of the glyph so we can undo later.
        !           297:  */
        !           298: bufmod()
        !           299: {
        !           300:        changes++;
        !           301:        if (curwind < 0)
        !           302:                return;
        !           303:        if (wind[curwind].undval == NULL)
        !           304:                wind[curwind].undval = newmat(GLROW, GLCOL);
        !           305:        bitcopy(wind[curwind].undval, wind[curwind].val, GLROW, GLCOL);
        !           306:        und_p_r = pen_r; und_p_c = pen_c;
        !           307:        und_c_r = curs_r; und_c_c = curs_c;
        !           308: }
        !           309: 
        !           310: /*
        !           311:  * undo: restore the backup copy.  We just swap pointers, which is
        !           312:  * the same as interchanging the two matrices.  This way, undo is
        !           313:  * its own inverse.
        !           314:  */
        !           315: undo()
        !           316: {
        !           317:        register bitmat tmp;
        !           318: 
        !           319:        if (wind[curwind].undval == NULL) {
        !           320:                error("Nothing to undo");
        !           321:        }
        !           322:        tmp = wind[curwind].val;
        !           323:        wind[curwind].val = wind[curwind].undval;
        !           324:        wind[curwind].undval = tmp;
        !           325:        pen_r = und_p_r; pen_c = und_p_c;
        !           326:        move(base[curwind].c+pen_c, base[curwind].r+GLROW-pen_r);
        !           327:        curs_r = und_c_r; curs_c = und_c_c;
        !           328:        syncwind(curwind);
        !           329:        changes++;
        !           330: }
        !           331: 
        !           332: /*
        !           333:  * drawline: draw a line of current flavor between the named two points.
        !           334:  * All points are relative to current window.
        !           335:  *
        !           336:  * The algorithm is that of a simple DDA.  This is similar to what the
        !           337:  * hardware of the HP 2648 does but the placing of the points will be
        !           338:  * different (because of thick pens and erasers).
        !           339:  */
        !           340: drawline(from_r, from_c, to_r, to_c)
        !           341: {
        !           342:        int length, i;
        !           343:        float x, y, xinc, yinc;
        !           344: 
        !           345:        if (trace)
        !           346:                fprintf(trace, "drawline from (%d, %d) to (%d, %d)\n", from_r, from_c, to_r, to_c);
        !           347:        length = max(abs(to_r-from_r), abs(to_c-from_c));
        !           348:        if (length <= 0) {
        !           349:                /*
        !           350:                 * The actual value doesn't matter, we're just avoiding
        !           351:                 * division by zero here.
        !           352:                 */
        !           353:                xinc = yinc = 1.0;
        !           354:        } else {
        !           355:                xinc = ((float) (to_r-from_r))/length;
        !           356:                yinc = ((float) (to_c-from_c))/length;
        !           357:        }
        !           358:        drawpoint(from_r, from_c);
        !           359:        x = from_r + 0.5; y = from_c + 0.5;
        !           360: 
        !           361:        for (i=0; i<length; i++) {
        !           362:                x += xinc; y += yinc;
        !           363:                drawpoint((int) x, (int) y);
        !           364:        }
        !           365: }
        !           366: 
        !           367: /*
        !           368:  * drawpoint: make a point of the current flavor at (r, c).
        !           369:  */
        !           370: drawpoint(r, c)
        !           371: register int r, c;
        !           372: {
        !           373:        register int i, j;
        !           374: 
        !           375:        if (penweight == 0)
        !           376:                setmat(wind[curwind].val, GLROW, GLCOL, r, c, pencolor);
        !           377:        else {
        !           378:                for (i=0; i<10; i++)
        !           379:                        for (j=0; j<10; j++)
        !           380:                                if (penmat[i][j])
        !           381:                                        setmat(wind[curwind].val, GLROW, GLCOL, r+i-4, c+j-4, pencolor);
        !           382:        }
        !           383: }
        !           384: 
        !           385: /*
        !           386:  * setcmd: handle the s command.  Format: s <what> <where>.
        !           387:  */
        !           388: setcmd()
        !           389: {
        !           390:        char what, where;
        !           391: 
        !           392:        message("set <what>");
        !           393:        what = inchar();
        !           394:        switch (what) {
        !           395: 
        !           396:        case 'p':       /* set pen */
        !           397:                message("set pen <weight>");
        !           398:                where = inchar();
        !           399:                switch (where) {
        !           400:                case 'f':       /* set pen fine */
        !           401:                case 'l':       /* set pen light */
        !           402:                        message("set pen fine");
        !           403:                        penweight = 0;
        !           404:                        break;
        !           405:                case 'h':       /* set pen heavy */
        !           406:                case 'b':       /* set pen bold */
        !           407:                        message("set pen heavy");
        !           408:                        penweight = 1;
        !           409:                        break;
        !           410:                default:
        !           411:                        error("Illegal kind of pen weight");
        !           412:                }
        !           413:                break;
        !           414:        
        !           415:        case 's':       /* set size of heavy pen */
        !           416:                message("set pen size to <size>");
        !           417:                where = inchar() - '0';
        !           418:                sprintf(msgbuf, "set pen size to %d", where);
        !           419:                message(msgbuf);
        !           420:                if (where > 0 && where < 10) {
        !           421:                        setpen(where);
        !           422:                } else
        !           423:                        error("Illegal size");
        !           424:                break;
        !           425:        
        !           426:        case 'd':
        !           427:                message("set draw");
        !           428:                pencolor = 1;
        !           429:                break;
        !           430: 
        !           431:        case 'e':
        !           432:                message("set erase");
        !           433:                pencolor = 0;
        !           434:                break;
        !           435: 
        !           436:        default:
        !           437:                error("Illegal set");
        !           438:        }
        !           439: }
        !           440: 
        !           441: /*
        !           442:  * setpen: set the heavy pen size to s.
        !           443:  * Main work here is defining template of pen.
        !           444:  */
        !           445: setpen(s)
        !           446: int s;
        !           447: {
        !           448:        register int i, j;
        !           449:        register float radius;
        !           450: 
        !           451:        if (s < 1)
        !           452:                s = 1;
        !           453:        hpensize = s;
        !           454:        radius = hpensize;
        !           455:        radius /= 2;
        !           456:        for (i=0; i<10; i++) {
        !           457:                for (j=0; j<10; j++) {
        !           458:                        penmat[i][j] = (radius >= sqrtmat[abs(i-4)][abs(j-4)]);
        !           459:                }
        !           460:        }
        !           461: 
        !           462:        /*
        !           463:         * Kludge to make a 2-wide pen possible by specifying 1.
        !           464:         */
        !           465:        if (hpensize == 1)
        !           466:                penmat[4][5] = 1;
        !           467: 
        !           468:        if (trace)
        !           469:                for (i=0; i<10; i++) {
        !           470:                        for (j=0; j<10; j++) {
        !           471:                                fprintf(trace, "%c", penmat[i][j] ? 'P' : '.');
        !           472:                        }
        !           473:                        fprintf(trace, "\n");
        !           474:                }
        !           475: }
        !           476: 
        !           477: /*
        !           478:  * error: print the given error message and return for another command.
        !           479:  */
        !           480: error(msg)
        !           481: char *msg;
        !           482: {
        !           483:        message(msg);
        !           484:        longjmp(env);
        !           485: }
        !           486: 
        !           487: /*
        !           488:  * copymove: do a move or copy command.
        !           489:  * cmd is C or M, the command.
        !           490:  */
        !           491: copymove(cmd)
        !           492: char cmd;
        !           493: {
        !           494:        char *action;
        !           495:        char src, dest;
        !           496:        bitmat cpy;
        !           497:        char lochr[5];
        !           498: 
        !           499:        if (cmd == 'C')
        !           500:                action = "copy";
        !           501:        else
        !           502:                action = "move";
        !           503:        sprintf(msgbuf, "%s <from>", action);
        !           504:        message(msgbuf);
        !           505:        src = inchar();
        !           506:        sprintf(msgbuf, "%s %s to <to>", action, rdchar(src));
        !           507:        message(msgbuf);
        !           508:        dest = inchar();
        !           509:        strcpy(lochr, rdchar(src));
        !           510:        sprintf(msgbuf, "%s %s to %s", action, lochr, rdchar(dest));
        !           511:        message(msgbuf);
        !           512: 
        !           513:        /* Do the copy */
        !           514:        disptable[dest] = disptable[src];
        !           515:        cht[dest] = cht[src];
        !           516:        if (cht[dest].wherewind >= 0)
        !           517:                wind[cht[dest].wherewind].used = dest;
        !           518: 
        !           519:        if (cmd == 'C') {
        !           520:                if (cht[dest].wherewind != -1) {
        !           521:                        /*
        !           522:                         * Make copies of the window so changing
        !           523:                         * one won't change the other.
        !           524:                         * The old copy gets the window on the screen, if any,
        !           525:                         * relegating the new copy to the background.
        !           526:                         */
        !           527:                        cpy = newmat(GLROW, GLCOL);
        !           528:                        if (cht[dest].wherewind >= 0)
        !           529:                                bitcopy(cpy, wind[cht[src].wherewind].val, GLROW, GLCOL);
        !           530:                        else
        !           531:                                bitcopy(cpy, cht[src].whereat, GLROW, GLCOL);
        !           532:                        if (cht[dest].wherewind == curwind)
        !           533:                                curwind = -1;
        !           534:                        cht[dest].wherewind = -2;
        !           535:                        cht[dest].whereat = cpy;
        !           536:                }
        !           537:        } else {
        !           538:                /*
        !           539:                 * Move. Delete the old entries.
        !           540:                 */
        !           541:                disptable[src].addr = disptable[src].nbytes = 0;
        !           542:                cht[src].wherewind = -1;
        !           543:        }
        !           544:        changes++;
        !           545: }
        !           546: 
        !           547: /*
        !           548:  * cch: make sure there is a current character.
        !           549:  */
        !           550: cch()
        !           551: {
        !           552:        if (curwind < 0)
        !           553:                error("No current glyph");
        !           554: }
        !           555: 
        !           556: /*
        !           557:  * confirm: if there have been changes, ask user if he is sure.
        !           558:  */
        !           559: confirm()
        !           560: {
        !           561:        char ch;
        !           562: 
        !           563:        if (changes == 0)
        !           564:                return;
        !           565:        message("Changes since last write -- Are you sure?");
        !           566:        ch = inchar();
        !           567:        if (isupper(ch))
        !           568:                ch = tolower(ch);
        !           569:        switch (ch) {
        !           570:        case 'y':
        !           571:        case 'q':
        !           572:        case 'e':
        !           573:                return;
        !           574:        case 'n':
        !           575:        default:
        !           576:                error("Not sure - aborted");
        !           577:        }
        !           578: }
        !           579: 
        !           580: /*
        !           581:  * delchar: the D command.  Delete a character from the buffer.
        !           582:  */
        !           583: delchar()
        !           584: {
        !           585:        register char c, c1, c2;
        !           586:        register int w;
        !           587:        char buf[5];
        !           588: 
        !           589:        message("delete <char>");
        !           590:        c1 = inchar();
        !           591:        sprintf(msgbuf, "delete %s through <char>", rdchar(c1));
        !           592:        message(msgbuf);
        !           593:        c2 = inchar();
        !           594:        strcpy(buf, rdchar(c1));
        !           595:        sprintf(msgbuf, "delete %s through %s", buf, rdchar(c2));
        !           596:        message(msgbuf);
        !           597:        changes++;
        !           598: 
        !           599:        for (c=c1; c<=c2; c++) {
        !           600:                if ((w = cht[c].wherewind) >= 0) {
        !           601:                        zermat(wind[w].val, GLROW, GLCOL);
        !           602:                        syncwind(w);
        !           603:                }
        !           604:                cht[c].wherewind = -1;
        !           605:                disptable[c].addr = 0;
        !           606:                disptable[c].nbytes = 0;
        !           607:                disptable[c].up = 0;
        !           608:                disptable[c].down = 0;
        !           609:                disptable[c].left = 0;
        !           610:                disptable[c].right = 0;
        !           611:                disptable[c].width = 0;
        !           612:        }
        !           613: }
        !           614: 
        !           615: /*
        !           616:  * zoom out to full screen so the screen doean't go nuts when we
        !           617:  * print off the current zoom window.  Save old value of zoom in
        !           618:  * oldzoom so space can put us back.
        !           619:  */
        !           620: zoomout()
        !           621: {
        !           622:        if (curzoom != 1)
        !           623:                zoomn(curzoom = 1);
        !           624: }
        !           625: 
        !           626: /*
        !           627:  * newglyph: the n command.
        !           628:  */
        !           629: newglyph()
        !           630: {
        !           631:        register int i, j;
        !           632:        int windno;
        !           633:        int vertoff, horoff;
        !           634:        char *tmp;
        !           635: 
        !           636:        message("new glyph <char>");
        !           637:        curchar = inchar();
        !           638:        sprintf(msgbuf, "new glyph %s", rdchar(curchar));
        !           639:        message(msgbuf);
        !           640: 
        !           641:        if (trace)
        !           642:                fprintf(trace, "\n\nnewglyph(%s)\n", rdchar(curchar));
        !           643:        if (disptable[curchar].nbytes != 0) {
        !           644:                if (trace)
        !           645:                        fprintf(trace, "char exists: %s\n", rdchar(curchar));
        !           646:                sprintf(msgbuf, "char exists: %s", rdchar(curchar));
        !           647:                error(msgbuf);
        !           648:        }
        !           649: 
        !           650:        turnofcurs();
        !           651:        /*
        !           652:         * Not on screen.  First find a suitable window,
        !           653:         * using round robin.
        !           654:         */
        !           655:        windno = nextwind;
        !           656:        if (trace)
        !           657:                fprintf(trace, "chose window %d\n", windno);
        !           658:        if (++nextwind >= NWIND)
        !           659:                nextwind = 0;
        !           660: #ifdef notdef
        !           661:        if (nextwind >= 3)
        !           662:                nextwind = 0;
        !           663: #endif
        !           664:        wind[windno].used = curchar;
        !           665: 
        !           666:        /* Put a box around the current window */
        !           667:        if (windno != curwind) {
        !           668:                drawbox(base[curwind].r-1, base[curwind].c-1, 0, GLROW+2, GLCOL+2);
        !           669:                drawbox(base[windno].r-1, base[windno].c-1, 1, GLROW+2, GLCOL+2);
        !           670:        }
        !           671: 
        !           672:        /* Print the char at the lower left of the window */
        !           673:        sprintf(msgbuf, "%s", rdchar(curchar));
        !           674:        dispmsg(msgbuf, base[windno].c, base[windno].r-11, 2);
        !           675:        
        !           676:        /* Now make room in the window */
        !           677:        if (wind[windno].onscreen == NULL) {
        !           678:                /* Brand new window, have to allocate space */
        !           679:                wind[windno].onscreen = newmat(GLROW, GLCOL);
        !           680:        } else {
        !           681:                /* Save prev glyph for later */
        !           682:                cht[wind[curchar].used].whereat = wind[windno].val;
        !           683:                cht[wind[curchar].used].wherewind = -2;
        !           684:        }
        !           685:        if (wind[windno].undval != NULL) {
        !           686:                if (trace)
        !           687:                        fprintf(trace, "newglyph frees undo: %x\n", wind[windno].undval);
        !           688:                free(wind[windno].undval);
        !           689:        }
        !           690:        wind[windno].undval = NULL;
        !           691: 
        !           692:        /*
        !           693:         * Vertical & horizontal offsets.  Line up the baseline
        !           694:         * of the char at BASELINE from bottom, but center
        !           695:         * horizontally.
        !           696:         */
        !           697:        wind[windno].val = newmat(GLROW, GLCOL);
        !           698: 
        !           699:        curwind = windno;
        !           700:        cht[curchar].wherewind = windno;
        !           701:        cht[curchar].rcent = curs_r = GLROW - BASELINE;
        !           702:        cht[curchar].ccent = curs_c = GLCOL / 2;
        !           703: 
        !           704: #ifdef notdef
        !           705:        dumpmat("wind[windno].onscreen", wind[windno].onscreen, GLROW, GLCOL);
        !           706: #endif
        !           707:        syncwind(windno);
        !           708: 
        !           709:        /*
        !           710:         * Mung the zoom out to 1 and back.  This is needed to
        !           711:         * re-center the glyph on the screen if zoomed in, otherwise
        !           712:         * if you move by one window it puts the cursor way over at
        !           713:         * the right with only half the window visible.
        !           714:         */
        !           715:        if ((i = curzoom) > 1) {
        !           716:                zoomn(1);
        !           717:                zoomn(i);
        !           718:        }
        !           719: }
        !           720: 
        !           721: /*
        !           722:  * numedit: change one of the numerical parameters.
        !           723:  */
        !           724: numedit()
        !           725: {
        !           726:        short * sp = 0;
        !           727:        char * cp = 0;
        !           728:        char c, f;
        !           729:        char *fld;
        !           730:        short ovalue, nvalue;
        !           731:        char numb[20];
        !           732: 
        !           733:        message("number of <char>");
        !           734:        c = inchar();
        !           735:        sprintf(msgbuf, "number of %s <field>", rdchar(c));
        !           736:        message(msgbuf);
        !           737:        f = inchar();
        !           738: 
        !           739:        switch (f) {
        !           740:        case 'a': sp = (short *)
        !           741:                        &disptable[c].addr;     fld = "addr";   break;
        !           742:        case 'n': sp = &disptable[c].nbytes;    fld = "nbytes"; break;
        !           743:        case 'u': cp = &disptable[c].up;        fld = "up";     break;
        !           744:        case 'd': cp = &disptable[c].down;      fld = "down";   break;
        !           745:        case 'l': cp = &disptable[c].left;      fld = "left";   break;
        !           746:        case 'r': cp = &disptable[c].right;     fld = "right";  break;
        !           747:        case 'w': sp = &disptable[c].width;     fld = "width";  break;
        !           748:        case 's': sp = (short *) &disptable[c].nbytes;
        !           749:                                                fld = "size";   break;
        !           750:        default: error("No such field");
        !           751:        }
        !           752: 
        !           753:        ovalue = sp ? *sp : *cp;
        !           754:        sprintf(msgbuf, "number of %s %s (old value %d) is ", rdchar(c), fld, ovalue);
        !           755:        readline(msgbuf, numb, sizeof numb);
        !           756:        nvalue = atoi(numb);
        !           757:        if (cp)
        !           758:                *cp = nvalue;
        !           759:        else
        !           760:                *sp = nvalue;
        !           761:        changes++;
        !           762: }
        !           763: 
        !           764: /*
        !           765:  * These routines turn the cursor and rubber band line on and off,
        !           766:  * remembering its state for the o and r commands.
        !           767:  */
        !           768: turnoncurs()
        !           769: {
        !           770:        curon();
        !           771:        curcurs = 1;
        !           772: }
        !           773: 
        !           774: turnofcurs()
        !           775: {
        !           776:        curoff();
        !           777:        curcurs = 0;
        !           778: }
        !           779: 
        !           780: turnonrb()
        !           781: {
        !           782:        rbon();
        !           783:        currb = 1;
        !           784: }
        !           785: 
        !           786: turnofrb()
        !           787: {
        !           788:        rboff();
        !           789:        currb = 0;
        !           790: }
        !           791: 
        !           792: synccurs()
        !           793: {
        !           794:        register int x, y;
        !           795: 
        !           796:        x = base[curwind].c + curs_c;
        !           797:        y = base[curwind].r + GLROW - curs_r - 1;
        !           798:        movecurs(x, y);
        !           799: }
        !           800: 
        !           801: inchar()
        !           802: {
        !           803:        sync();
        !           804:        synccurs();
        !           805:        return (rawchar());
        !           806: }
        !           807: 
        !           808: /*
        !           809:  * fillin - fill in with 1's all the spots that are in the enclosed
        !           810:  * area that (x, y) is in.
        !           811:  */
        !           812: fillin(x, y)
        !           813: int x, y;
        !           814: {
        !           815:        if (x<0 || x>=GLROW || y<0 || y>=GLCOL ||
        !           816:                mat(wind[curwind].val, GLROW, GLCOL, x, y))
        !           817:                return;
        !           818: 
        !           819:        setmat(wind[curwind].val, GLROW, GLCOL, x, y, 1);
        !           820:        fillin(x-1, y);
        !           821:        fillin(x+1, y);
        !           822:        fillin(x, y-1);
        !           823:        fillin(x, y+1);
        !           824: }
        !           825: 
        !           826: /*
        !           827:  * syncwind: make sure that window #n shows on the screen what it's
        !           828:  * supposed to after an arbitrary change.
        !           829:  */
        !           830: syncwind(n)
        !           831: int n;
        !           832: {
        !           833:        if (trace)
        !           834:                fprintf(trace, "syncwind(%d)\n", n);
        !           835:        update(wind[n].onscreen, wind[n].val, GLROW, GLCOL, base[n].r, base[n].c);
        !           836:        bitcopy(wind[n].onscreen, wind[n].val, GLROW, GLCOL);
        !           837: }
        !           838: 
        !           839: /*
        !           840:  * Embolden artificially emboldens the glyphs in the font by smearing
        !           841:  * them to the right by the current heavy pen size.  Or else italicize it.
        !           842:  */
        !           843: artificial()
        !           844: {
        !           845:        int low, high, cur;
        !           846:        int oldps, newps;
        !           847:        char lowch[10];
        !           848: #define ITAL   0
        !           849: #define BOLD   1
        !           850: #define RESIZE 2
        !           851: #define SMOOTH 3
        !           852:        int kind;
        !           853:        char *strbold;
        !           854: 
        !           855:        sprintf(msgbuf, "Artificially <embolden/italicize/resize/smooth>");
        !           856:        message(msgbuf);
        !           857: 
        !           858:        cur = inchar();
        !           859:        switch(cur) {
        !           860:        case 'i': case 'I': kind = ITAL; strbold = "italicize"; break;
        !           861:        case 'e': case 'E': kind = BOLD; strbold = "embolden"; break;
        !           862:        case 'r': case 'R': kind = RESIZE; strbold = "resize"; break;
        !           863:        case 's': case 'S': kind = SMOOTH; strbold = "smooth"; break;
        !           864:        default: error("No such artificial operation");
        !           865:        }
        !           866: 
        !           867:        sprintf(msgbuf, "Artificially %s glyphs from <char>", strbold);
        !           868:        message(msgbuf);
        !           869:        low = inchar();
        !           870:        strcpy(lowch, rdchar(low));
        !           871:        sprintf(msgbuf, "Artificially %s glyphs from %s to <char>", strbold, lowch);
        !           872:        message(msgbuf);
        !           873:        high = inchar();
        !           874:        if (kind == RESIZE) {
        !           875:                sprintf(msgbuf, "Artificially %s glyphs from %s to %s from <point size>", strbold, lowch, rdchar(high));
        !           876:                oldps = readnum(msgbuf);
        !           877:                sprintf(msgbuf, "Artificially %s glyphs from %s to %s from %dP to <point size>P", strbold, lowch, rdchar(high), oldps);
        !           878:                newps = readnum(msgbuf);
        !           879:                sprintf(msgbuf, "Artificially %s glyphs from %s to %s from %dP to %dP", strbold, lowch, rdchar(high), oldps, newps);
        !           880:                message(msgbuf);
        !           881:                if (oldps <= 0 || oldps > 36 || newps <= 0 || newps > 36 || oldps == newps)
        !           882:                        error("Bad point sizes");
        !           883:        } else {
        !           884:                sprintf(msgbuf, "Artificially %s glyphs from %s to %s", strbold, lowch, rdchar(high));
        !           885:                message(msgbuf);
        !           886:        }
        !           887: 
        !           888:        for (cur=low; cur<=high; cur++) {
        !           889:                getglyph(cur);
        !           890:                if (curchar == cur) {   /* e.g. if the getglyph succeeded */
        !           891:                        fflush(stdout);
        !           892:                        switch (kind) {
        !           893:                        case BOLD:
        !           894:                                boldglyph();
        !           895:                                break;
        !           896:                        case ITAL:
        !           897:                                italglyph();
        !           898:                                break;
        !           899:                        case RESIZE:
        !           900:                                if (oldps > newps)
        !           901:                                        shrinkglyph(oldps, newps);
        !           902:                                else
        !           903:                                        blowupglyph(oldps, newps);
        !           904:                                break;
        !           905:                        case SMOOTH:
        !           906:                                smoothglyph();
        !           907:                                break;
        !           908:                        }
        !           909:                        syncwind(curwind);
        !           910:                }
        !           911:        }
        !           912:        message("Done");
        !           913: }
        !           914: 
        !           915: /*
        !           916:  * Artificially embolden the current glyph.
        !           917:  */
        !           918: boldglyph()
        !           919: {
        !           920:        register int r, c, i;
        !           921:        int smear = hpensize < 2 ? 2 : hpensize;
        !           922: 
        !           923:        for (r=0; r<GLROW; r++)
        !           924:                for (c=GLCOL-1; c>=smear; c--)
        !           925:                        for (i=1; i<=smear; i++)
        !           926:                                if (mat(wind[curwind].val, GLROW, GLCOL, r, c-i))
        !           927:                                        setmat(wind[curwind].val, GLROW, GLCOL, r, c, 1);
        !           928: }
        !           929: 
        !           930: /*
        !           931:  * Artificially italicize the current glyph.
        !           932:  */
        !           933: italglyph()
        !           934: {
        !           935:        register int r, c, i, off;
        !           936:        int baser = cht[curchar].rcent; /* GLROW - BASELINE; */
        !           937: 
        !           938:        for (r=0; r<baser; r++) {
        !           939:                off = (baser-r) / SLOPE + 0.5;
        !           940:                for (c=GLCOL-1; c>=off; c--) {
        !           941:                        setmat(wind[curwind].val, GLROW, GLCOL, r, c,
        !           942:                                mat(wind[curwind].val, GLROW, GLCOL, r, c-off));
        !           943:                }
        !           944:                for (c=off-1; c>=0; c--)
        !           945:                        setmat(wind[curwind].val, GLROW, GLCOL, r, c, 0);
        !           946:        }
        !           947:        for (r=baser; r<GLROW; r++) {
        !           948:                off = (r-baser) * (2.0/7.0) + 0.5;
        !           949:                for (c=off; c<GLCOL; c++)
        !           950:                        setmat(wind[curwind].val, GLROW, GLCOL, r, c-off,
        !           951:                                mat(wind[curwind].val, GLROW, GLCOL, r, c));
        !           952:                for (c=off-1; c>=0; c--)
        !           953:                        setmat(wind[curwind].val, GLROW, GLCOL, r, c, 0);
        !           954:        }
        !           955: }
        !           956: 
        !           957: /*
        !           958:  * Blow up or shrink a glyph from oldps points to newps points.
        !           959:  * The basic idea is that for each on point in the old glyph we
        !           960:  * find the corresponding point in the new glyph and copy the value.
        !           961:  */
        !           962: shrinkglyph(oldps, newps)
        !           963: int oldps, newps;
        !           964: {
        !           965:        float ratio;
        !           966:        register int or, oc, nr, nc;
        !           967:        int n;
        !           968:        bitmat tmp, curw;
        !           969:        int baser = cht[curchar].rcent;
        !           970:        int basec = cht[curchar].ccent;
        !           971: 
        !           972:        ratio = (float) newps / (float) oldps;
        !           973:        tmp = newmat(GLROW, GLCOL);
        !           974:        curw = wind[curwind].val;
        !           975:        bitcopy(tmp, curw, GLROW, GLCOL);
        !           976:        zermat(curw, GLROW, GLCOL);
        !           977:        for (or=0; or<GLROW; or++) {
        !           978:                nr = baser + (or-baser)*ratio + 0.5;
        !           979:                for (oc=0; oc<GLCOL; oc++) {
        !           980:                        nc = basec + (oc-basec)*ratio + 0.5;
        !           981:                        if (nr < 0 || nr >= GLROW || nc < 0 || nc >= GLCOL)
        !           982:                                n = 0;
        !           983:                        else
        !           984:                                n = mat(tmp, GLROW, GLCOL, or, oc);
        !           985:                        if (n)
        !           986:                                setmat(curw, GLROW, GLCOL, nr, nc, n);
        !           987:                }
        !           988:        }
        !           989:        disptable[curchar].width = disptable[curchar].width * ratio + 0.5;
        !           990:        free(tmp);
        !           991: }
        !           992: 
        !           993: /*
        !           994:  * blow up a glyph.  Otherwise like shrinkglyph.
        !           995:  */
        !           996: blowupglyph(oldps, newps)
        !           997: int oldps, newps;
        !           998: {
        !           999:        float ratio;
        !          1000:        register int or, oc, nr, nc;
        !          1001:        int n;
        !          1002:        bitmat tmp, curw;
        !          1003:        int baser = cht[curchar].rcent;
        !          1004:        int basec = cht[curchar].ccent;
        !          1005: 
        !          1006:        ratio = (float) oldps / (float) newps;
        !          1007:        tmp = newmat(GLROW, GLCOL);
        !          1008:        curw = wind[curwind].val;
        !          1009:        bitcopy(tmp, curw, GLROW, GLCOL);
        !          1010:        zermat(curw, GLROW, GLCOL);
        !          1011:        for (nr=0; nr<GLROW; nr++) {
        !          1012:                or = baser + (nr-baser)*ratio + 0.5;
        !          1013:                for (nc=0; nc<GLCOL; nc++) {
        !          1014:                        oc = basec + (nc-basec)*ratio + 0.5;
        !          1015:                        if (or < 0 || or >= GLROW || oc < 0 || oc >= GLCOL)
        !          1016:                                n = 0;
        !          1017:                        else
        !          1018:                                n = mat(tmp, GLROW, GLCOL, or, oc);
        !          1019:                        if (n)
        !          1020:                                setmat(curw, GLROW, GLCOL, nr, nc, n);
        !          1021:                }
        !          1022:        }
        !          1023:        disptable[curchar].width = disptable[curchar].width / ratio + 0.5;
        !          1024:        free(tmp);
        !          1025: }
        !          1026: 
        !          1027: /*
        !          1028:  * Smooth a glyph.  We look for corners and trim the point.  Corners of
        !          1029:  * both blanks and dots in all 4 orientations are looked for.
        !          1030:  */
        !          1031: smoothglyph()
        !          1032: {
        !          1033:        bitmat tmp, curw;
        !          1034:        register int r, c;
        !          1035:        register int c3;
        !          1036:        int a3, b2, b3, b4, c1, c2, c4, c5, d2, d3, d4, e3;
        !          1037: 
        !          1038:        tmp = newmat(GLROW, GLCOL);
        !          1039:        curw = wind[curwind].val;
        !          1040:        bitcopy(tmp, curw, GLROW, GLCOL);
        !          1041:        for (r=2; r<GLROW-2; r++)
        !          1042:                for (c=2; c<GLCOL-2; c++) {
        !          1043:                        /*
        !          1044:                         *              a3
        !          1045:                         *           b2 b3 b4
        !          1046:                         *        c1 c2 c3 c4 c5
        !          1047:                         *           d2 d3 d4
        !          1048:                         *              d4
        !          1049:                         * where c3 is the square we are interested in
        !          1050:                         */
        !          1051:                        b3 = mat(tmp, GLROW, GLCOL, r-1, c  );
        !          1052:                        c2 = mat(tmp, GLROW, GLCOL, r  , c-1);
        !          1053:                        c4 = mat(tmp, GLROW, GLCOL, r  , c+1);
        !          1054:                        d3 = mat(tmp, GLROW, GLCOL, r+1, c  );
        !          1055:                        /* exactly 2 of the 4 neighbors must be dots */
        !          1056:                        if (b3+c2+c4+d3 != 2) continue;
        !          1057: 
        !          1058:                        c3 = mat(tmp, GLROW, GLCOL, r  , c  );
        !          1059:                        b2 = mat(tmp, GLROW, GLCOL, r-1, c-1);
        !          1060:                        b4 = mat(tmp, GLROW, GLCOL, r-1, c+1);
        !          1061:                        d2 = mat(tmp, GLROW, GLCOL, r+1, c-1);
        !          1062:                        d4 = mat(tmp, GLROW, GLCOL, r+1, c+1);
        !          1063:                        /* exactly one of the 4 diags must match the center */
        !          1064:                        if (b2+b4+d2+d4 != 3 - 2*c3) continue;
        !          1065: 
        !          1066:                        a3 = mat(tmp, GLROW, GLCOL, r-2, c  );
        !          1067:                        c1 = mat(tmp, GLROW, GLCOL, r  , c-2);
        !          1068:                        c5 = mat(tmp, GLROW, GLCOL, r  , c+2);
        !          1069:                        e3 = mat(tmp, GLROW, GLCOL, r+2, c  );
        !          1070: 
        !          1071:                        /* Figure out which of the 4 directions */
        !          1072:                        if (b2==c3) {
        !          1073:                                if (b3+c2+c1+a3 != 4*c3) continue;
        !          1074:                        } else
        !          1075:                        if (b4==c3) {
        !          1076:                                if (b3+c4+c5+a3 != 4*c3) continue;
        !          1077:                        } else
        !          1078:                        if (d2==c3) {
        !          1079:                                if (d3+c2+c1+e3 != 4*c3) continue;
        !          1080:                        } else
        !          1081:                        if (d4==c3) {
        !          1082:                                if (d3+c4+c5+e3 != 4*c3) continue;
        !          1083:                        }
        !          1084: 
        !          1085:                        /* It must be a corner.  Toggle it. */
        !          1086:                        setmat(curw, GLROW, GLCOL, r, c, !c3);
        !          1087:                }
        !          1088:        free(tmp);
        !          1089: }
        !          1090: 
        !          1091: /*
        !          1092:  * Read a number from bottom line ala readline.
        !          1093:  * This should probably go in lib2648.
        !          1094:  */
        !          1095: int
        !          1096: readnum(prompt)
        !          1097: char *prompt;
        !          1098: {
        !          1099:        char buf[10];
        !          1100:        int retval;
        !          1101: 
        !          1102:        readline(prompt, buf, sizeof buf);
        !          1103:        retval = atoi(buf);
        !          1104:        if (trace)
        !          1105:                fprintf(trace, "readline returns '%s', retval=%d\n", buf, retval);
        !          1106:        return (retval);
        !          1107: }
        !          1108: 
        !          1109: invert()
        !          1110: {
        !          1111:        register int r, c;
        !          1112:        int tmp1, tmp2, kind;
        !          1113:        bitmat curw = wind[curwind].val;
        !          1114: 
        !          1115:        message("Invert <horizontally/vertically>");
        !          1116:        kind = inchar();
        !          1117:        switch (kind) {
        !          1118:        case 'h': case 'H':
        !          1119:                message("Invert horizontally");
        !          1120:                for (r=0; r<GLROW; r++) {
        !          1121:                        if (trace)
        !          1122:                                fprintf(trace, "row %d\n", r);
        !          1123:                        for (c=0; c<=(GLCOL-1)/2; c++) {
        !          1124:                                tmp1 = mat(curw, GLROW, GLCOL, r, c);
        !          1125:                                tmp2 = mat(curw, GLROW, GLCOL, r, GLCOL-1-c);
        !          1126:                                if (trace)
        !          1127:                                        fprintf(trace, "cols %d (%d) <=> %d (%d)\n", c, tmp1, GLCOL-1-c, tmp2);
        !          1128:                                setmat(curw, GLROW, GLCOL, r, c, tmp2);
        !          1129:                                setmat(curw, GLROW, GLCOL, r, GLCOL-1-c, tmp1);
        !          1130:                        }
        !          1131:                }
        !          1132:                break;
        !          1133:        case 'v': case 'V':
        !          1134:                message("Invert vertically");
        !          1135:                for (c=0; c<GLCOL; c++) {
        !          1136:                        for (r=0; r<=(GLROW-1)/2; r++) {
        !          1137:                                tmp1 = mat(curw, GLROW, GLCOL, r, c);
        !          1138:                                tmp2 = mat(curw, GLROW, GLCOL, GLROW-1-r, c);
        !          1139:                                setmat(curw, GLROW, GLCOL, r, c, tmp2);
        !          1140:                                setmat(curw, GLROW, GLCOL, GLROW-1-r, c, tmp1);
        !          1141:                        }
        !          1142:                }
        !          1143:                break;
        !          1144:        default:
        !          1145:                error("Bad choice");
        !          1146:        }
        !          1147:        syncwind(curwind);
        !          1148: }

unix.superglobalmegacorp.com

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