/*------------------------------------------------------------------------------*
 * File Name:LT_Wks.c		 													*
 * Creation: CPY July 9 2003													*
 * Purpose: OriginC Source C file												*
 * Copyright (c) Originlab Corp.	2003										*
 * All Rights Reserved															*
 * 																				*
 * Modification Log:															*
 * EJP 07-10-2003 v7.0622 QA70-4745 SET_PAGE_IMPORT_INFO_ON_123_ASC_IMPORT		*
 * EJP 08-28-2003 v7.5678 QA70-4818 UPDATE_ASCIMP_FROM_FILTER_SAVED_TO_WKS		*
 * CPY 02-07-2004 v7.5818 QA70-5894 ALLOW_VIEWING_ALL_IMPORTED_IMAGES			*
 * SY 09-14-2004 v8.0115 QA70-6472 IMPORT_INFO_STORAGE_CLEANUP					* 
 * Danice 10/22/04 v8.0152 QA70-6891 RECORD_CHANGE_FOR_CODE_REUSE				*
 * SY 05/17/2005 QA70-7650 v8.0235 MORE_IMPORT_MODE_IN_OLD_ASCII_IMPORT_DLG		*
 * EJP 2005-08-02 v8.0280 MOVE_IMVIEW_TO_XFUNCTION								*
 * EJP 2006-02-17 v8.0366 MOVE_IMPORT_FILE_INFO_FROM_OC_TO_VC					*
 *	ML 8/10/2006 QA70-8901 SAMPLE_RATE_LABEL_TYPE								*
 *	ML 9/15/2006 QA70-8950 SPARKLINE_LABEL										*
 * Hong 11/22/06 USE_BETTER_NAME_FOR_SAMPLE_RATE								*
 * SY 2007-04-11 QA70-9592 8.0599 RESULT_SHEET_CONTEXT_MENU						*
 * Jasmine 07/25/07 WKS_HEADER_LABEL_MODIFICATION								*
 * Folger 07/25/07 FIX_BUGS_IN_SET_VIEW_MODE_OF_WKBOOK_ORGANIZER				*
 * Folger 07/25/07 FIX_BUGS_IN_GET_VIEW_MODE_OF_WKBOOK_ORGANIZER				*
 *	RVD 1/21/2008 qa70-10950 v8.0790 TRANSPOSE_WKS_TABLE						*
 *	RVD 2/22/2008 QA70-11158 v8.0811 DRAW_GRID_PAGE_BOUNDS						*
 *	Hong 12/19/08 QA80-12736 FIX_IMPORT_ASCII_FAIL_IMPORT_TO_GRAPH				*
 *------------------------------------------------------------------------------*/
 
#include <origin.h> // main Origin C header that is precompiled and already include most headers

#pragma labtalk(0) //--- CPY 7/26/05 hide all functions in this file from LT access, as XF should be used instead

#ifndef _RANGE_EX_H
#pragma message("including rangeEx.h separately")
#include <RangeEx.h>
#endif //_RANGE_EX_H

#include <import_image.h> //CPY 02-07-2004 v7.5818 QA70-5894 ALLOW_VIEWING_ALL_IMPORTED_IMAGES
//TD 10-22-03 No longer needs this file
//#include "filter_utils.h" /// EJP 08-28-2003 v7.5678 QA70-4818 UPDATE_ASCIMP_FROM_FILTER_SAVED_TO_WKS
#include "OriginEvents.h"
#include <GetNBox.h>

#define SHOW_ERR(_str)	out_str(_str)  

/**
	Get header lines stored in worksheet page during ASCII import
	Parameters:
		None
	Returns:
		string with header contents
	Example:
		// get string into LabTalk variable header$
		// note the $ suffix at end of command - is needed to place value of
		// string returned by function into the LT var
		header$=pg_get_header()$ 		
*/
string pg_get_header()
{
	string strHeader;
	WorksheetPage wpg = Project.Pages();
	if(wpg)
	{
		vector<byte> vb;
		if(wpg.GetMemory("ImportHeader", vb))
		{
			strHeader.SetBytes(vb);
		}
		else
			SHOW_ERR("No header available in worksheet");			
	}
	else
		SHOW_ERR("Active window must be a worksheet");
	return strHeader;
}


/**
	Dump header lines stored in worksheet page during ASCII import
	Parameters:
		nOutput = where to dump the header, 1 for script window, 0 for new notes window
	Returns:
		None
	Example:
		pg_dump_header 1; 		
*/
void pg_dump_header(int nOutput = 0)
{
	string strHeader;
	strHeader = pg_get_header();
	if(0 != strHeader.GetLength())
	{
		if(0 == nOutput)
		{
			Note nWnd;
			nWnd.Create();
			nWnd.Text = strHeader;
		}
		else
			strHeader.Write(WRITE_SCRIPT_WINDOW);
	}
}


/**
	Get string value of specified infor storage variable
	Parameters:
		strVarName = Name of info varible in page.info.user.variables section
	Returns:
		string value of specified variable
	Example:
		// get string into LabTalk variable var$
		// note the $ suffix at end of command - is needed to place value of
		// string returned by function into the LT var
		var$=pg_get_info_str("L1V1")$ 		
*/
string pg_get_info_str(string strVarName)
{
	string strVarValue;
	WorksheetPage wpg = Project.Pages();
	if(wpg)
		page_get_info_var_value(wpg, strVarName, strVarValue);
	else
		SHOW_ERR("Page not valid");
	return strVarValue;
}


/**
	Get real value of specified infor storage variable
	Parameters:
		strVarName = Name of info varible in page.info.user.variables section
	Returns:
		double, value of specified variable
	Example:
		// get value of variable into LabTalk variable myval
		myval=pg_get_info_val("L1V1") 		
*/
double pg_get_info_val(string strVarName)
{
	double dVarValue = 0.;	
	WorksheetPage wpg = Project.Pages();
	if(wpg)
		page_get_info_var_value(wpg, strVarName, dVarValue);
	else
		SHOW_ERR("Page not valid");
	return dVarValue;
}


/// EJP 07-10-2003 v7.0622 QA70-4745 SET_PAGE_IMPORT_INFO_ON_123_ASC_IMPORT
void set_binary_import_page_info(string lpcszFile)
{
	Page pgActive = Project.Pages();
	/// EJP 2006-02-17 v8.0366 MOVE_IMPORT_FILE_INFO_FROM_OC_TO_VC
	///set_page_import_info(pgActive, lpcszFile, 1); // 1 = Binary data type
	okutil_SetPageInfo(pgActive.GetName(), lpcszFile, 1); // 1 = Binary data type
	/// end MOVE_IMPORT_FILE_INFO_FROM_OC_TO_VC
}
/// end SET_PAGE_IMPORT_INFO_ON_123_ASC_IMPORT

