/*-----  PROGRAM INCLUDE FILES	-----*/

#include "common.h"

/*--------  DEFINES  ----------*/

#define NO_OUTPUT_FILE 1L
#define NO_ICON_FILE   2L
#define NO_INPUT_FILE  3L

#define CkErr(expression)  {if (ifferr == IFF_OKAY) ifferr = (expression);}

/*--------  GLOBAL STRUCTURES  --------*/

extern struct ILBMBase *ILBMBase;
extern struct IFFBase *IFFBase;

extern struct Window *setwin;
extern struct Gadget EquationD;
extern struct Gadget RotationX;
extern struct Gadget RotationY;
extern struct Gadget RotationZ;


/*-------  INTERNAL FUNCTIONS  --------*/

AllPlotData *AllocAllPlotData(VOID)
{
return ( AllocMem(sizeof(AllPlotData), MEMF_CLEAR) );
}


VOID FreeAllPlotData(AllPlotData *apd)
{
FreeMem( (void *)apd, sizeof(AllPlotData) );
}


VOID Init3DPL(AllPlotData *pd)
{
pd->dd.RotationX	=  45.;
pd->dd.RotationY	= -60.;
pd->dd.RotationZ	= -135.;
pd->dd.OriginX		=  160;
pd->dd.OriginY		=  100;
pd->dd.ProjPlane	=  0.;
pd->dd.ViewDist 	=  20.;
pd->dd.Scale		=  30.;
pd->dd.LineSpacingX	=  0.25;
pd->dd.LineSpacingY	=  0.25;
pd->dd.PlotXmin 	= -3.;
pd->dd.PlotXmax 	=  3.;
pd->dd.PlotYmin 	= -3.;
pd->dd.PlotYmax 	=  3.;
pd->dd.PlotPrecisionX	=  0.1;
pd->dd.PlotPrecisionY	=  0.1;

pd->ad.AxesXmin 	= -3.;
pd->ad.AxesXmax 	=  3.;
pd->ad.AxesYmin 	= -3.;
pd->ad.AxesYmax 	=  3.;
pd->ad.AxesZmin 	= -1.;
pd->ad.AxesZmax 	=  1.;
pd->ad.AxesPrecision	=  0.1;

pd->td.TicX		=  1.;
pd->td.TicY		=  1.;
pd->td.TicZ		=  1.;
pd->td.NumTicX		=  1;
pd->td.NumTicY		=  1;
pd->td.NumTicZ		=  1;

pd->ei.DependVar	= 'Z';
strcpy(pd->ei.IndependVar,"XY");
strcpy(&(pd->ei.Equation[0]),"SIN(X*Y)");

pd->pi.Surface		= XANDY;
pd->pi.AxesType 	= AXESTYPENONE;
pd->pi.RotationOrder	= ROTATEZYX;

strcpy(pd->nt,"This is a sample note");

}  /* Init3DPL */


IFFP Save3DPL(char *filename, AllPlotData *pd)
{
  LONG		 file;
  IFFP		 ifferr = IFF_OKAY;
  GroupContext	 fileContext, formContext;

  if (!(file = Open(filename, MODE_NEWFILE))) {
     printf("Can't open output file\n");
     return (NO_OUTPUT_FILE);
  }

  Write(file,"x",1);  /* 1.1 so Seek to beginning works ? */

#if DEBUG
  printf("\nSaving...\n");
#endif

  CkErr( OpenWIFF(szNotYetKnown, file, &fileContext) );
  CkErr( StartWGroup(FORM,szNotYetKnown,ID_3DPL,&fileContext,&formContext) );
  CkErr( PutEQUN(&formContext, &(pd->ei)) );
  CkErr( PutDRAW(&formContext, &(pd->dd)) );
  CkErr( PutAXES(&formContext, &(pd->ad)) );
  CkErr( PutTICS(&formContext, &(pd->td)) );
  CkErr( PutTYPE(&formContext, &(pd->pi)) );
  CkErr( PutNOTE(&formContext, pd->nt) );
  CkErr( EndWGroup(&formContext) );
  CkErr( CloseWGroup(&fileContext) );

  Close(file);

#if DEBUG
  if (ifferr == IFF_OKAY) {
     printf("3DPL IFF saved\n");
  }
  else {
     printf("Error on save\n");
  }
#endif

  return(ifferr);

}  /* Save3DPL */


