Annotation of researchv9/jtools/src/Jpic/pic1.c, revision 1.1

1.1     ! root        1: #include       <stdio.h>
        !             2: #include       "pic.h"
        !             3: #include       "y.tab.h"
        !             4: #define        dprintf if(dbg)printf
        !             5: 
        !             6: #define        PI      3.141592654
        !             7: #define        PI2     PI/2
        !             8: #define        SCALE   200     /* default scale: units/inch */
        !             9: #define        WID     150     /* default width for boxes and ellipses */
        !            10: #define        HT      100     /* default height and line length */
        !            11: 
        !            12: /* But there's one of these in pic.h? -Bart
        !            13: #define        MAXOBJ  400
        !            14:  */
        !            15: struct obj     *objlist[MAXOBJ];       /* store the elements here */
        !            16: int    nobj    = 0;
        !            17: 
        !            18: struct attr    attr[40];       /* attributes stored here as collected */
        !            19: int    nattr   = 0;    /* number of entries in attr_list */
        !            20: 
        !            21: #define        MAXTEXT 200
        !            22: struct text    text[MAXTEXT];  /* text strings stored here as collected */
        !            23: int    ntext   = 0;
        !            24: int    ntext1  = 0;    /* record ntext here on entry to each figure */
        !            25: 
        !            26: #define        SYMTAB  200
        !            27: struct symtab  symtab[SYMTAB];
        !            28: int    nsymtab = 0;
        !            29: 
        !            30: coord  curx    = 0;
        !            31: coord  cury    = 0;
        !            32: 
        !            33: int    hvmode  = R_DIR;        /* R => join left to right, D => top to bottom, etc. */
        !            34: 
        !            35: #define        MAXTYPE 12
        !            36: int    first[MAXTYPE]; /* indicates whether first of particular type */
        !            37:                        /* has been seen within this picture */
        !            38: 
        !            39: int    codegen = 0;    /* 1=>output for this picture; 0=>no output */
        !            40: 
        !            41: struct obj     *makenode();
        !            42: char   *malloc();
        !            43: 
        !            44: float  deltx   = 6;    /* max x value in output, for scaling */
        !            45: float  delty   = 6;    /* max y value in output, for scaling */
        !            46: float  scale   = 0;    /* implies simply scaling by this value; no crop or shift */
        !            47: int    dbg     = 0;
        !            48: extern FILE    *yyin;  /* input file pointer */
        !            49: int    lineno  = 0;
        !            50: char   *filename       = "-";
        !            51: int    synerr  = 0;
        !            52: char   *cmdname;
        !            53: int    crop    = 1;    /* trim off exterior white space if non-zero */
        !            54: 
        !            55: #define        DEV202  1
        !            56: #define        DEVAPS  2
        !            57: #define        DEVCAT  3
        !            58: #define        DEV450  4
        !            59: 
        !            60: /* You may want to change this if you don't have a 202... */
        !            61: 
        !            62: int    devtype = DEV202;
        !            63: int    res     = 972;  /* default is 202 */
        !            64: int    DX      = 4;    /* used only for old-style troff */
        !            65: int    DY      = 4;
        !            66: 
        !            67: /* mandatory values for graphic systems CAT: */
        !            68: /*
        !            69: int    devtype = DEVCAT;
        !            70: int    res     = 432;
        !            71: int    DX = 3;
        !            72: int    DY = 3;
        !            73: */
        !            74: 
        !            75: float  hshift  = 0;    /* move this far left for text (in em's) */
        !            76: float  vshift  = 0.2;  /* this far down */
        !            77: 
        !            78: coord  sxmin;          /* lower limit from s command */
        !            79: coord  symin;
        !            80: coord  sxmax   = 4096; /* upper */
        !            81: coord  symax   = 4096;
        !            82: 
        !            83: coord  xmin    = 30000;        /* min values found in actual data */
        !            84: coord  ymin    = 30000;
        !            85: coord  xmax    = -30000;       /* max */
        !            86: coord  ymax    = -30000;
        !            87: 
        !            88: extern float   atof();
        !            89: 
        !            90: main(argc,argv)
        !            91: char **argv;
        !            92: {
        !            93:        int casel, c;
        !            94: 
        !            95:        cmdname = argv[0];
        !            96:        casel = 0;
        !            97:        while (argc > 1 && *argv[1] == '-') {
        !            98:                switch (c = argv[1][1]) {
        !            99:                case 'T':
        !           100:                        if (strcmp(&argv[1][2], "aps") == 0) {
        !           101:                                res = 720;
        !           102:                                devtype = DEVAPS;
        !           103:                                DX = DY = 1;
        !           104:                        } else if (strcmp(&argv[1][2], "cat") == 0) {
        !           105:                                res = 432;
        !           106:                                devtype = DEVCAT;
        !           107:                                DX = DY = 3;
        !           108:                        } else if (strcmp(&argv[1][2], "450") == 0) {
        !           109:                                res = 240;
        !           110:                                devtype = DEV450;
        !           111:                        } else {
        !           112:                                res = atoi(&argv[1][2]);
        !           113:                        }
        !           114:                        break;
        !           115:                case 'c':
        !           116:                        crop = 0;
        !           117:                        break;
        !           118:                case 'l':
        !           119:                        delty = atof(&argv[1][2]);
        !           120:                        casel = 0;
        !           121:                        break;
        !           122:                case 'w':
        !           123:                case 's':
        !           124:                        if (argv[1][2] == 0) {
        !           125:                                argv++;
        !           126:                                argc--;
        !           127:                                deltx = atof(&argv[1][0]);
        !           128:                        } else
        !           129:                                deltx = atof(&argv[1][2]);
        !           130:                        if (c == 's')
        !           131:                                scale = deltx;
        !           132:                        break;
        !           133:                case 'd':
        !           134:                        dbg = 1;
        !           135:                        break;
        !           136:                }
        !           137:                argc--;
        !           138:                argv++;
        !           139:        }
        !           140:        if (!casel)
        !           141:                delty = deltx;
        !           142:        setdefaults();
        !           143:        if (argc <= 1) {
        !           144:                yyin = stdin;
        !           145:                getdata(yyin);
        !           146:        } else
        !           147:                while (argc-- > 1) {
        !           148:                        if ((yyin = fopen(*++argv, "r")) == NULL) {
        !           149:                                fprintf(stderr, "pic: can't open %s\n", *argv);
        !           150:                                exit(1);
        !           151:                        }
        !           152:                        filename = *argv;
        !           153:                        getdata(yyin);
        !           154:                        fclose(yyin);
        !           155:                }
        !           156:        exit(0);
        !           157: }
        !           158: 
        !           159: setdefaults()  /* set default sizes for variables like boxht */
        !           160: {
        !           161:        static struct {
        !           162:                char *name;
        !           163:                int val;
        !           164:        } defaults[] ={
        !           165:                "lineht", HT,
        !           166:                "linewid", HT,
        !           167:                "moveht", HT,
        !           168:                "movewid", HT,
        !           169:                "dashwid", HT/10,
        !           170:                "boxht", HT,
        !           171:                "boxwid", WID,
        !           172:                "circlerad", HT/2,
        !           173:                "arcrad", HT/2,
        !           174:                "ellipseht", HT,
        !           175:                "ellipsewid", WID,
        !           176:                "arrowht", HT/5,
        !           177:                "arrowwid", HT/10,
        !           178:                "textht", HT,
        !           179:                "textwid", WID,
        !           180:                "scale", SCALE,
        !           181:                NULL, 0
        !           182:        };
        !           183:        int i;
        !           184: 
        !           185:        for (i = 0; defaults[i].name != NULL; i++)
        !           186:                makevar(defaults[i].name, VARNAME, defaults[i].val);
        !           187: }
        !           188: 
        !           189: getdata(fin)
        !           190: register FILE *fin;
        !           191: {
        !           192:        char buf[1000], buf1[50];
        !           193:        FILE *svyyin;
        !           194:        int svlineno;
        !           195:        char *svfilename, *p;
        !           196: 
        !           197:        lineno = 0;
        !           198:        while (fgets(buf, sizeof buf, fin) != NULL) {
        !           199:                lineno++;
        !           200:                if (*buf == '.' && *(buf+1) == 'P' && *(buf+2) == 'S') {
        !           201:                        for (p = &buf[3]; *p == ' '; p++)
        !           202:                                ;
        !           203:                        if (*p++ == '<') {
        !           204:                                svyyin = yyin;
        !           205:                                svlineno = lineno;
        !           206:                                svfilename = filename;
        !           207:                                sscanf(p, "%s", buf1);
        !           208:                                if ((yyin = fopen(buf1, "r")) == NULL) {
        !           209:                                        fprintf(stderr, "pic: can't open %s\n", buf1);
        !           210:                                        exit(1);
        !           211:                                }
        !           212:                                lineno = 0;
        !           213:                                filename = p;
        !           214:                                getdata(yyin);
        !           215:                                fclose(yyin);
        !           216:                                lineno = svlineno;
        !           217:                                yyin = svyyin;
        !           218:                                filename = svfilename;
        !           219:                                continue;
        !           220:                        }
        !           221:                        reset();
        !           222:                        yyparse();
        !           223:                        if (buf[3] == ' ')      /* assume next thing is width */
        !           224:                                deltx = delty = atof(&buf[4]);
        !           225:                         else {    /* use scale to determine size */
        !           226:                                int t;
        !           227:                                t = xmax - xmin;
        !           228:                                if (t == 0)
        !           229:                                        t = ymax - ymin;
        !           230:                                deltx = delty = (float) t / (float)getvar(lookup("scale"));
        !           231:                        }
        !           232:                        dprintf("deltx = %.3f\n", deltx);
        !           233:                        if (codegen && !synerr) {
        !           234:                                openpl(&buf[3]);        /* puts out .PS, with ht & wid stuck in */
        !           235:                                print();        /* assumes \n at end */
        !           236:                                closepl();      /* this does the .PE */
        !           237:                        }
        !           238:                }
        !           239:                else
        !           240:                        fputs(buf, stdout);
        !           241:        }
        !           242: }
        !           243: 
        !           244: print()
        !           245: {
        !           246:        struct obj *p;
        !           247:        int i, j, m;
        !           248:        coord x0, y0, x1, y1, ox, oy, dx, dy;
        !           249: 
        !           250:        for (i = 0; i < nobj; i++) {
        !           251:                p = objlist[i];
        !           252:                ox = p->o_x;
        !           253:                oy = p->o_y;
        !           254:                x1 = p->o_val[0];
        !           255:                y1 = p->o_val[1];
        !           256:                m = p->o_mode;
        !           257:                switch (p->o_type) {
        !           258:                case TROFF:
        !           259:                        troff(text[p->o_nt1].t_val);
        !           260:                        break;
        !           261:                case BOX:
        !           262:                        move(ox, oy);
        !           263:                        dotext(p);      /* if there are any text strings */
        !           264:                        x0 = ox - (x1+1) / 2;
        !           265:                        y0 = oy - (y1+1) / 2;
        !           266:                        x1 = ox + x1 / 2;
        !           267:                        y1 = oy + y1 / 2;
        !           268:                        if (p->o_attr & INVIS)
        !           269:                                ;       /* nothing at all */
        !           270:                        else if (p->o_dotdash == 0)
        !           271:                                box(x0, y0, x1, y1);
        !           272:                        else
        !           273:                                dotbox(x0, y0, x1, y1, p->o_dotdash, p->o_ddval);
        !           274:                        if (ishor(m))
        !           275:                                move(isright(m) ? x1 : x0, oy); /* right side */
        !           276:                        else
        !           277:                                move(ox, isdown(m) ? y0 : y1);  /* bottom */
        !           278:                        break;
        !           279:                case CIRCLE:
        !           280:                        move(ox, oy);
        !           281:                        dotext(p);
        !           282:                        if ((p->o_attr & INVIS) == 0)
        !           283:                                circle(ox, oy, x1);
        !           284:                        if (ishor(m))
        !           285:                                move(ox + isright(m) ? x1 : -x1, oy);
        !           286:                        else
        !           287:                                move(ox, oy + isup(m) ? x1 : -x1);
        !           288:                        break;
        !           289:                case ELLIPSE:
        !           290:                        move(ox, oy);
        !           291:                        dotext(p);
        !           292:                        if ((p->o_attr & INVIS) == 0)
        !           293:                                ellipse(ox, oy, x1, y1);
        !           294:                        if (ishor(m))
        !           295:                                move(ox + isright(m) ? x1 : -x1, oy);
        !           296:                        else
        !           297:                                move(ox, oy - isdown(m) ? y1 : -y1);
        !           298:                        break;
        !           299:                case ARC:
        !           300:                        move(ox, oy);
        !           301:                        dotext(p);
        !           302:                        if (p->o_attr & HEAD1)
        !           303:                                arrow(x1 - (y1 - oy), y1 + (x1 - ox),
        !           304:                                      x1, y1, p->o_val[4], p->o_val[5]);
        !           305:                         if (p->o_attr & INVIS)
        !           306:                                 /* probably wrong when it's cw */
        !           307:                                 move(x1, y1);
        !           308:                         else
        !           309:                                arc(ox, oy, x1, y1, p->o_val[2], p->o_val[3]);
        !           310:                        if (p->o_attr & HEAD2)
        !           311:                                arrow(p->o_val[2] + p->o_val[3] - oy, p->o_val[3] - (p->o_val[2] - ox),
        !           312:                                      p->o_val[2], p->o_val[3], p->o_val[4], p->o_val[5]);
        !           313:                        if (p->o_attr & CW_ARC)
        !           314:                                move(x1, y1);   /* because drawn backwards */
        !           315:                        break;
        !           316:                case LINE:
        !           317:                case ARROW:
        !           318:                case SPLINE:
        !           319:                        move((ox + x1)/2, (oy + y1)/2); /* center */
        !           320:                        dotext(p);
        !           321:                        if (p->o_attr & HEAD1)
        !           322:                                arrow(ox + p->o_val[5], oy + p->o_val[6], ox, oy, p->o_val[2], p->o_val[3]);
        !           323:                         if (p->o_attr & INVIS)
        !           324:                                 move(x1, y1);
        !           325:                        else if (p->o_type == SPLINE)
        !           326:                                spline(ox, oy, p->o_val[4], &p->o_val[5]);
        !           327:                        else {
        !           328:                                int i, j, ndx, ndy;
        !           329:                                dx = ox;
        !           330:                                dy = oy;
        !           331:                                for (i=0, j=5; i < p->o_val[4]; i++, j += 2) {
        !           332:                                        ndx = dx + p->o_val[j];
        !           333:                                        ndy = dy + p->o_val[j+1];
        !           334:                                        if (p->o_dotdash == 0)
        !           335:                                                line(dx, dy, ndx, ndy);
        !           336:                                        else
        !           337:                                                dotline(dx, dy, ndx, ndy, p->o_dotdash, p->o_ddval);
        !           338:                                        dx = ndx;
        !           339:                                        dy = ndy;
        !           340:                                }
        !           341:                        }
        !           342:                        if (p->o_attr & HEAD2) {
        !           343:                                int i, j;
        !           344:                                dx = ox;
        !           345:                                dy = oy;
        !           346:                                for (i = 0, j = 5; i < p->o_val[4] - 1; i++, j += 2) {
        !           347:                                        dx += p->o_val[j];
        !           348:                                        dy += p->o_val[j+1];
        !           349:                                }
        !           350:                                arrow(dx, dy, x1, y1, p->o_val[2], p->o_val[3]);
        !           351:                        }
        !           352:                        break;
        !           353:                case MOVE:
        !           354:                        move(ox, oy);
        !           355:                        dotext(p);
        !           356:                        break;
        !           357:                case TEXT:
        !           358:                        move(ox, oy);
        !           359:                        label(x1, y1, 0);
        !           360:                        free(x1);
        !           361:                        break;
        !           362:                }
        !           363:        }
        !           364: }
        !           365: 
        !           366: dotline(x0, y0, x1, y1, ddtype, ddval) /* dotted line */
        !           367: coord x0, y0, x1, y1;
        !           368: int ddtype;
        !           369: int ddval;
        !           370: {
        !           371:        static int prevval = SCALE/20;  /* 20 per inch by default */
        !           372:        int i, numdots;
        !           373:        double a, b, sqrt(), dx, dy;
        !           374: 
        !           375:        if (ddval == 0)
        !           376:                ddval = prevval;
        !           377:        prevval = ddval;
        !           378:        /* don't save dot/dash value */
        !           379:        dx = x1 - x0;
        !           380:        dy = y1 - y0;
        !           381:        if (ddtype == DOT) {
        !           382:                numdots = sqrt(dx*dx + dy*dy) / prevval + 0.5;
        !           383:                for (i = 0; i <= numdots; i++) {
        !           384:                        a = (float) i / (float) numdots;
        !           385:                        move(x0 + (int)(a * dx), y0 + (int)(a * dy));
        !           386:                        dot();
        !           387:                }
        !           388:        } else if (ddtype == DASH) {
        !           389:                double d, dashsize, spacesize;
        !           390:                d = sqrt(dx*dx + dy*dy) + 0.5;
        !           391:                if (d <= 2 * prevval) {
        !           392:                        line(x0, y0, x1, y1);
        !           393:                        return;
        !           394:                }
        !           395:                numdots = d / (2 * prevval - 1) + 1;    /* ceiling */
        !           396:                dashsize = prevval;
        !           397:                spacesize = (d - numdots * dashsize) / (numdots - 1);
        !           398:                for (i = 0; i < numdots-1; i++) {
        !           399:                        a = i * (dashsize + spacesize) / d;
        !           400:                        b = a + dashsize / d;
        !           401:                        line(x0 + (int)(a*dx), y0 + (int)(a*dy), x0 + (int)(b*dx), y0 + (int)(b*dy));
        !           402:                        a = b;
        !           403:                        b = a + spacesize / d;
        !           404:                        move(x0 + (int)(a*dx), y0 + (int)(a*dy));
        !           405:                }
        !           406:                line(x0 + (int)(b * dx), y0 + (int)(b * dy), x1, y1);
        !           407:        }
        !           408:        prevval = SCALE/20;
        !           409: }
        !           410: 
        !           411: dotbox(x0, y0, x1, y1, ddtype, ddval)  /* dotted or dashed box */
        !           412: coord x0, y0, x1, y1;
        !           413: int ddtype;
        !           414: int ddval;
        !           415: {
        !           416:        dotline(x0, y0, x1, y0, ddtype, ddval);
        !           417:        dotline(x1, y0, x1, y1, ddtype, ddval);
        !           418:        dotline(x1, y1, x0, y1, ddtype, ddval);
        !           419:        dotline(x0, y1, x0, y0, ddtype, ddval);
        !           420: }
        !           421: 
        !           422: dotext(p)      /* print text strings of p in proper vertical spacing */
        !           423: struct obj *p;
        !           424: {
        !           425:        int i, nhalf;
        !           426: 
        !           427:        nhalf = p->o_nt2 - p->o_nt1 - 1;
        !           428:        for (i = p->o_nt1; i < p->o_nt2; i++) {
        !           429:                label(text[i].t_val, text[i].t_type, nhalf);
        !           430:                nhalf -= 2;
        !           431:        }
        !           432: }
        !           433: 
        !           434: reset()
        !           435: {
        !           436:        int i;
        !           437: 
        !           438:        for (i = 0; i < nobj; i++)
        !           439:                free(objlist[i]);
        !           440:        nobj = 0;
        !           441:        nattr = 0;
        !           442:        for (i = 0; i < ntext; i++)
        !           443:                free(text[i].t_val);
        !           444:        ntext = ntext1 = 0;
        !           445:        for (i = 0; i < MAXTYPE; i++)
        !           446:                first[i] = 0;
        !           447:        codegen = synerr = 0;
        !           448:        curx = cury = 0;
        !           449:        hvmode = R_DIR;
        !           450:        sxmin = symin = 0;
        !           451:        sxmax = symax = 4096;
        !           452:        xmin = ymin = 30000;
        !           453:        xmax = ymax = -30000;
        !           454: }
        !           455: 
        !           456: coord  xstack[20];     /* store curx here for pushdown {...} */
        !           457: coord  ystack[20];
        !           458: int    hvstack[20];
        !           459: int    nstack  = 0;
        !           460: 
        !           461: push()
        !           462: {
        !           463:        xstack[nstack] = curx;
        !           464:        ystack[nstack] = cury;
        !           465:        hvstack[nstack] = hvmode;
        !           466:        nstack++;
        !           467: }
        !           468: 
        !           469: pop()
        !           470: {
        !           471:        struct obj *p;
        !           472: 
        !           473:        nstack--;
        !           474:        curx = xstack[nstack];
        !           475:        cury = ystack[nstack];
        !           476:        hvmode = hvstack[nstack];
        !           477:        p = makenode(MOVE, 0);
        !           478:        dprintf("M %d %d\n", curx, cury);
        !           479: }
        !           480: 
        !           481: setvar(n, v, t)        /* store v in variable in table slot n */
        !           482: {
        !           483:        symtab[n].s_val = v;
        !           484:        symtab[n].s_type = t;
        !           485: }
        !           486: 
        !           487: getvar(n)      /* return value of variable in slot n */
        !           488: {
        !           489:        return(symtab[n].s_val);
        !           490: }
        !           491: 
        !           492: setdir(n)      /* set direction from n */
        !           493: int n;
        !           494: {
        !           495:        switch (n) {
        !           496:        case UP:        hvmode = U_DIR; break;
        !           497:        case DOWN:      hvmode = D_DIR; break;
        !           498:        case LEFT:      hvmode = L_DIR; break;
        !           499:        case RIGHT:     hvmode = R_DIR; break;
        !           500:        }
        !           501:        return(hvmode);
        !           502: }
        !           503: 
        !           504: coord getcomp(p, t)    /* return component of a position */
        !           505: struct obj *p;
        !           506: int t;
        !           507: {
        !           508:        switch (t) {
        !           509:        case DOTX:
        !           510:                return(p->o_x);
        !           511:        case DOTY:
        !           512:                return(p->o_y);
        !           513:        case DOTWID:
        !           514:                switch (p->o_type) {
        !           515:                case BOX:
        !           516:                        return(p->o_val[0]);
        !           517:                case CIRCLE:
        !           518:                case ELLIPSE:
        !           519:                        return(2 * p->o_val[0]);
        !           520:                case LINE:
        !           521:                case ARROW:
        !           522:                        return(p->o_val[0] - p->o_x);
        !           523:                }
        !           524:        case DOTHT:
        !           525:                switch (p->o_type) {
        !           526:                case BOX:
        !           527:                        return(p->o_val[1]);
        !           528:                case CIRCLE:
        !           529:                case ELLIPSE:
        !           530:                        return(2 * p->o_val[1]);
        !           531:                case LINE:
        !           532:                case ARROW:
        !           533:                        return(p->o_val[1] - p->o_y);
        !           534:                }
        !           535:        case DOTRAD:
        !           536:                switch (p->o_type) {
        !           537:                case CIRCLE:
        !           538:                case ELLIPSE:
        !           539:                        return(p->o_val[0]);
        !           540:                }
        !           541:        }
        !           542: }
        !           543: 
        !           544: 
        !           545: makeattr(type, val)    /* add attribute type and val */
        !           546: int type;
        !           547: int val;       /* typing probably wrong */
        !           548: {
        !           549:        if (type == 0 && val == 0) {    /* clear table for next stat */
        !           550:                nattr = 0;
        !           551:                return;
        !           552:        }
        !           553:        dprintf("attr %d:  %d %d\n", nattr, type, val);
        !           554:        attr[nattr].a_type = type;
        !           555:        attr[nattr].a_val = val;
        !           556:        nattr++;
        !           557: }
        !           558: 
        !           559: troffgen(s)    /* save away a string of troff commands */
        !           560: char *s;
        !           561: {
        !           562:        savetext(CENTER, s);    /* use the existing text mechanism */
        !           563:        makenode(TROFF, 0);
        !           564: }
        !           565: 
        !           566: printexpr(n)   /* print expression for debugging */
        !           567: int n;
        !           568: {
        !           569:        dprintf("%d\n", n);
        !           570: }
        !           571: 
        !           572: struct obj *boxgen(type)
        !           573: {
        !           574:        static int prevh = HT;
        !           575:        static int prevw = WID; /* golden mean, sort of */
        !           576:        int i, invis, at, ddtype, ddval;
        !           577:        int with, xwith, ywith;
        !           578:        int h, w;
        !           579:        coord x0, y0, x1, y1;
        !           580:        struct obj *p, *ppos;
        !           581: 
        !           582:        /* EXPENSIVE! */
        !           583:        h = getvar(lookup("boxht"));
        !           584:        w = getvar(lookup("boxwid"));
        !           585:        invis = at = 0;
        !           586:        with = xwith = ywith = 0;
        !           587:        ddtype = ddval = 0;
        !           588:        for (i = 0; i < nattr; i++) {
        !           589:                switch (attr[i].a_type) {
        !           590:                case HEIGHT:
        !           591:                        h = attr[i].a_val;
        !           592:                        break;
        !           593:                case WIDTH:
        !           594:                        w = attr[i].a_val;
        !           595:                        break;
        !           596:                case SAME:
        !           597:                        h = prevh;
        !           598:                        w = prevw;
        !           599:                        break;
        !           600:                case WITH:
        !           601:                        with = attr[i].a_val;   /* corner */
        !           602:                        break;
        !           603:                case AT:
        !           604:                        ppos = (struct obj *) attr[i].a_val;
        !           605:                        curx = ppos->o_x;
        !           606:                        cury = ppos->o_y;
        !           607:                        at++;
        !           608:                        break;
        !           609:                case INVIS:
        !           610:                        invis = INVIS;
        !           611:                        break;
        !           612:                case DOT:
        !           613:                case DASH:
        !           614:                        ddtype = attr[i].a_type;
        !           615:                        ddval = attr[i].a_val;
        !           616:                        if (ddval == 0)
        !           617:                                ddval = getvar(lookup("dashwid"));
        !           618:                        break;
        !           619:                case LJUST: case RJUST: case CENTER: case SPREAD: case FILL: case ABOVE: case BELOW:
        !           620:                        savetext(attr[i].a_type, attr[i].a_val);
        !           621:                        break;
        !           622:                }
        !           623:        }
        !           624:        if (with) {
        !           625:                switch (with) {
        !           626:                case NORTH:     ywith = -((h+1) / 2); break;
        !           627:                case SOUTH:     ywith = h / 2; break;
        !           628:                case EAST:      xwith = -((w+1) / 2); break;
        !           629:                case WEST:      xwith = w / 2; break;
        !           630:                case NE:        xwith = -((w+1) / 2); ywith = -((h+1) / 2); break;
        !           631:                case SE:        xwith = -((w+1) / 2); ywith = h / 2; break;
        !           632:                case NW:        xwith = w / 2; ywith = -((h+1) / 2); break;
        !           633:                case SW:        xwith = w / 2; ywith = h / 2; break;
        !           634:                }
        !           635:                curx += xwith;
        !           636:                cury += ywith;
        !           637:        }
        !           638:        if (!at) {
        !           639:                if (isright(hvmode))
        !           640:                        curx += (w+1) / 2;
        !           641:                else if (isleft(hvmode))
        !           642:                        curx -= w / 2;
        !           643:                else if (isup(hvmode))
        !           644:                        cury += (h+1) / 2;
        !           645:                else
        !           646:                        cury -= h / 2;
        !           647:        }
        !           648:        x0 = curx - w / 2;
        !           649:        y0 = cury - h / 2;
        !           650:        x1 = curx + (w+1) / 2;
        !           651:        y1 = cury + (h+1) / 2;
        !           652:        extreme(x0, y0);
        !           653:        extreme(x1, y1);
        !           654:        p = makenode(BOX, 2);
        !           655:        p->o_val[0] = w;
        !           656:        p->o_val[1] = h;
        !           657:        p->o_dotdash = ddtype;
        !           658:        p->o_ddval = ddval;
        !           659:        p->o_attr = invis;
        !           660:        dprintf("B %d %d %d %d at %d %d, h=%d, w=%d\n", x0, y0, x1, y1, curx, cury, h, w);
        !           661:        if (isright(hvmode))
        !           662:                curx = x1;
        !           663:        else if (isleft(hvmode))
        !           664:                curx = x0;
        !           665:        else if (isup(hvmode))
        !           666:                cury = y1;
        !           667:        else
        !           668:                cury = y0;
        !           669:        prevh = h;
        !           670:        prevw = w;
        !           671:        return(p);
        !           672: }
        !           673: 
        !           674: savetext(t, s) /* record text elements for current object */
        !           675: int t;
        !           676: char *s;
        !           677: {
        !           678:        switch (t) {
        !           679:        case CENTER:    t = 'C'; break;
        !           680:        case LJUST:     t = 'L'; break;
        !           681:        case RJUST:     t = 'R'; break;
        !           682:        case SPREAD:    t = 'S'; break;
        !           683:        case FILL:      t = 'F'; break;
        !           684:        case ABOVE:     t = 'A'; break;
        !           685:        case BELOW:     t = 'B'; break;
        !           686:        }
        !           687:        if (ntext >= MAXTEXT) {
        !           688:                fprintf(stderr, "too many text strings (%d)\n", ntext);
        !           689:                exit(1);
        !           690:        }
        !           691:        text[ntext].t_type = t;
        !           692:        text[ntext].t_val = s;
        !           693:        dprintf("saving %c text %s at %d\n", t, s, ntext);
        !           694:        ntext++;
        !           695: }
        !           696: 
        !           697: struct obj *circgen(type)
        !           698: {
        !           699:        static int rad[2] = { HT/2, WID/2 };
        !           700:        static int rad2[2] = { HT/2, HT/2 };
        !           701:        static coord x0, y0, x1, y1, x2, y2;
        !           702:        int i, at, t, invis;
        !           703:        int with, xwith, ywith;
        !           704:        int r, r2;
        !           705:        struct obj *p, *ppos;
        !           706: 
        !           707:        at = invis = 0;
        !           708:        with = xwith = ywith = 0;
        !           709:        t = (type == CIRCLE) ? 0 : 1;
        !           710:        if (type == CIRCLE)
        !           711:                r = r2 = getvar(lookup("circlerad"));
        !           712:        else if (type == ELLIPSE) {
        !           713:                r = getvar(lookup("ellipsewid")) / 2;
        !           714:                r2 = getvar(lookup("ellipseht")) / 2;
        !           715:        }
        !           716:        for (i = 0; i < nattr; i++)
        !           717:                switch (attr[i].a_type) {
        !           718:                case LJUST: case RJUST: case CENTER: case SPREAD: case FILL: case ABOVE: case BELOW:
        !           719:                        savetext(attr[i].a_type, attr[i].a_val);
        !           720:                        break;
        !           721:                case RADIUS:
        !           722:                        r = attr[i].a_val;
        !           723:                        break;
        !           724:                case DIAMETER:
        !           725:                case WIDTH:
        !           726:                        r = (attr[i].a_val + 1) / 2;
        !           727:                        break;
        !           728:                case HEIGHT:
        !           729:                        r2 = (attr[i].a_val + 1) / 2;
        !           730:                        break;
        !           731:                case SAME:
        !           732:                        r = rad[t];
        !           733:                        r2 = rad2[t];
        !           734:                        break;
        !           735:                case WITH:
        !           736:                        with = attr[i].a_val;
        !           737:                        break;
        !           738:                case AT:
        !           739:                        ppos = (struct obj *) attr[i].a_val;
        !           740:                        curx = ppos->o_x;
        !           741:                        cury = ppos->o_y;
        !           742:                        at++;
        !           743:                        break;
        !           744:                case INVIS:
        !           745:                        invis = INVIS;
        !           746:                        break;
        !           747:                }
        !           748:        if (type == CIRCLE)
        !           749:                r2 = r; /* probably superfluous */
        !           750:        if (with) {
        !           751:                switch (with) {
        !           752:                case NORTH:     ywith = -r2; break;
        !           753:                case SOUTH:     ywith = r2; break;
        !           754:                case EAST:      xwith = -r; break;
        !           755:                case WEST:      xwith = r; break;
        !           756:                case NE:        xwith = -r * 0.707; ywith = -r2 * 0.707; break;
        !           757:                case SE:        xwith = -r * 0.707; ywith = r2 * 0.707; break;
        !           758:                case NW:        xwith = r * 0.707; ywith = -r2 * 0.707; break;
        !           759:                case SW:        xwith = r * 0.707; ywith = r2 * 0.707; break;
        !           760:                }
        !           761:                curx += xwith;
        !           762:                cury += ywith;
        !           763:        }
        !           764:        if (!at) {
        !           765:                if (isright(hvmode))
        !           766:                        curx += r;
        !           767:                else if (isleft(hvmode))
        !           768:                        curx -= r;
        !           769:                else if (isup(hvmode))
        !           770:                        cury += r2;
        !           771:                else
        !           772:                        cury -= r2;
        !           773:        }
        !           774:        p = makenode(type, 2);
        !           775:        p->o_val[0] = rad[t] = r;
        !           776:        p->o_val[1] = rad2[t] = r2;
        !           777:        if (r <= 0 || r2 <= 0) {
        !           778:                yyerror("%s has invalid radius %d\n", (type==CIRCLE) ? "circle" : "ellipse", r<r2 ? r : r2);
        !           779:        }
        !           780:        p->o_attr = invis;
        !           781:        extreme(curx+r, cury+r2);
        !           782:        extreme(curx-r, cury-r2);
        !           783:        if (type == CIRCLE)
        !           784:                dprintf("C %d %d %d\n", curx, cury, r);
        !           785:        if (type == ELLIPSE)
        !           786:                dprintf("E %d %d %d %d\n", curx, cury, r, r2);
        !           787:        if (isright(hvmode))
        !           788:                curx += r;
        !           789:        else if (isleft(hvmode))
        !           790:                curx -= r;
        !           791:        else if (isup(hvmode))
        !           792:                cury += r2;
        !           793:        else
        !           794:                cury -= r2;
        !           795:        return(p);
        !           796: }
        !           797: 
        !           798: struct obj *arcgen(type)       /* handles circular and (eventually) elliptical arcs */
        !           799: {
        !           800:        static int prevw = HT/10;
        !           801:        static int prevh = HT/5;
        !           802:        static int prevrad = HT/2;
        !           803:        static int dtox[2][4] ={ 1, -1, -1, 1, 1, 1, -1, -1 };
        !           804:        static int dtoy[2][4] ={ 1, 1, -1, -1, -1, 1, 1, -1 };
        !           805:        static int dctrx[2][4] ={ 0, -1, 0, 1, 0, 1, 0, -1 };
        !           806:        static int dctry[2][4] ={ 1, 0, -1, 0, -1, 0, 1, 0 };
        !           807:        static int nexthv[2][4] ={ U_DIR, L_DIR, D_DIR, R_DIR, D_DIR, R_DIR, U_DIR, L_DIR };
        !           808:        double sqrt(), atan2(), sin(), cos();
        !           809:        float dx2, dy2, ht, phi, r, d;
        !           810:        int i, head, to, at, cw, invis;
        !           811:        struct obj *p, *ppos;
        !           812:        coord fromx, fromy, tox, toy;
        !           813: 
        !           814:        prevrad = getvar(lookup("arcrad"));
        !           815:        prevh = getvar(lookup("arrowht"));
        !           816:        prevw = getvar(lookup("arrowwid"));
        !           817:        fromx = curx;
        !           818:        fromy = cury;
        !           819:        head = to = at = cw = invis = 0;
        !           820:        for (i = 0; i < nattr; i++) {
        !           821:                switch (attr[i].a_type) {
        !           822:                case LJUST: case RJUST: case CENTER: case SPREAD: case FILL: case ABOVE: case BELOW:
        !           823:                        savetext(attr[i].a_type, attr[i].a_val);
        !           824:                        break;
        !           825:                case HEAD:
        !           826:                        head += attr[i].a_val;
        !           827:                        break;
        !           828:                case INVIS:
        !           829:                        invis = INVIS;
        !           830:                        break;
        !           831:                case HEIGHT:    /* length of arrowhead */
        !           832:                        prevh = attr[i].a_val;
        !           833:                        break;
        !           834:                case WIDTH:     /* width of arrowhead */
        !           835:                        prevw = attr[i].a_val;
        !           836:                        break;
        !           837:                case RADIUS:
        !           838:                        prevrad = attr[i].a_val;
        !           839:                        break;
        !           840:                case DIAMETER:
        !           841:                        prevrad = attr[i].a_val / 2;
        !           842:                        break;
        !           843:                case CW:
        !           844:                        cw = 1;
        !           845:                        break;
        !           846:                case FROM:      /* start point of arc */
        !           847:                        ppos = (struct obj *) attr[i].a_val;
        !           848:                        fromx = ppos->o_x;
        !           849:                        fromy = ppos->o_y;
        !           850:                        break;
        !           851:                case TO:        /* end point of arc */
        !           852:                        ppos = (struct obj *) attr[i].a_val;
        !           853:                        tox = ppos->o_x;
        !           854:                        toy = ppos->o_y;
        !           855:                        to++;
        !           856:                        break;
        !           857:                case AT:        /* center of arc */
        !           858:                        ppos = (struct obj *) attr[i].a_val;
        !           859:                        curx = ppos->o_x;
        !           860:                        cury = ppos->o_y;
        !           861:                        at = 1;
        !           862:                        break;
        !           863:                case UP:
        !           864:                        hvmode = U_DIR;
        !           865:                        break;
        !           866:                case DOWN:
        !           867:                        hvmode = D_DIR;
        !           868:                        break;
        !           869:                case RIGHT:
        !           870:                        hvmode = R_DIR;
        !           871:                        break;
        !           872:                case LEFT:
        !           873:                        hvmode = L_DIR;
        !           874:                        break;
        !           875:                }
        !           876:        }
        !           877:        if (!at && !to) {       /* the defaults are mostly OK */
        !           878:                curx = fromx + prevrad * dctrx[cw][hvmode];
        !           879:                cury = fromy + prevrad * dctry[cw][hvmode];
        !           880:                tox = fromx + prevrad * dtox[cw][hvmode];
        !           881:                toy = fromy + prevrad * dtoy[cw][hvmode];
        !           882:                hvmode = nexthv[cw][hvmode];
        !           883:        }
        !           884:        else if (!at) {
        !           885:                dx2 = (float)(tox - fromx) / 2;
        !           886:                dy2 = (float)(toy - fromy) / 2;
        !           887:                phi = atan2(dy2, dx2) + (cw ? -PI2 : PI2);
        !           888:                for (r=prevrad; (d = r*r - (dx2*dx2+dy2*dy2)) <= 0.0; r *= 2)
        !           889:                        ;       /* this kludge gets around too-small radii */
        !           890:                ht = sqrt(d);
        !           891:                curx = fromx + dx2 + ht * cos(phi) + 0.5;
        !           892:                cury = fromy + dy2 + ht * sin(phi) + 0.5;
        !           893:                dprintf("dx2,dy2=%g,%g, phi=%g, r,ht=%g,%g\n",
        !           894:                        dx2, dy2, phi, r, ht);
        !           895:        }
        !           896:        else if (at && !to) {   /* do we have all the cases??? */
        !           897:                tox = fromx + prevrad * dtox[cw][hvmode];
        !           898:                toy = fromy + prevrad * dtoy[cw][hvmode];
        !           899:                hvmode = nexthv[cw][hvmode];
        !           900:        }
        !           901:        if (cw) {       /* interchange roles of from-to and heads */
        !           902:                coord temp;
        !           903:                temp = fromx; fromx = tox; tox = temp;
        !           904:                temp = fromy; fromy = toy; toy = temp;
        !           905:                if (head == HEAD1)
        !           906:                        head = HEAD2;
        !           907:                else if (head == HEAD2)
        !           908:                        head = HEAD1;
        !           909:        }
        !           910:        p = makenode(type, 6);
        !           911:        /* these are wrong in general */
        !           912:        extreme(fromx, fromy);
        !           913:        extreme(tox, toy);
        !           914:        p->o_val[0] = fromx;
        !           915:        p->o_val[1] = fromy;
        !           916:        p->o_val[2] = tox;
        !           917:        p->o_val[3] = toy;
        !           918:        if (cw) {
        !           919:                curx = fromx;
        !           920:                cury = fromy;
        !           921:        } else {
        !           922:                curx = tox;
        !           923:                cury = toy;
        !           924:        }
        !           925:        p->o_val[4] = prevw;
        !           926:        p->o_val[5] = prevh;
        !           927:        p->o_attr = head | (cw ? CW_ARC : 0) | invis;
        !           928:        dprintf("arc at %d %d from %d %d to %d %d head %d %d\n",
        !           929:                p->o_x, p->o_y,
        !           930:                p->o_val[0], p->o_val[1], p->o_val[2], p->o_val[3], p->o_val[4], p->o_val[5]);
        !           931:        return(p);
        !           932: }
        !           933: 
        !           934: struct obj *linegen(type)
        !           935: {
        !           936:        static int prevdx = HT;
        !           937:        static int prevdy = 0;
        !           938:        static int prevw = HT/10;
        !           939:        static int prevh = HT/5;
        !           940:        int i, j, some, head, ddtype, ddval, invis;
        !           941:        int chop, chop1, chop2, x0, y0, x1, y1;
        !           942:        double sin(), cos(), atan2(), theta;
        !           943:        int defx, defy;
        !           944:        struct obj *p, *ppos;
        !           945:        static int xtab[] = { 1, 0, -1, 0 };    /* R=0, U=1, L=2, D=3 */
        !           946:        static int ytab[] = { 0, 1, 0, -1 };
        !           947:        int ndxy, dx[50], dy[50];
        !           948:        coord nx, ny;
        !           949: 
        !           950:        nx = curx;
        !           951:        ny = cury;
        !           952:        defx = getvar(lookup("linewid"));
        !           953:        defy = getvar(lookup("lineht"));
        !           954:        prevh = getvar(lookup("arrowht"));
        !           955:        prevw = getvar(lookup("arrowwid"));
        !           956:        dx[0] = dy[0] = ndxy = some = head = invis = 0;
        !           957:        chop = chop1 = chop2 = 0;
        !           958:        ddtype = ddval = 0;
        !           959:        for (i = 0; i < nattr; i++) {
        !           960:                switch (attr[i].a_type) {
        !           961:                case LJUST: case RJUST: case CENTER: case SPREAD: case FILL: case ABOVE: case BELOW:
        !           962:                        savetext(attr[i].a_type, attr[i].a_val);
        !           963:                        break;
        !           964:                case HEAD:
        !           965:                        head += attr[i].a_val;
        !           966:                        break;
        !           967:                case INVIS:
        !           968:                        invis = INVIS;
        !           969:                        break;
        !           970:                case CHOP:
        !           971:                        if (chop++ == 0)
        !           972:                                chop1 = chop2 = attr[i].a_val;
        !           973:                        else
        !           974:                                chop2 = attr[i].a_val;
        !           975:                        break;
        !           976:                case DOT:
        !           977:                case DASH:
        !           978:                        ddtype = attr[i].a_type;
        !           979:                        ddval = attr[i].a_val;
        !           980:                        if (ddval == 0)
        !           981:                                ddval = getvar(lookup("dashwid"));
        !           982:                        break;
        !           983:                case SAME:
        !           984:                        dx[ndxy] = prevdx;
        !           985:                        dy[ndxy] = prevdy;
        !           986:                        some++;
        !           987:                        break;
        !           988:                case LEFT:
        !           989:                        dx[ndxy] -= (attr[i].a_val==0) ? defx : attr[i].a_val;
        !           990:                        some++;
        !           991:                        hvmode = L_DIR;
        !           992:                        break;
        !           993:                case RIGHT:
        !           994:                        dx[ndxy] += (attr[i].a_val==0) ? defx : attr[i].a_val;
        !           995:                        some++;
        !           996:                        hvmode = R_DIR;
        !           997:                        break;
        !           998:                case UP:
        !           999:                        dy[ndxy] += (attr[i].a_val==0) ? defy : attr[i].a_val;
        !          1000:                        some++;
        !          1001:                        hvmode = U_DIR;
        !          1002:                        break;
        !          1003:                case DOWN:
        !          1004:                        dy[ndxy] -= (attr[i].a_val==0) ? defy : attr[i].a_val;
        !          1005:                        some++;
        !          1006:                        hvmode = D_DIR;
        !          1007:                        break;
        !          1008:                case HEIGHT:    /* length of arrowhead */
        !          1009:                        prevh = attr[i].a_val;
        !          1010:                        break;
        !          1011:                case WIDTH:     /* width of arrowhead */
        !          1012:                        prevw = attr[i].a_val;
        !          1013:                        break;
        !          1014:                case TO:
        !          1015:                        if (some) {
        !          1016:                                nx += dx[ndxy];
        !          1017:                                ny += dy[ndxy];
        !          1018:                                ndxy++;
        !          1019:                                dx[ndxy] = dy[ndxy] = some = 0;
        !          1020:                        }
        !          1021:                        ppos = (struct obj *) attr[i].a_val;
        !          1022:                        dx[ndxy] = ppos->o_x - nx;
        !          1023:                        dy[ndxy] = ppos->o_y - ny;
        !          1024:                        some++;
        !          1025:                        break;
        !          1026:                case BY:
        !          1027:                        ppos = (struct obj *) attr[i].a_val;
        !          1028:                        dx[ndxy] = ppos->o_x;
        !          1029:                        dy[ndxy] = ppos->o_y;
        !          1030:                        some++;
        !          1031:                        break;
        !          1032:                case THEN:      /* turn off any previous accumulation */
        !          1033:                        if (some) {
        !          1034:                                nx += dx[ndxy];
        !          1035:                                ny += dy[ndxy];
        !          1036:                                ndxy++;
        !          1037:                                dx[ndxy] = dy[ndxy] = some = 0;
        !          1038:                        }
        !          1039:                        break;
        !          1040:                case FROM:
        !          1041:                case AT:
        !          1042:                        ppos = (struct obj *) attr[i].a_val;
        !          1043:                        nx = curx = ppos->o_x;
        !          1044:                        ny = cury = ppos->o_y;
        !          1045:                        break;
        !          1046:                }
        !          1047:        }
        !          1048:        if (some) {
        !          1049:                nx += dx[ndxy];
        !          1050:                ny += dy[ndxy];
        !          1051:                ndxy++;
        !          1052:                defx = dx[ndxy-1];
        !          1053:                defy = dy[ndxy-1];
        !          1054:        } else {
        !          1055:                defx *= xtab[hvmode];
        !          1056:                defy *= ytab[hvmode];
        !          1057:                dx[ndxy] = defx;
        !          1058:                dy[ndxy] = defy;
        !          1059:                ndxy++;
        !          1060:                nx += defx;
        !          1061:                ny += defy;
        !          1062:        }
        !          1063:        prevdx = defx;
        !          1064:        prevdy = defy;
        !          1065:        if (chop) {
        !          1066:                if (chop == 1 && chop1 == 0)    /* just said "chop", so use default */
        !          1067:                        chop1 = chop2 = getvar(lookup("circlerad"));
        !          1068:                theta = atan2((float) defy, (float) defx);
        !          1069:                x0 = chop1 * cos(theta);
        !          1070:                y0 = chop1 * sin(theta);
        !          1071:                curx += x0;
        !          1072:                cury += y0;
        !          1073:                x1 = chop2 * cos(theta);
        !          1074:                y1 = chop2 * sin(theta);
        !          1075:                nx -= x1;
        !          1076:                ny -= y1;
        !          1077:                dx[0] -= x0;
        !          1078:                dy[0] -= y0;
        !          1079:                dx[ndxy-1] -= x1;
        !          1080:                dy[ndxy-1] -= y1;
        !          1081:                if(dbg)printf("chopping %d %d %d %d; cur=%d,%d end=%d,%d\n",
        !          1082:                        x0, y0, x1, y1, curx, cury, nx, ny);
        !          1083:        }
        !          1084:        p = makenode(type, 5 + 2 * ndxy);
        !          1085:        curx = p->o_val[0] = nx;
        !          1086:        cury = p->o_val[1] = ny;
        !          1087:        if (head || type == ARROW) {
        !          1088:                p->o_val[2] = prevw;
        !          1089:                p->o_val[3] = prevh;
        !          1090:                if (head == 0)
        !          1091:                        head = HEAD2;   /* default arrow head */
        !          1092:        }
        !          1093:        p->o_attr = head | invis;
        !          1094:        p->o_val[4] = ndxy;
        !          1095:        nx = p->o_x;
        !          1096:        ny = p->o_y;
        !          1097:        for (i = 0, j = 5; i < ndxy; i++, j += 2) {
        !          1098:                p->o_val[j] = dx[i];
        !          1099:                p->o_val[j+1] = dy[i];
        !          1100:                extreme(nx += dx[i], ny += dy[i]);
        !          1101:        }
        !          1102:        p->o_dotdash = ddtype;
        !          1103:        p->o_ddval = ddval;
        !          1104:        if (dbg) {
        !          1105:                printf("S or L from %d %d to %d %d with %d elements:\n", p->o_x, p->o_y, curx, cury, ndxy);
        !          1106:                for (i = 0, j = 5; i < ndxy; i++, j += 2)
        !          1107:                        printf("%d %d\n", p->o_val[j], p->o_val[j+1]);
        !          1108:        }
        !          1109:        extreme(p->o_x, p->o_y);
        !          1110:        extreme(curx, cury);
        !          1111:        return(p);
        !          1112: }
        !          1113: 
        !          1114: struct obj *splinegen(type)
        !          1115: {
        !          1116:        linegen(type);
        !          1117: }
        !          1118: 
        !          1119: struct obj *movegen(type)
        !          1120: {
        !          1121:        static int prevdx, prevdy;
        !          1122:        int i, dx, dy, some;
        !          1123:        int defx, defy;
        !          1124:        struct obj *p;
        !          1125:        struct obj *ppos;
        !          1126:        static int xtab[] = { 1, 0, -1, 0 };    /* R=0, U=1, L=2, D=3 */
        !          1127:        static int ytab[] = { 0, 1, 0, -1 };
        !          1128: 
        !          1129:        defx = getvar(lookup("movewid"));
        !          1130:        defy = getvar(lookup("moveht"));
        !          1131:        dx = dy = some = 0;
        !          1132:        for (i = 0; i < nattr; i++) {
        !          1133:                switch (attr[i].a_type) {
        !          1134:                case LJUST: case RJUST: case CENTER: case SPREAD: case FILL: case ABOVE: case BELOW:
        !          1135:                        savetext(attr[i].a_type, attr[i].a_val);
        !          1136:                        break;
        !          1137:                case SAME:
        !          1138:                        dx = prevdx;
        !          1139:                        dy = prevdy;
        !          1140:                        some++;
        !          1141:                        break;
        !          1142:                case LEFT:
        !          1143:                        dx -= (attr[i].a_val==0) ? defx : attr[i].a_val;
        !          1144:                        some++;
        !          1145:                        hvmode = L_DIR;
        !          1146:                        break;
        !          1147:                case RIGHT:
        !          1148:                        dx += (attr[i].a_val==0) ? defx : attr[i].a_val;
        !          1149:                        some++;
        !          1150:                        hvmode = R_DIR;
        !          1151:                        break;
        !          1152:                case UP:
        !          1153:                        dy += (attr[i].a_val==0) ? defy : attr[i].a_val;
        !          1154:                        some++;
        !          1155:                        hvmode = U_DIR;
        !          1156:                        break;
        !          1157:                case DOWN:
        !          1158:                        dy -= (attr[i].a_val==0) ? defy : attr[i].a_val;
        !          1159:                        some++;
        !          1160:                        hvmode = D_DIR;
        !          1161:                        break;
        !          1162:                case TO:
        !          1163:                        ppos = (struct obj *) attr[i].a_val;
        !          1164:                        dx = ppos->o_x - curx;
        !          1165:                        dy = ppos->o_y - cury;
        !          1166:                        some++;
        !          1167:                        break;
        !          1168:                case BY:
        !          1169:                        ppos = (struct obj *) attr[i].a_val;
        !          1170:                        dx = ppos->o_x;
        !          1171:                        dy = ppos->o_y;
        !          1172:                        some++;
        !          1173:                        break;
        !          1174:                case FROM:
        !          1175:                case AT:
        !          1176:                        ppos = (struct obj *) attr[i].a_val;
        !          1177:                        curx = ppos->o_x;
        !          1178:                        cury = ppos->o_y;
        !          1179:                        break;
        !          1180:                }
        !          1181:        }
        !          1182:        if (some) {
        !          1183:                defx = dx;
        !          1184:                defy = dy;
        !          1185:        } else {
        !          1186:                defx *= xtab[hvmode];
        !          1187:                defy *= ytab[hvmode];
        !          1188:        }
        !          1189:        prevdx = defx;
        !          1190:        prevdy = defy;
        !          1191:        extreme(curx, cury);
        !          1192:        curx += defx;
        !          1193:        cury += defy;
        !          1194:        extreme(curx, cury);
        !          1195:        p = makenode(MOVE, 0);
        !          1196:        dprintf("M %d %d\n", curx, cury);
        !          1197:        return(p);
        !          1198: }
        !          1199: 
        !          1200: struct obj *textgen(s, garb)
        !          1201: {
        !          1202:        static int prevdx, prevdy, prevrad = 10;
        !          1203:        int i, dx, dy, some, type;
        !          1204:        struct obj *p, *ppos;
        !          1205: 
        !          1206:        type = 'C';
        !          1207:        some = dx = dy = 0;
        !          1208:        for (i = 0; i < nattr; i++)
        !          1209:                switch (attr[i].a_type) {
        !          1210:                case LEFT:
        !          1211:                        dx -= attr[i].a_val;
        !          1212:                        some++;
        !          1213:                        break;
        !          1214:                case RIGHT:
        !          1215:                        dx += attr[i].a_val;
        !          1216:                        some++;
        !          1217:                        break;
        !          1218:                case UP:
        !          1219:                        dy += attr[i].a_val;
        !          1220:                        some++;
        !          1221:                        break;
        !          1222:                case DOWN:
        !          1223:                        dy -= attr[i].a_val;
        !          1224:                        some++;
        !          1225:                        break;
        !          1226:                case AT:
        !          1227:                        ppos = (struct obj *) attr[i].a_val;
        !          1228:                        curx = ppos->o_x;
        !          1229:                        cury = ppos->o_y;
        !          1230:                        break;
        !          1231:                case LJUST:
        !          1232:                        type = 'L';
        !          1233:                        break;
        !          1234:                case RJUST:
        !          1235:                        type = 'R';
        !          1236:                        break;
        !          1237:                case SPREAD:
        !          1238:                        type = 'S';
        !          1239:                        break;
        !          1240:                case FILL:
        !          1241:                        type = 'F';
        !          1242:                        break;
        !          1243:                case ABOVE:
        !          1244:                        type = 'A';
        !          1245:                        break;
        !          1246:                case BELOW:
        !          1247:                        type = 'B';
        !          1248:                        break;
        !          1249:                }
        !          1250:        dprintf("T %c %s\n", type, s);
        !          1251:        if (some) {
        !          1252:                prevdx = dx;
        !          1253:                prevdy = dy;
        !          1254:        } else {
        !          1255:                dx = prevdx;
        !          1256:                dy = prevdy;
        !          1257:        }
        !          1258:        extreme(curx, cury);
        !          1259:        curx += dx;
        !          1260:        cury += dy;
        !          1261:        extreme(curx, cury);    /* wrong */
        !          1262:        p = makenode(TEXT, 2);
        !          1263:        p->o_val[0] = s;
        !          1264:        p->o_val[1] = type;
        !          1265:        return(p);
        !          1266: }
        !          1267: 
        !          1268: char *tostring(s)
        !          1269: register char *s;
        !          1270: {
        !          1271:        register char *p;
        !          1272: 
        !          1273:        p = malloc(strlen(s)+1);
        !          1274:        if (p == NULL) {
        !          1275:                fprintf(stderr, "pic: out of space in tostring on %s", s);
        !          1276:                exit(1);
        !          1277:        }
        !          1278:        strcpy(p, s);
        !          1279:        return(p);
        !          1280: }
        !          1281: 
        !          1282: makevar(s, t, v)       /* make variable named s in table */
        !          1283: char *s;
        !          1284: int t;
        !          1285: int v; /* maybe wrong later */
        !          1286: {
        !          1287:        int i;
        !          1288: 
        !          1289:        for (i = 0; i < nsymtab; i++)
        !          1290:                if (strcmp(s, symtab[i].s_name) == 0)
        !          1291:                        return(i);
        !          1292:        if (nsymtab >= SYMTAB) 
        !          1293:                yyerror("symbol table overflow (%d)", SYMTAB);
        !          1294:        symtab[nsymtab].s_name = tostring(s);
        !          1295:        symtab[nsymtab].s_type = t;
        !          1296:        symtab[nsymtab].s_val = v;
        !          1297:        return(nsymtab++);
        !          1298: }
        !          1299: 
        !          1300: lookup(s)      /* find s in symtab */
        !          1301: char *s;
        !          1302: {
        !          1303:        int i;
        !          1304: 
        !          1305:        for (i = 0; i < nsymtab; i++)
        !          1306:                if (strcmp(s, symtab[i].s_name) == 0)
        !          1307:                        return(i);
        !          1308:        return(-1);
        !          1309: }
        !          1310: 
        !          1311: struct obj *makepos(x, y)      /* make a position cell */
        !          1312: coord x;
        !          1313: coord y;
        !          1314: {
        !          1315:        struct obj *p;
        !          1316: 
        !          1317:        p = makenode(PLACE, 0);
        !          1318:        p->o_x = x;
        !          1319:        p->o_y = y;
        !          1320:        return(p);
        !          1321: }
        !          1322: 
        !          1323: struct obj *getpos(p, corner)  /* find position of point */
        !          1324: struct obj *p;
        !          1325: int corner;
        !          1326: {
        !          1327:        coord x, y, x1, y1;
        !          1328: 
        !          1329:        dprintf("getpos %o %d\n", p, corner);
        !          1330:        x = p->o_x;
        !          1331:        y = p->o_y;
        !          1332:        x1 = p->o_val[0];
        !          1333:        y1 = p->o_val[1];
        !          1334:        switch (p->o_type) {
        !          1335:        case PLACE:
        !          1336:                break;
        !          1337:        case BOX:
        !          1338:                switch (corner) {
        !          1339:                case NORTH:     y += y1 / 2; break;
        !          1340:                case SOUTH:     y -= y1 / 2; break;
        !          1341:                case EAST:      x += x1 / 2; break;
        !          1342:                case WEST:      x -= x1 / 2; break;
        !          1343:                case NE:        x += x1 / 2; y += y1 / 2; break;
        !          1344:                case SW:        x -= x1 / 2; y -= y1 / 2; break;
        !          1345:                case SE:        x += x1 / 2; y -= y1 / 2; break;
        !          1346:                case NW:        x -= x1 / 2; y += y1 / 2; break;
        !          1347:                }
        !          1348:                break;
        !          1349:        case CIRCLE:
        !          1350:        case ELLIPSE:
        !          1351:                switch (corner) {
        !          1352:                case NORTH:     y += y1; break;
        !          1353:                case SOUTH:     y -= y1; break;
        !          1354:                case EAST:      x += x1; break;
        !          1355:                case WEST:      x -= x1; break;
        !          1356:                case NE:        x += 0.707 * x1; y += 0.707 * y1; break;
        !          1357:                case SE:        x += 0.707 * x1; y -= 0.707 * y1; break;
        !          1358:                case NW:        x -= 0.707 * x1; y += 0.707 * y1; break;
        !          1359:                case SW:        x -= 0.707 * x1; y -= 0.707 * y1; break;
        !          1360:                }
        !          1361:                break;
        !          1362:        case LINE:
        !          1363:        case ARROW:
        !          1364:        case MOVE:
        !          1365:                switch (corner) {
        !          1366:                case START:     break;  /* already in place */
        !          1367:                case END:       x = x1; y = y1; break;
        !          1368:                case CENTER:    x = (x+x1)/2; y = (y+y1)/2; break;
        !          1369:                case NORTH:     if (y1 > y) { x = x1; y = y1; } break;
        !          1370:                case SOUTH:     if (y1 < y) { x = x1; y = y1; } break;
        !          1371:                case EAST:      if (x1 > x) { x = x1; y = y1; } break;
        !          1372:                case WEST:      if (x1 < x) { x = x1; y = y1; } break;
        !          1373:                }
        !          1374:                break;
        !          1375:        case ARC:
        !          1376:                switch (corner) {
        !          1377:                case START:
        !          1378:                        if (p->o_attr & CW_ARC) {
        !          1379:                                x = p->o_val[2]; y = p->o_val[3];
        !          1380:                        } else {
        !          1381:                                x = x1; y = y1;
        !          1382:                        }
        !          1383:                        break;
        !          1384:                case END:
        !          1385:                        if (p->o_attr & CW_ARC) {
        !          1386:                                x = x1; y = y1;
        !          1387:                        } else {
        !          1388:                                x = p->o_val[2]; y = p->o_val[3];
        !          1389:                        }
        !          1390:                        break;
        !          1391:                }
        !          1392:                break;
        !          1393:        case SPLINE:
        !          1394:                switch (corner) {
        !          1395:                case END:
        !          1396:                        x = p->o_val[0];
        !          1397:                        y = p->o_val[1];
        !          1398:                        break;
        !          1399:                }
        !          1400:                break;
        !          1401:        }
        !          1402:        dprintf("getpos returns %d %d\n", x, y);
        !          1403:        return(makepos(x, y));
        !          1404: }
        !          1405: 
        !          1406: struct obj *gethere(n) /* make a place for curx,cury */
        !          1407: {
        !          1408:        dprintf("gethere %d %d\n", curx, cury);
        !          1409:        return(makepos(curx, cury));
        !          1410: }
        !          1411: 
        !          1412: struct obj *getlast(n, t)      /* find n-th previous occurrence of type t */
        !          1413: int n, t;
        !          1414: {
        !          1415:        int i, k;
        !          1416:        struct obj *p;
        !          1417: 
        !          1418:        k = n;
        !          1419:        for (i = nobj-1; i >= 0; i--) {
        !          1420:                p = objlist[i];
        !          1421:                if (p->o_type != t)
        !          1422:                        continue;
        !          1423:                if (--k > 0)
        !          1424:                        continue;       /* not there yes */
        !          1425:                dprintf("got a last of x,y= %d,%d\n", p->o_x, p->o_y);
        !          1426:                return(p);
        !          1427:        }
        !          1428:        yyerror("there is no %dth last", n);
        !          1429: }
        !          1430: 
        !          1431: struct obj *getfirst(n, t)     /* find n-th occurrence of type t */
        !          1432: int n, t;
        !          1433: {
        !          1434:        int i, k;
        !          1435:        struct obj *p;
        !          1436: 
        !          1437:        k = n;
        !          1438:        for (i = 0; i < nobj; i++) {
        !          1439:                p = objlist[i];
        !          1440:                if (p->o_type != t)
        !          1441:                        continue;
        !          1442:                if (--k > 0)
        !          1443:                        continue;       /* not there yes */
        !          1444:                dprintf("got a first of x,y= %d,%d\n", p->o_x, p->o_y);
        !          1445:                return(p);
        !          1446:        yyerror("there is no %dth ", n);
        !          1447:        }
        !          1448: }
        !          1449: 
        !          1450: struct obj *fixpos(p, x, y)
        !          1451: struct obj *p;
        !          1452: coord x, y;
        !          1453: {
        !          1454:        dprintf("fixpos returns %d %d\n", p->o_x + x, p->o_y + y);
        !          1455:        return(makepos(p->o_x + x, p->o_y + y));
        !          1456: }
        !          1457: 
        !          1458: struct obj *makenode(type, n)
        !          1459: int type, n;
        !          1460: {
        !          1461:        struct obj *p;
        !          1462: 
        !          1463:        p = (struct obj *) malloc(sizeof(struct obj) + (n-1)*sizeof(coord));
        !          1464:        if (p == NULL) {
        !          1465:                fprintf(stderr, "pic: out of space in makenode\n");
        !          1466:                exit(1);
        !          1467:        }
        !          1468:        p->o_type = type;
        !          1469:        p->o_count = n;
        !          1470:        p->o_mode = hvmode;
        !          1471:        p->o_x = curx;
        !          1472:        p->o_y = cury;
        !          1473:        p->o_nt1 = ntext1;
        !          1474:        p->o_nt2 = ntext;
        !          1475:        ntext1 = ntext; /* ready for next caller */
        !          1476:        p->o_attr = p->o_dotdash = p->o_ddval = 0;
        !          1477:        if (nobj >= MAXOBJ) {
        !          1478:                fprintf(stderr, "pic: objlist overflow\n");
        !          1479:                exit(1);
        !          1480:        }
        !          1481:        objlist[nobj++] = p;
        !          1482:        return(p);
        !          1483: }
        !          1484: 
        !          1485: extreme(x, y)  /* record max and min x and y values */
        !          1486: {
        !          1487:        if (x > xmax)
        !          1488:                xmax = x;
        !          1489:        if (y > ymax)
        !          1490:                ymax = y;
        !          1491:        if (x < xmin)
        !          1492:                xmin = x;
        !          1493:        if (y < ymin)
        !          1494:                ymin = y;
        !          1495: }

unix.superglobalmegacorp.com

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