/// EJP 08-28-2003 v7.5678 QA70-4818 UPDATE_ASCIMP_FROM_FILTER_SAVED_TO_WKS
/**
	Update an active worksheet's ASCII import settings.  A worksheet has internal settings and can also contain an ASCII import filter.
	Call this funtion to copy the settings from one to the other.
	Parameters:
		bUpdateInternal = 0 to update filter from internal settings, non-zero to update internal settings from filter.
	Returns:
		Zero for success or non-zero to indicate update did not occur.
	Example:
		Page pgActive = Project.Pages(); // get active page
		if( fuIsFilterInPage(pgActive, FILTER_TYPE_ASCII) ) // if page contains ASCII import filter
			pg_update_ascimp(1); // update the internal import settings from the import filter

int pg_update_ascimp(int bUpdateInternal)
{
	Page pgActive = Project.Pages();
	if( !pgActive || EXIST_WKS != pgActive.GetType() )
		return 1; // active page is not a wks
	
	Tree trFilter;
	if( !fuLoadFilterFromPage(trFilter, pgActive, FILTER_TYPE_ASCII) )
		return 1; // page does not have an ASCII filter

	Worksheet wks(pgActive.GetName());
	if( !wks )
		return 1; // failed to get reference to wks

	ASCIMP ascimp;
	if( bUpdateInternal ) // update internal settings from filter
	{
		if( !fuGetASCIMP(trFilter, ascimp) )
			return 1; // failed to get ASCIMP from filter
		wks.SetASCIMP(ascimp);
	}
	else // update filter from internal settings
	{
		wks.GetASCIMP(ascimp);
		fuSetASCIMP(trFilter, ascimp);
		fuSaveFilterToPage(trFilter, pgActive);
	}
	return 0; // ascimp updated
}
*/
/// end UPDATE_ASCIMP_FROM_FILTER_SAVED_TO_WKS

//----- CPY 10/26/03 QA70-3096 WKS_IMPORT_CHK_FILE_NAME_ALLOW_USE_ORIGINAL_WKS
static string getWksPageImportFilename(const WorksheetPage& wpg)
{
	string strTemp;
	string strStorageSection("System.IMPORT");
	Tree trSection;
	if( info_get_section(wpg, trSection, strStorageSection) )
	{
		string strVarName("FILEPATH");
		strVarName.MakeUpper();

		TreeNode trnVar;
		trnVar = trSection.GetNode(strVarName);
		if( trnVar )
			return trnVar.strVal;
	}
	return strTemp;
}
// check if if given filename already existed in a worksheet, if found, then make it the active window
// return 0 normally, but return 1 if user cancel
int check_wks_same_file_set_active(string strFilename)
{
	WorksheetPage wpg_this = Project.Pages();
	if(wpg_this)
	{
		string strFile = getWksPageImportFilename(wpg_this);
		if(strFile.CompareNoCase(strFilename) == 0)
			return 0; // nothing to do, already the correct file
	}
	int		nRet;	
	string str;
	string strMsg = _L("This file was already imported into another worksheet, do you want to use that worksheet instead?");
	
	foreach(WorksheetPage wpg in Project.WorksheetPages)
	{
		str = getWksPageImportFilename(wpg);
		if(str.CompareNoCase(strFilename) == 0)
		{
			string strTemp;
			nRet = MessageBox(GetWindow(), strMsg, "Origin Import", MB_YESNOCANCEL);
			if(IDCANCEL == nRet)
				return 1;
			if(IDNO == nRet)
				return 0;
			// Yes
			strTemp.Format("win -a %s", wpg.GetName());
			LT_execute(strTemp);
			return 0;
		}
	}
	return 0;
}
//----- end WKS_IMPORT_CHK_FILE_NAME_ALLOW_USE_ORIGINAL_WKS

#define STR_IM_VIEW "System.ImageView"
#define STR_MATRIX_WINDOW_INVALID "please select active matrix window first"
//--- CPY 02-08-2004 v7.5818 QA70-1352 IMPORT_MULTIPLE_IMAGES_INTO_MATRIX
// image show, set view mode and index
// imshow;// display current setting
#ifdef JUNK /// EJP 2005-08-02 v8.0280 MOVE_IMVIEW_TO_XFUNCTION
int imview(int nFile = 0, int nType = -1, int nOption = 0)
{
	MatrixLayer ml = Project.ActiveLayer();
	if(!ml)
	{
		out_str(STR_MATRIX_WINDOW_INVALID);
		return -1;
	}
	if(nFile <= 0)
	{
		string strStorageSection(STR_IM_VIEW);
		Tree trSection;
		if( info_get_section(ml, trSection, strStorageSection) && trSection.Type.IsValid())
		{
			Tree trtemp;
			int nTotal = matrix_layer_get_objects(ml, trSection.Type.nVal, trtemp);
			printf("Currently set to view %s, index = %d of %d\n", trSection.Type.nVal == IMGV_FILE? "File":"Data", trSection.Current.nVal+1, nTotal);
		}
		out_str("\nusage:");
		out_str("  imview 1 0;// view file1");
		out_str("  imview 2;// view file2, assme previous call already set internal to view file");
		out_str("  imview 1 1;// view data1(image1)");
		out_str("  imview 1 1 2;// view complex data1 imaginary, last arg can be 1,2,3,4 = Re,Im,Ph,Am");
		return 0;			
	}
	ml.SetViewImage(TRUE, nType, nFile-1, nOption);// 0 offset in C code, but 1 offset from LT
	ml.GetPage().Refresh();
	return 0;
}
#endif // JUNK /// EJP 2005-08-02 v8.0280 MOVE_IMVIEW_TO_XFUNCTION

int imlist(int nType = IMGV_FILE)
{
	MatrixLayer ml = Project.ActiveLayer();
	if(!ml)
	{
		out_str(STR_MATRIX_WINDOW_INVALID);
		return -1;
	}
	Tree tr;
	int nTotal = matrix_layer_get_objects(ml, nType, tr);
	out_tree(tr);
	return nTotal;
}
	