/*
IFFP Read3DPL(char *filename, AllPlotData *pd)
{
  LONG		 file;
  IFFP		 ifferr = IFF_OKAY;
  ID		 CkHdr;
  GroupContext	 fileContext, formContext;

  if (!(file = Open(filename, MODE_OLDFILE))) {
     printf("Can't open input file\n");
     return (NO_INPUT_FILE);
  }

#if DEBUG
  printf("\nReading...\n");
#endif

CkErr( OpenRIFF(file, &fileContext, NULL) );
CkErr( OpenRGroup(&fileContext,&formContext) );

CkHdr = GetFChunkHdr(&formContext);

while( (CkHdr != END_MARK) && (CkHdr != BAD_IFF) && (ifferr == IFF_OKAY) ) {

   switch(CkHdr) {

      case ID_EQUN:
	 ifferr = IFFReadBytes(sizeof(EqInfo),&formContext,&(pd->ei));
	 break;

      case ID_DRAW:
	 ifferr = IFFReadBytes(sizeof(DrawData),&formContext,&(pd->dd));
	 break;

      case ID_AXES:
	 ifferr = IFFReadBytes(sizeof(AxesData),&formContext,&(pd->ad));
	 break;

      case ID_TICS:
	 ifferr = IFFReadBytes(sizeof(TicData),&formContext,&(pd->td));
	 break;

      case ID_TYPE:
	 ifferr = IFFReadBytes(sizeof(PlotInfo),&formContext,&(pd->pi));
	 break;

      case ID_NOTE:
	 ifferr = IFFReadBytes(NOTELEN,&formContext,pd->nt);
	 break;

   } /* switch */

   CkHdr = GetChunkHdr(&formContext);

} /* while */

  CkErr( CloseRGroup(&formContext) );
  CkErr( CloseRGroup(&fileContext) );

  Close(file);

#if DEBUG
  if (ifferr == IFF_OKAY) {
     printf("3DPL IFF read\n");
  }
  else {
     printf("Error on read\n");
  }
#endif

  return(ifferr);

}  /* Read3DPL */
*/

LONG Read3DPL(STRPTR filename, AllPlotData *pd)
{
   APTR ifffile;
   ULONG *chunk;

if( !(ifffile = OldOpenIFF(filename)) )  return IffError();

if( !(chunk = (ULONG *)FindChunk(ifffile, ID_EQUN)) )  goto endread;
memcpy( &(pd->ei), (chunk+2), sizeof(EqInfo) );

if( !(chunk = (ULONG *)FindChunk(ifffile, ID_DRAW)) )  goto endread;
memcpy( &(pd->dd), (chunk+2), sizeof(DrawData) );

if( !(chunk = (ULONG *)FindChunk(ifffile, ID_AXES)) )  goto endread;
memcpy( &(pd->ad), (chunk+2), sizeof(AxesData) );

if( !(chunk = (ULONG *)FindChunk(ifffile, ID_TICS)) )  goto endread;
memcpy( &(pd->td), (chunk+2), sizeof(TicData) );

if( !(chunk = (ULONG *)FindChunk(ifffile, ID_TYPE)) )  goto endread;
memcpy( &(pd->pi), (chunk+2), sizeof(PlotInfo) );

if( !(chunk = (ULONG *)FindChunk(ifffile, ID_NOTE)) )  goto endread;
memcpy( &(pd->nt), (chunk+2), NOTELEN );


endread:

CloseIFF(ifffile);
return IffError();

}  /* Read3DPL */


