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