bool matrix_layer_get_import_info(MatrixLayer& ml, TreeNode &trn, int index) // = -1
{
	MatrixPage pg = ml.GetPage();
	if(!pg)
		return false;
	
	// Get binary storage
	vector<byte> vb;
	if( !pg.GetMemory(IMPORT_FILE_INFO, vb) )
		return false;
	
	// Fill tree
	if( !trn.XML.SetBytes(vb) )
		return false;

	// If caller wants all then return now
	if( -1 == index )
		return true;
	
	// Get single import info node
	string str;
	str.Format(IMPORT_FILE_ENUM, index);
	trn = trn.GetNode(str);
	if( !trn )
		return false;
	
	return true;
}

//	return  number of objects of specified type	
int matrix_layer_get_objects(MatrixLayer& ml, int nType, TreeNode& tr)
{
	if(IMGV_FILE == nType)
	{
		if(!matrix_layer_get_import_info(ml, tr))
			return 0;
	
		TreeNodeCollection tncFile(tr, IMPORT_FILE_ENUM);
		return tncFile.Count();
	}
	// view data
	
	return ml.MatrixObjects.Count();
}
//---

///Ryan 03-01-2004 v8.0827 QA70_4883 WKS_FIND_DATA
/**#
  			Find data in worksheet by searching for column text string
  		Parameters:
  			wksSrc = source worksheet found from 
			lpcszContent = string to search for column label
			vColIndexIn = column index to be found
			vNumOut = number of matches respectively to vColIndexIn
			bCaseSensitive = TRUE if case sensitive
			bFullMatch = FALSE if only match substring
		Return:
			true if success, 
*/
bool wks_find(const Worksheet& wksSrc, LPCSTR lpcszContent, const vector<int>& vColIndexIn, vector<int>& vNumOut, BOOL bCaseSensitive = TRUE, BOOL bFullMatch = TRUE)
{
	//Check input
	if( !wksSrc.IsValid() )
		return false;
	
	if( 0 == vColIndexIn.GetSize() )
	{
		return false;
	}
	
	string strContent( lpcszContent );
	if( !bFullMatch )
		strContent = "*"+strContent+"*";
	
	//Check data
	int i, j;
	int nMatch;
	vNumOut.SetSize( vColIndexIn.GetSize() );
	for( i = 0; i < vColIndexIn.GetSize(); i++ )
	{
		//creat temp dataset
		Dataset dsTemp( wksSrc, vColIndexIn[i] );
		if( !dsTemp.IsValid() )
		{
			vNumOut.SetSize(0);
			return false;
		}
		
		//get content of dataset
		vector<string> vecStr;
		if( false == dsTemp.GetStringArray( vecStr ))
			return false;
		
		//find data
		nMatch = 0;
		for( j = 0; j < vecStr.GetSize(); j++ )
		{
			if( vecStr[j].Match( strContent, bCaseSensitive ))
				nMatch++;
		}
		vNumOut[i] = nMatch;
	}
	return true;
}

/// SY 09-14-2004 v8.0115 QA70-6472 IMPORT_INFO_STORAGE_CLEANUP
// move from FileImport.c
#if _OC_VER >= 0x0800
void impinfo(int nFile = 0)
{
	Page pg = Project.Pages();
	if( !pg )
	{
		out_str(_L("No active page.\n"));
		return;
	}

	Tree tr;
	if( tree_get_binary_storage(tr, pg, IFI_BINARY_STORAGE_NAME) )
	{
		string str;
		str.Format(IFI_FILE_NODE_ENUM_NAME, nFile);
		TreeNode trn = tr.GetNode(str);
		if( trn )
			out_tree(trn);
		else
			out_tree(tr);
	}
	else
		out_str(_L("ImportFileInfo not found.\n"));
}
#endif // _OC_VER >= 0x0800

/// SY 05/17/2005 QA70-7650 v8.0235 MORE_IMPORT_MODE_IN_OLD_ASCII_IMPORT_DLG
/////////////////////////////////////////////////////////////////////////////
// Move Eric's code from AscImpOptions.c with minor change
//
/// EJP 2005-05-04 v8.0229 QA70-6555 NEW_IMPORT_MODES
int _GetListIndexFromImportMode(int nImportMode)
{
	/* following defines copied from OC_Types.h
	#define ASCIMP_MODE_REPLACE_DATA		0
	#define ASCIMP_MODE_APPEND_COLS			1
	#define ASCIMP_MODE_APPEND_ROWS			2
	#define ASCIMP_MODE_NEW_BOOKS			3
	#define ASCIMP_MODE_NEW_SHEETS			4
	#define ASCIMP_MODE_AUTO				5
	*/
	static int s_nListIndex[] = {
		1,//IW_LIST_IMPMODE_REPLACE,
		4,//IW_LIST_IMPMODE_NEW_COLS,
		5,//IW_LIST_IMPMODE_NEW_ROWS,
		2,//IW_LIST_IMPMODE_NEW_BOOKS,
		3,//IW_LIST_IMPMODE_NEW_SHEETS,
		0//IW_LIST_IMPMODE_AUTO
	};
	if( IS_IMPORT_MODE(nImportMode) )
		return s_nListIndex[nImportMode];
	return 0;//IW_LIST_IMPMODE_AUTO;
}

int _GetImportModeFromListIndex(int nListIndex)
{
	/* following enum copied from import_utils.h
	IW_LIST_IMPMODE_AUTO = 0,
	IW_LIST_IMPMODE_REPLACE,
	IW_LIST_IMPMODE_NEW_BOOKS,
	IW_LIST_IMPMODE_NEW_SHEETS,
	IW_LIST_IMPMODE_NEW_COLS,
	IW_LIST_IMPMODE_NEW_ROWS
	*/
	static int s_nImportMode[] = {
		ASCIMP_MODE_AUTO,
		ASCIMP_MODE_REPLACE_DATA,
		ASCIMP_MODE_NEW_BOOKS,
		ASCIMP_MODE_NEW_SHEETS,
		ASCIMP_MODE_APPEND_COLS,
		ASCIMP_MODE_APPEND_ROWS
	};
	if( 0 <= nListIndex && nListIndex < (sizeof(s_nImportMode) / sizeof(int)) )
		return s_nImportMode[nListIndex];
	return ASCIMP_MODE_AUTO;
}
/// end NEW_IMPORT_MODES
/// end MORE_IMPORT_MODE_IN_OLD_ASCII_IMPORT_DLG


/// TD 10-04-04 QA70-7000 GETNTREE_TO_GENERATE_POPUP_MENUS

