/*------------------------------------------------------------------------------*
 * File Name: nlsf_utils.c	 													*
 * Creation: Frank/P.J 2005-12-06												*
 * Purpose: OriginC Source C file												*
 * Copyright (c) OriginLab Corp. 2005, 2006, 2007, 2008, 2009, 2010				*
 * All Rights Reserved															*
 * 																				*
 * Modification Log:															*
 *	Leo 2005-12-9 MOVED_FROM_PFM_UTILS											*
 *	CPY 12/10/05 MOVE_NLF_FUNC_FROM_ANALYSIS_UTILS								*
 *	Frank 12/19/05 CONVERT_NEW_NLSF_REPORT_TREE_TO_OLD_NLSF_TREE				*
 *	Jasmine 02/06/06 GET_PARAMETERS_SETTINGS									*
 *	jasmine 02/11/06 MOVE_TO_NLSF_UTILS											*
 *	Jasmine 02/14/06 ADD_SET_SIZE												*
 *	Jasmine 03/13/06 v8.0374 REPLACE_VECTOR_POINTER_WITH_VECTOR					*
 *  Iris 4/13/06 MOVE_NLSF_FUNC_FROM_NLFITSESSION								*
 *	Jasmine 05/10/06 ENABLE_DISABLE_BOUNDS_SETTING								*
 *  Joe 8/16/06 MOVE_NLSF_FUNC_FROM_NLFITSESSION								*		
 *	ML 8/28/2006 MULTIPLE_DEPS_INDEPS_NLFIT										*
 *	Jasmine 01/27/07 SHOW_FUNC_DESCRIPTION_INSTEAD_OF_FDF_PATH					*
 *	Cheney 2007-3-22 USE_RIGHT_METHOD_TO_GET_FDF_FILE							*
 *	Cloud 03/23/07 INIT_PARAMS_FOR_PEAK_FUNC                                    *
 *  Cloud 03/24/07 MOVE_TO_INTERNAL_C                                           *
 *	Arvin/Cheney 03/26/07 QA70-9527 SUPPORT_SETTING_PARAMS_FROM_OC_LT 			*
 *	Jasmine 04/02/07 SUPPORT_SIGN_DIGITS										*
 *	Cheney 2007-4-9 CORRECT_LOGIC_OF_CALLING_INIT_BRANCH						*
 *	Cheney 2007-4-14 IF_NO_THEME_AUTO_INIT_WILL_ACCORDING_TO_FDF				*
 *	Cheney 2007-4-19 SHOW_CHECKBOX_FOR_PARAMS_INIT_AND_CONSTRAINTS				*
 *	Cheney 2007-4-23 USE_WRONG_ENTRY_FOR_AUTO_INIT_CHECK_BOX 					*
 *	Cheney 2007-4-24 CLEAN_UP_FDF_TREE_LOAD										*
 *	Cheney 2007-4-29 SEPRATE_BOUND_SETTING_FROM_PARAMS_SETTING_CEHCK_BOX		*
 *	Cheney 2007-5-5 FUNC_DESCRIPTION_NOT_WORK									*
 *	Cheney 2007-5-25 DO_SAVE_FDF												*
 *	Cheney 2007-6-7 SHOULD_USE_FDFT_CONVERT_BOOL_TO_01_WHEN_NODE_VAL_IS_STRING	*
 *	Cheney 2007-6-8 ALLOW_USER_EDIT_LINEAR_CONSTRINTS_WHEN_USE_BUILDIN_FUNC		*
 *	Jasmine 06/08/07 NEW_MECHANISM_TO_SAVE_BUILT_IN_FUNCTION					*
 *	Cheney 2007-6-13 SHOULD_ADD_SIGNIFICANT_DIGIT_IN_PARAMETER_SETTING_NODE		*
 *	Cheney 2007-6-19 ALWAYS_FIND_XY_FROM_CUMULATIVE_FIT_CURVE_IF_PEAK_FIT		*
 *	Jasmine 07/09/07 TEMP_CHANGE_FOR_FDFT_CONVERT_BOOL_TO_01_NOT_WORK_WAIT_HONG_FIX*
 *	Arvin 07/10/07 v8.0656 CLEAN_CODE_FOR_XF_SIMCURVE_AND_SIMSURFACE			*
 *	Folger 07/11/07 ADD_LOAD_FUNCTION_NAME_FROM_CUSTOMIZE_XML					*
 *	Cheney 2007-7-23 QA80-10090 MODIFY_STH_ABOUT_FDF_SAVING_AND_THEME_APPLY		*
 *	Cheney 2007-8-21 QA70-10256-P7 ADD_GLOBAL_FUC_FOR_UPDATE_CONTOUR_LEVEL		*
 *	Cloud 08/21/2007 SURFACE_INIT												*
 *	RVD 10/4/2007 v8.0715 qa7-10463 FIX_NLFIT_LIMIT_20_PARAMETERS				*
 *	Arvin 11/14/07 JUST_MOVE_FUNCTION_FROM_NUMFUNCTIONORGANIZER_TO_NLSF_UTILS	*
 *	Folger 11/15/07 FIX_LABEL_LOCALIZATION										*
 *	Cloud 12/10/07 SIGMA_OBJECT_SEEMS_OBSOLETE									*
 *	Folger 12/14/07 NEED_TO_JUDGE_CALL_FROM_NLFIT_OR_SIMCURVE					*
 *	Jasmine 12/25/07 QA80-9853 USE_SHORTER_FDF_PREVIEW_NAME						*
 *	Hong 01/02/08 QA80-10881 FIX_XML_FAIL_SAVED_FOLDER_NOT_CREATED_FIRST		*
 *	Folger 02/12/08 IMPROVE_SIMULATE_CURVE										*
 *	Jasmine 02/25/08 CHECK_GET_SIGMA_CONTROL									*
 *	Arvin 03/03/08 QA-11206 SETUP_CONTOUR_PLOT_FOR_SURFACE_FIT					*
 *	Sim 03-17-2008 FIX_CHECK_NLFIT_PDF_FILE_EXTENSION							*
 *	Hong 03/19/08 8.0827 NLFIT_REMOVE_SETTINGS_ALLREADY_IN_FDF_FILE_FROM_THEME	*
 *	Folger 03/20/08 QA80-11155 CENTRALIZE_OUTPUT_PARAMETER_COMMENTS_FOR_SIMCURVE_AND_SIMSURFACE
 *	Folger 04/02/08 QA80-11364 IMRPOVE_PA_FIT_BY_STORE_FIT_FUNCTION_TREE_FOR_LOOP
 *	CPY 4/3/08 PA_FIT_CNTRL_OPEN_EMPTY_NO_ERR_MSG								*	
 *	Folger 04/07/08 QA80-11384 FIX_GET_FDF_FULL_PATH_WITHOUT_CATEGORY			*
 *	Sim 04-07-2008 QA80-11371 THEME_SAVING_OPTIONS								*
 *	Folger 04/10/08 QA80-11398 FIX_XF_FITPEAKS_BROKEN_BECAUSE_SET_CONSTRAIN_WITH_WHITE_SPACE_ONLY
 *	Folger 04/11/08 APPLY_FDF_ORIGINAL_SETTING_AFTER_APPLY_THEME				*
 *	Sim 04-10-2008 QA80-11371 THEME_SAVING_OPTIONS_FOR_WIZ						*
 *	Jasmine 04/14/08 SIM_ASK_CONVERT_PA_FIT_TREE_DATA_ID						*
 *	Jasmine 04/17/08 PEAK_FIT_USE_SAME_FUNCTION_ID_AS_NLFIT						*
 *	Sim 04-22-2008 QA80-11371 THEME_SAVING_OPTIONS_HINT							*
 *	Jasmine 04/22/08 CENTRAILIZE_GET_NLSF_GET_PARAM_NAMES_CODES					*
 *	Hong 07/25/08 QA80-11593 FIX_BUILD_IN_FDF_USER_ADDED_DERIVED_PARAMETERS_LOST_IN_FIT_REPORT
 *	Folger 07/29/08 QA80-11909 PA_FIT_SHOULD_PICK_UP_DEFAULT_PARAMETER_VALUES_IN_FDF_AND_CENTER_VALUES_FROM_FIND_PEAK
 *	Hong 08/22/08 v8.0928 BETTER_LABEL_AVOID_CONFUSING							*
 *	CPY 8/24/08 QA70-12878 NLFIT_TOO_SLOW_TO_OPEN								*
 *	Sim 09-05-2008 QA80-12151 NLFIT_TOO_SLOW_TO_OPEN							*
 *	Sophy 10/20/2008 QA80-12406 ADD_DERIVATIVE_PARAM_PAGE_IN_CODE_TAB_OF_NLFIT_DLG
 *	Hong 11/04/08 QA80-12526 v8.0965b ADD_BACKWARD_COMPATIABLE					*
 *	Kyle 11/05/2008 QA80-12509-P1 ADD_PEAK_AMPLITUDE_INTO_CONTROL_SESSION_OF_FO	*
 *	Kyle 11/11/2008 QA80-12564 CREATE_X_Y_DATA_BASE_ON_GRAPY_SCALE				*
 *	Max 11/11/08 v8.0968c QA70-12564 NEED_TO_HANDLE_BOUNDARY_CASE				*
 *	Kyle 11/17/08 QA80-12591 CORRECT_FORMULA_TO_COMPUTE_X_DATA_FOR_FITTED_CURVE	*
 *	Sophy 12/19/2008 v8.0988c QA80-12798 SKIP_THEME_APPLIED_TO_OUTPUT_DISABLED_NODE_WHEN_CHANGE_PARAMS
 *	Hong 12/30/08 QA80-12878 v8.0992 FAST_POPUP_DLG_BY_SKIP_INIT_USING_NULL_FUNCTION
 *	Jasmine 02/17/09 QA80-10378 SHARE_FUNCTION_ORGANIZER_CODE_WITH_SELECTCAT	*
 *	Kyle 03/17/2009 QA80-12564-P7 GENERAL_ERROR_MESSAGE_FOR_X_RANGE_ERROR		*
 *	Folger 04/03/09 QA80-13408 NUMERIC_SAVED_INTO_FDF_SHOULD_USE_FULL_PRECISION	*
 *	Folger 04/08/09 QA80-13424-P4 FAILS_TO_EDIT_PARAM_SETTINGS_OF_USER_DEFINED_FDF_IN_FO
 *	Jasmine 04/16/09 QA80-13424 REWRITE_FUNCTION_TO_GET_PREVIEW_NAME			*
 *	Sophy 6/5/2009 MORE_SUPPORT_ON_NLFITSESSION_CUSTOMIZATION					*
 *	Folger 06/18/09 CENTRALIZE_CODE_ABOUT_GETTING_PEAK_FUNC_PARAM_INDICES		*
 *	Kyle 08/06/2009 QA80-14077 ADD_UNIT_FOR_PARAMETER_SETTINGS					*
 *	Jasmine 08/28/09 CENTRALIZE_FIND_PEAK_METHOD_COMBO							*
 *	Kyle 11/04/2009 QA80-14584 SCV_ADD_FITTING_FUNCTIONS						*
 *	Kenny 11/11/2009 QA81-14624 SUPPORT_DRAG_AND_DROP_MULTIPLE_ORIGIN_FILES		*
 *	Jasmine 11/20/09 QA80-14628 IMPROVE_FIND_MEANING_METHOD						*
 *	Kyle 11/26/2009 QA80-14584-P1 SKIP_FOLDER_INFO_WHILE_SCANING_FITTING_FUNCTIONS
 *	Kyle 12/01/2009 SHOULD_ALWAYS_REMOVE_DEFAULT_FUNCTION_FROM_THE_LIST			*
 *	Folger 12/14/09 QA81-14832 QUICK_NLSF_FITTING								*
 *	Folger 12/18/09 QA81-14859 THEME_SETTINGS_SUPPORT_APPLY_FIXED_STATUS_ONLY	*
 *	Kyle 01/14/2010 QA80-14957 COMMA_IS_USED_AS_SEPARATOR_SO_USE_POINT_AS_DELIMITER_EVEN_IN_GOS
 *	Jasmine 06/10/10 ORG-263-P1 REMOVE_CATEGORY_SEPARATOR_FOR_IT_IS_SELECTABLE_IN_COMBO
 *	Folger 06/24/10 ORG-390-S1 USE_ONE_IF_NO_PARAM_INIT_VALUE_SPECIFIED			*
 *	Folger 07/23/10 ORG-423-P3 SHOULD_NOT_COMPILE_FFW_IF_NAME_NOT_FITTING_FUNCTION
 *------------------------------------------------------------------------------*/
 
#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
#include "theme_utils.h"
#include <ONLSF.h>
#include "NumFunctionOrganizer.h"
//#include "XFunctionEx.h"
#include "nlsf_utils.h"
#include "NLFitSession.h"
#include <operation.h>
#include <ocGDI.h>
	
#ifdef _DEBUG
#include <Profiler.h>//------CPY 8/24/08 QA70-12878 NLFIT_TOO_SLOW_TO_OPEN
#endif

#define STR_FDF_FILE_FOLDER				"fitfunc"
#define STR_FDF_FILE_EXT				".fdf"

/// Hong 07/25/08 QA80-11593 FIX_BUILD_IN_FDF_USER_ADDED_DERIVED_PARAMETERS_LOST_IN_FIT_REPORT
// logic move into VC FDFTree.h
//#define	STR_CUSTOMIZED_BUILT_IN_FILE			"CustomizedBuiltIn.xml"	///Jasmine 06/08/07 NEW_MECHANISM_TO_SAVE_BUILT_IN_FUNCTION	
/// end FIX_BUILD_IN_FDF_USER_ADDED_DERIVED_PARAMETERS_LOST_IN_FIT_REPORT

///Leo 2005-12-9 MOVED_FROM_PFM_UTILS
#define MAX_NUM_ITERATIONS	100

enum {
	SETDATA_FAILED,
	INVALID_PARAMETER_SETTING,
	FAIL_TO_PERFORM_FITTING,
	FAIL_TO_GET_PARAMETER_RESULT,
	FAIL_TO_GET_CONFIDENCE_LEVEL_OF_PARAMETER,
	FAIL_TO_FIT_GETSUMMARYFITRESULT,
	SHOULD_SHARE_PARAMETER,
	UNKNOWN_ERROR_OCCUR
};
///End MOVED_FROM_PFM_UTILS

///Arvin/Cheney 03/26/07 QA70-9527 SUPPORT_SETTING_PARAMS_FROM_OC_LT 
/// RVD 10/4/2007 v8.0715 qa7-10463 FIX_NLFIT_LIMIT_20_PARAMETERS
#ifndef	NLSF_PARAM_TREE_CONSRUCTION_MOVE_VC
/// end FIX_NLFIT_LIMIT_20_PARAMETERS
static vector<string> gvsParamName = {"Share", "Fixed", "LowerBounds", "LowerBoundsExclusive", 
			"LowerBoundsEnable", "UpperBounds", "UpperBoundsExclusive", "UpperBoundsEnable", 
			"Values",
			"SignificantDigit"///Cheney 2007-6-13 SHOULD_ADD_SIGNIFICANT_DIGIT_IN_PARAMETER_SETTING_NODE	
};
/// RVD 10/4/2007 v8.0715 qa7-10463 FIX_NLFIT_LIMIT_20_PARAMETERS
#endif	//!NLSF_PARAM_TREE_CONSRUCTION_MOVE_VC
/// end FIX_NLFIT_LIMIT_20_PARAMETERS

//-----------------------------------------------------------------------
//------------------- CPY 12/10/05 MOVE_NLF_FUNC_FROM_ANALYSIS_UTILS
//-----------------------------------------------------------------------
//-------- CPY 10/8/04 QA70-4387 CENTRALIZE_NLF_TO_GETN_BASED_CODES
// strFuncSource = name used internal for function identification, usually the same as function name. This is the key to index fgroup pictures
// strFullpathFileName = function's FDF full path file name
///Jasmine 04/16/09 QA80-13424 REWRITE_FUNCTION_TO_GET_PREVIEW_NAME
//replace nlf_get_func_names which is commented below
bool nlf_get_func_preview_names(const TreeNode &trFunction, string& strFuncName, string& strFullpathFileName, string* pGroupName/*= NULL*/)
{
	strFuncName.Empty();
	strFullpathFileName.Empty();
	if(trFunction.GeneralInformation)
		trFunction.GetAttribute(STR_FILENAME_ATTRIB, strFullpathFileName);
	else
		return false;
	
	TreeNode trFunct = trFunction.GeneralInformation.FunctionSource;	
	if(trFunct.IsValid())
	{
		strFuncName = trFunct.strVal.GetToken(1,'.');
		strFuncName.MakeLower();
		if(pGroupName)
			*pGroupName = trFunct.strVal.GetToken(0,'.');
	}
	
	if( strFuncName.IsEmpty() )
		strFuncName = trFunction.GeneralInformation.FunctionName.strVal;
		
	if(strFuncName.IsEmpty() && strFullpathFileName.IsEmpty())
		return false;
	
	return true;	
}
///End REWRITE_FUNCTION_TO_GET_PREVIEW_NAME

///------ Folger 04/08/09 QA80-13424-P4 FAILS_TO_EDIT_PARAM_SETTINGS_OF_USER_DEFINED_FDF_IN_FO
//bool nlf_get_func_names(const TreeNode &trFunction, string &strFuncName, string& strFDFname, string* pstrFullpathFileName, string* pGroupName) //=NULL, NULL
//{
	//strFuncName.Empty();
	//strFDFname.Empty();
	//if(trFunction.GeneralInformation)
	//{
		//if(pstrFullpathFileName)
			////trFunction.GetAttribute(STR_LABEL_ATTRIB, *pstrFullpathFileName);	///Danice 12/23/04 : STR_LABEL_ATTRIB has been use for the function name in FO
			//trFunction.GetAttribute(STR_FILENAME_ATTRIB, *pstrFullpathFileName);
	//}
	//else
		//return false;
	/////Frank 10/11/04 v8.0147  MODIFY_CODE_TO_LOAD_SAMPLE_FORMULA_PREVIEW
	///*
	//if(0 == lstrcmpi(strFDFname, "") && pstrFullpathFileName)
	//{
		//strFDFname = *pstrFullpathFileName;
		//StringArray  vsFiles;
		//int iTokenSize ;
		//iTokenSize = strFDFname.GetTokens(vsFiles,'\\');
		//strFDFname = vsFiles[iTokenSize-1];
		//strFDFname = strFDFname.GetToken(0, '.');
	//}
	//*/
	//if(strFDFname.IsEmpty() && pstrFullpathFileName)
		//strFDFname = GetFileName( *pstrFullpathFileName, true );
	/////End  MODIFY_CODE_TO_LOAD_SAMPLE_FORMULA_PREVIEW
//
	//TreeNode trFunct = trFunction.GeneralInformation.FunctionSource;
	//
	//if(trFunct.IsValid())
	//{
		//strFuncName = trFunct.strVal.GetToken(1,'.');
		//strFuncName.MakeLower();
		//if(pGroupName)
			//*pGroupName = trFunct.strVal.GetToken(0,'.');
	//}
	//if(trFunction.GeneralInformation.FunctionPrev)
	//{
		//strFDFname = trFunction.GeneralInformation.FunctionPrev.strVal;
		//strFDFname.MakeLower();
	//}
	//if(strFDFname.IsEmpty() && strFuncName.IsEmpty())
		//return false;
	//
	//return true;
//}
bool nlf_get_func_names(const TreeNode &trFunction, string &strFuncName, string& strFDFname, string* pstrFullpathFileName, string* pGroupName) //=NULL, NULL
{
	strFuncName.Empty();
	strFDFname.Empty();
	
	TreeNode	trFuncName = trFunction.GeneralInformation.FunctionName;
	if ( trFuncName )
	{
		strFuncName = trFuncName.strVal;
	}
	else
	{
		ASSERT(false);
		return false;
	}
	
	string	strFullPath;
	trFunction.GetAttribute(STR_FILENAME_ATTRIB, strFullPath);
	if ( pstrFullpathFileName )
		*pstrFullpathFileName = strFullPath;
		
	strFDFname = GetFileName(strFullPath, true);
	
	if ( pGroupName )
	{
		TreeNode trFunctionSource = trFunction.GeneralInformation.FunctionSource;
		if ( trFunctionSource )
			*pGroupName = trFunctionSource.strVal.GetToken(0, '.');
	}
	
	return !(strFDFname.IsEmpty() && strFuncName.IsEmpty());
}
///------ End FAILS_TO_EDIT_PARAM_SETTINGS_OF_USER_DEFINED_FDF_IN_FO

bool nlf_get_preview_image(TreeNode &trPicts, const string& strFDFname, const string &strFuncName, bool bFormula)
{
	string strGroupFile = "fgroup";
	if(bFormula)
		strGroupFile += ".oqs";
	else
		strGroupFile += ".ocs";
	string 		strPackedPictName = GetAppPath(TRUE) + strGroupFile;
	///Jasmine 12/25/07 QA80-9853 USE_SHORTER_FDF_PREVIEW_NAME
	string strRenameFDFname = strFDFname;
	if(0 == strFuncName.CompareNoCase("Gaussian_LorenCross"))
		strRenameFDFname = "GaussLoren";
	string strRenameFuncname = strFuncName;
	if(0 == strFuncName.CompareNoCase("Gaussian_LorenCross"))
		strRenameFuncname =  "GaussLoren";
	HMETAFILE hmf = NULL;
	RECT16 rect;
	if(!strFDFname.IsEmpty())
		//hmf = get_packed_metafile(strPackedPictName, strFDFname, &rect);
		hmf = get_packed_metafile(strPackedPictName, strRenameFDFname, &rect);
	if(NULL == hmf)
		//hmf = get_packed_metafile(strPackedPictName, strFuncName, &rect);
		hmf = get_packed_metafile(strPackedPictName, strRenameFuncname, &rect);
	///End USE_SHORTER_FDF_PREVIEW_NAME
	if(NULL == hmf)
		return false;
	
	PictureHolder pictHold;
	if(!pictHold.CreateFromMetafile( hmf, rect.right - rect.left, rect.bottom - rect.top , true))
		return false;
	/*
	if( rect.right < 9000 && rect.bottom < 2500)
	{
		if(NULL == hmf || !pictHold.CreateFromMetafile(hmf, 9000,2500, true))//rect.right, rect.bottom, TRUE))
			return false;
	}
	else
		if( rect.right < 12000 && rect.bottom < 3000)
		{
			if(NULL == hmf || !pictHold.CreateFromMetafile(hmf, 12000,3000, true))//rect.right, rect.bottom, TRUE))
				return false;
		}
		else
		{
			if(NULL == hmf || !pictHold.CreateFromMetafile(hmf, 15000, 4000, TRUE))//14000,4000, true))//
				return false;
		}
	*/
	// if we get this far, then things are looking good
	trPicts.pict =  pictHold;
	if(!trPicts.IsValid())
		return false;
	return true;
}

//#define NLSF_INI_LOCATION "NLSF.ini", TRUE			///DG NLF_CLEAN_VISIT_INIFILE
#define GET_USER_FOLDER						GetAppPath(0)
#define GET_SYSTEM_FOLDER					GetAppPath(1)

///Frank 12/29/04 FUNCTION_OPERATOR_INI_AND_FDF

bool nlf_set_section_keys_and_values(LPCSTR lpcszSection, const vector<string> &saKeys, const vector<string> &saValues ,int* pnDefaultSel, int nIniPath)//= NULL, ORIGIN_PATH_USER
{
	if(saKeys.GetSize() != saValues.GetSize())
		return false;
	
	string strNlfPath = nlf_get_ini_filepath(nIniPath);
	INIFile iniNLSF(strNlfPath);	
	
	for(int ii=0; ii<saKeys.GetSize(); ii++)
		iniNLSF.WriteString(lpcszSection, saKeys[ii], saValues[ii]);
	
	if(pnDefaultSel && *pnDefaultSel<saKeys.GetSize())
		iniNLSF.WriteString(lpcszSection, "Default Function", saKeys[*pnDefaultSel]);
	
	return true;
}


// lpcszFunc has not path prefix
// nFolderLocation < 0 to search all
///End NLF_GET_FUNCTION_DETAIL	


//#define FDF_FILE_FOLDER						"fitfunc"


//---- end NLFIT_NOT_WORKING_NEED_CLEAN_UP



//-------- end CPY 10/8/04 QA70-4387 CENTRALIZE_NLF_TO_GETN_BASED_CODES




///end NLF_CLEAN_VISIT_INIFILE

///-----Frank 11/25/05 MOVE_FDFTREE_RELATE_TO_ANALYSIS_ULTIS
bool nlf_init_math_equ_fonts()
{
	string strPath = GetAppPath(TRUE);	  // need to use system (installed) path
	return nlsf_init_math_equ_fonts(strPath);
}
///-----End MOVE_FDFTREE_RELATE_TO_ANALYSIS_ULTIS

//---------------------------------------------------------------------
//------------------ end CPY 12/10/05 MOVE_NLF_FUNC_FROM_ANALYSIS_UTILS
//---------------------------------------------------------------------

bool nlf_load_simulate_settings(LPCSTR lpcszFuncName,vector& vParamVals, TreeNode* ptrSettings)
{
	if(nlf_load_simulate_settings(lpcszFuncName, ptrSettings))
	{
		vector<int> vnIDs;
		vector<string> vsValues;
		if( !tree_get_values_with_ids(*ptrSettings, vnIDs, vsValues) )		
			return false;
		vector<uint> vnIndexs;
		for( int n = IDE_SIMULATE_PARA_BEGIN; vnIDs.Find(vnIndexs, n) > 0;n++)
			vsValues.Add(atof(vsValues[vnIndexs[0]]));

		return true;
	}
	return false;
}
bool nlf_load_simulate_settings(LPCSTR lpcszFuncName,TreeNode* ptrSettings)
{
	Tree tr;
	//string strTempFile = THEME_TEMP_FILE;
	if(_nlsf_load_settings_from_files(lpcszFuncName, tr))
	//	if(tr.Save(strTempFile) && theme_load_settings(*ptrSettings, strTempFile))
	{
		*ptrSettings = tr;
		return true;
	}
	return false;
}
static bool _nlsf_load_settings_from_files(LPCSTR lpcszFuncName, TreeNode &trSource, TreeNode *ptrSettings = NULL, bool bAddIfNoExist = false)
{
	string strUserFile = USER_SIMULATE_FILE, strSysFile = SYS_SIMULATE_FILE;
	Tree trSettings;
	bool bFind=false;
	if(strUserFile.IsFile() && trSettings.Load(strUserFile) )
	{
		trSource=trSettings.GetNode(lpcszFuncName, false); //load user last setting first
		if(!trSource.IsEmpty())
			bFind = true;
	}
	else if(strSysFile.IsFile() && trSettings.Load(strSysFile)) //Third, load from system settings
		{
			trSource=trSettings.GetNode(lpcszFuncName, false); //load user last setting first
			if(trSource.IsValid() && !trSource.IsEmpty())
				bFind = true;
		}
	if(ptrSettings)
	{
		if(!bFind && bAddIfNoExist)
			trSettings.AddNode(lpcszFuncName);
		
		*ptrSettings = trSettings;
	}
	return bFind;
}
bool nlf_save_simulate_settings(LPCSTR lpcszFuncName, const TreeNode& trSettings)
{
	TreeNode trNode;
	Tree	tr;
	if(_nlsf_load_settings_from_files(lpcszFuncName, trNode, &tr, true))
	{
		//create_theme_tree_from_gui_tree(trSettings, trNode);
		tr.Save(USER_SIMULATE_FILE);
	}	
	return true;
}
void create_theme_tree_from_gui_tree(TreeNode &trGUI, TreeNode &trThemeNode)
{
	Tree trTheme;
	trTheme = trGUI.Clone();
	string strTempFile = THEME_TEMP_FILE;
	if(theme_save_settings(trTheme, strTempFile, true))
		trTheme.Load(strTempFile);

	bool bRet = trThemeNode.Replace( trTheme, true, true);
}

//------ Folger 04/02/08 QA80-11364 IMRPOVE_PA_FIT_BY_STORE_FIT_FUNCTION_TREE_FOR_LOOP
bool nlsf_init(TreeNode &trFF, vector& vX, vector& vY, vector<string>& vstrParams, vector& vParams)
{
	NumericFunction nf(trFF);
	int numParams = trFF.GeneralInformation.NumberOfParameters.nVal;
	ASSERT(numParams > 0); // CPY 4/9/08
	vParams.SetSize(numParams);
	
	///Jasmine 04/22/08 CENTRAILIZE_GET_NLSF_GET_PARAM_NAMES_CODES
	/*//Sandy 11/30/05 MODIFY_NLSF_INIT_TO_GET_PARAM_NAME
	vstrParams.SetSize(numParams);
	string strNames=trFF.FittingParameters.Names.strVal;
	strNames.GetTokens(vstrParams, ',');
	
	//Sandy 12/01/05 ADD_TRIM_SPACE_FROM_PARAM_NAME
	for(int ii=0; ii< numParams; ii++)
	{
		vstrParams[ii].TrimLeft();
		vstrParams[ii].TrimRight();
	}*/
	int nRet = nlsf_get_fit_param_names(trFF, vstrParams);
	if( -1 == nRet )
		return nRet;
	ASSERT(nRet == numParams);
	///End CENTRAILIZE_GET_NLSF_GET_PARAM_NAMES_CODES
	
	int nErr;	
//	return nf.ParamInit(vParams, vX, vY, nErr) && 0 != nErr;
	return nf.ParamInit(vParams, vX, vY, nErr) && 0 == nErr;
}
//------ End IMRPOVE_PA_FIT_BY_STORE_FIT_FUNCTION_TREE_FOR_LOOP

///Leo 2005-12-9 MOVED_FROM_PFM_UTILS

