home *** CD-ROM | disk | FTP | other *** search
/ Photo CD Demo 1 / Demo.bin / gle / gle / graph2.c < prev    next >
C/C++ Source or Header  |  1992-11-29  |  32KB  |  1,347 lines

  1. #define GRAPHDEF extern
  2. #include "graph.h"
  3. #include "color.h"
  4.  
  5. int fitbez(double **pxv, double **pyv, int **pmv,int *pnp, int multivalued);
  6. int var_clear_local(void);
  7. int big_open(char *s);
  8. int big_vec(int nomiss);
  9. int windownorm(void);
  10. int windowdn(int d);
  11. int big_mark(int mnum, double msize);
  12. double fnx(double vv);
  13. double fnx(double vv)
  14. {
  15.     if (xx[1].log==true) {
  16.         return (log10(vv)-log10(wxmin))/(log10(wxmax)-log10(wxmin))
  17.             * xlength + xbl;
  18.     } else {
  19.         return (((vv-wxmin)/(wxmax-wxmin)) * xlength + xbl);
  20.     }
  21. }
  22. double fny(double vv)
  23. {
  24.     if (xx[2].log==true) {
  25.         return (log10(vv)-log10(wymin))/(log10(wymax)-log10(wymin))
  26.             * ylength + ybl;
  27.     } else {
  28.         return (((vv-wymin)/(wymax-wymin)) * ylength + ybl);
  29.     }
  30. }
  31.  
  32. int bigalli;
  33. static int bigcol1,bigcol2,bigally;
  34. static long bigrecord;
  35. FILE *fptr;
  36. big_open(char *infile2)
  37. {
  38.     char infile[90];
  39.     char *s1,*s2;
  40.     strcpy(infile,infile2);
  41.     if (infile[strlen(infile)-1] == '$') {
  42.         { int idx,typ;
  43.         var_find(infile,&idx,&typ) ;
  44.         if (idx>=0) var_getstr(idx,infile);
  45.     }}
  46.     s1 = strchr(infile,',');
  47.     bigrecord = 0;
  48.     bigally = bigalli = 0;
  49.     bigcol1 = 1; bigcol2 = 2;
  50.     if (s1!=NULL) {
  51.         s2 = strchr(s1+1,',');
  52.         bigcol1 = atoi(s1+1);
  53.         if (s2!=NULL) {
  54.             if (*(s2+1) == '*') {
  55.                 bigally = true;
  56.             } else {
  57.                 bigcol2 = atoi(s2+1);
  58.                 if (bigcol2==0) {
  59.                     gprint("Expecting \"file.name,xcoloumn,ycolumn\" found [%s] \n",infile);
  60.                 }
  61.             }
  62.             *s1 = 0;
  63.         }
  64.     }
  65.     if (infile[strlen(infile)-1] == '$') {
  66.         { int idx,typ;
  67.         var_find(infile,&idx,&typ) ;
  68.         if (idx>=0) var_getstr(idx,infile);
  69.     }}
  70.     strlwr(infile);
  71.     fptr = fopen(infile,"r");
  72.     if (s1!=NULL) *s1 = ',';
  73.     if (fptr==NULL) {
  74.         gprint("Unable to open data file {%s} \n",infile);
  75.         return;
  76.     }
  77. }
  78. int big_line(double *x1, double *y1, int *m);
  79. big_line(double *x1, double *y1, int *m)
  80. {
  81.     static char *bigee;
  82.     int bg1;
  83.     static int ntk;
  84.     if (fptr==NULL) return;
  85. next_line:;
  86.     if (bigally) {
  87.         if (bigalli==0 || bigalli>=ntk) {
  88.             if (bigee!=NULL) { myfree(bigee); bigee = 0;}
  89.             if (feof(fptr)) return;
  90.             fgets(ebuff,390,fptr);
  91.             bigee = sdup(ebuff);
  92.             bigalli = 0;
  93.         }
  94.         strcpy(ebuff,bigee);
  95.         token_data(ebuff,tk,&ntk,tkbuff);
  96.         *x1 = ++bigrecord;
  97.         *y1 = atof(tk[++bigalli]);
  98.         *m = false;
  99.         if (feof(fptr) || abort_key()) {*m = true; return;}
  100.         return;
  101.     }
  102.     if (feof(fptr)) return;
  103.     fgets(ebuff,390,fptr);
  104.     token_data(ebuff,tk,&ntk,tkbuff);
  105.     if (ntk<bigcol1 || ntk<bigcol2) goto next_line;
  106.     bg1 = bigcol1;
  107.     if (bg1==0) bg1 = bigcol2;
  108.     if (*tk[bg1] != '*' && *tk[bigcol2] != '*') {
  109.         if (bigcol1==0) *x1 = ++bigrecord;
  110.         else *x1 = atof(tk[bigcol1]);
  111.         *y1 = atof(tk[bigcol2]);
  112.         *m = false;
  113.     } else { *m = true;}
  114.     if (feof(fptr) || abort_key()) {*m = true; return;}
  115. }
  116. setrange(double x, double y, int m)
  117. {
  118.     if (m) return;
  119.     if (x>range_x2) range_x2 = x;
  120.     if (x<range_x1) range_x1 = x;
  121.     if (y>range_y2) range_y2 = y;
  122.     if (y<range_y1) range_y1 = y;
  123. }
  124. preview_big()
  125. {
  126.     int dn;
  127.     double x1,y1,x2,y2;
  128.     int m1,m2;
  129.  
  130.     for (dn=1;dn<=ndata;dn++) {
  131.       if (dp[dn]!=NULL) {
  132.        if (dp[dn]->bigfile!=NULL && dp[dn]->autoscale) {
  133.         big_open(dp[dn]->bigfile);
  134.         if (fptr==NULL) goto endbigm;
  135.         if (feof(fptr))  goto xxx;
  136.         for (;;) {
  137. aaa2:            if (feof(fptr) || abort_key())  goto xxx;
  138.             big_line(&x1,&y1,&m1);
  139.             setrange(x1,y1,m1);
  140.         }
  141. xxx:        big_close();
  142. endbigm:    ;
  143.        }
  144.       }
  145.     }      
  146. }
  147.  
  148. request()
  149. {
  150.     static char s[20];
  151.     gprint("Press return to continue \n");
  152.     gets(s);
  153. }
  154. draw_bars()
  155. {
  156.     int b,nb,d,i,di,df,dt;
  157.     long sidecolor,topcolor;
  158.     double x3d,y3d;
  159.     int notop;
  160.     double *px,*py,xzz,*xt,*yt,*xf,*yf,bwid,whole_wid,bdis,yfval;
  161.     int *m;
  162.     double x,y,w;
  163.  
  164.     for (b=1;b<=g_nbar;b++) {
  165.     done_line = true;
  166.     if (br[b]==0) { gprint("Error, bars struct zero \n"); return;}
  167.     nb = br[b]->ngrp;    /* number of bars in each group */
  168.     d = br[b]->to[0];     /* dataset for first bar */
  169.     if (d==0 || dp[d]==NULL)  {gprint("Error, bars zero dataset \n");return;}
  170.     /* find the smallest x distance in dataset 1 */
  171.     px = dp[d]->xv;
  172.     py = dp[d]->yv;
  173.     if (px==NULL || nb==0) { gprint("error in bar data dn=%d  ngrp=%d\n",d,nb); return;}
  174.     m = dp[d]->miss;
  175.     xzz = 1e30;
  176.     for (i=1;i<dp[d]->np;i++,px++) {
  177.         w = *(px+1) - *(px);
  178.         if (w>0) if (w<xzz) xzz = w;
  179.     }
  180.     if (br[b]->width==0) br[b]->width = xzz/(nb*2);
  181.     if (br[b]->dist==0) br[b]->dist = br[b]->width*1.4 ;
  182.     bwid = br[b]->width;
  183.     bdis = br[b]->dist;
  184.  
  185.     windowdn(d);
  186.     g_gsave();
  187.     for (di=0;di<nb;di++) {
  188.         df = br[b]->from[di];
  189.         dt = br[b]->to[di];
  190.               whole_wid = (nb-1)*bdis+bwid;
  191.         g_set_line_width(br[b]->lwidth[di]);
  192.         g_set_line_style(&br[b]->lstyle[di][0]);
  193.         if (br[b]->color[di] == 0) br[b]->color[di] = COLOR_BLACK;
  194.         g_set_color(br[b]->color[di]);
  195.         g_set_fill(br[b]->fill[di]);
  196.  
  197.         x3d = br[b]->x3d;
  198.         y3d = br[b]->y3d;
  199.         topcolor = br[b]->top[di];
  200.         sidecolor = br[b]->side[di];
  201.         notop = br[b]->notop;
  202.  
  203.         df = br[b]->from[di];
  204.         dt = br[b]->to[di];
  205.         if (dp[df]==NULL || dp[dt]==NULL) {
  206.             gprint("No data in bargraph datasets\n");
  207.             goto bar_exit;
  208.         }
  209.         yf = dp[df]->yv;
  210.         xt = dp[dt]->xv;
  211.         yt = dp[dt]->yv;
  212.         m = dp[dt]->miss;
  213.         if (yt==NULL) {
  214.             gprint("No data in bargraph dataset. d(%d) \n",dt);
  215.             goto bar_exit;
  216.         }
  217.  
  218.         windowdn(d);
  219.         for (i=0;i<dp[d]->np;i++,xt++,yt++,m++) {
  220.           if (yf!=NULL) yfval = *yf++;
  221.             else     yfval = 0;
  222.           if (!*m) {
  223.             draw_bar((*xt)-whole_wid/2+di*bdis,yfval,*yt,bwid
  224.                 ,x3d,y3d,sidecolor,topcolor,notop);
  225.           }
  226.         }
  227.         windownorm();
  228.     }
  229. bar_exit:;
  230.     g_grestore();
  231.     }
  232. }
  233. /*--------------------------------------------------------------------------*/
  234. int box3d(double x1, double y1, double x2, double y2,double x3d,double y3d,long sidecolor, long topcolor, int notop);
  235. draw_bar(double x, double yf, double yt, double wd,double x3d,double y3d,long sidecolor, long topcolor, int notop)
  236. {
  237.     double x1,y1,x2,y2;
  238.  
  239.     x = x + wd/2;
  240.     /* ! draw a bar, wd wide, CENTREed at x , from yf, to yt, */
  241.  
  242.     x1 = x - wd/2;
  243.     y1 = yf;
  244.     x2 = x + wd/2;
  245.     y2 = yt;
  246.     box_clip(&x1,&y1,wxmin,wymin,wxmax,wymax);
  247.     box_clip(&x2,&y2,wxmin,wymin,wxmax,wymax);
  248.  
  249.     if (x3d!=0) {
  250.         box3d(fnx(x1),fny(y1),fnx(x2),fny(y2),x3d,y3d,sidecolor,topcolor,notop);
  251.     }
  252.     g_box_fill(fnx(x1),fny(y1),fnx(x2),fny(y2));
  253.     g_box_stroke(fnx(x1),fny(y1),fnx(x2),fny(y2));
  254. }
  255. box3d(double x1, double y1, double x2, double y2,double x3d,double y3d,long sidecolor, long topcolor, int notop)
  256. {
  257.     /* assuming x3d is positive for the moment */
  258.     double xx;
  259.  
  260.     if (x1>x2) { xx = x1; x1 = x2; x2 = xx;}
  261.     if (y1>y2) { xx = y1; y1 = y2; y2 = xx;}
  262.  
  263.     x3d = x3d*(x2-x1);
  264.     y3d = y3d*(x2-x1);
  265.  
  266.     if (x3d<0) {
  267.         xx = x1; x1 = x2; x2 = xx;
  268.     }
  269.     g_gsave();
  270.     g_set_path(true);
  271.     g_set_line_join(1);    /* use rounded lines to avoid ucky peeks */
  272.     g_newpath();
  273.     g_move(x2,y1);
  274.     g_line(x2+x3d,y1+y3d);
  275.     g_line(x2+x3d,y2+y3d);
  276.     g_line(x2,y2);
  277.     g_line(x2,y1);
  278.     if (topcolor!=0) {
  279.        g_set_fill(sidecolor);
  280.        g_fill();
  281.     }
  282.     g_stroke();
  283.     g_newpath();
  284.  
  285.     if (!notop) {    /* now draw top of bar  */
  286.      g_move(x2,y2);
  287.      g_line(x2+x3d,y2+y3d);
  288.      g_line(x1+x3d,y2+y3d);
  289.      g_line(x1,y2);
  290.      g_line(x2,y2);
  291.      if (topcolor!=0) {
  292.         g_set_fill(topcolor);
  293.         g_fill();
  294.      }
  295.      g_stroke();
  296.     }
  297.     g_newpath();
  298.     g_set_path(false);
  299.     g_newpath();
  300.     g_grestore();
  301. }
  302. /*------------------------------------------------------------------*/
  303. /*
  304. /*do_smooth()
  305. /*{
  306. /*    int i,j;
  307. /*    double *x,*y;
  308. /*    for (i=1;i<=ndata;i++) {
  309. /*        if (dp[i]!=NULL) if (dp[i]->smooth && dp[i]->np>3) {
  310. /*            gr_nomiss(i);    /* throw away missing points */
  311. /*            fitbez(&dp[i]->xv,&dp[i]->yv,&dp[i]->miss,&dp[i]->np);
  312. /*        }
  313. /*    }
  314. /*}
  315. */
  316.  
  317. /*------------------------------------------------------------------*/
  318. gr_thrownomiss()
  319. {
  320.     int i,j;
  321.     for (i=1;i<=ndata;i++) {
  322.         if (dp[i]!=NULL) if (dp[i]->nomiss && dp[i]->np>0) {
  323.             gr_nomiss(i);    /* throw away missing points */
  324.         }
  325.     }
  326. }
  327. gr_nomiss(int i)
  328. {
  329.     double *nx,*ny,*xt,*yt,oldlwidth;
  330.     int *m,*nm;
  331.     int dt,dn,k,npnts;
  332.  
  333.     for (dn=1;dn<=ndata;dn++) {
  334.       if (dp[dn]!=NULL) if (dp[dn]->xv!=NULL) {
  335.         k = 0;
  336.         yt = dp[dn]->yv;
  337.         xt = dp[dn]->xv;
  338.         m = dp[dn]->miss;
  339.         nx = xt; ny = yt; nm = m;
  340.         npnts = dp[dn]->np;
  341.         for (i=0;i<(npnts);i++,m++,xt++,yt++) {
  342.             if (!*m) {
  343.                 *nx++ = *xt;
  344.                 *ny++ = *yt;
  345.                 *nm++ = *m;
  346.                 k++;
  347.             }
  348.         }
  349.         dp[dn]->np = k;
  350.       }
  351.     }
  352. }
  353. roundrange(double *gmin,double *gmax)
  354. {
  355.     double delta,st,expnt,n,dticks;
  356.     int ni;
  357.  
  358.     if (*gmax < *gmin) {
  359.         *gmax = 100; *gmin = 10;
  360.         return;
  361.     }
  362.     delta = *gmax - *gmin;
  363.     if (delta==0) return;
  364.     st = delta/10;
  365.     expnt = floor(log10(st));
  366.     n = st/pow(10,expnt);
  367.     if (n>5)
  368.         ni = 10;
  369.     else if (n>2)
  370.         ni = 5;
  371.     else if (n>1)
  372.         ni = 2;
  373.     else
  374.         ni = 1;
  375.  
  376.     dticks = ni * pow(10,expnt);
  377.     if (*gmin ==  floor( *gmin/ dticks) * dticks)
  378.         *gmin = *gmin - dticks;
  379.     else
  380.         *gmin = (floor(*gmin/ dticks) * dticks );
  381.  
  382.     if (( floor( *gmax/ dticks) * dticks) != (*gmax / dticks) * dticks )
  383.         *gmax = floor(*gmax / dticks ) * dticks + dticks;
  384.     else
  385.         *gmax = *gmax  + dticks;
  386. }
  387.  
  388. window_set()
  389. {
  390.     wxmin = range_x1;
  391.     wxmax = range_x2;
  392.     wymin = range_y1;
  393.     wymax = range_y2;
  394.     if (!xx[1].log)  roundrange(&wxmin,&wxmax);
  395.     if (!xx[2].log)  roundrange(&wymin,&wymax);
  396.  
  397.     if (xx[1].minset) wxmin = xx[1].min;
  398.     xx[1].min = wxmin;
  399.     if (!xx[3].minset) xx[3].min = wxmin;
  400.  
  401.     if (xx[1].maxset) wxmax = xx[1].max;
  402.     xx[1].max = wxmax;
  403.     if (!xx[3].maxset) xx[3].max = wxmax;
  404.  
  405.     if (xx[2].minset) wymin = xx[2].min;
  406.     xx[2].min = wymin;
  407.     if (!xx[4].minset) xx[4].min = wymin;
  408.  
  409.     if (xx[2].maxset) wymax = xx[2].max;
  410.     xx[2].max = wymax;
  411.     if (!xx[4].maxset) xx[4].max = wymax;
  412.  
  413.     /* should go thru datasets to find max,min */
  414.     if (wxmin>=wxmax || wymin>=wymax) {
  415.         gprint("Warning no data (or no spread) and no min,max so making up range\n");
  416.         wxmin = 0;
  417.         wxmax = 10;
  418.         wymin = 0;
  419.         wymax = 10;
  420.     }
  421. }
  422. draw_fills()
  423. {
  424.     double x1,y1,x2,y2,ymx,lastx,lasty;
  425.     double *ssxt,*ssyt,*xt,*yt;
  426.     int dt,dn,i,n,*m,npnts,*ssm,free_smoothed=0;
  427.     struct fill_data *ff;
  428.  
  429.     /* set clipping region */
  430.  
  431.     for (n=1;n<=nfd;n++) {
  432.       if (fd[n]->type==0) return;
  433.       done_line = true;
  434.       ff = fd[n];
  435.       if (wxmin > ff->xmin) ff->xmin = wxmin;
  436.       if (wxmax < ff->xmax) ff->xmax = wxmax;
  437.       if (wymin > ff->ymin) ff->ymin = wymin;
  438.       if (wymax < ff->ymax) ff->ymax = wymax;
  439.  
  440.     g_beginclip();        /* saves current clipping */
  441.     g_set_path(true);
  442.     g_newpath();
  443.     g_move(fnx(ff->xmin),fny(ff->ymin));
  444.     g_box_stroke(fnx(ff->xmin),fny(ff->ymin),fnx(ff->xmax),fny(ff->ymax));
  445.     g_clip();        /* sets current path to be clipping */
  446.  
  447.       gntmp = 0;
  448.       dn = ff->da;
  449.       if (dp[dn]==NULL) { gprint("No data in fill dataset at all \n");return;}
  450.       free_smoothed = false;
  451.       yt = dp[dn]->yv;
  452.       xt = dp[dn]->xv;
  453.       m = dp[dn]->miss;
  454.       npnts = dp[dn]->np;
  455.  
  456.         if (dp[dn]->smooth && npnts>3 && npnts<190) {
  457.             gr_nomiss(dn);    /* throw away missing points */
  458.             fitbez(&xt,&yt,&m,&npnts,dp[dn]->smoothm);
  459.             ssxt = xt; ssyt = yt; ssm = m;
  460.             free_smoothed = true;
  461.         }
  462.  
  463.       ymx = ff->ymax;
  464.       if (xt==NULL) { gprint("No data in fill dataset \n"); return;}
  465.       x1 = *xt;
  466.       y1 = *yt;
  467.       switch(ff->type) {
  468.         case 1: /* x1,d1 */
  469.         ymx = ff->ymin;
  470.         case 2: /* d1,x2 */
  471.         fill_vec(*xt,ymx,*xt,*yt);
  472.         for (i=0;i<npnts-1;i++,xt++,yt++) {
  473.             fill_vec(*xt,*yt,*(xt+1),*(yt+1));
  474.         }
  475.         fill_vec(*xt,*yt,*xt,ymx);
  476.         fill_vec(*xt,ymx,*dp[dn]->xv,ymx);
  477.         break;
  478.         case 3: /* d1,d2 */
  479.         for (i=0;i<npnts-1;i++,m++,xt++,yt++) {
  480.             fill_vec(*xt,*yt,*(xt+1),*(yt+1));
  481.             x2 = *(xt+1); y2 = *(yt+1);
  482.         }
  483.         dn = ff->db;
  484.         yt = dp[dn]->yv;
  485.         xt = dp[dn]->xv;
  486.         m = dp[dn]->miss;
  487.         npnts = dp[dn]->np;
  488.  
  489.         if (free_smoothed) {myfrees(ssxt,"Fill1"); myfrees(ssyt,"x"); myfrees(ssm,"y");}
  490.         free_smoothed = false;
  491.         if (dp[dn]->smooth && npnts>3 && npnts<190) {
  492.             gr_nomiss(dn);    /* throw away missing points */
  493.             npnts = dp[dn]->np;
  494.             fitbez(&xt,&yt,&m,&npnts,dp[dn]->smoothm);
  495.             ssxt = xt; ssyt = yt; ssm = m;
  496.             free_smoothed = true;
  497.         }
  498.  
  499.         xt += npnts - 1;
  500.         yt += npnts - 1;
  501.         fill_vec(x2,y2,*xt,*yt);
  502.         for (i=0;i<npnts-1;i++,m--,xt--,yt--)
  503.             fill_vec(*xt,*yt,*(xt-1),*(yt-1));
  504.         fill_vec(*xt,*yt,x1,y1);
  505.         break;
  506.         case 4: /* d1 */
  507.         for (i=0;i<npnts-1;i++,m++,xt++,yt++) {
  508.             if (!*m && !*(m+1))
  509.                 fill_vec(*xt,*yt,*(xt+1),*(yt+1));
  510.         }
  511.         fill_vec(*xt,*yt,x1,y1);
  512.         break;
  513.       }
  514.  
  515.     if (free_smoothed) {myfrees(ssxt,"Fill2"); myfrees(ssyt,"f4"); myfrees(ssm,"f5");}
  516.     /* Paint the region defined */
  517.     g_set_fill(ff->color);
  518.     g_newpath();
  519.     g_move(fnx(tmpf[1]),fny(tmpf[2]));
  520.     lastx = tmpf[1]; lasty=tmpf[2];
  521.     for (i=1;i<=gntmp;i+=4) {
  522.         if (lastx!=tmpf[i] || lasty!=tmpf[i+1])  {
  523.             g_closepath();
  524.             g_move(fnx(tmpf[i]),fny(tmpf[i+1]));
  525.         }
  526.         g_line(fnx(tmpf[i+2]),fny(tmpf[i+3]));
  527.         lastx = tmpf[i+2]; lasty = tmpf[i+3];
  528.     }
  529.     g_closepath();
  530.     g_fill();
  531.     g_set_path(false);
  532.     g_endclip();
  533.     }
  534. }
  535. /*------------------------------------------------------------------*/
  536. fill_vec(double x1, double y1, double x2, double y2)
  537. {
  538.     alloc_temp(gntmp);
  539.     if (tmpf == NULL) {gprint("Ran out of tmp storage for fill \n"); gle_abort("tmp data \n"); }
  540.     tmpf[++gntmp] = x1;
  541.     tmpf[++gntmp] = y1;
  542.     tmpf[++gntmp] = x2;
  543.     tmpf[++gntmp] = y2;
  544. }
  545. int setupdown(char *s, int *doup, int *upd, int *upp, double *upval);
  546. setupdown(char *s, int *doup, int *upd, int *upp, double *upval)
  547. {
  548.     static char vbuf[9];
  549.     int j=0;
  550.  
  551.     *upd = 0;
  552.     *doup = true;
  553.     *upp = false;
  554.     if (*s==0) { *doup=false; return;}
  555.     if (*s=='D') { *upd = atoi(s+1); return; }
  556.     if (strstr(s,"%")!=NULL) { j=1; *upp = true; }
  557.     strncpy(vbuf,s,strlen(s)-j+1);
  558.     *upval = atof(vbuf);
  559. }
  560. /*------------------------------------------------------------------*/
  561. /*     d3 err .1            */
  562. /*     d3 err 10%            */
  563. /*     d3 errup 10% errdown d2        */
  564. /*     d3 err d1 errwidth .2        */
  565. dataset_null(int i)
  566. {
  567.     if (dp[i]==NULL) {
  568.         gprint("Dataset %d doesn't exist at all\n",i);
  569.         return true;
  570.     }
  571.     if (dp[i]->yv == NULL) {
  572.         gprint("Dataset %d doesn't exist\n",i);
  573.         return true;
  574.     }
  575.     return false;
  576. }
  577. #ifdef HERROR        /* because it won't fit on the PC */
  578. draw_herr()
  579. {
  580.     int errup,doup,upd,upp;
  581.     double upval,eup,edown,ewid;
  582.     int errdown,dodown,downd,downp;
  583.     double downval;
  584.     double *xt,*yt,x;
  585.     int *m,mup,mdown;
  586.     int dt,dn,i;
  587.  
  588.     g_gsave();
  589.     for (dn=1;dn<=ndata;dn++) {
  590.       dpp = dp[dn];
  591.       if (dpp!=NULL) if (dpp->herrup[0]!=0 || dpp->herrdown[0]!=0) {
  592.         done_line = true;
  593.         g_get_hei(&x);
  594.         if (dpp->herrwidth==0) dpp->herrwidth = x/3;
  595.         ewid = dpp->herrwidth;
  596.         setupdown(dpp->herrup,&doup,&upd,&upp,&upval);
  597.         setupdown(dpp->herrdown,&dodown,&downd,&downp,&downval);
  598.         g_set_color(dpp->color);
  599.         g_set_line_width(dpp->lwidth);
  600.         windowdn(dn);
  601.         yt = dpp->yv;
  602.         xt = dpp->xv;
  603.         m = dpp->miss;
  604.         if (upd) if (dataset_null(upd)) return;
  605.         if (downd) if (dataset_null(downd)) return;
  606.         for (i=0;i<dpp->np;i++,m++,xt++,yt++) {
  607.             mup = false; mdown = false;
  608.             if (upd) {
  609.                 eup = *(dp[upd]->yv+i);
  610.                 mup = *(dp[upd]->miss+i);
  611.             } else {
  612.                 eup = upval;
  613.                 if (upp) eup = (eup * *xt)/100;
  614.             }
  615.             if (downd) {
  616.                 edown = *(dp[downd]->yv+i);
  617.                 mdown = *(dp[downd]->miss+i);
  618.             } else {
  619.                 edown = downval;
  620.                 if (downp) edown = (edown * *xt)/100;
  621.             }
  622.             /* if (eup!=-999) { */
  623.              if (doup) if (!*m) if (!mup) draw_herrbar(*xt,*yt,eup,ewid);
  624.              if (dodown) if (!*m) if (!mdown) draw_herrbar(*xt,*yt,-edown,ewid);
  625.             /* } */
  626.         }
  627.         windownorm();
  628.       }
  629.     }
  630. exit_err:;
  631.     g_grestore();
  632. }
  633. draw_herrbar(double x, double y, double eup, double ewid)
  634. {
  635.     if (x>=wxmin && x<=wxmax && y>=wymin && y<=wymax ) {
  636.         g_move(fnx(x),fny(y));
  637.         g_line(fnx(x-eup),fny(y));
  638.         g_move(fnx(x-eup),-ewid/2+fny(y));
  639.         g_line(fnx(x-eup),ewid/2+fny(y));
  640.     }
  641. }
  642. #endif
  643. draw_err()
  644. {
  645.     int errup,doup,upd,upp;
  646.     double upval,eup,edown,ewid;
  647.     int errdown,dodown,downd,downp,big;
  648.     double downval;
  649.     double *xt,*yt,x;
  650.     int *m,mup,mdown;
  651.     int dt,dn,i;
  652.  
  653.     g_gsave();
  654.     for (dn=1;dn<=ndata;dn++) {
  655.       big = false;
  656.       dpp = dp[dn];
  657.       if (dpp!=NULL) if (dpp->errup[0]!=0 || dpp->errdown[0]!=0) {
  658.         if (dpp->bigfile!=NULL) {
  659.             big = true;
  660.             big_open(dpp->bigfile);
  661.            }
  662.         done_line = true;
  663.         g_get_hei(&x);
  664.         if (dpp->errwidth==0) dpp->errwidth = x/3;
  665.         ewid = dpp->errwidth;
  666.         setupdown(dpp->errup,&doup,&upd,&upp,&upval);
  667.         setupdown(dpp->errdown,&dodown,&downd,&downp,&downval);
  668.         g_set_color(dpp->color);
  669.         g_set_line_width(dpp->lwidth);
  670.         windowdn(dn);
  671.         yt = dpp->yv;
  672.         xt = dpp->xv;
  673.         m = dpp->miss;
  674.         if (upd) if (dataset_null(upd)) return;
  675.         if (downd) if (dataset_null(downd)) return;
  676.         if (big) {{
  677.              double x1,y1,x2,y2;
  678.              int m1,m2;
  679.  
  680.             if (fptr==NULL) goto endbigm;
  681.             if (feof(fptr))  goto xxx;
  682.             for (;;) {
  683. aaa2:
  684.                 if (feof(fptr) || abort_key())  goto xxx;
  685.                 big_line(&x1,&y1,&m2);
  686.                 if (m2) goto aaa2;
  687.                 mup = false; mdown = false;
  688.                 if (upd) {
  689.                     eup = *(dp[upd]->yv+i);
  690.                     mup = *(dp[upd]->miss+i);
  691.                 } else {
  692.                     eup = upval;
  693.                     if (upp) eup = (eup * y1)/100;
  694.                 }
  695.                 if (downd) {
  696.                     edown = *(dp[downd]->yv+i);
  697.                     mdown = *(dp[downd]->miss+i);
  698.                 } else {
  699.                     edown = downval;
  700.                     if (downp) edown = (edown * y1)/100;
  701.                 }
  702.                 if (doup) if (!mup) draw_errbar(x1,y1,eup,ewid);
  703.                 if (dodown) if (!mdown) draw_errbar(x1,y1,-edown,ewid);
  704.             }
  705. xxx:            fclose(fptr); fptr=NULL;
  706. endbigm:        ;
  707.         }} else {
  708.           for (i=0;i<dpp->np;i++,m++,xt++,yt++) {
  709.             mup = false; mdown = false;
  710.             if (upd) {
  711.                 eup = *(dp[upd]->yv+i);
  712.                 mup = *(dp[upd]->miss+i);
  713.             } else {
  714.                 eup = upval;
  715.                 if (upp) eup = (eup * *yt)/100;
  716.             }
  717.             if (downd) {
  718.                 edown = *(dp[downd]->yv+i);
  719.                 mdown = *(dp[downd]->miss+i);
  720.             } else {
  721.                 edown = downval;
  722.                 if (downp) edown = (edown * *yt)/100;
  723.             }
  724.             /* if (eup!=-999) { */
  725.              if (doup) if (!*m) if (!mup) draw_errbar(*xt,*yt,eup,ewid);
  726.              if (dodown) if (!*m) if (!mdown) draw_errbar(*xt,*yt,-edown,ewid);
  727.             /* } */
  728.           }
  729.         }
  730.         windownorm();
  731.       }
  732.     }
  733. exit_err:;
  734.     g_grestore();
  735. #ifdef HERROR
  736.     draw_herr();
  737. #endif
  738. }
  739. draw_errbar(double x, double y, double eup, double ewid)
  740. {
  741.     if (x>=wxmin && x<=wxmax && y>=wymin && y<=wymax ) {
  742.         g_move(fnx(x),fny(y));
  743.         g_line(fnx(x),fny(y+eup));
  744.         g_move(fnx(x)-ewid/2,fny(y+eup));
  745.         g_line(fnx(x)+ewid/2,fny(y+eup));
  746.     }
  747. }
  748. double dwx1,dwy1,dwx2,dwy2;
  749. windowdn(int d)
  750. {
  751.     dwx1 = wxmin; dwy1 = wymin; dwx2 = wxmax; dwy2 = wymax;
  752.     if (dp[d]==NULL) return;
  753.     if (dp[d]->xmax > dp[d]->xmin) {
  754.         wxmin = dp[d]->xmin; wxmax = dp[d]->xmax;
  755.     }
  756.     if (dp[d]->ymax > dp[d]->ymin) {
  757.         wymin = dp[d]->ymin; wymax = dp[d]->ymax;
  758.     }
  759. }
  760. windownorm()
  761. {
  762.     wxmin = dwx1 ; wymin = dwy1 ; wxmax = dwx2 ; wymax = dwy2 ;
  763. }
  764. draw_lines()
  765. {
  766.     double *ssxt,*ssyt,*xt,*yt,oldlwidth;
  767.     int *m,*ssm;
  768.     char oldlstyle[10];
  769.     int dt,dn,i,npnts,free_smoothed,big;
  770.  
  771.     g_gsave();
  772.     g_get_line_style(oldlstyle);
  773.     g_get_line_width(&oldlwidth);
  774.     for (dn=1;dn<=ndata;dn++) {
  775.       big = false;
  776.       last_vecx = 1e10;
  777.       last_vecy = 1e10;
  778.       if (dp[dn]!=NULL) {
  779.        if (dp[dn]->bigfile!=NULL) {
  780.         big=true;
  781.         big_open(dp[dn]->bigfile);
  782.        }
  783.        if (dp[dn]->xv!=NULL || big)
  784.         if (dp[dn]->line==true || dp[dn]->lstyle[0]!=0) {
  785.         free_smoothed = false;
  786.         g_set_line_style(oldlstyle); /* use defualts for each */
  787.         g_set_line_width(oldlwidth); /* use defaults for each */
  788.         g_set_line_style(dp[dn]->lstyle);
  789.         g_set_color(dp[dn]->color);
  790.         g_set_line_width(dp[dn]->lwidth);
  791.         windowdn(dn);
  792.         done_line = true;
  793.         yt = dp[dn]->yv;
  794.         xt = dp[dn]->xv;
  795.         m = dp[dn]->miss;
  796.         npnts = dp[dn]->np;
  797.  
  798.         if (dp[dn]->smooth && npnts>3 && npnts<190) {
  799.             /* (BUG, gr_nomiss has not been written HAS NOW !!! */
  800.             gr_nomiss(dn);    /* throw away missing points */
  801.             npnts = dp[dn]->np;
  802.             fitbez(&xt,&yt,&m,&npnts,dp[dn]->smoothm);
  803.             ssxt = xt; ssyt = yt; ssm = m;
  804.             free_smoothed = true;
  805.         }
  806.  
  807.         if (big) big_vec(dp[dn]->nomiss);
  808.         else {
  809.           for (i=0;i<(npnts-1);i++,m++,xt++,yt++) {
  810.             if (!*m && !*(m+1))
  811.                 draw_vec(*xt,*yt,*(xt+1),*(yt+1));
  812.           }
  813.         }
  814.         if (free_smoothed) {myfrees(ssxt,"Line1"); myfrees(ssyt,"l2"); myfrees(ssm,"l3");}
  815.         windownorm();
  816.       }
  817.       big_close();
  818.      }
  819.     }
  820.     g_grestore();
  821. }
  822. big_vec(int nomiss)
  823. {
  824.     double x1,y1,x2,y2;
  825.     int m1,m2;
  826.  
  827.  
  828.     if (fptr==NULL) return;
  829. aaa:
  830.     if (feof(fptr))  goto xxx;
  831.     big_line(&x1,&y1,&m1);
  832.     if (m1) goto aaa;
  833.     for (;;) {
  834. aaa2:
  835.         if (feof(fptr) || abort_key())  break;
  836.         big_line(&x2,&y2,&m2);
  837.         if (nomiss && m2) goto aaa2;
  838.         if (!m1 && !m2) draw_vec(x1,y1,x2,y2);
  839.         x1 = x2; y1 = y2; m1 = m2;
  840.     }
  841. xxx:    fclose(fptr); fptr = NULL;
  842. }
  843. big_close()
  844. {
  845.     if (fptr!=NULL) fclose(fptr);
  846.     fptr = NULL;
  847. }
  848. big_mark(int mnum, double msize)
  849. {
  850.     double x1,y1,x2,y2;
  851.     int m1,m2;
  852.  
  853.  
  854.     if (fptr==NULL) return;
  855.     if (feof(fptr))  goto xxx;
  856.     for (;;) {
  857. aaa2:
  858.         if (feof(fptr) || abort_key())  break;
  859.         big_line(&x1,&y1,&m2);
  860.         if (m2) goto aaa2;
  861.         draw_mark(x1,y1,mnum,msize,1.0);
  862.     }
  863. xxx:    fclose(fptr); fptr=NULL;
  864. }
  865. draw_vec(double x1,double y1,double x2,double y2)
  866. {
  867.     int invis;
  868.     if (x1>=wxmin && x1<=wxmax && y1>=wymin && y1<=wymax
  869.        && x2 >= wxmin && x2<=wxmax && y2>=wymin && y2<=wymax);
  870.     else {         /* ok one or both are outside our box */
  871.         gclip(&x1,&y1,&x2,&y2,wxmin,wymin,wxmax,wymax,&invis);
  872.         if (invis) return;
  873.     }
  874.     if (x1!=last_vecx || y1!=last_vecy) {
  875.         g_move(fnx(x1),fny(y1));
  876.     }
  877.     g_line(fnx(x2),fny(y2));
  878.     last_vecx = x2;
  879.     last_vecy = y2;
  880. }
  881. /*---------------------------------------------------------------------------*/
  882. draw_markers()
  883. {
  884.     double msize;
  885.     double *yd,dval,*xt,*yt,oldlwidth;
  886.     char oldlstyle[10];
  887.     int *m;
  888.     int dt,dn,i,big;
  889.  
  890.     g_gsave();
  891.     g_get_line_style(oldlstyle);
  892.     g_get_line_width(&oldlwidth);
  893.     for (dn=1;dn<=ndata;dn++) {
  894.       big = false;
  895.       last_vecx = 1e10;
  896.       last_vecy = 1e10;
  897.       if (dp[dn]!=NULL) if (dp[dn]->marker!=0) {
  898.         if (dp[dn]->bigfile!=NULL) {
  899.             big=true;
  900.             big_open(dp[dn]->bigfile);
  901.         } else big = false;
  902.         g_set_line_width(oldlwidth); /* use defaults for each */
  903.         g_set_color(dp[dn]->color);
  904.         g_set_line_width(dp[dn]->lwidth);
  905.         windowdn(dn);
  906.         done_line = true;
  907.         yt = dp[dn]->yv;
  908.         xt = dp[dn]->xv;
  909.         m = dp[dn]->miss;
  910.         msize = dp[dn]->msize;
  911.         if (msize==0) msize = g_fontsz*.6;
  912.         if (dp[dn]->mscale != 0) msize = msize* dp[dn]->mscale;
  913.         if (big) big_mark(dp[dn]->marker,msize);
  914.         else {
  915.          if (dp[dn]->mdata!=0) yd = dp[dp[dn]->mdata]->yv;
  916.          for (i=0;i<dp[dn]->np;i++,m++,xt++,yt++,yd++) {
  917.             if (!*m) {
  918.                 if (dp[dn]->mdata==0) dval = 1; else dval = *yd;
  919.                 draw_mark(*xt,*yt,dp[dn]->marker,msize,dval);
  920.             }
  921.          }
  922.         }
  923.         windownorm();
  924.       }
  925.     }
  926.     g_grestore();
  927. }
  928. /*---------------------------------------------------------------------------*/
  929. draw_mark(double x, double y,int mrk, double msize, double dval)
  930. {
  931.     /* globals   *** xmin, xmax, ymin, ymax,  ox,oy,  xbl, ybl */
  932.     if (x >= wxmin && x<=wxmax && y>=wymin && y<=wymax) {
  933.         g_move(fnx(x),fny(y));
  934.         g_marker2(mrk,msize,dval);
  935.     }
  936. }
  937. /*---------------------------------------------------------------------------*/
  938. box_clip(double *x,double *y,double wxmin,double wymin,double wxmax,double wymax)
  939. {
  940.     if (*x > wxmax) *x = wxmax;
  941.     if (*y > wymax) *y = wymax;
  942.     if (*x < wxmin) *x = wxmin;
  943.     if (*y < wymin) *y = wymin;
  944. }
  945. gclip(double *x1,double *y1,double *x2,double *y2
  946.         ,double xmin,double ymin,double xmax,double ymax,int *invis)
  947. {
  948.     double dx,dy;
  949.  
  950.     *invis = true;
  951.     if (*x2 > xmax) {
  952.         if (*x1 > xmax) return;
  953.         dx = *x2 - *x1;
  954.         dy = *y2 - *y1;
  955.         if (dx==0) return;
  956.         *y2 = *y1 + dy*(xmax-*x1)/dx;
  957.         *x2 = xmax;
  958.     }
  959.     if (*x1 > xmax) {
  960.         dx = *x1 - *x2;
  961.         dy = *y1 - *y2;
  962.         if (dx==0) return;
  963.         *y1 = *y2 + dy*(xmax-*x2)/dx;
  964.         *x1 = xmax;
  965.     }
  966.     if (*y2 > ymax) {
  967.         if (*y1 > ymax) return;
  968.         dy = *y2 - *y1;
  969.         dx = *x2 - *x1;
  970.         if (dy==0) return;
  971.         *x2 = *x1 + dx*(ymax-*y1)/dy;
  972.         *y2 = ymax;
  973.     }
  974.     if (*y1 > ymax) {
  975.         dx = *x1 - *x2;
  976.         dy = *y1 - *y2;
  977.         if (dy==0) return;
  978.         *x1 = *x2 + dx*(ymax-*y2)/dy;
  979.         *y1 = ymax ;
  980.     }
  981.     if (*x2 < xmin) {
  982.         if (*x1 < xmin) return;
  983.         dx = *x2 - *x1;
  984.         dy = *y2 - *y1;
  985.         if (dx==0) return;
  986.         *y2 = *y1 + dy*(xmin-*x1)/dx;
  987.         *x2 = xmin;
  988.     }
  989.     if (*x1 < xmin) {
  990.         dx = *x1 - *x2 ;
  991.         dy = *y1 - *y2 ;
  992.         if (dx==0) return;
  993.         *y1 = *y2 + dy*(xmin-*x2)/dx;
  994.         *x1 = xmin;
  995.     }
  996.     if (*y2 < ymin) {
  997.         if (*y1 < ymin) return;
  998.         dy = *y2 - *y1;
  999.         dx = *x2 - *x1;
  1000.         if (dy==0) return;
  1001.         *x2 = *x1 + dx*(ymin-*y1)/dy;
  1002.         *y2 = ymin;
  1003.     }
  1004.     if (*y1 < ymin) {
  1005.         dy = *y1 - *y2;
  1006.         dx = *x1 - *x2;
  1007.         if (dy==0) return;
  1008.         *x1 = *x2 + dx*(ymin-*y2)/dy;
  1009.         *y1 = ymin;
  1010.     }
  1011.     *invis = false;
  1012. }
  1013. axis_type(char *s)
  1014. {
  1015.     if (strncmp(s,"X2",2)==0) return 3;
  1016.     if (strncmp(s,"Y2",2)==0) return 4;
  1017.     if (strncmp(s,"X",1)==0) return 1;
  1018.     if (strncmp(s,"Y",1)==0) return 2;
  1019.     gprint("axis type did not match {%s} assuming xaxis \n",s);
  1020.     return 1;
  1021. }
  1022. vinit_axis(int i)
  1023. {
  1024.     long c;
  1025.     memset(&xx[i],0,sizeof(xx[i]));
  1026.     g_get_color(&c);
  1027.     xx[i].color = c;
  1028.     xx[i].side_color = c;
  1029.     xx[i].ticks_color = c;
  1030.     xx[i].label_color = c;
  1031.     xx[i].subticks_color = c;
  1032.      xx[i].side_lwidth = -1;
  1033.      xx[i].ticks_lwidth = -1;
  1034.      xx[i].subticks_lwidth = -1;
  1035.      xx[i].label_lwidth = -1;
  1036.     xx[i].type = i;
  1037.     if (i>2) xx[i].label_off = true;
  1038. }
  1039. doskip(char *s,int *ct)
  1040. {
  1041.     if (*s==' ') (*ct)++;
  1042. }
  1043. int polish_eval(char *exp, double *x);
  1044. double get_next_exp(char (*(*tk)[]),int *ntok,int *curtok)
  1045. {
  1046.     static int elen,etype,cp,i;
  1047.     static double x;
  1048.  
  1049.     (*curtok)++;
  1050.     cp = 0;
  1051.     elen = 0;
  1052.     etype = 1;
  1053.     dbg for (i=1;i<=*ntok;i++)  gprint("{%s} ",(*tk)[i]);
  1054.     dbg gprint("\n");
  1055.     dbg gprint("**get exp token ct %d  {%s} \n",*curtok,(*tk)[*curtok]);
  1056.     polish_eval((*tk)[*curtok],&x);
  1057.     return x;
  1058. }
  1059. polish_eval(char *exp, double *x)
  1060. {
  1061.     static long ebuff[300];
  1062.     static char ostr[20];
  1063.     static int elen,etype,cp,otyp;
  1064.     cp = 0;
  1065.     elen = 0;
  1066.     etype = 1;
  1067.     polish(exp,(char *) &ebuff,&elen,&etype);
  1068.     eval(ebuff,&cp,x,ostr,&otyp);
  1069. }
  1070. checktok(char *t, char *want)
  1071. {
  1072.     if (strcmp(t,want)==0) return true;
  1073.     else {
  1074.         gprint("Found token {%s} Wanted {%s} \n",t,want);
  1075.         return false;
  1076.     }
  1077. }
  1078. /*  LET d2 = exp(x) [ FROM exp TO exp [ STEP exp ] ]    */
  1079. /*  LET d3 = exp(dn,d...)                */
  1080. do_let(char *letcmd)
  1081. {
  1082.         static char *tk[200];
  1083.     static int ndn,dn_idx[11],dn_var[11];
  1084.         static char tkbuff[200];
  1085.     static int ntk,ct,i,elen,etype,dn,cp,savect,tt,dd,np,j;
  1086.     double letfrom,letto,letstep,ix;
  1087.     int varx,npnts,*newmiss;
  1088.     double *xt,*yt,*xf,logstep,*newx,*newy;
  1089.     int *mt,*mm;
  1090.     static char ostr[20];
  1091.     int gotfrom,vartype,otyp;
  1092.         double x,y,ox,oy;
  1093.         static char space_str[] = " ";
  1094.  
  1095.     if (tk[199]==NULL) for (i=0;i<200;i++) tk[i] = space_str;
  1096.     token(letcmd,(TOKENS) tk,&ntk,tkbuff);
  1097.     ct = 2;
  1098.  
  1099.     dd = atoi(tk[ct]+1);
  1100.     ct++;
  1101.     if (strcmp(tk[ct],"=")!=0) {
  1102.         gprint("%s\n",letcmd);
  1103.         gprint("Found {%s} When expecting {=} at token %d \n",tk[ct]
  1104.             ,ct);
  1105.         return;
  1106.     }
  1107.     ct++;
  1108.     savect = ct;
  1109.     gotfrom = false;
  1110.     for (ct=savect;ct<=ntk;ct++) {
  1111.         if (strcmp(tk[ct],"FROM")==0) {
  1112.             gotfrom = true;
  1113.             letfrom = get_next_exp((TOKENS) tk,&ntk,&ct);
  1114.             ct++;
  1115.             if (!checktok(tk[ct],"TO")) return;
  1116.             letto = get_next_exp((TOKENS) tk,&ntk,&ct);
  1117.             ct++;
  1118.             if (strcmp(tk[ct],"STEP")==0) {
  1119.                 letstep = get_next_exp((TOKENS) tk,&ntk,&ct);
  1120.                 ct++;
  1121.             } else
  1122.                 letstep = (letto-letfrom)/100;
  1123.             ct = ntk;
  1124.         }
  1125.     }
  1126.  
  1127.     var_set_local();
  1128.     var_alloc_local();
  1129.     ct = savect;
  1130.     elen = 0;
  1131.     etype = 1;
  1132.     polish(tk[ct],(char *) &ebuff,&elen,&etype);
  1133.  
  1134.     ndn = 0;
  1135.     if (!gotfrom) {
  1136.         dn_var[0]=12; dn_idx[0]=111;
  1137.         var_find_dn(dn_idx, dn_var, &ndn);
  1138.         if (ndn==0) {
  1139.             gprint("Expecting    FROM exp TO exp [ STEP exp] \n");
  1140.             gprint("or expression containing Dataset d1,d2 etc\n");
  1141.             gprint("But only got {%s}\n",letcmd);
  1142.         }
  1143.     }
  1144.  
  1145.  
  1146.     dn = dn_var[0];
  1147.     if (ndn>0)     np = dp[dn]->np;
  1148.     else {
  1149.         np = (letto-letfrom)/letstep + 1;
  1150.         if (xx[1].log==true) {
  1151.          if (letstep<9 || letstep>300) {
  1152.            letstep=60;
  1153.            gprint("Due to LOG xaxis stepsize is taken as number of steps (set to 60)\n");
  1154.          }
  1155.          np = letstep*2;
  1156.          letstep = letstep/3;
  1157.          logstep = 1+ (log10(letto)-log10(letfrom)) /((double) letstep);
  1158.         }
  1159.     }
  1160. /*    dbg for (i=ndata;i<=dd;i++) printf("dat apointer [%d] %p \n",i,dp[i]);
  1161. */
  1162.  
  1163.     if (ndata<dd) ndata = dd;
  1164.     if (dp[dd]==NULL) {
  1165.         dp[dd] = myallocz(sizeof(*dp[dd]));
  1166.         copy_default(dd);
  1167.     }
  1168.     /* copy default dataset settings */
  1169.     if (dp[dd]==NULL) gprint("Memory allocation error, graph dataset \n");
  1170.     np++;
  1171.     if (dp[dd]->xv != NULL) gprint("Over writing dataset %d \n",dd);
  1172.     newx = myallocz(sizeof(x)*np);
  1173.     newy = myallocz(sizeof(x)*np);
  1174.     newmiss = myallocz(sizeof(i)*np);
  1175.     np--;
  1176.     dp[dd]->np = np;
  1177.     xt = newx ; yt = newy; mt = newmiss;
  1178.  
  1179.     npnts = 0;
  1180.     var_find("X",&varx,&vartype);
  1181.     dn = dn_var[0];
  1182.     if (ndn>0) {
  1183.         xf = dp[dn]->xv;
  1184.         mm = dp[dn]->miss;
  1185.         for (i=0;i<dp[dn]->np;i++,xf++,mm++) {
  1186.             if (varx>=0) var_set(varx,*xf);
  1187.             for (j=0;j<ndn;j++) {
  1188.                 if (dp[dn_var[j]] == NULL) {
  1189.                     gprint("Dataset not defined {%d} \n",dn_var[j]);
  1190.                 } else {
  1191.                     var_set(dn_idx[j],dp[dn_var[j]]->yv[i]);
  1192.                 }
  1193.             }
  1194.             cp = 0;
  1195.             eval((long *) ebuff,&cp,&x,ostr,&otyp);
  1196.             if (! *mm) {
  1197.                 npnts++;
  1198.                 *(xt++) = *xf;
  1199.                 *(yt++) = x;
  1200.                 *(mt++) = 0;
  1201.                 setrange(*xf,x,0);
  1202.             }
  1203.          }
  1204.     } else {
  1205.         for (ix=letfrom;ix<=letto  && npnts<np ;) {
  1206.             if (varx>=0) var_set(varx,ix);
  1207.             cp = 0;
  1208.             eval((long *) ebuff,&cp,&x,ostr,&otyp);
  1209.             npnts++;
  1210.             *(xt++) = ix;
  1211.             *(yt++) = x;
  1212.             *(mt++) = 0;
  1213.             setrange(ix,x,0);
  1214.             if (xx[1].log==true) {
  1215.                 ix = ix*logstep;
  1216.                 if (ix>letto) ix = letto;
  1217.             } else ix+=letstep;
  1218.         }
  1219.     }
  1220.     dp[dd]->np = npnts;
  1221.     dp[dd]->miss = newmiss;
  1222.     dp[dd]->xv = newx;
  1223.     dp[dd]->yv = newy;
  1224.     var_free_local();
  1225.     var_clear_local();
  1226.     var_set_global();
  1227. }
  1228. struct key_struct {
  1229.     char lstyle[9];
  1230.     long color,fill;
  1231.     int marker;
  1232.     double msize,lwidth;
  1233.     char *descrip;
  1234. };
  1235. extern struct key_struct *kd[100];
  1236. int draw_key(int nkd, double koffsetx, double koffsety, char *kpos
  1237.     ,double khei, int knobox);
  1238. gdraw_key(double koffsetx, double koffsety, char *kpos, double khei, int knobox)
  1239. {
  1240.     int dt,dn,i,nkd;
  1241.  
  1242.     nkd = 0;
  1243.     for (dn=1;dn<=ndata;dn++) {
  1244.       if (dp[dn]!=NULL) if (dp[dn]->key_name!=NULL) {
  1245.         kd[++nkd] = myallocz(sizeof(*kd[1]));
  1246.         kd[nkd]->fill = dp[dn]->key_fill;
  1247.         kd[nkd]->color = dp[dn]->color;
  1248.         kd[nkd]->lwidth = dp[dn]->lwidth;
  1249.         kd[nkd]->marker = dp[dn]->marker;
  1250.         kd[nkd]->msize = dp[dn]->msize;
  1251.         strcpy(kd[nkd]->lstyle,dp[dn]->lstyle);
  1252.         if (kd[nkd]->lstyle[0]==0) if (dp[dn]->line==true)
  1253.             kd[nkd]->lstyle[0]='1';
  1254.         mystrcpy(&kd[nkd]->descrip,dp[dn]->key_name);
  1255.       }
  1256.     }
  1257.     draw_key(nkd,koffsetx,koffsety,kpos,khei,knobox);
  1258.     for (i=1;i<=nkd;i++) {
  1259.         if (kd[i]->descrip != NULL) myfrees(kd[i]->descrip,"GKEY");
  1260.         myfrees(kd[i],"GKEY1");
  1261.     }
  1262. }
  1263. /*----------------------------------------------------------------*/
  1264. #define next_dn  (ct+=1,skipspace,atoi(tk[ct]+1))
  1265. do_dataset(int d)
  1266. {
  1267.     int ct=2;
  1268.     while (ct<=ntk)  {
  1269.          kw("LINE")     dp[d]->line = true;
  1270.     else kw("LSTYLE")     next_str(dp[d]->lstyle);
  1271.     else kw("LWIDTH")     dp[d]->lwidth = next_exp;
  1272.     else kw("MARKER")     dp[d]->marker = next_marker;
  1273.     else kw("MDATA")     dp[d]->mdata = next_dn;
  1274.     else kw("COLOR")     dp[d]->color = next_color;
  1275.     else kw("KEYFILL")     dp[d]->key_fill = next_color;
  1276.     else kw("MSIZE")     dp[d]->msize = next_exp;
  1277.     else kw("MSCALE")     dp[d]->mscale = next_exp;
  1278.     else kw("KEY")         next_vquote(dp[d]->key_name);
  1279.     else kw("AUTOSCALE")     dp[d]->autoscale = true;
  1280.     else kw("AUTO")     dp[d]->autoscale = true;
  1281.     else kw("NOMISS")     dp[d]->nomiss = true;
  1282.     else kw("NOMISSING")     dp[d]->nomiss = true;
  1283.     else kw("BIGFILE")     next_vquote(dp[d]->bigfile);
  1284.     else kw("SMOOTH")     {
  1285.         dp[d]->smoothm = false;
  1286.         dp[d]->smooth = true;
  1287.         dp[d]->line = true;
  1288.     }
  1289.     else kw("SMOOTHM")     {
  1290.         dp[d]->smoothm = true;
  1291.         dp[d]->smooth = true;
  1292.         dp[d]->line = true;
  1293.     }
  1294.     else kw("XMIN")     dp[d]->xmin = next_exp;
  1295.     else kw("XMAX")     dp[d]->xmax = next_exp;
  1296.     else kw("YMIN")     dp[d]->ymin = next_exp;
  1297.     else kw("YMAX")     dp[d]->ymax = next_exp;
  1298. #ifdef HERROR         /* because it won't fit on the PC */
  1299.     else kw("HERR") {
  1300.         next_str(dp[d]->herrup);
  1301.         strcpy(dp[d]->herrdown, dp[d]->herrup);
  1302.     }
  1303.     else kw("HERRLEFT")    next_str(dp[d]->herrup);
  1304.     else kw("HERRRIGHT")    next_str(dp[d]->herrdown);
  1305.     else kw("HERRWIDTH")    dp[d]->herrwidth = next_exp;
  1306. #endif
  1307.     else kw("ERR") {
  1308.         next_str(dp[d]->errup);
  1309.         strcpy(dp[d]->errdown, dp[d]->errup);
  1310.     }
  1311.     else kw("ERRUP")    next_str(dp[d]->errup);
  1312.     else kw("ERRDOWN")    next_str(dp[d]->errdown);
  1313.     else kw("ERRWIDTH")    dp[d]->errwidth = next_exp;
  1314.     else gprint("Unrecognised GRAPH DN sub command {%s} \n ",tk[ct]);
  1315.     ct++;
  1316.     }
  1317. }
  1318. double graph_xgraph(double v)
  1319. {
  1320.     double vvv;
  1321.     if (graph_xmax == graph_xmin) return 0.0;
  1322.     if (xx[1].log==true) {
  1323.         vvv = graph_x1 +
  1324.              (log10(v)-log10(graph_xmin))/(log10(graph_xmax)
  1325.             -log10(graph_xmin))
  1326.             * (graph_x2-graph_x1) ;
  1327.     } else {
  1328.         vvv = graph_x1 +  ((v-graph_xmin)/(graph_xmax-graph_xmin))
  1329.                 * (graph_x2-graph_x1);
  1330.     }
  1331.     return vvv;
  1332. }
  1333. double graph_ygraph(double v)
  1334. {
  1335.     double vvv;
  1336.     if (graph_ymax == graph_ymin) return 0.0;
  1337.     if (xx[2].log==true) {
  1338.         vvv = graph_y1 +
  1339.              (log10(v)-log10(graph_ymin))/(log10(graph_ymax)
  1340.             -log10(graph_ymin))
  1341.             * (graph_y2-graph_y1) ;
  1342.         return vvv;
  1343.     } else {
  1344.          return graph_y1 +  ((v-graph_ymin)/(graph_ymax-graph_ymin)) * (graph_y2-graph_y1);
  1345.     }
  1346. }
  1347.