#include <origin.h>
#include <GetNBox.h>
#include <xfutils.h>
enum{
	execute_init,
	execute_update,
	execute_run,
	execute_report,
	execute_cleanup,
};
/*
*	Iris 06/22/2007 v8.0646 SUPPORT_ONE_LINE_SCRIPT_TO_DO_CALC_WITH_DEFAULT_SETTINGS
*   Iris 06/22/2007 v8.0646 INTRODUCE_EXECUTE_MODE_VAR
*   Iris 4/29/2008 FIX_NO_ROCCURVE_PLOT
*	Folger 09/02/09 XOP_CRASH_ORIGIN_WHEN_RUN_TWICE_WITH_FIRST_TIME_ERROR_THROWN
*/

enum
{
	ANOVA_INDEXED_DATA = 0,
	ANOVA_RAW_DATA
};

//put additional include files here
#include <Operation.h>
#include <..\OriginLab\curve_utils.h>
#include <..\OriginLab\nlsf_utils.h>
#include <..\OriginLab\graph_utils.h>

///Arvin 06/29/07 v8.652 XOP_NEED_SUPPORT_NLFIT
static	Operation	*s_pOp;
//static 	string		s_strClassName;
static	string		s_strFuncName; //For NLSF
///end  XOP_NEED_SUPPORT_NLFIT
/// Iris 06/22/2007 v8.0646 INTRODUCE_EXECUTE_MODE_VAR, not used now
//put your own support static functions here
//static bool _is_do_op_calc(LPCSTR lpcszClassName)
//{
	//string	strClassName(lpcszClassName);
	//bool	bDoCalcOnly = strClassName.IsEmpty() || okutil_cvt_str_to_predefined_type(strClassName) == PDS_UNASSIGNED;
	//return bDoCalcOnly;
//}
///end INTRODUCE_EXECUTE_MODE_VAR

static bool _is_ANOVA_tool(LPCSTR lpcszClassName, bool* pbTwoWay = NULL, bool* pbRM = NULL)
{
	string strClassName(lpcszClassName);
	strClassName.MakeUpper();
	if(strClassName.Find("ANOVA") < 0)
		return false;
	
	if(NULL != pbTwoWay)
		*pbTwoWay = strClassName.Find("ONE") < 0? true : false;
	
	if(NULL != pbRM)
		*pbRM = strClassName.Find("RM") < 0? false : true;
	return true;
}

///Arvin 06/29/07 v8.652 XOP_NEED_SUPPORT_NLFIT
static bool _is_nlsf_tool(LPCSTR lpcszClassName)
{
	string strClassName(lpcszClassName);
	return strClassName.Compare("FitNL") == 0 ? true : false;
}

static bool _get_function_name(const TreeNode& trGUI, string& strFuncName)
{
	TreeNode trOutGUI = trGUI.GetNode("GUI");
	TreeNode trFuncSel = trOutGUI.FunctionSelection;
	if(trFuncSel)
	{
		strFuncName = trFuncSel.FunctionList.strVal;
	}

	return strFuncName.IsEmpty() ? false : true;
}
///end XOP_NEED_SUPPORT_NLFIT
static string _sep_class_option(LPCSTR lpcszName, int* pnOption = NULL)
{
	string 	strClassName(lpcszName);
	string strTemp = strClassName;
	vector<string> vs;
	int 	nNumToken = strClassName.GetTokens(vs, '(');
	if(2 == nNumToken)
	{
		strClassName = vs[0];
		
		if(NULL != pnOption)
		{
			nNumToken = strTemp.GetTokens(vs, '_');
			if(nNumToken == 2)
				*pnOption = atoi(vs[1]);
		}
	}
	else
	{
		if(strClassName.GetTokens(vs, '_') == 2)
		{
			strClassName = vs[0];
			if(pnOption)
				*pnOption = atoi(vs[1]);
		}
	}
	return strClassName;	
}