bool nlsf_init(string strFuncFDFName, vector& vX, vector& vY, vector<string>& vstrParams, vector& vParams)
{
	Tree trFF;
	//------ CPY 4/3/08 PA_FIT_CNTRL_OPEN_EMPTY_NO_ERR_MSG
	/*
	///Cheney 2007-6-8 ALLOW_USER_EDIT_LINEAR_CONSTRINTS_WHEN_USE_BUILDIN_FUNC
	//if( !nlsf_FDF_to_tree(GetOriginPath()+"FitFunc\\"+strFuncFDFName+".FDF", &trFF ))
	///---Sim 03-17-2008 FIX_CHECK_NLFIT_PDF_FILE_EXTENSION
	//if( !nlsf_load_FDF_to_tree(GetOriginPath()+"FitFunc\\"+strFuncFDFName+".FDF", &trFF, FDFT_CONVERT_BOOL_TO_01, true ))
	string strFile = strFuncFDFName;
	add_file_extension(strFile, STR_FIT_FUNCTION_FILE_EXT);
	strFile = GetOriginPath()+ "FitFunc\\" + strFile;
	if( !nlsf_load_FDF_to_tree(strFile, &trFF, FDFT_CONVERT_BOOL_TO_01, true ))
	///---END FIX_CHECK_NLFIT_PDF_FILE_EXTENSION
	///end ALLOW_USER_EDIT_LINEAR_CONSTRINTS_WHEN_USE_BUILDIN_FUNC
		return false;
	*/
	if(!nlsf_load_fdf_tree(trFF, strFuncFDFName))
		return false;
	//----- end PA_FIT_CNTRL_OPEN_EMPTY_NO_ERR_MSG
	
	//------ Folger 04/02/08 QA80-11364 IMRPOVE_PA_FIT_BY_STORE_FIT_FUNCTION_TREE_FOR_LOOP
	//NumericFunction nf(trFF);
	//int numParams = trFF.GeneralInformation.NumberOfParameters.nVal;
	//vParams.SetSize(numParams);
	//
	////Sandy 11/30/05 MODIFY_NLSF_INIT_TO_GET_PARAM_NAME
	//vstrParams.SetSize(numParams);
	//string strNames=trFF.FittingParameters.Names.strVal;
	//strNames.GetTokens(vstrParams, ',');
	//
	////Sandy 12/01/05 ADD_TRIM_SPACE_FROM_PARAM_NAME
	//for(int ii=0; ii< numParams; ii++)
	//{
		//vstrParams[ii].TrimLeft();
		//vstrParams[ii].TrimRight();
	//}
	//int nErr;	
////	return nf.ParamInit(vParams, vX, vY, nErr) && 0 != nErr;
	//return nf.ParamInit(vParams, vX, vY, nErr) && 0 == nErr;
	
	return nlsf_init(trFF, vX, vY, vstrParams, vParams);
	//------ End IMRPOVE_PA_FIT_BY_STORE_FIT_FUNCTION_TREE_FOR_LOOP
}

/// Cloud 08/21/2007 SURFACE_INIT
bool nlsf_init(string strFunc, vector& vz, vector& vx, vector& vy, vector<string>& vstrParams, vector& vParams)
{
	Tree trFF;
	//------ CPY 4/3/08 PA_FIT_CNTRL_OPEN_EMPTY_NO_ERR_MSG
	//if( !nlsf_load_FDF_to_tree(GetOriginPath()+"FitFunc\\"+strFunc+".FDF", &trFF, FDFT_CONVERT_BOOL_TO_01, true ))
	if(!nlsf_load_fdf_tree(trFF, strFunc))
	//------
		return false;

	NumericFunction nf(trFF);
	int numParams = trFF.GeneralInformation.NumberOfParameters.nVal;
	
	///Jasmine 04/22/08 CENTRAILIZE_GET_NLSF_GET_PARAM_NAMES_CODES
	/*vstrParams.SetSize(numParams);
	string strNames=trFF.FittingParameters.Names.strVal;
	strNames.GetTokens(vstrParams, ',');
	
	for(int ii=0; ii< numParams; ii++)
	{
		vstrParams[ii].TrimLeft();
		vstrParams[ii].TrimRight();
	}*/	
	int nRet = nlsf_get_fit_param_names(trFF, vstrParams);
	if( -1 == nRet )
		return nRet;
	ASSERT(nRet == numParams);
	///End CENTRAILIZE_GET_NLSF_GET_PARAM_NAMES_CODES

	int nErr;
	//return nf.ParamInit(vParams, vx, vy, vz, nErr) && 0 != nErr;
	return nf.ParamInit(vParams, vx, vy, vz, nErr) && 0 == nErr;
}

bool nlsf_init(string strFunc, double dxmin, double dxmax, double dymin, double dymax, const matrix& mz, vector<string>& vstrParams, vector& vParams)
{
	Tree trFF;
	//------ CPY 4/3/08 PA_FIT_CNTRL_OPEN_EMPTY_NO_ERR_MSG
	//if( !nlsf_load_FDF_to_tree(GetOriginPath()+"FitFunc\\"+strFunc+".FDF", &trFF, FDFT_CONVERT_BOOL_TO_01, true ))
	if(!nlsf_load_fdf_tree(trFF, strFunc))
	//------
		return false;

	NumericFunction nf(trFF);
	int numParams = trFF.GeneralInformation.NumberOfParameters.nVal;
	
	///Jasmine 04/22/08 CENTRAILIZE_GET_NLSF_GET_PARAM_NAMES_CODES
	/*vstrParams.SetSize(numParams);
	string strNames=trFF.FittingParameters.Names.strVal;
	strNames.GetTokens(vstrParams, ',');
	
	for(int ii=0; ii< numParams; ii++)
	{
		vstrParams[ii].TrimLeft();
		vstrParams[ii].TrimRight();
	}*/
	int nRet = nlsf_get_fit_param_names(trFF, vstrParams);
	if( -1 == nRet )
		return nRet;
	ASSERT(nRet == numParams);
	///End CENTRAILIZE_GET_NLSF_GET_PARAM_NAMES_CODES

	int nCols = mz.GetNumCols();
	int nRows = mz.GetNumRows();
	vector vx(nCols*nRows);
	vector vy(nCols*nRows);
	vector vz(nCols*nRows);
	ocmath_mat_to_regular_xyz(mz, nRows, nCols, dxmin, dxmax, dymin, dymax, vx, vy, vz, true);
	int nErr;
	//return nf.ParamInit(vParams, vx, vy, vz, nErr) && 0 != nErr;
	return nf.ParamInit(vParams, vx, vy, vz, nErr) && 0 == nErr;
}
/// End SURFACE_INIT

bool nlsf_fit(string strFuncName, vector& vX, vector& vY, vector& vParams, vector<bool>& vbFixed, RegStats* psRegStats, int nReplicas) //=0
{
	int nRet;
	
	Tree trFF;
//------ CPY 4/3/08 PA_FIT_CNTRL_OPEN_EMPTY_NO_ERR_MSG
//	///Cheney 2007-6-8 ALLOW_USER_EDIT_LINEAR_CONSTRINTS_WHEN_USE_BUILDIN_FUNC
//	//if( !nlsf_FDF_to_tree(GetOriginPath()+"FitFunc\\"+strFuncName+".FDF", &trFF ))
//	if( !nlsf_load_FDF_to_tree(GetOriginPath()+"FitFunc\\"+strFuncName+".FDF", &trFF, FDFT_CONVERT_BOOL_TO_01, true ))
//	///end 	ALLOW_USER_EDIT_LINEAR_CONSTRINTS_WHEN_USE_BUILDIN_FUNC
	if(!nlsf_load_fdf_tree(trFF, strFuncName))
//------
		return false;

	NLSFONEDATA stDep, stIndep;
	stDep.pdData = vY;
	stDep.nSize = vY.GetSize();
	stIndep.pdData = vX;
	stIndep.nSize = vX.GetSize();
	
	int numParams = trFF.GeneralInformation.NumberOfParameters.nVal;
	vParams.SetSize(numParams);
	vbFixed.SetSize(numParams);
	
	NLFit fit;
	///Leo 2005-12-9 NEED_TO_SUPPORT_REPLICAS
	//	nRet = fit.SetFunction(trFF);
	nRet = fit.SetFunction(trFF, nReplicas + 1);
	if ( 0 >= nRet )
	{
		throw(SETDATA_FAILED);
	}
	nRet = fit.SetData(1, &stDep, &stIndep);
	if ( 0 != nRet )
	{
		throw(SETDATA_FAILED);
	}
	nRet = fit.SetParams(vParams.GetSize(), vParams, NULL, vbFixed);
	if ( 0 != nRet )
	{
		throw(INVALID_PARAMETER_SETTING);
	}
	nRet = fit.Fit(MAX_NUM_ITERATIONS);
	if(0 != nRet)
	{
		//Sandy 01/12/05 REPORT_FITTING_RESULT_TO_SELECT_PARAMETERS
		//throw(FAIL_TO_PERFORM_FITTING);
		return false;
	}
	nRet = fit.GetParameterResults(&vParams);
	if(0 != nRet)
	{
		throw(FAIL_TO_GET_PARAMETER_RESULT);
	}
	nRet = fit.GetSummaryFitResults(psRegStats, NULL); //sNLSFFitInfo
	if(0 != nRet)
	{
		throw(FAIL_TO_FIT_GETSUMMARYFITRESULT);
	}
	return true;
}

///Cheney 2007-4-24 CLEAN_UP_FDF_TREE_LOAD
bool nlsf_evaluate(TreeNode& trFF, vector& vX, vector& vY, vector& vParams, vector& vZ)
{
	///Arvin 1/04/06 FIND_Z_FROM_XY
	//vY.SetSize(vX.GetSize());
	//NumericFunction	nf(trFF);
	//return nf.Evaluate(vParams, vY, vX, NULL, vX.GetSize());
	NumericFunction	nf(trFF);
	if(vZ)
	{
		if(vX.GetSize() != vY.GetSize())
			return false;
		
		vZ.SetSize(vX.GetSize());
		return nf.Evaluate(vParams, vZ, vX, vY, vX.GetSize());	
	}
	else
	{
		vY.SetSize(vX.GetSize());
		return nf.Evaluate(vParams, vY, vX, NULL, vX.GetSize());
	}
}
///end CLEAN_UP_FDF_TREE_LOAD

///Arvin 1/04/06 FIND_Z_FROM_XY
//bool nlsf_evaluate(string strFunction, string strCategory, vector& vX, vector& vY, vector& vParams)
//bool nlsf_evaluate(string strFunction, string strCategory, vector& vX, vector& vY, vector& vParams, vector& vZ)
bool nlsf_evaluate(LPCSTR lpcszFunction, LPCSTR lpcszCategory, vector& vX, vector& vY, vector& vParams, vector& vZ)
///------
{
	Tree trFF;
	/*
	if( !nlsf_FDF_to_tree( GetAppPath(true)+"FitFunc\\"+strFDF+".FDF", &trFF ) ||
		!nlsf_FDF_to_tree( GetAppPath(false)+"FitFunc\\"+strFDF+".FDF", &trFF ))
	{
		return false;
	}
	*/
//------ CPY 4/3/08 PA_FIT_CNTRL_OPEN_EMPTY_NO_ERR_MSG
//	string strFullPath;
//	nlf_get_fdf_filename(strFunction, &strCategory, NULL, &strFullPath);
//	///Cheney 2007-6-8 ALLOW_USER_EDIT_LINEAR_CONSTRINTS_WHEN_USE_BUILDIN_FUNC
//	//if( !nlsf_FDF_to_tree( strFullPath, &trFF ))
//	if( !nlsf_load_FDF_to_tree( strFullPath, &trFF, FDFT_CONVERT_BOOL_TO_01, true ))
//	///end ALLOW_USER_EDIT_LINEAR_CONSTRINTS_WHEN_USE_BUILDIN_FUNC
//	{
//		printf("Fail to convert FDF to tree!\n");
//		return false;
//	}
	//if(!nlsf_load_fdf_tree(trFF, strFunction, strCategory))
	if(!nlsf_load_fdf_tree(trFF, lpcszFunction, lpcszCategory))
		return false;
//------
	///Cheney 2007-4-24 CLEAN_UP_FDF_TREE_LOAD
	/////Arvin 1/04/06 FIND_Z_FROM_XY
	////vY.SetSize(vX.GetSize());
	////NumericFunction	nf(trFF);
	////return nf.Evaluate(vParams, vY, vX, NULL, vX.GetSize());
	//NumericFunction	nf(trFF);
	//if(vZ)
	//{
		//if(vX.GetSize() != vY.GetSize())
			//return false;
		//
		//vZ.SetSize(vX.GetSize());
		//return nf.Evaluate(vParams, vZ, vX, vY, vX.GetSize());	
	//}
	//else
	//{
		//vY.SetSize(vX.GetSize());
		//return nf.Evaluate(vParams, vY, vX, NULL, vX.GetSize());
	//}
	return nlsf_evaluate(trFF, vX, vY, vParams, vZ);
	///end CLEAN_UP_FDF_TREE_LOAD
}

///Arvin 11/14/07 JUST_MOVE_FUNCTION_FROM_NUMFUNCTIONORGANIZER_TO_NLSF_UTILS
/// Kenny 11/11/2009 QA81-14624 SUPPORT_DRAG_AND_DROP_MULTIPLE_ORIGIN_FILES
//bool nlf_get_section_keys_and_values(LPCSTR lpcszSection, vector<string> &saKeys, vector<string> &saValues, int* pnDefaultSel, int nIniPath)//=NULL = NULL, 

#define GET_NLSF_INI_FILE(_strNLSFIniFile, _nPathType, _szPath)	\
	if ( _szPath )\
	{\
		_strNLSFIniFile = _szPath;\
		_strNLSFIniFile.TrimRight("\\");\
		_strNLSFIniFile += "\\" + "NLSF.ini";\
	}\
	else\
	{\
		_strNLSFIniFile = nlf_get_ini_filepath(_nPathType);\
	}

bool nlf_get_section_keys_and_values(LPCSTR lpcszSection, 
									 vector<string> &saKeys, 
									 vector<string> &saValues /*= NULL*/, 
									 int* pnDefaultSel /*= NULL*/, 
									 int nIniPath /*= ORIGIN_PATH_USER*/, 
									 LPCSTR lpcszIniPath /*= NULL*/)
/// End QA81-14624 SUPPORT_DRAG_AND_DROP_MULTIPLE_ORIGIN_FILES
{
	int	nDefaultSel = 0;
	saKeys.RemoveAll();
	
	/// Kenny 11/11/2009 QA81-14624 SUPPORT_DRAG_AND_DROP_MULTIPLE_ORIGIN_FILES
	//string strNLSFIniFilePath =nlf_get_ini_filepath(nIniPath);
	string strNLSFIniFilePath;
	GET_NLSF_INI_FILE(strNLSFIniFilePath, nIniPath, lpcszIniPath);
	/// End QA81-14624 SUPPORT_DRAG_AND_DROP_MULTIPLE_ORIGIN_FILES
	//if(!strNLSFIniFilePath.IsFile())
		//return false;
	
	INIFile iniNLSF(strNLSFIniFilePath);// when full path given, no need to worry about 2nd arg
	
	
	int nKeysCount = iniNLSF.GetKeyNames(saKeys, lpcszSection);
	//saValues.SetSize(nKeysCount);
	
	if(saValues != NULL)
	{
		saValues.RemoveAll();
		for(int nIndex = 0 ; nIndex < nKeysCount ; nIndex++)
			saValues.Add( iniNLSF.ReadString(lpcszSection, saKeys[nIndex]));
	}
	
	//if(pnDefaultSel != NULL )				///Kyle 12/01/2009 SHOULD_ALWAYS_REMOVE_DEFAULT_FUNCTION_FROM_THE_LIST
	{
		int nDefaIndex = saKeys.Find("Default Function" , 0 , true);
		if(nDefaIndex < 0 )
		{
			nDefaultSel = 0;
		}
		else
		{
			string strDefFunction;
			//strDefFunction = iniNLSF.ReadString( strSection , vsSectionkeys[ nDefaIndex ] );
			strDefFunction = saValues[nDefaIndex];
			saKeys.RemoveAt( nDefaIndex , 1);
			saValues.RemoveAt( nDefaIndex , 1);
			nDefaultSel = saKeys.Find( strDefFunction , 0 , true );
		}
		if(pnDefaultSel != NULL)		///Kyle 12/01/2009 SHOULD_ALWAYS_REMOVE_DEFAULT_FUNCTION_FROM_THE_LIST
			*pnDefaultSel = nDefaultSel;
	}
	return true;
}
///END JUST_MOVE_FUNCTION_TO_NLSF_UTILS

///Jasmine 02/17/09 QA80-10378 SHARE_FUNCTION_ORGANIZER_CODE_WITH_SELECTCAT
/// Kenny 11/11/2009 QA81-14624 SUPPORT_DRAG_AND_DROP_MULTIPLE_ORIGIN_FILES
// int nlsf_get_category_list(vector<string>& vsCategorys)
// {
// 	vector<string> vsShareCategorys;
// 	nlf_get_section_keys_and_values(STR_NODE_CATEGORY, vsCategorys, NULL, NULL, USER_FOLDER );
// 	nlf_get_section_keys_and_values(STR_NODE_CATEGORY, vsShareCategorys, NULL, NULL, ALL_USER_FOLDER );
// 	
// 	for(int ii=0; ii<vsShareCategorys.GetSize(); ii++)
// 	{
// 		if(-1 == vsCategorys.Find(vsShareCategorys[ii]))
// 			vsCategorys.Add(vsShareCategorys[ii]);
// 	}
// 	return vsCategorys.GetSize();
// }

int nlsf_get_category_list(vector<string>& vsCategorys, vector<int>& vnSeparatorIndices /*= NULL*/)
{
	vector<string> vsShareCategorys, vsCateValues, vsShareCateValues;
	nlf_get_section_keys_and_values(STR_NODE_CATEGORY, vsCategorys, vsCateValues, NULL, USER_FOLDER );
	nlf_get_section_keys_and_values(STR_NODE_CATEGORY, vsShareCategorys, vsShareCateValues, NULL, ALL_USER_FOLDER );
	
	ASSERT(vsCategorys.GetSize() == vsCateValues.GetSize());
	ASSERT(vsShareCategorys.GetSize() == vsShareCateValues.GetSize());

	///Jasmine 06/10/10 ORG-263-P1 REMOVE_CATEGORY_SEPARATOR_FOR_IT_IS_SELECTABLE_IN_COMBO
	/*if ( vnSeparatorIndices )
	{
		for (int ii = 0; ii < vsCateValues.GetSize(); ++ii)
		{
			if ( vsCateValues[ii].CompareNoCase("separator") == 0 )
			{
				vnSeparatorIndices.Add(ii);
			}
		}
	}

	for(int ii = 0; ii < vsShareCategorys.GetSize(); ++ii)
	{
		if( vsCategorys.Find(vsShareCategorys[ii]) < 0 )
		{
			int nIndex = vsCategorys.Add(vsShareCategorys[ii]);
			if ( vnSeparatorIndices && vsShareCategorys[ii].CompareNoCase("separator") == 0 )
			{
				vnSeparatorIndices.Add(nIndex);
			}
		}
	}*/
	for (int ii = vsCateValues.GetSize()-1; ii >= 0; ii--)
	{
		if ( vsCateValues[ii].CompareNoCase("separator") == 0 )
		{
			vsCategorys.RemoveAt(ii);
		}
	}

	for(ii = 0; ii < vsShareCategorys.GetSize(); ++ii)
	{
		if( vsCategorys.Find(vsShareCategorys[ii]) < 0 && vsShareCateValues[ii].CompareNoCase("separator") != 0)
	}
	///End REMOVE_CATEGORY_SEPARATOR_FOR_IT_IS_SELECTABLE_IN_COMBO
	return vsCategorys.GetSize();
}

bool nlsf_update_function(LPCSTR lpcszCategoryName, 
						  LPCSTR lpcszNewName, 
						  LPCSTR lpcszOldName, 
						  LPCSTR lpcszFileName, 
						  int nIniPath /*= ORIGIN_PATH_USER*/, 
						  LPCSTR lpcszIniPath /*= NULL*/)
{
	BOOL bUseIniType2GetPath = NULL == lpcszIniPath;
	string strNLSFIniFilePath, strOldName(lpcszOldName), strNewName(lpcszNewName);
	string strFileName = bUseIniType2GetPath && UNDEF_FOLDER == nIniPath ? lpcszFileName : GetFileName(lpcszFileName, true);

	GET_NLSF_INI_FILE(strNLSFIniFilePath, nIniPath, lpcszIniPath);

	BOOL bUseIniPath = !bUseIniType2GetPath || USER_FOLDER == nIniPath;
	INIFile iniNLSF(strNLSFIniFilePath, bUseIniPath);

	bool bRet = true;
	if(!strOldName.IsEmpty())
		bRet &= update_ini_line(iniNLSF, lpcszCategoryName, strOldName, NULL);
	if(bRet && !strNewName.IsEmpty())
		bRet &= update_ini_line(iniNLSF, lpcszCategoryName, strNewName, strFileName);
	return bRet;
}

bool nlsf_update_category(LPCSTR lpcszNewName, 
						  LPCSTR lpcszOldName, 
						  int nIniPath /*= ORIGIN_PATH_USER*/, 
						  LPCSTR lpcszIniPath /*= NULL*/)
{
	string strNLSFIniFilePath, strOldName(lpcszOldName), strNewName(lpcszNewName);

	GET_NLSF_INI_FILE(strNLSFIniFilePath, nIniPath, lpcszIniPath);

	INIFile iniNLSF(strNLSFIniFilePath);

	vector<string> vsKeys, vsValues, vsCKeys, vsCValues;
	int nPos;
	bool bRet=true;
	if(!strOldName.IsEmpty() && !strNewName.IsEmpty())
	{
		bRet &= nlf_get_section_keys_and_values(strOldName, vsKeys, vsValues, NULL, nIniPath, lpcszIniPath);
		bRet &= nlf_get_section_keys_and_values(STR_NODE_CATEGORY, vsCKeys, vsCValues, NULL, nIniPath, lpcszIniPath);
	}

	if(!strOldName.IsEmpty())
	{
		bRet &= update_ini_line(iniNLSF, STR_NODE_CATEGORY, strOldName, NULL);	//delete old category in category list
		if(!strNewName.IsEmpty())
			bRet &= update_ini_line(iniNLSF, STR_NODE_CATEGORY, NULL, NULL);//delete the whole old category list 
		if(bRet)
			bRet &= update_ini_line(iniNLSF, strOldName, NULL, NULL);	//delete old category and the functions
		nPos = vsCKeys.Find(strOldName);
	}

	if(!strNewName.IsEmpty())
	{
		for(int nIndex =0 ;nIndex <  vsKeys.GetSize(); nIndex++)
			bRet &= update_ini_line(iniNLSF, strNewName, vsKeys[nIndex], vsValues[nIndex]);
		if(strOldName.IsEmpty())
			update_ini_line(iniNLSF, STR_NODE_CATEGORY, strNewName, STR_FDF_FILE_FOLDER);
		else
		{
			if(nPos > -1 && nPos < vsCKeys.GetSize())
				vsCKeys[nPos] = strNewName;
			for(nIndex =0 ;nIndex <  vsCKeys.GetSize(); nIndex++)
				bRet &= update_ini_line(iniNLSF, STR_NODE_CATEGORY, vsCKeys[nIndex], vsCValues[nIndex]);
		}
	}
	return bRet;
}
/// End QA81-14624 SUPPORT_DRAG_AND_DROP_MULTIPLE_ORIGIN_FILES
///End SHARE_FUNCTION_ORGANIZER_CODE_WITH_SELECTCAT

//Sandy 12/05/05 MOVE_FROM_BASELINE_FUNC
//Sandy 12/06/05 ADD_FUNC_NAME_OUTPUT
//bool nlsf_get_func_filename(int funcIndex, string& strfuncNames)
bool nlsf_get_func(int funcIndex, string& strfuncName, string& strfileName,  string strCategory)
{
	NLFunctionList nlfl;
	Tree trFunc;
	
	vector<string> vsFileNames;
	vector<string> vsFuncNames;
	//vector<string> vsFunctions;
	string strFile;
	trFunc.SetAttribute(STR_LABEL_ATTRIB, strCategory);
	if(nlfl.GetFunctionList(trFunc))
	{
		tree_get_attributes(trFunc, vsFileNames, STR_FILENAME_ATTRIB, true);
		tree_get_attributes(trFunc, vsFuncNames, STR_LABEL_ATTRIB, true);
		//tree_get_attributes(trFunc, vsFunctions, STR_LABEL_ATTRIB, true);
		///Jasmine 04/14/10 QA81-15304 ANNOUNCE_FITTING_FUNC_CHANGE
		//in PA GUI may not update after FO removes a function, so funcIndex may become invalid
		if( funcIndex >= vsFuncNames.GetSize() )
			return false;
		strfuncName = vsFuncNames[funcIndex];
		
		if( funcIndex >= vsFileNames.GetSize() )
			return false;
		///End ANNOUNCE_FITTING_FUNC_CHANGE
		strFile = vsFileNames[funcIndex];
		strFile = GetFileName( strFile );
		//find a standard function to do this work later ---Sandy 01/12/05
		strfileName = strFile.Left(strFile.GetLength()-4);

		return true;
	}
	
	return false;
}

///Sandy add 2007-7-12
bool nlsf_func_to_fdf(const string strCategory, const string strfuncName, string& strfileName,  bool bFullPath)
{
	NLFunctionList nlfl;
	Tree trFunc;
	
	vector<string> vsFileNames;
	vector<string> vsFuncNames;

	string strFile;
	trFunc.SetAttribute(STR_LABEL_ATTRIB, strCategory);
	if(nlfl.GetFunctionList(trFunc))
	{
		tree_get_attributes(trFunc, vsFileNames, STR_FILENAME_ATTRIB, true);
		tree_get_attributes(trFunc, vsFuncNames, STR_LABEL_ATTRIB, true);

		int nFound = vsFuncNames.Find(strfuncName);
		if( -1 == nFound)
			return false;
		
		strFile = vsFileNames[nFound];
		
		if(bFullPath)
		{
			strfileName = strFile;
		}
		else
		{
			strFile = GetFileName( strFile );
			strfileName = strFile.Left(strFile.GetLength()-4);
		}

		return true;
	}
	
	return false;
}
//end

bool nslf_get_func_list(vector<string>& vsFuncNames, vector<string>& vsFileNames, string strCategory)
{
	NLFunctionList nlfl;
	Tree trFunc;

	trFunc.SetAttribute(STR_LABEL_ATTRIB, strCategory);
	if(nlfl.GetFunctionList(trFunc))
	{
		vsFuncNames.SetSize(0);
		vsFileNames.SetSize(0);
		tree_get_attributes(trFunc, vsFuncNames, STR_LABEL_ATTRIB, true);
		
		tree_get_attributes(trFunc, vsFileNames, STR_FILENAME_ATTRIB, true);
		
		for(int ii=0; ii<vsFileNames.GetSize(); ii++)
		{
			string strFileNames;
				
			strFileNames = vsFileNames[ii];
			
			strFileNames = GetFileName( strFileNames );
			
			vsFileNames[ii] = strFileNames.Left(strFileNames.GetLength()-4);
		}
			
		return true;
	}
	
	return false;
}

///End MOVED_FROM_PFM_UTILS

///Arvin 10/25/06 NLSF_GET_DEPENDENT_VARIABLE_NUMBER
///Cheney 2007-4-9 CORRECT_LOGIC_OF_CALLING_INIT_BRANCH
//int 	nlf_get_dependent_variable_number(const TreeNode& trFunc);
int 	nlf_get_dependent_variables(const TreeNode& trFunc, vector<string>* pvsDepVarNames)
///end CORRECT_LOGIC_OF_CALLING_INIT_BRANCH
{
	if( !trFunc)
		return -1;
	
	TreeNode trDepVarNum = trFunc.GeneralInformation.NumberOfDependentVariables;
	if( !trDepVarNum)
		return -1;
	
	///Cheney 2007-4-9 CORRECT_LOGIC_OF_CALLING_INIT_BRANCH
	if(pvsDepVarNames != NULL)
	{
		TreeNode trDepVar = trFunc.DependentVariables;
		if(!trDepVar)
			return -1;
		
		foreach(TreeNode trNode in trDepVar.Children)
		{
			pvsDepVarNames->Add(trNode.tagName)
		}
	}
	///end CORRECT_LOGIC_OF_CALLING_INIT_BRANCH
	
	return trDepVarNum.nVal;
}

///Cheney 2007-4-9 CORRECT_LOGIC_OF_CALLING_INIT_BRANCH
//int 	nlf_get_dependent_variable_number(LPCSTR lpcszFuncName);
int 	nlf_get_dependent_variables(LPCSTR lpcszFuncName, vector<string>* pvsDepVarNames)
///end CORRECT_LOGIC_OF_CALLING_INIT_BRANCH
{	
	//------ CPY 4/3/08 PA_FIT_CNTRL_OPEN_EMPTY_NO_ERR_MSG
/*	string 	strFilename;
	nlf_get_fdf_filename(lpcszFuncName, NULL, NULL, &strFilename);
	if( strFilename.IsEmpty() || !strFilename.IsFile() )
		return -1;
	
	Tree tr;
	TreeNode trFunc = tr.AddNode("Func");
	///Cheney 2007-6-8 ALLOW_USER_EDIT_LINEAR_CONSTRINTS_WHEN_USE_BUILDIN_FUNC
	//if( !nlsf_FDF_to_tree(strFilename, &trFunc))
	if( !nlsf_load_FDF_to_tree(strFilename, &trFunc, FDFT_CONVERT_BOOL_TO_01, true))
	///end ALLOW_USER_EDIT_LINEAR_CONSTRINTS_WHEN_USE_BUILDIN_FUNC
		return -1;
*/
	Tree tr;
	TreeNode trFunc = tr.AddNode("Func");
	if(!nlsf_load_fdf_tree(trFunc, lpcszFuncName))
		return false;
	//------ end PA_FIT_CNTRL_OPEN_EMPTY_NO_ERR_MSG
	///Cheney 2007-4-9 CORRECT_LOGIC_OF_CALLING_INIT_BRANCH
	//return nlf_get_dependent_variable_number(trFunc);
	return nlf_get_dependent_variables(trFunc, pvsDepVarNames);
	///end CORRECT_LOGIC_OF_CALLING_INIT_BRANCH
}
///end NLSF_GET_DEPENDENT_VARIABLE_NUMBER

