#include <origin.h>
#include <GetNBox.h>
#include <xfutils.h>
#include <GetNBox.h>
#include <o8dlg.h>
//#include <fft_utils.h>
/***************************************************************************************
/// Modification Log :
/// Folger 07/23/08 BETTER_OPREATION_OUTPUT_COLUMN_COMMENTS
/// Folger 09/25/08 QA80-12276 SET_SAMPLING_INTERVAL_FOR_YXRANGE_OUTPUT
///	Fisher 2008-11-7 QA80-12546 ADD_BACK_SMOOTH_OPTION_IN_DIFFERENTIATE_TOOL
/// ML 11/10/2008 QA70-12356 RANGE_GET_DATA_PROVIDE_MAP_OF_MISSING_VALUES
/// Kyle 11/11/2008 QA80-12356 SET_NOT_TO_ALTER_THE_INPUT_X_VALUES_WHEN_THERE_ARE_MISSING_VALUES
/// Kyle 01/21/2009 CHECK_WHETHER_INPUT_DATA_IS_EVENLY_SPACED_WHEN_SMOOTH_CHECKED
/// Kyle 02/12/2009 ONLY_SHOW_WARNING_MESSAGE_IF_INPUT_DATA_IS_NOT_EVEN_SPACED
/// Max 2/11/09 v8.0977b USE_ANOTHER_STRING_FOR_CENTRALIZATION
/// Folger 04/14/09 QA80-13436 IMPROVE_MECHANISM_ABOUT_XF_ERR_MSG_SHOWN_IN_BODY
***************************************************************************************/

///------ Folger 04/14/09 QA80-13436 IMPROVE_MECHANISM_ABOUT_XF_ERR_MSG_SHOWN_IN_BODY
IMPLEMENT_SHOULD_WARNING_MSG_SHOW_IN_XF_BODY
///------ End IMPROVE_MECHANISM_ABOUT_XF_ERR_MSG_SHOWN_IN_BODY

//put additional include files here
//#define Y_INDEX_IN_XYRANGE 1

//#define STR_DIFF_RESULT1 "Differentiate Result"
//#define STR_DIFF_RESULT2 " derivative of "
#define MIN_POINTS_IN_WINDOW				2		///Kyle 01/21/2009 CHECK_WHETHER_INPUT_DATA_IS_EVENLY_SPACED_WHEN_SMOOTH_CHECKED
#define MIN_INPUT_DATA_FOR_SMOOTH 			3		///Kyle 01/21/2009 CHECK_WHETHER_INPUT_DATA_IS_EVENLY_SPACED_WHEN_SMOOTH_CHECKED
#define STR_ERR_THROW _L("Differentiate Order")
#define MIN_DERIVATIVE_ORDER 0
#define	MIN_INPUT_DATA_NUMBER 2
//put your own support static functions here
/*
static void _set_order(const int order, string& srtOrder)
{
	switch(order)
	{
		case 1:
			srtOrder = "1st";
			break;
		case 2:
			srtOrder = "2nd";
			break;
		case 3:
			srtOrder = "3rd";
			break;
		case 4:
		default:
			srtOrder.Format("%dth",order);
			break;	
	}
}
*/
/// Max  8/15/07 REMOCE_COLOR_CONTROL
/*
static void _init_tree_show(TreeNode& trGetN)
{
	GraphLayer gl = Project.ActiveLayer();
	if(!gl.IsValid())
		trGetN.color.Show = false;
}
*/
/// END REMOCE_COLOR_CONTROL