///Arvin 01/16/08 SUPPORT_2D_FIT
static int _get_fit_type(LPCSTR lpcszName)
{
	string	strClassName(lpcszName);
	int nPre = strClassName.Find('(');
	int nSize = strClassName.GetLength();
	if(nPre > 0 && nPre < nSize)
	{
		int nRe = strClassName.Find(')', nPre+1);
		if(nRe > 0 && nRe < nSize && nRe - nPre == 2) 
		{
			string strType = strClassName.Mid(nPre+1, 1);
			int nFitType = atof(strType);
			if(nFitType > NLFIT_GENERAL_XY_FITTING && nFitType < NLFIT_MATRIX_FITTING+1)
				return nFitType;
		}
	}
	return NLFIT_GENERAL_XY_FITTING;
}
///end SUPPORT_2D_FIT

static string _get_classname_from_gui_tree(TreeNode& trGUI, int* pnOption)
{
	string	strClassName;
	strClassName = trGUI.name.strVal; //the value written in _construct_gui_tree
	
	strClassName = _sep_class_option(strClassName, pnOption);	
	return strClassName;
}

///Arvin 01/02/08 QA70-10890-P3 SUPPORT_OUTPUT_CUSTOMIZATION
/*
static bool _is_summary_table(LPCSTR lpszTagName)
{
	string strTagName(lpszTagName);
	if(strTagName.Compare("SummaryTable") == 0)
		return true;
	return false;
}

static bool _is_paste_result_table(LPCSTR lpszTagName)
{
	string strTagName(lpszTagName);
	if(strTagName.Compare("PasteResultTable") == 0)
		return true;
	return false;
}

static TreeNode _check_add_ouput_option_node(const TreeNode& trOpRoot, TreeNode& trOutputOptions, LPCSTR lpszTagName)
{
	TreeNode trNode = tree_get_node_by_tagname(trOpRoot, lpszTagName, true);
	if(trNode && trNode.Show)
	{
		TreeNode trTable = tree_check_get_node(trOutputOptions, lpszTagName);
		trTable.ID = trNode.ID;
		if(_is_summary_table(lpszTagName) || _is_paste_result_table(lpszTagName))
			trTable.Use = trNode.Use;
		else
			trTable.nVal = trNode.nVal;
		
		return trTable;
	}
}

static bool _construct_output_options_branch(TreeNode& trOut, TreeNode& trOpGUI)
{
	TreeNode trOutputOptions = tree_check_get_node(trOut, "OutputOptions");
	TreeNode trQuantities = trOpGUI.Quantities;
	if(trQuantities && trQuantities.Show)
	{
		_check_add_ouput_option_node(trQuantities, trOutputOptions, "SummaryTable");
		_check_add_ouput_option_node(trQuantities, trOutputOptions, "ANOVAtable");
		_check_add_ouput_option_node(trQuantities, trOutputOptions, "mCov");
		_check_add_ouput_option_node(trQuantities, trOutputOptions, "mCor");
	}
	
	TreeNode trResAnalysis = trOpGUI.ResAnalysis;
	if(trResAnalysis && trResAnalysis.Show)
	{
		TreeNode trOutputResAnalysis = tree_check_get_node(trOutputOptions, "Temp");
		trOutputResAnalysis.Replace(trResAnalysis.Clone());
	}
	
	TreeNode trOutput = trOpGUI.Output;
	if(trOutput)
		_check_add_ouput_option_node(trOutput, trOutputOptions, "PasteResultTable");
	
	TreeNode trResiduals = trOpGUI.Residuals;
	if(
	
		
}
*/
static void _copy_output_customization(TreeNode& trInputGUI, TreeNode& trOpGUI)
{
	tree_copy_values_by_id(trInputGUI, trOpGUI);
	//octree_copy_atts(&trInputGUI, &trOpGUI, STR_USE_ATTRIB);
}
///end SUPPORT_OUTPUT_CUSTOMIZATION