///Iris 12/12/05 MOVE_NLF_TO_UTILS_FILE
///Cheney 2007-4-9 CORRECT_LOGIC_OF_CALLING_INIT_BRANCH
//int 	nlf_get_independent_variable_number(const TreeNode& trFunc)
int 	nlf_get_independent_variables(const TreeNode& trFunc, vector<string>* pvsIndepVarNames)
///end CORRECT_LOGIC_OF_CALLING_INIT_BRANCH
{
	if( !trFunc)
		return -1;
	
	TreeNode trIndepVarNum = trFunc.GeneralInformation.NumberOfIndependentVariables;
	if( !trIndepVarNum)
		return -1;
	
	///Cheney 2007-4-9 CORRECT_LOGIC_OF_CALLING_INIT_BRANCH
	if(pvsIndepVarNames != NULL)
	{
		TreeNode trIndepVar = trFunc.IndependentVariables;
		if(!trIndepVar)
			return -1;
		
		foreach(TreeNode trNode in trIndepVar.Children)
		{
			pvsIndepVarNames->Add(trNode.tagName)
		}
	}
	///end CORRECT_LOGIC_OF_CALLING_INIT_BRANCH
	
	return trIndepVarNum.nVal;
}
/// Iris 6/07/05 NLSF_SUPPORT_XYZ_DATA
///Cheney 2007-4-9 CORRECT_LOGIC_OF_CALLING_INIT_BRANCH
//int 	nlf_get_independent_variable_number(LPCSTR lpcszFuncName)
int 	nlf_get_independent_variables(LPCSTR lpcszFuncName, vector<string>* pvsIndepVarNames)
///end CORRECT_LOGIC_OF_CALLING_INIT_BRANCH
{	
//------ CPY 4/3/08 PA_FIT_CNTRL_OPEN_EMPTY_NO_ERR_MSG
/*	string 	strFilename;
	nlf_get_fdf_filename(lpcszFuncName, NULL, NULL, &strFilename);	
	if( strFilename.IsEmpty() || !strFilename.IsFile() )
		return -1;
	
	Tree tr;
	TreeNode trFunc = tr.AddNode("Func");
	///Cheney 2007-6-8 ALLOW_USER_EDIT_LINEAR_CONSTRINTS_WHEN_USE_BUILDIN_FUNC
	//if( !nlsf_FDF_to_tree(strFilename, &trFunc))
	if( !nlsf_load_FDF_to_tree(strFilename, &trFunc, FDFT_CONVERT_BOOL_TO_01, true))	
	///end ALLOW_USER_EDIT_LINEAR_CONSTRINTS_WHEN_USE_BUILDIN_FUNC
*/
	Tree tr;
	TreeNode trFunc = tr.AddNode("Func");
	if(!nlsf_load_fdf_tree(trFunc, lpcszFuncName))
//------ end PA_FIT_CNTRL_OPEN_EMPTY_NO_ERR_MSG
		return -1;
	
	///Cheney 2007-4-9 CORRECT_LOGIC_OF_CALLING_INIT_BRANCH
	//return nlf_get_independent_variable_number(trFunc);	
	return nlf_get_independent_variables(trFunc, pvsIndepVarNames);	
	///end CORRECT_LOGIC_OF_CALLING_INIT_BRANCH
}
//------ CPY 4/3/08 PA_FIT_CNTRL_OPEN_EMPTY_NO_ERR_MSG
// this looks like not used anymore, should not have been written like this anyway
/*
///Cheney 2007-4-14 IF_NO_THEME_AUTO_INIT_WILL_ACCORDING_TO_FDF
bool nlf_is_auto_init_params(LPCSTR lpcszFuncName, bool& bAutoInit)
{
	string 	strFilename;
	nlf_get_fdf_filename(lpcszFuncName, NULL, NULL, &strFilename);	
	if( strFilename.IsEmpty() || !strFilename.IsFile() )
		return false;
	
	Tree tr;
	TreeNode trFunc = tr.AddNode("Func");
	///Cheney 2007-6-7 SHOULD_USE_FDFT_CONVERT_BOOL_TO_01_WHEN_NODE_VAL_IS_STRING
	//if( !nlsf_FDF_to_tree(strFilename, &trFunc))
	///Cheney 2007-6-8 ALLOW_USER_EDIT_LINEAR_CONSTRINTS_WHEN_USE_BUILDIN_FUNC
	//if( !nlsf_FDF_to_tree(strFilename, &trFunc, FDFT_CONVERT_BOOL_TO_01))
	if( !nlsf_load_FDF_to_tree(strFilename, &trFunc, FDFT_CONVERT_BOOL_TO_01, true))
	///end ALLOW_USER_EDIT_LINEAR_CONSTRINTS_WHEN_USE_BUILDIN_FUNC
	///end SHOULD_USE_FDFT_CONVERT_BOOL_TO_01_WHEN_NODE_VAL_IS_STRING
		return false;
	
	return nlf_is_auto_init_params(trFunc, bAutoInit);	
}
*/

bool nlf_is_auto_init_params(const TreeNode& trFunc, bool& bAutoInit)
{
	if( !trFunc)
		return false;
	
	///Cheney 2007-4-23 USE_WRONG_ENTRY_FOR_AUTO_INIT_CHECK_BOX 
	//as Max's mail
	//1. Compile on Param Change Script is not used anymore, so we can use that 
	//	bit to set "Enable Parameters Initialization" during reading;
	//2. so when reading, if "Enable Parameters Initialization" = 0 but "Compile 
	//	on Param Change Script" = 1, then we also set "Enable Parameters 
	//	Initialization" =1.
	//TreeNode trAutoInit = trFunc.Controls.InitializationScripts;
	//if(!trAutoInit)
		//return false;
		
	//bAutoInit = trAutoInit.strVal.Compare("On") == 0? true : false;
	TreeNode trCompileOnParamChangeScript = trFunc.Controls.CompileOnParamChangeScript;
	TreeNode trEnableParamInit = trFunc.Controls.EnableParametersInitialization;
	
	//build-in func no thoes tow control, just set it as true
	if(!trCompileOnParamChangeScript && !trEnableParamInit)
	{
		bAutoInit = true;
		return true;
	}
	///Jasmine 07/09/07 TEMP_CHANGE_FOR_FDFT_CONVERT_BOOL_TO_01_NOT_WORK_WAIT_HONG_FIX
	bool bCompileOnParamChangeScript;// = !trCompileOnParamChangeScript? false : trCompileOnParamChangeScript.nVal;
	bool bEnableParamInit;// = !trEnableParamInit? false : trEnableParamInit.nVal;
	if(trCompileOnParamChangeScript && (!trCompileOnParamChangeScript.strVal.CompareNoCase("on") || !trCompileOnParamChangeScript.strVal.CompareNoCase("1")))
		bCompileOnParamChangeScript = true;
	if(trEnableParamInit && (!trEnableParamInit.strVal.CompareNoCase("on") || !trEnableParamInit.strVal.CompareNoCase("1")))
		bEnableParamInit = true;
	///End TEMP_CHANGE_FOR_FDFT_CONVERT_BOOL_TO_01_NOT_WORK_WAIT_HONG_FIX
	bAutoInit = bCompileOnParamChangeScript? true : bEnableParamInit;
	///end USE_WRONG_ENTRY_FOR_AUTO_INIT_CHECK_BOX
	return true;
}
///end IF_NO_THEME_AUTO_INIT_WILL_ACCORDING_TO_FDF
//------ CPY 4/3/08 PA_FIT_CNTRL_OPEN_EMPTY_NO_ERR_MSG
// this looks like not used anymore, should not have been written like this anyway
/*
///Cheney 2007-4-19 SHOW_CHECKBOX_FOR_PARAMS_INIT_AND_CONSTRAINTS
bool nlf_is_enable_linear_constraints(LPCSTR lpcszFuncName, bool& bConstraints)
{
	string 	strFilename;
	nlf_get_fdf_filename(lpcszFuncName, NULL, NULL, &strFilename);
	if( strFilename.IsEmpty() || !strFilename.IsFile() )
		return false;
	
	Tree tr;
	TreeNode trFunc = tr.AddNode("Func");
	///Cheney 2007-6-7 SHOULD_USE_FDFT_CONVERT_BOOL_TO_01_WHEN_NODE_VAL_IS_STRING
	//if( !nlsf_FDF_to_tree(strFilename, &trFunc))
	///Cheney 2007-6-8 ALLOW_USER_EDIT_LINEAR_CONSTRINTS_WHEN_USE_BUILDIN_FUNC
	//if( !nlsf_FDF_to_tree(strFilename, &trFunc, FDFT_CONVERT_BOOL_TO_01))
	if( !nlsf_load_FDF_to_tree(strFilename, &trFunc, FDFT_CONVERT_BOOL_TO_01, true))
	///end ALLOW_USER_EDIT_LINEAR_CONSTRINTS_WHEN_USE_BUILDIN_FUNC
	///end SHOULD_USE_FDFT_CONVERT_BOOL_TO_01_WHEN_NODE_VAL_IS_STRING
		return false;
	
	return nlf_is_enable_linear_constraints(trFunc, bConstraints);	
}
*/

bool nlf_is_enable_linear_constraints(const TreeNode& trFunc, bool& bConstraints)
{
	if( !trFunc)
		return false;
	
	TreeNode trConstraints = trFunc.Controls.GeneralLinearConstraints;
	if(!trConstraints)
		return false;
	///Cheney 2007-4-24 CLEAN_UP_FDF_TREE_LOAD	
	//bConstraints = trConstraints.strVal.Compare("On") == 0? true : false;
	bConstraints = trConstraints.nVal;
	///end CLEAN_UP_FDF_TREE_LOAD
	return true;
}
///end SHOW_CHECKBOX_FOR_PARAMS_INIT_AND_CONSTRAINTS

bool nlf_is_3d_function(TreeNode& trOperation)
{
	bool 		bIsXYZData = false;
	
	TreeNode 	trFuncNode = trOperation.GUI.FunctionSelection.FunctionList;
	if(trFuncNode)
		///Cheney 2007-4-9 CORRECT_LOGIC_OF_CALLING_INIT_BRANCH
		//bIsXYZData = (2 == nlf_get_independent_variable_number(trFuncNode.strVal));
		bIsXYZData = (2 == nlf_get_independent_variables(trFuncNode.strVal));
		///end CORRECT_LOGIC_OF_CALLING_INIT_BRANCH

	return bIsXYZData;
}

///--------- Iris 10/13/05 QA70-8015-P16 ADD_REPLICA_NUM_OPTION_FOR_PEAK_FUNC
int nlf_get_duplicate_number(const TreeNode& trFunc)
{
	if( !trFunc )
		return -1;
	
	TreeNode trDuplicateNum = trFunc.Controls.NumberOfDuplicates;
	if( !trDuplicateNum )
		return -1;
	
	double dVal = trDuplicateNum.dVal;
	if( is_missing_value(dVal) )
		return -1;
	
	return (int)dVal;
}
//----------
///End MOVE_NLF_TO_UTILS_FILE

///Leo 2005-12-20 SUPPORT_REPLICA_AND_PARAM_SHARING_GROUP
int nlf_get_duplicate_offset(const TreeNode& trFunc)
{
	if (!trFunc)
	{
		return -1;
	}
	TreeNode trDuplicateOffset = trFunc.Controls.DuplicateOffset;
	if (!trDuplicateOffset)
	{
		return -1;
	}
	return trDuplicateOffset.nVal;
}

int nlf_get_duplicate_unit(const TreeNode& trFunc)
{
	if (!trFunc)
	{
		return -1;
	}
	TreeNode trDuplicateUnit = trFunc.Controls.DuplicateUnit;
	if (!trDuplicateUnit)
	{
		return -1;
	}
	return trDuplicateUnit.nVal;
}
///End SUPPORT_REPLICA_AND_PARAM_SHARING_GROUP


/* CPY 5/23/07 seems not used anymore and causing compile error
///-----Frank 12/19/05 CONVERT_NEW_NLSF_REPORT_TREE_TO_OLD_NLSF_TREE
void init_nlsf_functs_lists(TreeNode &trGetN, vector<string> &vsShowCategory)
{
	NLFitSelFunction nlf(trGetN);
	string strDefaultCate = "Origin Basic Functions";
	if(vsShowCategory && vsShowCategory.GetSize() > 0)
	{
		if(vsShowCategory.Find(strDefaultCate) < 0)
			strDefaultCate = vsShowCategory[0];
		//nlf.Init(strDefaultCate, NULL, NULL , &vsShowCategory);///Jasmine 03/13/06 REPLACE_VECTOR_POINTER_WITH_VECTOR, the pointer leads to strange crash
		nlf.Init(strDefaultCate, NULL, NULL , vsShowCategory);
	}
	else
		nlf.Init(strDefaultCate);	//==>NLFIT_SEL_FUNCTION_INIT
}*/
void update_nlsf_functs_lists(TreeNode &trGetN)
{
	NLFitSelFunction nlf(trGetN);
	nlf.OnChangeCategoryUpdateFunctionList();	
}
bool get_fdf(TreeNode &trGetN, TreeNode &trFF)
{
	NLFitSelFunction nlf(trGetN);
	string strCate, strFunc;
	nlf.GetCategoryAndFunction(strCate, strFunc);	
	return nlf.Load(trFF, strFunc, strCate);		
}
///Kyle 11/11/2008 QA80-12564 CREATE_X_Y_DATA_BASE_ON_GRAPY_SCALE
//void createXYData(Tree trFF, vector& vX, vector& vY, vector& vParams, double dXMin, double dXMax, int nPts)
void createXYData(Tree trFF, vector& vX, vector& vY, vector& vParams, double dXMin, double dXMax, int nPts, int nXScale)
///End CREATE_X_Y_DATA_BASE_ON_GRAPY_SCALE
{
	///Kyle 03/17/2009 QA80-12564-P7 GENERAL_ERROR_MESSAGE_FOR_X_RANGE_ERROR
	if(nPts < 1)
		return;
	///End GENERAL_ERROR_MESSAGE_FOR_X_RANGE_ERROR
	NumericFunction	NF(trFF);
	/// Max 11/11/08 v8.0968c QA70-12564 NEED_TO_HANDLE_BOUNDARY_CASE
	if (1 == nPts || is_equal(dXMax, dXMin))
	{
		vX.SetSize(1);
		vX[0] = dXMin;
	}
	/// END NEED_TO_HANDLE_BOUNDARY_CASE
	///Kyle 11/11/2008 QA80-12564 CREATE_X_Y_DATA_BASE_ON_GRAPY_SCALE
	//vX.Data(dXMin, dXMax, (dXMax - dXMin)/(nPts-1));
	///Kyle 11/17/08 QA80-12591 CORRECT_FORMULA_TO_COMPUTE_X_DATA_FOR_FITTED_CURVE 
	//switch(nXScale)	
	//{
	//case LOG10_SPACE:
		///// Max 11/11/08 v8.0968c QA70-12564 NEED_TO_HANDLE_BOUNDARY_CASE
		//ASSERT(dXMax > 0);
		//ASSERT(dXMin > 0);
		///// ---
		//double dInc = log10(dXMax / dXMin) / (nPts-1);
		//vX.Data(log10(dXMin), log10(dXMax), dInc);
		//vX = 10^vX;
		//break;
	//case LOGE_SPACE:
		///// Max 11/11/08 v8.0968c QA70-12564 NEED_TO_HANDLE_BOUNDARY_CASE
		//ASSERT(dXMax > 0);
		//ASSERT(dXMin > 0);
		///// ---
		//double dInc = ln(dXMax / dXMin) / (nPts-1);
		//vX.Data(ln(dXMin), ln(dXMax), dInc);
		//vX = exp(vX);
		//break;
	//case LOG2_SPACE:
		///// Max 11/11/08 v8.0968c QA70-12564 NEED_TO_HANDLE_BOUNDARY_CASE
		//ASSERT(dXMax > 0);
		//ASSERT(dXMin > 0);
		///// ---
		//double dLog2 = log(2.0);
		//double dInc = log(dXMax / dXMin) / (dLog2 * (nPts-1) );
		//vX.Data(log(dXMin)/dLog2, log(dXMax)/dLog2, dInc);
		//vX = 2^vX;
		//break;
	//default:
		//vX.Data(dXMin, dXMax, (dXMax - dXMin)/(nPts-1));
		//break;
	//}
	///Kyle 03/17/2009 QA80-12564-P7 GENERAL_ERROR_MESSAGE_FOR_X_RANGE_ERROR
	else
	///-----
	{
		double dRMin = real_space(dXMin, nXScale);
		double dRMax = real_space(dXMax, nXScale);
		vX.Data(dRMin, dRMax, (dRMax - dRMin)/(nPts-1));
		vX = real_inv_space(vX, nXScale);
	}
	///End CORRECT_FORMULA_TO_COMPUTE_X_DATA_FOR_FITTED_CURVE
	///End CREATE_X_Y_DATA_BASE_ON_GRAPY_SCALE
	vY = NF.Evaluate(vX, vParams);
}
///-----End  CONVERT_NEW_NLSF_REPORT_TREE_TO_OLD_NLSF_TREE

///Jasmine 02/06/06 GET_PARAMETERS_SETTINGS
//get parameters settings from string into vector

//format of lpcszParaName : "P1, P2"
int nlf_set_param_names_vector(LPCSTR lpcszParaName, vector<string>& vsParamNames)
{
	string strParaName = lpcszParaName;
	if(strParaName.IsEmpty())
		vsParamNames.SetSize(0);
	else
		strParaName.GetTokens(vsParamNames, ',');
	for(int ii = 0; ii < vsParamNames.GetSize(); ii++)
	{
		vsParamNames[ii].TrimLeft();
		vsParamNames[ii].TrimRight();
		if(vsParamNames[ii].IsEmpty())
			vsParamNames.RemoveAt(ii);
	}
	return vsParamNames.GetSize();
}

///Kyle 08/06/2009 QA80-14077 ADD_UNIT_FOR_PARAMETER_SETTINGS
int	nlf_set_param_unit_vector(LPCSTR lpcszParaUnit, vector<string>& vsParamUnits, int nOldSize, bool bResize)// = false
{
	int nNewSize;
	vsParamUnits.SetSize(nOldSize);
	string strParaUnit = lpcszParaUnit;
	if(strParaUnit.IsEmpty() && bResize)
		vsParamUnits.SetSize(0);
	if(!strParaUnit.IsEmpty())
		strParaUnit.GetTokens(vsParamUnits, ',');
	nNewSize = vsParamUnits.GetSize();
	if(!bResize)
	{
		nNewSize = nOldSize;
		vsParamUnits.SetSize(nNewSize);
	}
	for(int ii = 0; ii < nNewSize; ii++)
	{
		vsParamUnits[ii].TrimLeft();
		vsParamUnits[ii].TrimRight();
	}
	return nNewSize;	
}
///End 

///Jasmine 02/14/06 ADD_SET_SIZE
//format of lpcszParaMeaning : "coefficient, power"
int	nlf_set_param_meaning_vector(LPCSTR lpcszParaMeaning, vector<string>& vsParamMeanings, int nOldSize, bool bResize)// = false
{
	int nNewSize;
	vsParamMeanings.SetSize(nOldSize);
	string strParaMeaning = lpcszParaMeaning;
	if(strParaMeaning.IsEmpty() && bResize)
		vsParamMeanings.SetSize(0);
	if(!strParaMeaning.IsEmpty())
		strParaMeaning.GetTokens(vsParamMeanings, ',');
	nNewSize = vsParamMeanings.GetSize();
	if(!bResize)
	{
		nNewSize = nOldSize;
		vsParamMeanings.SetSize(nNewSize);
	}
	for(int ii = 0; ii < nNewSize; ii++)
	{
		vsParamMeanings[ii].TrimLeft();
		vsParamMeanings[ii].TrimRight();
		if(vsParamMeanings[ii].IsEmpty())
			vsParamMeanings[ii] = "?";//default value
	}
	return nNewSize;	
}
///Jasmine 04/02/07 SUPPORT_SIGN_DIGITS
//format of lpcszParaSignDigits : "0,5,0,3"
int	nlf_set_param_significant_digits_vector(LPCSTR lpcszParaSignDigits, vector<int>& vnParamSignDigits, int nOldSize, bool bResize)// = false
{
	int nNewSize;
	vnParamSignDigits.SetSize(nOldSize);
	string strParaSignDigits = lpcszParaSignDigits;
	if(strParaSignDigits.IsEmpty() && bResize)
		vnParamSignDigits.SetSize(0);
	if(!strParaSignDigits.IsEmpty())
	{
		vector<string> vsParamSignDigits;
		strParaSignDigits.GetTokens(vsParamSignDigits, ',');
		nNewSize = vsParamSignDigits.GetSize();
		vnParamSignDigits.SetSize(nNewSize);
		for(int ii = 0; ii < nNewSize; ii++)
		{
			vsParamSignDigits[ii].TrimLeft();
			vsParamSignDigits[ii].TrimRight();
			
			vnParamSignDigits[ii] = 0;//default value, free
			if(!vsParamSignDigits[ii].IsEmpty())
				vnParamSignDigits[ii] = atoi(vsParamSignDigits[ii]);
		}
	}
	if(!bResize)//keep old size
	{
		vnParamSignDigits.SetSize(nOldSize);
		if(nOldSize > nNewSize)
			for(int nn = nNewSize; nn < nOldSize; nn++)
				vnParamSignDigits[nn] = 0;//default value
	}
	return vnParamSignDigits.GetSize();	
}
///End SUPPORT_SIGN_DIGITS
//format of lpcszParaValue : "0.5(V),--(F),(V),10(F)"
int nlf_set_param_fixed_vector(LPCSTR lpcszParaValue, vector<bool>& vbParamFixed, int nOldSize, bool bResize)// = false
{
	int nNewSize;
	vbParamFixed.SetSize(nOldSize);
	string strParaValue = lpcszParaValue;
	if(strParaValue.IsEmpty() && bResize)
		vbParamFixed.SetSize(0);
	if(!strParaValue.IsEmpty())
	{
		vector<string> vsFixed;
		strParaValue.GetTokens(vsFixed, ',');
		nNewSize = vsFixed.GetSize();
		vbParamFixed.SetSize(nNewSize);//avoid index out of range
		for(int ii = 0; ii < nNewSize; ii++)
		{
			vsFixed[ii] = vsFixed[ii].GetToken(1, '(');
			vsFixed[ii] = vsFixed[ii].GetToken(0, ')');
			vsFixed[ii].TrimLeft();
			vsFixed[ii].TrimRight();
			vbParamFixed[ii] = 0;
			if((!vsFixed[ii].IsEmpty())&&(!vsFixed[ii].CompareNoCase("F")))
				vbParamFixed[ii] = 1;
		}
	}
	if(!bResize)//keep size
	{
		vbParamFixed.SetSize(nOldSize);
		if(nOldSize > nNewSize)
			for(int nn = nNewSize; nn < nOldSize; nn++)
				vbParamFixed[nn] = 0;//default value
	}
	return vbParamFixed.GetSize();
}

//format of lpcszParaValue : "0.5(V),--(F),(V),10(F)"
///------ Folger 06/24/10 ORG-390-S1 USE_ONE_IF_NO_PARAM_INIT_VALUE_SPECIFIED
//int nlf_set_param_values_vector(LPCSTR lpcszParaValue, vector& vdParamValues, int nOldSize, bool bResize)// = false
int nlf_set_param_values_vector(LPCSTR lpcszParaValue, vector& vdParamValues, int nOldSize, bool bResize/* = false*/, double rValueOverNANUM/* = NANUM*/)
///------ End USE_ONE_IF_NO_PARAM_INIT_VALUE_SPECIFIED
{
	int nNewSize;
	vdParamValues.SetSize(nOldSize);
	string strParaValue = lpcszParaValue;
	if(strParaValue.IsEmpty() && bResize)
		vdParamValues.SetSize(0);
	if(!strParaValue.IsEmpty())
	{
		vector<string> vsValue;
		strParaValue.GetTokens(vsValue, ',');
		for(int ii = 0; ii < vsValue.GetSize(); ii++)
		{
			vsValue[ii] = vsValue[ii].GetToken(0, '(');
			vsValue[ii].TrimLeft();
			vsValue[ii].TrimRight();
		}
		int iRet = convert_str_vector_to_num_vector(vsValue, vdParamValues);
		nNewSize = vdParamValues.GetSize();
	}
	if(!bResize)//keep size
	{
		vdParamValues.SetSize(nOldSize);
		if(nOldSize > nNewSize)
			for(int nn = nNewSize; nn < nOldSize; nn++)
				vdParamValues[nn] = NANUM;//default value
	}

	///------ Folger 06/24/10 ORG-390-S1 USE_ONE_IF_NO_PARAM_INIT_VALUE_SPECIFIED
	if ( !is_missing_value(rValueOverNANUM) )
	{
		vdParamValues.Replace(NANUM, rValueOverNANUM, MATREPL_TEST_EQUAL);
	}
	///------ End USE_ONE_IF_NO_PARAM_INIT_VALUE_SPECIFIED
	return vdParamValues.GetSize();
}

//format of lpcszParaBound : "0.045(X, OFF),100(X, OFF)"
int	nlf_set_param_bounds_vector(LPCSTR lpcszParaBound, vector& vdParamBounds, int nOldSize, bool bResize)// = false
{
	int nNewSize;
	vdParamBounds.SetSize(nOldSize);
	string strParaBoundList = lpcszParaBound;
	if(strParaBoundList.IsEmpty() && bResize)
		vdParamBounds.SetSize(0);
	if(!strParaBoundList.IsEmpty())
	{
		vector<string> vsBound;
		strParaBoundList.GetTokens(vsBound, ',');
		for(int ii = 0; ii < vsBound.GetSize(); ii++)
		{
			vsBound[ii] = vsBound[ii].GetToken(0, '(');
			vsBound[ii].TrimLeft();
			vsBound[ii].TrimRight();
		}
		int iRet = convert_str_vector_to_num_vector(vsBound,vdParamBounds);
		nNewSize = vdParamBounds.GetSize();
	}
	if(!bResize)//keep size
	{
		vdParamBounds.SetSize(nOldSize);
		if(nOldSize > nNewSize)
			for(int nn = nNewSize; nn < nOldSize; nn++)
				vdParamBounds[nn] = NANUM;//default value
	}
	return vdParamBounds.GetSize();
}

//format of lpcszParaBound : "0.045(X, OFF),100(X, OFF)"
int nlf_set_param_exclusive_vector(LPCSTR lpcszParaBound, vector<bool>& vbParamExclusive, int nOldSize, bool bResize)// = false
{
	int nNewSize;
	vbParamExclusive.SetSize(nOldSize);
	string strParaBoundList = lpcszParaBound;
	if(strParaBoundList.IsEmpty() && bResize)
		vbParamExclusive.SetSize(0);
	if(!strParaBoundList.IsEmpty())
	{
		vector<string> vsExclusive;
		strParaBoundList.GetTokens(vsExclusive, ',');
		nNewSize = vsExclusive.GetSize();
		vbParamExclusive.SetSize(nNewSize);//avoid index out of range
		for(int ii = 0; ii < nNewSize; ii++)
		{
			vsExclusive[ii] = vsExclusive[ii].GetToken(1, '(');
			vsExclusive[ii] = vsExclusive[ii].GetToken(0, ',');
			vsExclusive[ii].TrimLeft();
			vsExclusive[ii].TrimRight();
			vbParamExclusive[ii] = 1;
			if((!vsExclusive[ii].IsEmpty())&&(!vsExclusive[ii].CompareNoCase("I")))
				vbParamExclusive[ii] = 0;
		}
	}
	if(!bResize)//keep size
	{
		vbParamExclusive.SetSize(nOldSize);
		if(nOldSize > nNewSize)
			for(int nn = nNewSize; nn < nOldSize; nn++)
				vbParamExclusive[nn] = 1;//default value
	}
	return vbParamExclusive.GetSize();
}
///End ADD_SET_SIZE

///Jasmine 05/10/06 ENABLE_DISABLE_BOUNDS_SETTING
//format of lpcszParaBound : "0.045(X, OFF),100(X, OFF)"
int nlf_set_param_on_bounds_vector(LPCSTR lpcszParaBound, vector<bool>& vbParamOnBounds, int nOldSize, bool bResize)// = false
{
	int nNewSize;
	vbParamOnBounds.SetSize(nOldSize);
	string strParaBoundList = lpcszParaBound;
	if(strParaBoundList.IsEmpty() && bResize)
		vbParamOnBounds.SetSize(0);
	if(!strParaBoundList.IsEmpty())
	{
		vector<string> vsParamOnBounds;
		strParaBoundList.GetTokens(vsParamOnBounds, ',');
		nNewSize = vsParamOnBounds.GetSize();
		vbParamOnBounds.SetSize(nNewSize);//avoid index out of range
		for(int ii = 0; ii < nNewSize; ii++)
		{
			vsParamOnBounds[ii] = vsParamOnBounds[ii].GetToken(1, '(');
			vsParamOnBounds[ii] = vsParamOnBounds[ii].GetToken(1, ',');
			vsParamOnBounds[ii] = vsParamOnBounds[ii].GetToken(0, ')');
			vsParamOnBounds[ii].TrimLeft();
			vsParamOnBounds[ii].TrimRight();
			vbParamOnBounds[ii] = 0;//default value : OFF, to ignore the bounds setting
			if((!vsParamOnBounds[ii].IsEmpty())&&(!vsParamOnBounds[ii].CompareNoCase("ON")))
				vbParamOnBounds[ii] = 1;
		}
	}
	if(!bResize)//keep size
	{
		vbParamOnBounds.SetSize(nOldSize);
		if(nOldSize > nNewSize)
			for(int nn = nNewSize; nn < nOldSize; nn++)
				vbParamOnBounds[nn] = 0;//default value
	}
	return vbParamOnBounds.GetSize();
}
///End ENABLE_DISABLE_BOUNDS_SETTING

//get parameters settings from vector into string
string nlf_get_param_names_list(const vector<string> vsParamNames)
{
	string strParamName, strName;
	for(int ii = 0; ii < vsParamNames.GetSize(); ii++)
	{
		strName = vsParamNames[ii];
		strName.TrimLeft();
		strName.TrimRight();
		if(!strName.IsEmpty())
			strParamName = strParamName + strName + ",";
	}
	strParamName.Delete(strParamName.GetLength()-1);//remove last ","
	return strParamName;
}

///Kyle 08/06/2009 QA80-14077 ADD_UNIT_FOR_PARAMETER_SETTINGS
string nlf_get_param_unit_list(const vector<string> vsParamUnits)
{
	string strParamUnit, strUnit;
	for(int ii = 0; ii < vsParamUnits.GetSize(); ii++)
	{
		strUnit = vsParamUnits[ii];
		strUnit.TrimLeft();
		strUnit.TrimRight();
		strParamUnit = strParamUnit + strUnit + ",";
	}
	strParamUnit.Delete(strParamUnit.GetLength()-1);//remove last ","
	return strParamUnit;
}
///End ADD_UNIT_FOR_PARAMETER_SETTINGS

string nlf_get_param_meaning_list(const vector<string> vsParamMeanings)
{
	string strParamMeaning, strMeaning;
	for(int ii = 0; ii < vsParamMeanings.GetSize(); ii++)
	{
		strMeaning = vsParamMeanings[ii];
		strMeaning.TrimLeft();
		strMeaning.TrimRight();
		strMeaning = (strMeaning.IsEmpty())? "?": strMeaning;
		strParamMeaning = strParamMeaning + strMeaning + ",";
	}
	strParamMeaning.Delete(strParamMeaning.GetLength()-1);//remove last ","
	return strParamMeaning;
}
///Jasmine 04/02/07 SUPPORT_SIGN_DIGITS
string nlf_get_param_significant_digits_list(const vector<int> vnSignDigites)
{
	string strSignDigites;
	for(int ii = 0; ii < vnSignDigites.GetSize(); ii++)
		strSignDigites += (string)vnSignDigites[ii] + ",";
	strSignDigites.TrimRight(',');//remove last ","
	return strSignDigites;
}
///End SUPPORT_SIGN_DIGITS
string nlf_get_param_value_list(const vector vdParamValues, const vector<bool> vbParamFixed)
{
	string strParamValueList, strValue, strFixed;
	for(int ii = 0; ii < vdParamValues.GetSize() || ii < vbParamFixed.GetSize(); ii++)
	{
		strValue = "--";
		if(ii < vdParamValues.GetSize() && NANUM != vdParamValues[ii])
			///------ Folger 04/03/09 QA80-13408 NUMERIC_SAVED_INTO_FDF_SHOULD_USE_FULL_PRECISION
			//strValue = vdParamValues[ii];
			///Kyle 01/14/2010 QA80-14957 COMMA_IS_USED_AS_SEPARATOR_SO_USE_POINT_AS_DELIMITER_EVEN_IN_GOS
			//strValue = ftoa(vdParamValues[ii], "*15*");
			strValue.Format("%.15g", vdParamValues[ii]);
			///End COMMA_IS_USED_AS_SEPARATOR_SO_USE_POINT_AS_DELIMITER_EVEN_IN_GOS
			///------ End NUMERIC_SAVED_INTO_FDF_SHOULD_USE_FULL_PRECISION
		strFixed = (ii < vbParamFixed.GetSize() && vbParamFixed[ii])? "F" : "V";
		strParamValueList = strParamValueList + strValue + "(" + strFixed + "),";
	}
	strParamValueList.Delete(strParamValueList.GetLength()-1);//remove last ","
	return strParamValueList;
}

