/*------------------------------------------------------------------------------*
 * File Name:	SPE_Utils.C														*
 * Creation: Sim 07-17-2006														*
 * Purpose: OriginC Source C file												*
 * Copyright (c) ABCD Corp.	2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007		*
 * All Rights Reserved															*
 * 																				*
 * Modification Log:															*
 * AW 07/19/06 SOME_WORK_ON_SPE													*
 * Sim 07-20-2006 FIX_SINGLE_FRAME_BUG											*
 * Hong 12/30/06 ADD_MORE_VALID_FILE_CHECK										*
 *	Hong 08/01/07 v8.0671b MATRIX_START_NEW_COLUMNS_CHANGE_NEW_SHEET			*
 *	Hong 09/28/08 QA80-12258 v8.0849 SPE_SUPPORT_MORE_DATE_TYPE					*
 *	Hong 01/07/09 QA80-12258 v8.0994b FIX_FAIL_CORRECT_IMPROT_DOUBLE_DATA		*
 *	Hong 01/08/09 QA80-9252-P8 FIX_SPE_FILE_LOCKED_BY_IMPORT_ROUTINE			*
 *	Sophy 10/14/2009 QA80-12258-P3 IMPROVE_FILE_INFORMATION_WITH_MEANINGFUL_VALS*
 *	Sophy 10/20/2009 QA80-12258-P3 IMPROVE_FILE_INFORMATION_WITH_MEANINGFUL_VALS*
 *	Sophy 12/19/2009 QA80-12258-P3 MORE_WORK_ON_CVT_SPE_HEADER_TO_MEANINGFUL_VALS
 *	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			*
 *------------------------------------------------------------------------------*/
 
////////////////////////////////////////////////////////////////////////////////////
// you can include just this typical header file for most Origin built-in functions and classes
// and it takes a reasonable amount of time to compile, 
#include <origin.h>
// this file include most of the other header files except the NAG header, which takes longer to compile
// NAG routines
//#include <OC_nag.h> // this contains all the NAG headers, 

////////////////////////////////////////////////////////////////////////////////////
#include <tree_utils.h>
#include <oErrMsg.h> ///---Sim 11-07-2006 HANDLE_ERR_MESSAGE_USE_DLL
#include <GetNBox.h> /// Hong 09/28/08 QA80-12258 v8.0849 IMPORT_SPE_SHOW_CALIBRATION_INFO_IN_ORGANIZER
#include "SPE_Utils.h"
#include <..\Originlab\fu_utils.h> ///---Sim 02-04-2010 QA81-15063 MOVE_IMP_FILE_INFO_OUT_FROM_COL_USER_INFO_TREE

#define VALID_SPE_LAST_VALUE	0x5555 // Hong 12/30/06 ADD_MORE_VALID_FILE_CHECK

////////////////////////////////////////////////////////////////////////////////////
// start your functions here

///Sophy 10/20/2009 QA80-12258-P3 IMPROVE_FILE_INFORMATION_WITH_MEANINGFUL_VALS
static bool _get_type(int nType, string& strType)
{
	vector<string> vsControllerType = {
		"No Controller", //-1 offset
		"ST1000",
		"ST120(New)",
		"ST120(Old)",
		"ST130",
		"ST121",
		"ST138",
		"DC131",
		"ST133",
		"ST135",
		"VICCD",
		"ST116",
		"OMA3",
		"OMA4",
		"ST143",
		"VICCDBOX",
		"MICROMAX",
		"SPECTROMAX",
		"MICROVIEW",
		"LOW_COST_SPEC",
		"ST133_5MHZ",
		"EMPTY_5MHZ",
		"EPIX_CONTROLLER",
		"PVCAM",
		"GENERIC"
	};
	if ( nType < -1 || nType >= vsControllerType.GetSize() - 1)
		return false;

	strType = vsControllerType[nType + 1];
	return true;
}

static bool _get_detector(int nDetector, string& strName)
{
	const vector<string> vsDetectors = {
		"Custom CCD", //index offset -1
		"No CCD Sensor", //0
		
		"EEV 256x1024 3-phase",
		"EEV 276x384 3-phase",
		"EEV 1152x298 3-phase",
		"EEV 1152x1242",
		"KODAK 512x768",	//5
		
		"KODAK 1035x1317",
		"KODAK 1024x1280",
		"KODAK 2044x2033",
		"KODAK 2048x3072",
		"KODAK Fast1400", //10
		
		"OSTK1024B",
		"PI 330x1100 8 phase(horz)",
		"PI 532x1752",
		"RET 400x1200",
		"RET 512x512",		//15
		
		"Fairchild 4Kx4K MultiTap",
		"RET 1Kx1K",
		"RET 2Kx2K",
		"TEK 512x512B Back [100ns]",
		"TEK 512x512F Front [100ns]", //20
		
		"TEK 1024x1024B Back [100ns]",
		"TEK 1024x1024F Front [100ns]",
		"TEK 2Kx2K",
		"TH 576x384",
		"EEV 256x1024 6 phase", //25
		
		"EEV frame transfer",
		"EEV FT CCD 57 Front Illum",
		"Sensor Unlimited, Inc, SU320AS",
		"EEV 576x384 6 phase",
		"EEV 1152x298 6 phase", //30
		
		"EEV 1152x1242 6 phase",
		"KODAK 1024x1024 interline",
		"MIT CCD 36 special chip",
		"TEK 1024x1024B Back Illum",
		"TEK 1024x1024F Front Illum", //35
		
		"KODAK 1024x1536",
		"TEK 512x512B [200ns]",
		"TEK 512x512F [200ns]",
		"Fairchild 4096x4096",
		"TEK 512x512D Back Illum", //40
		
		"TEK 512x512D Front Illum",
		"HAMMAMATSU 64x1024",
		"HAMMAMATSU 128x1024",
		"HAMMAMATSU 256x1024",
		"EEV 256x1024 8 phase", //45
		
		"EEV 1152x770 3 phase",
		"EEV 1152x770 6 phase",
		"TEK 1024x1024B Back Illum",
		"PI 330x1100 6 phase(horz)",
		"EEV 256x1024 Front CCD30", //50
		
		"TEK 1024x1024D Back Illum",
		"TEK 1024x1024D Front Illum",
		"TEK 1024x1024D Back-T3 Illum",
		"Thomson 512x512 Front Illum",
		"Thomson 256x1024 FI MPP", //55
		
		"Thomson 2048x1024 FT",
		"SIT 800x2000 Back Illum",
		"SIT 800x2000 Front Illum",
		"TEST CHIP #1 240x330",
		"EEV 1203x1336 3 phase", //60
		
		"EEV 1203x1336 6 phase", 
		"PI 800x1000 Back",
		"PI special 64x1024",
		"PI special 128x1024",
		"PI special 256x1024", //65
		
		"KODAK 4096x4096",
		"EEV 100x1340 Front CCD36",
		"PI special 1030x1300",
		"Video Chip N.American Std 480x640",
		"Video Chip European Std 576x768", //70
		
		"PI special 582x782",
		"PI 2500x600 Back",
		"PI 2500x600 Front",
		"PI 512x512",
		"EEV 400x1340 Front", //75
		
		"EEV 700x1340 Front",
		"EEV 1024x1024",
		"EEV 1024x1024 frame transfer",
		"EEV 1300x1340 Front",
		"SITE 2048x2048 Back", //80
		
		"SITE 2048x2048 Front",
		"EEV 80x80 FT",
		"Special CCD36-00 for EEV",
		"Special CCD36-10 for EEV",
		"Special CCD36-20 for EEV", //85
		
		"Special CCD36-40 for EEV",
		"Thomson 2048x2048",
		"EEV 1300x1300 [OverScan]",
		"Epix Controller 1300x1024",
		"PI Back 512x512 FT(16-Tap)", //90
		
		"HAMMAMATSU 60x1024",
		"HAMMAMATSU 124x1024",
		"HAMMAMATSU 252x1024",
		"EEV 1024x512 FT CCD57",
		"InGaAs Chip 1x256", //95
		
		"InGaAs Chip 1x512 interleaving",
		"Roper Scientic Special 1024x1024 FT",
		"EEV 100x1340 Back CCD36",
		"EEV 400x1340 Back",
		"EEV 700x1340 Back", //100
		
		"EEV 1300x1340 Back",
		"EEV 1004x1024 CCD47-10",
		"EEV 512x2048 CCD42-10",
		"EEEV 2048x1024 FT CCD47-20",
		"EEV 400x1340 Back frame transfer", //105
		
		"EEV 256x1024 Back CCD30",
		"EEV 256x1024 OE CCD30",
		"HAMMAMATSU 58x1024 Back",
		"HAMMAMATSU 122x1024 Back",
		"HAMMAMATSU 250x1024 Back", //110
		
		"EEV 2048x2048 CCD42-40",
		"PID 330x1100 [8ph] V2",
		"Roper Scientic Special 1024x512 FT",
		"KODAK 2084x2084 [KAF-4300E]",
		"EEV 100x1340 Front CCD36", //115
		
		"EEV 400x1340 Front",
		"HAM 2x2048(CCD-PDA)",
		"KODAK 2084x2084 [XRAY]",
		"MARconi 288x576 FT CCD65",
		"Marconi 512x512 CCD77", //120
		
		"EEV 512x2048 Back CCD42-10",
		"InGaAs Chip 1x1024",
		"Xenics InGaAs Chip 256x320",
		"MIT CCD36(Summing Well)",
		"Sensors Unlimited SU256LSB", //125
		
		"InGaAs Chip 1x512(Sensors Unlimited)",
		"EEV 100x1340 Front CCD36",
		"EEV 100x1340 Back CCD36",
		"EEV 400x1340 Front CCD36",
		"EEV 400x1340 Back CCD36", //130
		
		"SpectraHIT 1340x150"
	};
	if ( nDetector >= END_OF_CCD_LIST || nDetector < -1 )
	{
		if ( nDetector >= PDA_DUMMY || nDetector < NO_PDA_SENSOR )
			return false;
		
		const vector<string> vsSensors = {
			"No PDA Sensor", //1000 offset
			"Diode Array Single 128",
			"Diode Array Single 256",
			"Diode Array Single 512",
			"Diode Array Single 1024",
			"Diode Array Single 2048",
			"Diode Array Dua 128l",
			"Diode Array Dual 256",
			"Diode Array Dual 512",
			"Diode Array Dual 1024",
			"Diode Array Dual 2048",
			"Diode Array Single 256 INGAS",
			"Diode Array Single 512 INGAS",
			"Diode Array Single 128 GE",
			"Diode Array Single 256 GE"
		}
		strName = vsSensors[nDetector - 1000];
		return true;
	}
	strName = vsDetectors[nDetector + 1];
	return true;
}