static int _construct_gui_tree(LPCSTR lpcszClassOption, TreeNode& trGUI, LPCSTR lpcszTheme = NULL, int nHasBaseline = 0)
{
	int		nOption = 0;
	//Need reset trGUI for init
	trGUI.Reset();
	string	strClassName = _sep_class_option(lpcszClassOption, &nOption);
	trGUI.name.strVal = (string)lpcszClassOption; //will use it when do execute_updateTree, execute_outputTree or execute_generateReport
	
	bool	bOK = false;
	///Arvin 06/29/07 v8.652 XOP_NEED_SUPPORT_NLFIT
	//Destroy static operation object first;
	_clean_operation_object();
	///end XOP_NEED_SUPPORT_NLFIT
	if(!strClassName.CompareNoCase("FitPeak"))
	{
		TreeNode trPeakNum = tree_check_get_node(trGUI, "PeakNum");
		trPeakNum.nVal = nOption;
		TreeNode trHasBaseline = tree_check_get_node(trGUI, "HasBaseline");
		if(nHasBaseline)
			trHasBaseline.nVal = 1;
		else
			trHasBaseline.nVal = 0;
		
		TreeNode trMultiPeakOptions = tree_check_get_node(trGUI, "MultiPeakOptions");
		if(trMultiPeakOptions)
			trMultiPeakOptions.nVal = 0;
		TreeNode trDataSteps = tree_check_get_node(trGUI, "DataSteps");
		if(trDataSteps)
			trDataSteps.nVal = 1;
		
		TreeNode trNumIterWithFixed = tree_check_get_node(trGUI, "NumIterWithFixed");
		if(trNumIterWithFixed)
			trNumIterWithFixed.nVal = 0;
	}
	
	Operation& op = (Operation &)op_create(strClassName, bOK, nOption);	
	if(op == NULL )
		return XFERR_FAIL_TO_CREATE_OPERATION;
	///Arvin 06/29/07 v8.652 XOP_NEED_SUPPORT_NLFIT
	else
		s_pOp = &op;
	///end XOP_NEED_SUPPORT_NLFIT	
	
	Tree 	trOp;
	///Arvin 06/29/07 v8.652 XOP_NEED_SUPPORT_NLFIT
	//op.GetTree(trOp);	
	s_pOp->GetTree(trOp);
	///end XOP_NEED_SUPPORT_NLFIT
	///Arvin 01/16/08 SUPPORT_2D_FIT
	if(!strClassName.CompareNoCase("FitPeak") || _is_nlsf_tool("FitNL"))
	{
		int nFitType = _get_fit_type(lpcszClassOption);
		if( nFitType != NLFIT_GENERAL_XY_FITTING)
		{
			trOp.SpecInfo.FitType.nVal = nFitType;
		}
	}
	///end SUPPORT_2D_FIT
	TreeNode trOutGUI = trGUI.GetNode("GUI");
	if(!trOutGUI)
		trOutGUI = trGUI.AddNode("GUI");
	trOutGUI.Replace(trOp.GUI.Clone());	
	
	// apply dialog theme
	string	strTheme(lpcszTheme);
	if( !strTheme.IsEmpty() )
		theme_apply_analysis_theme(strClassName, trOutGUI, strTheme);

	///Arvin 06/29/07 v8.652 XOP_NEED_SUPPORT_NLFIT
	/*
	//construct InputData subnodes
	TreeNode	trInputData = trOutGUI.InputData;		
	bool		bTwoWay, bRM;
	if( _is_ANOVA_tool(strClassName, &bTwoWay, &bRM) )// to construct input data subnodes for all ANOVA tools
	{
		_construct_anova_input_data_branch(trInputData, bTwoWay, bRM);
	}
	else // to construct input data subnodess for the tools like DescStats, FitLinear, FitPloynomial
	{				
		DWORD		dwDataRule = s_Op.GetDataRules(trOp);//op.GetDataRules(trOp);		
		Project.InitInputDataBranchFromSelection(trInputData, dwDataRule, NULL, NULL);
	}				
	*/
	int nRet = s_pOp->OnInitOperationTreeFromOCLT(trOp, trGUI);
	s_pOp->SetTree(trOp);
	if(nRet != OP_NOERROR)
		return XFERR_FAIL_TO_CONSTRUCT_INPUT_DATA_BRANCH;
		
	return CER_NO_ERROR;
}

