/*------------------------------------------------------------------------------*
 * File Name: SPCFile.cpp	 													*
 * Creation: 																	*
 * Purpose: OriginC Source C file												*
 * Copyright (c) OriginlabCorp.	 2006, 2007, 2008, 2009, 2010					*
 * All Rights Reserved															*
 * 																				*
 * Modification Log:															*
 *	Cheney 2006-12-5 READ_3D_DATA_TO_MATRIX_IF_X_Z_EVENLY_SPACED				*
 *	Cheney 2006-12-7 SET_Z_VALUE_AS_PARAMETER									*
 *	Cheney 2006-12-7 SET_COLUMN_PROPERTY										*
 *	Cheney 2006-12-9 PREPARE_ERR_MESSAGE										*
 *	Cheney 2006-12-22 SET_UNIT_AND_LONGNAME										*
 *	Cheney 2007-1-25 CHECK_IF_SET_SAMPLE_INTERVAL								*
 *	Cheney 2007-3-7 DATASET_NOW_ONLY_SUPPORT_DOUBLE_TYPE_COLUMN					*
 *	Hong 09/04/07 QA80-10263 ALLOW_SAVE_SNAME_WHEN_EXPORT_SPC_BY_ORIGIN			*
 *	Hong 04/21/08 QA80-7225 ADD_OPTION_CONTROL_WHETHER_RENAME_COL_SNAME			*
 *	Hong 07/01/08 QA80-11784 BRING_BACK_SPC_COLUMN_CORNER_INFO					*
 *	Hong 08/05/08 QA80-11953 IMPROVE_SPC_IMPORT_SPEED_BY_SET_DESIGNATION_AT_ONCE*
 *	Hong 08/08/08 QA80-11784 FIX_CRASH_WHEN_IMPORT_MULTI_FILE_AT_ONCE			*
 *	Kyle 12/25/2008 QA80-12811 FIX_SPC_HEADER_INFO_DIFFERENT_FROM_75			*
 *	Kyle 01/07/2009 v8.0994d QA80-12811-P1 FIX_SPC_HEADER_INFO_DIFFERENT_FROM_75*
 *	Sim 02-04-2010 QA81-15063 MOVE_IMP_FILE_INFO_OUT_FROM_COL_USER_INFO_TREE	*
 *	Sim 02-05-2010 QA81-15063 ROLL_BACK_MOVE_COL_INFO_OUT_OF_USER_TREE			*
 *------------------------------------------------------------------------------*/
 
////////////////////////////////////////////////////////////////////////////////////
// Including the system header file Origin.h should be sufficient for most Origin
// applications and is recommended. Origin.h includes many of the most common system
// header files and is automatically pre-compiled when Origin runs the first time.
// Programs including Origin.h subsequently compile much more quickly as long as
// the size and number of other included header files is minimized. All NAG header
// files are now included in Origin.h and no longer need be separately included.
//
// Right-click on the line below and select 'Open "Origin.h"' to open the Origin.h
// system header file.
#include <Origin.h>
////////////////////////////////////////////////////////////////////////////////////


////////////////////////////////////////////////////////////////////////////////////
// Include your own header files here.
#include <SPCData.h> /// Hong 07/01/08 QA80-11784 BRING_BACK_SPC_COLUMN_CORNER_INFO
#include "spcfile.h"
#include <..\Originlab\fu_utils.h> ///---Sim 02-04-2010 QA81-15063 MOVE_IMP_FILE_INFO_OUT_FROM_COL_USER_INFO_TREE
////////////////////////////////////////////////////////////////////////////////////
// Start your functions here.

///Cheney 2006-12-7 PREPARE_TRINFO_WHICH_WANT_TO_SHOW_IN_ORGANIZER
//enum spcTechType
//{
    //spcTechGen = 0,
    //spcTechGC = 1,
    //spcTechCgm = 2,
    //spcTechHPLC = 3,
    //spcTechFTIR = 4,
    //spcTechNIR = 5,
    //spcTechUV = 7,
    //spcTechXry = 8,
    //spcTechMS = 9,
    //spcTechNMR = 10,
    //spcTechRmn = 11,
    //spcTechFlr = 12,
    //spcTechAtm = 13,
    //spcTechDAD = 14,
    //spcTechThrm = 15,
    //spcTechCD = 16,
    //spcTechCNMR = 20,
    //spcTechHNMR = 21,
    //spcTechDNMR = 22,
    //spcTechANMR = 23
//};

//enum spcFileType
//{
    //spcFileTypeEven = 0,
    //spcFileTypeXYY = 1,
    //spcFileTypeXYXY = 2
//};
///end PREPARE_TRINFO_WHICH_WANT_TO_SHOW_IN_ORGANIZER

enum spcXType
{
    spcXArb = 0,
    spcXWaven = 1,
    spcXUMetr = 2,
    spcXNMetr = 3,
    spcXSecs = 4,
    spcXMinuts = 5,
    spcXHertz = 6,
    spcXKHertz = 7,
    spcXMHertz = 8,
    spcXMUnits = 9,
    spcXPPM = 10,
    spcXDays = 11,
    spcXYears = 12,
    spcXRamans = 13,
    spcXeV = 14,
    spcZTextL = 15,
    spcXDiode = 16,
    spcXChanl = 17,
    spcXDegrs = 18,
    spcXDegrF = 19,
    spcXDegrC = 20,
    spcXDegrK = 21,
    spcXPoint = 22,
    spcXMSec = 23,
    spcXUSec = 24,
    spcXNSec = 25,
    spcXGHertz = 26,
    spcXCM = 27,
    spcXMeters = 28,
    spcXMMetr = 29,
    spcXHours = 30,
    spcXAngst = 31,
    spcXDblIgm = 255
};

enum spcYPrec
{
    spcYPrec16BitFixed = 0,
    spcYPrec32BitFixed = 1,
    spcYPrec32BitFloat = 2
};