static bool _get_interface_type(int nType, string& strName)
{
	const vector<string> vsInterfaces = {
		"Not Connected",
		"DMA : fast! (ISA board)",
		"TAXI : fast serial (ISA board)",
		"EISA : EISA computer board",
		"TAXI : ISA board in EISA computer",
		"GPIB : OK but not fast",
		"Sun computer, EDT interface card",
		
		"Serial RS170 interface (VICCD)",
		"TAXI : ISA board in PCI computer",
		"SCSI : interface using apsi",
		"OMA4 : interface using emmory-mapped ISA card",
		"PCI scatter-gather, for IBM-PC card",
		
		"PCI simple sw does all the work, for IBM-PC card",
		"PCI scatter-gather, for MAC card",
		"PCI simple sw doest all the work, for Mac",
		"For demo software and test softward",
		"Eisa with new Datacollection object and ring zero driver",
		
		"Extended communication Parallel interface",
		"Data Translation PCI Frame Grabber(RS170)",
		"PCI Fast Fibre Channel Interface",
		"PCI with timer no interrupts",
		"Epix Interface",
		"Universal Serial Bus Interface",
		"PI 1394(firewire) Interface"
	};
	if ( nType < 0 || nType > PI1394_Interface )
		return false;
	strName = vsInterfaces[nType];
	return true;
}

static bool _get_shutter_type(int nType, string& strName)
{
	const vector<string> vsShutters = {
		"None", //1-offset
		"Large",
		"Remote",
		"Small",
		"Electronic",
		"Custom Comp"
	};
	
	if ( nType < 1 || nType > vsShutters.GetSize() )
		return false;
	strName = vsShutters[nType - 1];
	return true;
}

static bool _get_readout_mode(int nMode, string& strMode)
{
	const vector<string> vsReadoutMode = {
		"Not Used",
		"Full Frame",
		"Frame Transfer",
		"Kinetics",
		"Interlined CCD",
		"Odd Frame",
		"Even Frame",
		"Any Frame",
		"Rom DIF"
	};
	
	if ( nMode < 0 || nMode >= vsReadoutMode.GetSize() )
		return false;
	strMode = vsReadoutMode[nMode];
	return true;
}


static bool _get_timing_mode(int nMode, string& strMode)
{
	const vector<string> vsTimingMode = {
		"Free Run", //1 -offset
		"Line Sync",
		"ExtSync",
		"ExtSync Normal",
		"ExtTrig",
		"ExtTrig Normal",
		"Free Run with Store Trigger Enable",
		"ExtSync Normal with Store Trigger Enable",
		"ExtSync Preopen with Store Trigger Enable",
		"ExtTrig Normal with Store Trigger Enable",
		"ExtTrig Preopen with Store Trigger Enable",
		"DC131 Only External Shutter Control",
		"Event Counter",
		"Line Sync and Ext Trigger",
		"Line Sync and Store Enable",
		"Ext Sync and Ext Trig",
		"Pentamax Single Trigger Multiple Frames",
		"Kinetics only, Free Run",
		"Kinetics only, Single Trigger",
		"Kinetics only, multiple Trigger",
		"Internal Exposure Control",
		"External Exposure Contral",
		"Electronic Shutter Action between Images",
		"Sync Come from Backplane",
		"Single Trigger, Continuous Data",
		"Bulb Trigger",
		"DIF Single Triggered Mode",
		"DIF Dual Triggered Mode"
	};
	if ( nMode < 1 || nMode > vsTimingMode.GetSize() )
		return false;
	strMode = vsTimingMode[nMode - 1];
	return true;
}


static bool _get_ADC_Rate(int nIndex, string& strRate)
{
	const vector<string> vsADCRate = {
		"Unknown Speed",
		"25 KHz",
		"30 KHz",
		"33 KHz",
		"50 KHz",
		"60 KHz",
		"100 KHz",
		"150 KHz",
		"200 KHz",
		"430 KHz",
		"500 KHz",
		"1 MHz",
		"2 MHz",
		"5 MHz",
		"40 KHz",
		"333 KHz",
		"700 KHz",
		"1400 KHz",
		"3 MHz",
		"10 MHz",
		"20 MHz"
	};
	if ( nIndex < 0 || nIndex >= vsADCRate.GetSize() )
		return false;
	strRate = vsADCRate[nIndex];
	return true;
}


static bool _get_ADC_Resolution(int nIndex, string& strResolution)
{
	const vector<string> vsADCResolution = {
		"Unknown",
		"12 Bits",
		"14 Bits",
		"15 Bits",
		"16 Bits",
		"18 Bits"
	};
	if ( nIndex < 0 || nIndex >= vsADCResolution.GetSize() )
		return false;
	strResolution = vsADCResolution[nIndex];
	return true;
}

static bool _get_ADC_BitAdjust(int nIndex, string& strBitAdjust)
{
	const vector<string> vsADCBitAdjust = {
		"No Clip",
		"Clip1 LSB",
		"Clip2 LSB",
		"Clip1 MSB",
		"Clip2 MSB",
		"Clip MSB LSB"
	};
	
	if ( nIndex < 0 || nIndex >= vsADCBitAdjust.GetSize() )
		return false;
	strBitAdjust = vsADCBitAdjust[nIndex];
	return true;
}


static bool _get_AmpMode(int nMode, string& strAmpMode)
{
	const vector<string> vsAmpMode = {
		"Not Used",
		"Low Noise",
		"High Capability"
	};
	if ( nMode < 0 || nMode >= vsAmpMode.GetSize() )
		return false;
	strAmpMode = vsAmpMode[nMode];
	return true;
}

static bool _get_calib_unit(int nIndex, string& strUnits)
{
	const vector<string> vsCalibUnits = {
		"None",
		"Relative System Units",
		"Absolute Data Units",
		"Polynomial Calibration of User Units",
		"Polynomial Calibration of Wave Length",
		"Absolute Wave Number Units",
		"Relative Wave Number Units",
		"Electron Volts"
	};
	
	if ( nIndex < 0 || nIndex >= XW_XDUNITEND )
		return false;
	strUnits = vsCalibUnits[nIndex];
	return true;
}


static bool _get_software_package(int nTypeID, string& strApp)
{
	const vector<string> vsAppType = {
		"Unknown",
		"WinView",
		"WinSpec",
		"WinLite",
		"WinXTest"
	};
	if ( nTypeID < 0 || nTypeID >= vsAppType.GetSize() )
		return false;
	strApp = vsAppType[nTypeID];
	return true;
}

static bool _get_logicout(int nIndex, string& strLogicOut)
{
	const vector<string> vsLogicOut = {
		"Not Scan",
		"Shutter",
		"Not Ready",
		"Logic 0",
		"Cleaning",
		"Not Fit Image Shift",
		"BNG Reserved",
		"Logic 1"
	};
	if ( nIndex < 0 || nIndex >= vsLogicOut.GetSize() )
		return false;
	strLogicOut = vsLogicOut[nIndex];
	return true;
}

static bool _get_adc_type(int nType, string& strType)
{
	const vector<string> vsTypes = {
		"Unknown",
		"Slow 16 Bits", 
		"Fast 12 Bits",
		"Fast 16 Bits",
		"Slow 14 Bits",
		"Slow 15 Bits",
		"Slow 12 Bits",
		"Slow 18 Bits",
		"Fast",
		"Slow"
	};
	if ( nType < 0 || nType > SLOW_ADC )
		return false;
	strType = vsTypes[nType];
	return true;
}
///end IMPROVE_FILE_INFORMATION_WITH_MEANINGFUL_VALS