#define DISPSTR_SHOW_COL_HEADER   		_L("Column Header")
#define DISPSTR_SHOW_ROW_HEADER   		_L("Row Header")
#define DISPSTR_SHOW_LABEL_CATEGORY   	_L("Row Labels for Column Label Rows")   //CPY 7/25/07 HEADER_ROWS_SHOULD_BE_COL_LABEL_ROWS changed from "Header Rows"
//------CPY 7/25/07 HEADER_ROWS_SHOULD_BE_COL_LABEL_ROWS
// Easwar suggested that not useful to separately control this, so we should just remove it
//#define DISPSTR_SHOW_DATA_ROW_NAMES   	_L("Row Labels for Data Rows")
//-----
#define DISPSTR_SHOW_COLUMN_GRIDS   	_L("Column Grid")
#define DISPSTR_SHOW_ROW_GRIDS   		_L("Row Grid")
///End WKS_HEADER_LABEL_MODIFICATION
/// RVD 1/21/2008 qa70-10950 v8.0790 TRANSPOSE_WKS_TABLE
#define DISPSTR_TRANSPOSE		   		_L("Transpose")
/// end TRANSPOSE_WKS_TABLE
/// RVD 2/22/2008 QA70-11158 v8.0811 DRAW_GRID_PAGE_BOUNDS
#define DISPSTR_DRAW_PAGE_BOUNDS		_L("Page Break Preview Lines") //CPY 4/6/08 changed from "Draw Page Boundaries"
/// end DRAW_GRID_PAGE_BOUNDS

/// ML 12/7/2006 COLUMN_LABELS_STRINGS
//#define DISPSTR_SHOW_LONG_NAMES   		_L("Long Name")
//#define DISPSTR_SHOW_UNITS   			_L("Units")
//#define DISPSTR_SHOW_COMMENT   			_L("Comment")
#define DISPSTR_SHOW_LONG_NAMES   		STR_LONG_NAME_LABEL
#define DISPSTR_SHOW_UNITS   			STR_UNIT_LABEL
#define DISPSTR_SHOW_COMMENT   			STR_COMMENTS_LABEL
/// end COLUMN_LABELS_STRINGS
#define DISPSTR_SHOW_PARAMETERS   		_L("Parameters")
/// ML 12/7/2006 COLUMN_LABELS_STRINGS
///// ML 8/10/2006 QA70-8901 SAMPLE_RATE_LABEL_TYPE
///// Hong 11/22/06 USE_BETTER_NAME_FOR_SAMPLE_RATE
////#define DISPSTR_SHOW_SAMPLE_RATE   		_L("Sample Rate")
//#define DISPSTR_SHOW_SAMPLE_RATE   		_L("Sampling Interval")
///// end USE_BETTER_NAME_FOR_SAMPLE_RATE
///// end SAMPLE_RATE_LABEL_TYPE
///// ML 9/15/2006 QA70-8950 SPARKLINE_LABEL
//#define DISPSTR_SHOW_SPARKLINE   		_L("Sparkline")
///// end SPARKLINE_LABEL
#define DISPSTR_SHOW_SAMPLE_RATE   		STR_SAMPLE_RATE_LABEL
#define DISPSTR_SHOW_SPARKLINE   		STR_SPARKLINE_LABEL 

/// end COLUMN_LABELS_STRINGS

#define	DISPSTR_PRINT	 		  		_L("Print")

//#define GETN_OLDVAL _tmpSubNode.SetAttribute(STR_COMBO_CHANGED,_tmpSubNode.strVal);
//STR_COMBO_CHANGED inn tree_utils.h, probably not available in VC level

/// SY 2007-04-11 QA70-9592 8.0599 RESULT_SHEET_CONTEXT_MENU
///	void WksAccess::GetTree(TreeNode& trProperties, int nSubBranchID)// = 0
void WksAccess::GetTree(TreeNode& trProperties, int nSubBranchID, BOOL bResultSheet)// = 0, FALSE
/// end RESULT_SHEET_CONTEXT_MENU
{
	if(!IsValid() || !trProperties) //need a valid node
		return;
	GETN_USE(trProperties)
	
	GETN_BEGIN_BRANCH(View, _L("View")) GETN_ID_BRANCH(BRN_WKS_VIEW) GETN_OPTION_BRANCH(GETNBRANCH_OPEN)
		if( !bResultSheet )	/// SY 2007-04-11 QA70-9592 8.0599 RESULT_SHEET_CONTEXT_MENU
		{
		GETN_BEGIN_BRANCH(ColLabels, _L("Show Column Labels"))											GETN_ID_BRANCH(BRN_WKS_VIEW_COLUMN_LABELS)		
			GETN_CHECK(LongNames, DISPSTR_SHOW_LONG_NAMES, GetProperty(CMD_WKS_LONG_NAMES)) 			GETN_ID(CMD_WKS_LONG_NAMES) 	GETN_OLDVAL
			GETN_CHECK(Units, DISPSTR_SHOW_UNITS, GetProperty(CMD_WKS_UNITS)) 							GETN_ID(CMD_WKS_UNITS)			GETN_OLDVAL
			GETN_CHECK(Coments, DISPSTR_SHOW_COMMENT, GetProperty(CMD_WKS_COMMENT)) 					GETN_ID(CMD_WKS_COMMENT)		GETN_OLDVAL
			GETN_CHECK(Params, DISPSTR_SHOW_PARAMETERS, GetProperty(CMD_WKS_PARAMETERS)) 				GETN_ID(CMD_WKS_PARAMETERS)		GETN_OLDVAL
			/// ML 8/10/2006 QA70-8901 SAMPLE_RATE_LABEL_TYPE
			GETN_CHECK(SampleRate, DISPSTR_SHOW_SAMPLE_RATE, GetProperty(CMD_WKS_SAMPLE_RATE)) 				GETN_ID(CMD_WKS_SAMPLE_RATE)	GETN_OLDVAL
			/// end SAMPLE_RATE_LABEL_TYPE
			/// ML 9/15/2006 QA70-8950 SPARKLINE_LABEL
			GETN_CHECK(Sparkline, DISPSTR_SHOW_SPARKLINE, GetProperty(CMD_WKS_SPARKLINE)) 				GETN_ID(CMD_WKS_SPARKLINE)	GETN_OLDVAL
			/// end SPARKLINE_LABEL
		GETN_END_BRANCH(ColLabels)
		}
		//GETN_BEGIN_BRANCH(RowLabels, _L("Row Heading Labels"))												GETN_ID_BRANCH(BRN_WKS_VIEW_ROW_LABELS)///Jasmine 07/25/07 WKS_HEADER_LABEL_MODIFICATION
		GETN_BEGIN_BRANCH(RowLabels, _L("Row Labels"))												GETN_ID_BRANCH(BRN_WKS_VIEW_ROW_LABELS)					
			GETN_CHECK(LabelNames, DISPSTR_SHOW_LABEL_CATEGORY, GetProperty(CMD_WKS_LABEL_CATEGORY)) 		GETN_ID(CMD_WKS_LABEL_CATEGORY)	GETN_OLDVAL
			//------CPY 7/25/07 HEADER_ROWS_SHOULD_BE_COL_LABEL_ROWS
			//GETN_CHECK(RowNames, DISPSTR_SHOW_DATA_ROW_NAMES, 	GetProperty(CMD_WKS_DATA_ROW_NAMES))		GETN_ID(CMD_WKS_DATA_ROW_NAMES)	GETN_OLDVAL
			//------
		GETN_END_BRANCH(RowLabels)
		
		//GETN_BEGIN_BRANCH(Headings, _L("Show Headings"))													GETN_ID_BRANCH(BRN_WKS_VIEW_HEADINGS)///Jasmine 07/25/07 WKS_HEADER_LABEL_MODIFICATION
		GETN_BEGIN_BRANCH(Headings, _L("Show Headers"))													GETN_ID_BRANCH(BRN_WKS_VIEW_HEADINGS)			
			GETN_CHECK(ColHeader, DISPSTR_SHOW_COL_HEADER, GetProperty(CMD_WKS_COL_HEADER))					GETN_ID(CMD_WKS_COL_HEADER) 	GETN_OLDVAL
			GETN_CHECK(RowHeader, DISPSTR_SHOW_ROW_HEADER, GetProperty(CMD_WKS_ROW_HEADER)) 				GETN_ID(CMD_WKS_ROW_HEADER)		GETN_OLDVAL
		GETN_END_BRANCH(Headings)
		
		GETN_BEGIN_BRANCH(GridLines, _L("Show Grid Lines"))													GETN_ID_BRANCH(BRN_WKS_VIEW_GRIDLINES)			
			GETN_CHECK(ColGrids, DISPSTR_SHOW_COLUMN_GRIDS, GetProperty(CMD_WKS_COLUMN_GRIDS)) 				GETN_ID(CMD_WKS_COLUMN_GRIDS)	GETN_OLDVAL
			GETN_CHECK(RowGrids, DISPSTR_SHOW_ROW_GRIDS, GetProperty(CMD_WKS_ROW_GRIDS))					GETN_ID(CMD_WKS_ROW_GRIDS)		GETN_OLDVAL 
			/// RVD 2/22/2008 QA70-11158 v8.0811 DRAW_GRID_PAGE_BOUNDS
			GETN_CHECK(DrawBounds, DISPSTR_DRAW_PAGE_BOUNDS, GetProperty(CMD_WKS_DRAW_PAGE_BOUNDS))			GETN_ID(CMD_WKS_DRAW_PAGE_BOUNDS)		GETN_OLDVAL
			/// end DRAW_GRID_PAGE_BOUNDS
		GETN_END_BRANCH(GridLines)

	GETN_END_BRANCH(View)
}



