#include "Scian.h"
#include "ScianTypes.h"
#include "ScianIDs.h"
#include "ScianLists.h"
#include "ScianColors.h"
#include "ScianErrors.h"
#include "ScianNames.h"
#include "ScianGarbageMan.h"
#include "ScianMethods.h"
#include "ScianArrays.h"
#include "ScianTimers.h"
#include "ScianPictures.h"
#include "ScianWindows.h"
#include "ScianVisWindows.h"
#include "ScianDialogs.h"
#include "ScianComplexControls.h"
#include "ScianDatasets.h"
#include "ScianVisObjects.h"

#define MAX3(x,y,z) (MAX(MAX(x,y),z))
#define MIN3(x,y,z) (MIN(MIN(x,y),z))

#define MAXLINE 1024

#define NUMDIMS 4
#define DIM1 16
#define DIM2 16
#define DIM3 16
#define DIM4 16
#define NUMARRAYS 20
#define ARRAYSIZE (DIM1*DIM2*DIM3*DIM4)

#ifdef PROTO
char *ShortNameOf(char *n);
#else
char *ShortNameOf();
#endif

extern ObjPtr data3DScalar;

#define FTNREALS 0
#if FTNREALS
#define FTNGARBAGE 0x00000400L
#else
#define FTNGARBAGE 0x00000400L
#endif

#define FTNMIN -30000
#define FTNMAX 30000

static ObjPtr ReadGBCFile(name)
char *name;
/*Reads one of bali's binary files*/
{
    ObjPtr timeSteps;
    ObjPtr timedObj;
    FILE *inFile;
    long whichFrame;
    real dims[3];			/*The dimensions of the data, temp.*/
    real bounds[6];			/*The bounds of the data form*/
    long xSize, ySize;
    long dataSize;			/*Dummy to hold size of data*/
    real dataMin, dataMax;
    ObjPtr dataForm;
    ObjPtr dimsArray, boundsArray;
    long nFrames;
    int numRead;		/* number of elements successfully fread */
    int i, j, k, l, tmp;
    real bigArray[DIM1][DIM2][DIM3][DIM4];
    ObjPtr timeDatas[DIM1];
    int junk[5];
    unsigned int foo;
    ObjPtr minMaxArray;
    real minMax[2];

    inFile = fopen(name, "r");
    if (!inFile)
    {
	Error("ReadGBCFile", OPENFILEERROR, name);
	return NULLOBJ;
    }

    /* set up data lists for array parts to be shoveled into */
    for (i = 0; i < DIM1; ++i)
    {
	timeDatas[i] = NewList();
    }

    whichFrame = 0;
    /* using the brute force method, since all dimensions are equal length */
    while (ARRAYSIZE == (numRead = fread(bigArray, sizeof(real), ARRAYSIZE, inFile)))
    {
	for (i=0; i<DIM1; ++i)
	{
	    ObjPtr timeThing;

	    timeThing = NewRealArray(NUMDIMS - 1, (long) DIM2,
				     (long) DIM3, (long) DIM4);
	    CArray2Array(timeThing, bigArray[i]);
	    PostfixList(timeDatas[i], timeThing);
	}
	++whichFrame;
    }

    fclose(inFile);

    timeSteps = NewList();
    for (i = 0; i < whichFrame; ++i)
    {
	PostfixList(timeSteps, NewReal(i));
    }

    /*Create the data form*/
    dataForm = NewObject(dataFormClass, 0);
    dimsArray = NewRealArray(1, (long) 3);
    
    /*Put in some dimensions*/
    dims[0] = (real) DIM2;
    dims[1] = (real) DIM3;
    dims[2] = (real) DIM4;
    CArray2Array(dimsArray, dims);
    SetVar(dataForm, DIMENSIONS, dimsArray); 
    boundsArray = NewRealArray(1, 6L);
    bounds[0] = bounds[2] = bounds[4] = 0.0;
    bounds[1] = DIM2;
    bounds[3] = DIM3;
    bounds[5] = DIM4;
    CArray2Array(boundsArray, bounds);
    SetVar(dataForm, BOUNDS, boundsArray);

	minMax[0] = FTNMIN;
	minMax[1] = FTNMAX;
                minMaxArray = NewRealArray(1, 2L);
                    CArray2Array(minMaxArray, minMax);

    for (i=0; i<DIM1; ++i)
    {
	ObjPtr dataThing;

	dataThing = NewObject(data3DScalar, 0);
	SetVar(dataThing, DATA, NewTimedObject(timeSteps, timeDatas[i]));
	SetVar(dataThing, DATAFORM, dataForm);
	sprintf(tempStr, "%s%d", ShortNameOf(name), i);
	SetVar(dataThing, NAME, NewString(tempStr));
        SetVar(dataThing, MINMAX, minMaxArray);

	RegisterDataset(dataThing);
    }

    return NULLOBJ;
}

