/***************************************************************************
*                    Copyright (c) 1986, 87, 88 Tim Mooney                 *
*                      also Copyright 1989 Alan G Baxter                   *
*                                                                          *
*   Data input, screen & HPLG output- TM. Interface, Plt: support & con-   *
*   version files- AGB. See docs for distribution restrictions.            *
***************************************************************************/

/***************************************************************************
*   mp.c - PLOT DATA EMBEDDED IN TEXT FILE
*
*      Mp reads a text file and extracts data from it in a way defined by
*   interactive gadget selection.
*   When the data are collected, mp opens a high-res screen, and plots some
*   or all of the data -- again, in a user-defined way.  Some of the
*   details of plotting specifications can be altered in the "get how to"
*   window callable from menu selection in the main window.
****************************************************************************
*   Capabilities, limitations, and implementation notes:
*
*      Mp can plot lines or points of varying sizes; with or without error
*   bars; in 10 colors.  There is no internal limit on the number of data
*   sets plotted simultaneously, or on the number of points in a single
*   data set, or on the total size of all data sets.  Memory is allocated
*   dynamically; when it's used up, mp will stop processing the data file
*   and crash when it tries to open a new screen.
*
*      Points are actually drawn as squares, except for the smallest sizes.
*   Mp doesn't plot any other kinds of marks.  Points may be any size; one
*   may fill the screen, in fact.  All lines are solid, error bars are
*   lines.
*
*      GetDat() can scale data on input, directed by information in the
*   data file it's reading.  Although GetDat() can also extract a title and
*   labels from the data file, mp makes no use of them at present.
*
*      Once the data are plotted on the screen, the user can zoom in and
*   out, disable axes and grid, etc.  Also, the current picture can be
*   dumped to a file for plotting.  The only plotter language supported
*   is HPGL (Hewlett-Packard) since it's the only one I know.
*
*      IEEE maths libraries are used throughout.
***************************************************************************/
#include <graphics/display.h>
#include <libraries/dosextens.h>
#include <libraries/diskfont.h>
#include <exec/exec.h>
#include <intuition/intuitionbase.h>
#include <graphics/regions.h>
#include <devices/keymap.h>
#include <stdio.h>
#include <workbench/startup.h>
#include <graphics/gfxmacros.h>
#include <graphics/gfxbase.h>
#include <math.h>

#define MAIN_MODULE 1

#include "struct.h"
#include "plotlim.h"
#include "front.h"

struct IntuitionBase *IntuitionBase; /* Pointer aus exec */
struct GfxBase *GfxBase;
struct DiskfontBase  *DiskfontBase;


int MAXVERT=512;       /* Globally declared int replaces #define to allow */
                       /* switches in screen size for Australia  Vs USA   */
int CHARWIDTH=8;
int CHARHEIGHT=8;
int LMARGIN=57;  /* CHARWIDTH x 7 */
int TMARGIN=8;
int BMARGIN=24;    /* CHARHEIGHT x 3 */
int XMINP=57;      /* LMARGIN */
int YMAXP=504;   /* MAXVERT - TMARGIN */
int YMINP=24;    /* BMARGIN */

extern short firstcall;
extern int GetDat();
extern void plot();
extern struct Screen *screen;
extern struct NewScreen newscreen;
extern struct NewWindow newwindow;

#define QUIT 0
#define GO 1
int QuitFrontFlag=GO;  /* Quit flag for Front Window requester */
int KEEP_GOING=1;      /* Quit flag for the whole program which all but */
                       /* closes the screen when "New" is selected.     */
long IconBase;
int debug = FALSE;

FFP xtic[MAXTICS],ytic[MAXTICS];
short xticp[MAXTICS],yticp[MAXTICS];
char filename[150];
struct RastPort *p;
struct Pict *Pict;

extern struct ViewPort *vp;
char StartDir[150];