static void _construct_anova_input_data_branch(TreeNode& trInputData, bool bTwoWay, bool bRM)
{
	if(ANOVA_INDEXED_DATA == trInputData.Use)
	{
		okutil_anova_switch_to_indexed_data(&trInputData, bTwoWay, bRM);			
	}
	else
	{
		okutil_anova_switch_to_raw_data(&trInputData, bTwoWay, bRM);
	}	
}


/// Iris 06/22/2007 v8.0646 INTRODUCE_EXECUTE_MODE_VAR
//static bool _do_calculate(TreeNode& trGUI, TreeNode& trOut, TreeNode& trMakeTree, LPCSTR lpcszTheme = NULL, bool bDoReport = report_outTree)
static int _do_calculate(TreeNode& trGUI, TreeNode& trOut, LPCSTR lpcszTheme = NULL, int nExecuteMode = execute_run)
{
	int		nOption = 0;
	string	strClassName = _get_classname_from_gui_tree(trGUI, &nOption);
	
	string	strTheme(lpcszTheme);
	if( !strTheme.IsEmpty() )
		theme_apply_analysis_theme(trGUI.name.strVal, trGUI, strTheme); //the first var should be class name + option here, like DescStats_1 for stats on rows, so cannot use strClassName here
	
	/// Iris 06/22/2007 v8.0646 INTRODUCE_EXECUTE_MODE_VAR
	//if(trMakeTree)
		//trMakeTree.Replace(trGUI.Clone());
	///end INTRODUCE_EXECUTE_MODE_VAR	

	//
	//----------Calculation----------
	//
	bool 	bRet;
	///Arvin 06/29/07 v8.652 XOP_NEED_SUPPORT_NLFIT
	//bool	bOK = false;
	//Operation& op = (Operation &)op_create(strClassName, bOK, nOption); 
	//if(op == NULL )
	//	return XFERR_FAIL_TO_CREATE_OPERATION;
	
	//Tree	trOp;
	//op.GetTree(trOp);
	if(!s_pOp)
		return XFERR_FAIL_TO_CREATE_OPERATION;
	
	///Arvin 06/29/07 v8.652 XOP_NEED_SUPPORT_NLFIT	
	string strOpClassName = s_pOp->GetClassName();
	if(strClassName.Compare(strOpClassName) != 0)
		return XFERR_WRONG_CLASS_NAME;
	
	if(_is_nlsf_tool(strClassName))
	{
		string strFuncName; 
		_get_function_name(trGUI, strFuncName);
		if(	strFuncName.Compare(s_strFuncName) != 0)
			return XFERR_WRONG_FUNC_NAME;
	}
	///end XOP_NEED_SUPPORT_NLFIT
	Tree	trOp;
	s_pOp->GetTree(trOp);
	///end XOP_NEED_SUPPORT_NLFIT
	
	trOp.GUI.Replace(trGUI.GUI.Clone());
	///Arvin 06/29/07 v8.652 XOP_NEED_SUPPORT_NLFIT
	trOp.Operation.AutoUpdate.nVal = AU_NONE;
	TreeNode trUserSettings = trGUI.UserSettings;
	if(trUserSettings)
	{
		trOp.AddNode("UserSettings");
		trOp.UserSettings.Replace(trUserSettings.Clone());
	}
	///end XOP_NEED_SUPPORT_NLFIT
	
	///Cheney/Arvin 2007-9-10 XOP_NEED_SUPPORT_PFM
	TreeNode trFitWorkArea = trGUI.FitWorkArea;
	if(trFitWorkArea)
	{
		trOp.AddNode("FitWorkArea");
		trOp.FitWorkArea.Replace(trFitWorkArea.Clone());
		trOp.FitWorkArea.SetAttribute(STR_NO_INIT_FROM_OP_ATTRIB, NO_INIT_FIT_SESSION_FROM_OP_TREE);
	}
	
	TreeNode 	trPFWTree = trGUI.PFWTree;
	if(trPFWTree)
	{
		trOp.AddNode("PFWTree");
		trOp.PFWTree.Replace(trPFWTree.Clone());	
	}
	///end XOP_NEED_SUPPORT_PFM
	
	/// Iris 4/29/2008 FIX_NO_ROCCURVE_PLOT
	TreeNode	trROCCurve = trOp.GUI.CompControl.ROCCurve;
	if( trROCCurve )
	{
		trOp.GUI.Plots.Graph1.nVal = trROCCurve.Use;		
	}
	///end FIX_NO_ROCCURVE_PLOT
	
	int     nAutoUpdate = 0;
	///Arvin 06/29/07 v8.652 XOP_NEED_SUPPORT_NLFIT
	//op.SetTree(trOp);
	//op.OnNoEdit(nOption, nAutoUpdate);
	s_pOp->SetTree(trOp);
	s_pOp->OnNoEdit(nOption, nAutoUpdate);
	
	///Arvin 11/10/07 XOP_NEED_SUPPORT_CHANGE_FUNCTION
	s_pOp->GetTree(trOp);
	s_pOp->ClearOutputTables(trOp);
	s_pOp->SetTree(trOp);
	///end XOP_NEED_SUPPORT_CHANGE_FUNCTION
	
	///end XOP_NEED_SUPPORT_NLFIT
	//
	//----------Output----------
	//
	/// Iris 06/22/2007 v8.0646 INTRODUCE_EXECUTE_MODE_VAR
	//if(bDoReport)//do report according the settings in GUI.Output.Report nodes
	if(execute_report == nExecuteMode)
	///end INTRODUCE_EXECUTE_MODE_VAR
	{
		///Arvin 06/29/07 v8.652 XOP_NEED_SUPPORT_NLFIT
		//if( !op.Execute() )
		if( !s_pOp->Execute() )
		///end XOP_NEED_SUPPORT_NLFIT
			return XFERR_FAIL_TO_DO_CALC_OR_REPORT;
	}
	else if(execute_run == nExecuteMode && trOut)
	{
		///Arvin 06/29/07 v8.652 XOP_NEED_SUPPORT_NLFIT
		//bRet = 0 == op.Calculate()? true : false;
		bRet = 0 == s_pOp->Calculate()? true : false;
		///end XOP_NEED_SUPPORT_NLFIT
		if(bRet)
		{
			///Arvin 06/29/07 v8.652 XOP_NEED_SUPPORT_NLFIT
			//op.GetTree(trOp);	
			s_pOp->GetTree(trOp);	
			///end XOP_NEED_SUPPORT_NLFIT
			trOut.Replace(trOp.Calculation.Clone());
		}
		else
			return XFERR_FAIL_TO_DO_CALC;
	}
	else
		return XFERR_INCORRECT_VAR_VAL;
	
	return CER_NO_ERROR;
}

