#include <stdio.h>
#include <exec/types.h>
#include <exec/memory.h>
#include <intuition/intuition.h>
#include "mp.h"
#include "struct.h"

#define MAXCOLUMNS 10

extern int debug;

extern char *getwrd();
extern void trch();
extern int same(), numeric();
struct Plot *GetStructPlot();

/***************************************************************************
*     GetDat finds numeric data in a text file and stores it in arrays.
*
*     GetDat reads a text file whose handle is pointed to by 'fp'.  In
*  this file are expected to be lines containing "words" [of arbitrary
*  length, delimited by blanks, tabs, or commas.] In each line, the first
*  word will be pointed to by 'wp[0]'; the user thinks of this
*  word as being in column 1.  'wp[1]' will point to the next word,
*  etc.  GetDat is primarily interested in those words which look like
*  numbers.
*  
*     The user has assigned column numbers to the variables x, y, and e. 
*  She wants GetDat to find all the lines which contain numbers in those
*  columns and save the numbers in the arrays 'x[]', 'y[]', 'e[]'. 
*  Further, successive lines which contain numbers in the columns of
*  interest are to be treated as a list [possibly delimited by lines
*  which don't contain numbers in the columns of interest.]
*  Finally, the number of lists and the numbers of lines
*  in each list are to be saved in the data structure pointed to by the
*  argument 'Pict'. 
*  
*     Special handling: If the column associated with 'x[]' is given as 0,
*  the 'x[]' array is to be filled as if the x-columns of each list
*  contained [0,1,2...].  If the column associated with 'e[]' is 0, the
*  'e[]' array is not to be filled at all.
*  
*     Lines which begin with "*SCALFACT*" contain scale factors by which
*  collected data is to be multiplied.  Scale factor columns map to data
*  columns after the keyword "*SCALFACT*" is discarded. 
*  
*     Lines which begin with "*TITLE*", "*XLABEL*", and "*YLABEL*" are
*  interpreted as text to be stored in the structure pointed to by
*  'Pict'.  The keyword "*...*" and the blanks, tabs, or commas following
*  it are discarded. 
*
*************************************/

#define COLUMN_OK(z) (z<0 ? TRUE : numeric(wp[z]))
#define LINE_IS_DATA (COLUMN_OK(xcol) && COLUMN_OK(ycol) && COLUMN_OK(ecol))
#define DATA(z) (fact[(z)]*atoFFP(wp[(z)]))
#define PLOT_OPENED (Plot->NPts && !PlotClosed)

FFP fact[MAXCOLUMNS];                /* SCALE FACTORS */
short maxcol;    /* LARGEST OF ARGS: XCOL, YCOL, ECOL */
char title[80], xlabel[80], ylabel[80];

/********************************************/
void GetDat(fp, xcol, ycol, ecol, terse, Pict)
FILE *fp;
int xcol, ycol, ecol;   /* column numbers to be inspected */
int terse;              /* false => echo non-numeric lines to stdout */
struct Pict *Pict;      /* contains info for plotting this data */
{
   short i, PlotClosed = FALSE, Continued = FALSE;
   short xcoord = 0;
   char cbuf[100], *cb, *wp[MAXCOLUMNS];
   struct Plot *Plot, *PrevPlot;
   FFP *x, *y, *e;
   
/*** INITIALIZE ***/

   /* TRANSLATE from user column numbers to array indices, FIND max */
   xcol--; ycol--; ecol--; maxcol = max(xcol,max(ycol,ecol));
   if (debug) printf("GetDat: x, y, e columns: %d,%d,%d\n",xcol,ycol,ecol);
   for (i=0; i<=maxcol; i++) fact[i] = 1.;   /* init scale factors */
   Pict->NPlt = 0;
   Pict->Plot = GetStructPlot();
   Plot = Pict->Plot;
   x = Plot->x; y = Plot->y; e = Plot->e;

/*** GET DATA ***/

