/*------------------------------------------------------------------------------*
 * File Name: Tree_utils.h														*
 * Creation: CPY 3/17/03														*
 * Purpose: Origin C header for Tree and vsFlexGrid utilities that are 		 	*
 *	implemented in GetNBox.c													*
 * Copyright (c) OriginLab Corp.2003											*
 * All Rights Reserved															*
 * 																				*
 * Modification Log:															*
 *	RVD 9/3/2003 QA70-5078 v7.0682 PLOT_RANGE_APPLY								*
 *	CPY 10/21/03 QA70-4680 v7.5727 TREE_BRANCHESOPEN_CLOSE_REMEMBERED			*
 *	CPY v7.5785 12/19/03 QA70-5738 GETN_BOX_COMBO_CHANGE_NEEDED					*
 *  EJP 06-07-2004 v8.0853 QA70-6472 FILE_INFO_IN_PAGE							*
 *	Frank 06/16/04	v8.0890	TREE_SET_VALUE_FROM_VECTOR							*
 *	CPY SY 07/07/2004 QA70-6641 MOVE_OC_TREE_UTILITY_TO_VC_LEVEL				*
 *  Danice 9/24/04 QA70-6891 v8.0139 ADD_BRANCH_CONTROL							*
 *	YuI 10/03/04 QA70-4387 GETN_PICTURE_IMPLEMENTATION							*
 *	CPY 10/7/04 CHANGE_STR_LIST_TO_ENUM_LIST									*
 *	Forest 10/20/04	QA70-7057 ADD_GENERATE_HELP_FILE_UTILITIES					*
 *------------------------------------------------------------------------------*/

#ifndef _TREE_UTILS.H
#define _TREE_UTILS.H

#include <Tree.h>
#include <settings.h>
#include <storage.h>

//----- CPY SY 07/07/2004 QA70-6641 MOVE_OC_TREE_UTILITY_TO_VC_LEVEL
#if _OC_VER >= 0x0800
	#define _TREE_UTILS_FROM_DLL
	#include <ocTreeUtils.h>
#else
enum {TREE_COPY_SKIP_HIDDEN = 0x0001, TREE_COPY_ATTRIB_ENABLE = 0x0002};
#endif //_OC_VER >= 0x0800
//----- end	MOVE_OC_TREE_UTILITY_TO_VC_LEVEL

// const used in GetNBox for general purpose data type const
#define	TRGP_CHECK 		ONODETYPE_CHECKBOX
//---- CPY 10/7/04 CHANGE_STR_LIST_TO_ENUM_LIST, this seems very confusing with TRGP_STR_LIST used in GET_LIST, but we have a separate GET_STR_LIST
//#define TRGP_ENUM_COMBO	ONODETYPE_DROPDOWN_NUMERIC_FLOAT
//#define TRGP_STR_LIST	ONODETYPE_DROPLIST_STRINGS
#define TRGP_NUMERIC_LIST	ONODETYPE_DROPDOWN_NUMERIC_FLOAT
#define TRGP_ENUM_LIST		ONODETYPE_DROPLIST_STRINGS
// followings are kept in case users have harded these in their code
#define TRGP_ENUM_COMBO	TRGP_NUMERIC_LIST
#define TRGP_STR_LIST	TRGP_ENUM_LIST
//---- end CHANGE_STR_LIST_TO_ENUM_LIST
#define TRGP_STR		ONODETYPE_EDIT_BOX_ONELINE_TEXT
#define TRGP_DOUBLE		ONODETYPE_EDIT_BOX_NUMERIC_FLOAT
#define TRGP_COLOR		ONODETYPE_DROPLIST_COLORS
#define TRGP_RANGE		ONODETYPE_EDIT_RANGE
#define TRGP_BRANCH		ONODETYPE_BRANCH
#define	TRGP_INTERACTIVE	ONODETYPE_EDIT_BOX_INTERACTIVE
#define	TRGP_SLIDER		ONODETYPE_SLIDER
#define	TRGP_SLIDEREDIT	ONODETYPE_EDITSLIDER
#define	TRGP_DATA_RANGE	ONODETYPE_DATA_RANGE
#define	TRGP_MULTILINE_TEXT	ONODETYPE_MULTILINE_TEXT
#define TRGP_ORIGIN_TEXT	ONODETYPE_ORIGIN_TEXT

/// YuI 10/03/04 QA70-4387 GETN_PICTURE_IMPLEMENTATION
#define TRGP_PICTURE	ONODETYPE_PICTURE_HOLDER
/// end GETN_PICTURE_IMPLEMENTATION

#define INVALID_TREENODE_IDS	-1