enum spcYType
{
    spcYArb = 0,
    spcYIgram = 1,
    spcYAbsrb = 2,
    spcYKMonk = 3,
    spcYCount = 4,
    spcYVolts = 5,
    spcYDegrs = 6,
    spcYAmps = 7,
    spcYMeters = 8,
    spcYMVolts = 9,
    spcYLogdr = 10,
    spcYPercnt = 11,
    spcYIntens = 12,
    spcYRelInt = 13,
    spcYEnergy = 14,
    spcYDecbl = 16,
    spcYAbund = 17,
    spcYRelAbn = 18,
    spcYDegrF = 19,
    spcYDegrC = 20,
    spcYDegrK = 21,
    spcYIdxRf = 22,
    spcYExtCf = 23,
    spcYReal = 24,
    spcYImag = 25,
    spcYCmplx = 26,
    spcYMgram = 27,
    spcYGram = 28,
    spcYKGram = 29,
    spcYSRot = 30,
    spcYTrans = 128,
    spcYReflec = 129,
    spcYValley = 130,
    spcYEmisn = 131
};

enum spcZIncType
{
    spcZIncTypeNotMulti = -1,
    spcZIncTypeEven = 0,
    spcZIncTypeOrdered = 1,
    spcZIncTypeRandom = 2
};

///Cheney 2006-12-22 SET_UNIT_AND_LONGNAME
#define VEC_COL_PROPETY_SIZE 8

enum{
	spcXLabel			= 0,
	spcXUnit,
	spcYLabel,
	spcYUnit,
	spcZLabel,
	spcZUnit,
	spcWLabel,
	spcWUnit,
};

#define STR_UNEVENLY_SPACED "Unevenly spaced"
///end SET_UNIT_AND_LONGNAME

#define JULIAN_DAYS_1900	(2415019)			///Kyle 12/25/2008 QA80-12811 FIX_SPC_HEADER_INFO_DIFFERENT_FROM_75, copy from ....\LABUTIL\DATETIME.H

#define CHK_VALID_RETURN(__func__) if ( nRet = __func__ )\
	return nRet;


///////////////////////////////////////////////////////////////////////////////////////
/////
/////	spcfile class
/////
SPCFile::SPCFile()//BOOL bImport) = true)
//	:BinFile(bImport) 
{ 
	m_bValid = false;
	m_pSPCInfos = NULL; /// Hong 07/01/08 QA80-11784 BRING_BACK_SPC_COLUMN_CORNER_INFO
	try
	{
		m_SPCIO = CreateObject("GSpcIOLib.GSpcIO");
		m_bValid = m_SPCIO? true : false;
	} 
	catch(int nError)
	{
		///Cheney 2006-12-9 PREPARE_ERR_MESSAGE
		//out_str("fail to init SPC IO object!!!");
		error_report("fail to init SPC IO object!!!");
		///end PREPARE_ERR_MESSAGE
	}
}

/// Hong 07/01/08 QA80-11784 BRING_BACK_SPC_COLUMN_CORNER_INFO
SPCFile::~SPCFile()
{
	/// Hong 08/08/08 QA80-11784 FIX_CRASH_WHEN_IMPORT_MULTI_FILE_AT_ONCE
	//if ( m_pSPCInfos )
	//{
	//	delete m_pSPCInfos;
	//	m_pSPCInfos = NULL;
	//}
	safeFreeSPCInfo();
	/// end FIX_CRASH_WHEN_IMPORT_MULTI_FILE_AT_ONCE
}
/// end BRING_BACK_SPC_COLUMN_CORNER_INFO

int SPCFile::Open(LPCTSTR lpszFileName)
{
	if ( m_bValid )
	{
		try
		{
			m_SPCIO.OpenFile(lpszFileName);
			m_trHeader.Reset();
			if ( GetCOMObjectProperties(&m_SPCIO, &m_trHeader, FALSE ) )
			{
				string LogText;
				LogText = m_SPCIO.LogText;
				m_trHeader.AddTextNode(LogText, "LOGText");
				if(!LogText.IsEmpty())
					m_trHeader.LogText.ID = TRGP_MULTILINE_TEXT ;
				m_lpszFileName = lpszFileName;
				return 0;
			}
		}
		catch(int nError)
		{
			///Cheney 2006-12-9 PREPARE_ERR_MESSAGE
			//out_int("Error codes:", nError);
			error_report("Error codes:" + ftoa(nError));
			///end PREPARE_ERR_MESSAGE
		}
	}
	///Cheney 2006-12-9 PREPARE_ERR_MESSAGE
	//out_str("failed to get properties of COM object to treenode!");
	error_report("failed to get properties of COM object to treenode!");
	///end PREPARE_ERR_MESSAGE
	return spcErrorInitFailed;
}

int SPCFile::Import(Datasheet& ds, LPCTSTR lpszFileName, TreeNode& trInfo, int nC1, DWORD dwOption)  
{
	///---Sim 02-07-2007 ADD_RANGE_INFO
	if ( m_orng )
		m_orng.Reset();
	///---END ADD_RANGE_INFO
	
	int nRet;	
	CHK_VALID_RETURN(Open(lpszFileName));
	CHK_VALID_RETURN(ReadData(ds, nC1, dwOption));

	TreeNode trNode = m_trHeader;
	///--- Hong 02/06/07 
	//trInfo.Replace(trNode.Clone(), true, true);
	TreeNode trHeader = trInfo.AddNode("HeaderInfo");
	trHeader.Replace(trNode.Clone(), true, true);
	///---
	//ds.SetName(GetFileName(lpszFileName, TRUE)); ///---Sim 02-07-2007 ADD_AUTO_RENAME
	return 0;
}