static ObjPtr ReadGBC2File(name)
char *name;
/*Reads one of bali's binary files, only this time Scian time is across the
 * major spatial dimension
 */
{
    ObjPtr timeSteps;
    ObjPtr timedObj;
    FILE *inFile;
    long whichFrame;
    real dims[3];			/*The dimensions of the data, temp.*/
    real bounds[6];			/*The bounds of the data form*/
    long xSize, ySize;
    long dataSize;			/*Dummy to hold size of data*/
    real dataMin, dataMax;
    ObjPtr dataForm;
    ObjPtr dimsArray, boundsArray;
    ObjPtr retVal;
    long nFrames;
    int numRead;		/* number of elements successfully fread */
    int i, j, k, l, tmp;
    real bigArray[DIM1][DIM2][DIM3][DIM4];
    long junk[2];
    unsigned int foo;
    ObjPtr minMaxArray;
    real minMax[2];

    inFile = fopen(name, "r");
    if (!inFile)
    {
	Error("ReadGBC2File", OPENFILEERROR, name);
	return NULLOBJ;
    }

    /* setting up stuff for the objects created in the loop */
    retVal = NewList();
    minMax[0] = FTNMIN;
    minMax[1] = FTNMAX;
    minMaxArray = NewRealArray(1, 2L);
    CArray2Array(minMaxArray, minMax);

    /*Create the data form */
    dataForm = NewObject(dataFormClass, 0);
    dimsArray = NewRealArray(1, (long) 3);
    
    /* Put in some dimensions and bounds */
    dims[0] = (real) DIM2;
    dims[1] = (real) DIM3;
    dims[2] = (real) DIM4;
    CArray2Array(dimsArray, dims);
    SetVar(dataForm, DIMENSIONS, dimsArray); 
    boundsArray = NewRealArray(1, 6L);
    bounds[0] = bounds[2] = bounds[4] = 0.0;
    bounds[1] = DIM2;
    bounds[3] = DIM3;
    bounds[5] = DIM4;
    CArray2Array(boundsArray, bounds);
    SetVar(dataForm, BOUNDS, boundsArray);

    timeSteps = NewList();
    for (i = 0; i < DIM1; ++i)
    {
	PostfixList(timeSteps, NewReal(i));
    }

    whichFrame = 0;
    /* using the brute force method, since all dimensions are equal length */
    while (ARRAYSIZE == (numRead = fread(bigArray, sizeof(real), ARRAYSIZE, inFile)))
    {
	ObjPtr retThing, timeData;

	retThing = NewObject(data3DScalar, 0);
	timeData = NewList();

	for (i=0; i<DIM1; ++i)
	{
	    ObjPtr timeThing;

	    timeThing = NewRealArray(NUMDIMS - 1, (long) DIM2,
				     (long) DIM3, (long) DIM4);
	    CArray2Array(timeThing, bigArray[i]);
	    PostfixList(timeData, timeThing);
	}

	SetVar(retThing, DATA, NewTimedObject(timeSteps, timeData));
	SetVar(retThing, DATAFORM, dataForm);
	sprintf(tempStr, "%s%d", ShortNameOf(name), whichFrame);
	SetVar(retThing, NAME, NewString(tempStr));
        SetVar(retThing, MINMAX, minMaxArray);

	RegisterDataset(retThing);

	++whichFrame;
    }

    fclose(inFile);

    return NULLOBJ;
}

#define SSDIM1 4
#define SSDIM2 10
#define SSDIM3 10
#define SSDIM4 10
#define SSNUMARRAYS 200
#define SSNUMDIMS 4
#define SSARRAYSIZE (SSDIM1*SSDIM2*SSDIM3*SSDIM4)

