xref: /plan9/sys/src/cmd/pic/blockgen.c (revision 3e12c5d1bb89fc02707907988834ef147769ddaf)
1*3e12c5d1SDavid du Colombier #include <stdio.h>
2*3e12c5d1SDavid du Colombier #include <stdlib.h>
3*3e12c5d1SDavid du Colombier #include "pic.h"
4*3e12c5d1SDavid du Colombier #include "y.tab.h"
5*3e12c5d1SDavid du Colombier 
6*3e12c5d1SDavid du Colombier #define	NBRACK	20	/* depth of [...] */
7*3e12c5d1SDavid du Colombier #define	NBRACE	20	/* depth of {...} */
8*3e12c5d1SDavid du Colombier 
9*3e12c5d1SDavid du Colombier struct pushstack stack[NBRACK];
10*3e12c5d1SDavid du Colombier int	nstack	= 0;
11*3e12c5d1SDavid du Colombier struct pushstack bracestack[NBRACE];
12*3e12c5d1SDavid du Colombier int	nbstack	= 0;
13*3e12c5d1SDavid du Colombier 
14*3e12c5d1SDavid du Colombier void blockadj(obj *);
15*3e12c5d1SDavid du Colombier 
leftthing(int c)16*3e12c5d1SDavid du Colombier obj *leftthing(int c)	/* called for {... or [... */
17*3e12c5d1SDavid du Colombier 			/* really ought to be separate functions */
18*3e12c5d1SDavid du Colombier {
19*3e12c5d1SDavid du Colombier 	obj *p;
20*3e12c5d1SDavid du Colombier 
21*3e12c5d1SDavid du Colombier 	if (c == '[') {
22*3e12c5d1SDavid du Colombier 		if (nstack >= NBRACK)
23*3e12c5d1SDavid du Colombier 			ERROR "[...] nested too deep" FATAL;
24*3e12c5d1SDavid du Colombier 		stack[nstack].p_x = curx;
25*3e12c5d1SDavid du Colombier 		stack[nstack].p_y = cury;
26*3e12c5d1SDavid du Colombier 		stack[nstack].p_hvmode = hvmode;
27*3e12c5d1SDavid du Colombier 		curx = cury = 0;
28*3e12c5d1SDavid du Colombier 		stack[nstack].p_xmin = xmin;
29*3e12c5d1SDavid du Colombier 		stack[nstack].p_xmax = xmax;
30*3e12c5d1SDavid du Colombier 		stack[nstack].p_ymin = ymin;
31*3e12c5d1SDavid du Colombier 		stack[nstack].p_ymax = ymax;
32*3e12c5d1SDavid du Colombier 		nstack++;
33*3e12c5d1SDavid du Colombier 		xmin = ymin = 30000;
34*3e12c5d1SDavid du Colombier 		xmax = ymax = -30000;
35*3e12c5d1SDavid du Colombier 		p = makenode(BLOCK, 7);
36*3e12c5d1SDavid du Colombier 		p->o_val[4] = nobj;	/* 1st item within [...] */
37*3e12c5d1SDavid du Colombier 		if (p->o_nobj != nobj-1)
38*3e12c5d1SDavid du Colombier 			fprintf(stderr, "nobjs wrong%d %d\n", p->o_nobj, nobj);
39*3e12c5d1SDavid du Colombier 	} else {
40*3e12c5d1SDavid du Colombier 		if (nbstack >= NBRACK)
41*3e12c5d1SDavid du Colombier 			ERROR "{...} nested too deep" FATAL;
42*3e12c5d1SDavid du Colombier 		bracestack[nbstack].p_x = curx;
43*3e12c5d1SDavid du Colombier 		bracestack[nbstack].p_y = cury;
44*3e12c5d1SDavid du Colombier 		bracestack[nbstack].p_hvmode = hvmode;
45*3e12c5d1SDavid du Colombier 		nbstack++;
46*3e12c5d1SDavid du Colombier 		p = NULL;
47*3e12c5d1SDavid du Colombier 	}
48*3e12c5d1SDavid du Colombier 	return(p);
49*3e12c5d1SDavid du Colombier }
50*3e12c5d1SDavid du Colombier 
rightthing(obj * p,int c)51*3e12c5d1SDavid du Colombier obj *rightthing(obj *p, int c)	/* called for ... ] or ... } */
52*3e12c5d1SDavid du Colombier {
53*3e12c5d1SDavid du Colombier 	obj *q;
54*3e12c5d1SDavid du Colombier 
55*3e12c5d1SDavid du Colombier 	if (c == '}') {
56*3e12c5d1SDavid du Colombier 		nbstack--;
57*3e12c5d1SDavid du Colombier 		curx = bracestack[nbstack].p_x;
58*3e12c5d1SDavid du Colombier 		cury = bracestack[nbstack].p_y;
59*3e12c5d1SDavid du Colombier 		hvmode = bracestack[nbstack].p_hvmode;
60*3e12c5d1SDavid du Colombier 		q = makenode(MOVE, 0);
61*3e12c5d1SDavid du Colombier 		dprintf("M %g %g\n", curx, cury);
62*3e12c5d1SDavid du Colombier 	} else {
63*3e12c5d1SDavid du Colombier 		nstack--;
64*3e12c5d1SDavid du Colombier 		curx = stack[nstack].p_x;
65*3e12c5d1SDavid du Colombier 		cury = stack[nstack].p_y;
66*3e12c5d1SDavid du Colombier 		hvmode = stack[nstack].p_hvmode;
67*3e12c5d1SDavid du Colombier 		q = makenode(BLOCKEND, 7);
68*3e12c5d1SDavid du Colombier 		q->o_val[4] = p->o_nobj + 1;	/* back pointer */
69*3e12c5d1SDavid du Colombier 		p->o_val[5] = q->o_nobj - 1;	/* forward pointer */
70*3e12c5d1SDavid du Colombier 		if (xmin > xmax)	/* nothing happened */
71*3e12c5d1SDavid du Colombier 			xmin = xmax;
72*3e12c5d1SDavid du Colombier 		if (ymin > ymax)
73*3e12c5d1SDavid du Colombier 			ymin = ymax;
74*3e12c5d1SDavid du Colombier 		p->o_val[0] = xmin; p->o_val[1] = ymin;
75*3e12c5d1SDavid du Colombier 		p->o_val[2] = xmax; p->o_val[3] = ymax;
76*3e12c5d1SDavid du Colombier 		p->o_symtab = q->o_symtab = stack[nstack+1].p_symtab;
77*3e12c5d1SDavid du Colombier 		xmin = stack[nstack].p_xmin;
78*3e12c5d1SDavid du Colombier 		ymin = stack[nstack].p_ymin;
79*3e12c5d1SDavid du Colombier 		xmax = stack[nstack].p_xmax;
80*3e12c5d1SDavid du Colombier 		ymax = stack[nstack].p_ymax;
81*3e12c5d1SDavid du Colombier 	}
82*3e12c5d1SDavid du Colombier 	return(q);
83*3e12c5d1SDavid du Colombier }
84*3e12c5d1SDavid du Colombier 
blockgen(obj * p,obj * q)85*3e12c5d1SDavid du Colombier obj *blockgen(obj *p, obj *q)	/* handles [...] */
86*3e12c5d1SDavid du Colombier {
87*3e12c5d1SDavid du Colombier 	int i, invis, at, with;
88*3e12c5d1SDavid du Colombier 	double ddval, h, w, xwith, ywith;
89*3e12c5d1SDavid du Colombier 	double x0, y0, x1, y1, cx, cy;
90*3e12c5d1SDavid du Colombier 	obj *ppos;
91*3e12c5d1SDavid du Colombier 	Attr *ap;
92*3e12c5d1SDavid du Colombier 
93*3e12c5d1SDavid du Colombier 	invis = at = 0;
94*3e12c5d1SDavid du Colombier 	with = xwith = ywith = 0;
95*3e12c5d1SDavid du Colombier 	ddval = 0;
96*3e12c5d1SDavid du Colombier 	w = p->o_val[2] - p->o_val[0];
97*3e12c5d1SDavid du Colombier 	h = p->o_val[3] - p->o_val[1];
98*3e12c5d1SDavid du Colombier 	cx = (p->o_val[2] + p->o_val[0]) / 2;	/* geom ctr of [] wrt local orogin */
99*3e12c5d1SDavid du Colombier 	cy = (p->o_val[3] + p->o_val[1]) / 2;
100*3e12c5d1SDavid du Colombier 	dprintf("cx,cy=%g,%g\n", cx, cy);
101*3e12c5d1SDavid du Colombier 	for (i = 0; i < nattr; i++) {
102*3e12c5d1SDavid du Colombier 		ap = &attr[i];
103*3e12c5d1SDavid du Colombier 		switch (ap->a_type) {
104*3e12c5d1SDavid du Colombier 		case HEIGHT:
105*3e12c5d1SDavid du Colombier 			h = ap->a_val.f;
106*3e12c5d1SDavid du Colombier 			break;
107*3e12c5d1SDavid du Colombier 		case WIDTH:
108*3e12c5d1SDavid du Colombier 			w = ap->a_val.f;
109*3e12c5d1SDavid du Colombier 			break;
110*3e12c5d1SDavid du Colombier 		case WITH:
111*3e12c5d1SDavid du Colombier 			with = ap->a_val.i;	/* corner */
112*3e12c5d1SDavid du Colombier 			break;
113*3e12c5d1SDavid du Colombier 		case PLACE:	/* actually with position ... */
114*3e12c5d1SDavid du Colombier 			ppos = ap->a_val.o;
115*3e12c5d1SDavid du Colombier 			xwith = cx - ppos->o_x;
116*3e12c5d1SDavid du Colombier 			ywith = cy - ppos->o_y;
117*3e12c5d1SDavid du Colombier 			with = PLACE;
118*3e12c5d1SDavid du Colombier 			break;
119*3e12c5d1SDavid du Colombier 		case AT:
120*3e12c5d1SDavid du Colombier 		case FROM:
121*3e12c5d1SDavid du Colombier 			ppos = ap->a_val.o;
122*3e12c5d1SDavid du Colombier 			curx = ppos->o_x;
123*3e12c5d1SDavid du Colombier 			cury = ppos->o_y;
124*3e12c5d1SDavid du Colombier 			at++;
125*3e12c5d1SDavid du Colombier 			break;
126*3e12c5d1SDavid du Colombier 		case INVIS:
127*3e12c5d1SDavid du Colombier 			invis = INVIS;
128*3e12c5d1SDavid du Colombier 			break;
129*3e12c5d1SDavid du Colombier 		case TEXTATTR:
130*3e12c5d1SDavid du Colombier 			savetext(ap->a_sub, ap->a_val.p);
131*3e12c5d1SDavid du Colombier 			break;
132*3e12c5d1SDavid du Colombier 		}
133*3e12c5d1SDavid du Colombier 	}
134*3e12c5d1SDavid du Colombier 	if (with) {
135*3e12c5d1SDavid du Colombier 		switch (with) {
136*3e12c5d1SDavid du Colombier 		case NORTH:	ywith = -h / 2; break;
137*3e12c5d1SDavid du Colombier 		case SOUTH:	ywith = h / 2; break;
138*3e12c5d1SDavid du Colombier 		case EAST:	xwith = -w / 2; break;
139*3e12c5d1SDavid du Colombier 		case WEST:	xwith = w / 2; break;
140*3e12c5d1SDavid du Colombier 		case NE:	xwith = -w / 2; ywith = -h / 2; break;
141*3e12c5d1SDavid du Colombier 		case SE:	xwith = -w / 2; ywith = h / 2; break;
142*3e12c5d1SDavid du Colombier 		case NW:	xwith = w / 2; ywith = -h / 2; break;
143*3e12c5d1SDavid du Colombier 		case SW:	xwith = w / 2; ywith = h / 2; break;
144*3e12c5d1SDavid du Colombier 		}
145*3e12c5d1SDavid du Colombier 		curx += xwith;
146*3e12c5d1SDavid du Colombier 		cury += ywith;
147*3e12c5d1SDavid du Colombier 	}
148*3e12c5d1SDavid du Colombier 	if (!at) {
149*3e12c5d1SDavid du Colombier 		if (isright(hvmode))
150*3e12c5d1SDavid du Colombier 			curx += w / 2;
151*3e12c5d1SDavid du Colombier 		else if (isleft(hvmode))
152*3e12c5d1SDavid du Colombier 			curx -= w / 2;
153*3e12c5d1SDavid du Colombier 		else if (isup(hvmode))
154*3e12c5d1SDavid du Colombier 			cury += h / 2;
155*3e12c5d1SDavid du Colombier 		else
156*3e12c5d1SDavid du Colombier 			cury -= h / 2;
157*3e12c5d1SDavid du Colombier 	}
158*3e12c5d1SDavid du Colombier 	x0 = curx - w / 2;
159*3e12c5d1SDavid du Colombier 	y0 = cury - h / 2;
160*3e12c5d1SDavid du Colombier 	x1 = curx + w / 2;
161*3e12c5d1SDavid du Colombier 	y1 = cury + h / 2;
162*3e12c5d1SDavid du Colombier 	extreme(x0, y0);
163*3e12c5d1SDavid du Colombier 	extreme(x1, y1);
164*3e12c5d1SDavid du Colombier 	p->o_x = curx;
165*3e12c5d1SDavid du Colombier 	p->o_y = cury;
166*3e12c5d1SDavid du Colombier 	p->o_nt1 = ntext1;
167*3e12c5d1SDavid du Colombier 	p->o_nt2 = ntext;
168*3e12c5d1SDavid du Colombier 	ntext1 = ntext;
169*3e12c5d1SDavid du Colombier 	p->o_val[0] = w;
170*3e12c5d1SDavid du Colombier 	p->o_val[1] = h;
171*3e12c5d1SDavid du Colombier 	p->o_val[2] = cx;
172*3e12c5d1SDavid du Colombier 	p->o_val[3] = cy;
173*3e12c5d1SDavid du Colombier 	p->o_val[5] = q->o_nobj - 1;		/* last item in [...] */
174*3e12c5d1SDavid du Colombier 	p->o_ddval = ddval;
175*3e12c5d1SDavid du Colombier 	p->o_attr = invis;
176*3e12c5d1SDavid du Colombier 	dprintf("[] %g %g %g %g at %g %g, h=%g, w=%g\n", x0, y0, x1, y1, curx, cury, h, w);
177*3e12c5d1SDavid du Colombier 	if (isright(hvmode))
178*3e12c5d1SDavid du Colombier 		curx = x1;
179*3e12c5d1SDavid du Colombier 	else if (isleft(hvmode))
180*3e12c5d1SDavid du Colombier 		curx = x0;
181*3e12c5d1SDavid du Colombier 	else if (isup(hvmode))
182*3e12c5d1SDavid du Colombier 		cury = y1;
183*3e12c5d1SDavid du Colombier 	else
184*3e12c5d1SDavid du Colombier 		cury = y0;
185*3e12c5d1SDavid du Colombier 	for (i = 0; i <= 5; i++)
186*3e12c5d1SDavid du Colombier 		q->o_val[i] = p->o_val[i];
187*3e12c5d1SDavid du Colombier 	stack[nstack+1].p_symtab = NULL;	/* so won't be found again */
188*3e12c5d1SDavid du Colombier 	blockadj(p);	/* fix up coords for enclosed blocks */
189*3e12c5d1SDavid du Colombier 	return(p);
190*3e12c5d1SDavid du Colombier }
191*3e12c5d1SDavid du Colombier 
blockadj(obj * p)192*3e12c5d1SDavid du Colombier void blockadj(obj *p)	/* adjust coords in block starting at p */
193*3e12c5d1SDavid du Colombier {
194*3e12c5d1SDavid du Colombier 	double dx, dy;
195*3e12c5d1SDavid du Colombier 	int n, lev;
196*3e12c5d1SDavid du Colombier 
197*3e12c5d1SDavid du Colombier 	dx = p->o_x - p->o_val[2];
198*3e12c5d1SDavid du Colombier 	dy = p->o_y - p->o_val[3];
199*3e12c5d1SDavid du Colombier 	n = p->o_nobj + 1;
200*3e12c5d1SDavid du Colombier 	dprintf("into blockadj: dx,dy=%g,%g\n", dx, dy);
201*3e12c5d1SDavid du Colombier 	for (lev = 1; lev > 0; n++) {
202*3e12c5d1SDavid du Colombier 		p = objlist[n];
203*3e12c5d1SDavid du Colombier 		if (p->o_type == BLOCK)
204*3e12c5d1SDavid du Colombier 			lev++;
205*3e12c5d1SDavid du Colombier 		else if (p->o_type == BLOCKEND)
206*3e12c5d1SDavid du Colombier 			lev--;
207*3e12c5d1SDavid du Colombier 		dprintf("blockadj: type=%d o_x,y=%g,%g;", p->o_type, p->o_x, p->o_y);
208*3e12c5d1SDavid du Colombier 		p->o_x += dx;
209*3e12c5d1SDavid du Colombier 		p->o_y += dy;
210*3e12c5d1SDavid du Colombier 		dprintf(" becomes %g,%g\n", p->o_x, p->o_y);
211*3e12c5d1SDavid du Colombier 		switch (p->o_type) {	/* other absolute coords */
212*3e12c5d1SDavid du Colombier 		case LINE:
213*3e12c5d1SDavid du Colombier 		case ARROW:
214*3e12c5d1SDavid du Colombier 		case SPLINE:
215*3e12c5d1SDavid du Colombier 			p->o_val[0] += dx;
216*3e12c5d1SDavid du Colombier 			p->o_val[1] += dy;
217*3e12c5d1SDavid du Colombier 			break;
218*3e12c5d1SDavid du Colombier 		case ARC:
219*3e12c5d1SDavid du Colombier 			p->o_val[0] += dx;
220*3e12c5d1SDavid du Colombier 			p->o_val[1] += dy;
221*3e12c5d1SDavid du Colombier 			p->o_val[2] += dx;
222*3e12c5d1SDavid du Colombier 			p->o_val[3] += dy;
223*3e12c5d1SDavid du Colombier 			break;
224*3e12c5d1SDavid du Colombier 		}
225*3e12c5d1SDavid du Colombier 	}
226*3e12c5d1SDavid du Colombier }
227