   /* FIND list(s) of numbers in file, GET numbers in x,y(,e) arrays */
   while (cb = fgets(cbuf,100,fp)) {

      trch('\n',0,cb); trch('\t',' ',cbuf); trch(',',' ',cbuf);

      if (!KeyWord(cb,Pict)) {

         for (i=0; i<=maxcol; i++) wp[i] = getwrd(&cb);

         if (LINE_IS_DATA) {
            if (PlotClosed) {
               /* allocate, link, SET UP FOR NEW PLOT */
               Plot->NextPlot = GetStructPlot(); Plot = Plot->NextPlot;
               x = Plot->x; y = Plot->y; e = Plot->e;
               PlotClosed = FALSE; xcoord = 0;
            }
            else if (Plot->NPts == MAXPOINTS) {
               /* allocate, link, SET UP FOR CONTINUATION OF CURRENT PLOT */
               Continued = TRUE; PrevPlot = Plot;
               Plot->NextPlot = GetStructPlot(); Plot = Plot->NextPlot;
               x = Plot->x; y = Plot->y; e = Plot->e;
            }
            else if (Continued)
               {PrevPlot->Continued = TRUE; Continued = FALSE;}

            /*** PAYLOAD ***/
            /* STORE data in arrays, COUNT points */
            *(x++) = ( xcol>=0 ? DATA(xcol) : (FFP)(xcoord++));
            *(y++) = DATA(ycol);
            if (ecol>=0) *(e++) = DATA(ecol);
            Plot->NPts++;

            if (debug) {
            	printf("GetDat: x=%f, y=%f", *(x-1), *(y-1));
            	if (ecol>=0) printf(", e=%f", *(e-1));
            	printf("\n");
            }
         }

         else {
            /* line does not contain plottable data */
            if (!terse) printf("%s\n",cbuf);
            if (PLOT_OPENED) {
               Pict->NPlt++;
               PlotClosed = TRUE;
            }
         }
      }
   }
   
   if (PLOT_OPENED) Pict->NPlt++;
   return;
}


/******************/
int KeyWord(cb,Pict)
char *cb;
struct Pict *Pict;
{
   short i;
   
   if (same(cb,"*",1)) {
      if (same(cb,"*SCALFACT*",10)) {
         (void)getwrd(&cb);
         for (i=0; i<=maxcol; i++) {
            if (debug) printf("scalfact >%s<\n", cb);
            fact[i] = atoFFP(getwrd(&cb));
            if (debug) printf("scalfact %f\n", fact[i]);
         }
         return (TRUE);
      }
      else if (same(cb,"*TITLE*",7)) {
         (void)getwrd(&cb); (void)strcpy(title,cb);
         Pict->Title = title;
         return (TRUE);
      }
      else if (same(cb,"*XLABEL*",8)) {
         (void)getwrd(&cb); (void)strcpy(xlabel,cb);
         Pict->XLabel = xlabel;
         return (TRUE);
      }
      else if (same(cb,"*YLABEL*",8)) {
         (void)getwrd(&cb); (void)strcpy(ylabel,cb);
         Pict->YLabel = ylabel;
         return (TRUE);
      }
   }
   return (FALSE);
}


/*************************************************************************/
struct Remember *Key=NULL;

struct Plot *GetStructPlot()
{
   struct Plot *P;

   P     = (struct Plot *)AllocRemember(&Key,sizeof(struct Plot),MEMF_CLEAR);
   P->x  = (FFP *)AllocRemember(&Key,MAXPOINTS * sizeof(FFP),MEMF_CLEAR);
   P->y  = (FFP *)AllocRemember(&Key,MAXPOINTS * sizeof(FFP),MEMF_CLEAR);
   P->e  = (FFP *)AllocRemember(&Key,MAXPOINTS * sizeof(FFP),MEMF_CLEAR);
   P->xp = (short *)AllocRemember(&Key,MAXPOINTS * sizeof(short),MEMF_CLEAR);
   P->yp = (short *)AllocRemember(&Key,MAXPOINTS * sizeof(short),MEMF_CLEAR);
   P->ep = (short *)AllocRemember(&Key,MAXPOINTS * sizeof(short),MEMF_CLEAR);
   P->Reg = (struct PlotRegion *)
                  AllocRemember(&Key,sizeof(struct PlotRegion),MEMF_CLEAR);
   if (debug) {
      printf("GetStructPlot: Plot=%d\n",P);
      printf("...Plot->x=%d, ->y=%d, ->e=%d\n",P->x,P->y,P->e);
      printf("...Plot->xp=%d, ->yp=%d, ->ep=%d\n",P->xp,P->yp,P->ep);
      printf("...Plot->Reg=%d\n",P->Reg);
   }

   return(P);
}


/*******************/
void FreeStructPlot()
{
   FreeRemember(&Key,TRUE);
}