///Sophy 12/19/2009 QA80-12258-P3 MORE_WORK_ON_CVT_SPE_HEADER_TO_MEANINGFUL_VALS
static	bool _get_dectector_orientation(int nOrientation, string& strOrientation)
{
	switch(nOrientation)
	{
	case DET_GEO_NORMAL:
		strOrientation = "Normal";
		break;
	case DET_GEO_ROTATE:
		strOrientation = "Rotate";
		break;
	case DET_GEO_REVERSE:
		strOrientation = "Reverse";
		break;
	case DET_GEO_FLIP:
		strOrientation = "Flip";
		break;
	default:
		ASSERT(FALSE);
		strOrientation = "Unknown";
		return false;
	}
	return true;
}
///end MORE_WORK_ON_CVT_SPE_HEADER_TO_MEANINGFUL_VALS
SPEFile::SPEFile(BOOL bImport) 
:BinFile(bImport)
{
}

SPEFile::~SPEFile() 
{
}

//--------------------------------------------------------------------------
// ImportPrincetonInstrumentsFile
//
// This function is called by Origin's Import Wizard.
//
// Return:
//	zero for success
//	non-zero for error
//--------------------------------------------------------------------------


///Sophy 7/14/2010 ORG-568 IAEA_SPE_FILES_LEAD_TO_INFINITE_LOOP
bool		SPEFile::IsValidPrincetonFile(LPCSTR lpcszFileName)
{
	//there seems no specified field to validate Princetom SPE files, so for safety, I check multiple fields.
	SPEHEADER speHdr;
	if ( 0 != ReadHeader(lpcszFileName, speHdr) )
	{
		return false;
	}
	string strJunk;
	bool bCheckType = _get_type(speHdr.type, strJunk);
	if ( !bCheckType )
		return false;
	
	bool bCheckDetectorType = _get_detector(speHdr.DetType, strJunk);
	if ( !bCheckDetectorType )
		return false;
	//we assume CanDoVirtualChipFlag be TRUE/FALSE and should be 0 or 1
	if ( speHdr.CanDoVirtualChipFlag != 0 && speHdr.CanDoVirtualChipFlag != 1 )
		return false;
	
	bool bCheckADCType = _get_adc_type(speHdr.ADCtype, strJunk);
	bool bCheckADCRate = _get_ADC_Rate(speHdr.ADCrate, strJunk);
	if ( XOR(bCheckADCType, bCheckADCRate) )
		return false;
	
	return true;
}
//virtual int SPEFile::Import(LPCSTR lpcszFileName, Page &pgTarget, TreeNode& trFileInfo, TreeNode &trFilter)
virtual int SPEFile::Import(LPCSTR lpcszFileName, Page &pgTarget, TreeNode& trFileInfo, TreeNode &trFilter, int c1) // Hong 01/27/07 ADD_APPEND_COLUMN_MODE
{ 
//	if( trFilter.Type.nVal != FILTER_TYPE_USERDEFINED )
//		return SPE_ERR_FILTER_TYPE;
	SPEHEADER spehdr;
	
	int nRet;
	// return 0 means succ.
	/// AW 07/19/06 SOME_WORK_ON_SPE
	/*
	if ( nRet = ReadHeader(lpcszFileName, trFileInfo, spehdr) )
		return nRet;
	if ( nRet = ReadData(pgTarget, trFileInfo, spehdr) )
		return nRet;
	*/
	if ( nRet = ReadHeader(lpcszFileName, spehdr) )
		return nRet;
	m_strFileName = lpcszFileName; ///---Sim 01-29-2007 HOLD_ON_FILE_NAME
	//if ( nRet = ReadData(pgTarget, spehdr) )
	if ( nRet = ReadData(pgTarget, spehdr, c1) ) // Hong 01/27/07 ADD_APPEND_COLUMN_MODE
		return nRet;
	/// END SOME_WORK_ON_SPE
	
	setPageNameAndLabel(pgTarget, spehdr, lpcszFileName);
		
	// Output header to Notes window
	/// AW 07/19/06 GET_TREE_INFORMATION_IN_SPE
	/*
	Tree tr;
	tr = spehdr;
	nRet = headerToNotes(pgTarget, tr, lpcszFileName);
	*/
	/// AW 08/16/06 BACK_ONE_SPE_XF 
	//trFileInfo = spehdr;
	TreeNode trHeader = tree_check_get_node(trFileInfo, IMPTREE_NODE_HEADER);
	trHeader = spehdr;
	/// END BACK_ONE_SPE_XF
	//nRet = headerToNotes(pgTarget, trFileInfo, lpcszFileName); /// AW 09/29/06 GREG SUPPGEST REMOVING IT
	setInfoMeaning(trHeader); ///---Sim 10-25-2006 GET_USEFUL_FILE_INFO
	/// END GET_TREE_INFORMATION_IN_SPE
	
	return nRet;
}

/// Hong 08/01/07 v8.0671b MATRIX_START_NEW_COLUMNS_CHANGE_NEW_SHEET
int SPEFile::GetDimesion(LPCSTR lpcszFileName, int& nErr)
{
	SPEHEADER spehdr;
	
	if ( nErr = ReadHeader(lpcszFileName, spehdr) )
		return -1;
	
	return spehdr.ydim;		
}
/// end MATRIX_START_NEW_COLUMNS_CHANGE_NEW_SHEET
	
/// AW 07/19/06 SOME_WORK_ON_SPE
//virtual int SPEFile::ReadHeader(LPCSTR lpcszFileName, TreeNode& trFileInfo, SPEHEADER &spehdr)
int SPEFile::ReadHeader(LPCSTR lpcszFileName, SPEHEADER &spehdr)
/// END SOME_WORK_ON_SPE
{
	// Open data file
	/// Hong 01/08/09 QA80-9252-P8 FIX_SPE_FILE_LOCKED_BY_IMPORT_ROUTINE
	//if(!Open(lpcszFileName, file::modeRead | file::typeBinary | file::shareDenyWrite) )
	if(!Open(lpcszFileName, file::modeRead | file::typeBinary | file::shareDenyNone) )
	/// end FIX_SPE_FILE_LOCKED_BY_IMPORT_ROUTINE
		return IMPERR_FAILED_OPEN;  ///---Sim 11-07-2006 HANDLE_ERR_MESSAGE_USE_DLL
	Seek(0, file::begin);
	
	// Read header
	if ( Read(&spehdr, sizeof(SPEHEADER)) != sizeof(SPEHEADER) )
		return IMPERR_HEADER; //Read fail  ///---Sim 11-07-2006 HANDLE_ERR_MESSAGE_USE_DLL
	/// Hong 01/10/06 QA80-9252 ROLL_BACK
	// this is not total correct, need more research to make sure
	/*
	/// Hong 12/30/06 ADD_MORE_VALID_FILE_CHECK
	if( VALID_SPE_LAST_VALUE != spehdr.lastvalue ) 
		return IMPERR_INVALID_FILE;
	/// end ADD_MORE_VALID_FILE_CHECK
	*/
	/// end ROLL_BACK
	return 0;
}

/// AW 07/19/06 SOME_WORK_ON_SPE
//int SPEFile::ReadData(Page &pgTarget, SPEHEADER &spehdr)
int SPEFile::ReadData(Page &pgTarget, SPEHEADER &spehdr, int c1) // Hong 01/27/07 ADD_APPEND_COLUMN_MODE
/// END SOME_WORK_ON_SPE
{
	if (!IsOpen())
		return IMPERR_FAILED_OPEN;  ///---Sim 11-07-2006 HANDLE_ERR_MESSAGE_USE_DLL
	
	int iRet = 0;
	// Read data into page
/// AW 07/19/06 3_XF_NEED_FOR)_SPE
	if( 1 == spehdr.ydim )
		//return Import1DimToPage(pgTarget, spehdr);
		return Import1DimToPage(pgTarget, spehdr, c1); // Hong 01/27/07 ADD_APPEND_COLUMN_MODE
	else
		///---Sim 09-13-2006 CORRECT_IMPORT_TO_MATRIX
		//return ImportToMatrix((MatrixPage)pgTarget, spehdr);
		return Import2DimToPage(pgTarget, spehdr);
		///---END CORRECT_IMPORT_TO_MATRIX
	
	/// AW 08/16/06 BACK_ONE_SPE_XF
	/*	
	return iRet;

	switch ( pgTarget.GetType() )
	{
	case EXIST_MATRIX:
		return ImportToMatrix((MatrixPage)pgTarget, spehdr);
	case EXIST_WKS:
	case EXIST_EXTERN_WKS:
		return ImportToWks((WorksheetPage)pgTarget, spehdr); 
	default:
		ASSERT(false);	// should never come here
	}
	*/
	/// END BACK_ONE_SPE_XF
	return 0;
}
int SPEFile::ImportToMatrix(MatrixPage &mpTarget, SPEHEADER &spehdr)
{
	int nRet;
	int nNumFrames;
	MatrixLayer matLayer = mpTarget.Layers(); // Get Active layer
 
	int nRows, nCols, nBytesToRead;
	nRet = prepareReadPage(spehdr, nNumFrames, nRows, nCols, nBytesToRead);
	if( CER_NO_ERROR != nRet ) ///---Sim 11-07-2006 HANDLE_ERR_MESSAGE_USE_DLL
		return nRet;
	if( !matLayer.SetSize(nNumFrames, nRows, nCols, 0) ) // Index, Row, Col, 0
		return CER_FAILED_CREATE_MATRIX; ///---Sim 11-07-2006 HANDLE_ERR_MESSAGE_USE_DLL

	for (int nFrame=0; nFrame<nNumFrames; nFrame++)
	{
		Matrix mat(matLayer, nFrame);
		nRet = DataToMatrix(mat, spehdr.datatype, nRows, nCols, nBytesToRead);
		if (CER_NO_ERROR != nRet) ///---Sim 11-07-2006 HANDLE_ERR_MESSAGE_USE_DLL
			return nRet;
	}

	// Set target matrix view mode to Image
	if (matLayer)
	{
		///---Sim 07-20-2006 FIX_SINGLE_FRAME_BUG
		//if ( 1 == nNumFrames )
		if (1 == spehdr.ydim)
		///---End
		{
			matLayer.SetViewImage(FALSE);///---Sim 07-20-2006 FIX_SINGLE_FRAME_BUG
			Matrix mat(matLayer, 0 );
			mat.Transpose();         // !!!! need check if need do this, I use this to make it look same as in worksheet
		}
		else
			matLayer.SetViewImage();
	}
	
	return CER_NO_ERROR; ///---Sim 11-07-2006 HANDLE_ERR_MESSAGE_USE_DLL
	
}