main(argc,argv)
int argc;
union {
   char **args;
   struct WBStartup *msg;
} argv;
{
   struct WBArg *arg;
   int xcol=1, ycol=2, ecol=0, terse=TRUE, fpal=1;
   FILE *fp;
   struct IntuiMessage  *p_message;         /* pointer to message */
   void ProcMes();
   filename[0] = 0;

   /*** PARSE ARGS ***/
   if (argc != 0) { /* called from CLI */
      stcgfp(StartDir,argv.args[0]);
      if (argc>1)   {
         if (argv.args[argc-1][0] == '?') {
          printf("usage: MultiPlot [filename]\n");
          exit(0);
         }
         else   {
           strcpy(filename,argv.args[argc-1]);
           strcpy(Gadget4SIBuff,filename);
         }
      }
    }

   else { /* called from workbench */
      arg = argv.msg->sm_ArgList; /* point to command */
      if (arg->wa_Lock != NULL) {
         getpath(arg->wa_Lock,StartDir);
         if (isdev(StartDir)) strcat(StartDir,":");
      }
      else stcgfp(StartDir,arg->wa_Name);
      arg++;
      if (argv.msg->sm_NumArgs > 1) {
         getpath(arg->wa_Lock,Gadget4SIBuff);
         if (isdev(Gadget4SIBuff)) strcat(Gadget4SIBuff,":");
         strmfp(Gadget4SIBuff,Gadget4SIBuff,arg->wa_Name);
      }
   }

   /*** OPEN LIBRARIES ***/
   FFPLARGE = 1.0e10; FFPSMALL = 1.0e-10;
   DiskfontBase = (struct DiskfontBase *) OpenLibrary("diskfont.library",0);
   if( DiskfontBase == NULL )
      {
        printf("Can't open diskfont Library\n");
        sexit (FALSE);
      }
   GfxBase=NULL;
   GfxBase = (struct GfxBase *) OpenLibrary("graphics.library",33);
   if(GfxBase == NULL)
      {
        printf("Can't open GfxBase Library\n");
        sexit (FALSE);
      }
   IntuitionBase=NULL;
   IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library",33);  /* PAL Revision */
   if (IntuitionBase == NULL)
      { fpal=0;
        IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library",0);
        if(IntuitionBase == NULL) {
           printf("Can't open intuition library...\n");
          sexit(FALSE);
        }
      }
   /***** DO PAL - NTSC MAGIC. FROM SETPAL_NTSC *******/
   if (fpal > 0)
      { if (!  ( (GfxBase->DisplayFlags) & PAL )  ) fpal=0; }
   if (fpal == 0)  {
       MAXVERT=400;
       newscreen.Height=400;
       newwindow.Height=400;
    }
   if (!(IconBase = OpenLibrary("icon.library", 0))) {
      printf("Can't open Icon library...\n");
      sexit(FALSE);
   }
   screen = (struct Screen *)OpenScreen(&newscreen);
   vp = &screen->ViewPort;
   InitColors();

   while (KEEP_GOING)
   {

     /***  RESET  THE WINDOW IN CASE THIS IS NOT FIRST TIME THROUGH ***/
     NewFrontWindow.Screen = screen;
     NewFrontWindow.Title ="                Data Selection Window            ";
     NewFrontWindow.FirstGadget = &Gadget1;
     FrontWindow = (struct Window *)OpenWindow(&NewFrontWindow);
     ActivateGadget(&Gadget4,FrontWindow,0);
     p = FrontWindow->RPort;
     PrintIText(p,&IText2,0,0);
     QuitFrontFlag=GO;     /*** RESET FLAG IN CASE NOT FIRST TIME ***/
     firstcall=TRUE;


     while (QuitFrontFlag !=QUIT)
      {
        Wait(1l<<FrontWindow->UserPort->mp_SigBit);        /* wait for a message */
        while (p_message = (struct IntuiMessage *)GetMsg(FrontWindow->UserPort))
          ProcMes(p_message);

      }
     SetPointer(FrontWindow,WaitSprite,26,14,-4,-4);

     strcpy(filename,Gadget4SIBuff);
     xcol=Gadget1SInfo.LongInt;
     ycol=Gadget2SInfo.LongInt;
     ecol=Gadget3SInfo.LongInt;

     /*** OPEN FILE ***/
     fp = fopen(filename,"r");
     if (!fp) {
        printf("Can't open %s\n",filename);
        exit(1);
     }

     /*** ALLOCATE/INITIALIZE MEMORY FOR struct Pict ***/
     Pict = (struct Pict *)AllocMem(sizeof(struct Pict),MEMF_CLEAR);
     Pict->ErrBar = (ecol != 0);
     Pict->Tics = (struct Tics *)AllocMem(sizeof(struct Tics),MEMF_CLEAR);
     Pict->Tics->x = xtic;Pict->Tics->y = ytic;
     Pict->Tics->xp = xticp;Pict->Tics->yp = yticp;
     Pict->XRegionLock = Pict->YRegionLock = FALSE;
     Pict->Axes = TRUE;
     Pict->CurrReg =
        (struct PlotRegion *)AllocMem(sizeof(struct PlotRegion),MEMF_CLEAR);
     Pict->NewReg =
        (struct PlotRegion *)AllocMem(sizeof(struct PlotRegion),MEMF_CLEAR);
     Pict->Title = NULL;
     Pict->XLabel = NULL;
     Pict->YLabel = NULL;
     Pict->Plot = NULL;

     /*** GET DATA FROM FILE ***/
     GetDat(fp, xcol, ycol, ecol, terse, Pict);
     if (debug) printf("MultiPlot: closing data file\n");
     (void) fclose(fp);


     /*** PLOT DATA ***/
     CloseWindow(FrontWindow);
     ClearPointer(FrontWindow);

     plot(Pict);

     /*** DEALLOCATE MEMORY ***/
     FreeMem(Pict->NewReg,sizeof(struct PlotRegion));
     FreeMem(Pict->CurrReg,sizeof(struct PlotRegion));
     FreeMem(Pict->Tics,sizeof(struct Tics));
     FreeMem(Pict,sizeof(struct Pict));
     FreeStructPlot();
   }

   CloseScreen(screen);
   sexit(TRUE);
}