/** >Basic I/O
		quick display of a tree, only the tagName and Text are shown
	Parameters:
		tr = TreeNode to dump to output
		nLevel = 0, this function is called recursively inside, so there is no need to use this parameter from your code
	Returns:
		TRUE if given tree is a valid TreeNode
	See Also:
		tree_dump	
*/
bool out_tree(TreeNode& tr, int nLevel = 0);

/** >Basic I/O
		dump a tree to a specified output, also show standard attributes if any
	Parameters:
		tr = TreeNode to dump to output
		lpcsz = optional string to diplay before the dump
		nOutput = one of the constants defined in oc_const.h,
		enum {WRITE_SCRIPT_WINDOW, WRITE_STATUS_BAR, WRITE_OUTPUT_LOG, WRITE_MESSAGE_BOX, WRITE_COMPILER_OUTPUT};
		nLevel = 0, this function is called recursively inside, so there is no need to use this parameter from your code
	Returns:
		TRUE if given tree is a valid TreeNode
	See Also:
		out_tree	
*/
bool tree_dump(const TreeNode& tr, LPCSTR lpcsz = NULL, int nOutput = WRITE_SCRIPT_WINDOW); // = NULL, 0, 0

/** >Tree
	count number of leafs in the given tree
	Parameters:
		tr = TreeNode to count
		lpnSections = if given, then count the number of branches that contain these leafs
	Returns:
		total number of leafs
*/
int tree_count_items(TreeNode& tr, int* lpnSections = NULL);

/** >Tree
*/
TreeNode tree_get_node(TreeNode& trRoot, int nRow, int nStopLevel = -1, int nStartLevel = 0, int* lpInc = NULL);


//------ CPY 5/24/04 CHANGE_PARAM_NEED_REUSE_TREE
// call this function to get a node and it will add if not present
/** >Tree
	get a tree node and check if it is already present, if not, create it first
*/
TreeNode tree_check_get_node(TreeNode& tr, LPCSTR lpcszTag, int nID = 0, LPCSTR lpcszAttribName = NULL, LPCSTR lpcszAttribVal = NULL);
//------

/// SY 07/15/2004 QA70-6641 MOVE_OC_TREE_UTILITY_TO_VC_LEVEL
// move to ocTreeUtils.h
//enum {TREE_COPY_SKIP_HIDDEN = 0x0001, TREE_COPY_ATTRIB_ENABLE = 0x0002};
/// end MOVE_OC_TREE_UTILITY_TO_VC_LEVEL

/** >Tree
*/
int tree_copy_values(const TreeNode& trSrc, TreeNode& trDest, WORD wOptions = TREE_COPY_SKIP_HIDDEN | TREE_COPY_ATTRIB_ENABLE);

/** >Tree
	walk all tree nodes to delete specified attribute
	Parameters:
		tr = TreeNode to walk
		lpcszAttribute = attribute name to delete
	Returns:
		total number of nodes the specified attribute is deleted	
*/
int tree_remove_attribute(TreeNode& tr, LPCSTR lpcszAttribute);

//#define STR_ENABLE_ATTRIB		"Enable"
//#define	STR_SHOW_ATTRIB		"Show"
//#define STR_CHANGED_ATTRIB	"OldValue"
/// RVD 9/3/2003 QA70-5078 v7.0682 PLOT_RANGE_APPLY
#define	STR_PLOT_VIEW		"View"
#define	STR_PLOT_SETUP_DLG	"PlotSetupDlg"
/// end PLOT_RANGE_APPLY

#define STR_COMBO_CHANGED	"ComboChanged" //---- CPY v7.5785 12/19/03 QA70-5738 GETN_BOX_COMBO_CHANGE_NEEDED

/** >Tree
	if bSet, then NULL will clear changed
*/
bool tree_node_changed(TreeNode& trNode, bool bSet = false, LPCSTR lpcszOldValue = NULL);

/** >Tree
	walk tree and store attribute "OldValue" into all the nodes that has different value then the specified string
	Parameters:
		tr = TreeNode to walk
		vs = a linearized array of string values that should map to every tree node
	Returns:
		total number of nodes that has OldValue attributes added (changed)
	Remark:
		the vs array can be obtained by tree_get_values.
		
*/
int tree_update_changes(TreeNode& tr, const vector<string>& vs);

/**
	 set numeric value as well as putting a descriptive string to the node
	Parameters:
		tr = TreeNode to set
		dVal = a numerical value to set
		lpcszLabel = a text label to associate
	Example:
		tree_node_set_value(trCalculation.t, tvalue, "t-Value");	
	Returns:
		false if tr is invalid
bool tree_node_set_double(TreeNode& tr, double dVal, LPCSTR lpcszLabel);
*/