string nlf_get_param_bound_list(const vector vdParamBounds, const vector<bool> vbParamExclusive, const vector<bool> vbParamOnOff)
{
	string strParamBoundList, strBound, strExclusive, strOnOff;
	for(int ii = 0; ii < vdParamBounds.GetSize() || ii < vbParamExclusive.GetSize()|| ii < vbParamOnOff.GetSize(); ii++)
	{
		strBound = "--";
		if(ii < vdParamBounds.GetSize() && NANUM != vdParamBounds[ii])
			///------ Folger 04/03/09 QA80-13408 NUMERIC_SAVED_INTO_FDF_SHOULD_USE_FULL_PRECISION
			//strBound = vdParamBounds[ii];
			///Kyle 01/14/2010 QA80-14957 COMMA_IS_USED_AS_SEPARATOR_SO_USE_POINT_AS_DELIMITER_EVEN_IN_GOS
			//strBound = ftoa(vdParamBounds[ii], "*15*");
			strBound.Format("%.15g", vdParamBounds[ii]);
			///End COMMA_IS_USED_AS_SEPARATOR_SO_USE_POINT_AS_DELIMITER_EVEN_IN_GOS
			///------ End NUMERIC_SAVED_INTO_FDF_SHOULD_USE_FULL_PRECISION
		strExclusive = (ii < vbParamExclusive.GetSize() && !vbParamExclusive[ii])? "I" : "X";
		strOnOff = (ii < vbParamOnOff.GetSize() && vbParamOnOff[ii])? "On" : "Off";
		strParamBoundList = strParamBoundList + strBound + "(" + strExclusive + ", " + strOnOff + "),";
	}
	strParamBoundList.Delete(strParamBoundList.GetLength()-1);//remove last ","
	return strParamBoundList;
}
///End GET_PARAMETERS_SETTINGS
///End 
///jasmine 02/11/06 MOVE_TO_NLSF_UTILS
///Jasmine 01/25/06 PARA_SETTING_DLG
//format of combo list : "#0;<|#1;<="
//return a string value of the specified index in ComboList 
string nlf_get_sel_combo_list(LPCSTR lpcszComboList, int index, char cFirstSep, char cSecondSep, LPCSTR lpcszDefault)// = 0,  = '|',  = ';', = "NULL"
{
	string strComboList = lpcszComboList;
	if(strComboList.IsEmpty() || index < 0)
		//return ""; /// Iris 06/09/06 GIVE_DEFAULT_STR_FOR_ERROR_CASE
		return (string)lpcszDefault;
		
	vector<string> vs;
	int nSize = strComboList.GetTokens(vs, cFirstSep);
	index = (index < nSize)?index : (nSize - 1);
	
	/// Iris 4/17/06 FIX_RUNTIME_ERR_FOR_LITTLE_TOKENS_NUM
	if(vs[index].GetNumTokens(cSecondSep) < 2 )
		//return ""; /// Iris 06/09/06 GIVE_DEFAULT_STR_FOR_ERROR_CASE
		return (string)lpcszDefault;
		
	/// End FIX_RUNTIME_ERR_FOR_LITTLE_TOKENS_NUM
	return vs[index].GetToken(1, cSecondSep);;
}
//return the index of the given string value in ComboList
int nlf_get_combo_list_index(LPCSTR lpcszComboList, LPCSTR lpcszItem, char cFirstSep, char cSecondSep)// = '|',  = ';'
{
	string strComboList = lpcszComboList, strItem = lpcszItem;
	if(strComboList.IsEmpty())
		return 0;	
	vector<string> vs;
	int nSize = strComboList.GetTokens(vs, cFirstSep);
	for(int index = 0; index < nSize; index++)
	{
		if( !strItem.CompareNoCase( vs[index].GetToken(1, cSecondSep) ) )
			return index;
	}
	return 0;
}
///End PARA_SETTING_DLG
///End MOVE_TO_NLSF_UTILS

/// Iris 12/24/2008 v8.0990c CLEANUP_NLSF_GET_PARAM_NAMES_CODES
// should not use NLFitSessino here, too complex, should directly access fdf tree to get parameter names
/*
//2006-3-10 Sandy MOVE_FROM_XF
bool nlsf_get_param_names(string strFuncName, vector<string>& vParamNames, string strCategory)
{
	/// Hong 11/04/08 QA80-12526 v8.0965b ADD_BACKWARD_COMPATIABLE
	//NLFitSessionBase fit(false);
	NLFitSession 		fit;
	fit.SetAutoInitParams(false);
	/// end ADD_BACKWARD_COMPATIABLE
	if (!fit.SetFunction(strFuncName, strCategory))
	{
		return false;
	}
	return (0 != fit.GetParamNamesInFunction(vParamNames));
}
*/
int nlsf_get_param_names(LPCSTR lpszFunction, LPCSTR lpcszCategory, vector<string>& vParamNames)
{ 
	Tree trFDF;
	
	///Sophy 1/22/2010 SHOULD_NEVER_PASS_LPCSTR_AS_STRING_REFER
	//nlsf_get_FDF_tree_from_func_name(trFDF, lpszFunction, lpcszCategory);
	string strCateg(lpcszCategory);
	nlsf_get_FDF_tree_from_func_name(trFDF, lpszFunction, strCateg);
	///end SHOULD_NEVER_PASS_LPCSTR_AS_STRING_REFER
	
	return nlsf_get_fit_param_names(trFDF, vParamNames);
}

int nlsf_get_number_of_params(LPCSTR lpszFunction, LPCSTR lpcszCategory)
{
	vector<string> vsParamNames;
	return nlsf_get_param_names(lpszFunction, lpcszCategory, vsParamNames);
}

///end CLEANUP_NLSF_GET_PARAM_NAMES_CODES

//------ CPY 4/3/08 PA_FIT_CNTRL_OPEN_EMPTY_NO_ERR_MSG
// this is a good centralized function but unfortunately it is no longer used
/**/  /// Iris 12/24/2008 v8.0990c CLEANUP_NLSF_GET_PARAM_NAMES_CODES, remove need use this function in pa.

/// Iris 4/13/06 MOVE_NLSF_FUNC_FROM_NLFITSESSION
///Joe 8/16/06 MOVE_NLSF_FUNC_FROM_NLFITSESSION
//bool nlsf_get_FDF_tree_from_func_name(TreeNode &trFDF, LPCSTR lpcszFuncName)
///Cheney 2007-6-7 SHOULD_USE_FDFT_CONVERT_BOOL_TO_01_WHEN_NODE_VAL_IS_STRING
//bool nlsf_get_FDF_tree_from_func_name(TreeNode &trFDF, LPCSTR lpcszFuncName, string& strCategory)
///Cheney 2007-6-8 ALLOW_USER_EDIT_LINEAR_CONSTRINTS_WHEN_USE_BUILDIN_FUNC
//bool nlsf_get_FDF_tree_from_func_name(TreeNode &trFDF, LPCSTR lpcszFuncName, string& strCategory, DWORD dwCtrl)
bool nlsf_get_FDF_tree_from_func_name(TreeNode &trFDF, LPCSTR lpcszFuncName, string& strCategory, DWORD dwCtrl, bool bCustomized)
///end ALLOW_USER_EDIT_LINEAR_CONSTRINTS_WHEN_USE_BUILDIN_FUNC
///end SHOULD_USE_FDFT_CONVERT_BOOL_TO_01_WHEN_NODE_VAL_IS_STRING
///End MOVE_NLSF_FUNC_FROM_NLFITSESSION
{
	string 	strFilename;
	///Joe 8/16/06 MOVE_NLSF_FUNC_FROM_NLFITSESSION
	//nlf_get_fdf_filename(lpcszFuncName, NULL, NULL, &strFilename);
	nlf_get_fdf_filename(lpcszFuncName,&strCategory, NULL, &strFilename);
	///End MOVE_NLSF_FUNC_FROM_NLFITSESSION
	if( strFilename.IsEmpty() || !strFilename.IsFile() )
		return false;
	
	///Cheney 2007-6-7 SHOULD_USE_FDFT_CONVERT_BOOL_TO_01_WHEN_NODE_VAL_IS_STRING
	//if( !nlsf_FDF_to_tree(strFilename, &trFDF))
	///Cheney 2007-6-8 ALLOW_USER_EDIT_LINEAR_CONSTRINTS_WHEN_USE_BUILDIN_FUNC
	//if( !nlsf_FDF_to_tree(strFilename, &trFDF, dwCtrl))
	if( !nlsf_load_FDF_to_tree(strFilename, &trFDF, dwCtrl, bCustomized))
	///end SHOULD_USE_FDFT_CONVERT_BOOL_TO_01_WHEN_NODE_VAL_IS_STRING
		return false;
	return true;
}
/**/  /// Iris 12/24/2008 v8.0990c CLEANUP_NLSF_GET_PARAM_NAMES_CODES

string nlsf_get_param_init_code(const TreeNode &trFDF)
{	
	NLFunctionList  nlFuncList;
	TreeNode trNode = nlFuncList.GetParaInit(trFDF);
	
	if(!trNode)
		return "";
	else
		return trNode.strVal; 
}

string nlsf_get_formula(const TreeNode &trFDF)
{
	NLFunctionList  nlFuncList;
	TreeNode trNode = nlFuncList.GetFormula(trFDF, false, STR_FUNC_SCRIPT);
	
	if(!trNode)
		return "";
	else
		return trNode.strVal;
}

string nlsf_get_before_or_after_fitting_codes(const TreeNode &trFDF, bool bBeforeFitting)
{
	string strNode = bBeforeFitting? STR_INIT_SCRIPT : STR_SCRIPT_AFTER_FITTING;
	
	NLFunctionList  nlFuncList;
	TreeNode trNode = nlFuncList.GetScripts(trFDF, strNode);
	
	if(!trNode)
		return "";
	else
		return trNode.strVal;	
}
///Jasmine 05/08/06
string nlsf_get_constraints_codes(const TreeNode &trFDF)
{
	NLFunctionList  nlFuncList;
	TreeNode trNode = nlFuncList.GetConstraints(trFDF, false, STR_FUNC_SCRIPT);
	
	if(!trNode)
		return "";
	//------ Folger 04/10/08 QA80-11398 FIX_XF_FITPEAKS_BROKEN_BECAUSE_SET_CONSTRAIN_WITH_WHITE_SPACE_ONLY
	//else
		//return trNode.strVal;
	string strTmp = trNode.strVal;
	strTmp.TrimLeft();
	strTmp.TrimRight();
	return strTmp;
	//------
}
///Sophy 10/20/2008 QA80-12406 ADD_DERIVATIVE_PARAM_PAGE_IN_CODE_TAB_OF_NLFIT_DLG
string	nlsf_get_deriv_param_codes( const TreeNode& trFDF )
{
	NLFunctionList  nlFuncList;
	TreeNode trNode = nlFuncList.GetDerivedParams(trFDF);
	
	if(!trNode)
		return "";
	
	string strTmp = "";
	octree_branch_to_key_value_pairs_str( &trNode, &strTmp );
	return strTmp;
}
///end ADD_DERIVATIVE_PARAM_PAGE_IN_CODE_TAB_OF_NLFIT_DLG
///Jasmine 01/27/07 SHOW_FUNC_DESCRIPTION_INSTEAD_OF_FDF_PATH
/*
void 	nlsf_update_show_FDF_filename(TreeNode & trFuncSel, string& strFDF)
{
	NLFitSelFunction funSel(trFuncSel);
	funSel.UpdateShowFDFfilename(strFDF);
}
*/
void 	nlsf_update_show_func_description(TreeNode & trFuncSel, string& strDesc)
{
	NLFitSelFunction funSel(trFuncSel);
	funSel.UpdateShowFuncDescription(strDesc);
}
///End SHOW_FUNC_DESCRIPTION_INSTEAD_OF_FDF_PATH

///Cheney 2007-5-5 FUNC_DESCRIPTION_NOT_WORK
void 	nlsf_update_show_func_path(const TreeNode & trFuncSel, const string& strPath)
{
	NLFitSelFunction funSel(trFuncSel);
	funSel.UpdateShowFuncPath(strPath);
}
///end FUNC_DESCRIPTION_NOT_WORK

///Joe 8/16/06 MOVE_NLSF_FUNC_FROM_NLFITSESSION
string	nlsf_get_formula(const TreeNode& tr, string strSubNode)
{
	string str;
	if(!tr)
		return str;
	TreeNode trN = tr.GetNode(cvt_str_to_tag_name(STR_FUNC_FORMULA), false);
	if(!trN)
		return str;
	TreeNode trSubNode = trN.GetNode(cvt_str_to_tag_name(strSubNode), false);
	if(trSubNode)
		str = trSubNode.strVal;
	return str;
}

string 	nlsf_get_parainit(const TreeNode& tr)
{
	string str;
	if(!tr)
		return str;
	TreeNode trN = tr.GetNode(cvt_str_to_tag_name(STR_FUNC_PARA_INIT), false);
	if(!trN)
		return str;
	TreeNode trSubNode = trN.GetNode("Script", false);
	if(trSubNode)
		str = trSubNode.strVal;
	return str;
}

string	nlsf_get_scripts(const TreeNode& tr, LPCSTR lpcszNode)
{
	string str;
	if(!tr)
		return str;
	TreeNode trN = tr.GetNode(cvt_str_to_tag_name(lpcszNode), false);
	if(!trN)
		return str;
	TreeNode trSubNode = trN.GetNode("Script", false);
	if(trSubNode)
		str = trSubNode.strVal;
	return str;
}

TreeNode 	nlsf_get_parasetting(const TreeNode& tr)
{
	TreeNode trN;
	if(!tr)
		return trN;
	trN = tr.GetNode(cvt_str_to_tag_name(STR_PARAM_SETTING), false);

	if(trN.IsValid())
		trN = trN.GetNode("", false);
	return trN;
}	

TreeNode	nlsf_get_fittingpara(const TreeNode& tr, string strSubNode)
{
	strSubNode = cvt_str_to_tag_name(strSubNode);
	TreeNode trN;
	if(!tr.IsValid())
		return trN;
	
	trN = tr.GetNode(cvt_str_to_tag_name(STR_FUNC_FIT_PARAM), false);
	if(!trN)
		return trN;
	
	trN = trN.GetNode(strSubNode, false);
	return trN;
}
///End MOVE_NLSF_FUNC_FROM_NLFITSESSION

///Jasmine 04/22/08 CENTRAILIZE_GET_NLSF_GET_PARAM_NAMES_CODES
int		nlsf_get_fit_param_names(const TreeNode& trFDF, vector<string>& vstrParams)
{
	TreeNode trNames = nlsf_get_fittingpara(trFDF, STR_FUNC_NAMES);
	
	if(!trNames)
		return -1;
	string 	strNames = trNames.strVal;
	
	int numParams = strNames.GetTokens(vstrParams, ',');	
	for(int ii=0; ii< numParams; ii++)
	{
		vstrParams[ii].TrimLeft();
		vstrParams[ii].TrimRight();
	}
	
	return numParams;
}
///End CENTRAILIZE_GET_NLSF_GET_PARAM_NAMES_CODES

/// End MOVE_NLSF_FUNC_FROM_NLFITSESSION

///Cheney 2007-6-19 ALWAYS_FIND_XY_FROM_CUMULATIVE_FIT_CURVE_IF_PEAK_FIT
static bool _get_params_by_peak_index(int nPeak, int nNumParamsInFunc, vector& vPeakParams, const vector& vParams)
{
	if(vPeakParams.GetSize() != nNumParamsInFunc)
		return false;
	
	vPeakParams[0] = vParams[0]; //first params shared
	
	vector vtemp(nNumParamsInFunc - 1);
	int nNumParamsNotShare = nNumParamsInFunc - 1;
	int nParamBegin = 1 + nPeak * nNumParamsNotShare;
	int nParamEnd = nParamBegin + nNumParamsNotShare - 1;
	vParams.GetSubVector(vtemp, nParamBegin, nParamEnd);
	vPeakParams.SetSubVector(vtemp, 1);
	
	return true;
}

static double _evaluate_for_replica_fit(double dX, const vector& vParams, int nNumParamsInFunc, const NumericFunction& func)
{
	//how to know each center?
	//may be loop to compute by each peak formular
	//then use the lagest val, 
	//I use Gauss to try it, seems result is fine 
	int nPeaks = (vParams.GetSize() - 1) / (nNumParamsInFunc - 1);
	
	double dy = NANUM;
	for(int ii = 0; ii < nPeaks; ii++)
	{
		vector vPeakParams(nNumParamsInFunc);
		_get_params_by_peak_index(ii, nNumParamsInFunc, vPeakParams, vParams);
		double dytemp = func.Evaluate(dX, vPeakParams);
		
		if(dytemp > dy)
			dy = dytemp;
	}
	
	return dy; 
}
///end ALWAYS_FIND_XY_FROM_CUMULATIVE_FIT_CURVE_IF_PEAK_FIT

///Cheney 2006-8-24 ADD_GLOBAL_FUNCTION_FOR_FINDXY
bool compute_y_by_x(LPCSTR LpcszFuncFileName, int nParamsSize, double* pParams, double dX, double *pY)
{
	//------ CPY 4/3/08 PA_FIT_CNTRL_OPEN_EMPTY_NO_ERR_MSG
	/*
	///Cheney 2007-3-22 USE_RIGHT_METHOD_TO_GET_FDF_FILE
	//string	strFile = okutil_get_origin_path(ORIGIN_PATH_SYSTEM, "FitFunc") + LpcszFuncFileName + ".FDF";
	string 	strFile;
	nlf_get_fdf_filename(LpcszFuncFileName, NULL, NULL, &strFile);
	///end USE_RIGHT_METHOD_TO_GET_FDF_FILE
	Tree	trFF;
	///Cheney 2007-6-8 ALLOW_USER_EDIT_LINEAR_CONSTRINTS_WHEN_USE_BUILDIN_FUNC
	//if( !nlsf_FDF_to_tree(strFile, &trFF) )
	if( !nlsf_load_FDF_to_tree(strFile, &trFF, FDFT_CONVERT_BOOL_TO_01, true) )
	///end ALLOW_USER_EDIT_LINEAR_CONSTRINTS_WHEN_USE_BUILDIN_FUNC
	{
		return false;
	}
	*/
	Tree	trFF;
	if(!nlsf_load_fdf_tree(trFF, LpcszFuncFileName))
		return false;
	//------
	
	NumericFunction	func;
	if (!func.SetTree(trFF))
	{
		return false;
	}
	
	vector vParams(nParamsSize);
	memcpy(&vParams, pParams, nParamsSize*sizeof(double));
	
	string strFuncFileName(LpcszFuncFileName);	
	//if not polynomial, use Evaluate, else compute it
	if(strFuncFileName.Compare("POLY"))
	{
		///Cheney 2007-6-19 ALWAYS_FIND_XY_FROM_CUMULATIVE_FIT_CURVE_IF_PEAK_FIT
		//*pY = func.Evaluate(dX, vParams);
		int nNumParamsInFunc = trFF.GeneralInformation.NumberOfParameters.nVal;
		if( nNumParamsInFunc == vParams.GetSize() )
		{
			*pY = func.Evaluate(dX, vParams);
		}
		else		//has replica
		{
			*pY = _evaluate_for_replica_fit(dX, vParams, nNumParamsInFunc, func);
		}
		///end ALWAYS_FIND_XY_FROM_CUMULATIVE_FIT_CURVE_IF_PEAK_FIT
	}
	else
	{
		*pY = 0;
		///Sophy 10/14/2010 ORG-1246 BETTER_METHOD_TO_COMPUTE_POLYNOMIAL_XY
		//for(int ii = 0; ii < nParamsSize; ii++)
		//{
		//	*pY += vParams[ii]*dX^ii;
		//}
		for ( int ii = nParamsSize -1; ii >= 0; ii-- )
		{
			*pY = *pY * dX + vParams[ii];
		}
		///end BETTER_METHOD_TO_COMPUTE_POLYNOMIAL_XY
	}
	
	return true;
}
///end ADD_GLOBAL_FUNCTION_FOR_FINDXY

/// ML 8/28/2006 MULTIPLE_DEPS_INDEPS_NLFIT
#ifdef		__NLFIT_MULTI_DEPS_INDEPS_WEIGHTS__
BOOL	nlsf_init_datarange(DataRange &dr, TreeNode& trInputData, IntArray *pvnWeightMethods, DoubleArray *pvrAs, DoubleArray *pvrBs, DoubleArray *pvrCs)
{
	TreeNode	trResolved;
	if( !okxf_resolve_composite_range_tree(&trResolved, &trInputData, pvnWeightMethods, pvrAs, pvrBs, pvrCs) )
		return FALSE;

	return dr.Create(trResolved, 0);
}
#endif		// __NLFIT_MULTI_DEPS_INDEPS_WEIGHTS__
/// end MULTIPLE_DEPS_INDEPS_NLFIT

/// Iris 11/16/06 ADD_PARAMETER_SETTING_TO_THEME
TreeNode	nlsf_check_get_GUI_params_with_ID(TreeNode& trGUI, int nNumParams)
{
	TreeNode		trOpParams = trGUI.Parameters;
	if(trOpParams)
	///Arvin 02/22/08 QA70-11151 SUPPORT_PARAMETERS_BRANCH_DYNAMICAL_ALLOCATION
	///		return trOpParams;
#ifdef SUPPORT_PARAMETERS_BRANCH_DYNAMICAL_ALLOCATION
	{
		TreeNode trParamValues = trOpParams.Values;
		if(nNumParams == trParamValues.GetNodeCount())
			return trOpParams;
		//Remove old, create new
		trOpParams.Remove();
	}
#else
		return trOpParams;	
#endif
	///end SUPPORT_PARAMETERS_BRANCH_DYNAMICAL_ALLOCATION	
	trOpParams = tree_check_get_node(trGUI, "Parameters", IDE_NL_PARAMS); 
/// Hong 03/19/08 8.0827 NLFIT_REMOVE_SETTINGS_ALLREADY_IN_FDF_FILE_FROM_THEME		
#ifdef NLFIT_FDF_SETTINGS_SKIP_APPLY_THEME
	trOpParams.SetAttribute(STR_XVARIABLE_THEME_APPLICABILITY_ATTRIB, XVTA_DO_NOT_APPLY_VALUE|XVTA_DO_NOT_APPLY_ATTRIBUTES);
#endif //NLFIT_FDF_SETTINGS_SKIP_APPLY_THEME	
/// end NLFIT_REMOVE_SETTINGS_ALLREADY_IN_FDF_FILE_FROM_THEME
	trOpParams.Show = false;

	octree_nlsf_add_params_node_DataID(&trOpParams, nNumParams);
	
	return trOpParams;
}

/// RVD 10/4/2007 v8.0715 qa7-10463 FIX_NLFIT_LIMIT_20_PARAMETERS
#ifndef	NLSF_PARAM_TREE_CONSRUCTION_MOVE_VC
/// end FIX_NLFIT_LIMIT_20_PARAMETERS
/*
void nlsf_add_params_node_DataID(TreeNode& trParams, int nParamSize)
{
	//add DataID to make theme save in Theme
	trParams.DataID = IDE_NL_PARAMS;
	///Cheney 2007-4-29 SEPRATE_BOUND_SETTING_FROM_PARAMS_SETTING_CEHCK_BOX
	//trParams.ApplyTheme.DataID = IDE_NL_PARAMS_APPLY_THEME;
	///Cheney 2007-7-23 QA80-10090 MODIFY_STH_ABOUT_FDF_SAVING_AND_THEME_APPLY	
	//trParams.ApplyParamsTheme.DataID = IDE_NL_PARAMS_APPLY_THEME;
	//trParams.ApplyBoundTheme.DataID = IDE_NL_BOUND_APPLY_THEME;
	///end MODIFY_STH_ABOUT_FDF_SAVING_AND_THEME_APPLY
	///end SEPRATE_BOUND_SETTING_FROM_PARAMS_SETTING_CEHCK_BOX
	trParams.AutoParamsInit.DataID = IDE_NL_PARAMS_AUTO_INIT;
	///Cheney 2007-4-19 SHOW_CHECKBOX_FOR_PARAMS_INIT_AND_CONSTRAINTS
	trParams.LinearConstraints.DataID = IDE_NL_LINEAR_CONSTRAINTS;
	///end SHOW_CHECKBOX_FOR_PARAMS_INIT_AND_CONSTRAINTS
	
	///Arvin/Cheney 03/26/07 QA70-9527 SUPPORT_SETTING_PARAMS_FROM_OC_LT 
	//vector<string> vsParams = {"Share", "Fixed", "LowerBounds", "LowerBoundsExclusive", "LowerBoundsEnable",
	//"UpperBounds", "UpperBoundsExclusive", "UpperBoundsEnable", "Values"};
	///end SUPPORT_SETTING_PARAMS_FROM_OC_LT
	
	uint nParamIDs[] = {IDE_NL_PARAMS_SHARE_BASE, IDE_NL_PARAMS_FIXED_BASE,
		IDE_NL_PARAMS_LOWER_BOUNDS_BASE, IDE_NL_PARAMS_LOWER_BOUNDS_EXCLUSIVE_BASE,
		IDE_NL_PARAMS_LOWER_BOUNDS_ENABLE_BASE,	 IDE_NL_PARAMS_UPPER_BOUNDS_BASE,
		IDE_NL_PARAMS_UPPER_BOUNDS_EXCLUSIVE_BASE, IDE_NL_PARAMS_UPPER_BOUNDS_ENABLE_BASE,
		IDE_NL_PARAMS_VALUE_BASE,
		IDE_NL_PARAMS_SIGNIFICANT_DIGIT_BASE ///Cheney 2007-6-13 SHOULD_ADD_SIGNIFICANT_DIGIT_IN_PARAMETER_SETTING_NODE	
	};
	
	///Arvin/Cheney 03/26/07 QA70-9527 SUPPORT_SETTING_PARAMS_FROM_OC_LT 
	//int nParamItemCount = vsParams.GetSize();
	//for(int ii = 0; ii < nParamItemCount; ii++)
		//_nlsf_check_add_params_child_node(trParams, vsParams[ii], nParamIDs[ii], nParamSize);
	int nParamItemCount = gvsParamName.GetSize();
	for(int ii = 0; ii < nParamItemCount; ii++)
		_nlsf_check_add_params_child_node(trParams, gvsParamName[ii], nParamIDs[ii], nParamSize);
	///end SUPPORT_SETTING_PARAMS_FROM_OC_LT
}

static void _nlsf_check_add_params_child_node(TreeNode& trParams, LPCSTR strItemName, int nDataIDBase, int nParamSize)
{
	TreeNode trNode = tree_check_get_node_by_dataid(trParams, strItemName, nDataIDBase);
	//If parameter size < trNode's Size, trim the unnecessary children
	if(trNode.GetNodeCount() > nParamSize)
	{
		while(trNode.GetNodeCount() > nParamSize)
		{
			TreeNode trJunk = trNode.LastNode;
			trJunk.Remove();
		}
		return;
	}
	
	for(int ii = 1; ii <= nParamSize; ii++)
		TreeNode trParamChild =  tree_check_get_node_by_dataid(trNode, "Value" + ii, nDataIDBase + ii);
}
*/
/// RVD 10/4/2007 v8.0715 qa7-10463 FIX_NLFIT_LIMIT_20_PARAMETERS
#endif	//!NLSF_PARAM_TREE_CONSRUCTION_MOVE_VC
/// end FIX_NLFIT_LIMIT_20_PARAMETERS

///End ADD_PARAMETER_SETTING_TO_THEME

/// Cloud 03/24/07 MOVE_TO_INTERNAL_C
/// Cloud 03/23/07 INIT_PARAMS_FOR_PEAK_FUNC
//void    nlsf_init_peak_params(Curve crvData, vector& vPos, vector& vWidth)
//{
	//int iSize = crvData.GetSize();
	//int iPeakNum = 0;
	//vector vxData;
	//vector vyData;
	//vector vHeight;
	//vector<int> vIndice;
	//crvData.CopyData(vxData, vyData);
	//find_peaks_2nd_derivative(vxData, vyData, vPos, vHeight, vIndice, POSITIVE_DIRECTION, 0);
	//iPeakNum = vPos.GetSize();
//}
/// End INIT_PARAMS_FOR_PEAK_FUNC
/// End MOVE_TO_INTERNAL_C

///Arvin/Cheney 03/26/07 QA70-9527 SUPPORT_SETTING_PARAMS_FROM_OC_LT 
bool nlf_set_bool_param_from_user_params_setting(const TreeNode& trParams, vector<bool>& vParams, int nDataFrom)
{
	/// RVD 10/4/2007 v8.0715 qa7-10463 FIX_NLFIT_LIMIT_20_PARAMETERS
	#ifdef	NLSF_PARAM_TREE_CONSRUCTION_MOVE_VC

	return octree_nlf_set_bool_param_from_user_params_setting(&trParams, &vParams, nDataFrom);

	#else
	/// end FIX_NLFIT_LIMIT_20_PARAMETERS

	//load FDF already, so should be valid tree node
	if(!trParams.IsValid())
		return false;
	
	//check if right node
	int nPos = gvsParamName.Find(trParams.tagName);;
	if( nPos < 0)
		return false;

	int nSize = vParams.GetSize();
	int nOffSet = nDataFrom*nSize;
	for(int ii = 0; ii < nSize; ii++)
	{
		TreeNode trNode = trParams.Children.Item(ii + nOffSet);
		if(!trNode)
			return false;
		
		if(trNode.nVal < 0 || trNode.nVal > 1)
			return false;
		
		vParams[ii] = trNode.nVal;
	}
	return true;

	/// RVD 10/4/2007 v8.0715 qa7-10463 FIX_NLFIT_LIMIT_20_PARAMETERS
	#endif	//NLSF_PARAM_TREE_CONSRUCTION_MOVE_VC
	/// end FIX_NLFIT_LIMIT_20_PARAMETERS
}

