blockgen.c (5209B)
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 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 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 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 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 }