/// AW 08/16/06 BACK_ONE_SPE_XF
/*
int SPEFile::ImportToWks(WorksheetPage &wkspgTarget, SPEHEADER &spehdr)
{
	Worksheet wks;
	int nNumFrames;
	int nRet;
	int nRows, nCols, nBytesToRead;
	nRet = prepareReadPage(spehdr, nNumFrames, nRows, nCols, nBytesToRead);
	if( SPE_ERR_NONE != nRet )
		return nRet;
	
	for (int nFrame=0; nFrame<nNumFrames; nFrame++)
	{
		wks = wkspgTarget.Layers(nFrame);
		// read data to wks, add later
		
	}
	ASSERT(false);  // add later
	return -1;
	
}
*/
/// END BACK_ONE_SPE_XF

int SPEFile::prepareReadPage(SPEHEADER& spehdr, int& nNumFrames, int& nRows, int& nCols, int& nBytesToRead)
{
	//if (0 == nNumFrames) nNumFrames++; ///---Sim 07-20-2006 FIX_SINGLE_FRAME_BUG
	int iRet = GetBytesPerFrame(nBytesToRead, spehdr);
	if( CER_NO_ERROR != iRet ) ///---Sim 11-07-2006 HANDLE_ERR_MESSAGE_USE_DLL
		return iRet;

	if( 1 == spehdr.ydim )
	{
		// For a 1 dimensional file we read in all frames
		nRows = spehdr.NumFrames;
		nCols = spehdr.xdim;
		nBytesToRead *= spehdr.NumFrames;
		nNumFrames = 1;
	}
	else // more than 1 dimension
	{
		nRows = spehdr.ydim;
		nCols = spehdr.xdim;
		nNumFrames = spehdr.NumFrames;
	}
	if (0 == nNumFrames) nNumFrames++; ///---Sim 07-20-2006 FIX_SINGLE_FRAME_BUG
	return CER_NO_ERROR; ///---Sim 11-07-2006 HANDLE_ERR_MESSAGE_USE_DLL
}
/// END 3_XF_NEED_FOR)_SPE



//--------------------------------------------------------------------------
// GetBytesPerFrame
//
//--------------------------------------------------------------------------
int SPEFile::GetBytesPerFrame(int& nBytesPerFrame, SPEHEADER& spehdr)
{
	/// AW 07/19/06 SOME_WORK_ON_SPE
	//if( spehdr.datatype < 0 || spehdr.datatype > 3 )
	/// Hong 09/28/08 QA80-12258 v8.0849 SPE_SUPPORT_MORE_DATE_TYPE
	//if( spehdr.datatype < SPE_DATATYPE_FLOAT || spehdr.datatype > SPE_DATATYPE_UINT )
	if( IS_INVALID_SPE_DATATYPE(spehdr.datatype) )
	/// end SPE_SUPPORT_MORE_DATE_TYPE
	/// END SOME_WORK_ON_SPE
		return IMPERR_UNKNOW_TYPE; ///---Sim 11-07-2006 HANDLE_ERR_MESSAGE_USE_DLL

	/// Hong 01/07/09 QA80-12258 v8.0994b FIX_FAIL_CORRECT_IMPROT_DOUBLE_DATA
	//int nDataTypeSize[] = {4, 4, 4, 2};
	//int nBytesPerElement = nDataTypeSize[spehdr.datatype];	
	int		nBytesPerElement = 0;
	switch ( spehdr.datatype )
	{
	case SPE_DATATYPE_FLOAT:		
	case SPE_DATATYPE_LONG:
	case SPE_DATATYPE_INT:
	case SPE_DATATYPE_ULONG:
		nBytesPerElement = 4;
		break;
	case SPE_DATATYPE_UINT:
		nBytesPerElement = 2;
		break;
	case SPE_DATATYPE_DOUBLE:
		nBytesPerElement = 8;
		break;
	case SPE_DATATYPE_BYTE:
		nBytesPerElement = 1;
		break;			
	default:
		ASSERT(FALSE);
	}
	/// end FIX_FAIL_CORRECT_IMPROT_DOUBLE_DATA
	int nElementsPerFrame = spehdr.xdim * spehdr.ydim;
	
	nBytesPerFrame = nElementsPerFrame * nBytesPerElement;
	return CER_NO_ERROR; ///---Sim 11-07-2006 HANDLE_ERR_MESSAGE_USE_DLL
}

/// AW 07/19/06 SOME_WORK_ON_SPE
/*
//--------------------------------------------------------------------------
// SeekToFrameData
//
//--------------------------------------------------------------------------
int SPEFile::SeekToFrameData(SPEHEADER& spehdr, int nFrame)
{
	if( nFrame == 0 || nFrame == 1 )
		return SPE_ERR_NONE;

	if( nFrame < 0 || nFrame > spehdr.NumFrames )
		return SPE_ERR_FRAME_NUMBER;
	
	nFrame--; // our frame number is zero based
	
	// Get number of bytes per frame
	int nBytesPerFrame;
	int iRet = GetBytesPerFrame(nBytesPerFrame, spehdr);
	if( SPE_ERR_NONE != iRet )
		return iRet;

	try
	{
		Seek(sizeof(SPEHEADER) + (nBytesPerFrame * nFrame), file::begin);
		iRet = SPE_ERR_NONE;
	}
	catch(int nErr)
	{
		iRet = SPE_ERR_SEEK_DATA;
	}
	
	return iRet;
}
*/

int SPEFile::prepareReadMatrix(SPEHEADER& spehdr, int& nRows, int& nCols, int& nBytesToRead)
{
	int iRet = GetBytesPerFrame(nBytesToRead, spehdr);
	if( CER_NO_ERROR != iRet ) ///---Sim 11-07-2006 HANDLE_ERR_MESSAGE_USE_DLL
		return iRet;

	if( 1 == spehdr.ydim )
	{
		// For a 1 dimensional file we read in all frames
		nRows = spehdr.NumFrames;
		nCols = spehdr.xdim;
		nBytesToRead *= spehdr.NumFrames;
	}
	else // more than 1 dimension
	{
		nRows = spehdr.ydim;
		nCols = spehdr.xdim;
	}
	return CER_NO_ERROR; ///---Sim 11-07-2006 HANDLE_ERR_MESSAGE_USE_DLL
}
/// END SOME_WORK_ON_SPE	
	
//--------------------------------------------------------------------------
// DataToMatrix
//
//--------------------------------------------------------------------------
#define MATRIX_IMPORT_FOR_ALL_TYPE(_TYPE_) \
			matrix<_TYPE_> mm(nRows, nCols);\
			_TYPE_ *lp = mm;\
			nBytesRead = Read(lp, nBytesToRead);\
			mat = mm;\
			break;


