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