bool nlf_set_double_param_from_user_params_setting(const TreeNode& trParams, vector& vParams, int nDataFrom)
{
	/// RVD 10/4/2007 v8.0715 qa7-10463 FIX_NLFIT_LIMIT_20_PARAMETERS
	#ifdef	NLSF_PARAM_TREE_CONSRUCTION_MOVE_VC

	return octree_nlf_set_double_param_from_user_params_setting(&trParams, &vParams, nDataFrom);

	#else
	/// end FIX_NLFIT_LIMIT_20_PARAMETERS

	//load FDF already, so should be valid tree node
	if(!trParams.IsValid())
		return false;
	
	//check if right node
	int nPos = gvsParamName.Find(trParams.tagName);;
	if( nPos < 0)
		return false;

	int nSize = vParams.GetSize();
	int nOffSet = nDataFrom*nSize;
	for(int ii = 0; ii < nSize; ii++)
	{
		TreeNode trNode = trParams.Children.Item(ii + nOffSet);
		if(!trNode)
			return false;
		
		vParams[ii] = is_missing_value(trNode.dVal)? vParams[ii] : trNode.dVal;
	}
	return true;

	/// RVD 10/4/2007 v8.0715 qa7-10463 FIX_NLFIT_LIMIT_20_PARAMETERS
	#endif	//NLSF_PARAM_TREE_CONSRUCTION_MOVE_VC
	/// end FIX_NLFIT_LIMIT_20_PARAMETERS
}
///Jasmine 10/17/07 MISSING_SIGN_DIGITES
bool nlf_set_int_param_from_user_params_setting(const TreeNode& trParams, vector<int>& vParams, int nDataFrom)
{
	return octree_nlf_set_int_param_from_user_params_setting(&trParams, &vParams, nDataFrom);
}
///End MISSING_SIGN_DIGITES
///end SUPPORT_SETTING_PARAMS_FROM_OC_LT

///Cheney 2007-5-25 DO_SAVE_FDF
static void _delete_file(LPCSTR lpcszFile)
{
	string strFile(lpcszFile);
	if(!strFile.IsFile())
		return;
	DWORD dwAttributes = GetFileAttributes(strFile);
	//remove read-only attribute
	dwAttributes &= ~(FILE_ATTRIBUTE_READONLY);
	BOOL bRet = SetFileAttributes(strFile, dwAttributes); 
	bRet = DeleteFile(strFile);
}

void nlf_delete_precompile_files(const string& strFunctionName)
{
	string strFile = okutil_get_origin_path(ORIGIN_PATH_USER, NULL, TRUE) +"OriginC\NLSF\_nlf"+ strFunctionName + ".fit";
	_delete_file(strFile);
	strFile = okutil_get_origin_path(ORIGIN_PATH_USER, NULL, TRUE) +"OriginC\NLSF\_nlp"+ strFunctionName + ".fit";
	_delete_file(strFile);
}
///end DO_SAVE_FDF
//------ CPY 4/3/08 PA_FIT_CNTRL_OPEN_EMPTY_NO_ERR_MSG
// this looks like not used anymore, should not have been written like this anyway
/*
///Cheney 2007-6-8 ALLOW_USER_EDIT_LINEAR_CONSTRINTS_WHEN_USE_BUILDIN_FUNC
bool nlf_is_user_define_func(LPCSTR lpcszFuncName, bool& bUserDefine, string* pstrFuncType)
{
	string 	strFilename;
	nlf_get_fdf_filename(lpcszFuncName, NULL, NULL, &strFilename);
	if( strFilename.IsEmpty() || !strFilename.IsFile() )
		return false;
	
	Tree tr;
	TreeNode trFunc = tr.AddNode("Func");
	///Cheney 2007-6-7 SHOULD_USE_FDFT_CONVERT_BOOL_TO_01_WHEN_NODE_VAL_IS_STRING
	//if( !nlsf_FDF_to_tree(strFilename, &trFunc))
	///Cheney 2007-6-8 ALLOW_USER_EDIT_LINEAR_CONSTRINTS_WHEN_USE_BUILDIN_FUNC
	//if( !nlsf_FDF_to_tree(strFilename, &trFunc, FDFT_CONVERT_BOOL_TO_01))
	if( !nlsf_load_FDF_to_tree(strFilename, &trFunc, FDFT_CONVERT_BOOL_TO_01, true))
	///end ALLOW_USER_EDIT_LINEAR_CONSTRINTS_WHEN_USE_BUILDIN_FUNC
	///end SHOULD_USE_FDFT_CONVERT_BOOL_TO_01_WHEN_NODE_VAL_IS_STRING
		return false;
	
	return nlf_is_user_define_func(trFunc, bUserDefine, pstrFuncType);	
}
*/
/// Hong 12/30/08 QA80-12878 v8.0992 FAST_POPUP_DLG_BY_SKIP_INIT_USING_NULL_FUNCTION
static string _get_func_type(const TreeNode& trFunc)
{
	if ( !trFunc )
		return "";
	
	if ( !trFunc.GeneralInformation )
		return "";
	
	TreeNode 	trFuncType = trFunc.GeneralInformation.FunctionType;
	if ( !trFuncType )
		return "";
	
	return trFuncType.strVal;
}
/// end FAST_POPUP_DLG_BY_SKIP_INIT_USING_NULL_FUNCTION
bool nlf_is_user_define_func(const TreeNode& trFunc, bool& bUserDefine, string* pstrFuncType)
{
	/// Hong 12/30/08 QA80-12878 v8.0992 FAST_POPUP_DLG_BY_SKIP_INIT_USING_NULL_FUNCTION
	/*
	if( !trFunc)
		return false;
	
	TreeNode trFuncType = trFunc.GeneralInformation.FunctionType;
	if(!trFuncType)
		return false;
	
	bUserDefine = (0 == trFuncType.strVal.Compare("User-Defined"));
	
	if(pstrFuncType)
		*pstrFuncType = trFuncType.strVal;
	*/
	string		strFuncType = _get_func_type(trFunc);
	if ( strFuncType.IsEmpty() )
		return false;
	
	bUserDefine = (0 == strFuncType.Compare("User-Defined"));
	if ( pstrFuncType )
		*pstrFuncType = strFuncType;
	/// end FAST_POPUP_DLG_BY_SKIP_INIT_USING_NULL_FUNCTION
		
	return true;
}
///end ALLOW_USER_EDIT_LINEAR_CONSTRINTS_WHEN_USE_BUILDIN_FUNC

/// Hong 12/30/08 QA80-12878 v8.0992 FAST_POPUP_DLG_BY_SKIP_INIT_USING_NULL_FUNCTION
bool nlf_is_built_in_func(const TreeNode& trFunc, bool& bBuiltIn, string* pstrFuncType/* = NULL*/)
{
	string		strFuncType = _get_func_type(trFunc);
	if ( strFuncType.IsEmpty() )
		return false;
	
	bBuiltIn = (0 == strFuncType.Compare("Built-in"));
	if ( pstrFuncType )
		*pstrFuncType = strFuncType;
		
	return true;
}

bool nlf_is_built_in_null_func(const TreeNode& trFunc)
{
	bool 			bBuiltIn;
	if ( !nlf_is_built_in_func(trFunc, bBuiltIn) || !bBuiltIn )
		return false;
	
	NLFunctionList 	nlf;
	string			strFuncName = nlf.GetFunctionName(trFunc);
	return ( 0 == strFuncName.Compare("NULL") );
}
/// end FAST_POPUP_DLG_BY_SKIP_INIT_USING_NULL_FUNCTION

//------ CPY 4/3/08 PA_FIT_CNTRL_OPEN_EMPTY_NO_ERR_MSG

bool nlsf_load_fdf_tree(TreeNode &trFF, LPCSTR lpcszFunc, LPCSTR lpcszCat)// = NULL);
{
	string strFunc = lpcszFunc; // to help using in error_report as well as for ASSERT below
	
	// caller must just give fit func name, so check this assumption 
	ASSERT(!strFunc.IsEmpty());
	ASSERT(strFunc.Find('\\') < 0); // caller might have passed in full path
	ASSERT(strFunc.Find('.') < 0); // caller might have passed in with ext
	
	string strFullPath;
	
	//------ Folger 04/07/08 QA80-11384 FIX_GET_FDF_FULL_PATH_WITHOUT_CATEGORY
	//if(!nlsf_func_to_fdf(lpcszCat, lpcszFunc, strFullPath, true))
		//return BOOL_ERR("nlsf_func_to_fdf failed for " + strFunc);
	string strCate = lpcszCat;
	if(!nlf_get_fdf_filename(lpcszFunc, &strCate, NULL, &strFullPath))
		return BOOL_ERR("nlf_get_fdf_filename failed for " + strFunc);
	//------
	
	//nlsf_load_FDF_to_tree will construct tr and return true if we pass in empty str, so we should ensure this
	ASSERT(strFullPath.GetLength() > 8); //8 because we need at lease c:\a.fdf
	
	// could do strFilename.IsFile() to immediately return false too, but we will just trust nlsf_load_FDF_to_tree will do so
	if(!nlsf_load_FDF_to_tree(strFullPath, &trFF, FDFT_CONVERT_BOOL_TO_01, true))
		return BOOL_ERR("nlsf_load_fdf_tree failed for " + strFullPath);
	
	// success in loading, then ASSERT for really has correct tree, no need to check further as unlikely for wrong tree type
	ASSERT(strFunc.CompareNoCase(trFF.GeneralInformation.FunctionName.strVal)==0);
	
	return true;
}
//------ end PA_FIT_CNTRL_OPEN_EMPTY_NO_ERR_MSG

///Sophy 7/15/2010 ORG-545 CENTRALIZE_CODE_FOR_LOADING_FDF_TREE_FROM_FUNCTIONNAME
int	nlsf_load_FDF_to_tree(TreeNode& trFunction, LPCSTR lpcszFuncName, string* pstrCategory)
{
	string strFunctionName(lpcszFuncName);
	string strCategory, strFileName;
	if ( !nlf_get_fdf_filename(lpcszFuncName, &strCategory, NULL, &strFileName) )
		return FDFTYPE_NONE;
	if ( !nlsf_load_FDF_to_tree(strFileName, &trFunction, FDFT_CONVERT_BOOL_TO_01, true) )
		return FDFTYPE_NONE;

	trFunction.SetAttribute(STR_FILENAME_ATTRIB, strFileName);
	trFunction.SetAttribute(STR_CATEGORY_ATTRIB, strCategory);
	if ( pstrCategory != NULL )
		*pstrCategory = strCategory;
	
	bool bBuiltin = false;
	nlf_is_built_in_func(trFunction, bBuiltin);
	if ( bBuiltin )
		return FDFTYPE_BUILTIN;
	
	bool bUserDef = false;
	nlf_is_user_define_func(trFunction, bUserDef);
	if ( bUserDef )
		return FDFTYPE_USER;
	
	return FDFTYPE_UNKNOWN;
}
///end CENTRALIZE_CODE_FOR_LOADING_FDF_TREE_FROM_FUNCTIONNAME


///Jasmine 06/08/07 NEW_MECHANISM_TO_SAVE_BUILT_IN_FUNCTION
bool nlsf_load_FDF_to_tree(LPCSTR lpcszFDFname, TreeNode* pTreeNode, DWORD dwCtrl, bool bCustomized)// = true, 0
{
	if(!pTreeNode || !nlsf_FDF_to_tree(lpcszFDFname, pTreeNode, dwCtrl))
		return false;
	/// Hong 07/25/08 QA80-11593 FIX_BUILD_IN_FDF_USER_ADDED_DERIVED_PARAMETERS_LOST_IN_FIT_REPORT
	/*
	int nPath = okutil_get_origin_path_type(lpcszFDFname);
	if(SYS_FOLDER == nPath)	
	{
		string strPath=okutil_get_origin_path(USER_FOLDER, STR_FDF_FILE_FOLDER);
		strPath.TrimRight("\\");
		string strXMLFile = strPath + +"\\" + STR_CUSTOMIZED_BUILT_IN_FILE;
		//TreeNode trFDF = *pTreeNode; ///Cheney 2007-6-8 ALLOW_USER_EDIT_LINEAR_CONSTRINTS_WHEN_USE_BUILDIN_FUNC
		TreeNode trSetting;
		Tree trXML;
		if(trXML.Load(strXMLFile))
		{
			string strFunction;
			///Cheney 2007-6-8 ALLOW_USER_EDIT_LINEAR_CONSTRINTS_WHEN_USE_BUILDIN_FUNC
			//TreeNode tr = trFDF.GetNode(cvt_str_to_tag_name(STR_FUNC_GENERAL_INFO), false);
			TreeNode tr = pTreeNode->GetNode(cvt_str_to_tag_name(STR_FUNC_GENERAL_INFO), false);
			///end ALLOW_USER_EDIT_LINEAR_CONSTRINTS_WHEN_USE_BUILDIN_FUNC
			if(tr && tr.FunctionName)
				strFunction = tr.FunctionName.strVal;
			trSetting = trXML.GetNode(cvt_str_to_tag_name(strFunction), false);
		}
		if(trSetting.IsValid())
			///Cheney 2007-6-8 ALLOW_USER_EDIT_LINEAR_CONSTRINTS_WHEN_USE_BUILDIN_FUNC
			//trFDF.Replace(trSetting);
			pTreeNode->Replace(trSetting);
			///end ALLOW_USER_EDIT_LINEAR_CONSTRINTS_WHEN_USE_BUILDIN_FUNC	
	}
	*/
	/// end FIX_BUILD_IN_FDF_USER_ADDED_DERIVED_PARAMETERS_LOST_IN_FIT_REPORT
	return true;
}

/// Hong 07/25/08 QA80-11593 FIX_BUILD_IN_FDF_USER_ADDED_DERIVED_PARAMETERS_LOST_IN_FIT_REPORT
/*
bool nlsf_save_to_customized_xml(TreeNode& trFunction)
{
	int nType;
	okutil_fo_GetFuncFileName(&trFunction, true, &nType);
	if(SYS_FOLDER == nType)	
	{
		string strPath=okutil_get_origin_path(USER_FOLDER, STR_FDF_FILE_FOLDER);
		strPath.TrimRight("\\");
		/// Hong 01/02/08 QA80-10881 FIX_XML_FAIL_SAVED_FOLDER_NOT_CREATED_FIRST
		//string strXMLFile = strPath + +"\\" + STR_CUSTOMIZED_BUILT_IN_FILE;
		if ( !CheckMakePath(strPath) )
			return false;
		string strXMLFile = strPath + "\\" + STR_CUSTOMIZED_BUILT_IN_FILE;
		/// end FIX_XML_FAIL_SAVED_FOLDER_NOT_CREATED_FIRST
		Tree trXML;
		if(strXMLFile.IsFile())
			trXML.Load(strXMLFile);
		string strFunction;
		trFunction.GetAttribute(STR_LABEL_ATTRIB, strFunction);
		strFunction = cvt_str_to_tag_name(strFunction);
		TreeNode trSetting = trXML.GetNode(strFunction);
		if(!trSetting)
			trSetting = trXML.AddNode(strFunction);
		trSetting.Replace(trFunction, TRUE, TRUE);	
		///Jasmine 06/13/07 MAKE_CONNECTION_BETWEEN_SAME_FUNCTION
		trSetting.RemoveAttribute(STR_CHANGED_ATTRIB);
		trSetting.RemoveAttribute(STR_OLDFILENAME_ATTRIB);
		///End MAKE_CONNECTION_BETWEEN_SAME_FUNCTION
		trXML.Save(strXMLFile);
		return true;
	}
	return false;
}
*/
/// end FIX_BUILD_IN_FDF_USER_ADDED_DERIVED_PARAMETERS_LOST_IN_FIT_REPORT

bool nlsf_remove_from_customized_xml(TreeNode& trFunction)
{
	/// Hong 07/25/08 QA80-11593 FIX_BUILD_IN_FDF_USER_ADDED_DERIVED_PARAMETERS_LOST_IN_FIT_REPORT
	/*
	int nType;
	okutil_fo_GetFuncFileName(&trFunction, true, &nType);
	if(SYS_FOLDER == nType)	
	{
		string strPath=okutil_get_origin_path(USER_FOLDER, STR_FDF_FILE_FOLDER);
		strPath.TrimRight("\\");
		string strXMLFile = strPath + +"\\" + STR_CUSTOMIZED_BUILT_IN_FILE;
		Tree trXML;
		if(strXMLFile.IsFile())
			trXML.Load(strXMLFile);
		string strFunction;
		trFunction.GetAttribute(STR_LABEL_ATTRIB, strFunction);
		strFunction = cvt_str_to_tag_name(strFunction);
		TreeNode trSetting = trXML.GetNode(strFunction);
		if(trSetting)
			trSetting.Remove();
		trXML.Save(strXMLFile);
		return true;
	}
	return false;	
	*/
	return nlsf_reset_build_in_FDF(&trFunction);
	/// end FIX_BUILD_IN_FDF_USER_ADDED_DERIVED_PARAMETERS_LOST_IN_FIT_REPORT
}
///End NEW_MECHANISM_TO_SAVE_BUILT_IN_FUNCTION
//---------- CPY 3/39/08 SURFACE_FIT_USE_COLOR_CONTOUR_FOR_SRC_DATA
// moved to page_utils.h
/*
///Arvin 03/03/08 QA-11206 SETUP_CONTOUR_PLOT_FOR_SURFACE_FIT
bool nlsf_setup_fit_contour(DataPlot& dp, vector& zz, int nColor) 
{
	double z1 = zz[0];
	double z2 = zz[1];
	double zInc = zz[2];
	vector vLevels;
	vector<uint> vColors;
	vLevels.Data(z1, z2, zInc);
	int nLevels = vLevels.GetSize();
	double zmiddle = z1 + (z2-z1)/2;
	vColors.SetSize(nLevels-1); // number of lines = number of fill colors, line above last is separtely controlled
	vColors = nColor;
	int nErr = set_contour_lines(dp, vLevels, vColors);
	if(nErr != 0)
	{
		out_int("set_contour_lines err = ", nErr);
		return false;
	}
	return true;
}

// irl = Inner Residual Limit
// orl = Outer Residual Limit
// both expressed in percent of source data's Z range which is in zz[1] and zz[0]
bool nlsf_setup_residual_contour(DataPlot& dp, vector& zz, double irl, double orl, int nInnersteps, int nOutSteps) 
{
	if(irl >= orl)
		return error_report("inner residual limit must be smaller then the outer one");
	
	double dataScaleRange = fabs(zz[1] - zz[0]);
	double z1 = -dataScaleRange;
	double z2 = dataScaleRange;
	double zInc = 0;
	double f1 = irl * z2/100.; // residual limits, inner
	double f2 = orl * z2/100.; // residual limits, outer
	RoundLimits(&f1, &f2, &zInc, nOutSteps); 
	vector v3; v3.Data(f1, f2, zInc);
	vector v1; v1.Data(-f2, -f1, zInc);
	
	double zInnerInc = 2*f1/nInnersteps;// inner range inc
	vector v2; v2.Data(-f1+zInnerInc, f1-zInnerInc, zInnerInc);
	vector vLevels;
	vLevels = v1;
	vLevels.Append(v2);
	vLevels.Append(v3);
	int nLevels = vLevels.GetSize();
	vector<uint> vColors;
	vColors.SetSize(nLevels-1); // number of lines = number of fill colors, line above last is separtely controlled
	int c1 = SYSCOLOR_BLUE, c2 = SYSCOLOR_BLACK, c3 = SYSCOLOR_RED; 
	for(int ii = 0; ii < vColors.GetSize(); ii++)
	{
		if(vLevels[ii] < -f1)
			vColors[ii] = c1;
		else if(vLevels[ii] > f1)
			vColors[ii] = c3;
		else
			vColors[ii] = c2;
	}
	int nErr = set_contour_lines(dp, vLevels, vColors);
	if(nErr != 0)
	{
		out_int("set_contour_lines err = ", nErr);
		return false;
	}
	return true;
}*/
///end SETUP_CONTOUR_PLOT_FOR_SURFACE_FIT

///Cheney 2007-8-21 QA70-10256-P7 ADD_GLOBAL_FUC_FOR_UPDATE_CONTOUR_LEVEL
bool nlsf_update_residual_contour_levels(GraphLayer& gl, DataPlot& dp, vector& vData)
{
	if(vData.GetSize() == 0)
		return false;
	
	if(!dp || !gl)
		return false;
	
	GraphObject go = gl.GraphObjects("SPECTRUM1");
	if(!go)
		return false;
	go.Show(true);
	
	double 		dNumSigma = 3.0;
	///Jasmine 02/25/08 CHECK_GET_SIGMA_CONTROL, sigma and NumSigma are GraphObject in Report3DResidual.otp, 
	//if GraphLayer has no these object, the LT_execute will fail
	GraphObject goSigma = gl.GraphObjects("sigma");
	if(goSigma)
	{
		/// Cloud 12/10/07 SIGMA_OBJECT_SEEMS_OBSOLETE
		try
		{
			if( gl.LT_execute("sig=sigma.NumSigma") )
			{
				LT_get_var("sig", &dNumSigma);			
			}
		}
		catch(int err)
		{
		}
		/// End SIGMA_OBJECT_SEEMS_OBSOLETE
	}
	///End CHECK_GET_SIGMA_CONTROL
	
	int 	nP;
	double 	dMean, dSD;
	if( 0 != ocmath_basic_summary_stats(vData.GetSize(), vData, &nP, &dMean, &dSD) )
		return false;
	
	vector<double> 	vLevels(3);
	vLevels[0] = -dNumSigma * dSD;
	vLevels[1] = 0;
	vLevels[2] = -vLevels[0];
	
	vector<uint>	vnColors = {SYSCOLOR_GREEN, SYSCOLOR_BLUE};
	if(0 != dataplot_set_colormap(dp, vLevels, vnColors, SYSCOLOR_RED, SYSCOLOR_PINK, true) )
		return false;
	
	return true;
}
///end ADD_GLOBAL_FUC_FOR_UPDATE_CONTOUR_LEVEL

///Cheney 2007-10-15 QA70-10522-P4 CLEAN_CODE_AND_ADD_AUTO_FOR_OUTPUT_SETTING 
string nlsf_get_source_page_name(const DataRange& dr, int nFitType, string *pstrLayerName)
{
	if(NLFIT_MATRIX_FITTING == nFitType)
	{
		MatrixLayer ml;
		dr.GetParent(ml);
		if(!ml)
		{
			if(pstrLayerName)
		///Jasmine 10/15/07 BAD_CODE_COMPILE_FAIL
				*pstrLayerName = "";
			return "";
		}
		
		if(pstrLayerName)
			*pstrLayerName = ml.GetName();
		
		MatrixPage mp;
		mp = ml.GetPage();
		///End BAD_CODE_COMPILE_FAIL
		if(!mp)
			return "";
		
		return 	mp.GetName();  
	}

	//return get_source_page_name(dr, pstrLayerName);
	return get_range_source_page_name(dr, pstrLayerName);///Jasmine 10/15/07 MOVE_TO_PAGE_UTILS
}
///end CLEAN_CODE_AND_ADD_AUTO_FOR_OUTPUT_SETTING

///Arvin 07/10/07 v8.0656 CLEAN_CODE_FOR_XF_SIMCURVE_AND_SIMSURFACE
//------------------------------------------------------------------------------------
//----------Arvin 07/10/07 v8.0656 CLEAN_CODE_FOR_XF_SIMCURVE_AND_SIMSURFACE----------
//------------------------------------------------------------------------------------
#define IDST_SIMULATE_PARAS		(IDST_TREE_BRANCH_MASK + 1)

static void _init_nlsf_sel_fun(TreeNode &trGetN)
{
	NLFitSelFunction nlf(trGetN);
	string strCateg  = trGetN.categorylist.strVal;
	bool bSurfaceSim = strCateg.Compare("Surface Fitting") == 0 ? true : false; 
	if(bSurfaceSim)
	{
		vector<string> vs;
		vs.Add(strCateg);
		nlf.Init(strCateg, NULL, NULL , vs, true, false);
	}
	else
		//------ Folger 12/14/07 NEED_TO_JUDGE_CALL_FROM_NLFIT_OR_SIMCURVE
		//nlf.Init("Origin Basic Functions", NULL, NULL, NULL, true, false);	///Jasmine 05/18/07 ADD_NEW_AT_LIST_BOTTOM_TO_OPEN_FO, no need <new...> here
		nlf.Init("Origin Basic Functions", NULL, NULL, NULL, true, false, false);
		//------
}

static void _update_function_from_categ(TreeNode &trGetN)
{
	NLFitSelFunction nlf(trGetN);
	nlf.OnChangeCategoryUpdateFunctionList(false);	///Jasmine 05/18/07 ADD_NEW_AT_LIST_BOTTOM_TO_OPEN_FO
}

static string _get_function_name(TreeNode &trGetN)
{
	string strFunction = trGetN.functionlist.strVal;
	strFunction = strFunction.GetToken(0,'(');
	strFunction.TrimLeft();
	strFunction.TrimRight();
	return strFunction;
}
	
bool sim_xf_get_FDF(TreeNode &trGetN, TreeNode &trFF)
{
	NLFitSelFunction nlf(trGetN);
	string strCate, strFunc;
	nlf.GetCategoryAndFunction(strCate, strFunc);	
	return nlf.LoadEx(trFF, strFunc, strCate);		
}

void sim_xf_get_param_list(vector& vParams, TreeNode& trParams)
{
	foreach(TreeNode trN in trParams.Children)
		vParams.Add(trN.dVal);
}

///Arvin 04/04/07 v8.0596 CHECK_LEGALITY_OF_PARAMS
static bool _get_params_bound_info(LPCSTR lpcszFunName, LPCSTR lpcszCateg, vector<string>& vParamNames, vector& vParamLowerBounds, vector& vParamUpperBounds, vector<bool>& vbOnLowerBounds, vector<bool>& vbOnUpperBounds)
{
	NLFunctionList nlf;
	Tree trFF;
	string strFunction = lpcszFunName, strCateg = lpcszCateg;	
	if(!nlf.LoadEx(trFF, strFunction, strCateg))
		return false;
	
	string 	strParamList = nlf.GetFittingPara(trFF, true, "Names").strVal;
	int nNumParaInFunc = strParamList.GetTokens(vParamNames, ',');
	
	string strParaBoundList = nlf.GetFittingPara(trFF, true, "LowerBounds").strVal;
	//LowerBounds
	nlf_set_param_bounds_vector(strParaBoundList, vParamLowerBounds, nNumParaInFunc);
	nlf_set_param_on_bounds_vector(strParaBoundList, vbOnLowerBounds, nNumParaInFunc);
	///UpperBounds
	strParaBoundList = nlf.GetFittingPara(trFF, true, "UpperBounds").strVal;
	nlf_set_param_bounds_vector(strParaBoundList, vParamUpperBounds, nNumParaInFunc);
	nlf_set_param_on_bounds_vector(strParaBoundList, vbOnUpperBounds, nNumParaInFunc);
	
	return true;
}

int sim_xf_check_params_legality(LPCSTR lpcszFunName, LPCSTR lpcszCateg, const vector& vParamValues, string& strErrFuncOrParam, double& dLowerOrUpperBound)
{
	vector<string> vParamNames;
	vector vParamLowerBounds, vParamUpperBounds;
	vector<bool> vbOnLowerBounds, vbOnUpperBounds;
	if(!_get_params_bound_info(lpcszFunName, lpcszCateg, vParamNames, vParamLowerBounds, vParamUpperBounds, vbOnLowerBounds, vbOnUpperBounds))
	{
		strErrFuncOrParam = lpcszFunName;
		return XFERR_LOAD_FUNC_INFO;
	}
	
	if(vParamNames.GetSize() != vParamValues.GetSize())
	{
		return XFERR_WRONG_PARAM_NUMBER;
	}
	
	for(int ii = 0; ii < vParamNames.GetSize(); ii++)
	{
		string strParamName = vParamNames[ii];
		double dLower = vParamLowerBounds[ii], dUpper = vParamUpperBounds[ii], dValue = vParamValues[ii];
		if(!is_missing_value(dLower) && !is_missing_value(dValue) && dValue < dLower && vbOnLowerBounds[ii])
		{
			strErrFuncOrParam = strParamName;
			dLowerOrUpperBound = dLower;
			//strErrMsg = XFERR_PARAM_VALUE_TOO_SMALL + ":" + strParamName + "|" + dLower;
			return XFERR_PARAM_VALUE_TOO_SMALL;
		}
		
		if(!is_missing_value(dUpper) && !is_missing_value(dValue) && dValue > dUpper && vbOnUpperBounds[ii])
		{
			strErrFuncOrParam = strParamName;
			dLowerOrUpperBound = dUpper;
			//strErrMsg = XFERR_PARAM_VALUE_TOO_LARGE + ":" + strParamName + "|" + dUpper;
			return XFERR_PARAM_VALUE_TOO_LARGE;
		}	
	}
	
	return 0;
}

bool sim_xf_check_tree_settings(TreeNode& trGetN, string& strErrMsg)
{
	vector vParams;
	sim_xf_get_param_list(vParams, trGetN.pvalue);
	string strCategory = trGetN.categorylist.strVal;
	string strFunc = trGetN.functionlist.strVal;
	string strErrFuncOrParam;
	double dLowerOrUpperBound;
	int nRet = sim_xf_check_params_legality(strFunc, strCategory, vParams, strErrFuncOrParam, dLowerOrUpperBound);
	if(nRet != 0)
	{
		switch(nRet)
		{
		case XFERR_LOAD_FUNC_INFO:
			strErrMsg = XFERR_LOAD_FUNC_INFO;
			strErrMsg = strErrMsg + ":" + strErrFuncOrParam;
			break;
		case XFERR_WRONG_PARAM_NUMBER:
			strErrMsg = XFERR_WRONG_PARAM_NUMBER;
			break;
		case XFERR_PARAM_VALUE_TOO_SMALL:
			strErrMsg = XFERR_PARAM_VALUE_TOO_SMALL;
			strErrMsg = strErrMsg + ":" + strErrFuncOrParam + "|" + dLowerOrUpperBound;
			break;
		case XFERR_PARAM_VALUE_TOO_LARGE:
			strErrMsg = XFERR_PARAM_VALUE_TOO_LARGE;
			strErrMsg = strErrMsg + ":" + strErrFuncOrParam + "|" + dLowerOrUpperBound;
			break;
		}
		
		return false;
	}
	double dLevel = trGetN.noise.dVal;
	if(dLevel < 0 || dLevel > 100)//set noise level in [0, 100] by max's suggestion
	{
		strErrMsg = XFERR_WRONG_NOISE_LEVEL;
		strErrMsg = strErrMsg + ":" + 0 + "|" + 100;
		return false;
	}
	return true;
}
///end CHECK_LEGALITY_OF_PARAMS

static void _get_para_GETN_branch(TreeNode &trPara, string& strParams)
{
	int nDataID =  IDE_SIMULATE_PARA_BEGIN;
	int nParaCount = strParams.Count(',') ;
	if(nParaCount >=0)
		nParaCount++;
	else
		return;
	//------ Folger 11/15/07 FIX_LABEL_LOCALIZATION
	string strLabel = _L("Parameters");
	trPara.GetAttribute(STR_LABEL_ATTRIB, strLabel);
	//------ End FIX_LABEL_LOCALIZATION
	GETN_TREE(tr)
	//------ Folger 11/15/07 FIX_LABEL_LOCALIZATION
	//GETN_BEGIN_BRANCH(pvalue, "Parameters") GETN_OPTION_BRANCH(GETNBRANCH_OPEN) GETN_ID_BRANCH(IDST_SIMULATE_PARAS) //GETN_CHECKBOX_BRANCH(1)
	GETN_BEGIN_BRANCH(pvalue, strLabel) GETN_OPTION_BRANCH(GETNBRANCH_OPEN) GETN_ID_BRANCH(IDST_SIMULATE_PARAS) //GETN_CHECKBOX_BRANCH(1)
	//------ End FIX_LABEL_LOCALIZATION
	for(int n =0 ; n< nParaCount; n++)
	{
		string str = strParams.GetToken(n, ',');
		if (str.Compare("") == 0)
		{
			printf("Invalid Parameter Values!\n");
			return;
		}
		string strParaName = "P" + n;
		double dDefault = 1;
		GETN_NUM(strParaName, str, dDefault) GETN_ID(nDataID++)
	}
	GETN_END_BRANCH(pvalue)	//Match GETN_BEGIN_BRANCH

	if(tr.pvalue.IsEmpty())
		return;
	trPara.Replace(tr.pvalue);
}