/** >Tree
	 get both the numeric value of a tree node as well as its associated label
	Parameters:
		tr = TreeNode to get
		strLabel = the text label if present, otherwise the tagName
		dDefault = default value in case node is not a valid node
*/
double tree_node_get_double(TreeNode& tr, string& strLabel, double dDefault = _ONAN);

/** >Tree
	 get int value from a tree node, whether it is valid or not
	Parameters:
		tr = TreeNode to get
		nDefault = default value in case node is not a valid node
*/
int tree_node_get_int(TreeNode& tr, int nDefault = 0);

/** >Tree
	walk tree and copy all the values into given string vector
	Parameters:
		tr = TreeNode to walk
		vs = a linearized array of string values that should map to every tree node
*/
void tree_get_values(TreeNode& tr, vector<string>& vs);

/** >Tree
	walk tree and copy the specified attribute from all the nodes into given string vector
	Parameters:
		tr = TreeNode to walk
		vs = a linearized array of attribute values that should map to every tree node
		lpcszAttribute = the specified attribute to copy
	Remark:
		if the specified attribute does not exist for a node, it is considered as empty
*/
void tree_get_attributes(TreeNode& tr, vector<string>& vs, LPCSTR lpcszAttribute);

/** >Tree
		generate a tree from the Project's folders and pages
	Parameters:
		tr = TreeNode to receive the folders and pages
		dwPageTypeFilter = filter options 
	Returns :
		false if get no page
	Remarks:
		The generated tree will have a root node called "project"
		Folders will have tagName enumerated as Folder1, Folder2 etc
		Pages will have tagName enumerated as Page1, Page2 etc.
		Each folder and page will have STR_LABEL_ATTRIB for the display name, 
		folders will have STR_PATH_ATTRIB for the full folder path and pages will have STR_NAME_ATTRIB for the LT name
		
*/
bool tree_get_project_folders_and_pages(TreeNode &tr, DWORD dwPageTypeFilter = 0);

/** >Tree
*/
void tree_clear_all_value(TreeNode& tr);

/** >Tree
		get TreeNode by attribute and its value
	Parameters:
		tr = TreeNode to walk
		lpcszAttribute = attribute to be used
		lpcszAttribVal = attribute value to match
		bRecursive = true: go through all the tree node in tr; 
					false: just go through the Children of tr
		bCaseSensitive = true : compare the attribute value case sensitive, false : not case sensitive
	Returns:
		Return the TreeNode be found,  invalid tree node if not found.
	Remarks:
		Once TreeNode found, it returns.
	See Also:
		tree_get_node_by_id
*/
TreeNode tree_get_node_by_attributes(TreeNode tr, LPCSTR lpcszAttribute, LPCSTR lpcszAttributeVal, bool bRecursive = true, bool bCaseSensitive = false);

/** >Tree
		get TreeNode by ID matching
	Parameters:
		tr = TreeNode to walk
		nID = tree node ID to be used
		bRecursive = true: go through all the tree node in tr; 
					false: just go through the Children of tr
	Returns:
		Return the TreeNode be found, invalid tree node if not found.
	See Also:
		tree_get_node_by_attributes
*/
TreeNode tree_get_node_by_id(const TreeNode& tr, int nID, bool bRecursive = false);

//CPY 7/12/04 QA70-6641 this function was replaced by internal VC function, so need to check if Auto testing included this
/**#?8 >Tree
		copy value to attributes from tree to tree by specific attribute value
	Parameters:
		trSrc = Source TreeNode copy from
		trDest = TreeNode copied to
		lpcszDestAttribute = The attribute of target that copy source value to, if NULL, then STR_SHOW_ATTRIB is assumed
		lpcszAttributeToMatch = Match attribute and its value to copy, if NULL, then STR_DATAID_ATTRIB is assumed
		bRecursive = 	true: go through all the tree node in trSrc; 
						false: just go through the Children of trSrc
		bAllMatched = 	true: apply to all the match node in trDest
						false: only apply to 1st matched in trDest
		bCaseSensitive = 	true : compare the attribute value case sensitive
							false : not case sensitive
	Returns:
		false if copy none
	Remarks:
*/
bool tree_copy_values_to_attributes(TreeNode& trSrc, TreeNode& trDest, LPCSTR lpcsz2ndAttributeToTransfer = NULL, LPCSTR lpcszDestAttribute = NULL, LPCSTR lpcszAttributeToMatch = NULL, bool bRecursive = true, bool bAllMatched = true, bool bCaseSensitive = false);