int SPCFile::ReadData(Datasheet& ds, int nC1,  DWORD dwOption)
{
	int nRow= 0;
	m_wks = ds;
	m_mlayer = ds;
	if( m_bValid )
	{
		int nTotalSubFiles = m_trHeader.NumSubfiles.nVal;
		int nTotalRows = m_trHeader.NumPoints.nVal;
		int nTotalCols;
		switch( m_trHeader.FileType.nVal )
		{
		case spcFileTypeEven:
			nTotalCols = nTotalSubFiles;
			break;
		case spcFileTypeXYY:
			nTotalCols = nTotalSubFiles + 1;
			break;
		case spcFileTypeXYXY:
			nTotalCols = nTotalSubFiles * 2;
			break;
		default:
			ASSERT(FALSE);
			return spcErrorInvalidDataFile;
		}
		if ( m_wks )
		{
			/// Hong 07/01/08 QA80-11784 BRING_BACK_SPC_COLUMN_CORNER_INFO
			/// Hong 08/08/08 QA80-11784 FIX_CRASH_WHEN_IMPORT_MULTI_FILE_AT_ONCE
			safeFreeSPCInfo();
			/// end FIX_CRASH_WHEN_IMPORT_MULTI_FILE_AT_ONCE
			m_pSPCInfos = new SPCData(m_wks, nC1);
			if ( !m_pSPCInfos->IsValid() )
			{
				error_report("Fail to create SPC info for column");
			}
			readMainHeaderInfo();
			/// end BRING_BACK_SPC_COLUMN_CORNER_INFO
			return ReadDataToWks(nTotalRows, nTotalCols, nC1, dwOption);
		}
		///Cheney 2006-12-5 READ_3D_DATA_TO_MATRIX_IF_X_Z_EVENLY_SPACED
		if ( m_mlayer )
			return ReadDataToMat(nTotalCols, nTotalRows, dwOption);
		///end READ_3D_DATA_TO_MATRIX_IF_X_Z_EVENLY_SPACED
	}
	return spcErrorInvalidDataFile;  /// INVALID SPC DATA FILE
}


int SPCFile::ReadDataToWks(int nTotalRows, int nTotalCols, int nC1, DWORD dwOption)
{
	int nRet;
	int nTotalSubFiles = m_trHeader.NumSubfiles.nVal;
	int nFileType = m_trHeader.FileType.nVal;
	int nCol = nC1;		
	
	///---Sim 02-07-2007 ADD_RANGE_INFO
	if ( m_wks.GetNumCols() < nTotalCols + nC1 )
		m_wks.SetSize(-1, nTotalCols + nC1);
	m_orng.Add(m_wks, nC1, "Range", nC1 + nTotalCols - 1, 0, nTotalRows - 1);
	///---END ADD_RANGE_INFO
	///Cheney 2006-12-7 SET_Z_VALUE_AS_PARAMETER
	//vector<float> vz, vw;
	//vz.SetSize(nTotalRows);
	//vw.SetSize(nTotalRows);
	///END SET_Z_VALUE_AS_PARAMETER
	
	/// Hong 08/05/08 QA80-11953 IMPROVE_SPC_IMPORT_SPEED_BY_SET_DESIGNATION_AT_ONCE
	string		strDesignation = "XY";
	bool		bRepeat = true;
	switch ( nFileType )
	{
	case spcFileTypeXYY:
		strDesignation = "XYY";
		bRepeat = false;		
		break;
	case spcFileTypeEven:
		strDesignation = "Y";
		break;
	case spcFileTypeXYXY:
		break;
	}
	m_wks.SetColDesignations(strDesignation, bRepeat, nC1);
	/// end IMPROVE_SPC_IMPORT_SPEED_BY_SET_DESIGNATION_AT_ONCE
	
	///// AW 12/07/06 MORE_ON_SET_Z_VALUE_AS_PARAMETER
	BOOL bIsZIncTypeEven = m_trHeader.ZIncrementType.nVal == spcZIncTypeEven? TRUE : FALSE;
	double z;
	///// END MORE_ON_SET_Z_VALUE_AS_PARAMETER

	///Cheney 2006-12-22 SET_UNIT_AND_LONGNAME
	prepareColumnProperty();
	///end SET_UNIT_AND_LONGNAME
	///Cheney 2007-1-27 SUPPORT_START_NEW_COLUMNS
	double x0 = 0., xstep = 0.;
	///end SUPPORT_START_NEW_COLUMNS
	if ( spcFileTypeXYY == nFileType )
	{
		/// Hong 04/21/08 QA80-7225 ADD_OPTION_CONTROL_WHETHER_RENAME_COL_SNAME
		//CHK_VALID_RETURN(ReadXDataToCol(nCol, 0 ));
		CHK_VALID_RETURN(ReadXDataToCol(nCol, 0, dwOption));
		/// end ADD_OPTION_CONTROL_WHETHER_RENAME_COL_SNAME
		nCol++;
	}
	else if ( spcFileTypeEven == nFileType )
	{
		x0 = m_trHeader.FirstPoint.dVal;
		///Kyle 12/25/2008 QA80-12811 FIX_SPC_HEADER_INFO_DIFFERENT_FROM_75
		//xstep = (m_trHeader.LastPoint.dVal - x0)/nTotalRows;
		ASSERT(nTotalRows > 1);
		xstep = (m_trHeader.LastPoint.dVal - x0)/(nTotalRows-1);
		///End FIX_SPC_HEADER_INFO_DIFFERENT_FROM_75
		/// Hong 08/05/08 QA80-11953 IMPROVE_SPC_IMPORT_SPEED_BY_SET_DESIGNATION_AT_ONCE
		//Column cc(m_wks, nCol);	
		//if ( OKDATAOBJ_DESIGNATION_X == cc.GetType() )
			//cc.SetType(OKDATAOBJ_DESIGNATION_Y);
		/// end IMPROVE_SPC_IMPORT_SPEED_BY_SET_DESIGNATION_AT_ONCE
		///Cheney 2007-1-27 SUPPORT_START_NEW_COLUMNS
		//CHK_VALID_RETURN(m_wks.SetEvenSampling(x0, xstep, NULL ,m_trHeader.XLabel.strVal)); 
		///end SUPPORT_START_NEW_COLUMNS
		///Cheney 2007-1-25 CHECK_IF_SET_SAMPLE_INTERVAL
		m_bSetSampInterv = true;
		///end CHECK_IF_SET_SAMPLE_INTERVAL
	}
	bool	bFirstYCol = true; /// Hong 07/01/08 QA80-11784 BRING_BACK_SPC_COLUMN_CORNER_INFO
	for ( int ii = 0; ii < nTotalSubFiles; ii++ )
	{
		if ( spcFileTypeXYXY == nFileType )
		{
			/// Hong 04/21/08 QA80-7225 ADD_OPTION_CONTROL_WHETHER_RENAME_COL_SNAME
			//CHK_VALID_RETURN(ReadXDataToCol(nCol, ii ));
			CHK_VALID_RETURN(ReadXDataToCol(nCol, ii, dwOption));
			/// end ADD_OPTION_CONTROL_WHETHER_RENAME_COL_SNAME
			nCol++;
		}
		///Cheney 2007-1-27 SUPPORT_START_NEW_COLUMNS
		else if ( spcFileTypeEven == nFileType )
			CHK_VALID_RETURN(m_wks.SetEvenSampling(x0, xstep, m_wks.Columns(nCol) ,m_trHeader.XUnit.strVal, m_trHeader.XLabel.strVal)); 
		///end SUPPORT_START_NEW_COLUMNS
		/// Hong 07/01/08 QA80-11784 BRING_BACK_SPC_COLUMN_CORNER_INFO
		if ( bFirstYCol && m_pSPCInfos ) // check if necessary
		{
			//m_pSPCInfos->SetStartCol(nCol);
			bFirstYCol = false;
		}
		/// end BRING_BACK_SPC_COLUMN_CORNER_INFO
		/// Hong 04/21/08 QA80-7225 ADD_OPTION_CONTROL_WHETHER_RENAME_COL_SNAME
		//CHK_VALID_RETURN(ReadYDataToCol(nCol, ii ));
		CHK_VALID_RETURN(ReadYDataToCol(nCol, ii, dwOption));
		/// end ADD_OPTION_CONTROL_WHETHER_RENAME_COL_SNAME
		///Cheney 2006-12-7 SET_Z_VALUE_AS_PARAMETER
		if(nTotalSubFiles > 1)
		{
			///// AW 12/07/06 MORE_ON_SET_Z_VALUE_AS_PARAMETER
			/*
			double z = m_trHeader.ZStart.dVal+ii*m_trHeader.ZIncrement.dVal; //z is evenly
			if(m_trHeader.ZIncrementType.nVal != spcZIncTypeEven) // z is not evenly
			{
				Tree trHeader;
				GetCOMObjectProperties(&m_SPCIO, &trHeader, FALSE );
				z = m_trHeader.ZStart.dVal;
			}
			*/
			if ( bIsZIncTypeEven ) 
				z = m_trHeader.ZStart.dVal+ii*m_trHeader.ZIncrement.dVal; //z is evenly
			else
				z = m_SPCIO.ZStart;
			/// END MORE_ON_SET_Z_VALUE_AS_PARAMETER
			m_wks.Columns(nCol).SetParameter(ftoa(z));
		}
		///end SET_Z_VALUE_AS_PARAMETER
		
		///Cheney 2006-12-7 SET_COLUMN_PROPERTY
		handleColumnProperty(m_wks.Columns(nCol), ii);
		///end SET_COLUMN_PROPERTY
		///// temp testing codes to check W and Z
		//Tree trHeader;
		//GetCOMObjectProperties(&m_SPCIO, &trHeader, FALSE );
		//// END temp testing
		
		nCol++;
	}
	return 0; 
}

