/*------------------------------------------------------------------------------*
 * File Name:				 													*
 * Creation: 																	*
 * Purpose: OriginC Source C file												*
 * Copyright (c) ABCD Corp.	2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010		*
 * All Rights Reserved															*
 * 																				*
 * Modification Log:															*
 * Hong 01/17/07 ADD_SPARKLINE_TO_IMPORT_WIZARD									*
 * Sim 08-06-2007 SUPPORT_SMART_SPARKLINE										*
 * Sim 02-27-2008 QA80-11163 IMPORT_RENAME_BOTH_BOOK_LONG_AND_SHORT_NAME		*
 * Sim 09-18-2008 QA80-12203 MOVE_BIN_IMPORT_TO_VC								*
 *	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 "XFunctionEx.h" //<XFbase.h>
#include "iwbase.h" // Hong 8/21/06 CLEAN_HEADER_FILE
#include "fu_utils.h" /// Hong 8/18/06 REMOVE_TO_FU_UTILS
#include "impwiz.h"//Hong 8/07/06 MOVE_TO_IMPWIZ_H
#include <okocUtils.h> ///---Sim 09-18-2008 QA80-12203 MOVE_BIN_IMPORT_TO_VC

///Hong 8/07/06 MOVE_BINIMP_H
//#include "BinImp.h"      	// Function prototypes and non-localized constants 

///---Sim 08-17-2006 REMOVE_TO_FU_UTILS
/*
typedef struct tagBINIMP {
	int iHeaderBytes;				//number of bytes for header
	int iAutoColTypes;				//indicate if set col type explicitly
	int iNumColumns;				//number of columns
	int iPartial;					//indicate partial data will be read from the file
	int iPartialC1;					//partial reading start column number, 0 based, include this column
	int iPartialC2;					//partial reading end column number, this column will not be included
	int iPartialR1;					//partial reading start row number, 0 based, this row will be included
	int iPartialR2;					//partial reading end row number, this row will not be included
	int iRenameWks;					//if rename worksheet name to the file name
	int iBigEndian;					//numeric value byte order, use big endian if TRUE
	int iApplyRange;				//
	int iMode;						// Data destination in worksheet. See ASCIMP_MODE_* constants in OC_Types.h
	/// EJP 07-23-2003 v7.0631 QA70-4575 ADD_SKIPROWS_TO_BINIMP
	int iSkipRows;					// number of data rows to skip for each row of data read
	/// end ADD_SKIPROWS_TO_BINIMP
	/// EJP 09-12-2003 v7.5693 QA70-5073 ADD_READROWS_TO_BINIMP
	int iReadRows;
	/// end ADD_READROWS_TO_BINIMP
	vector<BYTE> vParamType;		//data type for each column
	vector<WORD> vParamSize;		//size of the data type for each column, bytes
	vector<WORD> vParamCount;		//number of consective columns with same data type
	DWORD flags; /// EJP 07-21-2004 QA70-6555 SUPPORT_WKBK_IN_IMPWIZ
} BINIMP;


enum {
	BIN_SUCCEED = 0,				// the import succeeded
	BIN_INVALID_ARGUMENT,			// invalid argument passed to the fucntion
	BIN_OPEN_FILE_FAILURE,			// fail to open the binary data file
	BIN_FAIL_INIT_WKS,				// fail to intialize the worksheet
	BIN_FAIL_RENAME_WKS,			// fail to rename the worksheet
	BIN_INVALID_TYPE,				// invalid data type found in the BINIMP struct 
	BIN_INVALID_SIZE				// invalid data element size
};
///end MOVE_BINIMP_H

#define IMPORT_FILTER_BINIMP					"BINIMP"

#define IS_TYPE_REAL(_type)  	(_type == BIP_TYPE_REAL)
#define IS_TYPE_INT(_type)	 	(_type == BIP_TYPE_INT)
#define IS_TYPE_UINT(_type)	 	(_type == BIP_TYPE_UINT)
#define IS_TYPE_STRING(_type)	(_type == BIP_TYPE_STRING)
*/
///---END REMOVE_TO_FU_UTILS

