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