static int _update_gui_tree(TreeNode& trGUI, LPCSTR lpcszTheme = NULL)
{
	int		nOption = 0;
	string	strClassName = _get_classname_from_gui_tree(trGUI, &nOption);
	// update GUI tree according Theme
	string	strTheme(lpcszTheme);
	if( !strTheme.IsEmpty() )
		theme_apply_analysis_theme(trGUI.name.strVal, trGUI, strTheme);
	///Arvin 06/29/07 v8.652 XOP_NEED_SUPPORT_NLFIT
	/*
	// update GUI tree according to InputData.Use for ANOVA
	bool		bTwoWay, bRM;
	if( _is_ANOVA_tool(strClassName, &bTwoWay, &bRM) )// to construct input data subnodes for all ANOVA tools
	{
		_construct_anova_input_data_branch(trGUI.GUI.InputData, bTwoWay, bRM);
	}
    */
    //bool	bOK = false;
	//Operation& op = (Operation &)op_create(strClassName, bOK, nOption); 
	//if(op == NULL )
		//return XFERR_FAIL_TO_CREATE_OPERATION;
	if(!s_pOp)
		return XFERR_FAIL_TO_CREATE_OPERATION;
	
	string strOpClassName = s_pOp->GetClassName();
	if(strClassName.Compare(strOpClassName) != 0)
		return XFERR_WRONG_CLASS_NAME;
	
	Tree 	trOp;
	s_pOp->GetTree(trOp);
	
	///Arvin 01/02/08 QA70-10890-P3 SUPPORT_OUTPUT_CUSTOMIZATION
	_copy_output_customization(trGUI.GUI, trOp.GUI);
	///end SUPPORT_OUTPUT_CUSTOMIZATION
    int nRet = s_pOp->OnInitOperationTreeFromOCLT(trOp, trGUI, false); //Update operation tree
    if(nRet != OP_NOERROR)
    	return XFERR_FAIL_TO_UPDATE_OPERATION_TREE;
  	s_pOp->SetTree(trOp); /// Not trOp.SpecInfo node when do report
  
    //For nlsf, need remember function name
	if(_is_nlsf_tool(strClassName))
	{
		_get_function_name(trGUI, s_strFuncName);
	}
    ///end XOP_NEED_SUPPORT_NLFIT
	return CER_NO_ERROR;
}