static ObjPtr ReadSSFile(name)
char *name;
/*Reads one of sergiu's binary files*/
{
    ObjPtr timeSteps;
    ObjPtr timedObj;
    FILE *inFile;
    long whichFrame;
    real dims[3];			/*The dimensions of the data, temp.*/
    real bounds[6];			/*The bounds of the data form*/
    long xSize, ySize;
    long dataSize;			/*Dummy to hold size of data*/
    real dataMin, dataMax;
    ObjPtr dataForm;
    ObjPtr dimsArray, boundsArray;
    long nFrames;
    int numRead;		/* number of elements successfully fread */
    int i, j, k, l, tmp;
    real bigArray[SSDIM1][SSDIM2][SSDIM3][SSDIM4];
    ObjPtr timeDatas[SSDIM1];
    int junk[5];
    unsigned int foo;
    ObjPtr minMaxArray;
    real minMax[2];

    inFile = fopen(name, "r");
    if (!inFile)
    {
	Error("ReadSSFile", OPENFILEERROR, name);
	return NULLOBJ;
    }

    /* set up data lists for array parts to be shoveled into */
    for (i = 0; i < SSDIM1; ++i)
    {
	timeDatas[i] = NewList();
    }

    whichFrame = 0;
    /* using the brute force method, since all dimensions are equal length */
    while (SSARRAYSIZE == (numRead = fread(bigArray, sizeof(real), SSARRAYSIZE, inFile)))
    {
	for (i=0; i<SSDIM1; ++i)
	{
	    ObjPtr timeThing;

	    timeThing = NewRealArray(SSNUMDIMS - 1, (long) SSDIM2,
				     (long) SSDIM3, (long) SSDIM4);
	    CArray2Array(timeThing, bigArray[i]);
	    PostfixList(timeDatas[i], timeThing);
	}
	++whichFrame;
    }

    fclose(inFile);

    timeSteps = NewList();
    for (i = 0; i < whichFrame; ++i)
    {
	PostfixList(timeSteps, NewReal(i));
    }

    /*Create the data form*/
    dataForm = NewObject(dataFormClass, 0);
    dimsArray = NewRealArray(1, (long) 3);
    
    /*Put in some dimensions*/
    dims[0] = (real) SSDIM2;
    dims[1] = (real) SSDIM3;
    dims[2] = (real) SSDIM4;
    CArray2Array(dimsArray, dims);
    SetVar(dataForm, DIMENSIONS, dimsArray); 
    boundsArray = NewRealArray(1, 6L);
    bounds[0] = bounds[2] = bounds[4] = 0.0;
    bounds[1] = SSDIM2;
    bounds[3] = SSDIM3;
    bounds[5] = SSDIM4;
    CArray2Array(boundsArray, bounds);
    SetVar(dataForm, BOUNDS, boundsArray);

    minMax[0] = -25;
    minMax[1] = 25;
    minMaxArray = NewRealArray(1, 2L);
    CArray2Array(minMaxArray, minMax);

    for (i=0; i<SSDIM1; ++i)
    {
	ObjPtr retThing;

	retThing = NewObject(data3DScalar, 0);
	SetVar(retThing, DATA, NewTimedObject(timeSteps, timeDatas[i]));
	SetVar(retThing, DATAFORM, dataForm);
	sprintf(tempStr, "%s%d", ShortNameOf(name), i);
	SetVar(retThing, NAME, NewString(tempStr));
        SetVar(retThing, MINMAX, minMaxArray);

	RegisterDataset(retThing);
    }

    return NULLOBJ;
}

/* maximum number of atoms in one molecule file */
#define NATOMS 1024
/* maximum atomic number of a single atom */
#define MAXWT 256

#define G90_SPHERE_SCALE 0.7
/* #define G90_SUBDIVIDE_CYLINDERS 5 */