static bool _find_param_in_list(LPCSTR lpcszParam, string& lpcszList, char chDelimiter)
{
	vector<string> vsComboList;
	lpcszList.GetTokens(vsComboList, chDelimiter);
	return is_in_list(lpcszParam, vsComboList);
}

int sim_xf_update_grid_tree(TreeNode &trGetN, bool bInitGrid, bool bSimCurve, int* pCtrl)
{
	string strCategoryList, strFuncList;
	strCategoryList = trGetN.categorylist.strVal;
	strFuncList = trGetN.functionlist.strVal;
	strCategoryList.Remove('\"');
	strFuncList.Remove('\"');
	if(bInitGrid)
	{
		_init_nlsf_sel_fun(trGetN);
		if(!strCategoryList.IsEmpty())
		{
			string strComboList;
			trGetN.categorylist.GetAttribute(STR_COMBO_ATTRIB, strComboList);
			if(_find_param_in_list(strCategoryList, strComboList, '|'))
			{
				trGetN.categorylist.strVal = strCategoryList;
				_update_function_from_categ(trGetN);
				trGetN.functionlist.GetAttribute(STR_COMBO_ATTRIB, strComboList);
				if(_find_param_in_list(strFuncList, strComboList, '|'))
					trGetN.functionlist.strVal = strFuncList;
			}
		}
	}
	else
		if(tree_node_changed(trGetN.categorylist))
			_update_function_from_categ(trGetN);
	
	int nCtrl = 0;
	string strFunction = _get_function_name(trGetN);
	/// Iris 02/16/2007 v8.0654 SHOW_WRONG_DLG_IF_NO_FUNCTION_IN_SELECTED_CATEGORY
	if(strFunction.IsEmpty())
		return XFERR_NO_FUNCTION_SELECTED;
	///end SHOW_WRONG_DLG_IF_NO_FUNCTION_IN_SELECTED_CATEGORY
	int nNumIndep =  nlf_get_independent_variables(strFunction);
	if( bSimCurve && nNumIndep != 1)
		return XFERR_NOT_2D_FUNCTION;
	
	if(!bSimCurve && nNumIndep != 2)
		return XFERR_NOT_3D_FUNCTION;
	
	Tree trFF;
	if(!sim_xf_get_FDF(trGetN, trFF))
		return XFERR_LOAD_FDF_TREE_FAILED;
	
	string	strParamNames = trFF.FittingParameters.Names.strVal;
	trGetN.pname.strVal = strParamNames;
	trGetN.pname.Enable = false;
	
	//int		numParamsInFunction = trFF.GeneralInformation.NumberOfParameters.nVal;
	int		numIndependentVariables = trFF.GeneralInformation.NumberOfIndependentVariables.nVal;

	trGetN.pname.Show = false;
	bool bCateChanged = tree_node_changed( trGetN.categorylist);
	bool bFunctChanged = tree_node_changed( trGetN.functionlist);
	if(bFunctChanged || bCateChanged || bInitGrid)
	{
		_get_para_GETN_branch(trGetN.pvalue,strParamNames);
		Tree tr;
		if(!tr.Load(USER_SIMULATE_FILE))
		{
			if(!tr.Load(SYS_SIMULATE_FILE))
				return XFERR_LOAD_SETTING_FAILED;
		}
		
		TreeNode trFind = tr.GetNode(strFunction);//tr.FindNodeByAttribute(STR_NAME_ATTRIB, strFunction);
		if(trFind.IsValid())
		{
			octree_copy_values_by_id(&trFind, &trGetN, false, STR_ID_ATTRIB, STR_DATAID_ATTRIB);
			nCtrl = 1; //Gray out Save button
		}
		else
			nCtrl = 2; 	
		//nCtrl > 0, Need update GUI
		if(pCtrl)
			*pCtrl = nCtrl;
		
		return 0; 
	}
	if(pCtrl)
		*pCtrl = 0;//No need update GUI
	
	return 0; 
}

//------ Folger 02/12/08 IMPROVE_SIMULATE_CURVE
#define	STR_CATEGORY_NAME_ATTRIB	"CategoryName"
#define	STR_FUNCTION_NAME_ATTRIB	"FunctionName"
bool sim_xf_access_cate_and_func_last_used(string &strCategory, string &strFunction, bool bGet)	// = true
{
	Tree	tr;
	string	strFile = USER_SIMULATE_FILE;
	if( !tr.Load(strFile) )
	{
		if ( !tr.Load(SYS_SIMULATE_FILE) )
			return false;
		tr.Save(USER_SIMULATE_FILE);
	}
	
	if ( bGet )
	{
		if ( !tr.GetAttribute(STR_CATEGORY_NAME_ATTRIB, strCategory) || !tr.GetAttribute(STR_FUNCTION_NAME_ATTRIB, strFunction) )
			return false;
	}
	else
	{
		tr.SetAttribute(STR_CATEGORY_NAME_ATTRIB, strCategory);
		tr.SetAttribute(STR_FUNCTION_NAME_ATTRIB, strFunction);
		tr.Save(strFile);
	}
	return true;
}
//------

//------ Folger 03/20/08 QA80-11155 CENTRALIZE_OUTPUT_PARAMETER_COMMENTS_FOR_SIMCURVE_AND_SIMSURFACE
void	sim_generate_function_and_parameters_comments(const DataRange &dr, LPCSTR lpcszFunction, const TreeNode &trParam)
{
	Worksheet wks;
	int c1, c2;
	dr.GetRange(wks, c1, c2);
	if ( wks )
	{
		int nRanges = dr.GetNumRanges();
				
		Grid grid;
		if ( !grid.Attach(wks) )
			return;
		vector<string>	vsUDLs;
		vector<int>		vnTypes;
		grid.GetUserDefinedLabelNames(vsUDLs);
		grid.GetShowLabels(vnTypes);
		
		for ( int ii=0; ii<nRanges; ++ii )
		{
			dr.GetRange(wks, c1, c2, ii);
			if ( c1<0 || c2<0 )
				continue;
			Column cc(wks, c1);
			cc.SetComments(lpcszFunction);
			
			int nCount = vsUDLs.GetSize();
			foreach ( TreeNode trPara in trParam.Children )
			{
				string strLabel;
				trPara.GetAttribute(STR_LABEL_ATTRIB, strLabel);
				
				int nIndex;
				if ( (nIndex = vsUDLs.Find(strLabel)) < 0 )
				{
					nIndex = nCount++;
					vsUDLs.Add(strLabel);
					vnTypes.Add(RCLT_UDL + nIndex);
				}
				
				cc.SetExtendedLabel(ftoa(trPara.dVal), RCLT_UDL + nIndex);
			}
		}
			
		grid.SetUserDefinedLabelNames(vsUDLs);
		grid.SetShowLabels(vnTypes);
	}
}
//------ End CENTRALIZE_OUTPUT_PARAMETER_COMMENTS_FOR_SIMCURVE_AND_SIMSURFACE

//I don't know why we use this ID, only keep same as original theme file fdf_simulate.ois
#define IDE_SIMULATE_VARIABLE_BEGIN   		0x00050032
#define IDE_SIMULATE_VARIABLE_INCREMENT 	0x00010000
static void _create_theme_tree_for_new_function(TreeNode& trGetN, TreeNode& trTheme)
{	
	string strFunction = _get_function_name(trGetN);
	int nID;
	string strNode = "node";
	
	Tree tr;
	tr.AddNode(strFunction, 0);
	TreeNode trFunc = tr.GetNode(strFunction);
	nID = IDE_SIMULATE_VARIABLE_BEGIN;
	trFunc.AddNumericNode(trGetN.x1.dVal, strNode+ftoa(nID), nID);
	nID += IDE_SIMULATE_VARIABLE_INCREMENT;
	trFunc.AddNumericNode(trGetN.x2.dVal, strNode+ftoa(nID), nID);
	nID += IDE_SIMULATE_VARIABLE_INCREMENT;
	trFunc.AddNumericNode(trGetN.nx.dVal, strNode+ftoa(nID), nID);
	
	string strCateg  = trGetN.categorylist.strVal;;
	bool   bSurfaceSimFunc = (2 == nlf_get_independent_variables(strFunction)) ? true : false;
	if(bSurfaceSimFunc)
	{
		nID += IDE_SIMULATE_VARIABLE_INCREMENT;
		trFunc.AddNumericNode(trGetN.y1.dVal, strNode+ftoa(nID), nID);
		nID += IDE_SIMULATE_VARIABLE_INCREMENT;
		trFunc.AddNumericNode(trGetN.y2.dVal, strNode+ftoa(nID), nID);
		nID += IDE_SIMULATE_VARIABLE_INCREMENT;
		trFunc.AddNumericNode(trGetN.ny.dVal, strNode+ftoa(nID), nID);
	}
	
	nID += IDE_SIMULATE_VARIABLE_INCREMENT;
	trFunc.AddNumericNode(trGetN.noise.dVal, strNode+ftoa(nID), nID);
	TreeNode trPValue = trGetN.pvalue;
	nID = IDE_SIMULATE_PARA_BEGIN;
	
	foreach(TreeNode trN in trPValue.Children)
	{
		trFunc.AddNumericNode(trN.dVal, strNode+ftoa(nID), nID);
		nID++;
	}
	
	trTheme.Replace(trFunc);
}
	
bool sim_xf_on_save_button(TreeNode &trGetN, string& strErrMsg)
{
	Tree tr;
	if(!tr.Load(USER_SIMULATE_FILE)&& !tr.Load(SYS_SIMULATE_FILE))
	{
		strErrMsg = XFERR_LOAD_XML_FAILED;
		return false;
	}

	string strFunction = _get_function_name(trGetN);
	TreeNode trFind = tr.GetNode(strFunction);
	if(!trFind.IsValid())
	{
		tr.AddNumericNode(0, strFunction, 0);
		trFind = tr.GetNode(strFunction);
		_create_theme_tree_for_new_function(trGetN, trFind);
	}
		
	octree_copy_values_by_id(&trGetN, &trFind, false, STR_DATAID_ATTRIB, STR_ID_ATTRIB);
	tr.Save(USER_SIMULATE_FILE);
	
	return true;
}
//------------------------------------------------------------------------------------
//----------end Arvin 07/10/07 v8.0656 CLEAN_CODE_FOR_XF_SIMCURVE_AND_SIMSURFACE------
//------------------------------------------------------------------------------------

//------Folger 07/11/07 ADD_LOAD_FUNCTION_NAME_FROM_CUSTOMIZE_XML
bool load_function_name_from_customize_xml(vector<string> &vsFuncName)
{
	/// Hong 07/25/08 QA80-11593 FIX_BUILD_IN_FDF_USER_ADDED_DERIVED_PARAMETERS_LOST_IN_FIT_REPORT
	/*
	int nType;
	string strPath=okutil_get_origin_path(USER_FOLDER, STR_FDF_FILE_FOLDER);
	strPath.TrimRight("\\");
	string strXMLFile = strPath + "\\" + STR_CUSTOMIZED_BUILT_IN_FILE;
	Tree trXML;
	if(strXMLFile.IsFile())
		trXML.Load(strXMLFile);
	foreach(TreeNode trFunction in trXML.Children)
	{
		string strFunction;
		trFunction.GetAttribute(STR_LABEL_ATTRIB, strFunction);
		vsFuncName.Add(strFunction);
	}
	//strFunction = cvt_str_to_tag_name(strFunction);
	return true;
	*/
	return (0 == nlsf_get_customized_build_in_FDF_function_name(&vsFuncName) ? false : true);
	/// end FIX_BUILD_IN_FDF_USER_ADDED_DERIVED_PARAMETERS_LOST_IN_FIT_REPORT
}
//------end ADD_LOAD_FUNCTION_NAME_FROM_CUSTOMIZE_XML

///Arvin 01/10/06 ADD_CREATING_CURVES_FUNCTIONS_FOR_PALETTE_EDIT_TOOL
static bool _line_segement_curve(const vector& vx, const vector& vy, vector& vCurveX, vector& vCurveY)
{
	int nRet = ocmath_interpolate(vCurveX, vCurveY, vCurveX.GetSize(), vx, vy, vx.GetSize(), INTERP_TYPE_LINEAR);
	if(nRet != OE_NOERROR)
		return false;
	
	return true;
}

static bool _spline_curve(const vector& vx, const vector& vy, vector& vCurveX, vector& vCurveY)
{
	int nRet = ocmath_interpolate(vCurveX, vCurveY, vCurveX.GetSize(), vx, vy, vx.GetSize(), INTERP_TYPE_SPLINE);
	if(nRet != OE_NOERROR)
		return false;
	
	return true;
}

bool nlsf_func_curve(const vector& vx, const vector& vy, const string strFuncName, vector& vCurveX, vector& vCurveY)
{	
	string strCategory = "Origin Basic Functions";
	//TreeNode trFDF;
	//if(!nlsf_get_FDF_tree_from_func_name(trFDF, strFuncName, strCategory))
	//	return false;
	
	/// Hong 11/04/08 QA80-12526 v8.0965b ADD_BACKWARD_COMPATIABLE
	//NLFitSessionBase fit(false);
	NLFitSession 		fit;
	fit.SetAutoInitParams(false);
	/// end ADD_BACKWARD_COMPATIABLE
	if (!fit.SetFunction(strFuncName, strCategory ))
	{
		return false;
	}
	if (!fit.SetData(vy, vx))
	{
		return false;
	}
	if (!fit.ParamsInitValues())
	{
		return false;
	}
	vector vParams, vErrors;
	if (!fit.GetFitResultsParams(vParams, vErrors))
	{
		return false;
	}
	
	int nFitOutcome;
	if (!fit.Fit(&nFitOutcome))
	{
		if (!fit.GetFitResultsParams(vParams, vErrors))
		{
			return false;
		}
	}
	
	if(nlsf_evaluate(strFuncName, strCategory, vCurveX, vCurveY, vParams))
	{
		return true;
	}
	
	return false;
}

bool nlsf_logistic_curve(const vector& vx, const vector& vy, const int nPower, const int nCenter, vector& vCurveX, vector& vCurveY)
{	
	string strCategory = "Origin Basic Functions";
	string strFuncName = "Logistic";

	/// Hong 11/04/08 QA80-12526 v8.0965b ADD_BACKWARD_COMPATIABLE
	//NLFitSessionBase fit(false);
	NLFitSession 		fit;
	fit.SetAutoInitParams(false);
	/// end ADD_BACKWARD_COMPATIABLE
	if (!fit.SetFunction(strFuncName, strCategory ))
	{
		return false;
	}
	if (!fit.SetData(vy, vx))
	{
		return false;
	}
	if (!fit.ParamsInitValues())
	{
		return false;
	}
	vector vParams, vErrors;
	if (!fit.GetFitResultsParams(vParams, vErrors))
	{
		return false;
	}
	
	vParams[2] = nCenter;
	vParams[3] = nPower;
	
	int nFitOutcome;
	if (!fit.Fit(&nFitOutcome))
	{
		if (!fit.GetFitResultsParams(vParams, vErrors))
		{
			return false;
		}
	}
	
	if(nlsf_evaluate(strFuncName, strCategory, vCurveX, vCurveY, vParams))
	{
		return true;
	}
	
	return false;
}


bool create_curve_for_palette_edit(const vector& vx, const vector& vy, vector& vCurveX, vector& vCurveY, int nPts, int nCurveType)
{
	vector<uint> vN;
	vx.Sort(SORT_ASCENDING, true, vN);
	vy.Reorder(vN);
	
	int nSize = vx.GetSize();
	double dMin, dMax;
	dMin = vx[0];
	dMax = vx[nSize-1];
	vCurveX.Data(dMin, dMax, (dMax-dMin)/(nPts-1.0));
	vCurveY.SetSize(nPts);
	
	switch(nCurveType)
	{
	case LINE_SEGMENT_CURVE:
		return _line_segement_curve(vx, vy, vCurveX, vCurveY);
		
	case SPLINE_CURVE:
		return _spline_curve(vx, vy, vCurveX, vCurveY);
		
	case GUASSAMP_CURVE:
		string strFuncName = "GaussAmp";
		return nlsf_func_curve(vx, vy, strFuncName, vCurveX, vCurveY);
		
	case LOGISTIC_CURVE:
		string strFuncName = "Logistic";
		return nlsf_func_curve(vx, vy, strFuncName, vCurveX, vCurveY);		
	}
	
	return false;
}
///end ADD_CREATING_CURVES_FUNCTIONS_FOR_PALETTE_EDIT_TOOL

///Arvin 02/22/08 QA70-11151 SUPPORT_PARAMETERS_BRANCH_DYNAMICAL_ALLOCATION
#ifdef SUPPORT_PARAMETERS_BRANCH_DYNAMICAL_ALLOCATION
///---Sim 04-07-2008 QA80-11371 THEME_SAVING_OPTIONS
/*
int _get_prameter_number_from_theme(TreeNode& trTheme, vector<int>& vnIDs, vector<string>& vsValues)
{
	if(!trTheme)
		return 0;
	
	if(!octree_get_theme(&trTheme, &vnIDs, &vsValues, NULL))
		return 0;
	
	if(vnIDs.GetSize() < 1)
		return 0;
	int nNumParams = 0;
	vector<uint> vecIndex; 
	int nParamBaseID = IDE_NL_PARAMS_VALUE_BASE+1;
	while(vnIDs.Find(vecIndex, nParamBaseID, nParamBaseID) && vecIndex.GetSize() > 0)
	{
		nNumParams++;
		nParamBaseID++;
	}
	
	return nNumParams;
}

bool nlsf_construct_parameter_branch_by_theme_Tree(const TreeNode& trTheme, TreeNode& trGUI)
{
	if(!trTheme)
		return false;

	vector<int> vnIDs;
	vector<string> vsValues;
	int nNumParams = _get_prameter_number_from_theme(trTheme, vnIDs, vsValues);
	TreeNode 	trParams = nlsf_check_get_GUI_params_with_ID(trGUI, nNumParams); 
	if(nNumParams > 0 && trParams)
	{
		int nDupID = 0;
		int nn = tree_set_values_by_ids(trParams, vnIDs, vsValues, 0, &nDupID);
		return nn > 0 ? true : false;
	}
	return false;
}
*/
static int _get_prameter_number_from_theme(TreeNode& trTheme)
{
	if(!trTheme)
		return 0;
	
	vector<int> vnIDs;
	vector<string> vsValues;
	
	if(!octree_get_theme(&trTheme, &vnIDs, &vsValues, NULL))
		return 0;
	
	if(vnIDs.GetSize() < 1)
		return 0;
	int nNumParams = 0;
	vector<uint> vecIndex; 
	int nParamBaseID = IDE_NL_PARAMS_VALUE_BASE+1;
	while(vnIDs.Find(vecIndex, nParamBaseID, nParamBaseID) && vecIndex.GetSize() > 0)
	{
		nNumParams++;
		nParamBaseID++;
	}
	
	return nNumParams;
}
bool nlsf_construct_parameter_branch_by_theme_Tree(const TreeNode& trTheme, TreeNode& trGUI)
{
	if(!trTheme)
		return false;

	int nNumParams = _get_prameter_number_from_theme(trTheme);
	TreeNode 	trParams = nlsf_check_get_GUI_params_with_ID(trGUI, nNumParams); 
	if ( !trParams )
		return false;
	return true;
}

/*
static void _go_through_parent_to_allow_apply(TreeNode& tr, const TreeNode& trRoot)
{
	TreeNode trParent = tr;
	while( trParent.tagName != trRoot.tagName )
	{
		trParent = trParent.Parent();
		if ( !trParent )
			return;
		trParent.SetAttribute(STR_XVARIABLE_THEME_APPLICABILITY_ATTRIB, 0); // allow apply
	}
}

static void _set_apply_attribute(TreeNode& trRoot, int nDestNodeID, bool bApply, bool bDoApplyKeeyAttr = false)
{
	TreeNode trDest;
	if ( nDestNodeID < 0 )
		return;
	else if ( 0 == nDestNodeID )
		trDest = trRoot;
	else
		trDest = tree_get_node_by_id(trRoot, nDestNodeID, true);
	if ( !trDest )
		return;
	
	int n = (bApply) ? 0 : XVTA_DO_NOT_APPLY_VALUE|XVTA_DO_NOT_APPLY_ATTRIBUTES;
	string str = n;

	if ( !(bDoApplyKeeyAttr && bApply) )
		tree_set_attribute_to_all_nodes(trDest, STR_XVARIABLE_THEME_APPLICABILITY_ATTRIB, str);
	
	if ( bApply )
		_go_through_parent_to_allow_apply(trDest, trRoot);
}

static void _set_apply_attribute(TreeNode& trRoot, int nDestNodeID, const TreeNode& trThemeFilter, int nSettingNodeID, bool bDoApplyKeeyAttr = false)
{
	if ( !trThemeFilter || !trRoot )
		return;
	
	TreeNode trSetting = tree_get_node_by_id(trThemeFilter, nSettingNodeID, true);
	if ( !trSetting )
		return;
	
	bool bApply = trSetting.nVal;
	
	_set_apply_attribute(trRoot, nDestNodeID, bApply, bDoApplyKeeyAttr);
}

bool nlsf_setup_theme_filter_setting(TreeNode& trGUI, const TreeNode& trThemeFilter, const vector<int>& vnGUIID, const vector<int>& vnThemeFilterID)
{
	// other options must be dealt first
	_set_apply_attribute(trGUI, 0, 						trThemeFilter, IDE_THEME_FILTER_OTHER, true);
	
	// separater options will overwirte trGUI again
	/#
	_set_apply_attribute(trGUI, IDE_NLSF_FUNCTION,			trThemeFilter, IDE_NL_THEME_FILTER_FUNC);
	_set_apply_attribute(trGUI, IDE_NLSF_CATEGORY,			trThemeFilter, IDE_NL_THEME_FILTER_FUNC);
	_set_apply_attribute(trGUI, IDE_NL_PARAMS_VALUE_BASE,	trThemeFilter, IDE_NL_THEME_FILTER_PARAMS);
	_set_apply_attribute(trGUI, IDE_NL_PARAMS_FIXED_BASE,	trThemeFilter, IDE_NL_THEME_FILTER_FIXED);
	_set_apply_attribute(trGUI, IDE_NL_PARAMS_SHARE_BASE,	trThemeFilter, IDE_NL_THEME_FILTER_SHARE);
	_set_apply_attribute(trGUI, IDE_NL_PARAMS_LOWER_BOUNDS_BASE,	trThemeFilter, IDE_NL_THEME_FILTER_ULB);
	_set_apply_attribute(trGUI, IDE_NL_PARAMS_UPPER_BOUNDS_BASE,	trThemeFilter, IDE_NL_THEME_FILTER_ULB);
	_set_apply_attribute(trGUI, IDE_NLSF_CODES_CONSTRAINTS,	trThemeFilter, IDE_NL_THEME_FILTER_CONSTRAINTS);
	_set_apply_attribute(trGUI, IDE_NLSF_CODES_AFTERFIT,	trThemeFilter, IDE_NL_THEME_FILTER_SCRIPT);
	_set_apply_attribute(trGUI, IDE_NL_PARAMS_AUTO_INIT,	trThemeFilter, IDE_NL_THEME_FILTER_AUTO_PARAM_INIT);
	_set_apply_attribute(trGUI, IDE_NL_LINEAR_CONSTRAINTS,	trThemeFilter, IDE_NL_THEME_FILTER_ENABLE_LINEAR_CONSTRAINTS);
	#/
	ASSERT(vnGUIID.GetSize() == vnThemeFilterID.GetSize());
	for ( int ii = 0; ii < vnThemeFilterID.GetSize(); ii++ )
	{
		_set_apply_attribute(trGUI, vnGUIID[ii], trThemeFilter, vnThemeFilterID[ii]);
	}
	
	_set_apply_attribute(trGUI, IDE_DS_THEME_FILTER, true); // theme setting should always been kept
	return true;
}
*/

void nlsf_get_theme_filter_id_array(vector<int>& vnGUIID, vector<int>& vnThemeFilterID)
{
	vnGUIID.SetSize(0);
	vnThemeFilterID.SetSize(0);
	
	vnGUIID.Add(IDE_NLSF_FUNCTION);
	vnThemeFilterID.Add(IDE_NL_THEME_FILTER_FUNC);
	
	vnGUIID.Add(IDE_NLSF_CATEGORY);
	vnThemeFilterID.Add(IDE_NL_THEME_FILTER_FUNC);
	
	vnGUIID.Add(IDE_NL_PARAMS_VALUE_BASE);
	vnThemeFilterID.Add(IDE_NL_THEME_FILTER_PARAMS);
	
	vnGUIID.Add(IDE_NL_PARAMS_FIXED_BASE);
	///------ Folger 12/18/09 QA81-14859 THEME_SETTINGS_SUPPORT_APPLY_FIXED_STATUS_ONLY
	//vnThemeFilterID.Add(IDE_NL_THEME_FILTER_FIXED);
	vnThemeFilterID.Add(MAKELONG(IDE_NL_THEME_FILTER_FIXED, IDE_NL_THEME_FILTER_FIXED_ONLY));
	///------ End THEME_SETTINGS_SUPPORT_APPLY_FIXED_STATUS_ONLY
	
	/// Iris 4/21/2008 QA80-11371 SAVE_FIX_VALUE_WITH_TOGETHER_WITH_FIX_STATUS
	vnGUIID.Add(IDE_NL_PARAMS_FIXED_VALUE_BASE);
	vnThemeFilterID.Add(IDE_NL_THEME_FILTER_FIXED);
	///END SAVE_FIX_VALUE_WITH_TOGETHER_WITH_FIX_STATUS
	
	vnGUIID.Add(IDE_NL_PARAMS_SHARE_BASE);
	vnThemeFilterID.Add(IDE_NL_THEME_FILTER_SHARE);
	
	vnGUIID.Add(IDE_NL_PARAMS_LOWER_BOUNDS_BASE);
	vnThemeFilterID.Add(IDE_NL_THEME_FILTER_ULB);
	
	vnGUIID.Add(IDE_NL_PARAMS_UPPER_BOUNDS_BASE);
	vnThemeFilterID.Add(IDE_NL_THEME_FILTER_ULB);
	
	vnGUIID.Add(IDE_NLSF_CODES_CONSTRAINTS);
	vnThemeFilterID.Add(IDE_NL_THEME_FILTER_CONSTRAINTS);
	
	vnGUIID.Add(IDE_NLSF_CODES_AFTERFIT);
	vnThemeFilterID.Add(IDE_NL_THEME_FILTER_SCRIPT);
	
	vnGUIID.Add(IDE_NL_PARAMS_AUTO_INIT);
	vnThemeFilterID.Add(IDE_NL_THEME_FILTER_AUTO_PARAM_INIT);
	
	vnGUIID.Add(IDE_NL_LINEAR_CONSTRAINTS);
	vnThemeFilterID.Add(IDE_NL_THEME_FILTER_ENABLE_LINEAR_CONSTRAINTS);
	
	vnGUIID.Add(IDE_NLSF_CODES_PARAINIT);
	vnThemeFilterID.Add(IDE_NL_THEME_FILTER_CODES_PARAINIT);
}

//------ Folger 04/11/08 APPLY_FDF_ORIGINAL_SETTING_AFTER_APPLY_THEME
//static bool _apply_fdf(TreeNode& trGUI)
//{
	//// need to do
	//return true;
//}
bool apply_fdf(TreeNode& trGUI, LPCSTR lpcszFunctionName)// = NULL)
{
	vector<int> vnDataIDs = {
		IDE_NL_PARAMS_AUTO_INIT,
		IDE_NLSF_CODES_PARAINIT,
		IDE_NL_LINEAR_CONSTRAINTS,
		IDE_NLSF_CODES_CONSTRAINTS,
		IDE_NLSF_CODES_AFTERFIT,
		IDE_NLSF_CODES_DERIVATIVE, ///Sophy 10/20/2008 QA80-12406 ADD_DERIVATIVE_PARAM_PAGE_IN_CODE_TAB_OF_NLFIT_DLG
		IDE_NLSF_CODES_FUNC
	};
	
	bool	bAlwaysGetFromFDF = false;
	string	strFuncName;
	TreeNode trFunctionSelection = trGUI.FunctionSelection;
	if ( trFunctionSelection )
	{
		ASSERT(trFunctionSelection.FunctionList);
		strFuncName = trFunctionSelection.FunctionList.strVal;
	}
	
	else
	{
		strFuncName = lpcszFunctionName;
		bAlwaysGetFromFDF = true;		//if trGUI did not contain function name, assume that theme is reseted
	}
		
	if ( strFuncName.IsEmpty() )
		return false;
	
	Tree trFDF;
	if ( !nlsf_load_fdf_tree(trFDF, strFuncName) )
		return false;
	
	for ( int ii=0; ii<vnDataIDs.GetSize(); ++ii )
	{
		TreeNode trNode = tree_get_node_by_id(trGUI, vnDataIDs[ii], true);
		if ( trNode )
		{
			int nVal = -1;		//invalid
			trNode.GetAttribute(STR_XVARIABLE_THEME_APPLICABILITY_ATTRIB, nVal);
			if ( !bAlwaysGetFromFDF && (nVal&XVTA_DO_NOT_APPLY_VALUE) == 0 )
				continue;
			
			switch ( vnDataIDs[ii] )
			{
			case IDE_NL_PARAMS_AUTO_INIT:
				{
					bool bAutoInit = true;
					nlf_is_auto_init_params(trFDF, bAutoInit);
					trNode.nVal = bAutoInit;
				}
				break;
			
			case IDE_NLSF_CODES_PARAINIT:
				{
					TreeNode trParamsInitScript = trFDF.ParametersInitialization.Script;
					if ( trParamsInitScript )
						trNode.strVal = trParamsInitScript.strVal;
				}
				break;
				
			case IDE_NL_LINEAR_CONSTRAINTS:
				{
					bool bConstraints = true;
					nlf_is_enable_linear_constraints(trFDF, bConstraints);
					trNode.nVal = bConstraints;
				}
				break;
				
			case IDE_NLSF_CODES_CONSTRAINTS:
				{
					TreeNode trConstraintsScript = trFDF.CONSTRAINTS.Script;
					if ( trConstraintsScript )
						trNode.strVal = trConstraintsScript.strVal;
				}
				break;
				
			case IDE_NLSF_CODES_AFTERFIT:
				{
					TreeNode trAfterFitScript = trFDF.AFTERFITTING.Script;
					if ( trAfterFitScript )
						trNode.strVal = trAfterFitScript.strVal;
				}
				break;
			///Sophy 10/20/2008 QA80-12406 ADD_DERIVATIVE_PARAM_PAGE_IN_CODE_TAB_OF_NLFIT_DLG
			case IDE_NLSF_CODES_DERIVATIVE:
				{
					trNode.strVal = nlsf_get_deriv_param_codes( trFDF );
				}
				break;
			///end ADD_DERIVATIVE_PARAM_PAGE_IN_CODE_TAB_OF_NLFIT_DLG
			case IDE_NLSF_CODES_FUNC:
				{
					TreeNode trFormula = trFDF.FORMULA.Script;
					if ( trFormula )
						trNode.strVal = trFormula.strVal;
				}
				break;
				
			default:
				break;
			}
		}
	}
	
	return true;
}
//------ End APPLY_FDF_ORIGINAL_SETTING_AFTER_APPLY_THEME