int isdev(string)
char *string;
{
while ((*string!=':') && (*string!='\0')) string++;
if (*string==':') return(FALSE);
else return(TRUE);
}




void ProcMes(p_message)
struct IntuiMessage *p_message;
{
ULONG MesClass;        /*     Fields for storing      */
USHORT MesCode;        /*     intuimessage data       */
APTR Pointer;          /*                             */
int HandleEvent();

   MesClass = p_message->Class;             /* Store values */
   MesCode = p_message->Code;
   Pointer = p_message->IAddress;
   ReplyMsg(p_message);                     /* Reply to message */
   HandleEvent(MesClass,MesCode,Pointer);
}





int HandleEvent(MesClass,MesCode,Pointer)
ULONG MesClass;        /*     Fields for storing      */
USHORT MesCode;        /*     intuimessage data       */
APTR Pointer;          /*                             */
{
FILE *fp;
struct Process  *OurTask;
struct Window   *old_pr_WindowPtr;
static char drive[150], path[100], node[30], extn[20];



  if ( MesClass == GADGETDOWN)
    {

      if (Pointer == (APTR)&Gadget6)
         {
              if (fp = fopen(Gadget4SIBuff,"r") )
                {
                   fclose(fp);
                   QuitFrontFlag = QUIT;
                }
              else Message("     Can't open file        ");
         }
      if (Pointer == (APTR)&Gadget5)
         {
          strsfn(Gadget4SIBuff,drive,path,node,extn);
          strcat(drive,path);
          strmfe(node,node,extn);

          OurTask = (struct Process *)FindTask(0L);
          old_pr_WindowPtr = (struct Window *)OurTask->pr_WindowPtr;
          OurTask->pr_WindowPtr = (APTR)FrontWindow;
          if (get_fname(FrontWindow,screen,"Select File to Open...",node,drive)==NULL)
               {
                  OurTask->pr_WindowPtr = (APTR)old_pr_WindowPtr;
                  return(0);
               }
           OurTask->pr_WindowPtr = (APTR)old_pr_WindowPtr;
           RemoveGadget(FrontWindow,&Gadget4);
           strmfp(Gadget4SIBuff,drive,node);
           AddGadget(FrontWindow,&Gadget4,-1L);
           RefreshGadgets(&Gadget4,FrontWindow,NULL);
           DrawBorder(p,&Border2,108,97);
          }
       else ;
    }
  if ( MesClass == RAWKEY)
    {
      if (MesCode ==196)  /* RETURN key RELEASED */
         {
              if (fp = fopen(Gadget4SIBuff,"r") )
                {
                   fclose(fp);
                   QuitFrontFlag = QUIT;
                }
              else Message("     Can't open file        ");
         }
       else ;
    }
   else ;
   return(1);
}

sexit(Err)
int Err;
{
if (IconBase) CloseLibrary(IconBase);
if (IntuitionBase) CloseLibrary(IntuitionBase);
if (GfxBase) CloseLibrary(GfxBase);
if (DiskfontBase) CloseLibrary(DiskfontBase);
exit(Err);
}