//----- CPY 6/16/04 QA70-6294 OC_INPUT_DATA_NODE_CLEANUP
/** >Tree
	set the attributes to all nodes in the given tree
	Parameters:
		tr = root tree node to set attributes
		lpcszAttrib = name of attribute to set
		lpcszAttribVal = value of attribute to set
		b1stLevelChildrenOnly = true will set only the immediate children, false will set current node as well as all child nodes recursively
*/
//void tree_set_attribute_to_all_nodes(TreeNode& tr, LPCSTR lpcszAttrib, LPCSTR lpcszAttribVal, bool b1stLevelChildrenOnly = false)		///Danice 9/24/04 ADD_BRANCH_CONTROL
void tree_set_attribute_to_all_nodes(TreeNode& tr, LPCSTR lpcszAttrib, LPCSTR lpcszAttribVal, bool b1stLevelChildrenOnly = false, bool bBranchOnly = false);
//-----
#ifdef _ORGOBJ_H

/** >Tree
	add all Info storage into given treenode
	Parameters:
		trNode = tree node to add info storage
		orgObj = Origin object, can be Page, Layer, Column
		lpcszObjName = name of the Origin object, if NULL, will use GetName
		lpcszObjLabel = label of the Origin object, if NULL, will use GetLabel
		nObjIndex = index >= 0 for additional info to be stored in the StrData of the tree node for each item, use NPLOT_FOR_WKS if this is for text label display in a worksheet
	Return:
		TRUE for success
*/
bool tree_add_info(TreeNode& trNode, const OriginObject& orgObj, LPCSTR lpcszObjName = NULL, LPCSTR lpcszObjLabel = NULL, int nObjIndex = -1);
#define NPLOT_FOR_WKS 100000	// a large enough number that is impossible for plot index

#endif //_ORGOBJ_H

// For reading/writing to/from ini files
#define SZ_TREE_INI_SECTION_NODE_PREFIX "section"
#define SZ_TREE_INI_KEY_NODE_PREFIX "key"

/**#? >Tree
	Get the tree node that represents a specified ini section.
	Parameters:
		trIni = tree node that represents an ini file
		lpcszSection = pointer to an ini section name
	Return:
		If a tree node representing the specified ini section then it is returned, else an invalid tree node is returned.
*/
TreeNode tree_get_ini_section(TreeNode &trIni, LPCSTR lpcszSection);

/** >Tree
	Read an ini file into a tree node.
	Parameters:
		trIni = tree node to receive the ini file
		lpcszSection = pointer to an ini file name
	Return:
		true for success, false for error
*/
bool tree_read_ini(TreeNode &trIni, LPCSTR lpcszFile);

/** >Tree
	Read an ini file into a tree node.
	Parameters:
		trIni = tree node to receive the ini file
		iniFile = the ini file to read from
	Return:
		true for success, false for error
*/
bool tree_read_ini(TreeNode &trIni, INIFile &iniFile);

/** >Tree
	Read an ini section into a tree node.
	Parameters:
		trIni = tree node to receive the ini section
		lpcszFile = pointer to an ini file name
		lpcszSection = pointer to an ini section name
	Return:
		true for success, false for error
*/
bool tree_read_ini_section(TreeNode &trIni, LPCSTR lpcszFile, LPCSTR lpcszSection);

/** >Tree
	Read an ini section into a tree node.
	Parameters:
		trIni = tree node to receive the ini section
		iniFile = the ini file to read from
		lpcszSection = pointer to an ini section name
	Return:
		true for success, false for error
*/
bool tree_read_ini_section(TreeNode &trIni, INIFile &iniFile, LPCSTR lpcszSection);

/** >Tree
	Write a tree node, that represents an ini file, to an ini file.
	Parameters:
		trIni = tree node representing an ini file
		lpcszFile = pointer to an ini file name
	Return:
		true for success, false for error.
*/
bool tree_write_ini(TreeNode &trIni, LPCSTR lpcszFile, bool bClearSections=false);

/** >Tree
	Write a tree node, that represents an ini file, to an ini file.
	Parameters:
		trIni = tree node representing an ini file
		iniFile = ini file to be written to
	Return:
		true for success, false for error
*/
bool tree_write_ini(TreeNode &trIni, INIFile &iniFile, bool bClearSections=false);

/** >Tree
	Write a tree node, that represents an ini section, to an ini file.
	Parameters:
		trIniSection = tree node representing an ini section
		iniFile = ini file to be written to
	Return:
		true for success, false for error
*/
bool tree_write_ini_section(TreeNode &trIniSection, INIFile &iniFile, bool bClearSection=false);