VOID PrintData(AllPlotData *pd)
{
printf("pd->dd.RotationX = %f\n", pd->dd.RotationX);
printf("pd->dd.RotationY = %f\n", pd->dd.RotationY);
printf("pd->dd.RotationZ = %f\n", pd->dd.RotationZ);
printf("pd->dd.OriginX = %d\n", pd->dd.OriginX);
printf("pd->dd.OriginY = %d\n", pd->dd.OriginY);
printf("pd->dd.ProjPlane = %f\n", pd->dd.ProjPlane);
printf("pd->dd.ViewDist = %f\n", pd->dd.ViewDist);
printf("pd->dd.Scale = %f\n", pd->dd.Scale);
printf("pd->dd.LineSpacingX = %f\n", pd->dd.LineSpacingX);
printf("pd->dd.LineSpacingY = %f\n", pd->dd.LineSpacingY);
printf("pd->dd.PlotXmin = %f\n", pd->dd.PlotXmin);
printf("pd->dd.PlotXmax = %f\n", pd->dd.PlotXmax);
printf("pd->dd.PlotYmin = %f\n", pd->dd.PlotYmin);
printf("pd->dd.PlotYmax = %f\n", pd->dd.PlotYmax);
printf("pd->dd.PlotPrecisionX = %f\n", pd->dd.PlotPrecisionX);
printf("pd->dd.PlotPrecisionY = %f\n", pd->dd.PlotPrecisionY);

printf("pd->ad.AxesXmin = %f\n", pd->ad.AxesXmin);
printf("pd->ad.AxesXmax = %f\n", pd->ad.AxesXmax);
printf("pd->ad.AxesYmin = %f\n", pd->ad.AxesYmin);
printf("pd->ad.AxesYmax = %f\n", pd->ad.AxesYmax);
printf("pd->ad.AxesZmin = %f\n", pd->ad.AxesZmin);
printf("pd->ad.AxesZmax = %f\n", pd->ad.AxesZmax);
printf("pd->ad.AxesPrecision = %f\n", pd->ad.AxesPrecision);

printf("pd->td.TicX = %f\n", pd->td.TicX);
printf("pd->td.TicY = %f\n", pd->td.TicY);
printf("pd->td.TicZ = %f\n", pd->td.TicZ);
printf("pd->td.NumTicX = %d\n", pd->td.NumTicX);
printf("pd->td.NumTicY = %d\n", pd->td.NumTicY);
printf("pd->td.NumTicZ = %d\n", pd->td.NumTicZ);

printf("pd->ei.DependVar = %c\n", pd->ei.DependVar);
printf("pd->ei.IndependVar = %s\n", pd->ei.IndependVar);
printf("pd->ei.Equation = %s\n", pd->ei.Equation);

printf("pd->pi.Surface = %d\n", pd->pi.Surface);
printf("pd->pi.AxesType = %d\n", pd->pi.AxesType);
printf("pd->pi.RotationOrder = %d\n", pd->pi.RotationOrder);

printf("pd->nt = %s\n", pd->nt);

} /* PrintData */