bool WksAccess::SetTree(TreeNode& trProperties) // update wks properties from tree
{
	if(NULL == trProperties || !trProperties)
		return false;
	
	vector<int> vnNewIDs;
	vector<string> vsNewValue;
	int nUpdates = tree_get_values_with_ids(trProperties, vnNewIDs, vsNewValue, true, true);
	///Danice RECORD_CHANGE_FOR_CODE_REUSE
//	RecordChangeByIDs(trProperties, vnNewIDs, vsNewValue);
	///end
	for(int ii = 0; ii < nUpdates; ii++)
	{
		SetProperty(vnNewIDs[ii], vsNewValue[ii]);
	}
	return true;
	
	
}
//--- CPY 10/25/04 WKBOOK_ORGANIZER_SET_VAL_FIX
// not sure why Danice added this
/*
///Danice RECORD_CHANGE_FOR_CODE_REUSE
static void RecordChangeByIDs(TreeNode &tr, vector<int> vnIDs, vector<string> vsValues)
{
	int nSize=vnIDs.GetSize();
	for(int ii=0; ii< nSize; ii++)
	{
		TreeNode trChange = tree_get_node_by_attributes(tr, STR_DATAID_ATTRIB, (string)vnIDs[ii]);
		if(trChange)
			trChange.SetAttribute(STR_CHANGED_ATTRIB, vsValues[ii]);
	}
}
///end
*/
bool GetBool(LPCSTR lpcszVal)
{
	return atoi(lpcszVal);
}
void SetBool(bool bVal, const string& strVal)
{
	strVal.Format("%d", bVal);
}

int  WksAccess::findProperty(int nProperty)
{
	int nRet 		= 0;
	int nCurrProp 	= 1;
	/// ML 9/18/2006 QA70-8950 SPARKLINE_LABEL
	//for(int ii = 0;  ii < MAX_EVENTS && nCurrProp; ii++)
	for(int ii = 0;  ii < MAX_WKS_PROPS && nCurrProp; ii++)
	/// end SPARKLINE_LABEL
	{
		nCurrProp = l_table[ii].m_nProp;
		if(nCurrProp == nProperty)
			return ii;
	}
	
	return -1;
}

bool WksAccess::TogglePropertyValue(int nProperty)
{
  string strVal;
  if(GetProperty(nProperty, strVal))
  {
  	SetBool(!GetBool(strVal), strVal);
  	return SetProperty(nProperty, strVal);
  }
  return false;
}

bool WksAccess::GetProperty(int nProperty)
{
	string strVal;
  	if(GetProperty(nProperty, strVal))
  		return GetBool(strVal);
  	
  	return false;
}
bool WksAccess::SetProperty(int nProperty, LPCSTR lpcszProperty)
{
	int nEntry = findProperty(nProperty);
	if(nEntry < 0)
		return false;
	
	PROPFUNCSET pfnSet = l_table[nEntry].m_pFnSet;
	if(pfnSet)
	{
		pfnSet(lpcszProperty);
		m_bHandled = TRUE;
		return true;
	}
	return false;
}

bool WksAccess::GetProperty(int nProperty, string &strProperty)
{
	int nEntry = findProperty(nProperty);
	if(nEntry < 0)
		return false;
	
	PROPFUNCGET pfnGet = l_table[nEntry].m_pFnGet;
	if(pfnGet)
	{
		pfnGet(strProperty);
		return true;
	}
	return false;
}