/// EJP 06-07-2004 v8.0853 QA70-6472 FILE_INFO_IN_PAGE
/** >Tree
	Get a TreeNode from a binary storage in a page.
	Parameters:
		trn = tree node to receive the specified binary storage
		pgSource = page to hold the binary storage
		lpcszName = pointer to the name of the binary storage
	Return:
		true for success, false for error
*/
bool tree_get_binary_storage(TreeNode& trn, Page& pgSource, LPCSTR lpcszName);

/** >Tree
	Put a TreeNode into a binary storage in a page.
	Parameters:
		trn = tree node to put into a binary storage
		pgSource = page holding a binary storage
		lpcszName = pointer to the name of the binary storage
	Return:
		true for success, false for error
*/
bool tree_put_binary_storage(TreeNode& trn, Page& pgTarget, LPCSTR lpcszName);
/// end FILE_INFO_IN_PAGE

/** >Import Export
	Read the export settings, for a specified format, into a tree node.
	Parameters:
		trSettings = tree node to receive the settings
		lpcszFormat = pointer to the image format whose settings are to be read
	Return:
		true for success, false for error
*/
bool tree_read_image_export_settings(TreeNode &trSettings, LPCSTR lpcszFormat);

/** >Import Export
	Write the export settings, for a specified format, into a tree node.
	Parameters:
		trSettings = tree node containing the settings
		lpcszFormat = pointer to the image format whose settings are to be written
	Return:
		true for success, false for error
*/
bool tree_write_image_export_settings(TreeNode &trSettings, LPCSTR lpcszFormat, bool bClearSections=false);

/** >Import Export
	Get the image export settings from a page.
	Parameters:
		trSettings = tree node to receive the settings
		pg = page to get the settings from
		lpcszFormat = pointer to the image format
	Return:
		true for success, false for error
*/
bool tree_get_page_image_export_settings(TreeNode &trSettings, Page &pg, LPCSTR lpcszFormat);

/** >Import Export
	Set the image export settings into a page.
	Parameters:
		trSettings = tree node containing the settings
		pg = page to set the settings into
		lpcszFormat = pointer to the image format
	Return:
		true for success, false for error
*/
bool tree_set_page_image_export_settings(TreeNode &trSettings, Page &pg, LPCSTR lpcszFormat, bool bClearSection=false);

/**#
		It dumps into the appropriate output (output log and/or note window) according to the
		settings in the tree the trRep.Contents.Header.Table branch.
	Returns:
		true if OK, otherwise false.
*/
bool	tree_header_table_report(TreeNode &trRep);


/**#
		It retrieves the information from trRep.Settings about where the report should go
		(output log and/or a Note window) and how, and creates, if needed, the Note window
		for output.
	Paramaters:
		trRep=the Reporting branch.
		dwTarget=(output) it receives the information about where the report should go as a
					combination of bits:
					enum {
						TYPETARGET_NAMED_WINDOW			= 0x00000002UL,		// to the particular Notes window
						TYPETARGET_OUTPUTLOG			= 0x00000004UL,		// to output log
					};
		strNoteWnd=the name of the note window
		pbAppendToNote=the address of a BOOL to optionally return the information whether the report should
						be appended to the note window or the current contents of the note window should be replaced.

*/
bool	tree_reporting_prepare_targets(TreeNode &trRep, DWORD &dwTarget, string &strNoteWnd, BOOL *pbAppendToNote = NULL);

enum {SETTINGS_MAIN, SETTINGS_GUI};

/**# >Operation
*/
void 	save_default_settings(TreeNode& tr, LPCSTR lpcszClassName, int nCategory = SETTINGS_MAIN);

/**# >Operation
*/
BOOL	load_default_settings(Tree& tr, LPCSTR lpcszClassName, int nCategory = SETTINGS_MAIN);

/** >System
		Save the given array of boolean values into a single DWORD in the registry.
	Parameters:
		lpcszDlgName = name of the dialog, this is used as the section name in the registry under /Dialogs/lpcszDlgName
		vbValues = array of 1 and 0 that each will be assigned to a bit in the DWORD value saved into registry
		lpcszValName = Value name in registry to save, if not specified, CheckBoxes will be used
	Return:
		True for success, false for error.
*/
bool save_default_checkboxes(LPCSTR lpcszDlgName, const vector<byte>& vbValues, LPCSTR lpcszKey = NULL);