static ObjPtr ReadG90File(name)
char *name;
/*Reads one kind of gaussian output file*/
{
    FILE *inFile, *conFile;		/* inFile is the real data, conFile is the connection file*/
    real dims[3];			/*The dimensions of the data, temp.*/
    real bounds[6];			/*The bounds of the data form*/
    ObjPtr dataForm;
    ObjPtr dimsArray, boundsArray;
    ObjPtr retField, retList, retPicture; /*the things that get returned */
    ObjPtr fieldData;	/* the actual data of the field */
    ObjPtr picture, picArray[MAXWT];	/* contains the NFF objects representing atoms*/
    int i, j, k, l, tmp;
    Bool notdone;
    real xScale, yScale, zScale;
    real xLoc, yLoc, zLoc;
    real rot[3][3];
    int idummy;
    int nAtoms = 0, n1 = 0, n2 = 0, n3 = 0; /* yeah, just 'cause I'm paranoid doesn't mean the compiler isn't out to get me! */
    real *dataPtr;
    real origin[3];
    float center[NATOMS][3];
    real stickRad = PLUSINF;
    real dataAverage;		/* running average of the data */
    int dataCount;		/* running count of number of data items */
    int titleLines;		/* count of number of title lines */

    inFile = fopen(name, "r");
    if (!inFile)
    {
	Error("ReadG90File", OPENFILEERROR, name);
	return NULLOBJ;
    }

    /* read the header information */
    titleLines = 0;
    while (4 != fscanf(inFile, "%d %f %f %f\n", &nAtoms,
			&origin[0], &origin[1], &origin[2]))
    {
	++titleLines;
    }
    if (titleLines)
	fprintf(stderr, "assuming %d title lines before real data\n", titleLines);

    if (4 != fscanf(inFile, "%d %f %f %f\n", &n1,&rot[0][0],&rot[1][0],&rot[2][0]))
    {
	ReportError("ReadG90file", "error reading header line 2");
    }
    if (4 != fscanf(inFile, "%d %f %f %f\n", &n2,&rot[0][1],&rot[1][1],&rot[2][1]))
    {
	ReportError("ReadG90file", "error reading header line 3");
    }
    if (4 != fscanf(inFile, "%d %f %f %f\n", &n3,&rot[0][2],&rot[1][2],&rot[2][2]))
    {
	ReportError("ReadG90file", "error reading header line 4");
    }

    xScale = sqrt(rot[0][0]*rot[0][0]+rot[1][0]*rot[1][0]+rot[2][0]*rot[2][0]);
    yScale = sqrt(rot[0][1]*rot[0][1]+rot[1][1]*rot[1][1]+rot[2][1]*rot[2][1]);
    zScale = sqrt(rot[0][2]*rot[0][2]+rot[1][2]*rot[1][2]+rot[2][2]*rot[2][2]);

#if 0
#define SCALE 100

    xScale /= SCALE;
    yScale /= SCALE;
    zScale /= SCALE;
#endif

    /* create new Pictures for the blobs representing the atoms */
    for (i = 0; i < MAXWT; ++i)
    {
	picArray[i] = NULLOBJ;
    }

    if (nAtoms >= NATOMS)
    {
	sprintf(tempStr, "number of atoms, %d, exceeds maximum, %d", nAtoms, NATOMS-1);
	ReportError("ReadG90File", tempStr);
	return NULLOBJ;
    }

    /* read the atom position data */
    for (i = 0; i < nAtoms; ++i)
    {
	unsigned int atomicNum;
	float atomicCharge;
	float atomRad;

	if (5 != fscanf(inFile, "%d %f %f %f %f\n", &atomicNum, &atomicCharge,
				&xLoc, &yLoc, &zLoc))
	{
	    sprintf(tempStr, "error reading atom %d\n", i);
	    ReportError("ReadG90file", tempStr);
	}
	/* this could all be done in a transformation matrix, but oh well.. */
	center[i][0] = xLoc * rot[0][0] + yLoc * rot[1][0] + zLoc * rot[2][0];
	center[i][1] = xLoc * rot[0][1] + yLoc * rot[1][1] + zLoc * rot[2][1];
	center[i][2] = xLoc * rot[0][2] + yLoc * rot[1][2] + zLoc * rot[2][2];
	center[i][0] /= xScale;
	center[i][1] /= yScale;
	center[i][2] /= zScale;
	/* size of atom is proportional to sqrt(atomicNumber + C) */
/*
	fprintf(stderr, "loc was %f, %f, %f, transformed to %f, %f, %f. atomicNum %d, scaled to %f\n",
	    xLoc, yLoc, zLoc, center[i][0], center[i][1], center[i][2],
		atomicNum, cbrt(atomicNum));
*/
	if (atomicNum >= MAXWT)
	{
	    ReportError("ReadG90file", "atomic number exceeded maximum");
	    atomicNum = 1;
	}

	if (!picArray[atomicNum])
	    picArray[atomicNum] = NewPicture();

	atomRad = G90_SPHERE_SCALE * cbrt(atomicNum) * MAX3(xScale, yScale, zScale);
	AppendSphereToPicture(picArray[atomicNum], center[i], atomRad, -2);
	stickRad = stickRad < atomRad ? stickRad : atomRad;
    }

    for (i = 0; i < MAXWT; ++i)
    {
	if (picArray[i])
	{
	    retPicture = NewObject(geometryClass,0);
	    SetVar(retPicture, DATA, picArray[i]);
	    SetVar(picArray[i], REPOBJ, retPicture);
	    sprintf(tempStr, "%s-%d-%s", "atoms", i, ShortNameOf(name));
	    SetVar(retPicture, NAME, NewString(tempStr));
	    RegisterDataset(retPicture);
	}
    }

    /* create the data holder */
    fieldData = NewRealArray(3, (long) n1, (long) n2, (long) n3);
    dataPtr = ArrayMeat(fieldData);

    /* read the grid data */
    dataAverage = 0.0;
    dataCount = 0;
    notdone = true;
    for (i=0; i<n1 && notdone; ++i)
    {
	for (j=0; j<n2 && notdone; ++j)
	{
	    for (k=0; k<n3 && notdone; ++k)
	    {
		real curVal;
		if (1 != fscanf(inFile, "%g", &curVal))
		{
		    sprintf(tempStr, "error reading array element %d %d %d\n", n1, n2, n3);
		    ReportError("ReadG90File", tempStr);
		    notdone = false;
		}
		*(dataPtr + i * n2 * n3 + j * n3 + k) = curVal;
		dataAverage = (dataAverage * dataCount + curVal) / (dataCount + 1);
		++dataCount;
	    }
	}
    }

    fprintf(stderr, "average data value is %f\n", dataAverage);

    fclose(inFile);

    /*Create the data form*/
    dataForm = NewObject(dataFormClass, 0);
    dimsArray = NewRealArray(1, (long) 3);
    
    /*Put in some dimensions*/
    dims[0] = n1;
    dims[1] = n2;
    dims[2] = n3;
    CArray2Array(dimsArray, dims);
    SetVar(dataForm, DIMENSIONS, dimsArray); 

    /* bounds determined by dimension length+way axis is stretched/squashed */
    boundsArray = NewRealArray(1, 6L);
    bounds[0] = origin[0];
    bounds[1] = xScale * n1 + origin[0];
    bounds[2] = origin[1];
    bounds[3] = yScale * n2 + origin[1];
    bounds[4] = origin[2];
    bounds[5] = zScale * n3 + origin[2];
    CArray2Array(boundsArray, bounds);
    SetVar(dataForm, BOUNDS, boundsArray);

    retField = NewObject(data3DScalar, 0);
    SetVar(retField, DATA, fieldData);
    SetVar(retField, DATAFORM, dataForm);
    sprintf(tempStr, "%s-%s", "charge", ShortNameOf(name));
    SetVar(retField, NAME, NewString(tempStr));

    RegisterDataset(retField);

    /* see if the connection file exists */
    sprintf(tempStr, "%s.bond", name);
    conFile = fopen(tempStr, "r");
    if (!conFile)
    {
	printf("bonds file not found. Won't show molecular bonds\n");
	return NULLOBJ;
    }
    /* stick radius == 1/2 the radius of the smallest atom */
    stickRad /= 2.0;

    picture = NewPicture();

    while(true)
    {
	int at1, at2;

	if (2 != fscanf(conFile, "%d%d", &at1, &at2))
	    goto done;

	if (at1 > nAtoms || at1 <= 0 || at2 > nAtoms || at2 <= 0)
	{
	    printf("atom number out of range in bonds. Some bonds not shown\n");
	}
	else
	{
#ifdef G90_SUBDIVIDE_CYLINDERS

	    float from[3], to[3];

	    for (j = 0; j < 3; ++j)
		to[j] = center[at1-1][j];

	    for(i = 1; i < G90_SUBDIVIDE_CYLINDERS + 1; ++i)
	    {		
		for (j = 0; j < 3; ++j)
		{
		    from[j] = to[j];
		    to[j] = center[at1-1][j] + i * ((center[at2-1][j]
			- center[at1-1][j]) / G90_SUBDIVIDE_CYLINDERS);
		}
		AppendFrustumToPicture(picture, from, stickRad,
					to, stickRad, -2 /*EMP*/);
	    }
#else
	    AppendFrustumToPicture(picture, center[at1-1], stickRad,
					    center[at2-1], stickRad, -2 /*EMP*/);
#endif
	}
    }
done:
    retPicture = NewObject(geometryClass,0);
    SetVar(retPicture, DATA, picture);
    SetVar(picture, REPOBJ, retPicture);
    sprintf(tempStr, "%s-%s", "bonds", ShortNameOf(name));
    SetVar(retPicture, NAME, NewString(tempStr));
    RegisterDataset(retPicture);

    return NULLOBJ;
}

