devutf: add unicode aliases for accented characters
[troff.git] / pic / misc.c
blobe9ec76c9ff7a8b5bf0be4c673cd03dab9a6cfb8f
1 #include <stdio.h>
2 #include <string.h>
3 #include <stdlib.h>
4 #include <math.h>
5 #include "pic.h"
6 #include "y.tab.h"
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. */
14 switch (n) {
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;
20 return(hvmode);
23 curdir(void) /* convert current dir (hvmode) to RIGHT, LEFT, etc. */
25 switch (hvmode) {
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;
32 return 0;
35 double getcomp(obj *p, int t) /* return component of a position */
37 switch (t) {
38 case DOTX:
39 return p->o_x;
40 case DOTY:
41 return p->o_y;
42 case DOTWID:
43 switch (p->o_type) {
44 case BOX:
45 case BLOCK:
46 case TEXT:
47 return p->o_val[0];
48 case CIRCLE:
49 case ELLIPSE:
50 return 2 * p->o_val[0];
51 case LINE:
52 case ARROW:
53 return p->o_val[0] - p->o_x;
54 case PLACE:
55 return 0;
57 case DOTHT:
58 switch (p->o_type) {
59 case BOX:
60 case BLOCK:
61 case TEXT:
62 return p->o_val[1];
63 case CIRCLE:
64 case ELLIPSE:
65 return 2 * p->o_val[1];
66 case LINE:
67 case ARROW:
68 return p->o_val[1] - p->o_y;
69 case PLACE:
70 return 0;
72 case DOTRAD:
73 switch (p->o_type) {
74 case CIRCLE:
75 case ELLIPSE:
76 return p->o_val[0];
79 ERROR "you asked for a weird dimension or position" WARNING;
80 return 0;
83 double exprlist[100];
84 int nexpr = 0;
86 void exprsave(double f)
88 exprlist[nexpr++] = f;
91 char *sprintgen(char *fmt)
93 char buf[1000];
95 sprintf(buf, fmt, exprlist[0], exprlist[1], exprlist[2], exprlist[3], exprlist[4]);
96 nexpr = 0;
97 free(fmt);
98 return tostring(buf);
101 void makefattr(int type, int sub, double f) /* double attr */
103 YYSTYPE val;
104 val.f = f;
105 makeattr(type, sub, val);
108 void makeoattr(int type, obj *o) /* obj* attr */
110 YYSTYPE val;
111 val.o = o;
112 makeattr(type, 0, val);
115 void makeiattr(int type, int i) /* int attr */
117 YYSTYPE val;
118 val.i = i;
119 makeattr(type, 0, val);
122 void maketattr(int sub, char *p) /* text attribute: takes two */
124 YYSTYPE val;
125 val.p = p;
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 */
136 YYSTYPE val;
137 val.p = p;
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 */
144 nattr = 0;
145 return;
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;
153 nattr++;
156 void printexpr(double f) /* print expression for debugging */
158 printf("%g\n", f);
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)
168 register char *p;
170 p = malloc(strlen(s)+1);
171 if (p == NULL)
172 ERROR "out of space in tostring on %s", s FATAL;
173 strcpy(p, s);
174 return(p);
177 obj *makepos(double x, double y) /* make a position cell */
179 obj *p;
181 p = makenode(PLACE, 0);
182 p->o_x = x;
183 p->o_y = y;
184 return(p);
187 obj *makebetween(double f, obj *p1, obj *p2) /* make position between p1 and p2 */
189 obj *p;
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);
195 return(p);
198 obj *getpos(obj *p, int corner) /* find position of point */
200 double x, y;
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) */
208 double x, y, x1, y1;
210 if (p == NULL)
211 ERROR "null object" FATAL;
212 dprintf("whatpos %o %d %d\n", p, p->o_type, corner);
213 x = p->o_x;
214 y = p->o_y;
215 if (p->o_type != PLACE && p->o_type != MOVE) {
216 x1 = p->o_val[0];
217 y1 = p->o_val[1];
219 switch (p->o_type) {
220 case PLACE:
221 break;
222 case BOX:
223 case BLOCK:
224 case TEXT:
225 switch (corner) {
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;
234 case START:
235 if (p->o_type == BLOCK)
236 return whatpos(objlist[(int)p->o_val[2]], START, px, py);
237 case END:
238 if (p->o_type == BLOCK)
239 return whatpos(objlist[(int)p->o_val[3]], END, px, py);
241 break;
242 case ARC:
243 switch (corner) {
244 case START:
245 if (p->o_attr & CW_ARC) {
246 x = p->o_val[2]; y = p->o_val[3];
247 } else {
248 x = x1; y = y1;
250 break;
251 case END:
252 if (p->o_attr & CW_ARC) {
253 x = x1; y = y1;
254 } else {
255 x = p->o_val[2]; y = p->o_val[3];
257 break;
259 if (corner == START || corner == END)
260 break;
261 x1 = y1 = sqrt((x1-x)*(x1-x) + (y1-y)*(y1-y));
262 /* Fall Through! */
263 case CIRCLE:
264 case ELLIPSE:
265 switch (corner) {
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;
275 break;
276 case LINE:
277 case SPLINE:
278 case ARROW:
279 switch (corner) {
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;
289 break;
290 case MOVE:
291 /* really ought to be same as line... */
292 break;
294 dprintf("whatpos returns %g %g\n", x, y);
295 *px = x;
296 *py = y;
297 return 1;
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 */
308 int i, k;
309 obj *p;
311 k = n;
312 for (i = nobj-1; i >= 0; i--) {
313 p = objlist[i];
314 if (p->o_type == BLOCKEND) {
315 i = p->o_val[4];
316 continue;
318 if (p->o_type != t)
319 continue;
320 if (--k > 0)
321 continue; /* not there yet */
322 dprintf("got a last of x,y= %g,%g\n", p->o_x, p->o_y);
323 return(p);
325 ERROR "there is no %dth last", n FATAL;
326 return(NULL);
329 obj *getfirst(int n, int t) /* find n-th occurrence of type t */
331 int i, k;
332 obj *p;
334 k = n;
335 for (i = 0; i < nobj; i++) {
336 p = objlist[i];
337 if (p->o_type == BLOCK && t != BLOCK) { /* skip whole block */
338 i = p->o_val[5] + 1;
339 continue;
341 if (p->o_type != t)
342 continue;
343 if (--k > 0)
344 continue; /* not there yet */
345 dprintf("got a first of x,y= %g,%g\n", p->o_x, p->o_y);
346 return(p);
348 ERROR "there is no %dth ", n FATAL;
349 return(NULL);
352 double getblkvar(obj *p, char *s) /* find variable s2 in block p */
354 YYSTYPE y;
356 y = getblk(p, s);
357 return y.f;
360 obj *getblock(obj *p, char *s) /* find variable s in block p */
362 YYSTYPE y;
364 y = getblk(p, s);
365 return y.o;
368 YYSTYPE getblk(obj *p, char *s) /* find union type for s in p */
370 static YYSTYPE bug;
371 struct symtab *stp;
373 if (p->o_type != BLOCK) {
374 ERROR ".%s is not in that block", s WARNING;
375 return(bug);
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);
381 return(stp->s_val);
383 ERROR "there is no .%s in that []", s WARNING;
384 return(bug);
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)
407 obj *p;
409 p = (obj *) calloc(1, sizeof(obj) + (n-1)*sizeof(ofloat));
410 if (p == NULL)
411 ERROR "out of space in makenode" FATAL;
412 p->o_type = type;
413 p->o_count = n;
414 p->o_nobj = nobj;
415 p->o_mode = hvmode;
416 p->o_x = curx;
417 p->o_y = cury;
418 p->o_nt1 = ntext1;
419 p->o_nt2 = ntext;
420 ntext1 = ntext; /* ready for next caller */
421 if (nobj >= nobjlist)
422 objlist = (obj **) grow((char *) objlist, "objlist",
423 nobjlist *= 2, sizeof(obj *));
424 objlist[nobj++] = p;
425 return(p);
428 void extreme(double x, double y) /* record max and min x and y values */
430 if (x > xmax)
431 xmax = x;
432 if (y > ymax)
433 ymax = y;
434 if (x < xmin)
435 xmin = x;
436 if (y < ymin)
437 ymin = y;