BOOL WksAccess::addProperty(int nProp, PROPFUNCGET pFnGet, PROPFUNCSET pFnSet)
{
	/// ML 9/18/2006 QA70-8950 SPARKLINE_LABEL
	//if(l_nCurrent >= MAX_EVENTS)
	//	return FALSE;
	if(l_nCurrent >= MAX_WKS_PROPS)
		return FALSE;
	/// end SPARKLINE_LABEL
	
	l_table[l_nCurrent].m_nProp 	= nProp;
	l_table[l_nCurrent].m_pFnGet 	= pFnGet;
	l_table[l_nCurrent].m_pFnSet 	= pFnSet;
	
	l_nCurrent++;
	
	return TRUE;
}


BOOL WksAccess::IsHandled()
{
	return m_bHandled;
}


WksAccess::WksAccess()
{
	m_bHandled	= FALSE;
	InitializePropertyTable();
}

void WksAccess::InitializePropertyTable()
{
		if(!l_bInit)
		{
			/// ML 9/18/2006 QA70-8950 SPARKLINE_LABEL
			//for(int ii = 0; ii < MAX_EVENTS; ii++)
			for(int ii = 0; ii < MAX_WKS_PROPS; ii++)
			/// end SPARKLINE_LABEL
			{
				l_table[ii].m_nProp = 0;
			}
			
			addProperty(CMD_WKS_LONG_NAMES, IsShownLongNames, ShowHideLongNames);
			addProperty(CMD_WKS_UNITS, IsShownUnits, ShowHideUnits);
			addProperty(CMD_WKS_COMMENT, IsShownComments, ShowHideComments);
			addProperty(CMD_WKS_PARAMETERS, IsShownParameters, ShowHideParameters);
			/// ML 8/10/2006 QA70-8901 SAMPLE_RATE_LABEL_TYPE
			addProperty(CMD_WKS_SAMPLE_RATE, IsShownSampleRate, ShowHideSampleRate);
			/// end SAMPLE_RATE_LABEL_TYPE
			/// ML 9/15/2006 QA70-8950 SPARKLINE_LABEL
			addProperty(CMD_WKS_SPARKLINE, IsShownSparkline, ShowHideSparkline);
			/// end SPARKLINE_LABEL
			addProperty(CMD_WKS_LABEL_CATEGORY, IsShownLabelNames, ShowHideLabelNames);
			addProperty(CMD_WKS_DATA_ROW_NAMES, IsShownRowNames, ShowHideRowNames);
			addProperty(CMD_WKS_COL_HEADER, IsShownColHeaders, ShowHideColHeaders);
			addProperty(CMD_WKS_ROW_HEADER, IsShownRowHeaders, ShowHideRowHeaders);
			addProperty(CMD_WKS_COLUMN_GRIDS, IsShownColGrids, ShowHideColGrids);
			addProperty(CMD_WKS_ROW_GRIDS, IsShownRowGrids, ShowHideRowGrids); 
			addProperty(CMD_WKS_DRAW_PAGE_BOUNDS, IsDrawPageBounds, SetDrawPageBounds);	/// RVD 2/22/2008 QA70-11158 v8.0811 DRAW_GRID_PAGE_BOUNDS
			addProperty(0, NULL, NULL); 
			
			l_bInit = true;
		}
}




bool WksAccess::ShowDialog(TreeNode &tr, 
					LPCSTR LpcszTitle,// = NULL
					LPCSTR  lpcszDescription,// = NULL
					HWND hWndParent// = NULL
					)
{
	if( GetNBox(tr, LpcszTitle, lpcszDescription, NULL, NULL, hWndParent))
	{
		SetTree(tr);
		//return true;
	}
	
	return true;//false; //CPY 10/8/04, return false will open old dialog, we should not show old dialog anymore
	
}

static  bool			WksAccess::l_bInit 	= false;
static  int 			WksAccess::l_nCurrent 	= 0;


//-----
/// end GETNTREE_TO_GENERATE_POPUP_MENUS



///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
/// Hong 05/30/07 v8.0629b BETTER_INTERFACE
static bool	update_view_mode(TreeNode& trn, int nRow, int nCol, TreeNode& trNode, DWORD dwCntrl, int nType, WndContainer& dlg)
{
	if ( dwCntrl & GETNEVENT_VIEW_LIST ) // only deal event check\uncheck, not sure if this bit is really correct
	{
		//-------Folger 07/25/07 FIX_BUGS_IN_SET_VIEW_MODE_OF_WKBOOK_ORGANIZER
		//double dMode = (double)trNode.nVal;
		//LT_set_var("page.cntrl", dMode);
		MatrixPage mp = Project.ActiveLayer().GetPage();
		if (mp)
			mp.SetViewMode(trNode.nVal, false, trn.View.LayerIndex.nVal);
		//-------End FIX_BUGS_IN_SET_VIEW_MODE_OF_WKBOOK_ORGANIZER
	}
	
	return true;
}

static bool	update_show_mode(TreeNode& trn, int nRow, int nCol, TreeNode& trNode, DWORD dwCntrl, int nType, WndContainer& dlg)
{
	// need add this later if oc can access show mode
	return true;
}
/// end BETTER_INTERFACE

//Hong 7/24/06  SHARE_WKBOOK_MATBOOK_ORGANIZER_ADD_MORE
void MatAccess::GetTree(TreeNode& trProperties, int nSubBranchID)// = 0
{
	if(!IsValid() || !trProperties) //need a valid node
		return;
	GETN_USE(trProperties)
	
	GETN_BEGIN_BRANCH(View, _L("View")) GETN_ID_BRANCH(BRN_WKS_VIEW) GETN_OPTION_BRANCH(GETNBRANCH_OPEN)	
		/// Hong 05/30/07 v8.0629b BETTER_INTERFACE
		//GETN_CHECK(DataImage, "data/image", false) 
		//GETN_CHECK(XY, "show x/y", false) 			
		//GETN_CHECK(ColRow, "show column/row", false)
		//GETN_CHECK(Coor, "coordinate", false)
		//-------Folger 07/25/07 FIX_BUGS_IN_GET_VIEW_MODE_OF_WKBOOK_ORGANIZER
		//double dMode = 0;
		//LT_get_var("page.cntrl", &dMode);
		//GETN_LIST(DataImage, _L("Mode"), (int)dMode, _L("Data Mode|Image Mode"))
		int nMode = 0;
		if (MatrixObjects.Count())
			nMode = MatrixObjects(0).IsImageView();
		GETN_LIST(DataImage, _L("Mode"), nMode, _L("Data Mode|Image Mode"))
		//-------End FIX_BUGS_IN_GET_VIEW_MODE_OF_WKBOOK_ORGANIZER
			GETN_OPTION_EVENT_EX(update_view_mode)

		int nShow = 0;
		// need get page Show setting here
		GETN_LIST(ShowType, _L("Show"), nShow, _L("Column/Row|X/Y"))
			GETN_OPTION_EVENT_EX(update_show_mode)
		GETN_CHECK(Coor, _L("Coordinate"), false)
		/// end BETTER_INTERFACE
		/// Hong 05/28/07 MORE_FOR_MATRIX_ORGANIZER
		//GETN_NUM(ObjNum, "num of Mat obj",3) GETN_READ_ONLY
		int nMatObjects = MatrixObjects.Count();
		GETN_NUM(ObjNum, _L("Number of Matrix Objects"), nMatObjects) GETN_READ_ONLY_COLOR
		GETN_NUM(LayerIndex, _L("Layer Index"), GetIndex())	//-------Folger 07/25/07 FIX_BUGS_IN_SET_VIEW_MODE_OF_WKBOOK_ORGANIZER
		/// end MORE_FOR_MATRIX_ORGANIZER
	GETN_END_BRANCH(View)
	
	/// Hong 05/28/07 MORE_FOR_MATRIX_ORGANIZER
	// do NOT have function to implement this, hidden for right now
	/// Hong 05/30/07 v8.0629b BETTER_INTERFACE
	//trProperties.View.DataImage.Show = 0;
	//trProperties.View.XY.Show = 0;
	//trProperties.View.ColRow.Show = 0;
	trProperties.View.ShowType.Show = 0;
	/// end BETTER_INTERFACE
	trProperties.View.Coor.Show = 0;
	trProperties.View.LayerIndex.Show = 0;		//-------Folger 07/25/07 FIX_BUGS_IN_SET_VIEW_MODE_OF_WKBOOK_ORGANIZER
	/// end MORE_FOR_MATRIX_ORGANIZER
}