///Cheney 2006-12-5 READ_3D_DATA_TO_MATRIX_IF_X_Z_EVENLY_SPACED
int SPCFile::ReadDataToMat(int nTotalRows, int nTotalCols, DWORD dwOption)
{
	int nRet;

	//if 1 subfile, means no Z value, should not import to matrix
	//if z type or x type is not evenly spaced, should not import to matrix
  	int nFileType = m_trHeader.FileType.nVal;
  	///Cheney 2006-12-9 PREPARE_ERR_MESSAGE
	//if(nTotalRows == 1 || spcZIncTypeEven != m_trHeader.ZIncrementType.nVal || spcFileTypeEven != nFileType) //only 1 subfile, means no Z value, should not import to matrix
		//return spcErrorCannotImpToMat;
	if(nTotalRows == 1) //only 1 subfile, means no Z value, should not import to matrix
		return spcErrorNoZAxis;
	
	if(spcZIncTypeEven != m_trHeader.ZIncrementType.nVal)
		return spcErrorZNotEven;
	
	if(spcFileTypeEven != nFileType)
		return spcErrorXNotEven;
	///end PREPARE_ERR_MESSAGE
	
	//get x value's start and end, z value's start and end	
	double x1 = m_trHeader.FirstPoint.dVal;
	double x2 = m_trHeader.LastPoint.dVal;
	
	//set matobj's row number by number of w plane
	int nNumWPlanes = m_trHeader.WNumPlanes.nVal;
	nTotalRows = nNumWPlanes == 0? nTotalRows : nTotalRows/ nNumWPlanes;
	///---Sim 02-07-2007 ADD_RANGE_INFO
	//m_mlayer.SetSize(nNumWPlanes == 0? 1:nNumWPlanes, nTotalRows, nTotalCols);
	int nMatObjs = nNumWPlanes == 0? 1:nNumWPlanes;
	if ( m_mlayer.MatrixObjects.Count() > nMatObjs ) // not delete original matrix object
		nMatObjs = m_mlayer.MatrixObjects.Count();
	m_mlayer.SetSize(nMatObjs, nTotalRows, nTotalCols);
	m_orng.Add(m_mlayer, 0, "Range", nMatObjs - 1);
	///---END ADD_RANGE_INFO
	
	double dZIncreasement = m_trHeader.ZIncrement.dVal;
	double z1 = m_trHeader.ZStart.dVal;
	double z2 = z1 + dZIncreasement*(nTotalRows-1);
	
	if(nNumWPlanes == 0)  //no W plane
	{
		CHK_VALID_RETURN(ReadDataToEachMatObj( 0, nTotalRows, nTotalCols, x1, x2, z1, z2, dwOption) )
	}
	else //if has W plane, each w value is a matrix obj
	{
		for(int ii = 0; ii < nNumWPlanes; ii++) 
		{
			CHK_VALID_RETURN(ReadDataToEachMatObj( ii, nTotalRows, nTotalCols, x1, x2, z1, z2, dwOption) )
			z1 = z2 + dZIncreasement;
			z2 = z1 + dZIncreasement*(nTotalRows-1);
			
			///Cheney 2006-12-7 SET_COLUMN_PROPERTY
			////get w value, I don't konw where to put it, just import
			//double w = m_trHeader.WPlaneValue.dVal+ii*m_trHeader.WIncrement.dVal; //w is evenly
			//if(m_trHeader.WIncrement.dVal == 0) // w is not evenly
			//{
				//m_SPCIO.SubfileIndex = ii*nTotalRows/nNumWPlanes;
				//GetCOMObjectProperties(&m_SPCIO, &m_trHeader, FALSE );
				//w = m_trHeader.WPlaneValue.dVal;
			//}
			///end SET_COLUMN_PROPERTY
		}
	}
	
	///Cheney 2006-12-6 FIX_SOME_LITTLE_BUG
	//double x1, x2, z1, z2, dZIncreasement;	
	//int nNumWPlanes;
	//
	//x1 = m_trHeader.FirstPoint.dVal;
	//x2 = m_trHeader.LastPoint.dVal;
	//
	//nNumWPlanes = m_trHeader.WNumPlanes.nVal;
	//nTotalRows /= nNumWPlanes;
//
	//m_mlayer.SetSize(nNumWPlanes, nTotalRows, nTotalCols);
	//int nFileIndexOffset = 0;
	//for ( int ii = 0; ii < nNumWPlanes; ii++ )
	//{
		//CHK_VALID_RETURN(ReadDataToEachMatObj( ii, nTotalRows, nTotalCols, x1, x2, z1, z2, dwOption) )
//
		//z1 += dZIncreasement;
		//z2 += dZIncreasement;
	//}
	///end FIX_SOME_LITTLE_BUG
	
	return 0; 
}

