|
|
1.1 ! root 1: /* Copyright (c) 1988 AT&T */ ! 2: /* All Rights Reserved */ ! 3: ! 4: /* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T */ ! 5: /* The copyright notice above does not evidence any */ ! 6: /* actual or intended publication of such source code. */ ! 7: ! 8: /* @(#)picasso:misc.c 1.0 */ ! 9: #include "picasso.h" ! 10: #include "y.tab.h" ! 11: ! 12: extern int pic_compat; ! 13: extern int batch; ! 14: ! 15: double getcomp(p, t) /* return component of a position; these must now be */ ! 16: obj *p; /* transformed as there is no later chance to do so. */ ! 17: int t; ! 18: { ! 19: float bnd[4]; ! 20: ! 21: switch (t) { ! 22: case DOTX: return Xformx(p, 1, p->o_x, p->o_y); ! 23: case DOTY: return Xformy(p, 1, p->o_x, p->o_y); ! 24: case DOTRAD: ! 25: switch (p->o_type) { ! 26: case SECTOR: ! 27: case ARC: ! 28: case BOX: ! 29: case ARROW: ! 30: case LINE: return p->o_val[N_VAL].f; ! 31: case CIRCLE: ! 32: case ELLIPSE: break; /* fall through to DOTWID case */ ! 33: } ! 34: case DOTHT: ! 35: case DOTWID: if (p->o_type <= TEXT) { ! 36: get_bounds(p, bnd, 1); ! 37: if (t == DOTHT) ! 38: return (bnd[3] - bnd[1]); ! 39: else ! 40: return (bnd[2] - bnd[0]); ! 41: } ! 42: } ! 43: yyerror("can't happen getcomp"); ! 44: } ! 45: ! 46: exprsave(f) ! 47: double f; ! 48: { ! 49: if (nexpr >= nexprlist) ! 50: exprlist = (float *) grow((char *)exprlist, "exprlist", ! 51: nexprlist += 256, sizeof(float)); ! 52: exprlist[nexpr] = f; ! 53: return ++nexpr; ! 54: } ! 55: ! 56: char *sprintgen(fmt) ! 57: char *fmt; ! 58: { ! 59: char buf[1000]; ! 60: ! 61: sprintf (buf, fmt, exprlist[0], exprlist[1], exprlist[2], ! 62: exprlist[3], exprlist[4]); ! 63: nexpr = 0; ! 64: free(fmt); ! 65: return tostring(buf); ! 66: } ! 67: ! 68: printexpr(f) /* print expression for debugging */ ! 69: double f; ! 70: { ! 71: fprintf(stderr, "%g\n", f); ! 72: } ! 73: ! 74: printpos(p) /* print position for debugging */ ! 75: obj *p; ! 76: { ! 77: double x, y; ! 78: ! 79: x = Xformx(p, 1, p->o_x, p->o_y); ! 80: y = Xformy(p, 0, p->o_x, p->o_y); ! 81: fprintf(stderr, "%g, %g\n", x, y); ! 82: } ! 83: ! 84: char *tostring(s) ! 85: register char *s; ! 86: { ! 87: register char *p; ! 88: ! 89: p = malloc(strlen(s)+1); ! 90: if (p == NULL) { ! 91: yyerror("out of space in tostring on %s", s); ! 92: exit(1); ! 93: } ! 94: strcpy(p, s); ! 95: return(p); ! 96: } ! 97: ! 98: obj *makepos(x, y, corner, q) /* make a position cell */ ! 99: double x, y; ! 100: int corner; ! 101: obj *q; ! 102: { ! 103: obj *p; ! 104: ! 105: p = makenode(PLACE, 1, 0); ! 106: if (q) ! 107: p->o_parent = q; ! 108: p->o_x = x; ! 109: p->o_y = y; ! 110: p->o_val[0].f = corner; ! 111: return(p); ! 112: } ! 113: ! 114: obj *makebetween(f, p1, p2) /* make position between p1 and p2 */ ! 115: double f; /* again, transforms must be applied */ ! 116: obj *p1, *p2; ! 117: { ! 118: obj *p; ! 119: double x1, y1, x2, y2; ! 120: ! 121: p = makenode(PLACE, 3, 0); ! 122: x1 = Xformx(p1, 1, p1->o_x, p1->o_y); ! 123: y1 = Xformy(p1, 0, p1->o_x, p1->o_y); ! 124: x2 = Xformx(p2, 1, p2->o_x, p2->o_y); ! 125: y2 = Xformy(p2, 0, p2->o_x, p2->o_y); ! 126: p->o_x = x1 + f * (x2 - x1); ! 127: p->o_y = y1 + f * (y2 - y1); ! 128: p->o_val[0].f = f; ! 129: p->o_val[1].o = p1; ! 130: p->o_val[2].o = p2; ! 131: return(p); ! 132: } ! 133: ! 134: int xdelta[8] = {1,1,1,0,-1,-1,-1,0}, ! 135: ydelta[8] = {-1,0,1,1,1,0,-1,-1}; ! 136: ! 137: obj *getnth(p, nth) /* find nth point of an object */ ! 138: obj *p; ! 139: int nth; ! 140: { ! 141: float x, y; ! 142: int n = nth; ! 143: ! 144: switch (p->o_type) { ! 145: default: if (n != 1) ! 146: yyerror("object has only 1 point defined"); ! 147: return p; ! 148: case ARC: if (n > 2) { ! 149: yyerror("arcs have only 2 points defined"); ! 150: return p; ! 151: } ! 152: /* else fall through to SECTOR case */ ! 153: case SECTOR: if ((n %= 3) == 0) ! 154: return p; ! 155: else if (n == 1) { ! 156: x = p->o_val[N_VAL+2].f; ! 157: y = p->o_val[N_VAL+3].f; ! 158: } ! 159: else { ! 160: x = p->o_val[N_VAL+4].f; ! 161: y = p->o_val[N_VAL+5].f; ! 162: } ! 163: break; ! 164: case BLOCK: while (n--) { ! 165: p = p->o_next; ! 166: if (p->o_type <= TEXT) ! 167: continue; ! 168: else if (p->o_type == BLOCKEND) { ! 169: yyerror("[] has less than %d objects", ! 170: nth); ! 171: p = p->o_parent; ! 172: } ! 173: } ! 174: return p; ! 175: case BOX: n %= 8; ! 176: x = p->o_x + xdelta[n] * p->o_wid / 2; ! 177: y = p->o_y + ydelta[n] * p->o_ht / 2; ! 178: break; ! 179: case ARROW: ! 180: case LINE: ! 181: case SPLINE: if (--n > p->o_val[N_VAL+3].f) { ! 182: yyerror("line has less than %d points", nth); ! 183: return p; ! 184: } ! 185: x = p->o_val[N_VAL + 4 + 2 * n].f; ! 186: y = p->o_val[N_VAL + 5 + 2 * n].f; ! 187: break; ! 188: case CIRCLE: ! 189: case ELLIPSE: n %= 8; ! 190: x = xdelta[n] * p->o_wid / 2; ! 191: y = ydelta[n] * p->o_ht / 2; ! 192: if (n % 2 == 0) { ! 193: x *= M_SQRT1_2; ! 194: y *= M_SQRT1_2; ! 195: } ! 196: x += p->o_x; ! 197: y += p->o_y; ! 198: break; ! 199: } ! 200: /* DBK--Here also there is a question of whether x and y should ! 201: be transformed */ ! 202: return makepos(x, y, nth, p); ! 203: } ! 204: ! 205: obj *getpos(p, corner) /* find position of point */ ! 206: obj *p; ! 207: int corner; ! 208: { ! 209: float x, y; ! 210: ! 211: if (pic_compat && (p->o_type == CIRCLE || p->o_type == ELLIPSE) && ! 212: (corner == NE || corner == NW || corner == SW || corner == SE)) ! 213: return getnth(p, corner == NE ? 2 : corner == NW ? 4 : ! 214: corner == SW ? 6 : 8); ! 215: if (corner == -1 ) ! 216: if (pic_compat && (p->o_type == LINE || p->o_type == ARROW || ! 217: p->o_type == SPLINE)) ! 218: corner = START; ! 219: else ! 220: return p; ! 221: whatpos(p, corner, &x, &y); ! 222: return makepos(x,y,corner,(corner < EAST || corner > SW)? p: (obj *)0); ! 223: } ! 224: ! 225: whatpos(p, corner, px, py) /* what is the position (no side effect) */ ! 226: obj *p; ! 227: int corner; ! 228: float *px, *py; ! 229: { ! 230: float x, y, bnd[4]; ! 231: ! 232: if (corner >= EAST && corner <= SW) { ! 233: get_bounds(p, bnd, 1); ! 234: switch (corner) { ! 235: case NE: x = bnd[2]; y = bnd[3]; break; ! 236: case SW: x = bnd[0]; y = bnd[1]; break; ! 237: case SE: x = bnd[2]; y = bnd[1]; break; ! 238: case NW: x = bnd[0]; y = bnd[3]; break; ! 239: case NORTH: x = (bnd[0]+bnd[2])/2; y = bnd[3]; break; ! 240: case SOUTH: x = (bnd[0]+bnd[2])/2; y = bnd[1]; break; ! 241: case EAST: x = bnd[2]; y = (bnd[1]+bnd[3])/2; break; ! 242: case WEST: x = bnd[0]; y = (bnd[1]+bnd[3])/2; break; ! 243: } ! 244: } ! 245: else { /* DBK--note that get_bounds returns the transformed position, ! 246: but the following calculations do not!! */ ! 247: x = p->o_x; ! 248: y = p->o_y; ! 249: ! 250: /* futz around for special cases: */ ! 251: ! 252: switch (p->o_type) { ! 253: case BLOCK: if (corner == START) ! 254: whatpos(p->o_next, START, &x, &y); ! 255: else if (corner == END) ! 256: whatpos(p->o_val[N_VAL+1].o->o_prev,END,&x,&y); ! 257: break; ! 258: case ARC: if (corner == START) { ! 259: x = p->o_val[N_VAL+2].f; ! 260: y = p->o_val[N_VAL+3].f; ! 261: } ! 262: else if (corner == END) { ! 263: x = p->o_val[N_VAL+4].f; ! 264: y = p->o_val[N_VAL+5].f; ! 265: } ! 266: break; ! 267: case LINE: ! 268: case SPLINE: ! 269: case ARROW: switch (corner) { ! 270: int n; ! 271: case START: x = p->o_val[N_VAL+4].f; ! 272: y = p->o_val[N_VAL+5].f; ! 273: break; ! 274: case END: n = N_VAL + 4 + 2*p->o_val[N_VAL+3].f; ! 275: x = p->o_val[n].f; ! 276: y = p->o_val[n+1].f; ! 277: break; ! 278: } ! 279: break; ! 280: } ! 281: } ! 282: *px = x; ! 283: *py = y; ! 284: return 1; ! 285: } ! 286: ! 287: obj *gethere() /* make a place for curx,cury */ ! 288: { ! 289: return(makepos(curx, cury, 0, (obj *)0)); ! 290: } ! 291: ! 292: obj *getlast(n, t) /* find n-th previous occurrence of type t */ ! 293: int n, t; ! 294: { ! 295: int k; ! 296: obj *p; ! 297: ! 298: k = n; ! 299: if (t == TEXTOBJ) /* for purely syntactical reasons */ ! 300: t = TEXT; ! 301: for (p = objtail->o_prev; p != objhead; p = p->o_prev) { ! 302: if (p->o_type == BLOCKEND) { ! 303: p = p->o_parent; ! 304: if (t != BLOCK && t != OBJECT) ! 305: continue; ! 306: } ! 307: if (t == OBJECT && p->o_type > TEXT) ! 308: continue; ! 309: if (t != OBJECT && p->o_type != t) ! 310: continue; ! 311: if (--k > 0) ! 312: continue; /* not there yet */ ! 313: return(p); ! 314: } ! 315: yyerror("there is no %dth last", n); ! 316: return(NULL); ! 317: } ! 318: ! 319: obj *getfirst(n, t) /* find n-th occurrence of type t */ ! 320: int n, t; ! 321: { ! 322: int k; ! 323: obj *p; ! 324: ! 325: k = n; ! 326: if (t == TEXTOBJ) ! 327: t = TEXT; ! 328: for (p = objhead->o_next; p != objtail; p = p->o_next) { ! 329: if (p->o_type == BLOCK ! 330: && t != BLOCK && t != OBJECT) { /* skip block, */ ! 331: if (p->o_val[N_VAL].o != NULL) /* unless it's */ ! 332: p = p->o_val[N_VAL].o; /* still active */ ! 333: continue; ! 334: } ! 335: if (t == OBJECT && p->o_type > TEXT) ! 336: continue; ! 337: if (t != OBJECT && p->o_type != t) ! 338: continue; ! 339: if (--k > 0) ! 340: continue; /* not there yet */ ! 341: return(p); ! 342: } ! 343: yyerror("there is no %dth", n); ! 344: return(NULL); ! 345: } ! 346: ! 347: double getblkvar(p, s) /* find variable s2 in block p */ ! 348: obj *p; ! 349: char *s; ! 350: { ! 351: YYSTYPE y, getblk(); ! 352: ! 353: y = getblk(p, s); ! 354: free(s); ! 355: return y.f; ! 356: } ! 357: ! 358: obj *getblock(p, s) /* find variable s in block p */ ! 359: obj *p; ! 360: char *s; ! 361: { ! 362: YYSTYPE y, getblk(); ! 363: ! 364: y = getblk(p, s); ! 365: free(s); ! 366: return y.o; ! 367: } ! 368: ! 369: YYSTYPE getblk(p, s) /* find union type for s in p */ ! 370: obj *p; ! 371: char *s; ! 372: { ! 373: static YYSTYPE bug; ! 374: struct symtab *stp; ! 375: ! 376: if (p->o_type != BLOCK) { ! 377: yyerror(".%s is not in that block", s); ! 378: return(bug); ! 379: } ! 380: for (stp = p->o_val[N_VAL+1].s; stp != NULL; stp = stp->s_next) ! 381: if (strcmp(s, stp->s_name) == 0) ! 382: return(stp->s_val); ! 383: yyerror("there is no .%s in that []", s); ! 384: return(bug); ! 385: } ! 386: ! 387: obj *fixpos(p, x, y) /* this, addpos & subpos SHOULD be altered to give */ ! 388: obj *p; /* o_x,o_y as offset from position of p, with p as */ ! 389: double x, y; /* o_parent, but I haven't yet worked out the xform. */ ! 390: { ! 391: #if 1 ! 392: /* DBK: 3/21/90 -- comment out the following if clause. It has the effect ! 393: of changing A in the expression A + x,y !!! ! 394: if (p->o_type == PLACE) { ! 395: p->o_x += x; ! 396: p->o_y += y; ! 397: return p; ! 398: } ! 399: end of commented out code *************/ ! 400: x += Xformx(p, 1, p->o_x, p->o_y); ! 401: y += Xformy(p, 0, p->o_x, p->o_y); ! 402: #else ! 403: if (p->o_type == PLACE) { ! 404: x += p->o_x; ! 405: y += p->o_y; ! 406: } ! 407: else { ! 408: x += Xformx(p, 1, p->o_x, p->o_y); ! 409: y += Xformy(p, 0, p->o_x, p->o_y); ! 410: } ! 411: #endif ! 412: return makepos(x, y, 0, (obj *)0); ! 413: } ! 414: ! 415: obj *addpos(p, q) ! 416: obj *p, *q; ! 417: { ! 418: double x, y; ! 419: ! 420: x = Xformx(q, 1, q->o_x, q->o_y); ! 421: y = Xformy(q, 0, q->o_x, q->o_y); ! 422: /* DBK: see above ! 423: if (p->o_type == PLACE) { ! 424: p->o_x += x; ! 425: p->o_y += y; ! 426: return p; ! 427: } ! 428: */ ! 429: x += Xformx(p, 1, p->o_x, p->o_y); ! 430: y += Xformy(p, 0, p->o_x, p->o_y); ! 431: return makepos(x, y, 0, (obj *)0); ! 432: } ! 433: ! 434: obj *subpos(p, q) ! 435: obj *p, *q; ! 436: { ! 437: double x, y; ! 438: ! 439: x = Xformx(q, 1, q->o_x, q->o_y); ! 440: y = Xformy(q, 0, q->o_x, q->o_y); ! 441: /* DBK: see above ! 442: if (p->o_type == PLACE) { ! 443: p->o_x -= x; ! 444: p->o_y -= y; ! 445: return p; ! 446: } ! 447: */ ! 448: x -= Xformx(p, 1, p->o_x, p->o_y); ! 449: y -= Xformy(p, 0, p->o_x, p->o_y); ! 450: return makepos(x, y, 0, (obj *)0); ! 451: } ! 452: ! 453: obj *makenode(type, n, layer) ! 454: int type, n, layer; ! 455: { ! 456: obj *p; ! 457: ! 458: if (objbuf && batch) ! 459: print_buf(); ! 460: p = (obj *) calloc(1, sizeof(obj) + (n-1)*sizeof(YYSTYPE)); ! 461: if (p == NULL) { ! 462: yyerror("out of space in makenode"); ! 463: exit(1); ! 464: } ! 465: if (n > 65535) ! 466: yyerror("making excessively large object"); ! 467: p->o_next = objtail; ! 468: p->o_prev = objtail->o_prev; ! 469: p->o_prev->o_next = objtail->o_prev = p; ! 470: p->o_parent = cur_block; ! 471: p->o_x = curx; ! 472: p->o_y = cury; ! 473: p->o_nt1 = ntext1; ! 474: p->o_nt2 = ntext; ! 475: p->o_text = -1; ! 476: #if 1 ! 477: /* force all strings in object to have same justification */ ! 478: { ! 479: int jflags, lastf; ! 480: jflags = RJUST|LJUST|CENTER|ABOVE|BELOW; ! 481: lastf = text[ntext-1].t_type & jflags; ! 482: for ( ; ntext1 < ntext; ntext1++) ! 483: text[ntext1].t_type = text[ntext1].t_type & ~ jflags | lastf; ! 484: } ! 485: #endif ! 486: ntext1 = ntext; /* ready for next caller */ ! 487: if (layer < -128) ! 488: layer = -128; ! 489: else if (layer > 127) ! 490: layer = 127; ! 491: if ((p->o_layer = layer) > 0 && layer > top_layer) ! 492: top_layer = layer; ! 493: if ((p->o_type = type) <= TEXT) { ! 494: p->o_mxx = p->o_myy = 1.0; /* initialize xform matrix */ ! 495: p->o_size = n; /* keep count, for copies */ ! 496: } ! 497: return(p); ! 498: } ! 499: ! 500: freenode (p) /* free space occupied by object p */ ! 501: obj *p; ! 502: { ! 503: obj *q, *q1; ! 504: ! 505: if (p->o_type == BLOCK) { /* I think there's */ ! 506: freesymtab(p->o_val[N_VAL+1].s); /* a bug here, for */ ! 507: q = p->o_val[N_VAL].o; /* nested blocks. */ ! 508: p->o_prev->o_next = q->o_next; ! 509: q->o_next->o_prev = p->o_prev; ! 510: q->o_next = (obj *)NULL; ! 511: for (q = p->o_next; q != NULL; ) { ! 512: if (q->o_type == BLOCK) ! 513: freesymtab(q->o_val[N_VAL+1].s); ! 514: q1 = q; ! 515: q = q->o_next; ! 516: free(q1); ! 517: } ! 518: } ! 519: else { ! 520: p->o_prev->o_next = p->o_next; ! 521: p->o_next->o_prev = p->o_prev; ! 522: } ! 523: free (p); ! 524: if (!objbuf) redo_gbox = 1; /* page boundaries are now suspect */ ! 525: } ! 526: ! 527: extreme(x, y, bbox) /* record max and min x and y values */ ! 528: double x, y; ! 529: float *bbox; ! 530: { ! 531: if ((float)x < bbox[0]) bbox[0] = x; ! 532: if ((float)y < bbox[1]) bbox[1] = y; ! 533: if ((float)x > bbox[2]) bbox[2] = x; ! 534: if ((float)y > bbox[3]) bbox[3] = y; ! 535: } ! 536: ! 537: track_bounds(x0, y0, x1, y1) /* insert a bounding box into the global box */ ! 538: double x0, y0, x1, y1; ! 539: { ! 540: if (x0 < Gbox[0]) Gbox[0] = x0; ! 541: if (y0 < Gbox[1]) Gbox[1] = y0; ! 542: if (x1 > Gbox[2]) Gbox[2] = x1; ! 543: if (y1 > Gbox[3]) Gbox[3] = y1; ! 544: } ! 545: ! 546: get_bounds(p, bbox, flag) /* reconstruct bounding box from center/basis/xform */ ! 547: obj *p; ! 548: float *bbox; ! 549: int flag; ! 550: { ! 551: static obj *lastp = (obj *)0; ! 552: static double x0, y0, x1, y1; ! 553: double w, h, wm, hm, x, y; ! 554: double owid, oht; ! 555: ! 556: if (flag && p == lastp) ! 557: goto done; ! 558: x = Xformx(p, 1, p->o_x, p->o_y); ! 559: y = Xformy(p, 0, p->o_x, p->o_y); ! 560: if (p->o_type > TEXT) { ! 561: x0 = x1 = x; ! 562: y0 = y1 = y; ! 563: } ! 564: else { ! 565: if (p->o_type == TEXT) { ! 566: x += Linx(p,0,p->o_val[N_VAL-2].f,p->o_val[N_VAL-1].f); ! 567: y += Liny(p,0,p->o_val[N_VAL-2].f,p->o_val[N_VAL-1].f); ! 568: } ! 569: else if (p->o_type == ARC || p->o_type == SECTOR) { ! 570: x -= Linx(p,0,p->o_val[N_VAL+6].f,p->o_val[N_VAL+7].f); ! 571: y -= Liny(p,0,p->o_val[N_VAL+6].f,p->o_val[N_VAL+7].f); ! 572: } ! 573: owid = p->o_wid + p->o_weight; ! 574: oht = p->o_ht + p->o_weight; ! 575: if ( ( p->o_type == ARROW || p->o_type == LINE ! 576: || p->o_type == SPLINE || p->o_type == ARC) ! 577: && (p->o_attr & HEAD12)) { ! 578: w = p->o_val[N_VAL+(p->o_type == ARC ? 8 : 1)].f; ! 579: owid += w; /* account for width of arrowheads */ ! 580: oht += w; ! 581: } ! 582: w = Linx(p, 0, owid, oht) / 2; /* transform main diagonal */ ! 583: h = Liny(p, 0, owid, oht) / 2; ! 584: wm = Linx(p, 0, -owid, oht) / 2; /* transform other diagonal */ ! 585: hm = Liny(p, 0, -owid, oht) / 2; ! 586: if (w < 0) w = -w; ! 587: if (h < 0) h = -h; ! 588: if (wm < 0) wm = -wm; ! 589: if (hm < 0) hm = -hm; ! 590: if (w < wm) w = wm; ! 591: if (h < hm) h = hm; ! 592: x0 = x - w; ! 593: x1 = x + w; ! 594: y0 = y - h; ! 595: y1 = y + h; ! 596: } ! 597: lastp = p; ! 598: done: bbox[0] = x0; bbox[1] = y0; bbox[2] = x1; bbox[3] = y1; ! 599: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.