///Cheney 2007-6-7 ADD_AN_ERR_CHECK_FUNC
static int _check_err_condition(TreeNode& trGetN)
{
	int nErr = CER_NO_ERROR;

	if(get_input_xyrange_num(trGetN.iy) != 1)
		nErr = CER_NOT_ONE_XYRANGE;
	
	if(nErr == CER_NO_ERROR && 0>= get_input_xyrange_data_size(trGetN.iy))
		nErr = CER_NO_DATA;
	int nSize = get_input_xyrange_data_size(trGetN.iy);
	///Arvin 07/30/07 WRONG_ERR_MASSAGE
	if(nErr == CER_NO_ERROR && MIN_INPUT_DATA_NUMBER > nSize)
		nErr = CER_DATA_TOO_FEW;
	///END WRONG_ERR_MASSAGE
	if(nErr == CER_NO_ERROR && trGetN.order.nVal < 0)
		nErr = CER_INPUT_ARGUMENT_LESS_THAN_SPECIFIED_VALUE;
	
	///Kyle 01/21/2009 CHECK_WHETHER_INPUT_DATA_IS_EVENLY_SPACED_WHEN_SMOOTH_CHECKED
	if(nErr == CER_NO_ERROR && trGetN.smooth.nVal)
	{
		if(nSize < MIN_INPUT_DATA_FOR_SMOOTH)
			return CER_DATA_TOO_FEW;
		if(trGetN.order.nVal > trGetN.poly.nVal)
			return CER_POLYDEG_GREATER_THAN_DERVORDER;
		
		if(trGetN.npts.nVal < MIN_POINTS_IN_WINDOW || trGetN.npts.nVal >= nSize)
			return XFERR_INVALID_WINDOW_POINTS;

		// for warning, should check this at last
		XYRange xyTemp;
		if(xy_range_from_GetN_data_node(trGetN.iy, xyTemp) && xyTemp.IsValid())
		{
			double dInterval;
			vector vx, vy;
			xyTemp.GetData(vy, vx,NULL, 0, 0);
			if(OE_NOERROR != ocmath_sampling_resolution(vx.GetSize(), vx, &dInterval))
				/// Max 2/11/09 v8.0977b USE_ANOTHER_STRING_FOR_CENTRALIZATION
				//return CER_DATA_NOT_SUITABLE_FOR_SMOOTH;
				return XFWAR_NOT_EVEN_SPACE_IN_SG_SMOOTH;
				/// ---
		}
	}
	///End CHECK_WHETHER_INPUT_DATA_IS_EVENLY_SPACED_WHEN_SMOOTH_CHECKED
	
	return nErr;
}
///end ADD_AN_ERR_CHECK_FUNC

//------ Folger 07/23/08 BETTER_OPREATION_OUTPUT_COLUMN_COMMENTS
static	void	_set_output_range_comments(XYRange& oy, const XYRange& iy, int nOrder)
{
	vector<string>		vsNumerPostfix = {"th", "st", "nd", "rd", "th", "th", "th", "th", "th", "th"};
	
	string	strOrder = ftoa(nOrder);
	int nTmp = nOrder % 100;
	if ( nTmp == 11 || nTmp == 12 || nTmp == 13 )
		strOrder += "th";
	else
		strOrder += vsNumerPostfix[nOrder % 10];
	
	string	strComments;
	strComments.Format("%s derivative of %s", strOrder, get_input_data_range_string(iy));
	oy.SetOutputComment(strComments);
}
//------ End BETTER_OPREATION_OUTPUT_COLUMN_COMMENTS