///---Sim 09-18-2008 QA80-12203 MOVE_BIN_IMPORT_TO_VC
/*
static 	LONG	s_nStartCol = 0;
static	LONG	s_nStartRow = 0;

/// EJP 06-23-2003 IMPROVE_IMPORT_SPEED
static LONG s_lRowSizeInBytes;
static BYTE *s_pbyRowBuffer;
static LONG s_lBytesBeforePartial;
static int s_iFirstParamVecElement;
static int s_iFirstParamCount;
static int s_iLastParamVecElement;
static int s_iLastParamCount;

//typedef int (*FUNCBINC)(Worksheet &wks, LPCSTR lpcszFile, BINIMP *pbi, ASCIMPRESULT* pResult); /// AW 08/06/06 CHECK_IW_FILTER

///---Sim 08-17-2006 REMOVE_TO_FU_UTILS
/$
static BOOL fuGetBINIMP(TreeNode& trFilter, BINIMP& binimp, BOOL bGetCommonNode=FALSE)
{
	TreeNode trBINIMP = trFilter.GetNode(IMPORT_FILTER_BINIMP);
	if( trBINIMP )
	{
		binimp = trBINIMP;
		if( bGetCommonNode )
		{
			binimp.iMode = trFilter.Common.ImportMode.nVal;
			binimp.iRenameWks = trFilter.Common.RenameWks.nVal;
			binimp.iPartial = trFilter.Common.Partial.nVal;
			binimp.iPartialC1 = trFilter.Common.PartialC1.nVal;
			binimp.iPartialC2 = trFilter.Common.PartialC2.nVal;
			binimp.iPartialR1 = trFilter.Common.PartialR1.nVal;
			binimp.iPartialR2 = trFilter.Common.PartialR2.nVal;
			binimp.iSkipRows = tree_node_get_int(trFilter.Common.SkipRows, 0); /// EJP 07-23-2003 v7.0631 QA70-4575 ADD_SKIPROWS_TO_BINIMP
			/// EJP 07-21-2004 QA70-6555 SUPPORT_WORKBOOK_IMPWIZ
			#if _OC_VER >= 0x0800
			binimp.flags = tree_node_get_int(trFilter.Common.Flags, 0);
			#endif // _OC_VER >= 0x0800
			/// end SUPPORT_WORKBOOK_IMPWIZ
		}
		return TRUE;
	}
	return FALSE;
}
$/
///---END REMOVE_TO_FU_UTILS

/// AW 08/06/06 CHECK_IW_FILTER
/$
string fuGetDesignations(TreeNode& trFilter)
{
	string str;
	if( trFilter.Common.ColDesignations )
		str = trFilter.Common.ColDesignations.strVal;
	return str;
}
string fuGetFormats(TreeNode& trFilter)
{
	string str;
	if( trFilter.Common.ColFormats )
		str = trFilter.Common.ColFormats.strVal;
	return str;
}
BOOL fuGetRepetitive(TreeNode& trFilter)
{
	if( trFilter.Common.ColDesignationsRepetitive )
		return trFilter.Common.ColDesignationsRepetitive.nVal;
	return FALSE; // default is off
}
$/
/// END CHECK_IW_FILTER

//BOOL fuGetCustomDate(TreeNode& tnFilter, string& strFormat)
//{
	//ASCIMP ai;
	//if( fuGetASCIMP(tnFilter, ai) )
	//{
		//strFormat = ai.szDateFormat;
		//strFormat.TrimLeft();
		//strFormat.TrimRight();
		//return (!strFormat.IsEmpty());
	//}
	//return FALSE;
//}


// Get the worksheet columns' formats or designations setting, it actually modifies the current settings according filter setting
// This function is called when need to change part of the current settings according filter.
//static int GetColumnSetting(string &strSetting, LPCSTR lpcszFilterSetting, int nTargetCol, int nNumCols, BOOL bRepetitive)
//{
	//if( strSetting.IsEmpty() )
		//return 1; // Error
//
	//// If the filter is NULL, just use strSetting
	//if( !lpcszFilterSetting )
		//return 0; // Success
	//
	//int nFilterLen = lstrlen(lpcszFilterSetting);
	//int nSettingLen = strSetting.GetLength();
	//
	//if( nSettingLen - nTargetCol < nFilterLen )
		//return 1;
	//
	//int nPos = 0;
	//int nCurPosInFilterStr = 0;
	//
	//LPSTR lpszSetting = strSetting.GetBuffer(nSettingLen);
	//LPSTR lpsz = lpszSetting + nTargetCol;
	//
	//while( nPos < nNumCols )
	//{
		//if( nCurPosInFilterStr >= nFilterLen )
			//nCurPosInFilterStr = bRepetitive ? 0 : nFilterLen - 1;
//
		//*(lpsz + nPos) = *(lpcszFilterSetting + nCurPosInFilterStr);
		//
		//nPos++;
		//nCurPosInFilterStr++;
	//}
	//strSetting.ReleaseBuffer();
	//
	//return 0;
//}

////////////////////////////////////////////////////////////////////////////////////
// Start your functions here.

static bool get_param_info_for_col(int& iParamVecElement, int& iParamCount, BINIMP& binimp, int iCol)
{
	int iCurrCol = 0;
	for( int iElement = 0; iElement < binimp.vParamCount.GetSize(); iElement++ )
	{
		for( int iCount = 0; iCount < binimp.vParamCount[iElement]; iCount++ )
		{
			if( iCurrCol == iCol )
			{
				iParamVecElement = iElement;
				iParamCount = iCount;
				return true;
			}
			iCurrCol++;
		}
	}
	return false;
}

static int get_num_bytes_before_col(BINIMP &binimp, int iCol)
{
	int iBytesBeforeCol = 0, iCurrCol = 0;

	for( int iElement = 0; iElement < binimp.vParamCount.GetSize(); iElement++ )
	{
		for( int iCount = 0; iCount < binimp.vParamCount[iElement]; iCount++ )
		{
			if( iCurrCol == iCol )
				return iBytesBeforeCol;
			iBytesBeforeCol += binimp.vParamSize[iElement];
			iCurrCol++;
		}
	}
	return 0;
}

static void init_globals(BINIMP &binimp)
{
	s_lRowSizeInBytes = 0;
	s_pbyRowBuffer = NULL;
	
	if( binimp.iPartial )
	{
		get_param_info_for_col(s_iFirstParamVecElement, s_iFirstParamCount, binimp, binimp.iPartialC1);
		if( binimp.iPartialC2 >= 0 )
			get_param_info_for_col(s_iLastParamVecElement, s_iLastParamCount, binimp, binimp.iPartialC2);
		else
		{
			s_iLastParamVecElement = -1;
			s_iLastParamCount = -1;
		}
		
		s_lBytesBeforePartial = get_num_bytes_before_col(binimp, binimp.iPartialC1);
	}
	else
	{
		s_iFirstParamVecElement = 0;
		s_iFirstParamCount = 0;
		
		s_iLastParamVecElement = -1;
		s_iLastParamCount = -1;
		
		s_lBytesBeforePartial = 0;
	}
}

static void init_wks_starting_col_and_row(Worksheet& wks, BINIMP& binimp)
{
	switch( binimp.iMode )
	{
	case ASCIMP_MODE_REPLACE_DATA:
		s_nStartCol = 0;
		s_nStartRow = 0;
		break;
	case ASCIMP_MODE_APPEND_COLS:
		/// SY 10/13/2004 v8.0147 IMPORT_WIZARD_CLEANUP
		///s_nStartCol = FindEmptyColumn(wks);
		s_nStartCol = wks_find_empty_column(wks);
		/// end IMPORT_WIZARD_CLEANUP
		s_nStartRow = 0;
		break;
	case ASCIMP_MODE_APPEND_ROWS:
		s_nStartCol = 0;
		Dataset dd(wks, 0);
		if( dd.IsValid() )
			s_nStartRow = dd.GetSize();
		else
			s_nStartRow = 0;
		break;
	}
}

static int get_column_count(BINIMP &binimp)
{
	int iCount = 0;
	for( int i = 0; i < binimp.vParamCount.GetSize(); i++ )
		iCount += binimp.vParamCount[i];
	return iCount;
}

static LONG get_binimp_row_size(BINIMP& binimp)
{
	LONG lSize = 0;
	for( int i = 0; i < binimp.vParamType.GetSize(); i++ )
		lSize += (binimp.vParamSize[i] * binimp.vParamCount[i]);
	return lSize;
}

static void reverse_bytes(BYTE *pbyData, int iSize)
{
	BYTE by;

	for( int i = 0; i < iSize/2; i++ )
	{
		by = *(pbyData + i);
		*(pbyData + i) = *(pbyData + iSize - i - 1);
		*(pbyData + iSize - i - 1) = by;
	}
}

static int set_worksheet_cell(Worksheet &wks, int iRow, int iCol, BYTE *pbyData, int iDataType, int iDataSize, bool bBigEndian)
{
	if( IS_TYPE_REAL(iDataType) )
	{
		if( bBigEndian )
			reverse_bytes(pbyData, iDataSize);
		
		if( sizeof(float) == iDataSize )
		{
			float fData = *((float*)pbyData);
			wks.SetCell(iRow, iCol, fData);
		}
		else if( sizeof(double) == iDataSize )
		{
			double dData = *((double*)pbyData);
			wks.SetCell(iRow, iCol, dData);
		}
	}
	else if( IS_TYPE_INT(iDataType) )
	{
		if( bBigEndian )
			reverse_bytes(pbyData, iDataSize);

		int iData = 0;
		switch( iDataSize )
		{
		case sizeof(char):
			iData = *((char*)pbyData);
			break;
		case sizeof(short):
			iData = *((short*)pbyData);
			break;
		case sizeof(long):
			iData = *((long*)pbyData);
			break;
		}
		
		wks.SetCell(iRow, iCol, iData);
	}
	else if( IS_TYPE_UINT(iDataType) )
	{
		if( bBigEndian )
			reverse_bytes(pbyData, iDataSize);

		DWORD dwData = 0;
		switch( iDataSize )
		{
		case sizeof(char):
			dwData = *((BYTE*)pbyData);
			break;
		case sizeof(short):
			dwData = *((WORD*)pbyData);
			break;
		case sizeof(long):
			dwData = *((DWORD*)pbyData);
			break;
		}
		
		wks.SetCell(iRow, iCol, dwData);
	}
	else if( IS_TYPE_STRING(iDataType) )
	{
		string strData;
		LPSTR lpstr = strData.GetBuffer(iDataSize + 1);
		if( lpstr )
		{
			memcpy(lpstr, pbyData, iDataSize);
			*(lpstr + iDataSize) = 0; // be sure it is null terminated
			strData.ReleaseBuffer();
			wks.SetCell(iRow, iCol, strData);
		}
	}
	return 0;
}

static int row_buffer_to_wks(Worksheet& wks, int iWksRow, BYTE *pbyRowBuffer, BINIMP& binimp)
{
	int iParamCount = 0;

	if( binimp.iPartial )
	{
		// Skip bytes for unwanted columns
		pbyRowBuffer += s_lBytesBeforePartial;
		iParamCount = s_iFirstParamCount;
	}

	int iWksCol = s_nStartCol;
	
	for( int iParamVecElement = s_iFirstParamVecElement; iParamVecElement < binimp.vParamType.GetSize(); iParamVecElement++ )
	{
		while( iParamCount < binimp.vParamCount[iParamVecElement] )
		{
			// Set worksheet cell
			set_worksheet_cell(wks, iWksRow, iWksCol, pbyRowBuffer, binimp.vParamType[iParamVecElement], binimp.vParamSize[iParamVecElement], binimp.iBigEndian);

			// Advance pointer to data for next paramter.
			pbyRowBuffer += binimp.vParamSize[iParamVecElement];
			
			// If we have set the cell of the last column.
			if( iParamVecElement == s_iLastParamVecElement && iParamCount == s_iLastParamCount )
				return 0; // we are done
			
			// Next parameter in vector element.
			iParamCount++;

			// Next wks column.
			iWksCol++;
		}
		iParamCount = 0;
	}
	
	return 0;
}
/// Hong 01/17/07 ADD_SPARKLINE_TO_IMPORT_WIZARD
/// Hong 8/07/06 NO_NEED_M_STRESULT
/// SY 09/08/2004 v8.0131 QA70-6472 IMPORT_INFO_STORAGE_CLEANUP
///static int import_binary_file(Worksheet& wks, LPCSTR lpcstrFile, BINIMP& binimp)
//static int import_binary_file(Worksheet& wks, LPCSTR lpcstrFile, BINIMP& binimp, ASCIMPRESULT* pResult)
//static int import_binary_file(Worksheet& wks, LPCSTR lpcstrFile, BINIMP& binimp)
///---Sim 08-06-2007 SUPPORT_SMART_SPARKLINE
//static int import_binary_file(Worksheet& wks, LPCSTR lpcstrFile, BINIMP& binimp, bool bAddSparkLines)
/// Hong 11/02/07 QA80-10541 FIX_BINARY_FAIL_IMPORT_TO_GRAPH
//static int import_binary_file(Worksheet& wks, LPCSTR lpcstrFile, BINIMP& binimp, int nSparklines)
static int import_binary_file(Worksheet& wks, LPCSTR lpcstrFile, BINIMP& binimp, int nSparklines, DataRange& drImported)
/// end FIX_BINARY_FAIL_IMPORT_TO_GRAPH
///---END SUPPORT_SMART_SPARKLINE
/// end IMPORT_INFO_STORAGE_CLEANUP
/// end NO_NEED_M_STRESULT
/// end ADD_SPARKLINE_TO_IMPORT_WIZARD
{
	init_globals(binimp);
	init_wks_starting_col_and_row(wks, binimp); 
	
	int iColCount = get_column_count(binimp); /// SY 09/08/2004 v8.0131 QA70-6472 IMPORT_INFO_STORAGE_CLEANUP
	
	if( binimp.iPartial )
	{
		if( (binimp.iPartialC1 > binimp.iPartialC2 && binimp.iPartialC2 != -1) ||
			/// SY 09/08/2004 v8.0131 QA70-6472 IMPORT_INFO_STORAGE_CLEANUP
			///(binimp.iPartialC1 >= get_column_count(binimp)) ||
			(binimp.iPartialC1 >= iColCount) ||
			/// end IMPORT_INFO_STORAGE_CLEANUP
			(binimp.iPartialR1 > binimp.iPartialR2 && binimp.iPartialR2 != -1) )
		{
			return 1; // invalid range specified
		}
		
		///---Sim 01-24-2007 FIX_COL_COUNT_WHEN_PARTIAL_COL
		if ( -1 == binimp.iPartialC2 ) // to the end of column
		{
			iColCount -= binimp.iPartialC1;
		}
		else 
		{
			iColCount = binimp.iPartialC2 - binimp.iPartialC1 + 1;
		}
		///---END FIX_COL_COUNT_WHEN_PARTIAL_COL
	}
	file fil;
	if( fil.Open(lpcstrFile, file::modeRead | file::typeBinary) )
	{
		// Get the number of bytes in each row of data.
		s_lRowSizeInBytes = get_binimp_row_size(binimp);
		if( s_lRowSizeInBytes )
		{
			// Allocate a buffer to hold a row of data
			s_pbyRowBuffer = (BYTE*)malloc(s_lRowSizeInBytes);
			if( s_pbyRowBuffer )
			{
				// Skip header bytes.
				fil.Seek(binimp.iHeaderBytes, file::begin);

				int iDataRow = 0; // 0=first row of data

				// If partial import then skip unwanted rows.
				if( binimp.iPartial && binimp.iPartialR1 > 0 )
				{
					fil.Seek(binimp.iPartialR1 * s_lRowSizeInBytes, file::current);
					iDataRow = binimp.iPartialR1;
				}
				
				// Set starting wks row.
				int iWksRow = s_nStartRow;
				int nC1 = s_nStartCol; //Hong 01/17/07 ADD_SPARKLINE_TO_IMPORT_WIZARD
				int iSkipRows = 0; /// EJP 07-23-2003 v7.0631 QA70-4575 ADD_SKIPROWS_TO_BINIMP
				int iReadRows = binimp.iReadRows; /// EJP 09-12-2003 v7.5693 QA70-5073 ADD_READROWS_TO_BINIMP

				// Read data rows.
				while( fil.Read(s_pbyRowBuffer, s_lRowSizeInBytes) == s_lRowSizeInBytes )
				{
					/// EJP 07-23-2003 v7.0631 QA70-4575 ADD_SKIPROWS_TO_BINIMP
					if( iSkipRows )
					{
						iSkipRows--;
						/// EJP 09-12-2003 v7.5693 ADD_READROWS_TO_BINIMP
						if( 0 == iSkipRows )
							iReadRows = binimp.iReadRows;
						/// end ADD_READROWS_TO_BINIMP
					}
					else // iSkipRows == 0
					{
					/// end ADD_SKIPROWS_TO_BINIMP
						// Put row into worksheet.
						row_buffer_to_wks(wks, iWksRow, s_pbyRowBuffer, binimp);
						iWksRow++; // Next worksheet row.
					/// EJP 07-23-2003 v7.0631 QA70-4575 ADD_SKIPROWS_TO_BINIMP

						/// EJP 09-12-2003 v7.5693 QA70-5073 ADD_READROWS_TO_BINIMP
						///iSkipRows = binimp.iSkipRows; // reset iSkipRows
						if( binimp.iSkipRows )
						{
							iReadRows--;
							if( 0 == iReadRows )
								iSkipRows = binimp.iSkipRows; // reset iSkipRows
						}
						/// end ADD_READROWS_TO_BINIMP
					}
					/// end ADD_SKIPROWS_TO_BINIMP
					
					// If partial import and we just did the last row...
					if( binimp.iPartial && iDataRow == binimp.iPartialR2 )
						break; // Partial import is done.
					
					iDataRow++; // Next row of data
				}
		
				free(s_pbyRowBuffer);
				
				///---Sim 02-24-2007 ADD_FILE_NAME_TO_COL_USER_INFO_TREE
				// set column user info tree
				for (int nCol = nC1; nCol < nC1 + iColCount; nCol++)
				{
					Column cc(wks, nCol);
					string strColumnInfo = "ColumnInfo";
					Tree trColumnInfo;
					trColumnInfo.AddTextNode(lpcstrFile, "ImportFile");
					trColumnInfo.Enable = ENABLE_READ_ONLY;
					trColumnInfo.SetAttribute(STR_ATTRIB_BRANCH, GETNBRANCH_OPEN);
					set_user_info(cc, strColumnInfo, trColumnInfo);
				}
				///---END ADD_FILE_NAME_TO_COL_USER_INFO_TREE
				
				/// Hong 11/02/07 QA80-10541 FIX_BINARY_FAIL_IMPORT_TO_GRAPH
				DataRange dr;
				dr.Add(wks, nC1, STR_RANGE_STR, nC1 + iColCount - 1);
				drImported = dr;
				/// end FIX_BINARY_FAIL_IMPORT_TO_GRAPH
				///---Sim 08-06-2007 SUPPORT_SMART_SPARKLINE
				/$
				///Hong 01/17/07 ADD_SPARKLINE_TO_IMPORT_WIZARD
				if( bAddSparkLines )
				{
					XFBase xf("sparklines");
					if( !xf )
						return CER_FAILED_LOAD_SPK_LINE_XF;
					xf.SetArg("sel", 0);
					xf.SetArg("c1", nC1+1); // XF sparklines use LT index
					xf.SetArg("c2", nC1 + iColCount);
					/// end FIX_SPARK_LINE_DISAPPEAR
					xf.SetArg("wks", wks);
					if ( !xf.Evaluate() )
						return CER_SPK_LINE_RUN_ERROR;
				}
				$/
				if ( !update_sparkline(nSparklines, wks, nC1, nC1 + iColCount - 1) )
					return CER_SPK_LINE_RUN_ERROR;
				///---END SUPPORT_SMART_SPARKLINE
				/// end ADD_SPARKLINE_TO_IMPORT_WIZARD
				///Hong 8/07/06 NO_NEED_M_STRESULT
				///// SY 09/08/2004 v8.0131 QA70-6472 IMPORT_INFO_STORAGE_CLEANUP
				//if( pResult )
				//{
					//pResult->nR1 = s_nStartRow;
					//pResult->nR2 = s_nStartRow + iDataRow - 1;
					//pResult->nC1 = s_nStartCol;
					//pResult->nC2 = s_nStartCol + iColCount - 1;
				//}
				///// end IMPORT_INFO_STORAGE_CLEANUP
				///end NO_NEED_M_STRESULT
			}
		}
		fil.Close();
	}

	return 0;
}
*/
static void convert_binimp(const BINIMP& binimp, CBINIMP& cbinimp)
{
	// hard code to convert OC struct to VC struct
	// Need US dev to see this problem
	//Tree temp;
	//temp = binimp;
	//cbinimp = temp;
	cbinimp.iHeaderBytes		= binimp.iHeaderBytes;
	cbinimp.iAutoColTypes		= binimp.iAutoColTypes;
	cbinimp.iNumColumns			= binimp.iNumColumns;
	cbinimp.iPartial			= binimp.iPartial;
	cbinimp.iPartialC1			= binimp.iPartialC1;
	cbinimp.iPartialC2			= binimp.iPartialC2;
	cbinimp.iPartialR1			= binimp.iPartialR1;
	cbinimp.iPartialR2			= binimp.iPartialR2;
	cbinimp.iRenameWks			= binimp.iRenameWks;
	cbinimp.iBigEndian			= binimp.iBigEndian;
	cbinimp.iApplyRange			= binimp.iApplyRange;
	cbinimp.iMode				= binimp.iMode;
	cbinimp.iSkipRows			= binimp.iSkipRows;
	cbinimp.iReadRows			= binimp.iReadRows;
	cbinimp.flags				= binimp.flags;
	// convert vector<type> to type*
	cbinimp.pParamType = binimp.vParamType;
	cbinimp.pParamSize = binimp.vParamSize;
	cbinimp.pParamCount = binimp.vParamCount;
	cbinimp.nNumParams = binimp.vParamType.GetSize();
}

