#include <stdio.h>
#include <ctype.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();
extern struct Window *FrontWindow;
extern struct NewScreen newscreen;
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));
   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); trch('\r',' ',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++;
         }

         else {
            /* line does not contain plottable data */
            if (PLOT_OPENED) {
               Pict->NPlt++;
               PlotClosed = TRUE;
            }
         }
      }
   }

   if (PLOT_OPENED) Pict->NPlt++;
   return;
}

int CheckDat(fp, xcol, ycol, ecol)
FILE *fp;
int xcol, ycol, ecol;   /* column numbers to be inspected */
{
char cbuf[100];
int i=0;
   maxcol = max(xcol,max(ycol,ecol));

   while ( fgets(cbuf,99,fp) && ( (i==0) || (i>=maxcol) ) )
       {
          strcat(cbuf,'\0');
          i=countwords(&cbuf);
       }
    if ( (i<maxcol) && (i!=0) )
      {
         SetWindowTitles(FrontWindow,-1,newscreen.DefaultTitle);
         Message("   Not enough columns in file   ");
         return(FALSE);
      }
  return(TRUE);
}

countwords(s)
char *s;
{
int x=0;


  while ((*s !='\0')&&(!isdigit(*s)))
    {
       if (isalpha(*s))   return(0);
       s++;
    }

  while (*s !='\0')
    {
       if (isdigit(*s))
         {
            x++;
            while (isalnum(*s)||ispunct(*s))  s++;
         }
       else s++;
     }
   return(x);
}

/******************/
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++) {
            fact[i] = atoFFP(getwrd(&cb));
         }
         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);
   return(P);
}


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