void differentiate(const XYRange& iy, const int& order, const int& smooth, const int& poly, const int& npts, XYRange& oy, const int& plot)
{
	/// *****		Function Description		***** ///
	//
	//	Simple derivative calculations.
	//Description:
	//	Simple derivative calculations without smoothing. Missing values are ignored.
	//	There is no smoothing performed in this function. 
	//	Derivative is computed by taking the average of the two data points slopes from the previous and next data points. 
	//Parameter:
	//	iy = [input] input data to be differentiated
	//	oy = [output] derivatived data
	//Output:
	//	The function returns followings:
	//	1. oy(XYRange): result of derivatives
	//	2. DerivPlot(graph): the derivatives curve
			
	/// *****		Terminate if error setting		***** ///
	
	vector vx, vy, vderivatived;
	
	/// ML 11/10/2008 QA70-12356 RANGE_GET_DATA_PROVIDE_MAP_OF_MISSING_VALUES
	//if (!iy.IsValid() || iy.GetNumData(DRR_GET_DEPENDENT) != 1 || !iy.GetData(vy, vx))
	//	XF_THROW(CER_NOT_ONE_XYRANGE)
	vector<int>		vnMissingValsIndices;
	if (!iy.IsValid() || iy.GetNumData(DRR_GET_DEPENDENT) != 1 || !iy.GetData(vy, vx, NULL, 0, DRR_BAD_WEIGHT_TREATMENT, &vnMissingValsIndices))
		XF_THROW(CER_NOT_ONE_XYRANGE)
	/// end RANGE_GET_DATA_PROVIDE_MAP_OF_MISSING_VALUES
	
	if(0 > order)
		XF_THROW_EX2(CER_INPUT_ARGUMENT_LESS_THAN_SPECIFIED_VALUE, STR_ERR_THROW, MIN_DERIVATIVE_ORDER)
		
	if(0>= vy.GetSize())
		XF_THROW(CER_NO_DATA);
	/*
	vector<uint> vN;
	// Handle missing values
	int nMissing;
	if (0 < (nMissing = ocmath_count(NANUM, vy.GetSize(), vy)))
	{
		int nSize = vx.GetSize();
		vy.Sort(SORT_ASCENDING, false, vN);
		vx.Reorder(vN);
		vx.SetSize(nSize - nMissing);
		vy.SetSize(nSize - nMissing);
		printf("Warning: %d missing values are ignored!\n", nMissing);
	}
	*/
	
	//y.GetData(vy, vx);	//	Copy X, Y data from XYRange into vectors
	vderivatived = vy;
	///Arvin 07/24/06 ADD_ORDER_OF_DERIVATIVE
	/*
	if (OE_NOERROR != ocmath_derivative(vx, vderivatived, vy.GetSize()))
	{
		//	output derivatived data
		/*
		derivative.GetPage().Show(FALSE);
		derivative.GetPage().Rename("Derivative1", FALSE);
		derivative.SetSize(-1,2);
		derivative.SetColDesignations("XY");
		Column colY;
		plot.GetYColumn(colY);
		Worksheet wks;
		colY.GetParent(wks);
		string strLabel;
		if(wks && colY)
			strLabel = "Derivative of " + wks.GetPage().GetName() + "_" + colY.GetName();
		derivative.Columns(1).SetLabel(strLabel);
		Dataset da(derivative, 0); da = vx;
		Dataset db(derivative, 1); db = vderivatived;
		*/
		/*
		if (oy.SetData(&vderivatived, &vx))
		{
			//	create the derivative curve
			/*
			GraphPage gp;
			GraphLayer gl;
			gp.Create("Origin", CREATE_HIDDEN);
			if( gp.IsValid() )
			{
				gp.Rename("DerivPlot1", FALSE);
				gl = gp.Layers();
				if( gl.IsValid() )
				{
					gl.AddPlot(oy, IDM_PLOT_LINE);
					gl.Rescale();
				}	
			}
			*/
			/*
			oy.MakePlot(iy);
		}
		else
		{
			//throw(DATARANGE_SETDATA_FAILED);
	
		}
	}
	else
	{
		// derivative failed
		XF_THROW(ERR_DERIVATIVE_FAILED);
	}
	*/
	/// Fisher 2008-11-11 QA80-12546 ADD_BACK_SMOOTH_OPTION_IN_DIFFERENTIATE_TOOL
	/*
	for( int ii = 1; ii <= order; ii++)
	{
		/// Fisher 2008-11-7 QA80-12546 ADD_BACK_SMOOTH_OPTION_IN_DIFFERENTIATE_TOOL
		//if (OE_NOERROR != ocmath_derivative(vx, vderivatived, vy.GetSize()))
	    if (OE_NOERROR != ocmath_derivative(vx, vderivatived, vy.GetSize(), 0, smooth, npts, poly))
	    /// End ADD_BACK_SMOOTH_OPTION_IN_DIFFERENTIATE_TOOL
	    {
			//	output derivatived data
			
			//derivative.GetPage().Show(FALSE);
			//derivative.GetPage().Rename("Derivative1", FALSE);
			//derivative.SetSize(-1,2);
			//derivative.SetColDesignations("XY");
			//Column colY;
			//plot.GetYColumn(colY);
			//Worksheet wks;
			//colY.GetParent(wks);
			//string strLabel;
			//if(wks && colY)
					//strLabel = "Derivative of " + wks.GetPage().GetName() + "_" + colY.GetName();
			//derivative.Columns(1).SetLabel(strLabel);
			//Dataset da(derivative, 0); da = vx;
			//Dataset db(derivative, 1); db = vderivatived;
			
			XF_THROW(CER_DIFFERENTIATE_FAILED);
	    }
	}
	*/
	///Kyle 01/21/2009 CHECK_WHETHER_INPUT_DATA_IS_EVENLY_SPACED_WHEN_SMOOTH_CHECKED
	//BOOL bUseSGDeri = false;
	//
	//if(smooth && npts>=4 && poly > 1 && vy.GetSize() > 2)
	//{	
		//double dTimeInterval = vx[1] - vx[0];
		//if( 0 == fft_sampling_resolution(&vx, dTimeInterval))
			//bUseSGDeri = true;
	//}
	//
	//if(bUseSGDeri)
	//{
		//ocmath_savitsky_golay_derivative(vx, vy, vderivatived, vx.GetSize(), npts/2, -1, poly, order);
	//}
	if(vy.GetSize() < MIN_INPUT_DATA_NUMBER)
		XF_THROW_EX(CER_DATA_TOO_FEW, MIN_INPUT_DATA_NUMBER);
	
	bool bIsEvenSpaced = true;			///Kyle 02/12/2009 ONLY_SHOW_WARNING_MESSAGE_IF_INPUT_DATA_IS_NOT_EVEN_SPACED
	
	if(smooth)
	{
		if(vy.GetSize() < MIN_INPUT_DATA_FOR_SMOOTH)
			XF_THROW_EX(CER_DATA_TOO_FEW, MIN_INPUT_DATA_FOR_SMOOTH);
		///Kyle 02/12/2009 ONLY_SHOW_WARNING_MESSAGE_IF_INPUT_DATA_IS_NOT_EVEN_SPACED
		//double dInterval;
		//if(OE_NOERROR != ocmath_sampling_resolution(vx.GetSize(), vx, &dInterval))
			//XF_THROW(CER_DATA_NOT_SUITABLE_FOR_SMOOTH);
		double dInterval;
		if(OE_NOERROR != ocmath_sampling_resolution(vx.GetSize(), vx, &dInterval))
			bIsEvenSpaced = false;
		///End ONLY_SHOW_WARNING_MESSAGE_IF_INPUT_DATA_IS_NOT_EVEN_SPACED
		
		if(order > poly)
			XF_THROW(CER_POLYDEG_GREATER_THAN_DERVORDER);
		
		if(npts < MIN_POINTS_IN_WINDOW || npts >= vx.GetSize())
			XF_THROW(XFERR_INVALID_WINDOW_POINTS);
		ocmath_savitsky_golay_derivative(vx, vy, vderivatived, vx.GetSize(), npts/2, -1, poly, order);
	}
	///End CHECK_WHETHER_INPUT_DATA_IS_EVENLY_SPACED_WHEN_SMOOTH_CHECKED
	else
	{	
		for( int ii = 1; ii <= order; ii++)
		{
			/// Fisher 2008-11-7 QA80-12546 ADD_BACK_SMOOTH_OPTION_IN_DIFFERENTIATE_TOOL
			//if (OE_NOERROR != ocmath_derivative(vx, vderivatived, vy.GetSize()))
			///Kyle 01/21/2009 CHECK_WHETHER_INPUT_DATA_IS_EVENLY_SPACED_WHEN_SMOOTH_CHECKED
		    //if (OE_NOERROR != ocmath_derivative(vx, vderivatived, vy.GetSize(), 0, smooth, npts, poly))
		    if (OE_NOERROR != ocmath_derivative(vx, vderivatived, vy.GetSize()))
		    ///End CHECK_WHETHER_INPUT_DATA_IS_EVENLY_SPACED_WHEN_SMOOTH_CHECKED
		    /// End ADD_BACK_SMOOTH_OPTION_IN_DIFFERENTIATE_TOOL
		    {
				//	output derivatived data
				/*
				derivative.GetPage().Show(FALSE);
				derivative.GetPage().Rename("Derivative1", FALSE);
				derivative.SetSize(-1,2);
				derivative.SetColDesignations("XY");
				Column colY;
				plot.GetYColumn(colY);
				Worksheet wks;
				colY.GetParent(wks);
				string strLabel;
				if(wks && colY)
					strLabel = "Derivative of " + wks.GetPage().GetName() + "_" + colY.GetName();
				derivative.Columns(1).SetLabel(strLabel);
				Dataset da(derivative, 0); da = vx;
				Dataset db(derivative, 1); db = vderivatived;
				*/
				XF_THROW(CER_DIFFERENTIATE_FAILED);
		    }
		}
	}
	/// End ADD_BACK_SMOOTH_OPTION_IN_DIFFERENTIATE_TOOL
	
	
	/// ML 11/10/2008 QA70-12356 RANGE_GET_DATA_PROVIDE_MAP_OF_MISSING_VALUES
	////------ Folger 09/25/08 QA80-12276 SET_SAMPLING_INTERVAL_FOR_YXRANGE_OUTPUT
	////if (oy.SetData(&vderivatived, &vx))
	//if( set_xyrange_data_ex(oy, &vderivatived, &vx) )
	////------
	///Kyle 11/11/2008 QA80-12356 SET_NOT_TO_ALTER_THE_INPUT_X_VALUES_WHEN_THERE_ARE_MISSING_VALUES
	//if( set_xyrange_data_ex(oy, &vderivatived, &vx, 0, NULL, &vnMissingValsIndices) )
	if( set_xyrange_data_ex(oy, &vderivatived, &vx, 0, iy, &vnMissingValsIndices) )
	///End SET_NOT_TO_ALTER_THE_INPUT_X_VALUES_WHEN_THERE_ARE_MISSING_VALUES
	/// end RANGE_GET_DATA_PROVIDE_MAP_OF_MISSING_VALUES
	{
		//	create the derivative curve
		/*
		GraphPage gp;
		GraphLayer gl;
		gp.Create("Origin", CREATE_HIDDEN);
		if( gp.IsValid() )
		{
			gp.Rename("DerivPlot1", FALSE);
			gl = gp.Layers();
			if( gl.IsValid() )
			{
				gl.AddPlot(oy, IDM_PLOT_LINE);
				gl.Rescale();
			}
		}
		*/
		/// Max 5/16/07 QA70-9715 NEW_NAME_CREATION
		/*
		Worksheet wks;
		int r1, r2, c1, c2;
		//iy.GetRange(0, r1, c1, r2, c2, wks);
		// Max 11/17/06 RUNTIME_ERROR_IF_NO_X_COLUMN
		//string strName = range_get_col_name(iy, Y_INDEX_IN_XYRANGE);
		int nYindex = get_first_y_col_index(iy);
		string strName = range_get_col_name(iy, nYindex);
		// END RUNTIME_ERROR_IF_NO_X_COLUMN
		//string srtOrder;
		//_set_order(order, srtOrder);
		*/
		/// END NEW_NAME_CREATION
		/*
		if(strName == NULL)
			strName = STR_DIFF_RESULT1;
		else
			//strName ="Differentiate of " + strName;
			strName.Format("%s" + STR_DIFF_RESULT2 + "%s", srtOrder, strName);
		oy.GetRange(Y_INDEX_IN_XYRANGE, r1, c1, r2, c2, wks);
		wks.Columns(c1).SetLongName(strName);
		*/
		/// Max 8/15/07 ADD_PLOT_VARIABLE_CONTROL
		/*
		// If user starts from a graph, create the Derivative Curve graph
		GraphLayer gl = Project.ActiveLayer();
		if(gl.IsValid())
		{
			GraphPage gp;
			gp.Create("Origin");
			GraphLayer glnew = gp.Layers();
			if(glnew)
			{
				int nIndex = glnew.AddPlot(oy, IDM_PLOT_LINE);
				DataPlot dp = glnew.DataPlots(nIndex);
				if(dp)
					dp.SetColor(color);
				glnew.Rescale();
				legend_update(glnew);
				gp.SetShow();
			}
		}
		*/
		if(plot)
		{
			///Arvin 08/23/07 QA70-10073 KEEP_OUTPUT_CURVE_CUSTOMIZATION_AFTER_RECALCULATE_FOR_XF
			/*
			GraphPage gp;
			gp.Create("Origin");
			GraphLayer glnew = gp.Layers();
			if(glnew)
			{
				int nIndex = glnew.AddPlot(oy, IDM_PLOT_LINE);
				glnew.Rescale();
				legend_update(glnew);
			}
			*/
			xf_check_plot_output_rng_in_graph(oy);
			///end KEEP_OUTPUT_CURVE_CUSTOMIZATION_AFTER_RECALCULATE_FOR_XF
		}
		/// END ADD_PLOT_VARIABLE_CONTROL
	}
	else
		XF_THROW(CER_DIFFERENTIATE_FAILED);
	///end ADD_ORDER_OF_DERIVATIVE
	
	//LT_execute("legend -s");
	
	//------ Folger 07/23/08 BETTER_OPREATION_OUTPUT_COLUMN_COMMENTS
	_set_output_range_comments(oy, iy, order);
	//------
	
	///Kyle 02/12/2009 ONLY_SHOW_WARNING_MESSAGE_IF_INPUT_DATA_IS_NOT_EVEN_SPACED
	///------ Folger 04/14/09 QA80-13436 IMPROVE_MECHANISM_ABOUT_XF_ERR_MSG_SHOWN_IN_BODY
	//if(smooth && !bIsEvenSpaced)
	if ( SHOULD_WARNING_MSG_SHOW_IN_XF_BODY && smooth && !bIsEvenSpaced )
	///------ End IMPROVE_MECHANISM_ABOUT_XF_ERR_MSG_SHOWN_IN_BODY
	{
		warning_msg_box(XFWAR_NOT_EVEN_SPACE_IN_SG_SMOOTH, false, 'I');
	}
	///End ONLY_SHOW_WARNING_MESSAGE_IF_INPUT_DATA_IS_NOT_EVEN_SPACED
}

