8 int whatpos(obj
*p
, int corner
, double *px
, double *py
);
9 void makeattr(int type
, int sub
, YYSTYPE val
);
10 YYSTYPE
getblk(obj
*, char *);
12 setdir(int n
) /* set direction (hvmode) from LEFT, RIGHT, etc. */
15 case UP
: hvmode
= U_DIR
; break;
16 case DOWN
: hvmode
= D_DIR
; break;
17 case LEFT
: hvmode
= L_DIR
; break;
18 case RIGHT
: hvmode
= R_DIR
; break;
23 curdir(void) /* convert current dir (hvmode) to RIGHT, LEFT, etc. */
26 case R_DIR
: return RIGHT
;
27 case L_DIR
: return LEFT
;
28 case U_DIR
: return UP
;
29 case D_DIR
: return DOWN
;
31 ERROR
"can't happen curdir" FATAL
;
35 double getcomp(obj
*p
, int t
) /* return component of a position */
50 return 2 * p
->o_val
[0];
53 return p
->o_val
[0] - p
->o_x
;
65 return 2 * p
->o_val
[1];
68 return p
->o_val
[1] - p
->o_y
;
79 ERROR
"you asked for a weird dimension or position" WARNING
;
86 void exprsave(double f
)
88 exprlist
[nexpr
++] = f
;
91 char *sprintgen(char *fmt
)
95 sprintf(buf
, fmt
, exprlist
[0], exprlist
[1], exprlist
[2], exprlist
[3], exprlist
[4]);
101 void makefattr(int type
, int sub
, double f
) /* double attr */
105 makeattr(type
, sub
, val
);
108 void makeoattr(int type
, obj
*o
) /* obj* attr */
112 makeattr(type
, 0, val
);
115 void makeiattr(int type
, int i
) /* int attr */
119 makeattr(type
, 0, val
);
122 void maketattr(int sub
, char *p
) /* text attribute: takes two */
126 makeattr(TEXTATTR
, sub
, val
);
129 void addtattr(int sub
) /* add text attrib to existing item */
131 attr
[nattr
-1].a_sub
|= sub
;
134 void makevattr(char *p
) /* varname attribute */
138 makeattr(VARNAME
, 0, val
);
141 void makeattr(int type
, int sub
, YYSTYPE val
) /* add attribute type and val */
143 if (type
== 0 && val
.i
== 0) { /* clear table for next stat */
147 if (nattr
>= nattrlist
)
148 attr
= (Attr
*) grow((char *)attr
, "attr", nattrlist
+= 100, sizeof(Attr
));
149 dprintf("attr %d: %d %d %d\n", nattr
, type
, sub
, val
.i
);
150 attr
[nattr
].a_type
= type
;
151 attr
[nattr
].a_sub
= sub
;
152 attr
[nattr
].a_val
= val
;
156 void printexpr(double f
) /* print expression for debugging */
161 void printpos(obj
*p
) /* print position for debugging */
163 printf("%g, %g\n", p
->o_x
, p
->o_y
);
166 char *tostring(char *s
)
170 p
= malloc(strlen(s
)+1);
172 ERROR
"out of space in tostring on %s", s FATAL
;
177 obj
*makepos(double x
, double y
) /* make a position cell */
181 p
= makenode(PLACE
, 0);
187 obj
*makebetween(double f
, obj
*p1
, obj
*p2
) /* make position between p1 and p2 */
191 dprintf("fraction = %.2f\n", f
);
192 p
= makenode(PLACE
, 0);
193 p
->o_x
= p1
->o_x
+ f
* (p2
->o_x
- p1
->o_x
);
194 p
->o_y
= p1
->o_y
+ f
* (p2
->o_y
- p1
->o_y
);
198 obj
*getpos(obj
*p
, int corner
) /* find position of point */
202 whatpos(p
, corner
, &x
, &y
);
203 return makepos(x
, y
);
206 int whatpos(obj
*p
, int corner
, double *px
, double *py
) /* what is the position (no side effect) */
211 ERROR
"null object" FATAL
;
212 dprintf("whatpos %o %d %d\n", p
, p
->o_type
, corner
);
215 if (p
->o_type
!= PLACE
&& p
->o_type
!= MOVE
) {
226 case NORTH
: y
+= y1
/ 2; break;
227 case SOUTH
: y
-= y1
/ 2; break;
228 case EAST
: x
+= x1
/ 2; break;
229 case WEST
: x
-= x1
/ 2; break;
230 case NE
: x
+= x1
/ 2; y
+= y1
/ 2; break;
231 case SW
: x
-= x1
/ 2; y
-= y1
/ 2; break;
232 case SE
: x
+= x1
/ 2; y
-= y1
/ 2; break;
233 case NW
: x
-= x1
/ 2; y
+= y1
/ 2; break;
235 if (p
->o_type
== BLOCK
)
236 return whatpos(objlist
[(int)p
->o_val
[2]], START
, px
, py
);
238 if (p
->o_type
== BLOCK
)
239 return whatpos(objlist
[(int)p
->o_val
[3]], END
, px
, py
);
245 if (p
->o_attr
& CW_ARC
) {
246 x
= p
->o_val
[2]; y
= p
->o_val
[3];
252 if (p
->o_attr
& CW_ARC
) {
255 x
= p
->o_val
[2]; y
= p
->o_val
[3];
259 if (corner
== START
|| corner
== END
)
261 x1
= y1
= sqrt((x1
-x
)*(x1
-x
) + (y1
-y
)*(y1
-y
));
266 case NORTH
: y
+= y1
; break;
267 case SOUTH
: y
-= y1
; break;
268 case EAST
: x
+= x1
; break;
269 case WEST
: x
-= x1
; break;
270 case NE
: x
+= 0.707 * x1
; y
+= 0.707 * y1
; break;
271 case SE
: x
+= 0.707 * x1
; y
-= 0.707 * y1
; break;
272 case NW
: x
-= 0.707 * x1
; y
+= 0.707 * y1
; break;
273 case SW
: x
-= 0.707 * x1
; y
-= 0.707 * y1
; break;
280 case START
: break; /* already in place */
281 case END
: x
= x1
; y
= y1
; break;
282 default: /* change! */
283 case CENTER
: x
= (x
+x1
)/2; y
= (y
+y1
)/2; break;
284 case NORTH
: if (y1
> y
) { x
= x1
; y
= y1
; } break;
285 case SOUTH
: if (y1
< y
) { x
= x1
; y
= y1
; } break;
286 case EAST
: if (x1
> x
) { x
= x1
; y
= y1
; } break;
287 case WEST
: if (x1
< x
) { x
= x1
; y
= y1
; } break;
291 /* really ought to be same as line... */
294 dprintf("whatpos returns %g %g\n", x
, y
);
300 obj
*gethere(void) /* make a place for curx,cury */
302 dprintf("gethere %g %g\n", curx
, cury
);
303 return(makepos(curx
, cury
));
306 obj
*getlast(int n
, int t
) /* find n-th previous occurrence of type t */
312 for (i
= nobj
-1; i
>= 0; i
--) {
314 if (p
->o_type
== BLOCKEND
) {
321 continue; /* not there yet */
322 dprintf("got a last of x,y= %g,%g\n", p
->o_x
, p
->o_y
);
325 ERROR
"there is no %dth last", n FATAL
;
329 obj
*getfirst(int n
, int t
) /* find n-th occurrence of type t */
335 for (i
= 0; i
< nobj
; i
++) {
337 if (p
->o_type
== BLOCK
&& t
!= BLOCK
) { /* skip whole block */
344 continue; /* not there yet */
345 dprintf("got a first of x,y= %g,%g\n", p
->o_x
, p
->o_y
);
348 ERROR
"there is no %dth ", n FATAL
;
352 double getblkvar(obj
*p
, char *s
) /* find variable s2 in block p */
360 obj
*getblock(obj
*p
, char *s
) /* find variable s in block p */
368 YYSTYPE
getblk(obj
*p
, char *s
) /* find union type for s in p */
373 if (p
->o_type
!= BLOCK
) {
374 ERROR
".%s is not in that block", s WARNING
;
377 for (stp
= p
->o_symtab
; stp
!= NULL
; stp
= stp
->s_next
)
378 if (strcmp(s
, stp
->s_name
) == 0) {
379 dprintf("getblk %s found x,y= %g,%g\n",
380 s
, (stp
->s_val
.o
)->o_x
, (stp
->s_val
.o
)->o_y
);
383 ERROR
"there is no .%s in that []", s WARNING
;
387 obj
*fixpos(obj
*p
, double x
, double y
)
389 dprintf("fixpos returns %g %g\n", p
->o_x
+ x
, p
->o_y
+ y
);
390 return makepos(p
->o_x
+ x
, p
->o_y
+ y
);
393 obj
*addpos(obj
*p
, obj
*q
)
395 dprintf("addpos returns %g %g\n", p
->o_x
+q
->o_x
, p
->o_y
+q
->o_y
);
396 return makepos(p
->o_x
+q
->o_x
, p
->o_y
+q
->o_y
);
399 obj
*subpos(obj
*p
, obj
*q
)
401 dprintf("subpos returns %g %g\n", p
->o_x
-q
->o_x
, p
->o_y
-q
->o_y
);
402 return makepos(p
->o_x
-q
->o_x
, p
->o_y
-q
->o_y
);
405 obj
*makenode(int type
, int n
)
409 p
= (obj
*) calloc(1, sizeof(obj
) + (n
-1)*sizeof(ofloat
));
411 ERROR
"out of space in makenode" FATAL
;
420 ntext1
= ntext
; /* ready for next caller */
421 if (nobj
>= nobjlist
)
422 objlist
= (obj
**) grow((char *) objlist
, "objlist",
423 nobjlist
*= 2, sizeof(obj
*));
428 void extreme(double x
, double y
) /* record max and min x and y values */