static ObjPtr ReadPBOLDFile(name)
char *name;
/*Reads one of bali's binary files*/
{
    FILE *inFile;
    real dims[3];			/*The dimensions of the data, temp.*/
    real bounds[6];			/*The bounds of the data form*/
    ObjPtr dataForm;
    ObjPtr dimsArray, boundsArray;
    ObjPtr retField, retList, retPicture; /*the things that get returned */
    ObjPtr fieldData;	/* the actual data of the field */
    ObjPtr picture;	/* contains the NFF objects representing atoms*/
    int i, j, k, l, tmp;
    Bool notdone;
    real rdummy, rdummy1, rdummy2;
    real xScale, yScale, zScale;
    real xLoc, yLoc, zLoc;
    int idummy;
    int nAtoms = 0, n1 = 0, n2 = 0, n3 = 0; /* yeah, just 'cause I'm paranoid doesn't mean the compiler isn't out to get me! */
    real *dataPtr;
    real origin[3];

    inFile = fopen(name, "r");
    if (!inFile)
    {
	Error("ReadPBOLDFile", OPENFILEERROR, name);
	return NULLOBJ;
    }

    /* read the header information */
    if (4 != fscanf(inFile, "%d %f %f %f\n", &nAtoms,
			&origin[0], &origin[1], &origin[2]))
    {
	FileFormatError("ReadPBOLDfile", "error reading header line 1");
    }

    /* HAK! */
    rdummy1 = 0.0; rdummy2 = 0.0;
    if (4 != fscanf(inFile, "%d %f %f %f\n", &n1,&xScale,&rdummy1,&rdummy2))
    {
	FileFormatError("ReadPBOLDfile", "error reading header line 2");
    }
    if (4 != fscanf(inFile, "%d %f %f %f\n", &n2,&rdummy1,&yScale,&rdummy2))
    {
	FileFormatError("ReadPBOLDfile", "error reading header line 3");
    }
    if (4 != fscanf(inFile, "%d %f %f %f\n", &n3,&rdummy1,&rdummy2,&zScale))
    {
	FileFormatError("ReadPBOLDfile", "error reading header line 4");
    }
    if (rdummy1 != 0.0 || rdummy2 != 0.0)
    {
	FileFormatError("ReadPBOLDfile", "warning: I don't understand files with weird orientations yet!");
    }

    /* create a new Picture for the NFF stuff representing the atoms */
    picture = NewPicture();

    /* read the atom position data */
    for (i = 0; i < nAtoms; ++i)
    {
	float center[3];
	int atomicNum;
	float atomicCharge;
	if (5 != fscanf(inFile, "%d %f %f %f %f\n", &atomicNum, &atomicCharge,
				&xLoc, &yLoc, &zLoc))
	{ 
	    sprintf(tempStr, "error reading atom %d\n", i);
	    FileFormatError("ReadPBOLDfile", tempStr);
	}
	center[0] = (xLoc - origin[0]) / xScale;
	center[1] = (yLoc - origin[1]) / yScale;
	center[2] = (zLoc - origin[2]) / zScale;
	AppendSphereToPicture(picture, center, 1, -2);
    }

    retPicture = NewObject(geometryClass,0);
    SetVar(retPicture, DATA, picture);
    SetVar(picture, REPOBJ, retPicture);
    sprintf(tempStr, "%s%s", "atoms.", ShortNameOf(name));
    SetVar(retPicture, NAME, NewString(tempStr));
    RegisterDataset(retPicture);

#if 0
    fprintf(stderr, "reading array of dimensions %d, %d, %d\n", n1, n2, n3);
#endif

    /* create the data holder */
    fieldData = NewRealArray(3, (long) n1, (long) n2, (long) n3);
    dataPtr = ArrayMeat(fieldData);

    /* read the grid data */
    notdone = true;
    for (i=0; i<n1 && notdone; ++i)
    {
	for (j=0; j<n2 && notdone; ++j)
	{
	    for (k=0; k<n3 && notdone; ++k)
	    {
		real curVal;
		if (1 != fscanf(inFile, "%g", &curVal))
		{
		    sprintf(tempStr, "error reading array element %d %d %d\n", n1, n2, n3);
		    ReportError("ReadPBOLDFile", tempStr);
		    notdone = false;
		}
		*(dataPtr + i * n2 * n3 + j * n3 + k) = curVal;
	    }
	}
    }

    fclose(inFile);

    /*Create the data form*/
    dataForm = NewObject(dataFormClass, 0);
    dimsArray = NewRealArray(1, (long) 3);
    
    /*Put in some dimensions*/
    dims[0] = n1;
    dims[1] = n2;
    dims[2] = n3;
    CArray2Array(dimsArray, dims);
    SetVar(dataForm, DIMENSIONS, dimsArray); 
    boundsArray = NewRealArray(1, 6L);
    bounds[0] = bounds[2] = bounds[4] = 0.0;
    bounds[1] = n1;
    bounds[3] = n2;
    bounds[5] = n3;
    CArray2Array(boundsArray, bounds);
    SetVar(dataForm, BOUNDS, boundsArray);

    retField = NewObject(data3DScalar, 0);
    SetVar(retField, DATA, fieldData);
    SetVar(retField, DATAFORM, dataForm);
    sprintf(tempStr, "%s%s", "charge.", ShortNameOf(name));
    SetVar(retField, NAME, NewString(tempStr));


    RegisterDataset(retField);
    return NULLOBJ;
}