//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 differentiate_event1(TreeNode& trGetN, int nRow, int nEventID, DWORD& dwEnables, LPCSTR lpcszNodeName, WndContainer& DynaCntrlContainer, string& strAux, string& strErrMsg)
{
	if( xf_is_extended_event(nEventID) )
		return differentiate_event1_ex(trGetN, nRow, nEventID, dwEnables, lpcszNodeName, DynaCntrlContainer, strAux, strErrMsg);
	DECLARE_BUTTON_ENABLES
	//if(nEventID == GETNE_ON_INIT)
		//_init_tree_show(trGetN);
	
	int nErr = CER_NO_ERROR;
	
	/// Fisher 2008-11-7 QA80-12546 ADD_BACK_SMOOTH_OPTION_IN_DIFFERENTIATE_TOOL
	if(trGetN.smooth.nVal)
	{
		trGetN.poly.Enable = true;
		trGetN.npts.Enable = true;
	}
	else
	{
		trGetN.poly.Enable = false;
		trGetN.npts.Enable = false;
	}
	    /// End ADD_BACK_SMOOTH_OPTION_IN_DIFFERENTIATE_TOOL	
	
	
	///Cheney 2007-6-7 ADD_AN_ERR_CHECK_FUNC
	//if(get_input_xyrange_num(trGetN.iy) != 1)
		//nErr = CER_NOT_ONE_XYRANGE;
	//
	//if(nErr == CER_NO_ERROR && 0>= get_input_xyrange_data_size(trGetN.iy))
		//nErr = CER_NO_DATA;
	//
	//if(nErr == CER_NO_ERROR && trGetN.order.nVal < 0)
		//nErr = CER_INPUT_ARGUMENT_LESS_THAN_SPECIFIED_VALUE;
	nErr = _check_err_condition(trGetN);
	/////end ADD_AN_ERR_CHECK_FUNC
	
	
	if(nErr != CER_NO_ERROR)
	{
		bOKEnable = false;
		strErrMsg = nErr;
		///Arvin 07/30/07 WRONG_ERR_MASSAGE
		if(nErr == CER_DATA_TOO_FEW)
		{
			strErrMsg += ":";
			///Kyle 01/21/2009 CHECK_WHETHER_INPUT_DATA_IS_EVENLY_SPACED_WHEN_SMOOTH_CHECKED
			//strErrMsg += MIN_INPUT_DATA_NUMBER;
			if(trGetN.smooth.nVal)
				strErrMsg += MIN_INPUT_DATA_FOR_SMOOTH;
			else
				strErrMsg += MIN_INPUT_DATA_NUMBER;
			///End CHECK_WHETHER_INPUT_DATA_IS_EVENLY_SPACED_WHEN_SMOOTH_CHECKED
		}
		///end WRONG_ERR_MASSAGE
		if (nErr == CER_INPUT_ARGUMENT_LESS_THAN_SPECIFIED_VALUE)
		{
			strErrMsg += ":";
			strErrMsg += STR_ERR_THROW;
			strErrMsg += "|";
			strErrMsg += MIN_DERIVATIVE_ORDER;
		}
		
		///Kyle 02/12/2009 ONLY_SHOW_WARNING_MESSAGE_IF_INPUT_DATA_IS_NOT_EVEN_SPACED
		/// Max 2/11/09 v8.0977b USE_ANOTHER_STRING_FOR_CENTRALIZATION
		//if(nErr == CER_DATA_NOT_SUITABLE_FOR_SMOOTH)
		if(nErr == XFWAR_NOT_EVEN_SPACE_IN_SG_SMOOTH)
		/// ---	
			bOKEnable = true;
		///End ONLY_SHOW_WARNING_MESSAGE_IF_INPUT_DATA_IS_NOT_EVEN_SPACED
	}
	
	return false;

}