static bool import_binary_file(Worksheet& wks, LPCSTR lpcstrFile, BINIMP& binimp, TreeNode& trInfo)
{
	if ( !wks )
		return false;
	string strRange;
	wks.GetRangeString(strRange);
	
	CBINIMP cbinimp; // for VC
	convert_binimp(binimp, cbinimp);
	
	return okoc_binary_import(lpcstrFile, strRange, &cbinimp, &trInfo);
}
///---END QA80-12203 MOVE_BIN_IMPORT_TO_VC
	
//class OC_REGISTERED IWBINARY : public IWBase
class OC_REGISTERED IWBINARY : public ImpWiz//Hong 8/07/06 MOVE_TO_IMPWIZ_H
{

public:
	IWBINARY():ImpWiz() {m_iFilterType = FILTER_TYPE_BINARY} /// AW 08/03/06 MORE_ON_IW_IMPORT
	~IWBINARY() {}
protected:
	/// AW 08/06/06 CHECK_IW_FILTER
	/*
	virtual int PrepareWksColsForImport(Layer &lyTarget, TreeNode &trFilter)
	{
		//need to implement
	
		int n, nCols = 0;
		string str;
	
		/// EJP 2006-03-24 v8.0380 PRESERVE_ACTIVE_PAGE_AND_LAYER
		///Worksheet wks(pgTarget.GetName());
		Worksheet wks(lyTarget);
		/// end PRESERVE_ACTIVE_PAGE_AND_LAYER
		if( !wks )
			return IMPERR_PREPARE_WKS; // error, no worksheet
		BINIMP binimp;
		fuGetBINIMP(trFilter, binimp);
		for( n = 0; n < binimp.vParamCount.GetSize(); n++ )
			nCols += binimp.vParamCount[n];
		if( nCols != binimp.iNumColumns )
		{
			binimp.iNumColumns = nCols;
			printf("BINIMP.iNumColumns updated\n");
		}
		///////////////////////////////////////////////////
		// The following will adjust nCols based on the
		// partial import settings.
		///////////////////////////////////////////////////
		int nFirstSourceCol = 0;
		if( trFilter.Common.Partial.nVal )
		{
			nFirstSourceCol = trFilter.Common.PartialC1.nVal;
			
			if( nFirstSourceCol > trFilter.Common.PartialC2.nVal )
				nCols -= nFirstSourceCol;
			else
				nCols = trFilter.Common.PartialC2.nVal - nFirstSourceCol + 1;
		}
		
		///////////////////////////////////////////////////
		// The following (switch on import mode) will
		// adjust nCols based on the import mode.
		///////////////////////////////////////////////////
		int nFirstTargetCol = 0;
		int nNumExistingCols = wks.GetNumCols();
		int nNewCols = 0;
		switch( fuGetImportMode(trFilter) )
		{
		case ASCIMP_MODE_REPLACE_DATA:
		case ASCIMP_MODE_APPEND_ROWS:
		case ASCIMP_MODE_NEW_BOOKS:
		case ASCIMP_MODE_NEW_SHEETS:
		case ASCIMP_MODE_AUTO:
			if( nCols > nNumExistingCols )
				nNewCols = nCols - nNumExistingCols;
			break;
		case ASCIMP_MODE_APPEND_COLS:
			/// SY 10/13/2004 v8.0147 IMPORT_WIZARD_CLEANUP
			///nFirstTargetCol = FindEmptyColumn(wks);
			nFirstTargetCol = wks_find_empty_column(wks);
			/// end IMPORT_WIZARD_CLEANUP
			 
			if( nFirstTargetCol >= 0 )
			{
				nNewCols = nCols - (nNumExistingCols - nFirstTargetCol);
			}
			else // no empty columns
			{
				nFirstTargetCol = nNumExistingCols;
				nNewCols = nCols;
			}
			break;
		}
		/// EJP 08-29-2003 v7.5680 IMPROVE_IMPORT_SPEED_OF_MANY_COLS
		///for( n = nNumExistingCols; n < nCols; n++ )
		///wks.AddCol();
		if( nNewCols > 0 )
		{
			/// EJP 2006-03-24 v8.0380 PRESERVE_ACTIVE_PAGE_AND_LAYER
			Page pgTarget;
			lyTarget.GetParent(pgTarget);
			/// end PRESERVE_ACTIVE_PAGE_AND_LAYER
			str.Format("work -a %d", nNewCols);
			pgTarget.LT_execute(str);
		}
		/// end IMPROVE_IMPORT_SPEED_OF_MANY_COLS
	
		///////////////////////////////////////////////////////
		// The follwoing will construct the designation and
		// format strings.
		///////////////////////////////////////////////////////
		bool bRepetitive = fuGetRepetitive(trFilter);
	
		// Start with the designations and formats in the filter.
		string strColDesig = fuGetDesignations(trFilter);
		string strColFormat = fuGetFormats(trFilter);
	
		// If a partial import then remove the skipped columns	
		//if( nFirstSourceCol )
		//{
			//strColDesig.Delete(0, nFirstSourceCol);
			//strColFormat.Delete(0, nFirstSourceCol);
		//}
		//
		if( nFirstTargetCol ) // if not importing into the first column
		{
			string strExistColDesig = wks.GetColDesignations();
			strExistColDesig.Delete(nFirstTargetCol, strExistColDesig.GetLength() - nFirstTargetCol);
			strColDesig.Insert(0, strExistColDesig);
			
			string strExistColFormat = wks.GetColFormats();
			strExistColFormat.Delete(nFirstTargetCol, strExistColFormat.GetLength() - nFirstTargetCol);
			strColFormat.Insert(0, strExistColFormat);
		}
		/// end FIX_COL_DESIGNATIONS_AND_FORMATS_SET
	
		/// EJP 08-12-2003 v7.0656 QA70-4808 IMPORT_INTO_LOCKED_COL_WARNING
		if( wks.IsWriteProtected(nFirstTargetCol, nFirstTargetCol + nCols) )
		{
			if( IDNO == MessageBox(GetWindow(),
				_L("The data's target window has a locked column.\nDo you want to continue import?"),
				_L("File Import"), MB_YESNO) )
			{
				return IMPERR_CANCEL_ON_LOCKED_COL;
			}
		}
		/// end IMPORT_INTO_LOCKED_COL_WARNING
		
		/// EJP 09-15-2003 v7.5695 QA70-5135.19 AVOID_UNWANTED_REPEATING_OF_LAST_COL_DESIG_AND_FORMAT
		// When the col designation and format strings have less cols than the wks
		// we need to append the current existing settings to avoid having our
		// last setting repeating and overwriting the existing settings.
		/// SY 06-04-2004 v7.5882 QA70-5417.39 AVOID_UNWANTED_REPEATING_OF_LAST_COL_DESIG_AND_FORMAT
		///	if( strColDesig.GetLength() < wks.GetNumCols() && !bRepetitive )
		///	{
		///		string strTmp = wks.GetColFormats();
		///		strTmp.Delete(0, strColDesig.GetLength());
		///		strColFormat += strTmp;
		///		
		///		strTmp = wks.GetColDesignations();
		///		strTmp.Delete(0, strColDesig.GetLength());
		///		strColDesig += strTmp;
		///	}
		///	/// end AVOID_UNWANTED_REPEATING_OF_LAST_COL_DESIG_AND_FORMAT
		if( strColDesig.GetLength() < wks.GetNumCols() && !bRepetitive )
		{
			string strTmp = wks.GetColFormats();
			GetColumnSetting(strTmp, strColFormat, nFirstTargetCol, nCols, bRepetitive);
			strColFormat = strTmp;
			
			strTmp = wks.GetColDesignations();
			GetColumnSetting(strTmp, strColDesig, nFirstTargetCol, nCols, bRepetitive);
			strColDesig = strTmp;
		}
		/// end AVOID_UNWANTED_REPEATING_OF_LAST_COL_DESIG_AND_FORMAT
		
		if( !strColDesig.IsEmpty() )
			wks.SetColDesignations(strColDesig, bRepetitive);
		if( !strColFormat.IsEmpty() )
		{
			wks.SetColFormats(strColFormat, bRepetitive);
			///// EJP 2005-08-03 v8.0281 QA70-7886 ADD_CUSTOM_FORMAT_TO_OBJECT_LEVEL
			//string strCustomFormat;
			//if( fuGetCustomDate(trFilter, strCustomFormat) )
			//{
				//Column col;
				//int nIndex = strColFormat.Find('3', 0);
				//while( nIndex >= 0 )
				//{
					//col = wks.Columns(nIndex);
					//if( col )
					//{
						//Tree tr;
						//if( info_get_section(col, tr, "system.display") )
						//{
							//tr.CustomFormat.strVal = strCustomFormat;
							//info_set_section(col, tr, "system.display");
						//}
						//col.SetSubFormat(LDF_OBJ_CUSTOM);
					//}
					//nIndex = strColFormat.Find('3', nIndex + 1);
				//}
				//
			//}
			///// end ADD_CUSTOM_FORMAT_TO_OBJECT_LEVEL
		}
	
		return IMPERR_NONE;
	}
	*/
	virtual int GetColNumberFromFilter(TreeNode &trFilter) 
	{
		int nCols;
		BINIMP binimp;
		fuGetBINIMP(trFilter, binimp);
		for( int nn = 0; nn < binimp.vParamCount.GetSize(); nn++ )
			nCols += binimp.vParamCount[nn];
		if( nCols != binimp.iNumColumns )
		{
			binimp.iNumColumns = nCols;
			printf("BINIMP.iNumColumns updated\n");
		}
		return nCols;
	}
	/// END CHECK_IW_FILTER
	