/// AW 07/19/06 SOME_WORK_ON_SPE
/*		
int SPEFile::DataToMatrix(Matrix& mat, SPEHEADER& spehdr)
{
	int nBytesPerFrame;
	int iRet;
	if( iRet = GetBytesPerFrame(nBytesPerFrame, spehdr) )
		return iRet;
	
	int nRows, nCols;
	int nBytesToRead;
	if( 1 == spehdr.ydim )
	{
		// For a 1 dimensional file we read in all frames
		nRows = spehdr.NumFrames;
		nCols = spehdr.xdim;
		nBytesToRead = nBytesPerFrame * spehdr.NumFrames;
	}
	else // more than 1 dimension
	{
		nRows = spehdr.ydim;
		nCols = spehdr.xdim;
		nBytesToRead = nBytesPerFrame;
	}
*/
int SPEFile::DataToMatrix(Matrix& mat, int nDataType, int nRows, int nCols, int nBytesToRead )
/// END SOME_WORK_ON_SPE
{	
	int nBytesRead = 0;
	switch( nDataType )
	{
	case SPE_DATATYPE_FLOAT:
		MATRIX_IMPORT_FOR_ALL_TYPE(float)
	case SPE_DATATYPE_LONG:
		MATRIX_IMPORT_FOR_ALL_TYPE(long)
	case SPE_DATATYPE_INT:
		/// Hong 12/30/06 
		// Justin said: integer in SPE is only short in oc
		//MATRIX_IMPORT_FOR_ALL_TYPE(int)
		MATRIX_IMPORT_FOR_ALL_TYPE(short)  
		/// end 
	case SPE_DATATYPE_UINT:
		MATRIX_IMPORT_FOR_ALL_TYPE(ushort)
	/// Hong 09/28/08 QA80-12258 v8.0849 SPE_SUPPORT_MORE_DATE_TYPE
	case SPE_DATATYPE_DOUBLE:
		MATRIX_IMPORT_FOR_ALL_TYPE(double)
	case SPE_DATATYPE_BYTE:
		MATRIX_IMPORT_FOR_ALL_TYPE(BYTE)
	case SPE_DATATYPE_ULONG:
		MATRIX_IMPORT_FOR_ALL_TYPE(uint)
	/// end SPE_SUPPORT_MORE_DATE_TYPE
	default:
		return IMPERR_UNKNOW_TYPE; ///---Sim 11-07-2006 HANDLE_ERR_MESSAGE_USE_DLL
	}

	if( nBytesRead != nBytesToRead )
		return IMPERR_FAILED_READ; ///---Sim 11-07-2006 HANDLE_ERR_MESSAGE_USE_DLL
	return CER_NO_ERROR;  ///---Sim 11-07-2006 HANDLE_ERR_MESSAGE_USE_DLL
}