ObjPtr ReadDAKFile(name)
char *name;
{
    FILE *inFile;
    Bool timeDep;
    int ngrid, ach, time, nc, mc, ibtype[4]; /* parameters read from header*/
    char *title;
    ObjPtr tempData[7];
    real *meatPtr[7];
    ObjPtr tempDataset;
    ObjPtr tempDataForm;
    ObjPtr tempDimsArray;
    real dims[2];
    int i, j, k, l, m; /* misc. loop counters. */
    real bounds[4];
    ObjPtr boundsArray;
    int result;

    inFile = fopen(name, "r");
    if (!inFile)
    {
	Error("ReadDAKFile", OPENFILEERROR, name);
	return NULLOBJ;
    }

    tempStr[0] = 0;
    if (NULL == fgets(tempStr, TEMPSTRSIZE, inFile))
    {
	FileFormatError("ReadDAKFile", "title not found");
	return NULLOBJ;
    }
    if (strlen(tempStr) && tempStr[strlen(tempStr)-1] == '\n')
    {
	tempStr[strlen(tempStr)] = '\0';
	printf("zapped the \n in the title\n");
    }

    printf("strlen(tempStr) = %d\n", strlen(tempStr));

    title = malloc(strlen(tempStr) + 1);
    for (i=0; i<strlen(tempStr) + 1; ++i)
    {
	title[i] = '\0';
    }
    strncpy(title, tempStr, strlen(tempStr) + 1 < TEMPSTRSIZE ?
				strlen(tempStr) + 1 : TEMPSTRSIZE);

    if (1 != fscanf(inFile, "%d", &ngrid))
    {
	FileFormatError("ReadDAKFile", "error in header line");
	free(title);
	return NULLOBJ;
    }


    fprintf(stderr, "title = %s, ngrid = %d\n", title, ngrid);

    for (i = 0; i<ngrid; ++i)
    {
	if (6 != (result = fscanf(inFile, "%d%d%d%d%d%d", &nc, &mc,
			&(ibtype[0]), &(ibtype[1]), &(ibtype[2]), &(ibtype[3]))))
	{
		printf("result == %d\n", result);
		FileFormatError("ReadDAKFile", "error reading section header");
		free(title);
		return NULLOBJ;
	}

	fprintf(stderr,"nc = %d, mc = %d, ibtype = %d, %d, %d, %d\n",
		nc, mc, ibtype[0], ibtype[1], ibtype[2], ibtype[3]);

	dims[0] = mc;
	dims[1] = nc;

	tempDataForm = NewObject(dataFormClass, 0);
	tempDimsArray = NewRealArray(1, 2L);

	CArray2Array(tempDimsArray, dims);
	SetVar(tempDataForm, DIMENSIONS, tempDimsArray);

	/*Put in the bounds*/
	bounds[0] = 0.;
	bounds[1] = mc - 1.0;
	bounds[2] = 0.;
	bounds[3] = nc - 1.0;
	boundsArray = NewRealArray(1, 4L);
	CArray2Array(boundsArray, bounds);
	SetVar(tempDataForm, BOUNDS, boundsArray);


	for (j=0; j<7; ++j)
	{
	    tempData[j] = NewRealArray(2, (long) mc, (long) nc);
	    meatPtr[j] = ArrayMeat(tempData[j]);
	}
	for (k=0; k<mc; ++k)
	{
	    for (l=0; l<nc; ++l)
	    {
		for (m=0; m<7; ++m) /* seven sets of data interleaved */
		{
		    int tmp1, tmp2;

		    if (1 != fscanf(inFile,"%n%12f%n",&tmp1,meatPtr[m]++,&tmp2))
		    {
			FileFormatError("ReadDAKFile", "error reading data");
			return NULLOBJ;
		    }
		    if (tmp2-tmp1 > 14 || tmp2-tmp1 < 11)
		    {
			printf("weird float read, tmp2 - tmp1 = %d\n", tmp2-tmp1);
		    }
		}
	    }
	}
	for (j=0; j<7; ++j)
	{
	    tempDataset = NewObject(data2DScalar, 0);
	    SetVar (tempDataset, DATA, tempData[j]);
	    SetVar (tempDataset, DATAFORM, tempDataForm);
	    sprintf(tempStr, "%s-%d-%d", ShortNameOf(name), i, j);
	    SetVar (tempDataset, NAME, NewString(tempStr));

	    RegisterDataset(tempDataset);
	}
    }
    return NULLOBJ;
}

