misc.c 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. #include <stdio.h>
  10. #include <string.h>
  11. #include <stdlib.h>
  12. #include <math.h>
  13. #include "pic.h"
  14. #include "y.tab.h"
  15. int whatpos(obj *p, int corner, double *px, double *py);
  16. void makeattr(int type, int sub, YYSTYPE val);
  17. YYSTYPE getblk(obj *, char *);
  18. setdir(int n) /* set direction (hvmode) from LEFT, RIGHT, etc. */
  19. {
  20. switch (n) {
  21. case UP: hvmode = U_DIR; break;
  22. case DOWN: hvmode = D_DIR; break;
  23. case LEFT: hvmode = L_DIR; break;
  24. case RIGHT: hvmode = R_DIR; break;
  25. }
  26. return(hvmode);
  27. }
  28. curdir(void) /* convert current dir (hvmode) to RIGHT, LEFT, etc. */
  29. {
  30. switch (hvmode) {
  31. case R_DIR: return RIGHT;
  32. case L_DIR: return LEFT;
  33. case U_DIR: return UP;
  34. case D_DIR: return DOWN;
  35. }
  36. ERROR "can't happen curdir" FATAL;
  37. return 0;
  38. }
  39. double getcomp(obj *p, int t) /* return component of a position */
  40. {
  41. switch (t) {
  42. case DOTX:
  43. return p->o_x;
  44. case DOTY:
  45. return p->o_y;
  46. case DOTWID:
  47. switch (p->o_type) {
  48. case BOX:
  49. case BLOCK:
  50. case TEXT:
  51. return p->o_val[0];
  52. case CIRCLE:
  53. case ELLIPSE:
  54. return 2 * p->o_val[0];
  55. case LINE:
  56. case ARROW:
  57. return p->o_val[0] - p->o_x;
  58. case PLACE:
  59. return 0;
  60. }
  61. case DOTHT:
  62. switch (p->o_type) {
  63. case BOX:
  64. case BLOCK:
  65. case TEXT:
  66. return p->o_val[1];
  67. case CIRCLE:
  68. case ELLIPSE:
  69. return 2 * p->o_val[1];
  70. case LINE:
  71. case ARROW:
  72. return p->o_val[1] - p->o_y;
  73. case PLACE:
  74. return 0;
  75. }
  76. case DOTRAD:
  77. switch (p->o_type) {
  78. case CIRCLE:
  79. case ELLIPSE:
  80. return p->o_val[0];
  81. }
  82. }
  83. ERROR "you asked for a weird dimension or position" WARNING;
  84. return 0;
  85. }
  86. double exprlist[100];
  87. int nexpr = 0;
  88. void exprsave(double f)
  89. {
  90. exprlist[nexpr++] = f;
  91. }
  92. char *sprintgen(char *fmt)
  93. {
  94. 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);
  99. }
  100. void makefattr(int type, int sub, double f) /* double attr */
  101. {
  102. YYSTYPE val;
  103. val.f = f;
  104. makeattr(type, sub, val);
  105. }
  106. void makeoattr(int type, obj *o) /* obj* attr */
  107. {
  108. YYSTYPE val;
  109. val.o = o;
  110. makeattr(type, 0, val);
  111. }
  112. void makeiattr(int type, int i) /* int attr */
  113. {
  114. YYSTYPE val;
  115. val.i = i;
  116. makeattr(type, 0, val);
  117. }
  118. void maketattr(int sub, char *p) /* text attribute: takes two */
  119. {
  120. YYSTYPE val;
  121. val.p = p;
  122. makeattr(TEXTATTR, sub, val);
  123. }
  124. void addtattr(int sub) /* add text attrib to existing item */
  125. {
  126. attr[nattr-1].a_sub |= sub;
  127. }
  128. void makevattr(char *p) /* varname attribute */
  129. {
  130. YYSTYPE val;
  131. val.p = p;
  132. makeattr(VARNAME, 0, val);
  133. }
  134. void makeattr(int type, int sub, YYSTYPE val) /* add attribute type and val */
  135. {
  136. if (type == 0 && val.i == 0) { /* clear table for next stat */
  137. nattr = 0;
  138. return;
  139. }
  140. if (nattr >= nattrlist)
  141. attr = (Attr *) grow((char *)attr, "attr",
  142. nattrlist += 100, sizeof(Attr));
  143. dprintf("attr %d: %d %d %d\n", nattr, type, sub, val.i);
  144. attr[nattr].a_type = type;
  145. attr[nattr].a_sub = sub;
  146. attr[nattr].a_val = val;
  147. nattr++;
  148. }
  149. void printexpr(double f) /* print expression for debugging */
  150. {
  151. printf("%g\n", f);
  152. }
  153. void printpos(obj *p) /* print position for debugging */
  154. {
  155. printf("%g, %g\n", p->o_x, p->o_y);
  156. }
  157. char *tostring(char *s)
  158. {
  159. register char *p;
  160. p = malloc(strlen(s)+1);
  161. if (p == NULL)
  162. ERROR "out of space in tostring on %s", s FATAL;
  163. strcpy(p, s);
  164. return(p);
  165. }
  166. obj *makepos(double x, double y) /* make a position cell */
  167. {
  168. obj *p;
  169. p = makenode(PLACE, 0);
  170. p->o_x = x;
  171. p->o_y = y;
  172. return(p);
  173. }
  174. obj *makebetween(double f, obj *p1, obj *p2) /* make position between p1 and p2 */
  175. {
  176. obj *p;
  177. dprintf("fraction = %.2f\n", f);
  178. p = makenode(PLACE, 0);
  179. p->o_x = p1->o_x + f * (p2->o_x - p1->o_x);
  180. p->o_y = p1->o_y + f * (p2->o_y - p1->o_y);
  181. return(p);
  182. }
  183. obj *getpos(obj *p, int corner) /* find position of point */
  184. {
  185. double x, y;
  186. whatpos(p, corner, &x, &y);
  187. return makepos(x, y);
  188. }
  189. int whatpos(obj *p, int corner, double *px, double *py) /* what is the position (no side effect) */
  190. {
  191. double x, y, x1, y1;
  192. if (p == NULL)
  193. ERROR "null object" FATAL;
  194. dprintf("whatpos %o %d %d\n", p, p->o_type, corner);
  195. x = p->o_x;
  196. y = p->o_y;
  197. if (p->o_type != PLACE && p->o_type != MOVE) {
  198. x1 = p->o_val[0];
  199. y1 = p->o_val[1];
  200. }
  201. switch (p->o_type) {
  202. case PLACE:
  203. break;
  204. case BOX:
  205. case BLOCK:
  206. case TEXT:
  207. switch (corner) {
  208. case NORTH: y += y1 / 2; break;
  209. case SOUTH: y -= y1 / 2; break;
  210. case EAST: x += x1 / 2; break;
  211. case WEST: x -= x1 / 2; break;
  212. case NE: x += x1 / 2; y += y1 / 2; break;
  213. case SW: x -= x1 / 2; y -= y1 / 2; break;
  214. case SE: x += x1 / 2; y -= y1 / 2; break;
  215. case NW: x -= x1 / 2; y += y1 / 2; break;
  216. case START:
  217. if (p->o_type == BLOCK)
  218. return whatpos(objlist[(int)p->o_val[2]], START, px, py);
  219. case END:
  220. if (p->o_type == BLOCK)
  221. return whatpos(objlist[(int)p->o_val[3]], END, px, py);
  222. }
  223. break;
  224. case ARC:
  225. switch (corner) {
  226. case START:
  227. if (p->o_attr & CW_ARC) {
  228. x = p->o_val[2]; y = p->o_val[3];
  229. } else {
  230. x = x1; y = y1;
  231. }
  232. break;
  233. case END:
  234. if (p->o_attr & CW_ARC) {
  235. x = x1; y = y1;
  236. } else {
  237. x = p->o_val[2]; y = p->o_val[3];
  238. }
  239. break;
  240. }
  241. if (corner == START || corner == END)
  242. break;
  243. x1 = y1 = sqrt((x1-x)*(x1-x) + (y1-y)*(y1-y));
  244. /* Fall Through! */
  245. case CIRCLE:
  246. case ELLIPSE:
  247. switch (corner) {
  248. case NORTH: y += y1; break;
  249. case SOUTH: y -= y1; break;
  250. case EAST: x += x1; break;
  251. case WEST: x -= x1; break;
  252. case NE: x += 0.707 * x1; y += 0.707 * y1; break;
  253. case SE: x += 0.707 * x1; y -= 0.707 * y1; break;
  254. case NW: x -= 0.707 * x1; y += 0.707 * y1; break;
  255. case SW: x -= 0.707 * x1; y -= 0.707 * y1; break;
  256. }
  257. break;
  258. case LINE:
  259. case SPLINE:
  260. case ARROW:
  261. switch (corner) {
  262. case START: break; /* already in place */
  263. case END: x = x1; y = y1; break;
  264. default: /* change! */
  265. case CENTER: x = (x+x1)/2; y = (y+y1)/2; break;
  266. case NORTH: if (y1 > y) { x = x1; y = y1; } break;
  267. case SOUTH: if (y1 < y) { x = x1; y = y1; } break;
  268. case EAST: if (x1 > x) { x = x1; y = y1; } break;
  269. case WEST: if (x1 < x) { x = x1; y = y1; } break;
  270. }
  271. break;
  272. case MOVE:
  273. /* really ought to be same as line... */
  274. break;
  275. }
  276. dprintf("whatpos returns %g %g\n", x, y);
  277. *px = x;
  278. *py = y;
  279. return 1;
  280. }
  281. obj *gethere(void) /* make a place for curx,cury */
  282. {
  283. dprintf("gethere %g %g\n", curx, cury);
  284. return(makepos(curx, cury));
  285. }
  286. obj *getlast(int n, int t) /* find n-th previous occurrence of type t */
  287. {
  288. int i, k;
  289. obj *p;
  290. k = n;
  291. for (i = nobj-1; i >= 0; i--) {
  292. p = objlist[i];
  293. if (p->o_type == BLOCKEND) {
  294. i = p->o_val[4];
  295. continue;
  296. }
  297. if (p->o_type != t)
  298. continue;
  299. if (--k > 0)
  300. continue; /* not there yet */
  301. dprintf("got a last of x,y= %g,%g\n", p->o_x, p->o_y);
  302. return(p);
  303. }
  304. ERROR "there is no %dth last", n FATAL;
  305. return(NULL);
  306. }
  307. obj *getfirst(int n, int t) /* find n-th occurrence of type t */
  308. {
  309. int i, k;
  310. obj *p;
  311. k = n;
  312. for (i = 0; i < nobj; i++) {
  313. p = objlist[i];
  314. if (p->o_type == BLOCK && t != BLOCK) { /* skip whole block */
  315. i = p->o_val[5] + 1;
  316. continue;
  317. }
  318. if (p->o_type != t)
  319. continue;
  320. if (--k > 0)
  321. continue; /* not there yet */
  322. dprintf("got a first of x,y= %g,%g\n", p->o_x, p->o_y);
  323. return(p);
  324. }
  325. ERROR "there is no %dth ", n FATAL;
  326. return(NULL);
  327. }
  328. double getblkvar(obj *p, char *s) /* find variable s2 in block p */
  329. {
  330. YYSTYPE y;
  331. y = getblk(p, s);
  332. return y.f;
  333. }
  334. obj *getblock(obj *p, char *s) /* find variable s in block p */
  335. {
  336. YYSTYPE y;
  337. y = getblk(p, s);
  338. return y.o;
  339. }
  340. YYSTYPE getblk(obj *p, char *s) /* find union type for s in p */
  341. {
  342. static YYSTYPE bug;
  343. struct symtab *stp;
  344. if (p->o_type != BLOCK) {
  345. ERROR ".%s is not in that block", s WARNING;
  346. return(bug);
  347. }
  348. for (stp = p->o_symtab; stp != NULL; stp = stp->s_next)
  349. if (strcmp(s, stp->s_name) == 0) {
  350. dprintf("getblk %s found x,y= %g,%g\n",
  351. s, (stp->s_val.o)->o_x, (stp->s_val.o)->o_y);
  352. return(stp->s_val);
  353. }
  354. ERROR "there is no .%s in that []", s WARNING;
  355. return(bug);
  356. }
  357. obj *fixpos(obj *p, double x, double y)
  358. {
  359. dprintf("fixpos returns %g %g\n", p->o_x + x, p->o_y + y);
  360. return makepos(p->o_x + x, p->o_y + y);
  361. }
  362. obj *addpos(obj *p, obj *q)
  363. {
  364. dprintf("addpos returns %g %g\n", p->o_x+q->o_x, p->o_y+q->o_y);
  365. return makepos(p->o_x+q->o_x, p->o_y+q->o_y);
  366. }
  367. obj *subpos(obj *p, obj *q)
  368. {
  369. dprintf("subpos returns %g %g\n", p->o_x-q->o_x, p->o_y-q->o_y);
  370. return makepos(p->o_x-q->o_x, p->o_y-q->o_y);
  371. }
  372. obj *makenode(int type, int n)
  373. {
  374. obj *p;
  375. p = (obj *) calloc(1, sizeof(obj) + (n-1)*sizeof(ofloat));
  376. if (p == NULL)
  377. ERROR "out of space in makenode" FATAL;
  378. p->o_type = type;
  379. p->o_count = n;
  380. p->o_nobj = nobj;
  381. p->o_mode = hvmode;
  382. p->o_x = curx;
  383. p->o_y = cury;
  384. p->o_nt1 = ntext1;
  385. p->o_nt2 = ntext;
  386. ntext1 = ntext; /* ready for next caller */
  387. if (nobj >= nobjlist)
  388. objlist = (obj **) grow((char *) objlist, "objlist",
  389. nobjlist *= 2, sizeof(obj *));
  390. objlist[nobj++] = p;
  391. return(p);
  392. }
  393. void extreme(double x, double y) /* record max and min x and y values */
  394. {
  395. if (x > xmax)
  396. xmax = x;
  397. if (y > ymax)
  398. ymax = y;
  399. if (x < xmin)
  400. xmin = x;
  401. if (y < ymin)
  402. ymin = y;
  403. }