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