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