static void _clean_operation_object()
{
	//Destroy static operation object
	if ( s_pOp )
	{
		s_pOp->DestroyInternal();
		s_pOp = NULL;
	}
}


void xop(const int& execute, const string& classname, TreeNode& iotrgui, TreeNode& otrresult, const string& theme, const int& baseline)
{
	int nRet = 	CER_NO_ERROR;
	
	/// Iris 06/22/2007 v8.0646 INTRODUCE_EXECUTE_MODE_VAR
	/*
	if( !_is_do_op_calc(classname) )
	{
		/// Iris 06/22/2007 v8.0646 SUPPORT_ONE_LINE_SCRIPT_TO_DO_CALC_WITH_DEFAULT_SETTINGS
		//nRet = _construct_gui_tree(classname, mtrGUI, dataMode);
		Tree	trGUI;
		nRet = _construct_gui_tree(classname, trGUI, theme, dataMode);
		if( !mtrGUI ) // if mtrGUI is invalid, means no need to output GUI, just want to report calculation results by default GUI settings
		{
			if(CER_NO_ERROR == nRet)
			{
				nRet = _do_calculate(trGUI, otrresult, mtrGUI, theme, report);
			}
		}
		else
		{
			mtrGUI.Replace(trGUI.Clone());
		}
		///end SUPPORT_ONE_LINE_SCRIPT_TO_DO_CALC_WITH_DEFAULT_SETTINGS
	}
	else
	{
		nRet = _do_calculate(itrGUI, otrresult, mtrGUI, theme, report);
	}
	*/
	
	//write this convertion since cause runtime error theme is invalid object when it is not assigned in Command window
	string	strTheme;
	if(theme)
		strTheme = theme;
	
	switch(execute)
	{
	case execute_init:
		nRet = _construct_gui_tree(classname, iotrgui, strTheme, baseline);
		break;
		
	case execute_update:
		nRet = _update_gui_tree(iotrgui, strTheme);
		break;
		
	case execute_run:	
	case execute_report:
		nRet = _do_calculate(iotrgui, otrresult, strTheme, execute);
		///------ Folger 09/02/09 XOP_CRASH_ORIGIN_WHEN_RUN_TWICE_WITH_FIRST_TIME_ERROR_THROWN
		if ( CER_NO_ERROR != nRet )
			_clean_operation_object();
		///------ End XOP_CRASH_ORIGIN_WHEN_RUN_TWICE_WITH_FIRST_TIME_ERROR_THROWN
		break;
	///Arvin 06/29/07 v8.652 XOP_NEED_SUPPORT_NLFIT
	case execute_cleanup:
		_clean_operation_object();
	///end 	XOP_NEED_SUPPORT_NLFIT
	default:
		break;
	}	
	///end INTRODUCE_EXECUTE_MODE_VAR
	
	if(CER_NO_ERROR != nRet)
		XF_THROW(nRet);
	
}

