Annotation of researchv9/jtools/src/Jpic/pic1.c, revision 1.1.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.