/** >System
		Setrive a array of boolean values saved by save_default_checkboxes in the registry.
	Parameters:
		lpcszDlgName = name of the dialog, this is used as the section name in the registry under /Dialogs/lpcszDlgName
		vbValues = array of 1 and 0 that each will represent each bit in the DWORD value saved into registry
		lpcszValName = Value name in registry to save, if not specified, CheckBoxes will be used
	Return:
		True for success, false if lpcszDlgName section does not have the item in registry.
*/
bool load_default_checkboxes(LPCSTR lpcszDlgName, vector<byte>& vbValues, LPCSTR lpcszValName = NULL);

/**#
*/
bool dlg_save_to_registry(LPCSTR lpcszSecName, LPCSTR lpcszValName, DWORD dwVal);
/**#
*/
bool dlg_load_registry(LPCSTR lpcszSecName, LPCSTR lpcszValName, DWORD& dwVal);

/** >Tree
		walk all nodes, if .ID exists, then add the ID and the value to two vectors vnIDs & vsValues
	Example:
		This example reads values of nodes from TreeNode.ini, and saves user's modifications to this file.
		
		#include <GetNBox.h>
		enum{ID_NUMEXP, ID_B, ID_B_T1, ID_B_T2, ID_B_T3, ID_DATARANGE, ID_CURVECOLOR};
		void test()
		{		
			GETN_TREE(myTree)
			GETN_COMBO(numExp, "Number of Terms", 1, "1|2|3")	GETN_ID(ID_NUMEXP)
			
			GETN_BEGIN_BRANCH(DecayTime, "Decay Times") GETN_ID_BRANCH(ID_B)
				GETN_NUM(decayT1, "1st Decay Time (t1)", 0.0)	GETN_ID(ID_B_T1)
				GETN_NUM(decayT2, "2nd Decay Time (t2)", 0.0)	GETN_ID(ID_B_T2)
				GETN_NUM(decayT3, "3rd Decay Time (t3)", 0.0)	GETN_ID(ID_B_T3)
			GETN_END_BRANCH(DecayTime)
				
			GETN_RANGE(DataRange, "Data Range", 0, 99, 1, 30)	GETN_ID(ID_DATARANGE)
			
			GETN_COLOR(FitCurveColor, "Fit Curve color", 1)	GETN_ID(ID_CURVECOLOR)
			
			string  strFileName = "TreeNode.ini";
			vector<int> vnIDs;
			vector<string> vsValues;
						
			if( tree_read_values_with_ids(strFileName, vnIDs, vsValues) )
				tree_set_values_by_ids(myTree, vnIDs, vsValues);
	
			if(GetNBox(myTree, "Fit Exp Decay", "Fit Exponential Decay 1,2,3"))
			{
				out_tree(myTree);
				tree_get_values_with_ids(myTree, vnIDs, vsValues);
				tree_save_values_with_ids(strFileName, vnIDs, vsValues);
			}
		} 
	Parameters:
		trSetting = a source tree
		vnIDs = vector of IDs from tr.
		vsValues = vector of strVals from tr.
		bIncludeSub = TRUE or FALSE, if bIncludeSub == TRUE, this function will go through all tree node;
		if not, will just go  through the first level.
	Returns:
		the number of the node have ID
 */
int tree_get_values_with_ids(const TreeNode& trSetting, vector<int>& vnIDs, vector<string>& vsValues, bool bIncludeSub = true
#ifdef  _TREE_UTILS_FROM_DLL
 		,bool bCheckChange = false);
#else  //_TREE_UTILS_FROM_DLL
		);
#endif//  _TREE_UTILS_FROM_DLL
/** >Tree
		walk all nodes, look for nodes with matching ID, and apply value, if the have same ID, will 
		just save the first one ID corresponding value.
	Parameters:
		trSetting = a source tree
		vnIDs = vector of IDs.
		vsValues = vector of string values, must be the same size of vnIDs.
	Returns:
		number of matching found nodes,
		if return -1 mean input tree node not invalid,
		-2 mean the pairs of vector size to 0;
		-3 when the pair vector not the same size,
 */
int tree_set_values_by_ids(TreeNode& trSetting, const vector<int>& vnIDs, const vector<string>& vsValues);

/** >Tree
		walk all nodes, look for nodes with ID, and apply it to destination tree nodes that has same ID
	Parameters:
		trSrc = a source tree node
		trDest = destination tree node
	Returns:
		number of nodes that the values are copied or 0 if none.
 */
int tree_copy_values_by_id(const TreeNode& trSrc, TreeNode& trDest);