//--------------------------------------------------------------------------
// Import1DimToPage
//
// Import 1 dimensional data to the specified page.
// If the page is not a worksheet then a new worksheet is created.
// A temporary matrix is always created.  Data is imported into the temporary
// matrix, transposed, and then copied into the target worksheet.
//--------------------------------------------------------------------------
//int SPEFile::Import1DimToPage(Page& pgTarget, SPEHEADER& spehdr)
int SPEFile::Import1DimToPage(Page& pgTarget, SPEHEADER& spehdr, int c1) // Hong 01/27/07 ADD_APPEND_COLUMN_MODE 
{
	// Create a temporary matrix page
	MatrixPage mp;
	mp.Create("origin.otm", CREATE_HIDDEN);
	if( !mp )
		return CER_FAILED_CREATE_TEMP_MATRIX_PAGE; ///---Sim 11-07-2006 HANDLE_ERR_MESSAGE_USE_DLL

	// Get temporary matrix
	Matrix matTmp(mp.GetName());
	if( !matTmp )
		return CER_FAILED_CREATE_TEMP_MATRIX; ///---Sim 11-07-2006 HANDLE_ERR_MESSAGE_USE_DLL
	
	// Import data into temporary matrix
	/// AW 07/19/06 SOME_WORK_ON_SPE
	/*
	int i = DataToMatrix(matTmp, spehdr);
	if( SPE_ERR_NONE != i )
		return i;
	*/
	int nRows, nCols, nBytesToRead;
	int nRet;
	if ( nRet = prepareReadMatrix(spehdr, nRows, nCols, nBytesToRead) )
		return nRet;
	if ( nRet = DataToMatrix(matTmp, spehdr.datatype, nRows, nCols, nBytesToRead) )
		return nRet;
	/// END SOME_WORK_ON_SPE
	
	// Transpose temporary matrix
	//matTmp.Transpose();			/// AW 07/19/06 SOME_WORK_ON_SPE

	// Get target worksheet page
	WorksheetPage wpTarget;
	if( pgTarget && EXIST_WKS == pgTarget.GetType() )
	{
		wpTarget = pgTarget;
	}
	else
	{
		// Create a new worksheet page
		wpTarget.Create("Origin.otw");
		if( !wpTarget.IsValid() )
			return CER_FAILED_CREATE_WKS_PAGE; ///---Sim 11-07-2006 HANDLE_ERR_MESSAGE_USE_DLL
		
		pgTarget = wpTarget;
	}
	
	// Get target worksheet
	Worksheet wks(wpTarget.GetName());
	if( !wks.IsValid() )
		return CER_FAILED_CREATE_WKS; ///---Sim 11-07-2006 HANDLE_ERR_MESSAGE_USE_DLL

	// Setup worksheet
	//wks.SetSize(spehdr.xdim, spehdr.NumFrames, TRUE);
	//wks.SetColDesignations("Y");
	
	// Copy temporary matrix into target worksheet
	/// AW 07/19/06 SOME_WORK_ON_SPE
	//matTmp.CopyTo(wks, 0, 0, spehdr.xdim - 1, spehdr.NumFrames - 1);
	/// Hong 01/27/07 ADD_APPEND_COLUMN_MODE
	//matTmp.CopyTo(wks, 0, 0, spehdr.NumFrames - 1, spehdr.xdim - 1);
	matTmp.CopyTo(wks, 0, 0, spehdr.NumFrames - 1, spehdr.xdim - 1, 0, c1); ///---Sim 02-01-2007 FIX_START_ROW
	/// end ADD_APPEND_COLUMN_MODE
	/// END SOME_WORK_ON_SPE
	/// Hong 01/27/07 ADD_APPEND_COLUMN_MODE
	int nColNum = c1 + spehdr.NumFrames;
	//wks.SetSize( -1, nColNum);
	
	for(int ii=c1; ii < nColNum; ii++)
	{
		Column cc = wks.Columns( ii );
		cc.SetType(OKDATAOBJ_DESIGNATION_Y);
		
		///---Sim 01-29-2007 ADD_USER_INFO_TREE
		///---Sim 02-04-2010 QA81-15063 MOVE_IMP_FILE_INFO_OUT_FROM_COL_USER_INFO_TREE
		//string strColumnInfo = "ColumnInfo";
		//Tree trColumnInfo;
		//trColumnInfo.AddTextNode(m_strFileName, "ImportFile");
		//trColumnInfo.Enable = ENABLE_READ_ONLY;
		//trColumnInfo.SetAttribute(STR_ATTRIB_BRANCH, GETNBRANCH_OPEN);
		//set_user_info(cc, strColumnInfo, trColumnInfo);
		fu_set_import_file_name_info(cc, m_strFileName, IMPORT_INFO_TO_USER_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(cc, m_strFileName);
		///---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
		///---END ADD_USER_INFO_TREE
	}
	/// end ADD_APPEND_COLUMN_MODE
	
	// Destroy temporary matrix page
	mp.Destroy();
	
	return CER_NO_ERROR; ///---Sim 11-07-2006 HANDLE_ERR_MESSAGE_USE_DLL
}

//--------------------------------------------------------------------------
// Import2DimToPage
//
// Import 2 dimensional data to the specified page
// If the specified page is not a matrix page then a new matrix page is
// created.
//--------------------------------------------------------------------------
int SPEFile::Import2DimToPage(Page& pgTarget, SPEHEADER& spehdr)
{
	// Get target matrix page
	MatrixPage mpTarget;
	MatrixLayer matLayer;
	if( pgTarget && EXIST_MATRIX == pgTarget.GetType() )
		mpTarget = pgTarget;
	else
	{
		// Create a new matrix page
		mpTarget.Create("origin.otm");
		if( !mpTarget.IsValid() )
			return CER_FAILED_CREATE_MATRIX_PAGE; ///---Sim 11-07-2006 HANDLE_ERR_MESSAGE_USE_DLL
		
		pgTarget = mpTarget;
	}
	matLayer = mpTarget.Layers(); // Get Active layer
	int nNumFrames = spehdr.NumFrames;
	if (0 == nNumFrames) nNumFrames++;
	if( !matLayer.SetSize(nNumFrames, spehdr.ydim, spehdr.xdim, 0) ) // Index, Row, Col, 0
		return CER_FAILED_CREATE_MATRIX; ///---Sim 11-07-2006 HANDLE_ERR_MESSAGE_USE_DLL

	// Import the specified frame
	int nRet;
	
	/// AW 07/19/06 SOME_WORK_ON_SPE
	int nRows, nCols, nBytesToRead;
	nRet = prepareReadMatrix(spehdr, nRows, nCols, nBytesToRead);
	if( CER_NO_ERROR != nRet ) ///---Sim 11-07-2006 HANDLE_ERR_MESSAGE_USE_DLL
		return nRet;
	/// END SOME_WORK_ON_SPE

	for (int nFrame=0; nFrame<nNumFrames; nFrame++)
	{
		/// AW 07/19/06 SOME_WORK_ON_SPE
		/*
		nRet = SeekToFrameData(spehdr, nFrame);  
		if (SPE_ERR_NONE != nRet)
			return nRet;
		Matrix mat(matLayer, nFrame);
		nRet = DataToMatrix(mat, spehdr);
		*/
		Matrix mat(matLayer, nFrame);
		nRet = DataToMatrix(mat, spehdr.datatype, nRows, nCols, nBytesToRead);
		/// END SOME_WORK_ON_SPE
		if (CER_NO_ERROR != nRet) ///---Sim 11-07-2006 HANDLE_ERR_MESSAGE_USE_DLL
			return nRet;
	}

	// Set target matrix view mode to Image
	if (matLayer)
		matLayer.SetViewImage();
	
	return CER_NO_ERROR; ///---Sim 11-07-2006 HANDLE_ERR_MESSAGE_USE_DLL
}

///---Sim 11-13-2006 NO_NEED_FOR_HEADER_INFO
/*
//--------------------------------------------------------------------------
// headerToNotes
//
//--------------------------------------------------------------------------
int SPEFile::headerToNotes(Page& pg, TreeNode trFileInfo, LPCSTR lpcszFile)
{
	pg.Info.Add("User");
	pg.Info.User.AddSection("Variables");
	
	using var = pg.Info.User.Variables;    
	foreach( TreeNode tn in trFileInfo.Children )
	{
		if( is_numeric(tn.Text) )
			var.AddDouble(tn.tagName, tn.dVal);
		else
			var.AddString(tn.tagName, tn.Text);
	}
	
	string str;
	//if( false == tree_to_str(trFileInfo, str) ) //==> error!
	vector<int> vnTableDisplayFormat = { DISPLAY_CENTER, DISPLAY_RIGHT, DISPLAY_RIGHT};
	if( false == tree_to_str(trFileInfo, str, vnTableDisplayFormat, true) )
		return SPE_ERR_TREE2STR;
	
	// Create Note Window
	Note noteWnd;
	if( !noteWnd.Create() )
		return SPE_ERR_CREATE_NOTE_PAGE;
	
	string strFilename = GetFileName(lpcszFile);
	noteWnd.Rename(strFilename);
	
	string strLabel;
	strLabel.Format("File Information for %s", strFilename);
	noteWnd.Label = strLabel;
	noteWnd.TitleShow = WIN_TITLE_SHOW_LABEL;

	strLabel.Format("File Information for %s\n\n", lpcszFile);
	noteWnd.Text = strLabel + str;

	return 0;
}
*/
///---END NO_NEED_FOR_HEADER_INFO

//--------------------------------------------------------------------------
// setPageNameAndLabel
//
//--------------------------------------------------------------------------
void SPEFile::setPageNameAndLabel(Page& pg, SPEHEADER& spehdr, LPCSTR lpcszFile)
{
	if( pg && pg.IsValid() )
	{
		// Target worksheet page name and label
		string strFilename = GetFileName(lpcszFile);
		pg.Rename(strFilename);
		
		string strLabel;
		strLabel.Format("%s (%d X %d X %d)", strFilename, spehdr.xdim, spehdr.ydim, spehdr.NumFrames ? spehdr.NumFrames : 1);
		pg.Label = strLabel;
		pg.TitleShow = WIN_TITLE_SHOW_LABEL;
	}
}

///---Sim 08-06-2006 SET_FILE_INFO_MEANING
//--------------------------------------------------------------------------
// setInfoMeaning()
//
//--------------------------------------------------------------------------
void SPEFile::setInfoMeaning(TreeNode &trFileInfo)
{
	int nType;
	bool bValue;
	string str;
	
	Tree trMeaning;
	
	/////////////////////////////////////////////
	// Start set information meaing
	/////////////////////////////////////////////
	//----------- General Info Page -------------
	TreeNode trGeneral = trMeaning.AddNode("General");
	// not finish get File Create By
	///Sophy 10/20/2009 QA80-12258-P3 IMPROVE_FILE_INFORMATION_WITH_MEANINGFUL_VALS
	string strCreatedApp;
	_get_software_package(trFileInfo.SWmade.nVal, strCreatedApp);
	trGeneral.SoftwarePackage.strVal = strCreatedApp;
	///end IMPROVE_FILE_INFORMATION_WITH_MEANINGFUL_VALS
	trGeneral.SoftwareVersion.strVal = trFileInfo.sw_version.strVal;
	trGeneral.FileHeaderVersion.dVal = trFileInfo.file_header_ver.dVal;
	trGeneral.Comments1.strVal = trFileInfo.Comments0.strVal;
	trGeneral.Comments2.strVal = trFileInfo.Comments1.strVal;
	trGeneral.Comments3.strVal = trFileInfo.Comments2.strVal;
	trGeneral.Comments4.strVal = trFileInfo.Comments3.strVal;
	trGeneral.Comments5.strVal = trFileInfo.Comments4.strVal;
	
	//----------- Hardware Info Page -------------
	TreeNode trHardware = trMeaning.AddNode("Hardware");
	
	// Controller
	TreeNode trController = trHardware.AddNode("Controller");
	///Sophy 10/14/2009 QA80-12258-P3 IMPROVE_FILE_INFORMATION_WITH_MEANINGFUL_VALS
	trController.Version.nVal = trFileInfo.ControllerVersion.nVal;
	///end IMPROVE_FILE_INFORMATION_WITH_MEANINGFUL_VALS
	trController.Number.nVal = trFileInfo.controllerNum.nVal;
	
	nType = trFileInfo.type.nVal;
	///Sophy 10/20/2009 QA80-12258-P3 IMPROVE_FILE_INFORMATION_WITH_MEANINGFUL_VALS
	//string strControllerType[13] = {"Unknow", "new120 (Type II)", "old120 (Type I )",
		//"ST130", "ST121", "ST138", "DC131 (PentaMax)", "ST133 (MicroMax/SpectroMax)",
		//"ST135 (GPIB)", "VICCD", "ST116 (GPIB)", "OMA3 (GPIB)", "OMA4"};
	//if ( 13 <= nType ) // unknow type
		//nType = 0;
	//trController.Type.strVal = strControllerType[nType];
	string strType;
	_get_type(nType, strType);
	trController.Type.strVal = strType;
	///end IMPROVE_FILE_INFORMATION_WITH_MEANINGFUL_VALS
	///Sophy 10/20/2009 QA80-12258-P3 IMPROVE_FILE_INFORMATION_WITH_MEANINGFUL_VALS
	//int nLogicOutput = trFileInfo.LogicOutput.nVal;
	//if ( 0 != nLogicOutput )
		//trController.LogicOut.dVal = nLogicOutput;
	//else
		//trController.LogicOut.strVal = "Not Scan";
	string strLogicOut = "Unknown";
	_get_logicout(trFileInfo.LogicOutput.nVal, strLogicOut);
	trController.LogicOut.strVal = strLogicOut;
	///end IMPROVE_FILE_INFORMATION_WITH_MEANINGFUL_VALS
	
	///Sophy 10/20/2009 QA80-12258-P3 IMPROVE_FILE_INFORMATION_WITH_MEANINGFUL_VALS
	string strInterface;
	_get_interface_type(trFileInfo.interface_type.nVal, strInterface);
	trController.Interface.strVal = strInterface;
	///end IMPROVE_FILE_INFORMATION_WITH_MEANINGFUL_VALS
	// Readout
	TreeNode trReadout = trHardware.AddNode("Readout");
	///Sophy 10/20/2009 QA80-12258-P3 IMPROVE_FILE_INFORMATION_WITH_MEANINGFUL_VALS
	//trReadout.Mode.dVal = trFileInfo.readoutMode.nVal; // need convert meaning
	string strReadoutMode;
	_get_readout_mode(trFileInfo.readoutMode.nVal, strReadoutMode);
	trReadout.Mode.strVal = strReadoutMode;
	///end IMPROVE_FILE_INFORMATION_WITH_MEANINGFUL_VALS
	
	// Detector
	TreeNode trDetector = trHardware.AddNode("Detector");
	///Sophy 10/20/2009 QA80-12258-P3 IMPROVE_FILE_INFORMATION_WITH_MEANINGFUL_VALS
	string strDetector;
	_get_detector(trFileInfo.DetType.nVal, strDetector);
	trDetector.Type.strVal = strDetector;
	///end IMPROVE_FILE_INFORMATION_WITH_MEANINGFUL_VALS
		
	trDetector.X.Dimension.nVal = trFileInfo.xDimDet.nVal;
	trDetector.X.Pre.nVal = trFileInfo.XPrePixels.nVal;
	trDetector.X.Post.nVal = trFileInfo.XPostPixels.nVal;	
	trDetector.Y.Dimension.nVal = trFileInfo.yDimDet.nVal;
	trDetector.Y.Pre.nVal = trFileInfo.YPrePixels.nVal;
	trDetector.Y.Post.nVal = trFileInfo.YPostPixels.nVal;

	trDetector.CustomChip.strVal = trFileInfo.CustomChipFlag.nVal ? "Yes" : "No";
	trDetector.CustomTiming.strVal = trFileInfo.CustomTimingFlag.nVal ? "Yes" : "No";
	///Sophy 12/19/2009 QA80-12258-P3 MORE_WORK_ON_CVT_SPE_HEADER_TO_MEANINGFUL_VALS
	string strOrientation;
	_get_dectector_orientation(trFileInfo.geometric.nVal, strOrientation);
	trDetector.Orientation.strVal = strOrientation;
	///end MORE_WORK_ON_CVT_SPE_HEADER_TO_MEANINGFUL_VALS
	///Sophy 10/20/2009 QA80-12258-P3 IMPROVE_FILE_INFORMATION_WITH_MEANINGFUL_VALS
	//trDetector.ShutterType.nVal = trFileInfo.ShutterType.nVal; // need convert meaning
	string strShutterType;
	_get_shutter_type(trFileInfo.ShutterType.nVal, strShutterType);
	trDetector.ShutterType.strVal = strShutterType;
	///end IMPROVE_FILE_INFORMATION_WITH_MEANINGFUL_VALS

	// Cleans
	TreeNode trCleans = trHardware.AddNode("Cleans");
	trCleans.NumberCleans.nVal = trFileInfo.cleans.nVal;
	trCleans.AutoCleansActive.strVal = trFileInfo.AutoCleansActive.nVal ? "Yes" : "No";
	trCleans.StripsPerClean.nVal = trFileInfo.NumSkpPerCln.nVal;
	trCleans.UseContCleansInst.strVal = trFileInfo.UseContCleansInst.nVal ? "Yes" : "No";
	
	// Skips
	TreeNode trSkips = trHardware.AddNode("Skips");
	trSkips.MinimumBlockSize.nVal = trFileInfo.minblk.nVal;
	trSkips.NumberOfBlocks.nVal = trFileInfo.numminblk.nVal;
	
	//----------- Experiment Info Page -------------
	TreeNode trExperiment = trMeaning.AddNode("Experiment");
	
	// DateTime
	TreeNode trDateTime = trExperiment.AddNode("DateTime");
	str = trFileInfo.date.strVal; // make a proper format
	str.Insert(2, " ");
	str.Insert(6, " ");
	trDateTime.DateFileCreated.strVal = str;
	str = trFileInfo.ExperimentTimeLocal.strVal;; // make a proper format
	str.Insert(2, ":");
	str.Insert(5, ":");
	trDateTime.ExperimentTimeLocal.strVal = str;
	
	// Timing
	TreeNode trTiming = trExperiment.AddNode("Timing");
	///Sophy 10/20/2009 QA80-12258-P3 IMPROVE_FILE_INFORMATION_WITH_MEANINGFUL_VALS
	//trTiming.Mode.nVal = trFileInfo.mode.nVal; // need convert meaning
	string strTimingMode;
	_get_timing_mode(trFileInfo.mode.nVal, strTimingMode);
	trTiming.Mode.strVal = strTimingMode;
	///end IMPROVE_FILE_INFORMATION_WITH_MEANINGFUL_VALS
	trTiming.TriggeredMode.strVal = trFileInfo.TriggeredModeFlag.nVal ? "Yes" : "No";
	trTiming.ContinuousCleans.strVal = trFileInfo.ContinuousCleansFlag.nVal ? "Yes" : "No";
	trTiming.ExternalTrigger.strVal = trFileInfo.ExternalTriggerFlag.nVal ? "Yes" : "No";
	
	// ADC
	TreeNode trADC = trExperiment.AddNode("ADC");
	///Sophy 10/20/2009 QA80-12258-P3 IMPROVE_FILE_INFORMATION_WITH_MEANINGFUL_VALS
	//trADC.Rate.nVal = trFileInfo.ADCrate.nVal; // need convert meaning
	//trADC.Type.nVal = trFileInfo.ADCtype.nVal; // need convert meaning
	//trADC.Resolution.nVal = trFileInfo.ADCresolution.nVal; // need convert meaning
	//trADC.BitAdjust.nVal = trFileInfo.ADCbitAdjust.nVal; // need convert meaning
	string strRate;
	_get_ADC_Rate(trFileInfo.ADCrate.nVal, strRate);
	trADC.Rate.strVal = strRate;
	
	string strADCType = "Unknown";
	_get_adc_type(trFileInfo.ADCtype.nVal, strADCType);
	trADC.Type.strVal = strADCType;
	
	string strResolution;
	_get_ADC_Resolution(trFileInfo.ADCresolution.nVal, strResolution);
	trADC.Resolution.strVal = strResolution;
	
	string strBitAdjust;
	_get_ADC_BitAdjust(trFileInfo.ADCbitAdjust.nVal, strBitAdjust);
	trADC.BitAdjust.strVal = strBitAdjust;
	///end IMPROVE_FILE_INFORMATION_WITH_MEANINGFUL_VALS
	trADC.Offset.nVal = trFileInfo.ADCoffset.nVal; // need convert meaning

	// Collection Parameters
	TreeNode trCollectionParameters = trExperiment.AddNode("CollectionParameters");
	// not finish get Exposure
	
	///Sophy 10/14/2009 QA80-12258-P3 IMPROVE_FILE_INFORMATION_WITH_MEANINGFUL_VALS
	string strExpTime;
	float fExposureSec = trFileInfo.exp_sec.dVal;
	strExpTime.Format("%f sec", fExposureSec);
	trCollectionParameters.Exposure.strVal = strExpTime;
	///end IMPROVE_FILE_INFORMATION_WITH_MEANINGFUL_VALS
	
	nType = trFileInfo.datatype.nVal;
	string strDataType[5] = {"FLOAT", "LONG INTEGER", "INTEGER", "UNSIGNED INTEGER", "Unknow"};
	if ( 5 <= nType ) // unknow type
		nType = 4;
	trCollectionParameters.DataType.strVal = strDataType[nType];
	
	trCollectionParameters.XSize.nVal = trFileInfo.xdim.nVal;
	trCollectionParameters.YSize.nVal = trFileInfo.ydim.nVal;
	trCollectionParameters.DelayTime.dVal = trFileInfo.DelayTime.dVal;
	trCollectionParameters.ReadoutTime.dVal = trFileInfo.ReadoutTime.dVal;
	trCollectionParameters.NumberFrames.nVal = trFileInfo.NumFrames.nVal;
	///Sophy 10/20/2009 QA80-12258-P3 IMPROVE_FILE_INFORMATION_WITH_MEANINGFUL_VALS
	//trCollectionParameters.AmpMode.nVal = trFileInfo.AmpHiCapLowNoise.nVal; // need convert meaning
	string strAmpMode;
	_get_AmpMode(trFileInfo.AmpHiCapLowNoise.nVal, strAmpMode);
	trCollectionParameters.AmpMode.strVal = strAmpMode;
	///end IMPROVE_FILE_INFORMATION_WITH_MEANINGFUL_VALS
	trCollectionParameters.Accumulation.nVal = trFileInfo.lavgexp.nVal;
	// not finish get Accumulation Type
	trCollectionParameters.SetTemperature.dVal = trFileInfo.DetTemperature.dVal;
	trCollectionParameters.AvalancheGain.dVal = trFileInfo.AvGain.dVal;
	
	///Sophy 10/14/2009 QA80-12258-P3 IMPROVE_FILE_INFORMATION_WITH_MEANINGFUL_VALS
	trCollectionParameters.AccumType.strVal = trFileInfo.HWaccumFlag.nVal == 1 ? "Hardware" : "Software";
	///end IMPROVE_FILE_INFORMATION_WITH_MEANINGFUL_VALS
	//----------- ROIs Info Page -------------
	TreeNode trROIs = trMeaning.AddNode("ROIs");
	int nNumROI = trROIs.RegionNumber.nVal = trFileInfo.NumROI.nVal;
	for (int nNumber = 0; nNumber < nNumROI; nNumber++ )
	{
		string strTag;
		strTag.Format("ROI%d", nNumber+1);
		TreeNode trROI = trROIs.AddNode(strTag);
		
		strTag.Format("ROIinfoblk%d", nNumber);
		trROI.XStart.nVal = trFileInfo.GetNode(strTag+"startx").nVal;
		trROI.XEnd.nVal = trFileInfo.GetNode(strTag+"endx").nVal;
		trROI.XGroup.nVal = trFileInfo.GetNode(strTag+"groupx").nVal;
		trROI.YStart.nVal = trFileInfo.GetNode(strTag+"starty").nVal;
		trROI.YEnd.nVal = trFileInfo.GetNode(strTag+"endy").nVal;
		trROI.YGroup.nVal = trFileInfo.GetNode(strTag+"groupy").nVal;
	}
	
	//----------- Calibration Info Page -------------
	TreeNode trCalibration = trMeaning.AddNode("Calibration");
	/// Hong 09/28/08 QA80-12258 v8.0849 IMPORT_SPE_SHOW_CALIBRATION_INFO_IN_ORGANIZER
	//// not finish get Calibration	
	//trCalibration.Show = 0;
	///Sophy 10/14/2009 QA80-12258-P3 IMPROVE_FILE_INFORMATION_WITH_MEANINGFUL_VALS
	bool bCalValid = trFileInfo.calib_xcalib_valid.nVal || trFileInfo.calib_ycalib_valid.nVal;
	TreeNode trCalValid = trCalibration.AddNode("CalibraValid");
	trCalValid.SetAttribute(STR_LABEL_ATTRIB, bCalValid ? _L("Calibration is Valid") : _L("Calibration is NOT Valid")); //show result on label
	///end IMPROVE_FILE_INFORMATION_WITH_MEANINGFUL_VALS
	
	///Sophy 10/20/2009 QA80-12258-P3 IMPROVE_FILE_INFORMATION_WITH_MEANINGFUL_VALS
	string strInputUnit, strScaleUnit, strPolynomUnit;
	_get_calib_unit(trFileInfo.calib_xcurrent_unit.nVal, strScaleUnit);
	_get_calib_unit(trFileInfo.calib_xpolynom_unit.nVal, strPolynomUnit);
	_get_calib_unit(trFileInfo.calib_xinput_unit.nVal, strInputUnit);
	///end IMPROVE_FILE_INFORMATION_WITH_MEANINGFUL_VALS
	if ( trFileInfo.calib_xcalib_valid.nVal )
	{
		GETN_USE(trCalibration)
		GETN_BEGIN_BRANCH(X, "X")
			GETN_NUM(ScaleOffset, _L("Scaling Offset"), trFileInfo.calib_xoffset.dVal)
			GETN_NUM(ScaleFactor, _L("Scaling Factor"), trFileInfo.calib_xfactor.dVal)
			///Sophy 10/20/2009 QA80-12258-P3 IMPROVE_FILE_INFORMATION_WITH_MEANINGFUL_VALS
			//GETN_NUM(ScaleUnit, _L("Scaling Unit"), trFileInfo.calib_xcurrent_unit.nVal) // maybe need transform
			GETN_STR(ScaleUnit, _L("Scaling Unit"), strScaleUnit)
			///end IMPROVE_FILE_INFORMATION_WITH_MEANINGFUL_VALS
			GETN_STR(ScaleDescription, _L("Scaling Description"), trFileInfo.calib_xstr.strVal)
			//GETN_NUM(InputUnit, _L("Input Unit"), trFileInfo.calib_xinput_unit.nVal)
			//GETN_NUM(PolynomUnit, _L("Polynomial Unit"), trFileInfo.calib_xpolynom_unit.nVal)
			GETN_STR(InputUnit, _L("Input Unit"), strInputUnit)
			GETN_STR(PolynomUnit, _L("Polynomial Unit"), strPolynomUnit)
			///end IMPROVE_FILE_INFORMATION_WITH_MEANINGFUL_VALS
			GETN_NUM(PolynomOrder, _L("Polynomial Order"), trFileInfo.calib_xpolynom_order.nVal)
			///Sophy 12/19/2009 QA80-12258-P3 MORE_WORK_ON_CVT_SPE_HEADER_TO_MEANINGFUL_VALS
			string strCalibMethod = "Unknown";
			if ( trFileInfo.calib_xpolynom_order.nVal > 1 )
			{
				ASSERT(trFileInfo.calib_xcalib_count.nVal > trFileInfo.calib_xpolynom_order.nVal);
				strCalibMethod = "Polynomial";
			}
			else
				strCalibMethod = "Linear";
			GETN_STR(CalibMethod, _L("Calibration Method"), strCalibMethod);
			///end MORE_WORK_ON_CVT_SPE_HEADER_TO_MEANINGFUL_VALS
			GETN_NUM(InputCount, _L("Count of Input"), trFileInfo.calib_xcalib_count.nVal)
			for ( int iXCalib = 0; iXCalib < trFileInfo.calib_xcalib_count.nVal; ++iXCalib )
			{
				string		strLabel;
				strLabel.Format(_L("Data %d"), iXCalib);
				GETN_BEGIN_BRANCH(Input, strLabel)
					GETN_NUM(Position, _L("Pixel Position"), trFileInfo.GetNode("calib_xpixel_position"+iXCalib).dVal)
					GETN_NUM(Value, _L("Value"), trFileInfo.GetNode("calib_xcalib_value"+iXCalib).dVal)
					GETN_NUM(Coeff, _L("Polynomial Coefficient"), trFileInfo.GetNode("calib_xpolynom_coeff"+iXCalib).dVal)					
				GETN_END_BRANCH(Input)
			}
		GETN_END_BRANCH(X)
	}
	if ( trFileInfo.calib_ycalib_valid.nVal )
	{
		GETN_USE(trCalibration)
		GETN_BEGIN_BRANCH(Y, "Y")
			GETN_NUM(ScaleOffset, _L("Scaling Offset"), trFileInfo.calib_yoffset.dVal)
			GETN_NUM(ScaleFactor, _L("Scaling Factor"), trFileInfo.calib_yfactor.dVal)
			GETN_NUM(ScaleUnit, _L("Scaling Unit"), trFileInfo.calib_ycurrent_unit.nVal) // maybe need transform
			GETN_STR(ScaleDescription, _L("Scaling Description"), trFileInfo.calib_ystr.strVal)
			GETN_NUM(InputUnit, _L("Input Unit"), trFileInfo.calib_yinput_unit.nVal)
			GETN_NUM(PolynomUnit, _L("Polynomial Unit"), trFileInfo.calib_ypolynom_unit.nVal)
			GETN_NUM(PolynomOrder, _L("Polynomial Order"), trFileInfo.calib_ypolynom_unit.nVal)
			GETN_NUM(InputCount, _L("Count of Input"), trFileInfo.calib_ycalib_count.nVal)
			for ( int iYCalib = 0; iYCalib < trFileInfo.calib_ycalib_count.nVal; ++iYCalib )
			{
				string		strLabel;
				strLabel.Format(_L("Data %d"), iYCalib);
				GETN_BEGIN_BRANCH(Input, strLabel)
					GETN_NUM(Position, _L("Pixel Position"), trFileInfo.GetNode("calib_ycalib_position"+iYCalib).dVal)
					GETN_NUM(Value, _L("Value"), trFileInfo.GetNode("calib_ycalib_value"+iYCalib).dVal)
					GETN_NUM(Coeff, _L("Polynomial Coefficient"), trFileInfo.GetNode("calib_ypolynom_coeff"+iYCalib).dVal)					
				GETN_END_BRANCH(Input)
			}
		GETN_END_BRANCH(Y)
	}
	/// end IMPORT_SPE_SHOW_CALIBRATION_INFO_IN_ORGANIZER	
	
	//----------- Process Info Page -------------
	TreeNode trProcess = trMeaning.AddNode("Process");
	trProcess.BackgroundSubtractionApplied.strVal = (trFileInfo.BackGrndApplied.nVal == 1) ? "Yes" : "No";
	trProcess.FlapFieldCorrectionApplied.strVal = (trFileInfo.flatFieldApplied.nVal == 1) ? "Yes" : "No";
	trProcess.BlemishRemovalApplied.strVal = (trFileInfo.BlemishApplied.nVal == 1) ? "Yes" : "No";
	
	// Threshold
	TreeNode trThreshold = trProcess.AddNode("Threshold");
	
	bValue = (trFileInfo.ThresholdMinLive.nVal == 1);
	trThreshold.MinimumApplied.strVal = bValue ? "Yes" : "No";
	if ( bValue )
		trThreshold.MinimumValue.dVal = trFileInfo.ThresholdMinVal.dVal;
	
	bValue = (trFileInfo.ThresholdMaxLive.nVal == 1);
	trThreshold.MaximumApplied.strVal = bValue ? "Yes" : "No";
	if ( bValue )
		trThreshold.MaximumValue.dVal = trFileInfo.ThresholdMaxVal.dVal;
	
	// Cosmic Ray Removal
	trThreshold.CosmicRayRemovalApplied.strVal = (trFileInfo.CosmicApplied.nVal == 1) ? "Yes" : "No";
	/////////////////////////////////////////////
	// Done set information meaing
	/////////////////////////////////////////////

	trFileInfo.Replace(trMeaning, TRUE, TRUE);
}
///---END SET_FILE_INFO_MEANING

/*
//--------------------------------------------------------------------------
// tree2str
//
//--------------------------------------------------------------------------
BOOL SPEFile::tree2str(TreeNode& tr, string& str, int nLevel) // = 0
{
	if(NULL==tr)
		return false;
	
	for(int ii = 0; ii < nLevel; ii++)
		str +="  ";
	
	if(tr.GetNodeCount() > 0) // branch node
	{
		str +=tr.tagName + "\n";
		foreach(TreeNode cNode in tr.Children)
			tree2str(cNode, str, nLevel+1);
	}
	else // leaf node
	{
		string strTemp;
		strTemp.Format("%s = %s\n", tr.tagName, tr.Text);
		str += strTemp;
	}

	return true;
}
*/

/*
//--------------------------------------------------------------------------
//--------------------------------------------------------------------------
int ImportSPEFrame(string lpcszMatrix, int nFrame)
{
	MatrixPage pg(lpcszMatrix);
	
	// get file path from page.info.system.import.filepath$
	string strFile;
	page_get_info_var_value(pg, "filepath", strFile, "system.import");
		
	// Open data file
	file filSrc;
	if( !filSrc.Open(strFile, file::modeRead | file::typeBinary | file::shareDenyWrite) )
		return SPE_ERR_FILE_OPEN;
	
	// Read header
	SPEHEADER spehdr;
	int i = filSrc.Read(&spehdr, sizeof(SPEHEADER));
	
	if( sizeof(SPEHEADER) == i )
		i = Import2DimToPage(pg, filSrc, spehdr, nFrame);  
	else
		i = SPE_ERR_READ_HEADER;
	
	filSrc.Close();
	
	return i;
}
*/