//bool is_param_in_theme_filter_setting(TreeNode& trGUI)
//{
	//TreeNode trDS = get_external_settings_branch(trGUI);
	//
	//TreeNode trThemeFilter = tree_get_node_by_id(trDS, IDE_DS_THEME_FILTER, true);
	//if ( trThemeFilter )
	//{
		//TreeNode tr = tree_get_node_by_id(trThemeFilter, IDE_NL_THEME_FILTER_PARAMS, true);
		//if ( tr )
		//{
			//return (tr.nVal);
		//}
	//}
	//
	//return true; // default parameters in theme
//}

///Sophy 12/19/2008 v8.0988c QA80-12798 SKIP_THEME_APPLIED_TO_OUTPUT_DISABLED_NODE_WHEN_CHANGE_PARAMS
void _update_output_filter_one_branch(TreeNode& trBookSheetBranch)
{
	if ( !trBookSheetBranch )
		return;
	
	int nSkipTheme = 0;
	if ( trBookSheetBranch.GetAttribute(STR_SKIP_THEME_ATTRIB, nSkipTheme) && 1 == nSkipTheme )
	{
		int nAppliability = XVTA_DO_NOT_APPLY_VALUE|XVTA_DO_NOT_APPLY_ATTRIBUTES;
		string	strAppliabitily = nAppliability;
		tree_set_attribute_to_all_nodes(trBookSheetBranch, STR_XVARIABLE_THEME_APPLICABILITY_ATTRIB, strAppliabitily);
	}
}

void _update_output_filter_settings(TreeNode& trGUI)
{
	TreeNode trOutput = tree_get_node_by_tagname(trGUI, "Output", true);
	if ( !trOutput )
		return;
	
	if( trOutput.Report )
		_update_output_filter_one_branch( trOutput.Report );
		
	if( trOutput.Data )
		_update_output_filter_one_branch( trOutput.Data );
	
	if( trOutput.Residual )
		_update_output_filter_one_branch( trOutput.Residual );
		
	if( trOutput.FindXY )
		_update_output_filter_one_branch( trOutput.FindXY );
}
///end SKIP_THEME_APPLIED_TO_OUTPUT_DISABLED_NODE_WHEN_CHANGE_PARAMS

//------ Folger 04/11/08 APPLY_FDF_ORIGINAL_SETTING_AFTER_APPLY_THEME
//bool nlsf_apply_theme(LPCSTR lpcszClassName, TreeNode& trGUI, LPCSTR lpcszThemeName, bool bLoadFactDefault)// = true
bool nlsf_apply_theme(LPCSTR lpcszClassName, TreeNode& trGUI, LPCSTR lpcszThemeName, bool bLoadFactDefault, LPCSTR lpcszFunctionName)// = true, = NULL
//------
{
	//------ CPY 8/24/08 QA70-12878 NLFIT_TOO_SLOW_TO_OPEN
#ifdef _DEBUG
	//Profiler __junk(20);
#endif
	//-----
	Tree trGUIBackup;
	trGUIBackup.Replace(trGUI);
	
	Tree trThemeFilter;
	Tree trTheme;
	
	TreeNode trDS = get_external_settings_branch(trGUI);
	TreeNode tr = tree_get_node_by_id(trDS, IDE_DS_THEME_FILTER, true);
	if ( tr )
		trThemeFilter.Replace(tr);
	
	_update_output_filter_settings(trGUI);///Sophy 12/19/2008 v8.0988c QA80-12798 SKIP_THEME_APPLIED_TO_OUTPUT_DISABLED_NODE_WHEN_CHANGE_PARAMS
	
	///---Sim 09-05-2008 QA80-12151 NLFIT_TOO_SLOW_TO_OPEN
	//theme_apply_analysis_theme(lpcszClassName, trThemeFilter, lpcszThemeName, bLoadFactDefault, trTheme);
	if ( !theme_is_factory_default(lpcszThemeName) )
	{
		theme_apply_analysis_theme(lpcszClassName, trThemeFilter, lpcszThemeName, false, trTheme);
	///---END QA80-12151 NLFIT_TOO_SLOW_TO_OPEN
		nlsf_construct_parameter_branch_by_theme_Tree(trTheme, trGUI); // set variable size of parameter
		if ( !trThemeFilter.IsEmpty() )
		{
			vector<int> vnGUIID;
			vector<int> vnThemeFilterID;
			nlsf_get_theme_filter_id_array(vnGUIID, vnThemeFilterID);
			theme_setup_theme_filter_setting(trGUI, trThemeFilter, vnGUIID, vnThemeFilterID);
		}
	///---Sim 09-05-2008 QA80-12151 NLFIT_TOO_SLOW_TO_OPEN
	}
	else
	{
		nlsf_construct_parameter_branch_by_theme_Tree(trTheme, trGUI); // set variable size of parameter
	}
	///---END QA80-12151 NLFIT_TOO_SLOW_TO_OPEN
	
	bool bRet;
	//temporary solution for empty theme in NLFit
	//bRet = theme_apply_analysis_theme(lpcszClassName, trGUI, lpcszThemeName, bLoadFactDefault);
	bRet = theme_apply_analysis_theme(lpcszClassName, trGUI, lstrlen(lpcszThemeName) == 0 ? THEME_FILENAME_FACTORY_DEFAULT : lpcszThemeName, bLoadFactDefault);
	if (bRet)
		//------ Folger 04/11/08 APPLY_FDF_ORIGINAL_SETTING_AFTER_APPLY_THEME
		//bRet = _apply_fdf(trGUI);
		bRet = apply_fdf(trGUI, lpcszFunctionName);		
		//------

	// restore theme apply attribute
	octree_remove_attribute(&trGUI, STR_XVARIABLE_THEME_APPLICABILITY_ATTRIB);
	octree_copy_atts_by_id(&trGUIBackup, &trGUI, STR_XVARIABLE_THEME_APPLICABILITY_ATTRIB);
	
	return true;
}
///---END QA80-11371 THEME_SAVING_OPTIONS
#endif
///end SUPPORT_PARAMETERS_BRANCH_DYNAMICAL_ALLOCATION

///---Sim 04-10-2008 QA80-11371 THEME_SAVING_OPTIONS_FOR_WIZ
///---Sim 04-22-2008 QA80-11371 THEME_SAVING_OPTIONS_HINT
static bool OnShowHint(TreeNode& tr, int nRow, int nCol, TreeNode& trNode, DWORD nEventInfo, int nCntrlType, WndContainer& getNContainer)
{
	// Important!!!	// Assume Hint treenode is next to Checkbox
	TreeNode trHint = trNode.NextNode;
	if ( trHint )
	{
		trHint.Show = trNode.nVal;
	}
	return true;
}
///---END QA80-11371 THEME_SAVING_OPTIONS_HINT
/*
When any checkbox expect "Other Settings" is checked, "Function Type" should be checked. 
On the other hand, when "Function Type" is unchecked, any checkbox expect "Other Settings" should be unchecked. 

when "Fixed Status" is checked, "Parameter Values" should be checked too.
when "Parameter Values" is unchecked, "Fixed Status" should be unchecked too.
*/
static bool OnFuncSettingChange(TreeNode& tr, int nRow, int nCol, TreeNode& trNode, DWORD nEventInfo, int nCntrlType, WndContainer& getNContainer)
{
	if ( 1 == trNode.nVal )
	{
		TreeNode trParent = trNode.Parent();
		TreeNode trFuncType = tree_get_node_by_id(trParent, IDE_NL_THEME_FILTER_FUNC);
		if ( trFuncType )
			trFuncType.nVal = 1;
	}
	return true;
}
static bool OnFuncTypeChange(TreeNode& tr, int nRow, int nCol, TreeNode& trNode, DWORD nEventInfo, int nCntrlType, WndContainer& getNContainer)
{
	if ( 0 == trNode.nVal )
	{
		TreeNode trParent = trNode.Parent();
		vector<int> vnIDs = {IDE_NL_THEME_FILTER_CODES_PARAINIT, IDE_NL_THEME_FILTER_AUTO_PARAM_INIT,
							IDE_NL_THEME_FILTER_PARAMS, IDE_NL_THEME_FILTER_FIXED, IDE_NL_THEME_FILTER_SHARE, IDE_NL_THEME_FILTER_ULB, 
							IDE_NL_THEME_FILTER_ENABLE_LINEAR_CONSTRAINTS, IDE_NL_THEME_FILTER_CONSTRAINTS, IDE_NL_THEME_FILTER_SCRIPT};
		vector<string> vsValues;
		vsValues.SetSize(vnIDs.GetSize());
		for (int ii = 0; ii < vsValues.GetSize(); ii++ )
			vsValues[ii] = 0;
		
		tree_set_values_by_ids(trParent, vnIDs, vsValues);
	}
	return true;
}
static bool OnParamValuesChange(TreeNode& tr, int nRow, int nCol, TreeNode& trNode, DWORD nEventInfo, int nCntrlType, WndContainer& getNContainer)
{
	///---Sim 04-22-2008 QA80-11371 SAVE_FIX_VALUE_WITH_TOGETHER_WITH_FIX_STATUS
	/*
	if ( 0 == trNode.nVal )
	{
		TreeNode trParent = trNode.Parent();
		TreeNode trFixed = tree_get_node_by_id(trParent, IDE_NL_THEME_FILTER_FIXED);
		if ( trFixed )
			trFixed.nVal = 0;
	}
	*/
	///---END QA80-11371 SAVE_FIX_VALUE_WITH_TOGETHER_WITH_FIX_STATUS
	///---Sim 04-22-2008 QA80-11371 THEME_SAVING_OPTIONS_HINT
	OnShowHint(tr, nRow, nCol, trNode, nEventInfo, nCntrlType, getNContainer);
	///---END QA80-11371 THEME_SAVING_OPTIONS_HINT
	
	return OnFuncSettingChange(tr, nRow, nCol, trNode, nEventInfo, nCntrlType, getNContainer);
}

/// Iris 4/21/2008 QA80-11371 SAVE_FIX_VALUE_WITH_TOGETHER_WITH_FIX_STATUS
/*
static bool OnFixedChange(TreeNode& tr, int nRow, int nCol, TreeNode& trNode, DWORD nEventInfo, int nCntrlType, WndContainer& getNContainer)
{
	if ( 1 == trNode.nVal )
	{
		TreeNode trParent = trNode.Parent();
		TreeNode trParamValues = tree_get_node_by_id(trParent, IDE_NL_THEME_FILTER_PARAMS);
		if ( trParamValues )
			trParamValues.nVal = 1;
	}
	return OnFuncSettingChange(tr, nRow, nCol, trNode, nEventInfo, nCntrlType, getNContainer);
}
*/
///end SAVE_FIX_VALUE_WITH_TOGETHER_WITH_FIX_STATUS
///------ Folger 12/18/09 QA81-14859 THEME_SETTINGS_SUPPORT_APPLY_FIXED_STATUS_ONLY
static bool OnFixedChange(TreeNode& tr, int nRow, int nCol, TreeNode& trNode, DWORD nEventInfo, int nCntrlType, WndContainer& getNContainer)
{
	if ( trNode.DataID == IDE_NL_THEME_FILTER_FIXED_ONLY && 1 == trNode.nVal )
	{
		TreeNode trFixedValue = tree_get_node_by_id(tr, IDE_NL_THEME_FILTER_FIXED, true);
		if ( trFixedValue )
			trFixedValue.nVal = 0.
	}
	else if ( trNode.DataID == IDE_NL_THEME_FILTER_FIXED && 1 == trNode.nVal )
	{
		TreeNode trFixed = tree_get_node_by_id(tr, IDE_NL_THEME_FILTER_FIXED_ONLY, true);
		if ( trFixed )
			trFixed.nVal = 0.
	}
	
	return OnFuncSettingChange(tr, nRow, nCol, trNode, nEventInfo, nCntrlType, getNContainer);
}
///------ End THEME_SETTINGS_SUPPORT_APPLY_FIXED_STATUS_ONLY

void nlsf_construct_theme_filter(TreeNode& trThemeFilter, bool bAddOther) // = true
{
	GETN_USE(trThemeFilter)
		/// Hong 08/22/08 v8.0928 BETTER_LABEL_AVOID_CONFUSING
		//GETN_CHECK(FunctionList, _L("Function Type"), 1)	GETN_ID(IDE_NL_THEME_FILTER_FUNC)
		GETN_CHECK(FunctionList, _L("Function Selection"), 1)	GETN_ID(IDE_NL_THEME_FILTER_FUNC)
		/// end BETTER_LABEL_AVOID_CONFUSING
			GETN_OPTION_EVENT_EX(OnFuncTypeChange)
		GETN_CHECK(ParaInitCode, _L("Parameter Initialization code"), 0)	GETN_ID(IDE_NL_THEME_FILTER_CODES_PARAINIT)
			GETN_OPTION_EVENT_EX(OnFuncSettingChange)
		GETN_CHECK(AutoParamsInit, _L("Auto Parameter Initialization Status"), 0)	GETN_ID(IDE_NL_THEME_FILTER_AUTO_PARAM_INIT)
			GETN_OPTION_EVENT_EX(OnFuncSettingChange)
		GETN_CHECK(Values, _L("Parameter Values"), 0)	GETN_ID(IDE_NL_THEME_FILTER_PARAMS)
			GETN_OPTION_EVENT_EX(OnParamValuesChange)
		///---Sim 04-22-2008 QA80-11371 THEME_SAVING_OPTIONS_HINT
		// Important!!! Hint must next to Checkbox treenode
		GETN_STR(ValuesHint, _L("This option will not take effect if Auto Parameter Initialization is enabled in your function or theme"), "")	GETN_HINT
		///---END QA80-11371 THEME_SAVING_OPTIONS_HINT			
		/// Iris 4/21/2008 QA80-11371 SAVE_FIX_VALUE_WITH_TOGETHER_WITH_FIX_STATUS
		//GETN_CHECK(Fixed, _L("Fixed Status"), 0)	GETN_ID(IDE_NL_THEME_FILTER_FIXED)
			//GETN_OPTION_EVENT_EX(OnFixedChange)
		///------ Folger 12/18/09 QA81-14859 THEME_SETTINGS_SUPPORT_APPLY_FIXED_STATUS_ONLY
		GETN_CHECK(FixedOnly, _L("Fixed Status Only"), 0)				GETN_ID(IDE_NL_THEME_FILTER_FIXED_ONLY)
			GETN_OPTION_EVENT_EX(OnFixedChange)
		///------ End THEME_SETTINGS_SUPPORT_APPLY_FIXED_STATUS_ONLY
		GETN_CHECK(Fixed, _L("Fixed Status and Fixed Value"), 0)	GETN_ID(IDE_NL_THEME_FILTER_FIXED)
			///------ Folger 12/18/09 QA81-14859 THEME_SETTINGS_SUPPORT_APPLY_FIXED_STATUS_ONLY
			//GETN_OPTION_EVENT_EX(OnFuncSettingChange)
			GETN_OPTION_EVENT_EX(OnFixedChange)
			///------ End THEME_SETTINGS_SUPPORT_APPLY_FIXED_STATUS_ONLY
		///end SAVE_FIX_VALUE_WITH_TOGETHER_WITH_FIX_STATUS
		GETN_CHECK(Share, _L("Share Status"), 1)	GETN_ID(IDE_NL_THEME_FILTER_SHARE)
			GETN_OPTION_EVENT_EX(OnFuncSettingChange)
		GETN_CHECK(UpperLowerBounds, _L("Upper and Lower Bounds"), 0)	GETN_ID(IDE_NL_THEME_FILTER_ULB)
			GETN_OPTION_EVENT_EX(OnFuncSettingChange)
		GETN_CHECK(LinearConstraints, _L("Enable Linear Constraints Status"), 0)	GETN_ID(IDE_NL_THEME_FILTER_ENABLE_LINEAR_CONSTRAINTS)
			GETN_OPTION_EVENT_EX(OnFuncSettingChange)
		GETN_CHECK(Constraints, _L("Constraints"), 0)	GETN_ID(IDE_NL_THEME_FILTER_CONSTRAINTS)
			GETN_OPTION_EVENT_EX(OnFuncSettingChange)
		GETN_CHECK(AfterFit, _L("Script after Fitting"), 0)	GETN_ID(IDE_NL_THEME_FILTER_SCRIPT)
			GETN_OPTION_EVENT_EX(OnFuncSettingChange)
	if ( bAddOther )
	{
		GETN_CHECK(Other, _L("Other Settings"), 1)	GETN_ID(IDE_THEME_FILTER_OTHER)
	}
}
///---END QA80-11371 THEME_SAVING_OPTIONS_FOR_WIZ	

///Jasmine 04/14/08 SIM_ASK_CONVERT_PA_FIT_TREE_DATA_ID
int pa_fit_convert_data_id_for_theme_saving(const TreeNode& trGetN, vector<int>& vnIDs)
{
	if(!trGetN)
		return -1;
	
	vector<int> vnIDsNeedConvert = {IDE_NLSF_CATEGORY, 
									IDE_NLSF_CODES_AFTERFIT, 
									IDE_NLSF_CODES_CONSTRAINTS,	IDE_NL_LINEAR_CONSTRAINTS,
									IDE_NLSF_CODES_PARAINIT};
	vector<int> vnDataIDs 	= {	IDE_NLSF_FUNCTION,	IDE_NL_PARAMS_AUTO_INIT,	///Jasmine 04/17/08 PEAK_FIT_USE_SAME_FUNCTION_ID_AS_NLFIT
								IDE_NL_PARAMS_VALUE_BASE, 
								IDE_NL_PARAMS_FIXED_BASE,	IDE_NL_PARAMS_FIXED_VALUE_BASE, 
								IDE_NL_PARAMS_SHARE_BASE, 
								IDE_NL_PARAMS_LOWER_BOUNDS_BASE, IDE_NL_PARAMS_UPPER_BOUNDS_BASE}; 
	
	
	bool 	bReplace 		= 0 != vnIDs.GetSize();
	int 	nBackupIDSize	= vnIDsNeedConvert.GetSize();
	for(int ii = 0; ii < nBackupIDSize; ii++)
	{
		int nConvertID = vnIDsNeedConvert[ii];
		int nIndex = -1;
		if(bReplace)
		{
			vector<uint> vecIndex;
			if( 0 < vnIDs.Find(vecIndex, nConvertID) )
				nIndex = vecIndex[0];
			else
				continue;
		}
		
		int nDataID = -1;
		TreeNode trNode = trGetN.FindNodeByAttribute(STR_BACKUP_ID_ATTRIB, nConvertID);
		if(trNode)
			trNode.GetAttribute(STR_DATAID_ATTRIB, nDataID);
		
		if(bReplace)
			vnIDs[nIndex] = nDataID;
		else
			vnIDsNeedConvert[ii] = nDataID;
	}
	
	if( !bReplace )//reset all
	{
		vnIDs.Append(vnIDsNeedConvert);
		vnIDs.Append(vnDataIDs);
	}
	
	return vnIDs.GetSize();
}
///End SIM_ASK_CONVERT_PA_FIT_TREE_DATA_ID

///------ Folger 06/18/09 CENTRALIZE_CODE_ABOUT_GETTING_PEAK_FUNC_PARAM_INDICES
//bool nlsf_get_peak_param_indices(const TreeNode& trFDF, int* pnXCenter, int* pnXWidth)	//NULL, NULL
//{
	//if(!pnXCenter && !pnXWidth)
		//return false;
	//
	//if(trFDF && trFDF.Controls)
	//{
		//if(pnXCenter)
		//{
			//TreeNode trXCenter = trFDF.Controls.GetNode( cvt_str_to_tag_name(STR_FUNC_PEAK_CENTER) );
			//if(!trXCenter)
				//return false;
			//
			//int nXCenter = trXCenter.nVal;
			//*pnXCenter = nXCenter;
		//}
		//
		//if(pnXWidth)
		//{
			//TreeNode trXWidth = trFDF.Controls.GetNode( cvt_str_to_tag_name(STR_FUNC_PEAK_WIDTH) );
			//if(!trXWidth)
				//return false;
			//
			//int nXWidth = trXWidth.nVal;
			//*pnXWidth = nXWidth;
		//}
		//
		//return true;
	//}
	//
	//return false;
//}
//
//bool nlsf_get_2d_peak_param_indices(const TreeNode& trFDF, int* pnXCenter, int* pnYCenter, int* pnXWidth, int* pnYWidth)	//NULL, NULL, NULL, NULL
//{
	//if( nlsf_get_peak_param_indices(trFDF, pnXCenter, pnXWidth) )
	//{
		//if(pnYCenter)
		//{
			//TreeNode trYCenter = trFDF.Controls.GetNode( cvt_str_to_tag_name(STR_FUNC_PEAK_CENTER2) );
			//if(!trYCenter)
				//return false;
			//
			//int nYCenter = trYCenter.nVal;
			//*pnYCenter = nYCenter;			
		//}
		//
		//if(pnYWidth)
		//{
			//TreeNode trYWidth =  trFDF.Controls.GetNode( cvt_str_to_tag_name(STR_FUNC_PEAK_WIDTH2) );
			//if(!trYWidth)
				//return false;
			//
			//int nYWidth = trYWidth.nVal;
			//*pnYWidth = nYWidth;
		//}		
		//
		//return true;
	//}
	//
	//return false;
//}

static	BOOL	_nlsf_get_peak_param_indices(NLPEAKPARAMS& stNLPEAKPARAMS, const TreeNode& trFDF)
{
	NumericFunction		nf(trFDF);
	return nf.GetPeakParametersIndices(&stNLPEAKPARAMS);
}

bool nlsf_get_peak_param_indices(const TreeNode& trFDF, int* pnXCenter, int* pnXWidth, int* pnAmplitude/* = NULL*/)	//NULL, NULL
{
	if ( NULL == pnXCenter && NULL == pnXWidth )
		return false;
	
	NLPEAKPARAMS	stNLPEAKPARAMS;
	if ( !_nlsf_get_peak_param_indices(stNLPEAKPARAMS, trFDF) )
		return false;
	
	if ( NULL != pnXCenter )
		*pnXCenter = stNLPEAKPARAMS.nIndexCenter;
	if ( NULL != pnXWidth )
		*pnXWidth = stNLPEAKPARAMS.nIndexWidth;
	if ( NULL != pnAmplitude )
		*pnAmplitude = stNLPEAKPARAMS.nIndexAmplitude;
	
	return true;
}

bool nlsf_get_2d_peak_param_indices(const TreeNode& trFDF, int* pnXCenter, int* pnYCenter, int* pnXWidth, int* pnYWidth, int* pnAmplitude/* = NULL*/)	//NULL, NULL, NULL, NULL
{
	if ( NULL == pnXCenter && NULL == pnYCenter && NULL == pnXWidth && NULL == pnYWidth && NULL == pnAmplitude)
		return false;
	
	NLPEAKPARAMS	stNLPEAKPARAMS;
	if ( !_nlsf_get_peak_param_indices(stNLPEAKPARAMS, trFDF) )
		return false;
	
	if ( NULL != pnXCenter )
		*pnXCenter = stNLPEAKPARAMS.nIndexCenter;
	if ( NULL != pnYCenter )
		*pnYCenter = stNLPEAKPARAMS.nIndexCenter2;
	if ( NULL != pnXWidth )
		*pnXWidth = stNLPEAKPARAMS.nIndexWidth;
	if ( NULL != pnYWidth )
		*pnYWidth = stNLPEAKPARAMS.nIndexWidth2;
	if ( NULL != pnAmplitude )
		*pnAmplitude = stNLPEAKPARAMS.nIndexAmplitude;
	
	return true;
}
///------ End CENTRALIZE_CODE_ABOUT_GETTING_PEAK_FUNC_PARAM_INDICES

///------ Folger 06/18/09 CENTRALIZE_CODE_ABOUT_GETTING_PEAK_FUNC_PARAM_INDICES
//bool nlsf_get_peak_param_indices(LPCSTR lpcszFunction, LPCSTR lpcszCategory, int* pnXCenter, int* pnXWidth)	//NULL, NULL
bool nlsf_get_peak_param_indices(LPCSTR lpcszFunction, LPCSTR lpcszCategory, int* pnXCenter, int* pnXWidth, int* pnAmplitude/* = NULL*/)	//NULL, NULL
///------ End CENTRALIZE_CODE_ABOUT_GETTING_PEAK_FUNC_PARAM_INDICES
{
	if(!pnXCenter && !pnXWidth)
		return false;
	
	Tree trFDF;
	if( nlsf_load_fdf_tree(trFDF, lpcszFunction, lpcszCategory) )
	{
		///------ Folger 06/18/09 CENTRALIZE_CODE_ABOUT_GETTING_PEAK_FUNC_PARAM_INDICES
		//return nlsf_get_peak_param_indices(trFDF, pnXCenter, pnXWidth);
		return nlsf_get_peak_param_indices(trFDF, pnXCenter, pnXWidth, pnAmplitude);
		///------ End CENTRALIZE_CODE_ABOUT_GETTING_PEAK_FUNC_PARAM_INDICES
	}
	
	return false;
}

///------ Folger 06/18/09 CENTRALIZE_CODE_ABOUT_GETTING_PEAK_FUNC_PARAM_INDICES
//bool nlsf_get_2d_peak_param_indices(LPCSTR lpcszFunction, LPCSTR lpcszCategory, int* pnXCenter, int* pnYCenter, int* pnXWidth, int* pnYWidth)	//NULL, NULL, NULL, NULL
bool nlsf_get_2d_peak_param_indices(LPCSTR lpcszFunction, LPCSTR lpcszCategory, int* pnXCenter, int* pnYCenter, int* pnXWidth, int* pnYWidth, int* pnAmplitude/* = NULL*/)	//NULL, NULL, NULL, NULL
///------ End CENTRALIZE_CODE_ABOUT_GETTING_PEAK_FUNC_PARAM_INDICES
{
	if(!pnXCenter && !pnYCenter && !pnXWidth && !pnYWidth)
		return false;
	
	Tree trFDF;
	if( nlsf_load_fdf_tree(trFDF, lpcszFunction, lpcszCategory) )
	{
		///------ Folger 06/18/09 CENTRALIZE_CODE_ABOUT_GETTING_PEAK_FUNC_PARAM_INDICES
		//return nlsf_get_2d_peak_param_indices(trFDF, pnXCenter, pnYCenter, pnXWidth, pnYWidth);
		return nlsf_get_2d_peak_param_indices(trFDF, pnXCenter, pnYCenter, pnXWidth, pnYWidth, pnAmplitude);
		///------ End CENTRALIZE_CODE_ABOUT_GETTING_PEAK_FUNC_PARAM_INDICES
	}
	
	return false;
}
///Jasmine 07/30/08 PEAK_FIT_CHECK_GOOD_PEAK_FUNC
///Jasmine 11/20/09 QA80-14628 IMPROVE_FIND_MEANING_METHOD	
int peak_fit_get_offset_param(LPCSTR lpcstrParams, bool b2DFunc)
{
	//vector<string> vsPossibleName = {"offset", "base", "baseline"};
	//return _find_meaning(lpcstrMeaning, vsPossibleName);string strParams = trNames.strVal;
	string strParams(lpcstrParams);
	strParams.TrimLeft();
	
	string strOffset = STR_OFFSET_PARAM_NAME_PFM;
	if(b2DFunc)
		strOffset = STR_OFFSET_PARAM_NAME_SPFM;
	
	///Jasmine 07/14/10 ORG-486-S1 CENTRALIZE_PEAK_ATTRIB_TO_NLFIT
	//vector<string> vsPossibleName(1);
	//vsPossibleName[0] = strOffset;
	//return _find_peak_param_by_match_meaning(lpcstrParams, vsPossibleName);
	vector<string> vsParams;	
	okutil_get_tokens(lpcstrParams, &vsParams, PARAM_SEPERATE_CHAR, NULL);
	int nIndex = vsParams.Find(strOffset);
	return nIndex;
	///End CENTRALIZE_PEAK_ATTRIB_TO_NLFIT

}

///Jasmine 07/14/10 ORG-486-S1 CENTRALIZE_PEAK_ATTRIB_TO_NLFIT
static int _peak_fit_get_param_index(const TreeNode& trFunction, LPCSTR lpcszTagName)
{
	int nIndex = -1;
	
	if(trFunction)
	{
		TreeNode trNode = tree_get_node_by_tagname(trFunction, lpcszTagName, true, false, true);
		if(trNode)
			nIndex = trNode.nVal - 1;
	}
	
	return nIndex;
}

int peak_fit_get_center_param(const TreeNode& trFunction, bool bGetX)
{
	string strTagName = cvt_str_to_tag_name(bGetX? STR_FUNC_PEAK_CENTER:STR_FUNC_PEAK_CENTER2);
	return _peak_fit_get_param_index(trFunction, strTagName);
}
int peak_fit_get_center_param(LPCSTR lpcstrMeaning, bool bGetX)
{
	if(!bGetX)
	{
		vector<string> vsPossibleName = {"*y*center*", "*y*centre*"};
		return _find_peak_param_by_match_meaning(lpcstrMeaning, vsPossibleName);
	}
	
	vector<string> vsPossibleName = {"*x*center*", "*x*centre*", "*center*", "*centre*"};
	return _find_peak_param_by_match_meaning(lpcstrMeaning, vsPossibleName,  "*y*");	
}

int peak_fit_get_width_param(const TreeNode& trFunction, bool bGetX)
{	
	string strTagName = cvt_str_to_tag_name(bGetX? STR_FUNC_PEAK_WIDTH:STR_FUNC_PEAK_WIDTH2);
	return _peak_fit_get_param_index(trFunction, strTagName);
}
int peak_fit_get_width_param(LPCSTR lpcstrMeaning, bool bGetX)
{	
	if(!bGetX)
	{
		vector<string> vsPossibleName = {"*y*width*"};
		return _find_peak_param_by_match_meaning(lpcstrMeaning, vsPossibleName);
	}
	
	vector<string> vsPossibleName = {"*x*width*", "*width*"};
	return _find_peak_param_by_match_meaning(lpcstrMeaning, vsPossibleName,  "*y*");
}

int peak_fit_get_height_param(const TreeNode& trFunction)
{
	return _peak_fit_get_param_index( trFunction, cvt_str_to_tag_name(STR_FUNC_PEAK_AMPLITUDE) );
}
int peak_fit_get_height_param(LPCSTR lpcstrMeaning)
{
	vector<string> vsPossibleName = {"*amplitude*", "*area*", "*height*", "*amp*"};
	return _find_peak_param_by_match_meaning(lpcstrMeaning, vsPossibleName);
}