/** >Tree
		save the id-value pair into file
	Parameters:
		lpcszFilename = full file name to store data pairs
		vnIDs = vector of IDs.
		vsValues = vector of string values, must be the same size of vnIDs.
	Returns:
		true if succeed
*/
bool tree_save_values_with_ids(LPCSTR lpcszFilename, const vector<int> vnIDs, const vector<string>& vsValues);
/** >Tree
		read the id-value pair from file
	Parameters:
		lpcszFullFilename = full file name to store data pairs
		vnIDs = vector of IDs.
		vsValues = vector of string values, must be the same size of vnIDs.
	Returns:
		true if succeed
 */
bool tree_read_values_with_ids(LPCSTR lpcszFilename, vector<int>& vnIDs, vector<string>& vsValues);

///	Frank 06/16/04	v8.0890	TREE_SET_VALUE_FROM_VECTOR
/** >Tree
	 set string value to the TreeNode leaf, set order as the vector index
	Parameters:
		tr = TreeNode to set value
		vs = vector of the value want to input to treenode, if it is branch node, the cell will empty.
		nStartIndex = index of the start cell of the vector
	Example:
		tree_set_values( tr, vs, 0 )	
	Returns:
		false if tr is invalid
*/
bool tree_set_values( TreeNode &tr, vector<string>& vs, int* lpnSections = NULL);//=0);
//End TREE_SET_VALUE_FROM_VECTOR
//---- end TREE_BRANCHESOPEN_CLOSE_REMEMBERED

//---- CPY 10/21/03 QA70-4680 v7.5727 TREE_BRANCHESOPEN_CLOSE_REMEMBERED
// following class written by Xuan Sun

/** >Utility
	This Class can be used to compress byte vectors (1 and 0s) to hex strings, and to decompress
	hex strings back to byte vectors.
	
	Note: Since it converts every 4 bits to a hex char, so if there is less than 4 bits, 
	0's will be filled in. For example {1,0,1,0,1,1} will be converted to "AC", because 
	1010=10=A, and 1100=12=C, notice that two 0's are filled at the end in "1100". "AC"
	will be decompressed to {1,0,1,0,1,1,0,0}
*/
class BitsHex
{
public:

	/**
		convert a vector of 1's and 0's to a hex string
	*/
	bool BitsToHexStr(const vector<byte>& vn, string& strHex)
	{
		byte bb=0;
		byte bTemp=0;
		int jj=0;
		strHex.Empty();
		for(int ii=0;ii<vn.GetSize();ii++)
		{
			bTemp=vn[ii];
			bTemp<<=(7-jj);
			bb=bb|bTemp;
			jj+=1;
			
			//Convert every 4 bytes to one hex char
			if(jj>=4 || ii==(vn.GetSize()-1))
			{
				strHex += byteToHex(bb);
				jj=0;
				bb=0;
			}
		}
		
		return true;
	}
	
	/**
		convert a hex string to a vector of 1's and 0's
	*/
	bool HexStrToBits(const string& strHex, vector<byte>& vn)
	{	
		int nHex;
		char cHex;
		byte bTest;
		vn.SetSize(0);
		for(int ii=0; ii<strHex.GetLength(); ii++)
		{
			cHex = strHex[ii];
			
			// convert the hex to int first
			nHex = hexToInt(cHex);
			
			if (nHex<0)
				return false;
			
			bTest=1;
			bTest<<=3;
			for(int jj=0; jj<4; jj++)
			{
				//put 1's and 0's in the vector
				vn.Add((nHex&bTest)?1:0);
				bTest>>=1;
				//printf("%d",vn[vn.GetSize()-1]);
			}
		}
		//printf("\n");
		return true;
	}

	/**
		a little utility function
	*/
	void vector_out(const vector<byte>& vn)
	{
		for(int ii = 0; ii < vn.GetSize(); ii++)
			printf("%d", vn[ii]);
		printf("\n");
	}
private:

	/**
		convert a hex to an int(0 to 15), if error return -1
	*/
	int hexToInt(char cHex)
	{
		int nInt;
		if(cHex>='0' && cHex<='9')
			nInt = cHex - '0';
		
		else if(cHex>='a' && cHex<='z')
			nInt = cHex - 'a' + 10;
		
		else if(cHex>='A' && cHex<='Z')
			nInt = cHex - 'A' + 10;
		
		else
			return -1;
		
		return nInt;
	}

