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