///  AW 12/06/06 MORE_ON_3D_4D_SPC
/*
int SPCFile::ReadDataToEachMatLayer(int nTotalLayerRows, int nTotalLayerCols, DWORD dwOption, int nLayerIndex, double x1, double x2)
{
	int nRet;
	
	//prepare output matrixlayer
	MatrixPage mp;
	m_mlayer.GetParent(mp);
	m_mlayer = mp.Layers(nLayerIndex);
	if(!m_mlayer)
	{
		mp.AddLayer();
		m_mlayer = mp.Layers(nLayerIndex);
	}
		
	//prepare output matrixlayer size
	MatrixObject mo = m_mlayer.MatrixObjects(0);	
	mo.SetNumRows(nTotalLayerRows);
	mo.SetNumCols(nTotalLayerCols);
	
	double z1 = m_trHeader.ZStart.dVal + nLayerIndex*nTotalLayerRows * m_trHeader.ZIncrement.dVal;
	double z2 = z1 + m_trHeader.ZIncrement.dVal * (nTotalLayerRows - 1);
	
	mo.SetXY(x1, z1, x2, z2);
	
	for ( int ii = 0; ii < nTotalLayerRows; ii++ )
	{
		vector<float> vYData;
		m_SPCIO.SubfileIndex = ii + nLayerIndex*nTotalLayerRows;
		vYData = m_SPCIO.YPoints;
		CHK_VALID_RETURN(mo.GetDataObject().SetRow(vYData, ii))
	}
}
*/
int SPCFile::ReadDataToEachMatObj(int nWPlantIndex, int nTotalLayerRows, int nTotalLayerCols, double x1, double x2, double z1, double z2, DWORD dwOption)
{
	int nRet;
	
	MatrixObject mo = m_mlayer.MatrixObjects(nWPlantIndex);	
	mo.SetXY(x1, z1, x2, z2);
	vector<float> vYData;
	int nSubFileIndexOffset = nWPlantIndex*nTotalLayerRows;
	
	for ( int ii = 0; ii < nTotalLayerRows; ii++ )
	{
		m_SPCIO.SubfileIndex = ii + nSubFileIndexOffset;
		vYData = m_SPCIO.YPoints;
		CHK_VALID_RETURN(mo.GetDataObject().SetRow(vYData, ii))
		///Cheney 2006-12-7 SET_COLUMN_PROPERTY
		//get w value, I don't konw where to put it, just import
		if(m_trHeader.WNumPlanes.nVal > 0)
			double w = getWForEachSubfile(m_SPCIO.SubfileIndex);
		///end SET_COLUMN_PROPERTY
	}
	return 0;
}
///  END MORE_ON_3D_4D_SPC

///end READ_3D_DATA_TO_MATRIX_IF_X_Z_EVENLY_SPACED

/// Hong 04/21/08 QA80-7225 ADD_OPTION_CONTROL_WHETHER_RENAME_COL_SNAME
//int SPCFile::ReadXDataToCol(int nCol, int nSubFileIndex)
int SPCFile::ReadXDataToCol(int nCol, int nSubFileIndex, DWORD dwOption) // = 0
/// end ADD_OPTION_CONTROL_WHETHER_RENAME_COL_SNAME
{
	Column cc(m_wks, nCol);	
	/// Hong 08/05/08 QA80-11953 IMPROVE_SPC_IMPORT_SPEED_BY_SET_DESIGNATION_AT_ONCE
	//if ( OKDATAOBJ_DESIGNATION_X != cc.GetType() )
		//cc.SetType(OKDATAOBJ_DESIGNATION_X);
	/// end IMPROVE_SPC_IMPORT_SPEED_BY_SET_DESIGNATION_AT_ONCE
	
	///Cheney 2007-3-7 DATASET_NOW_ONLY_SUPPORT_DOUBLE_TYPE_COLUMN
	cc.SetFormat(OKCOLTYPE_NUMERIC);
	///end DATASET_NOW_ONLY_SUPPORT_DOUBLE_TYPE_COLUMN
	cc.SetInternalDataType(FSI_REAL, 0);
	
	/// Hong 04/21/08 QA80-7225 ADD_OPTION_CONTROL_WHETHER_RENAME_COL_SNAME
	//cc.SetName(m_trHeader.XCustomLabel.strVal, OCD_ENUM_NEXT); /// Hong 09/04/07 QA80-10263 ALLOW_SAVE_SNAME_WHEN_EXPORT_SPC_BY_ORIGIN
	string	strShortName = m_trHeader.XCustomLabel.strVal;
	if ( (dwOption & SPC_RENAME_SNAME) && !strShortName.IsEmpty() )
	{
		strShortName = strShortName.Left(MAX_COL_SHORT_NAME);
		cc.SetName(strShortName, OCD_ENUM_NEXT);
	}
	/// end ADD_OPTION_CONTROL_WHETHER_RENAME_COL_SNAME
	///Cheney 2006-12-22 SET_UNIT_AND_LONGNAME
	cc.SetLongName(m_trHeader.XLabel.strVal);
	if(!m_trHeader.XUnit.strVal.IsEmpty())
		cc.SetUnits(m_trHeader.XUnit.strVal);
	//cc.SetUnits(m_trHeader.XLabel.strVal);
	///end SET_UNIT_AND_LONGNAME
	
	Dataset<float> ds(cc);
	try 
	{
		m_SPCIO.SubfileIndex = nSubFileIndex;
		ds = m_SPCIO.XPoints;
	}
	catch (int nErro)
	{
		return nErro;
	}	
	return 0;
}