	/**
		use the high four bits to convert to a hex char
	*/
	char byteToHex(byte bb)
	{
		char cHex;
		byte bTest = 1;
		bTest<<=4;
		int nConvert=0;
		
		for(int ii=0; ii<4; ii++)
		{
			if(bTest&bb)
			{
				// convert byte to int first
				nConvert += 1<<ii;
			}
			
			bTest<<=1;
		}
		
		if(nConvert<=9)
		{
			cHex = '0'+ nConvert;
		} 
		else
		{
			cHex = 'A'+ (nConvert-10);
		}
		
		return cHex;
	}

};
//----------- CPY 6/15/04 QA70-6294 OC_DATA_PLOT_SEL_INFO_CONSOLIDATION
/** >Tree
	scan the current tree node for all child notes and find the next child node tag name
	Parameters:
		tr = A tree branch node that we need to scan for
		strTag = result tagName
	Returns:
		the enumeration index of the tag if successful, or -1 if tr is not a branch
	Remark:
		The first child is used to get the enumeration prefix. If the first child is not in the form of enumerated node, we return -1
	
*/
int tree_get_next_enum_tag_name(const TreeNode& tr, string& strTag = NULL);
//------------

//------- CPY 8/30/04 QA70-6667 RESULT_SHEET_QUERY
/** >Tree
	append tr2 into tr1 with all children and all attributes
	
*/
int tree_append_children(TreeNode& tr1, const TreeNode& tr2, LPCSTR lpcszPrefix);

/** >Tree
	output contents of tree to a string
*/
int tree_to_str(const TreeNode& tr, string& str, bool bSkipHidden = true, bool bSimpleTypesOnly = true, bool bCheckUseLabel = true);
//string	tree_to_treetable_str(TreeNode &trNode, int nXoffset= 0 ,int nExtraSpace = 1, bool bLev1AsCols = true , string strDoubleValueFormat = "*" , int nDisplayFormat = DISPLAY_LEFT	 );
//string	tree_to_treetable_str(TreeNode &trNode, vector<int> &vnDisplayFormat,bool bSkipHidden,bool bTranspose = true,  int nXoffset= 0 ,int nExtraSpace = 1, bool bLev1AsCols = true , string strDoubleValueFormat = "*" );
string	tree_one_treetable_to_str(TreeNode &trNode, vector<int> &vnDisplayFormat,bool bSkipHidden,bool bTranspose = true,  int nXoffset= 0 ,int nExtraSpace = 1, bool bLev1AsCols = true , string strDoubleValueFormat = "*" );
int tree_to_str(const TreeNode& tr, string& str, vector<int> &vnDisplayFormat, bool bSkipHidden = true, bool bSimpleTypesOnly = true, bool bCheckUseLabel = true);

//-------

///---Frank v8.0147	10/14/04			CENTRALIZE_FO_FUNCTION_TO_TREE_UTLIS
//Update NLSF file on user folder
/**
	update specified lines of ini file.
Example:
	StringArray saLines;
	int iError = ReadFileLines(saLines, "C:\\Origin80\\Origin.ini");
Parameters:
	iniFile= The file you want to update
	lpcszSectionName = Name of Section to update
	lpcszKeyName = Name of key to update, if equal to NULL, will remove the section .
	lpcszValue = Value you want to update of the key, if NULL, will delete the key.
Return:
	Returns true for success or false not.  
*/
bool update_ini_line(INIFile &iniFile, LPCSTR lpcszSectionName, LPCSTR lpcszKeyName, LPCSTR lpcszValue);
void get_ini_keys_and_values(INIFile &iniNLSF,LPCSTR lpcszSection, StringArray &saKeys, StringArray &saValues  );
///---End			CENTRALIZE_FO_FUNCTION_TO_TREE_UTLIS

#if _OC_VER >= 0x0800
///Forest 10/20/04	QA70-7057 ADD_GENERATE_HELP_FILE_UTILITIES
/** 
	use strArge and strFuncPrototype to get trFuncArgu
Remarks:
	When one argument is pointer or reference, this argument in parameter field must be marked [input] or [output].
	And, when the argument is [output](output argument), it should not be const. 
	
Parameters:
	strArgu= [input]arguments description in Parameter field
	strFuncPrototype= [input]prototype of function
	trArgu= [output]descripts the argument in the form of treenode, which has name, datatype, and bits 3 properties; First 2 are string, the third is int,
					by now, the bit will be enum { ARGU_BIT_POINTER = 0x02,  ARGU_BIT_REFERENCE = 0x03, ARGU_BIT_CONST = 0x04, ARGU_BIT_HAS_DEFAULT = 0x08}

Return:
	no error return TRUE, otherwise return FALSE;
*/
bool ocsp_func_argu(const string& strArgu, const string& strFuncPrototype, TreeNode& trArgu);
///End ADD_GENERATE_HELP_FILE_UTILITIES
#endif //#if _OC_VER >= 0x0800

#endif //_TREE_UTILS.H