bool MatAccess::SetTree(TreeNode& trProperties) // update wks properties from tree
{
	if(NULL == trProperties || !trProperties)
		return false;
	
	vector<int> vnNewIDs;
	vector<string> vsNewValue;
	int nUpdates = tree_get_values_with_ids(trProperties, vnNewIDs, vsNewValue, true, true);
	///Danice RECORD_CHANGE_FOR_CODE_REUSE
//	RecordChangeByIDs(trProperties, vnNewIDs, vsNewValue);
	///end
	for(int ii = 0; ii < nUpdates; ii++)
	{
	//	SetProperty(vnNewIDs[ii], vsNewValue[ii]);
	}
	return true;	
}

int  MatAccess::findProperty(int nProperty)
{
	int nRet 		= 0;
	int nCurrProp 	= 1;
	for(int ii = 0;  ii < MAX_EVENTS && nCurrProp; ii++)
	{
		nCurrProp = l_table[ii].m_nProp;
		if(nCurrProp == nProperty)
			return ii;
	}
	
	return -1;
}

/*BOOL WksAccess::addProperty(int nProp, PROPFUNCGET pFnGet, PROPFUNCSET pFnSet)
{
	if(l_nCurrent >= MAX_EVENTS)
		return FALSE;
	
	l_table[l_nCurrent].m_nProp 	= nProp;
	l_table[l_nCurrent].m_pFnGet 	= pFnGet;
	l_table[l_nCurrent].m_pFnSet 	= pFnSet;
	
	l_nCurrent++;
	
	return TRUE;
}
*/

BOOL MatAccess::IsHandled()
{
	return m_bHandled;
}


MatAccess::MatAccess()
{
	m_bHandled	= FALSE;
	InitializePropertyTable();
}

void MatAccess::InitializePropertyTable()
{
		if(!l_bInit)
		{
			for(int ii = 0; ii < MAX_EVENTS; ii++)
			{
				l_table[ii].m_nProp = 0;
			}
			
			//addProperty(CMD_WKS_LONG_NAMES, IsShownLongNames, ShowHideLongNames);
			//addProperty(CMD_WKS_UNITS, IsShownUnits, ShowHideUnits);
			//addProperty(CMD_WKS_COMMENT, IsShownComments, ShowHideComments);
			//addProperty(CMD_WKS_PARAMETERS, IsShownParameters, ShowHideParameters);
			//addProperty(CMD_WKS_LABEL_CATEGORY, IsShownLabelNames, ShowHideLabelNames);
			//addProperty(CMD_WKS_DATA_ROW_NAMES, IsShownRowNames, ShowHideRowNames);
			//addProperty(CMD_WKS_COL_HEADER, IsShownColHeaders, ShowHideColHeaders);
			//addProperty(CMD_WKS_ROW_HEADER, IsShownRowHeaders, ShowHideRowHeaders);
			//addProperty(CMD_WKS_COLUMN_GRIDS, IsShownColGrids, ShowHideColGrids);
			//addProperty(CMD_WKS_ROW_GRIDS, IsShownRowGrids, ShowHideRowGrids); 
			//addProperty(0, NULL, NULL); 
			
			l_bInit = true;
		}
}

bool MatAccess::ShowDialog(TreeNode &tr, 
					LPCSTR LpcszTitle,// = NULL
					LPCSTR  lpcszDescription,// = NULL
					HWND hWndParent// = NULL
					)
{
	if( GetNBox(tr, LpcszTitle, lpcszDescription, NULL, NULL, hWndParent))
	{
		SetTree(tr);
		//return true;
	}
	
	return true;//false; //CPY 10/8/04, return false will open old dialog, we should not show old dialog anymore
	
}

static  bool			MatAccess::l_bInit 	= false;
static  int 			MatAccess::l_nCurrent 	= 0;
///end SHARE_WKBOOK_MATBOOK_ORGANIZER_ADD_MORE

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
////
////   GridAccess
////
////
void	GridAccess::InitializePropertyTable()
{
	if(!l_bInit)
	{
		for(int ii = 0; ii < MAX_EVENTS; ii++)
		{
			l_table[ii].m_nProp = 0;
		}
		
		addProperty(CMD_WKS_COL_HEADER, IsShownColHeaders, ShowHideColHeaders);
		addProperty(CMD_WKS_ROW_HEADER, IsShownRowHeaders, ShowHideRowHeaders);
		addProperty(CMD_WKS_COLUMN_GRIDS, IsShownColGrids, ShowHideColGrids);
		addProperty(CMD_WKS_ROW_GRIDS, IsShownRowGrids, ShowHideRowGrids); 
		addProperty(CMD_WKS_TRANSPOSE, IsTransposed, SetTranspose);	/// RVD 1/21/2008 qa70-10950 v8.0790 TRANSPOSE_WKS_TABLE
		addProperty(0, NULL, NULL); 
		
		l_bInit = true;
	}
}