/// Hong 04/21/08 QA80-7225 ADD_OPTION_CONTROL_WHETHER_RENAME_COL_SNAME
//int SPCFile::ReadYDataToCol(int nCol, int nSubFileIndex)
int SPCFile::ReadYDataToCol(int nCol, int nSubFileIndex, DWORD dwOption) // = 0
/// end ADD_OPTION_CONTROL_WHETHER_RENAME_COL_SNAME
{
	Column cc(m_wks, nCol);	
	/// Hong 08/05/08 QA80-11953 IMPROVE_SPC_IMPORT_SPEED_BY_SET_DESIGNATION_AT_ONCE
	//if ( OKDATAOBJ_DESIGNATION_Y != cc.GetType() )
		//cc.SetType(OKDATAOBJ_DESIGNATION_Y);
	/// end IMPROVE_SPC_IMPORT_SPEED_BY_SET_DESIGNATION_AT_ONCE

	/// Hong 04/21/08 QA80-7225 ADD_OPTION_CONTROL_WHETHER_RENAME_COL_SNAME
	//cc.SetName(m_trHeader.YCustomLabel.strVal, OCD_ENUM_NEXT); /// Hong 09/04/07 QA80-10263 ALLOW_SAVE_SNAME_WHEN_EXPORT_SPC_BY_ORIGIN	
	string	strShortName = m_trHeader.YCustomLabel.strVal;
	if ( (dwOption & SPC_RENAME_SNAME) && !strShortName.IsEmpty() )
	{		
		strShortName = strShortName.Left(MAX_COL_SHORT_NAME);
		cc.SetName(strShortName, OCD_ENUM_NEXT); 
	}
	/// end ADD_OPTION_CONTROL_WHETHER_RENAME_COL_SNAME		
	///Cheney 2007-3-7 DATASET_NOW_ONLY_SUPPORT_DOUBLE_TYPE_COLUMN
	cc.SetFormat(OKCOLTYPE_NUMERIC);
	///end DATASET_NOW_ONLY_SUPPORT_DOUBLE_TYPE_COLUMN
	cc.SetInternalDataType(FSI_REAL, 0);
	///Cheney 2006-12-22 SET_UNIT_AND_LONGNAME
	cc.SetLongName(m_trHeader.YLabel.strVal);
	if(!m_trHeader.YUnit.strVal.IsEmpty())
		cc.SetUnits(m_trHeader.YUnit.strVal);
	///end SET_UNIT_AND_LONGNAME
	Dataset<float> ds(cc);
	try 
	{
		m_SPCIO.SubfileIndex = nSubFileIndex;
		ds = m_SPCIO.YPoints;
	}
	catch (int nErro)
	{
		return nErro;
	}	
	/// Hong 07/01/08 QA80-11784 BRING_BACK_SPC_COLUMN_CORNER_INFO
	readSubHeaderInfo(nSubFileIndex, cc);
	/// end BRING_BACK_SPC_COLUMN_CORNER_INFO	
	return 0;
}

/// Hong 07/01/08 QA80-11784 BRING_BACK_SPC_COLUMN_CORNER_INFO
bool	SPCFile::readMainHeaderInfo()
{
	if ( !m_pSPCInfos )
		return false;
	
	OSPCMAINHeader	spcMainHeader;
	getMainHeader(spcMainHeader);
	m_pSPCInfos->SetSPCMainHeader(&spcMainHeader);
	
	ASSERT(m_trHeader.LOGText);	
	///Kyle 12/25/2008 QA80-12811 FIX_SPC_HEADER_INFO_DIFFERENT_FROM_75, "\n" will no output in a newline, and "\r\n" does
	//m_pSPCInfos->SetSPCTextLog(m_trHeader.LOGText.strVal);
	string strText = m_trHeader.LOGText.strVal;
	strText.Replace("\n", "\r\n");
	m_pSPCInfos->SetSPCTextLog(strText);
	///End FIX_SPC_HEADER_INFO_DIFFERENT_FROM_75
	m_pSPCInfos->SetFileName(m_lpszFileName);
	return true;
}

bool	SPCFile::readSubHeaderInfo(int nSubFileIndex, const Column& col)
{
	if ( !m_pSPCInfos || !col )
		return false;
	
	OSPCSUBHeader	spcSubHeader;
	getSubHeader(spcSubHeader, nSubFileIndex, col);
	m_pSPCInfos->SetSPCSubHeader(&spcSubHeader, nSubFileIndex + 1); // LT index
	
	return true;
}

