Annotation of 43BSD/old/fed/subr.c, revision 1.1.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.