BOOL	GridAccess::addProperty(int nProp, GAPROPFUNCGET pFnGet, GAPROPFUNCSET pFnSet)
{
	if(l_nCurrent >= MAX_EVENTS)
		return FALSE;
	
	l_table[l_nCurrent].m_nProp 	= nProp;
	l_table[l_nCurrent].m_pFnGet 	= pFnGet;
	l_table[l_nCurrent].m_pFnSet 	= pFnSet;
	
	l_nCurrent++;
	
	return TRUE;
}

void	GridAccess::GetTree(TreeNode& trProperties, int nSubBranchID)
{
	if(!IsValid() || !trProperties) //need a valid node
		return;
	
	GETN_USE(trProperties)
	
	GETN_BEGIN_BRANCH(View, _L("View")) GETN_ID_BRANCH(BRN_WKS_VIEW) GETN_OPTION_BRANCH(GETNBRANCH_OPEN)
		//GETN_BEGIN_BRANCH(Headings, _L("Show Headings"))													GETN_ID_BRANCH(BRN_WKS_VIEW_HEADINGS)///Jasmine 07/25/07 WKS_HEADER_LABEL_MODIFICATION
		GETN_BEGIN_BRANCH(Headings, _L("Show Headers"))													GETN_ID_BRANCH(BRN_WKS_VIEW_HEADINGS)			
			GETN_CHECK(ColHeader, DISPSTR_SHOW_COL_HEADER, GetProperty(CMD_WKS_COL_HEADER))					GETN_ID(CMD_WKS_COL_HEADER) 	GETN_OLDVAL
			GETN_CHECK(RowHeader, DISPSTR_SHOW_ROW_HEADER, GetProperty(CMD_WKS_ROW_HEADER)) 				GETN_ID(CMD_WKS_ROW_HEADER)		GETN_OLDVAL
		GETN_END_BRANCH(Headings)
		
		GETN_BEGIN_BRANCH(GridLines, _L("Show Grid Lines"))													GETN_ID_BRANCH(BRN_WKS_VIEW_GRIDLINES)			
			GETN_CHECK(ColGrids, DISPSTR_SHOW_COLUMN_GRIDS, GetProperty(CMD_WKS_COLUMN_GRIDS)) 				GETN_ID(CMD_WKS_COLUMN_GRIDS)	GETN_OLDVAL
			GETN_CHECK(RowGrids, DISPSTR_SHOW_ROW_GRIDS, GetProperty(CMD_WKS_ROW_GRIDS))					GETN_ID(CMD_WKS_ROW_GRIDS)		GETN_OLDVAL 
			/// RVD 1/21/2008 qa70-10950 v8.0790 TRANSPOSE_WKS_TABLE
			GETN_CHECK(Transpose, DISPSTR_TRANSPOSE, GetProperty(CMD_WKS_TRANSPOSE)) 				GETN_ID(CMD_WKS_TRANSPOSE)		GETN_OLDVAL
			/// end TRANSPOSE_WKS_TABLE
		GETN_END_BRANCH(GridLines)

	GETN_END_BRANCH(View)
}

bool GridAccess::GetProperty(int nProperty)
{
	string strVal;
  	if(GetProperty(nProperty, strVal))
  		return GetBool(strVal);
  	
  	return false;
}
bool GridAccess::SetProperty(int nProperty, LPCSTR lpcszProperty)
{
	int nEntry = findProperty(nProperty);
	if(nEntry < 0)
		return false;
	
	GAPROPFUNCSET pfnSet = l_table[nEntry].m_pFnSet;
	if(pfnSet)
	{
		pfnSet(lpcszProperty);
		m_bHandled = TRUE;
		return true;
	}
	return false;
}

bool GridAccess::GetProperty(int nProperty, string &strProperty)
{
	int nEntry = findProperty(nProperty);
	if(nEntry < 0)
		return false;
	
	GAPROPFUNCGET pfnGet = l_table[nEntry].m_pFnGet;
	if(pfnGet)
	{
		pfnGet(strProperty);
		return true;
	}
	return false;
}

int	GridAccess::findProperty(int nProperty)
{
	int nRet 		= 0;
	int nCurrProp 	= 1;
	for(int ii = 0;  ii < MAX_EVENTS && nCurrProp; ii++)
	{
		nCurrProp = l_table[ii].m_nProp;
		if(nCurrProp == nProperty)
			return ii;
	}
	
	return -1;
}

bool GridAccess::TogglePropertyValue(int nProperty)
{
	string	strVal;
	if(GetProperty(nProperty, strVal))
	{
		SetBool(!GetBool(strVal), strVal);
		return SetProperty(nProperty, strVal);
	}
	
	return false;
}


BOOL GridAccess::IsHandled()
{
	return m_bHandled;
}

bool GridAccess::SetTree(TreeNode& trProperties) // update properties from tree
{
	if(NULL == trProperties || !trProperties)
		return false;
	
	vector<int> vnNewIDs;
	vector<string> vsNewValue;
	int nUpdates = tree_get_values_with_ids(trProperties, vnNewIDs, vsNewValue, true, true);
	for(int ii = 0; ii < nUpdates; ii++)
	{
		SetProperty(vnNewIDs[ii], vsNewValue[ii]);
	}
	return true;
	
	
}


//////////////////////////////////////////////////////
//////////////////////////////////////////////////////
//////////////////////////////////////////////////////
// Begin OC functions to be used from LabTalk
//////////////////////////////////////////////////////
//////////////////////////////////////////////////////
//////////////////////////////////////////////////////
#pragma labtalk(2)	// the following can be used from LT only inside the "run -oc cmd" syntax, or "run -oc {val=func(arg)}" syntax.

/// Hong 12/19/08 QA80-12736 FIX_IMPORT_ASCII_FAIL_IMPORT_TO_GRAPH
/// EJP 07-10-2003 v7.0622 QA70-4745 SET_PAGE_IMPORT_INFO_ON_123_ASC_IMPORT
void set_ascii_import_page_info(string lpcszFile)
{
	Page pgActive = Project.Pages();
	/// EJP 2006-02-17 v8.0366 MOVE_IMPORT_FILE_INFO_FROM_OC_TO_VC
	///set_page_import_info(pgActive, lpcszFile, 0); // 0 = ASCII data type
	okutil_SetPageInfo(pgActive.GetName(), lpcszFile, 0); // 0 = ASCII data type
	/// end MOVE_IMPORT_FILE_INFO_FROM_OC_TO_VC
}
/// end SET_PAGE_IMPORT_INFO_ON_123_ASC_IMPORT
/// end FIX_IMPORT_ASCII_FAIL_IMPORT_TO_GRAPH