void	SPCFile::getMainHeader(OSPCMAINHeader& spcMainHeader)
{
	ASSERT(m_SPCIO);	
	
	spcMainHeader.ftflgs = 		m_trHeader.FileType.nVal;
	spcMainHeader.fexper = 		m_trHeader.TechniqueType.nVal;
	spcMainHeader.fnpts =		(spcFileTypeXYXY == spcMainHeader.ftflgs) ? 0 : m_trHeader.NumPoints.nVal;
	spcMainHeader.ffirst =		m_trHeader.FirstPoint.dVal;
	spcMainHeader.flast =		m_trHeader.LastPoint.dVal;
	spcMainHeader.fnsub =		m_trHeader.NumSubfiles.nVal;
	spcMainHeader.fxtype =		m_trHeader.XType.nVal;
	spcMainHeader.fytype =		m_trHeader.YType.nVal;
	spcMainHeader.fztype =		m_trHeader.ZType.nVal;	
	double		dJulianDate = m_trHeader.Date.dVal;
	///Kyle 12/25/2008 QA80-12811 FIX_SPC_HEADER_INFO_DIFFERENT_FROM_75, dJulianDate is base on (JULIAN_DAYS_1900 -1), so add offset
	dJulianDate += (JULIAN_DAYS_1900 -1);
	///End FIX_SPC_HEADER_INFO_DIFFERENT_FROM_75
	SYSTEMTIME	sysTime;
	JulianDateToSystemTime(&dJulianDate, &sysTime);
	spcMainHeader.fdate = sysTime;
	lstrcpyn(spcMainHeader.fres, m_trHeader.Resolution.strVal, SPC_RESOLUTION_LENGTH);
	lstrcpyn(spcMainHeader.fsource, m_trHeader.Source.strVal, SPC_SOURCE_LENGTH);
	spcMainHeader.fpeakpt =	m_trHeader.PeakPoint.nVal;	
	for ( int ii = 0; ii < SPC_SPARE_SIZE; ii++ )
	{
		spcMainHeader.fspare[ii] = m_SPCIO.Spare(ii);
	}
	lstrcpyn(spcMainHeader.fcmnt, m_trHeader.Comment.strVal, SPC_COMMENT_LENGTH);
	lstrcpyn(spcMainHeader.fcatxt, m_trHeader.XLabel.strVal, SPC_AXIS_LABEL_LENGTH);
	lstrcpyn(spcMainHeader.fcatyt, m_trHeader.YLabel.strVal, SPC_AXIS_LABEL_LENGTH);
	lstrcpyn(spcMainHeader.fcatzt, m_trHeader.ZLabel.strVal, SPC_AXIS_LABEL_LENGTH);
	spcMainHeader.fmods =		m_trHeader.ModificationBitMask.nVal;
	lstrcpyn(spcMainHeader.fmethod ,m_trHeader.Method.strVal, SPC_METHOD_SIZE);
	///Kyle 01/07/2009 v8.0994d QA80-12811-P1 FIX_SPC_HEADER_INFO_DIFFERENT_FROM_75
	//spcMainHeader.fzinc =		m_trHeader.ZIncrement.nVal;
	spcMainHeader.fzinc =		m_trHeader.ZIncrement.dVal;
	///End FIX_SPC_HEADER_INFO_DIFFERENT_FROM_75
	spcMainHeader.fwplanes =	m_trHeader.WNumPlanes.nVal;
	spcMainHeader.fwinc =		m_trHeader.WIncrement.nVal;
	spcMainHeader.fwtype =		m_trHeader.WType.nVal;	
}

void	SPCFile::getSubHeader(OSPCSUBHeader& spcSubHeader, int nSubFileIndex, const Column& col)
{
	ASSERT(m_SPCIO && col);
	ASSERT(nSubFileIndex <= m_trHeader.NumSubfiles.nVal);
	
	string		strColName;
	col.GetName(strColName);
	lstrcpyn(spcSubHeader.colname, strColName, NAME_SIZE);
	m_SPCIO.SubfileIndex = nSubFileIndex;
	spcSubHeader.subindex =			nSubFileIndex + 1; // LT index
	spcSubHeader.fZstart =			m_SPCIO.ZStart;
	spcSubHeader.fZend =			m_SPCIO.ZEnd;
	spcSubHeader.subnpts = 			(spcFileTypeXYXY == m_trHeader.FileType.nVal) ? m_SPCIO.NumPoints : 0;
	spcSubHeader.subscan = 			m_SPCIO.NumScans;
	if ( m_trHeader.WNumPlanes.nVal > 0 )
		spcSubHeader.subwlevel = getWForEachSubfile(nSubFileIndex); // Not sure if this code is correct
}
/// end BRING_BACK_SPC_COLUMN_CORNER_INFO

///Cheney 2006-12-7 SET_COLUMN_PROPERTY
double SPCFile::getWForEachSubfile(int nSubFile)
{
	ASSERT(m_trHeader.WNumPlanes.nVal); /// Hong 07/01/08 QA80-11784 BRING_BACK_SPC_COLUMN_CORNER_INFO
	int nWPlaneIndex = nSubFile/(m_trHeader.NumSubfiles.nVal/m_trHeader.WNumPlanes.nVal);
	double w = m_trHeader.WPlaneValue.dVal+nWPlaneIndex*m_trHeader.WIncrement.dVal; //w is evenly
	if(m_trHeader.WIncrement.dVal == 0) // w is not evenly
	{
		Tree trHeader;
		GetCOMObjectProperties(&m_SPCIO, &trHeader, FALSE );
		w = m_SPCIO.WPlaneValue;
	}
	return w;
}
///end SET_COLUMN_PROPERTY