static int _find_peak_param_by_match_meaning(LPCSTR lpcstrMeaning, const vector<string>& vsMatch,  LPCSTR lpcstrExclude = NULL)
{
	string 	strMeaning(lpcstrMeaning);
	vector<string> vsMeaning;	
	if(strMeaning.GetTokens(vsMeaning, PARAM_SEPERATE_CHAR) <= 0)
		return -1;
	
	int nIndex = -1;	
	
	for(int ii = 0; ii < vsMatch.GetSize(); ii++)
	{
		string strMatch = vsMatch[ii];
		
		for(int jj = 0; jj < vsMeaning.GetSize(); jj++)
		{
			string strMeaning = vsMeaning[jj];
			if( !strMeaning.Match(strMatch) )
				continue;

			if( lpcstrExclude && strMeaning.Match(lpcstrExclude) )
				continue;
			
			nIndex = jj;
			break;
		}		

		if(nIndex != -1)
			break;
	}
	
	return nIndex;
}
///End IMPROVE_FIND_MEANING_METHOD	
///End CENTRALIZE_PEAK_ATTRIB_TO_NLFIT

bool peak_fit_is_peak_func(const TreeNode& trFDF, vector<string>* pvsInvalidParams/* = NULL*/)
{
	//vsInvalidParams.SetSize(0);
	vector<string>		vsInvalidParams;
	
	if(!trFDF)
		return error_report("trFDF is invalid");
	
	bool b2DFunc = 1 < nlf_get_independent_variables(trFDF);
	
	TreeNode trParams = trFDF.GetNode(cvt_str_to_tag_name(STR_FUNC_FIT_PARAM), false);
	if(!trParams)
		return error_report(STR_FUNC_FIT_PARAM + " node is missing");
	
	TreeNode trNames = trParams.GetNode(cvt_str_to_tag_name(STR_FUNC_NAMES), false);
	if(!trNames)
		return error_report(STR_FUNC_PARAMETER_NAMES + " node is missing");
	
	//TreeNode trMeanings = trParams.GetNode(cvt_str_to_tag_name(STR_PARAM_SETTING_MEANINGS), false);
	//if(!trMeanings)
		//return error_report(STR_PARAM_SETTING_MEANINGS + " node is missing");
	
	TreeNode trControl = trFDF.GetNode(cvt_str_to_tag_name(STR_FUNC_CONTROLS), false);
	if(!trControl)
		return error_report(STR_FUNC_CONTROLS + " node is missing");
	
	///Jasmine 07/28/10 ORG-486-P4 WRONG_DUPLICATE_OFFSET_LEAD_TO_RUNTIME_ERROR
	if(nlf_get_duplicate_offset(trFDF) <= 1)
		return error_report(STR_DUPLICATE_OFFSET + " is invalid");
	///End WRONG_DUPLICATE_OFFSET_LEAD_TO_RUNTIME_ERROR
	
	//1. offset param y0, first param
	int offsetparam = 0;
	if( offsetparam != peak_fit_get_offset_param(trNames.strVal, b2DFunc) )
		vsInvalidParams.Add(STR_OFFSET_PEAK_INFO);
	
	//2. center param
	TreeNode trCenter = trControl.GetNode(cvt_str_to_tag_name(STR_FUNC_PEAK_CENTER), false);
	if(!trCenter || trCenter.nVal <= 0)//1 offset
		vsInvalidParams.Add(STR_X_CENTER_PEAK_INFO);
	
	if(b2DFunc)
	{
		trCenter = trControl.GetNode(cvt_str_to_tag_name(STR_FUNC_PEAK_CENTER2), false);
		if(!trCenter || trCenter.nVal <= 0)//1 offset
			vsInvalidParams.Add(STR_Y_CENTER_PEAK_INFO);		
	}
		
	//3. width param
	TreeNode trWidth = trControl.GetNode(cvt_str_to_tag_name(STR_FUNC_PEAK_WIDTH), false);
	if(!trWidth || trWidth.nVal <= 0)//1 offset
		vsInvalidParams.Add(STR_X_WIDTH_PEAK_INFO);
	
	if(b2DFunc)
	{
		trWidth = trControl.GetNode(cvt_str_to_tag_name(STR_FUNC_PEAK_WIDTH2), false);
		if(!trWidth || trWidth.nVal <= 0)//1 offset
			vsInvalidParams.Add(STR_Y_WIDTH_PEAK_INFO);		
	}
	
	//4. height param
	///Kyle 11/05/2008 QA80-12509-P1 ADD_PEAK_AMPLITUDE_INTO_CONTROL_SESSION_OF_FO
	//if( -1 == peak_fit_get_height_param(trMeanings.strVal) )
	TreeNode trAmplitude = trControl.GetNode(cvt_str_to_tag_name(STR_FUNC_PEAK_AMPLITUDE), false);
	if(!trAmplitude || trAmplitude.nVal <= 0)//1 offset
	///End ADD_PEAK_AMPLITUDE_INTO_CONTROL_SESSION_OF_FO
		vsInvalidParams.Add(STR_AMPLITUDE_PEAK_INFO);
		
	if ( pvsInvalidParams != NULL )
		*pvsInvalidParams = vsInvalidParams;
	
	return 0 == vsInvalidParams.GetSize();
}

//for FO GUI
bool peak_fit_is_peak_func_ex(const TreeNode& trFuncGUI)
{
	if(!trFuncGUI)
		return error_report("trFuncGUI is invalid");
	
	vector<string> vsInvalidParams;
	
	vector<string> vsIndepVars;
	int nRet = okutil_get_tokens(trFuncGUI.GetNode(cvt_str_to_tag_name(STR_FUNC_INDEPENDENT_VARS), false).strVal, &vsIndepVars, PARAM_SEPERATE_CHAR, NULL);
	bool b2DFunc = nRet > 1;
	
	TreeNode trNames = trFuncGUI.GetNode(cvt_str_to_tag_name(STR_FUNC_PARAMETER_NAMES), false);
	if(!trNames)
		return error_report(STR_FUNC_PARAMETER_NAMES + " node is missing");
	
	TreeNode trControl = trFuncGUI.GetNode(cvt_str_to_tag_name(STR_FUNC_CONTROLS), false);
	if(!trControl)
		return error_report(STR_FUNC_CONTROLS + " node is missing");
	
	//1. offset param y0, first param
	int offsetparam = 0;
	if( offsetparam != peak_fit_get_offset_param(trNames.strVal, b2DFunc) )
		vsInvalidParams.Add(STR_OFFSET_PEAK_INFO);
	
	//2. center param
	TreeNode trCenter = trControl.GetNode(cvt_str_to_tag_name(STR_FUNC_PEAK_CENTER), false);
	if(!trCenter || trCenter.nVal <= 0)//1 offset
		vsInvalidParams.Add(STR_X_CENTER_PEAK_INFO);
	
	if(b2DFunc)
	{
		trCenter = trControl.GetNode(cvt_str_to_tag_name(STR_FUNC_PEAK_CENTER2), false);
		if(!trCenter || trCenter.nVal <= 0)//1 offset
			vsInvalidParams.Add(STR_Y_CENTER_PEAK_INFO);		
	}
		
	//3. width param
	TreeNode trWidth = trControl.GetNode(cvt_str_to_tag_name(STR_FUNC_PEAK_WIDTH), false);
	if(!trWidth || trWidth.nVal <= 0)//1 offset
		vsInvalidParams.Add(STR_X_WIDTH_PEAK_INFO);
	
	if(b2DFunc)
	{
		trWidth = trControl.GetNode(cvt_str_to_tag_name(STR_FUNC_PEAK_WIDTH2), false);
		if(!trWidth || trWidth.nVal <= 0)//1 offset
			vsInvalidParams.Add(STR_Y_WIDTH_PEAK_INFO);		
	}
	
	//4. height param
	///Kyle 11/05/2008 QA80-12509-P1 ADD_PEAK_AMPLITUDE_INTO_CONTROL_SESSION_OF_FO
	//if( -1 == peak_fit_get_height_param(trMeanings.strVal) )
	TreeNode trAmplitude = trControl.GetNode(cvt_str_to_tag_name(STR_FUNC_PEAK_AMPLITUDE), false);
	if(!trAmplitude || trAmplitude.nVal <= 0)//1 offset
	///End ADD_PEAK_AMPLITUDE_INTO_CONTROL_SESSION_OF_FO
		vsInvalidParams.Add(STR_AMPLITUDE_PEAK_INFO);
		
	
	return 0 == vsInvalidParams.GetSize();
}
///End PEAK_FIT_CHECK_GOOD_PEAK_FUNC


///Jasmine 07/14/10 ORG-486-S1 CENTRALIZE_PEAK_ATTRIB_TO_NLFIT


//if set it's not a peak function, bReset = true
bool set_duplicate_unit_for_peak_fit(TreeNode& trFunction, bool bReset/* = false*/)
{
	if(!trFunction || !trFunction.Controls)
		return false;
	
	vector<string> vsDuplicateNodes = {STR_DUPLICATE_NUM, STR_DUPLICATE_OFFSET, STR_DUPLICATE_UNIT};
	
	TreeNode trControls = trFunction.Controls;
	
	int nOffsetParamNum = 1;//it can only have one offset parameter y0(or z0)
		
	int nNumberOfDuplicates = 0;//always 0		
	int	nDuplicateOffset	= nOffsetParamNum + 1;		
	int nDuplicateUnit		= 0;
	
	TreeNode trNode = trFunction.GetNode(cvt_str_to_tag_name(STR_FUNC_GENERAL_INFO), false);
	if(trNode)
		trNode = trNode.GetNode(cvt_str_to_tag_name(STR_FUNC_NUM_PARAMS), false);
	if(trNode)
		nDuplicateUnit = trNode.nVal - nOffsetParamNum;
	
	for(int ii = 0; ii < vsDuplicateNodes.GetSize(); ii++)
	{
		string strTagName = cvt_str_to_tag_name(vsDuplicateNodes[ii]);
		if(bReset)
		{	
			TreeNode trNode = trControls.GetNode(strTagName, false);
			if(trNode)
				trNode.strVal = "N/A";
		}
		else
		{
			TreeNode trNode = tree_check_get_node(trControls, strTagName);
			if(lstrcmp(vsDuplicateNodes[ii], STR_DUPLICATE_NUM) == 0)
				trNode.nVal = nNumberOfDuplicates;
			else if(lstrcmp(vsDuplicateNodes[ii], STR_DUPLICATE_OFFSET) == 0)
				trNode.nVal = nDuplicateOffset;
			else if(lstrcmp(vsDuplicateNodes[ii], STR_DUPLICATE_UNIT) == 0)
				trNode.nVal = nDuplicateUnit;
		}
	}	
	
	return true;
}

//if set it's not a peak function
bool remove_peak_attributes_from_tree(TreeNode& trFunction)
{
	if(!trFunction || !trFunction.Controls)
		return false;
	TreeNode trControls = trFunction.Controls;

	vector<string> vsFDFNames = {STR_FUNC_PEAK_CENTER, STR_FUNC_PEAK_WIDTH,
								STR_FUNC_PEAK_CENTER2, STR_FUNC_PEAK_WIDTH2,
								STR_FUNC_PEAK_AMPLITUDE};
	
	for(int ii = 0; ii < vsFDFNames.GetSize(); ii++)
	{
		string strTagName = cvt_str_to_tag_name(vsFDFNames[ii]);
		TreeNode trNode = trControls.GetNode(strTagName, false);	
		if(trNode)
			trNode.Remove();
	}
	
	return true;
}

bool write_peak_attributes_to_tree(const vector<string>& vsPeakAttrib, TreeNode& trFunction)
{
	if(vsPeakAttrib.GetSize() < 4 || !trFunction || !trFunction.Controls)//4: offset, x center, x width, amplitude are necessary
	{
		ASSERT(0);
		return false;
	}
	TreeNode trControls = trFunction.Controls;
	
	vector<string> vsGUINames, vsFDFNames;	
	vector<int>	vnIDs;
	//no offset here
	vsGUINames.Add(STR_X_CENTER_PEAK_INFO);
	vsFDFNames.Add(STR_FUNC_PEAK_CENTER);
	vnIDs.Add(IDS_CONTROL_PEAK_CENTER_ARG_INDEX);
	
	vsGUINames.Add(STR_X_WIDTH_PEAK_INFO);
	vsFDFNames.Add(STR_FUNC_PEAK_WIDTH);
	vnIDs.Add(IDS_CONTROL_PEAK_WIDTH_ARG_INDEX);
	
	vsGUINames.Add(STR_Y_CENTER_PEAK_INFO);
	vsFDFNames.Add(STR_FUNC_PEAK_CENTER2);
	vnIDs.Add(IDS_CONTROL_PEAK_CENTER_ARG_INDEX_2);
	
	vsGUINames.Add(STR_Y_WIDTH_PEAK_INFO);
	vsFDFNames.Add(STR_FUNC_PEAK_WIDTH2);
	vnIDs.Add(IDS_CONTROL_PEAK_WIDTH_ARG_INDEX_2);
	
	vsGUINames.Add(STR_AMPLITUDE_PEAK_INFO);
	vsFDFNames.Add(STR_FUNC_PEAK_AMPLITUDE);
	vnIDs.Add(IDS_CONTROL_PEAK_AMPLITUDE_ARG_INDEX);
	
	for(int ii = 0; ii < vsGUINames.GetSize(); ii++)
	{
		string strGUIName = vsGUINames[ii], strFDFName = vsFDFNames[ii];
		int nIndex = vsPeakAttrib.Find(strGUIName);
		if(nIndex >= 0)
		{
			TreeNode trNode = tree_check_get_node(trControls, cvt_str_to_tag_name(strFDFName), vnIDs[ii]);
			trNode.nVal = nIndex + 1;//in FDF it's 1 offset			 
		}
		else
		{
			if( strFDFName.Compare(STR_FUNC_PEAK_CENTER) == 0 
				|| strFDFName.Compare(STR_X_WIDTH_PEAK_INFO) == 0 
				|| strFDFName.Compare(STR_AMPLITUDE_PEAK_INFO) == 0 )
			{
				ASSERT(0);
			}
			
			TreeNode trNode = trControls.GetNode(cvt_str_to_tag_name(strFDFName), false);	
			if(trNode)
				trNode.Remove();
		}
	}
	
	return true;
}
///End CENTRALIZE_PEAK_ATTRIB_TO_NLFIT

class OneCurveDataPointerManager
{
public:
	OneCurveDataPointerManager()
	{
		m_pOneCruveData = new OneCurveData;
	}
	~OneCurveDataPointerManager()
	{
		delete m_pOneCruveData;
	}
	OneCurveData* GetObject()
	{
		return m_pOneCruveData;
	}
private:
	OneCurveData*		m_pOneCruveData;	
};

bool nlsf_calc_ave_data(const vector& vConcatenateX, const vector& vConcatenateY, int& nAveSize, vector& vAveX, vector& vAveY, vector& vErr, int nErrType)
{
	OneCurveDataPointerManager 	curveDataObject;
	OneCurveData*	pOneCruveData = curveDataObject.GetObject();
	if (NULL == pOneCruveData)
		return false;
	
	double *px = (double*)malloc(sizeof(double) * nAveSize);
	if(NULL == px)
		return false;
	
	double *py = (double*)malloc(sizeof(double) * nAveSize);
	if(NULL == py)
		return false;
	
	memcpy(px, vConcatenateX, sizeof(double)*nAveSize);
	memcpy(py, vConcatenateY, sizeof(double)*nAveSize);
	
	pOneCruveData->nSize = nAveSize;
	pOneCruveData->pX = px;
	pOneCruveData->pY = py;
	
	vAveX.SetSize(nAveSize);
	vAveY.SetSize(nAveSize);
	vErr.SetSize(nAveSize);
	
	int nNumCurve = 1;
	int nRet = ocmath_ave_replica_data_for_multiple_curves(nNumCurve, pOneCruveData, &nAveSize, vAveX, vAveY,  vErr, nErrType);
	
	free(pOneCruveData->pX);
	free(pOneCruveData->pY);
	
	if(nRet != OE_NOERROR)
		return false;
	
	vAveX.SetSize(nAveSize);
	vAveY.SetSize(nAveSize);
	vErr.SetSize(nAveSize);
	
	return true;
}

///Sophy 6/19/2008 QA80-10686 TREATE_DIFFERENT_WEIGHT_AS_DIFFERENT_INPUTDATA_ON_COMPARE_FIT_RESULT
string	nlsf_get_weight_method_name( int nMethodIndex )
{
	string	strMethods = STR_LIST_WEIGHTING_METHODS;
	string	strWTName = "";
	int		nNumTokens = strMethods.GetNumTokens('|');
	if( 0 <= nMethodIndex && nMethodIndex < nNumTokens )
	{
		strWTName = strMethods.GetToken( nMethodIndex, '|' );
	}
	return strWTName;
}
///end TREATE_DIFFERENT_WEIGHT_AS_DIFFERENT_INPUTDATA_ON_COMPARE_FIT_RESULT

//------ Folger 07/29/08 QA80-11909 PA_FIT_SHOULD_PICK_UP_DEFAULT_PARAMETER_VALUES_IN_FDF_AND_CENTER_VALUES_FROM_FIND_PEAK
int		nlsf_get_params_init_info(const TreeNode& trFDF, vector& vParamValues, vector<string>* pvsParamNames)		// NULL
{
	if ( !trFDF )
	{
		ASSERT(false);
		return -1;
	}
	
	vector<string>	vsParamNames;
	int			nNumParamInFunc = nlsf_get_fit_param_names(trFDF, vsParamNames);
	
	TreeNode	trInitValues = tree_get_node_by_tagname(trFDF, "InitialValues", true);
	if ( trInitValues )
	{
		nlf_set_param_values_vector(trInitValues.strVal, vParamValues, nNumParamInFunc);
	}
	
	if ( pvsParamNames )
		*pvsParamNames = vsParamNames;
	
	return vParamValues.GetSize();
}
//------ End PA_FIT_SHOULD_PICK_UP_DEFAULT_PARAMETER_VALUES_IN_FDF_AND_CENTER_VALUES_FROM_FIND_PEAK

bool nlsf_get_param_init_code(const TreeNode& trFDF, string& strCode)
{	
	if( !trFDF )
		return false;
	
	TreeNode trParamsInitScript = trFDF.ParametersInitialization.Script;
	if ( !trParamsInitScript )
		return false;	
	
	strCode = trParamsInitScript.strVal;
	ocu_skip_C_comments(&strCode);
	strCode.TrimLeft();
	strCode.TrimRight();
	if(strCode.IsEmpty())
		return false;
	
	return true;		
}

/// Iris 11/11/2008 v8.0968 MOVE_PA_ENUM_TO_NEW_HEADER_PA_UTILS, moved from PFM_utils
string get_function_list(LPCSTR lpcszCategory)
{
	string strFunctions;
	vector<string> 	vsFuncNames;
	vector<string>  vsFileNames;
	if( nslf_get_func_list(vsFuncNames, vsFileNames, lpcszCategory) )
	{
		strFunctions.SetTokens( vsFuncNames, '|' );
	}
	return strFunctions;
}
///end MOVE_PA_ENUM_TO_NEW_HEADER_PA_UTILS

///Jasmine 08/28/09 CENTRALIZE_FIND_PEAK_METHOD_COMBO
typedef	string	(*FUNC_GET_FIND_PEAK_METHODS)();
///End CENTRALIZE_FIND_PEAK_METHOD_COMBO

///Sophy 6/5/2009 MORE_SUPPORT_ON_NLFITSESSION_CUSTOMIZATION
///Arvin 03/12/08 REPLICA_AUTO_INIT_PARAMS_FOR_SURFACE_FIT as CP said
bool add_auto_init_params_branch_under_replica(TreeNode& trReplicaInit)
{
	if(!trReplicaInit)
		return false;
	
	Tree tr;
	GETN_USE(tr)
	//----- Iris 11/24/2008 v8.0987 discussed with Max, "Auto Parameter Init" not a good name since not mentioned peak finding
	//GETN_BEGIN_BRANCH(ReplicaInitParam, _L("Auto Parameter Init")) GETN_ID_BRANCH(IDST_REPLICA_PARAM_INIT_OPTIONS) GETN_OPTION_BRANCH(GETNBRANCH_SAVE_SETTINGS | GETNBRANCH_OPEN) 
	GETN_BEGIN_BRANCH(ReplicaInitParam, _L("Peak Finding Settings")) GETN_ID_BRANCH(IDST_REPLICA_PARAM_INIT_OPTIONS) GETN_OPTION_BRANCH(GETNBRANCH_SAVE_SETTINGS | GETNBRANCH_OPEN) 
	//-----
	///Jasmine 08/28/09 CENTRALIZE_FIND_PEAK_METHOD_COMBO
	string strMethods;
	FUNC_GET_FIND_PEAK_METHODS	pfn = Project.FindFunction("get_find_peak_methods", "OriginLab\\curve_utils.c", true);
	if(pfn)
		strMethods = pfn();
	else
		ASSERT(0);	
	//GETN_BEGIN_BRANCH(InitMethod,  _L("Peak Finding Method"))  GETN_COMBO_BRANCH(0, STR_NLFIT_LIST_REPLICA_FINDING_PEAK_METHODS) GETN_ID(IDE_REPLICA_PARAM_INIT_METHOD) //GETN_OPTION_BRANCH(GETNBRANCH_SAVE_SETTINGS | GETNBRANCH_OPEN)
	GETN_BEGIN_BRANCH(InitMethod,  _L("Peak Finding Method"))  GETN_COMBO_BRANCH(0, strMethods) GETN_ID(IDE_REPLICA_PARAM_INIT_METHOD)
	///End CENTRALIZE_FIND_PEAK_METHOD_COMBO
	/// Iris 4/13/2009 QA80-13448 CHANGE_LOCAL_POINT_PERCENT_TO_LOCAL_POINTS
	//GETN_NUM(LocalPoints, _L("Local Points(%)"), 5) GETN_ID(IDE_REPLICA_PARAM_INIT_LOCAL_POINTS)
	GETN_NUM(LocalPoints, _L("Local Points"), 5) GETN_ID(IDE_REPLICA_PARAM_INIT_LOCAL_POINTS)
	///end CHANGE_LOCAL_POINT_PERCENT_TO_LOCAL_POINTS
	GETN_NUM(WinHeight, _L("Window Height(%)"), 20) GETN_ID(IDE_REPLICA_PARAM_INIT_WIN_HEIGHT)  //GETN_ADD_AUTO(1)
	GETN_NUM(WinWidth, _L("Window Width(%)"), 50) GETN_ID(IDE_REPLICA_PARAM_INIT_WIN_WIDTH)     //GETN_ADD_AUTO(1)
	GETN_NUM(MinPts, _L("Minimum Points"), 8) GETN_ID(IDE_REPLICA_PARAM_INIT_CONTOUR_MIN_PTS)
	GETN_NUM(MaxArea, _L("Maximum Area"), 0.2) GETN_ID(IDE_REPLICA_PARAM_INIT_CONTOUR_MAX_AREA)
	GETN_NUM(NumZLevels, _L("Number of Z Levels"), 80) GETN_ID(IDE_REPLICA_PARAM_INIT_CONTOUR_NUM_Z_LEVELS)
	GETN_NUM(MinRoundness, _L("Minimum Roundness([0, 1])"), 0.5) GETN_ID(IDE_REPLICA_PARAM_INIT_CONTOUR_MIN_ROUNDNESS)
	GETN_END_BRANCH(InitMethod)
	//------ Folger 04/18/08 SHOULD_SET_DEFAULT_TO_BOTH_AS_PA_ACCORDING_TO_MAX
	//GETN_LIST(Direction, _L("Peak Direction"), 0, _L("Positive|Negative|Both")) GETN_ID(IDE_REPLICA_PARAM_INIT_DIRECTION)
	GETN_LIST(Direction, _L("Peak Direction"), 2, _L("Positive|Negative|Both")) GETN_ID(IDE_REPLICA_PARAM_INIT_DIRECTION)
	//------
	GETN_NUM(MinHeight, STR_MIN_HEIGHT_GENERAL_LABEL, 3) GETN_ID(IDE_REPLICA_PARAM_INIT_MIN_HEIGHT) //GETN_ADD_AUTO(1)
	GETN_END_BRANCH(ReplicaInitParam)
	trReplicaInit.Replace(tr.ReplicaInitParam);
	return true;
}
///end REPLICA_AUTO_INIT_PARAMS_FOR_SURFACE_FIT
///End MORE_SUPPORT_ON_NLFITSESSION_CUSTOMIZATION

/// Bill 07/12/2010 ORG-545 ADD_FUNCTION_TO_GET_FITFUNC_LIST_BY_FILE_TYPE
int nlsf_get_func_list(int nFileType, vector<string>& vsFuncNames, vector<string>& vsFileNames, vector<string>& vsCategorys)
{
	vector<string> vsAllCategorys;
	vector<int> vnSeparatorIndices;
	int nCategorys;

	vsFuncNames.RemoveAll();

	if ( vsFileNames != NULL )
		vsFileNames.RemoveAll();

	if ( vsCategorys != NULL )
		vsCategorys.RemoveAll();

	nCategorys = nlsf_get_category_list(vsAllCategorys, vnSeparatorIndices);

	for (int i = 0 ; i < nCategorys ; ++i)
	{
		int nFuncs;
		vector<string> vsFuncsInCategory;
		vector<string> vsFuncFileNamesInCategory;

		nFuncs = nlsf_get_func_list_in_category(nFileType, vsAllCategorys[i], vsFuncsInCategory, vsFuncFileNamesInCategory);

		if ( nFuncs > 0 )
		{
			for (int j = 0 ; j < vsFuncsInCategory.GetSize() ; ++j)
			{
				if ( vsFuncNames.Find(vsFuncsInCategory[j]) == -1 )
				{
					vsFuncNames.Add(vsFuncsInCategory[j]);

					if ( vsFileNames != NULL ) 
						vsFileNames.Add(vsFuncFileNamesInCategory[j]);

					if ( vsCategorys != NULL )
						vsCategorys.Add(vsAllCategorys[i]);  // This should be i, not j
				}
			}
		}
	}

	return vsFuncNames.GetSize();
}

int nlsf_get_func_list_in_category(int nFileType, const string & strCategory, vector<string> & vsFuncs, vector<string> & vsFileNames)
{
	vector<string> vsFunctions;
	vector<string> vsFuncFileNames;
	vector<string> vsFuncFileFullNames;

	nlf_get_section_keys_and_values(strCategory, vsFunctions, vsFuncFileNames, NULL, nFileType);
	
	string strPath	= okutil_get_origin_path(nFileType, STR_FDF_FILE_FOLDER);
	string strFileName;
	string strFileFullName;

	if(strPath.IsEmpty())
		return 0;
	strPath.TrimRight("\\");
	strPath += "\\";

	for (int i = 0 ; i < vsFuncFileNames.GetSize() ; ++i)
	{
		int nIndex = vsFuncFileNames[i].ReverseFind('\\');
		if ( nIndex > 0 && (nFileType == ORIGIN_PATH_UNDEF || nFileType == ORIGIN_PATH_USER))
		{
			strFileFullName = vsFuncFileNames[i];
		}
		else
		{
			separate_file_name_ext(vsFuncFileNames[i], strFileName);
			strFileFullName = strPath + strFileName + ".fdf";
		}

		if ( strFileFullName.IsFile() )
		{
			vsFuncs.Add(vsFunctions[i]);
			vsFileNames.Add(strFileFullName);
		}
	}

	return vsFuncs.GetSize();
}
/// End ADD_FUNCTION_TO_GET_FITFUNC_LIST_BY_FILE_TYPE

///Kyle 11/04/2009 QA80-14584 SCV_ADD_FITTING_FUNCTIONS
#ifdef _ADD_FITTING_FUNCTIONS_TO_SCV

int nlsf_find_fitting_functions(vector<string>& vsFuncNames, vector<string>& vsFuncArgs, LPCSTR lpcszCategory)
{
	vsFuncNames.SetSize(0);
	vsFuncArgs.SetSize(0);

	///Kyle 11/26/2009 QA80-14584-P1 SKIP_FOLDER_INFO_WHILE_SCANING_FITTING_FUNCTIONS, only the function name is needed and it will fail to get func info by passing "NewFunction1 (User)" to nlsf_get_fit_func_info()
	//vector<string> vsFileNames;
	//if( !nslf_get_func_list(vsFuncNames, vsFileNames, lpcszCategory) )
	//{
	//	vsFuncNames.SetSize(0);
	//	return 0;
	//}
	vector<string> vsUserFunctions, vsUserFuncFileNames, vsSharedFunctions, vsSharedFuncFileNames;
	nlf_get_section_keys_and_values(lpcszCategory, vsUserFunctions, vsUserFuncFileNames, NULL, USER_FOLDER);
	nlf_get_section_keys_and_values(lpcszCategory, vsSharedFunctions, vsSharedFuncFileNames, NULL, ALL_USER_FOLDER);
	vsFuncNames.Append(vsUserFunctions);
	vsFuncNames.Append(vsSharedFunctions);
	///End SKIP_FOLDER_INFO_WHILE_SCANING_FITTING_FUNCTIONS

	vsFuncArgs.SetSize(vsFuncNames.GetSize());

	vector<string> vsDepenVars, vsIndepVars, vsParamNames;
	for(int nFunc = vsFuncNames.GetSize() - 1; nFunc >= 0; nFunc--)
	{
		string strFuncName = vsFuncNames[nFunc];
		if( !is_good_C_identifier(strFuncName) || !nlsf_get_fit_func_info(strFuncName, &vsDepenVars, &vsIndepVars, &vsParamNames) || 1 != vsDepenVars.GetSize() )
		{
			vsFuncNames.RemoveAt(nFunc);
			vsFuncArgs.RemoveAt(nFunc);
		}
		else
		{
			vsIndepVars.Append(vsParamNames);
			string strArgList;
			strArgList.SetTokens(vsIndepVars, ',');
			vsFuncArgs[nFunc] = strArgList;
		}
	}

	return vsFuncArgs.GetSize();
}

#endif //_ADD_FITTING_FUNCTIONS_TO_SCV
///End SCV_ADD_FITTING_FUNCTIONS

///------ Folger 07/23/10 ORG-423-P3 SHOULD_NOT_COMPILE_FFW_IF_NAME_NOT_FITTING_FUNCTION
int		nlsf_utils(int nMsg, DWORD dwCntrl = 0, LPVOID lpData = NULL)
{
	switch ( nMsg )
	{
	case NLSFMSG_CHECKFUNC:
		{
			LPCSTR	lpcszName = (LPCSTR)lpData;
			Tree	trFDF;
			string	strCategory;
			return	nlsf_load_FDF_to_tree(trFDF, lpcszName, &strCategory) <= FDFTYPE_UNKNOWN ? 1 : 0;
		}

	default:
		break;
	}

	return 1;
}
///------ End SHOULD_NOT_COMPILE_FFW_IF_NAME_NOT_FITTING_FUNCTION