#define READONE(dataPtr)						\
{									\
    int READtmp1, READtmp2;						\
									\
    if (1 != fscanf(inFile,"%n%12f%n",&READtmp1,dataPtr,&READtmp2))	\
    {									\
	FileFormatError("ReadDAKNEWFile", "error reading data");	\
	return NULLOBJ;							\
    }									\
    if (READtmp2-READtmp1 > 14 || READtmp2-READtmp1 < 11)		\
    {									\
	FileFormatError("ReadDAKNEWFile", "confused data format?");	\
	return NULLOBJ;							\
    }									\
}

ObjPtr ReadDAKNEWFile(name)
char *name;
{
    FILE *inFile;
    Bool timeDep;
    int ngrid, ach, time, nc, mc, ibtype[4]; /* parameters read from header*/
    char *title;
    ObjPtr tempData[7];
    real *meatPtr[7];
    ObjPtr tempDataset;
    ObjPtr tempDataForm;
    ObjPtr tempDimsArray;
    ObjPtr tempGrid,tempGrid2;
    ObjPtr tempGridData,tempGridData2;
    long int rank;
    real dims[2];
    long index[2];
    int i, j, k, l, m; /* misc. loop counters. */
    real bounds[4];
    ObjPtr boundsArray;
    int result;
    real dummy;

    inFile = fopen(name, "r");
    if (!inFile)
    {
	Error("ReadDAKFile", OPENFILEERROR, name);
	return NULLOBJ;
    }

    tempStr[0] = 0;
    if (NULL == fgets(tempStr, TEMPSTRSIZE, inFile))
    {
	FileFormatError("ReadDAKNEWFile", "title not found");
	return NULLOBJ;
    }
    if (strlen(tempStr) && tempStr[strlen(tempStr)-1] == '\n')
    {
	tempStr[strlen(tempStr)] = '\0';
	printf("zapped the \n in the title\n");
    }

    printf("strlen(tempStr) = %d\n", strlen(tempStr));

    title = malloc(strlen(tempStr) + 1);
    for (i=0; i<strlen(tempStr) + 1; ++i)
    {
	title[i] = '\0';
    }
    strncpy(title, tempStr, strlen(tempStr) + 1 < TEMPSTRSIZE ?
				strlen(tempStr) + 1 : TEMPSTRSIZE);

    if (1 != fscanf(inFile, "%d", &ngrid))
    {
	FileFormatError("ReadDAKNEWFile", "error in header line");
	free(title);
	return NULLOBJ;
    }


    fprintf(stderr, "title = %s, ngrid = %d\n", title, ngrid);

    for (i = 0; i<ngrid; ++i)
    {
	float gridXMin, gridXMax, gridYMin, gridYMax;
	if (6 != (result = fscanf(inFile, "%d%d%d%d%d%d", &nc, &mc,
			&(ibtype[0]), &(ibtype[1]), &(ibtype[2]), &(ibtype[3]))))
	{
		printf("result == %d\n", result);
		FileFormatError("ReadDAKNEWFile", "error reading section header");
		free(title);
		return NULLOBJ;
	}

	fprintf(stderr,"nc = %d, mc = %d, ibtype = %d, %d, %d, %d\n",
		nc, mc, ibtype[0], ibtype[1], ibtype[2], ibtype[3]);

	/* file fields 0 and 1 ignored, presently */
	/* Create holders for file fields 2, 5, 6 */
	for (j=0; j<5; ++j)
	{
	    tempData[j] = NewRealArray(2, (long) mc, (long) nc);
	    meatPtr[j] = ArrayMeat(tempData[j]);
	}
	/* Create holder for 2d vector field (formed by file fields 0, 1)*/
	tempGrid = NewObject(datasetClass, 0);
	SetVar(tempGrid, DEFAULTICON, icon2DVector);
	SetVar(tempGrid, NCOMPONENTS, NewInt(2));
	rank = 2;
	tempGridData = SetVar(tempGrid, DATA, NewArray(AT_OBJECT, 1, &rank));
	for (k = 0; k < rank; ++k)
	{
	    ((ObjPtr *) ELEMENTS(tempGridData))[k] = NewRealArray(2, (long) mc, (long) nc);
	}
	if (!SetCurField(FIELD1, tempGrid)) return NULLOBJ;

	/* Create another vecotr field which double-defines  */
	tempGrid2 = NewObject(datasetClass, 0);
	SetVar(tempGrid2, DEFAULTICON, icon2DVector);
	SetVar(tempGrid2, NCOMPONENTS, NewInt(2));
	tempGridData2 = SetVar(tempGrid2, DATA, NewArray(AT_OBJECT, 1, &rank));
	((ObjPtr *) ELEMENTS(tempGridData2))[0] = tempData[3];
	((ObjPtr *) ELEMENTS(tempGridData2))[1] = tempData[4];

	gridXMin = gridYMin = PLUSINF;
	gridXMax = gridYMax = MINUSINF;

	for (index[0]=0; index[0]<mc; ++index[0])
	{
	    for (index[1]=0; index[1]<nc; ++index[1])
	    {
		/* seven sets of data interleaved */

#define FOOBARSCALE 10.0

		/* file fields 0 and 1 form 2D vector dataset */
		READONE(&dummy);
		dummy *= FOOBARSCALE;
		PutFieldComponent(FIELD1, 0, index, dummy);
		if (gridXMin > dummy)
		    gridXMin = dummy;
		if (gridXMax < dummy)
		    gridXMax = dummy;
		READONE(&dummy)
		dummy *= FOOBARSCALE;
		PutFieldComponent(FIELD1, 1, index, dummy);
		if (gridYMin > dummy)
		    gridYMin = dummy;
		if (gridYMax < dummy)
		    gridYMax = dummy;

		/* file field 2 to scalar dataset 0 */
		READONE(meatPtr[0]);
		++meatPtr[0];

		/* file fields 3 and 4 ignored */
		/* temporarily viewed as 2 separate scalars */
		READONE(meatPtr[3]);
		++meatPtr[3];
		READONE(meatPtr[4]);
		++meatPtr[4];

		/* file fields 5 and 6 to scalar datasets 1 and 2 */
		READONE(meatPtr[1]);
		++meatPtr[1];
		READONE(meatPtr[2]);
		++meatPtr[2];
	    }
	}

	dims[0] = mc;
	dims[1] = nc;

	tempDataForm = NewObject(dataFormClass, 0);
	tempDimsArray = NewRealArray(1, 2L);

	CArray2Array(tempDimsArray, dims);
	SetVar(tempDataForm, DIMENSIONS, tempDimsArray);

	/*Put in the bounds*/
	bounds[0] = gridXMin;
	bounds[1] = gridXMax;
	bounds[2] = gridYMin;
	bounds[3] = gridYMax;
	boundsArray = NewRealArray(1, 4L);
	CArray2Array(boundsArray, bounds);
	SetVar(tempDataForm, BOUNDS, boundsArray);

	/* hold our nose and dive in, hoping this grid stuff works */
	SetVar(tempDataForm, DATA, tempGrid);

	/* finish up and Register the scalar fields */
	for (j=0; j<5; ++j)
	{
	    tempDataset = NewObject(data2DScalar, 0);
	    SetVar (tempDataset, DATA, tempData[j]);
	    SetVar (tempDataset, DATAFORM, tempDataForm);
	    if (j < 3)
		sprintf(tempStr, "%s-%d-scalar%d", ShortNameOf(name), i, j);
	    else
		sprintf(tempStr, "%s-%d-vcomp%d", ShortNameOf(name), i, j-3);
	    SetVar (tempDataset, NAME, NewString(tempStr));
	    RegisterDataset(tempDataset);

	}
	/* Register the vector field */
	sprintf(tempStr, "%s-%d-vector", ShortNameOf(name), i);
	SetVar (tempGrid2, NAME, NewString(tempStr));
	SetVar (tempGrid2, DATAFORM, tempDataForm);
	RegisterDataset(tempGrid2);
    }
    return NULLOBJ;
}

void InitJohnFiles()
{
    DefineFormat("GBC", "", ReadGBCFile, 0);
    DefineFormat("GBC2", "", ReadGBC2File, 0);
    DefineFormat("SS", "", ReadSSFile, 0);
#ifndef RELEASE
    DefineFormat("PB", "pb", ReadG90File, 0);
#endif
    DefineFormat("G90", "g90", ReadG90File, 0);
/*    DefineFormat("PBOLD", "", ReadPBOLDFile, 0);
*/
    DefineFormat("DAK", "fplt", ReadDAKNEWFile, 0);
}

void KillJohnFiles()
{
}