///Cheney 2006-12-7 SET_COLUMN_PROPERTY
bool	SPCFile::handleColumnProperty(Column& col, int nSubFileIndex)
{
	//set user parameter
	vector<string> vsNames;
	vector<string> vsValues;
	//if(m_trHeader.NumSubfiles.nVal > 1)
	//{
		//if(!m_trHeader.ZLabel)
			//return false;
		//
		//vsNames.Add("Z Label");
		//vsValues.Add(m_trHeader.ZLabel.strVal);
		//vsNames.Add("Z Unit");
		//vsValues.Add(m_trHeader.ZUnit.strVal);
	//}
	
	if(m_trHeader.WNumPlanes.nVal > 0)
	{
		double w = getWForEachSubfile(nSubFileIndex);
		vsNames.Add("W Value");
		//vsNames.Add("W Label");
		vsValues.Add(ftoa(w));
		
		//if(!m_trHeader.WLabel)
			//return false;
		//
		//vsValues.Add(m_trHeader.WLabel.strVal);
		//vsNames.Add("W Unit");
		//vsValues.Add(m_trHeader.WUnit.strVal);
	}
	vsNames.Add("Subfile Index");
	vsValues.Add(ftoa(m_SPCIO.SubFileIndex+1));
	set_user_parameters(col, vsNames,  vsValues);
	
	//set user info
	string strChannelInfo = "ChannelInfo";
	Tree trChannelInfo;
	trChannelInfo.AddTextNode(m_lpszFileName, "ImportFile");
	if(m_trHeader.NumSubfiles.nVal > 1)
	{
		trChannelInfo.AddTextNode(m_trHeader.ZIncrementType.nVal==spcZIncTypeEven? ftoa(m_trHeader.ZIncrement.dVal) : STR_UNEVENLY_SPACED, "ZIncrement");
		trChannelInfo.AddTextNode(m_trHeader.ZLabel.strVal, "ZLabel");
		trChannelInfo.AddTextNode(m_trHeader.ZUnit.strVal, "ZUnit");
	}
	if(m_trHeader.WNumPlanes.nVal > 0)
	{
		trChannelInfo.AddTextNode(m_trHeader.WIncrement.dVal==0? STR_UNEVENLY_SPACED : ftoa(m_trHeader.WIncrement.dVal), "WIncrement");
		trChannelInfo.AddTextNode(m_trHeader.WLabel.strVal, "WLabel");
		trChannelInfo.AddTextNode(m_trHeader.WUnit.strVal, "WUnit");
	}
	trChannelInfo.AddTextNode(ftoa(m_SPCIO.NumScans), "NumberOfCoAddedScans");
	trChannelInfo.Enable = ENABLE_READ_ONLY;
	trChannelInfo.SetAttribute(STR_ATTRIB_BRANCH, GETNBRANCH_OPEN);
	///---Sim 02-05-2010 QA81-15063 ROLL_BACK_MOVE_COL_INFO_OUT_OF_USER_TREE
	//trChannelInfo.Show = 0; ///---Sim 02-04-2010 QA81-15063 MOVE_IMP_FILE_INFO_OUT_FROM_COL_USER_INFO_TREE
	//bool bRet = set_user_info(col, strChannelInfo, trChannelInfo);
	bool bRet = fu_set_import_file_info(col, trChannelInfo, strChannelInfo, IMPORT_INFO_TO_USER_TREE);
	///---END QA81-15063 ROLL_BACK_MOVE_COL_INFO_OUT_OF_USER_TREE
	///---Sim 02-04-2010 QA81-15063 MOVE_IMP_FILE_INFO_OUT_FROM_COL_USER_INFO_TREE
	///---Sim 02-05-2010 QA81-15063 ROLL_BACK_MOVE_COL_INFO_OUT_OF_USER_TREE
	// roll back move column info out of user tree, as CP said
	//fu_set_import_file_name_info(col, m_lpszFileName);
//
	//trChannelInfo.RemoveChild("ImportFile");
	//trChannelInfo.Show = 1;
	//set_import_file_info(col, trChannelInfo, "SPCChannelInfo");
	///---END QA81-15063 ROLL_BACK_MOVE_COL_INFO_OUT_OF_USER_TREE
	///---END QA81-15063 MOVE_IMP_FILE_INFO_OUT_FROM_COL_USER_INFO_TREE
	return true;
}
///end SET_COLUMN_PROPERTY

///Cheney 2006-12-22 SET_UNIT_AND_LONGNAME
bool	SPCFile::prepareLabelAndUnit(TreeNode& trUbitLabel, string& strLabel, string& strUnit)
{
	if(!trUbitLabel)
		return false;
	
	string strUbitLabel = trUbitLabel.strVal;
	strLabel = strUbitLabel.GetToken( 0, '(' );
	strUnit = strUbitLabel.GetToken( 1, '(' );
	if(!strUnit.IsEmpty())
		strUnit.TrimRight( ')' );
	
	return true;
}

bool	SPCFile::prepareColumnProperty()
{
	//X
	string strLabel, strUnit;
	if(!prepareLabelAndUnit(m_trHeader.XLabel, strLabel, strUnit))
		return false;
	
	m_trHeader.XLabel.strVal = strLabel;
	TreeNode trXUnit = m_trHeader.InsertNode(m_trHeader.XType, "XUnit");
	trXUnit.strVal = strUnit;
	
	//Y
	if(!prepareLabelAndUnit(m_trHeader.YLabel, strLabel, strUnit))
		return false;
	
	m_trHeader.YLabel.strVal = strLabel;
	TreeNode trYUnit = m_trHeader.InsertNode(m_trHeader.YType, "YUnit");
	trYUnit.strVal = strUnit;
	
	//Z
	if(m_trHeader.NumSubfiles.nVal > 1)
	{
		if(!prepareLabelAndUnit(m_trHeader.ZLabel, strLabel, strUnit))
			return false;

		m_trHeader.ZLabel.strVal = strLabel;
		TreeNode trZUnit = m_trHeader.InsertNode(m_trHeader.ZStart, "ZUnit");
		trZUnit.strVal = strUnit;
	}
	
	//W
	if(m_trHeader.WNumPlanes.nVal > 0)
	{
		if(!prepareLabelAndUnit(m_trHeader.WLabel, strLabel, strUnit))
			return false;
		
		TreeNode trWLabel = m_trHeader.InsertNode(m_trHeader.LOGText, "WLabel");
		trWLabel.strVal = strLabel;
		TreeNode trWUnit = m_trHeader.InsertNode(m_trHeader.LOGText, "WUnit");
		trWUnit.strVal = strUnit;
	}
	return true;
}
///end SET_UNIT_AND_LONGNAME

/// Hong 08/08/08 QA80-11784 FIX_CRASH_WHEN_IMPORT_MULTI_FILE_AT_ONCE
void 	SPCFile::safeFreeSPCInfo()
{
	if ( m_pSPCInfos )
	{
		delete m_pSPCInfos;
		m_pSPCInfos = NULL;
	}
}
/// end FIX_CRASH_WHEN_IMPORT_MULTI_FILE_AT_ONCE