int differentiate_make_tree(TreeNode& tr, LPCSTR lpcszVarName)
{
	return false;
}
//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 differentiate_before_execute(TreeNode& trGetN, int nGetNDialog, int& nRet, int dwCntrl)
{
	
	//------ fisher 11/16/07 ADD_MAP_ID_TO_CHM
	if(is_use_origin_chm())
		trGetN.SetAttribute(STR_HELPID_ATTRIB, IDD_XF_differentiate);
	
	///Arvin 08/16/07 QA70-10073 KEEP_OUTPUT_CURVE_CUSTOMIZATION_AFTER_RECALCULATE_FOR_XF
	//if (dwCntrl&LTXF_CHANGE_PARAM)
	//if ((dwCntrl&LTXF_CHANGE_PARAM) || (dwCntrl&LTXF_FROM_AUTO_UPDATE))
	///end KEEP_OUTPUT_CURVE_CUSTOMIZATION_AFTER_RECALCULATE_FOR_XF
		//trGetN.plot.nVal = 0;	
	
	///Cheney 2007-6-7 ADD_AN_ERR_CHECK_FUNC
	///Cheney 2007-6-14 PROCEED_WITH_DLG_SHOULD_IF_ERR
	//if(0 == nGetNDialog && (dwCntrl&LTXF_THEME_USED) && _check_err_condition(trGetN) != CER_NO_ERROR)
	if(0 == nGetNDialog && (dwCntrl&LTXF_THEME_USED) && (dwCntrl&LTXF_FROM_GUI_MENU)
		&& _check_err_condition(trGetN) != CER_NO_ERROR)
	///end 	PROCEED_WITH_DLG_SHOULD_IF_ERR
		nRet = XFEVT_PROCEED_WITH_DLG;	
	///end ADD_AN_ERR_CHECK_FUNC
	
	///------ Folger 04/14/09 QA80-13436 IMPROVE_MECHANISM_ABOUT_XF_ERR_MSG_SHOWN_IN_BODY
	if ( is_xf_startup(nGetNDialog, dwCntrl) )
		SET_WARNING_MSG_SHOW_IN_XF_BODY(IS_ERR_MSG_OK_TO_SHOW_IN_BODY);
	///------ End IMPROVE_MECHANISM_ABOUT_XF_ERR_MSG_SHOWN_IN_BODY
	
}
//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 differentiate_event1_ex(TreeNode& trGetN, int nRow, int nEventID, DWORD& dwEnables, LPCSTR lpcszNodeName, WndContainer& DynaCntrlContainer, string& strAux, string& strErrMsg)
{
	return false;
}