	virtual int ImportFile(Layer& lyTarget, int nFile, string& strFileName, TreeNode& trFilter, TreeNode& tnInfo, int nImportMode)
	{
		Worksheet wks(lyTarget);
		if( !wks )
			return IMPERR_NO_TARGET_PAGE;
		
		BINIMP binimp;
		fuGetBINIMP(trFilter, binimp);
		
		if( strFileName.IsEmpty() || &binimp == NULL )
		{
			printf("Invalid object in arguments\n");
			return BIN_INVALID_ARGUMENT;
		}
		
		if( binimp.vParamType.GetSize() == 0 )
			return BIN_INVALID_ARGUMENT;		
		///---Sim 09-18-2008 QA80-12203 MOVE_BIN_IMPORT_TO_VC
		/*
		///---Sim 08-06-2007 SUPPORT_SMART_SPARKLINE
		/$
		/// Hong 01/17/07 ADD_SPARKLINE_TO_IMPORT_WIZARD
		bool bAddSparklines = fuGetSparkLine(trFilter); 
		//return import_binary_file(wks, strFileName, binimp, &m_stResult);
		return import_binary_file(wks, strFileName, binimp, bAddSparklines);//Hong 8/07/06 NO_NEED_M_STRESULT
		/// end ADD_SPARKLINE_TO_IMPORT_WIZARD
		$/
		int nSparklines = fuGetSparkLine(trFilter);
		/// Hong 11/02/07 QA80-10541 FIX_BINARY_FAIL_IMPORT_TO_GRAPH
		//return import_binary_file(wks, strFileName, binimp, nSparklines);
		///---Sim 02-27-2008 QA80-11163 IMPORT_RENAME_BOTH_BOOK_LONG_AND_SHORT_NAME
		//return import_binary_file(wks, strFileName, binimp, nSparklines, m_orng);
		int nRet = import_binary_file(wks, strFileName, binimp, nSparklines, m_orng);
		if ( 0 == nRet )
		{
			TreeNode trDataRange = tree_check_get_node(tnInfo, "DataRange");
			getRangeInfo(trDataRange, m_orng);
		}
		return nRet;
		///---END QA80-11163 IMPORT_RENAME_BOTH_BOOK_LONG_AND_SHORT_NAME
		/// end FIX_BINARY_FAIL_IMPORT_TO_GRAPH
		///---END SUPPORT_SMART_SPARKLINE
		*/
		if ( !import_binary_file(wks, strFileName, binimp, tnInfo) )
			return IMPERR_IMPORT_FUNC_ERR;
		
		TreeNode trDataRange = tree_get_node_by_tagname(tnInfo, "DataRange", true);
		m_orng = get_and_check_range(trDataRange);
		for (int nIndex = 0; nIndex < m_orng.GetNumRanges(); nIndex++ )
		{
			int nC1, nC2;
			m_orng.GetRange(wks, nC1, nC2, nIndex);
			// set column user info tree
			for (int nCol = nC1; nCol <= nC2; nCol++)
			{
				Column cc(wks, nCol);
				///---Sim 02-04-2010 QA81-15063 MOVE_IMP_FILE_INFO_OUT_FROM_COL_USER_INFO_TREE
				//string strColumnInfo = "ColumnInfo";
				//Tree trColumnInfo;
				//trColumnInfo.AddTextNode(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, 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, 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
			}
		}
		int nSparklines = fuGetSparkLine(trFilter);
		for (nIndex = 0; nIndex < m_orng.GetNumRanges(); nIndex++ )
		{
			int nC1, nC2;
			m_orng.GetRange(wks, nC1, nC2, nIndex);
			if ( !update_sparkline(nSparklines, wks, nC1, nC2) )
				return CER_SPK_LINE_RUN_ERROR;
		}
		
		return IMPERR_NONE; // success
		///---END QA80-12203 MOVE_BIN_IMPORT_TO_VC
	}
	
	/// AW 08/06/06 CHECK_IW_FILTER
	/*
	virtual int GenerateImpInfo(string& strFileName, Layer& lyTarget, TreeNode& trFilter, TreeNode& trImpInfo)
	{
		Page pgTarget;
		if (lyTarget)
			lyTarget.GetParent(pgTarget);
		
		Tree trFile;
		int iFilterType = fuGetType(trFilter);
		impinfo_GetLastFileNode(pgTarget, trFile);
		impinfo_FileInfoToFileNode(trFile, strFileName, iFilterType);
		
		TreeNode trNode = trImpInfo.FirstNode;
		while( trNode )
		{
			trFile.AddNode(trNode, true);
			trNode = trNode.NextNode;
		}

		impinfo_SetLastFileNode(pgTarget, trFile);
		//trImpInfo = trFile.Clone(); // this code seem couldn't copy really. maybe memory junk come up.

		return 0; 		
	}
	*/
	/// END CHECK_IW_FILTER
	///Hong NO_NEED_M_STRESULT
//protected:
	//ASCIMPRESULT m_stResult;   /// AW ????
	///end NO_NEED_M_STRESULT
};
