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