//nEventID < 0 on event, like GETNE_ON_INIT, GETNE_ON_OK etc, >0 on change from control
//return 0 to do nothing, return PEVENT_GETN_RET_TO_CLOSE to close dialog
//dwEnables = bOKEnable, bBTN1Enable, bBTN2Enable, bBTN3Enable, , can set to false to disable OK/Apply buttons
//lpcszNodeName = the trGetN TreeNode tag name that generates the event, or is  if GETNE_ON_OK etc
//strAux = optional string for XF Wizard Bar, like DLG_NEED_CHANGE_GRID etc, it will be invalid if from internal node value change event
//strErrMsg = allowing messages to be shown
int xop_event1(TreeNode& trGetN, int nRow, int nEventID, DWORD& dwEnables, LPCSTR lpcszNodeName, WndContainer& DynaCntrlContainer, string& strAux, string& strErrMsg)
{
	if( xf_is_extended_event(nEventID) )
		return xop_event1_ex(trGetN, nRow, nEventID, dwEnables, lpcszNodeName, DynaCntrlContainer, strAux, strErrMsg);
	DECLARE_BUTTON_ENABLES
	return false;

}

int xop_make_tree(TreeNode& tr, LPCSTR lpcszVarName)
{
	return -1;
}
//nGetNDialog = 0,1,2, corresponding to the XF GetN dropdown, 0 = dialog is not used
//you can change nRet to be one of XFEVT_PROCEED (defualt), XFEVT_ABORT, XFEVT_PROCEED_NO_DLG or XFEVT_PROCEED_WITH_DLG(when nGetNDialog = 0)
//nGetNDialog = -1 when Ok on GetN dialog to allow handler to preocess <auto> etc variables
//dwCntrl is combination of bits
//LTXF_FROM_GUI_MENU, LTXF_FROM_GUI_PROMPT, LTXF_FROM_AUTO_UPDATE, LTXF_FROM_FUNCTION, LTXF_THEME_USED, LTXF_CHANGE_PARAM
void xop_before_execute(TreeNode& trGetN, int nGetNDialog, int& nRet, int dwCntrl)
{

}
//nEventID < 0 on event, like GETNE_ON_INIT, GETNE_ON_OK etc, >0 on change from control
//return 0 to do nothing, return PEVENT_GETN_RET_TO_CLOSE to close dialog
//dwEnables = bOKEnable, bBTN1Enable, bBTN2Enable, bBTN3Enable, , can set to false to disable OK/Apply buttons
//lpcszNodeName = the trGetN TreeNode tag name that generates the event, or is  if GETNE_ON_OK etc
//strAux = optional string for XF Wizard Bar, like DLG_NEED_CHANGE_GRID etc, it will be invalid if from internal node value change event
//strErrMsg = allowing messages to be shown
int xop_event1_ex(TreeNode& trGetN, int nRow, int nEventID, DWORD& dwEnables, LPCSTR lpcszNodeName, WndContainer& DynaCntrlContainer, string& strAux, string& strErrMsg)
{
	return false;
}