VOID SetGadgets(struct Gadget *gadget, AllPlotData *pd)
   /* gadget is the Gadget to begin with
      pd is the data to insert	       */
{
   struct Gadget *fgadget;  /* Copy of first gadget */
   STRPTR gtext;
   STRPTR string;
   LONG *longint;

   fgadget = gadget;

   while(gadget) {   /* loop until no more gadgets */

      string = ((struct StringInfo *)(gadget->SpecialInfo))->Buffer;
      longint = &(((struct StringInfo *)(gadget->SpecialInfo))->LongInt);

      switch(gadget->GadgetID) {

	 case SURFACE:
	    gtext = gadget->GadgetText->NextText->IText;
	    switch(pd->pi.Surface) {
	       case XONLY:
		  strcpy(gtext, "X Only ");
		  break;
	       case YONLY:
		  strcpy(gtext, "Y Only ");
		  break;
	       case XANDY:
		  strcpy(gtext, "X and Y");
		  break;
	       default:
		  break;
	    } /* switch */
	    break;

	 case AXESTYPE:
	    gtext = gadget->GadgetText->NextText->IText;
	    switch(pd->pi.AxesType) {
	       case AXESTYPENONE:
		  strcpy(gtext, "None");
		  break;
	       case AXESTYPESTAR:
		  strcpy(gtext, "Star");
		  break;
	       case AXESTYPEBOX:
		  strcpy(gtext, "Box ");
		  break;
	       default:
		  break;
	    } /* switch */
	    break;

	 case SWAPXYZ:
	    {		       /* begin block */
	    WORD tempTopEdge[3];
	    struct Gadget *tempGadget;

	    /* Obtain three top edges for X, Y, and Z gadgets in order */
	    tempTopEdge[0] = RotationX.TopEdge;
	    tempTopEdge[1] = RotationY.TopEdge;
	    tempTopEdge[2] = RotationZ.TopEdge;
	    sqsort(&tempTopEdge[0], 3);  /* Sort short integers, ascending */

	    /* Obtain gadget after X, Y, and Z gadgets */
	    tempGadget = RotationX.NextGadget;
	    while( (tempGadget == &RotationY) || (tempGadget == &RotationZ) ) {
	       tempGadget = tempGadget->NextGadget;
	    }

	    switch(pd->pi.RotationOrder) {
	       case ROTATEXYZ:
			     /* New positions */
		  RotationX.TopEdge = tempTopEdge[0];
		  RotationY.TopEdge = tempTopEdge[1];
		  RotationZ.TopEdge = tempTopEdge[2];
			     /* Order gadgets in list */
		  EquationD.NextGadget = &RotationX;
		  RotationX.NextGadget = &RotationY;
		  RotationY.NextGadget = &RotationZ;
		  RotationZ.NextGadget = tempGadget;
		  break;
	       case ROTATEXZY:
			     /* New positions */
		  RotationX.TopEdge = tempTopEdge[0];
		  RotationZ.TopEdge = tempTopEdge[1];
		  RotationY.TopEdge = tempTopEdge[2];
			     /* Order gadgets in list */
		  EquationD.NextGadget = &RotationX;
		  RotationX.NextGadget = &RotationZ;
		  RotationZ.NextGadget = &RotationY;
		  RotationY.NextGadget = tempGadget;
		  break;
	       case ROTATEYXZ:
			     /* New positions */
		  RotationY.TopEdge = tempTopEdge[0];
		  RotationX.TopEdge = tempTopEdge[1];
		  RotationZ.TopEdge = tempTopEdge[2];
			     /* Order gadgets in list */
		  EquationD.NextGadget = &RotationY;
		  RotationY.NextGadget = &RotationX;
		  RotationX.NextGadget = &RotationZ;
		  RotationZ.NextGadget = tempGadget;
		  break;
	       case ROTATEYZX:
			     /* New positions */
		  RotationY.TopEdge = tempTopEdge[0];
		  RotationZ.TopEdge = tempTopEdge[1];
		  RotationX.TopEdge = tempTopEdge[2];
			     /* Order gadgets in list */
		  EquationD.NextGadget = &RotationY;
		  RotationY.NextGadget = &RotationZ;
		  RotationZ.NextGadget = &RotationX;
		  RotationX.NextGadget = tempGadget;
		  break;
	       case ROTATEZXY:
			     /* New positions */
		  RotationZ.TopEdge = tempTopEdge[0];
		  RotationX.TopEdge = tempTopEdge[1];
		  RotationY.TopEdge = tempTopEdge[2];
			     /* Order gadgets in list */
		  EquationD.NextGadget = &RotationZ;
		  RotationZ.NextGadget = &RotationX;
		  RotationX.NextGadget = &RotationY;
		  RotationY.NextGadget = tempGadget;
		  break;
	       case ROTATEZYX:
			     /* New positions */
		  RotationZ.TopEdge = tempTopEdge[0];
		  RotationY.TopEdge = tempTopEdge[1];
		  RotationX.TopEdge = tempTopEdge[2];
			     /* Order gadgets in list */
		  EquationD.NextGadget = &RotationZ;
		  RotationZ.NextGadget = &RotationY;
		  RotationY.NextGadget = &RotationX;
		  RotationX.NextGadget = tempGadget;
		  break;
	       default:
		  break;
	    } /* switch */
	    } /* end block */
	    break;

	 case ROTATIONX:
	    *longint = (LONG)(pd->dd.RotationX);
	    sprintf(string, "%d", *longint);
	    break;

	 case ROTATIONY:
	    *longint = (LONG)(pd->dd.RotationY);
	    sprintf(string, "%d", *longint);
	    break;

	 case ROTATIONZ:
	    *longint = (LONG)(pd->dd.RotationZ);
	    sprintf(string, "%d", *longint);
	    break;

	 case ORIGINX:
	    *longint = pd->dd.OriginX;
	    sprintf(string, "%d", *longint);
	    break;

	 case ORIGINY:
	    *longint = pd->dd.OriginY;
	    sprintf(string, "%d", *longint);
	    break;

	 case SIZINGPROJPLANE:
	    gcvt(pd->dd.ProjPlane, 10, string);
	    break;

	 case SIZINGVIEWDIST:
	    gcvt(pd->dd.ViewDist, 10, string);
	    break;

	 case SIZINGSCALE:
	    gcvt(pd->dd.Scale, 10, string);
	    break;

	 case LINESPACINGX:
	    gcvt(pd->dd.LineSpacingX, 10, string);
	    break;

	 case LINESPACINGY:
	    gcvt(pd->dd.LineSpacingY, 10, string);
	    break;

	 case PLOTSPANXMIN:
	    gcvt(pd->dd.PlotXmin, 10, string);
	    break;

	 case PLOTSPANXMAX:
	    gcvt(pd->dd.PlotXmax, 10, string);
	    break;

	 case PLOTSPANYMIN:
	    gcvt(pd->dd.PlotYmin, 10, string);
	    break;

	 case PLOTSPANYMAX:
	    gcvt(pd->dd.PlotYmax, 10, string);
	    break;

	 case PLOTPRECISIONX:
	    gcvt(pd->dd.PlotPrecisionX, 10, string);
	    break;

	 case PLOTPRECISIONY:
	    gcvt(pd->dd.PlotPrecisionY, 10, string);
	    break;

	 case AXESSPANXMIN:
	    gcvt(pd->ad.AxesXmin, 10, string);
	    break;

	 case AXESSPANXMAX:
	    gcvt(pd->ad.AxesXmax, 10, string);
	    break;

	 case AXESSPANYMIN:
	    gcvt(pd->ad.AxesYmin, 10, string);
	    break;

	 case AXESSPANYMAX:
	    gcvt(pd->ad.AxesYmax, 10, string);
	    break;

	 case AXESSPANZMIN:
	    gcvt(pd->ad.AxesZmin, 10, string);
	    break;

	 case AXESSPANZMAX:
	    gcvt(pd->ad.AxesZmax, 10, string);
	    break;

	 case AXESPRECISION:
	    gcvt(pd->ad.AxesPrecision, 10, string);
	    break;

	 case EQUATIONZ:
	    strcpy(string, pd->ei.Equation);
	    break;

	 case SETTINGSNOTE:
	    strcpy(string, pd->nt);
	    break;

      } /* switch */

      gadget = gadget->NextGadget;

   } /* while */

   RefreshGadgets(fgadget, setwin, NULL);

} /* SetGadgets */
