|
|
1.1 ! root 1: #include <stdio.h> ! 2: #include "grap.h" ! 3: #include "y.tab.h" ! 4: ! 5: #define MAXTICK 200 ! 6: int ntick = 0; ! 7: double tickval[MAXTICK]; /* tick values (one axis at a time */ ! 8: char *tickstr[MAXTICK]; /* and labels */ ! 9: ! 10: int tside = 0; ! 11: int tlist = 0; /* 1 => explicit values given */ ! 12: int toffside = 0; /* no ticks on these sides */ ! 13: int tick_dir = OUT; ! 14: double ticklen = TICKLEN; /* default tick length */ ! 15: int autoticks = LEFT|BOT; ! 16: int autodir = 0; /* set LEFT, etc. if automatic ticks go in */ ! 17: ! 18: savetick(f, s) /* remember tick location and label */ ! 19: double f; ! 20: char *s; ! 21: { ! 22: if (ntick >= MAXTICK) ! 23: fatal("too many ticks (%d)", MAXTICK); ! 24: tickval[ntick] = f; ! 25: tickstr[ntick] = s; ! 26: ntick++; ! 27: } ! 28: ! 29: dflt_tick(f) ! 30: double f; ! 31: { ! 32: if (f >= 0.0) ! 33: savetick(f, tostring("%g")); ! 34: else ! 35: savetick(f, tostring("\\%g")); ! 36: } ! 37: ! 38: tickside(n) /* remember which side these ticks go on */ ! 39: int n; ! 40: { ! 41: tside |= n; ! 42: } ! 43: ! 44: tickoff(side) /* remember explicit sides */ ! 45: int side; ! 46: { ! 47: toffside |= side; ! 48: } ! 49: ! 50: setlist() /* remember that there was an explicit list */ ! 51: { ! 52: tlist = 1; ! 53: } ! 54: ! 55: tickdir(dir, val, explicit) /* remember in/out [expr] */ ! 56: int dir, explicit; ! 57: double val; ! 58: { ! 59: tick_dir = dir; ! 60: if (explicit) ! 61: ticklen = val; ! 62: } ! 63: ! 64: ticks() /* set autoticks after ticks statement */ ! 65: { ! 66: /* was there an explicit "ticks [side] off"? */ ! 67: if (toffside) ! 68: autoticks &= ~toffside; ! 69: /* was there an explicit list? (eg "ticks at ..." or "ticks from ...") */ ! 70: if (tlist) { ! 71: if (tside & (BOT|TOP)) ! 72: autoticks &= ~(BOT|TOP); ! 73: if (tside & (LEFT|RIGHT)) ! 74: autoticks &= ~(LEFT|RIGHT); ! 75: } ! 76: /* was there a side without a list? (eg "ticks left in") */ ! 77: if (tside && !tlist) { ! 78: if (tick_dir == IN) ! 79: autodir |= tside; ! 80: if (tside & (BOT|TOP)) ! 81: autoticks = (autoticks & ~(BOT|TOP)) | (tside & (BOT|TOP)); ! 82: if (tside & (LEFT|RIGHT)) ! 83: autoticks = (autoticks & ~(LEFT|RIGHT)) | (tside & (LEFT|RIGHT)); ! 84: } ! 85: tlist = tside = toffside = 0; ! 86: tick_dir = OUT; ! 87: } ! 88: ! 89: double modfloor(f, t) ! 90: double f, t; ! 91: { ! 92: t = fabs(t); ! 93: return floor(f/t) * t; ! 94: } ! 95: ! 96: double modceil(f, t) ! 97: double f, t; ! 98: { ! 99: t = fabs(t); ! 100: return ceil(f/t) * t; ! 101: } ! 102: ! 103: double xtmin, xtmax; /* range of ticks */ ! 104: double ytmin, ytmax; ! 105: double xquant, xmult; /* quantization & scale for auto x ticks */ ! 106: double yquant, ymult; ! 107: double lograt = 5; ! 108: ! 109: do_autoticks(p) /* make set of ticks for default coord only */ ! 110: Obj *p; ! 111: { ! 112: double x, xl, xu, q; ! 113: ! 114: if (p == NULL) ! 115: return; ! 116: fprintf(tfd, "Autoticks:\t# x %g..%g, y %g..%g", ! 117: p->pt.x, p->pt1.x, p->pt.y, p->pt1.y); ! 118: fprintf(tfd, "; xt %g,%g, yt %g,%g, xq,xm = %g,%g, yq,ym = %g,%g\n", ! 119: xtmin, xtmax, ytmin, ytmax, xquant, xmult, yquant, ymult); ! 120: if ((autoticks & (BOT|TOP)) && p->pt1.x >= p->pt.x) { /* make x ticks */ ! 121: q = xquant; ! 122: xl = p->pt.x; ! 123: xu = p->pt1.x; ! 124: if (xl >= xu) ! 125: dflt_tick(xl); ! 126: else if ((p->log & XFLAG) && xu/xl >= lograt) { ! 127: for (x = q; x < xu; x *= 10) { ! 128: logtick(x, xl, xu); ! 129: if (xu/xl <= 100) { ! 130: logtick(2*x, xl, xu); ! 131: logtick(5*x, xl, xu); ! 132: } ! 133: } ! 134: } else { ! 135: xl = modceil(xtmin - q/100, q); ! 136: xu = modfloor(xtmax + q/100, q) + q/2; ! 137: for (x = xl; x <= xu; x += q) ! 138: dflt_tick(x); ! 139: } ! 140: tside = autoticks & (BOT|TOP); ! 141: ticklist(p, 0); ! 142: } ! 143: if ((autoticks & (LEFT|RIGHT)) && p->pt1.y >= p->pt.y) { /* make y ticks */ ! 144: q = yquant; ! 145: xl = p->pt.y; ! 146: xu = p->pt1.y; ! 147: if (xl >= xu) ! 148: dflt_tick(xl); ! 149: else if ((p->log & YFLAG) && xu/xl >= lograt) { ! 150: for (x = q; x < xu; x *= 10) { ! 151: logtick(x, xl, xu); ! 152: if (xu/xl <= 100) { ! 153: logtick(2*x, xl, xu); ! 154: logtick(5*x, xl, xu); ! 155: } ! 156: } ! 157: } else { ! 158: xl = modceil(ytmin - q/100, q); ! 159: xu = modfloor(ytmax + q/100, q) + q/2; ! 160: for (x = xl; x <= xu; x += q) ! 161: dflt_tick(x); ! 162: } ! 163: tside = autoticks & (LEFT|RIGHT); ! 164: ticklist(p, 0); ! 165: } ! 166: } ! 167: ! 168: logtick(v, lb, ub) ! 169: double v, lb, ub; ! 170: { ! 171: float slop = 1.0; /* was 1.001 */ ! 172: ! 173: if (slop * lb <= v && ub >= slop * v) ! 174: dflt_tick(v); ! 175: } ! 176: ! 177: Obj *setauto() /* compute new min,max, and quant & mult */ ! 178: { ! 179: Obj *p, *q; ! 180: ! 181: if ((q = lookup("lograt",0)) != NULL) ! 182: lograt = q->fval; ! 183: for (p = objlist; p; p = p->next) ! 184: if (p->type == NAME && strcmp(p->name,dflt_coord) == 0) ! 185: break; ! 186: if (p) { ! 187: if ((p->log & XFLAG) && p->pt1.x/p->pt.x >= lograt) ! 188: autolog(p, 'x'); ! 189: else ! 190: autoside(p, 'x'); ! 191: if ((p->log & YFLAG) && p->pt1.y/p->pt.y >= lograt) ! 192: autolog(p, 'y'); ! 193: else ! 194: autoside(p, 'y'); ! 195: } ! 196: return p; ! 197: } ! 198: ! 199: autoside(p, side) ! 200: Obj *p; ! 201: int side; ! 202: { ! 203: double r, s, d, ub, lb; ! 204: ! 205: if (side == 'x') { ! 206: xtmin = lb = p->pt.x; ! 207: xtmax = ub = p->pt1.x; ! 208: } else { ! 209: ytmin = lb = p->pt.y; ! 210: ytmax = ub = p->pt1.y; ! 211: } ! 212: if (ub <= lb) ! 213: return 0; /* cop out on little ranges */ ! 214: d = ub - lb; ! 215: r = s = 1; ! 216: while (d * s < 10) ! 217: s *= 10; ! 218: d *= s; ! 219: lb *= s; ! 220: ub *= s; ! 221: while (10 * r < d) ! 222: r *= 10; ! 223: if (r > d/3) ! 224: r /= 2; ! 225: else if (r <= d/6) ! 226: r *= 2; ! 227: if (side == 'x') { ! 228: xquant = r / s; ! 229: } else { ! 230: yquant = r / s; ! 231: } ! 232: } ! 233: ! 234: autolog(p, side) ! 235: Obj *p; ! 236: int side; ! 237: { ! 238: double r, s, t, d, ub, lb; ! 239: int flg; ! 240: ! 241: if (side == 'x') { ! 242: xtmin = lb = p->pt.x; ! 243: xtmax = ub = p->pt1.x; ! 244: flg = p->coord & XFLAG; ! 245: } else { ! 246: ytmin = lb = p->pt.y; ! 247: ytmax = ub = p->pt1.y; ! 248: flg = p->coord & YFLAG; ! 249: } ! 250: for (s = 1; lb * s < 1; s *= 10) ! 251: ; ! 252: lb *= s; ! 253: ub *= s; ! 254: for (r = 1; 10 * r < lb; r *= 10) ! 255: ; ! 256: for (t = 1; t < ub; t *= 10) ! 257: ; ! 258: if (side == 'x') ! 259: xquant = r / s; ! 260: else ! 261: yquant = r / s; ! 262: if (flg) ! 263: return; ! 264: if (ub / lb < 100) { ! 265: if (lb >= 5 * r) ! 266: r *= 5; ! 267: else if (lb >= 2 * r) ! 268: r *= 2; ! 269: if (ub * 5 <= t) ! 270: t /= 5; ! 271: else if (ub * 2 <= t) ! 272: t /= 2; ! 273: if (side == 'x') { ! 274: xtmin = r / s; ! 275: xtmax = t / s; ! 276: } else { ! 277: ytmin = r / s; ! 278: ytmax = t / s; ! 279: } ! 280: } ! 281: } ! 282: ! 283: iterator(from, to, op, by, fmt) /* create an iterator */ ! 284: double from, to, by; ! 285: int op; ! 286: char *fmt; ! 287: { ! 288: double x; ! 289: ! 290: /* should validate limits, etc. */ ! 291: /* punt for now */ ! 292: ! 293: dprintf("iterate from %g to %g by %g, op = %c, fmt=%s\n", ! 294: from, to, by, op, fmt ? fmt : ""); ! 295: switch (op) { ! 296: case '+': ! 297: case ' ': ! 298: for (x = from; x <= to + (SLOP-1) * by; x += by) ! 299: if (fmt) ! 300: savetick(x, tostring(fmt)); ! 301: else ! 302: dflt_tick(x); ! 303: break; ! 304: case '-': ! 305: for (x = from; x >= to; x -= by) ! 306: if (fmt) ! 307: savetick(x, tostring(fmt)); ! 308: else ! 309: dflt_tick(x); ! 310: break; ! 311: case '*': ! 312: for (x = from; x <= SLOP * to; x *= by) ! 313: if (fmt) ! 314: savetick(x, tostring(fmt)); ! 315: else ! 316: dflt_tick(x); ! 317: break; ! 318: case '/': ! 319: for (x = from; x >= to; x /= by) ! 320: if (fmt) ! 321: savetick(x, tostring(fmt)); ! 322: else ! 323: dflt_tick(x); ! 324: break; ! 325: } ! 326: if (fmt) ! 327: free(fmt); ! 328: } ! 329: ! 330: ticklist(p, explicit) /* fire out the accumulated ticks */ ! 331: Obj *p; ! 332: int explicit; /* 1 => list, 0 => auto */ ! 333: { ! 334: if (p == NULL) ! 335: return; ! 336: fprintf(tfd, "Ticks_%s:\n\tticklen = %g\n", p->name, ticklen); ! 337: print_ticks(TICKS, explicit, p, "ticklen", ""); ! 338: } ! 339: ! 340: print_ticks(type, explicit, p, lenstr, descstr) ! 341: int type, explicit; ! 342: Obj *p; ! 343: char *lenstr, *descstr; ! 344: { ! 345: int i, logflag, inside; ! 346: char buf[100]; ! 347: double tv; ! 348: ! 349: for (i = 0; i < ntick; i++) /* any ticks given explicitly? */ ! 350: if (tickstr[i] != NULL) ! 351: break; ! 352: if (i >= ntick && type == TICKS) /* no, so use values */ ! 353: for (i = 0; i < ntick; i++) { ! 354: if (tickval[i] >= 0.0) ! 355: sprintf(buf, "%g", tickval[i]); ! 356: else ! 357: sprintf(buf, "\\-%g", -tickval[i]); ! 358: tickstr[i] = tostring(buf); ! 359: } ! 360: else ! 361: for (i = 0; i < ntick; i++) { ! 362: if (tickstr[i] != NULL) { ! 363: sprintf(buf, tickstr[i], tickval[i]); ! 364: free(tickstr[i]); ! 365: tickstr[i] = tostring(buf); ! 366: } ! 367: } ! 368: logflag = sidelog(p->log, tside); ! 369: for (i = 0; i < ntick; i++) { ! 370: tv = tickval[i]; ! 371: halfrange(p, tside, tv); ! 372: if (logflag) { ! 373: if (tv <= 0.0) ! 374: fatal("can't take log of tick value %g", tv); ! 375: logit(tv); ! 376: } ! 377: if (type == GRID) ! 378: inside = LEFT|RIGHT|TOP|BOT; ! 379: else if (explicit) ! 380: inside = (tick_dir == IN) ? tside : 0; ! 381: else ! 382: inside = autodir; ! 383: if (tside & BOT) ! 384: maketick(p->name, BOT, inside, tv, tickstr[i], lenstr, descstr); ! 385: if (tside & TOP) ! 386: maketick(p->name, TOP, inside, tv, tickstr[i], lenstr, descstr); ! 387: if (tside & LEFT) ! 388: maketick(p->name, LEFT, inside, tv, tickstr[i], lenstr, descstr); ! 389: if (tside & RIGHT) ! 390: maketick(p->name, RIGHT, inside, tv, tickstr[i], lenstr, descstr); ! 391: if (tickstr[i]) { ! 392: free(tickstr[i]); ! 393: tickstr[i] = NULL; ! 394: } ! 395: } ! 396: ntick = 0; ! 397: } ! 398: ! 399: maketick(name, side, inflag, val, lab, lenstr, descstr) ! 400: char *name; ! 401: int side, inflag; ! 402: double val; ! 403: char *lab, *lenstr, *descstr; ! 404: { ! 405: char *sidestr, *td; ! 406: ! 407: fprintf(tfd, "\tline %s ", descstr); ! 408: inflag &= side; ! 409: switch (side) { ! 410: case BOT: ! 411: case 0: ! 412: td = inflag ? "up" : "down"; ! 413: fprintf(tfd, "%s %s from (x_%s(%g),0)", td, lenstr, name, val); ! 414: break; ! 415: case TOP: ! 416: td = inflag ? "down" : "up"; ! 417: fprintf(tfd, "%s %s from (x_%s(%g),frameht)", td, lenstr, name, val); ! 418: break; ! 419: case LEFT: ! 420: td = inflag ? "right" : "left"; ! 421: fprintf(tfd, "%s %s from (0,y_%s(%g))", td, lenstr, name, val); ! 422: break; ! 423: case RIGHT: ! 424: td = inflag ? "left" : "right"; ! 425: fprintf(tfd, "%s %s from (framewid,y_%s(%g))", td, lenstr, name, val); ! 426: break; ! 427: } ! 428: fprintf(tfd, "\n"); ! 429: sidestr = tick_dir == IN ? "start" : "end"; ! 430: if (lab != NULL) { ! 431: /* BUG: should fix size of lab here */ ! 432: switch (side) { ! 433: case BOT: case 0: ! 434: /* can drop "box invis" with new pic */ ! 435: fprintf(tfd, "\tbox invis \"%s\" ht .25 wid 0 with .n at last line.%s", ! 436: lab, sidestr); ! 437: break; ! 438: case TOP: ! 439: fprintf(tfd, "\tbox invis \"%s\" ht .2 wid 0 with .s at last line.%s", ! 440: lab, sidestr); ! 441: break; ! 442: case LEFT: ! 443: fprintf(tfd, "\t\"%s \" rjust at last line.%s", ! 444: lab, sidestr); ! 445: break; ! 446: case RIGHT: ! 447: fprintf(tfd, "\t\" %s\" ljust at last line.%s", ! 448: lab, sidestr); ! 449: break; ! 450: } ! 451: /* BUG: works only if "down x" comes before "at wherever" */ ! 452: lab_adjust(); ! 453: fprintf(tfd, "\n"); ! 454: } ! 455: } ! 456: ! 457: Attr *grid_desc = 0; ! 458: ! 459: griddesc(a) ! 460: Attr *a; ! 461: { ! 462: grid_desc = a; ! 463: } ! 464: ! 465: gridlist(p) ! 466: Obj *p; ! 467: { ! 468: int i, logflag; ! 469: double tv; ! 470: char *framestr; ! 471: ! 472: if ((tside & (BOT|TOP)) || tside == 0) ! 473: framestr = "frameht"; ! 474: else ! 475: framestr = "framewid"; ! 476: fprintf(tfd, "Grid_%s:\n", p->name); ! 477: tick_dir = IN; ! 478: print_ticks(GRID, 0, p, framestr, desc_str(grid_desc)); ! 479: if (grid_desc) { ! 480: freeattr(grid_desc); ! 481: grid_desc = 0; ! 482: } ! 483: } ! 484: ! 485: char *desc_str(a) /* convert DOT to "dotted", etc. */ ! 486: Attr *a; ! 487: { ! 488: static char buf[50], *p; ! 489: ! 490: if (a == NULL) ! 491: return p = ""; ! 492: switch (a->type) { ! 493: case DOT: p = "dotted"; break; ! 494: case DASH: p = "dashed"; break; ! 495: case INVIS: p = "invis"; break; ! 496: default: p = ""; ! 497: } ! 498: if (a->fval != 0.0) { ! 499: sprintf(buf, "%s %g", p, a->fval); ! 500: return buf; ! 501: } else ! 502: return p; ! 503: } ! 504: ! 505: sidelog(logflag, side) /* figure out whether to scale a side */ ! 506: int logflag, side; ! 507: { ! 508: if ((logflag & XFLAG) && ((side & (BOT|TOP)) || side == 0)) ! 509: return 1; ! 510: else if ((logflag & YFLAG) && (side & (LEFT|RIGHT))) ! 511: return 1; ! 512: else ! 513: return 0; ! 514: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.