/*------------------------------------------------------------------------------*
 * File Name: PBRangeList.h														*
 * Creation: Folger 07/06/07													*
 * Purpose: Origin C Header														*
 * Copyright (c) OriginLab Corp.2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007	*
 * All Rights Reserved															*
 * 																				*
 * Modification Log:															*
 * Folger 07/17/07 CLEAN_UP_DUPLICATED_CODES_IN_PROJECT_BROWSER_RANGE_BROWSER	*
 * Folger 07/24/07 CLEAN_UP_DATAPLOT_RANGE_STRING_CODE							*
 * Folger 07/26/07 TRIM_ALL_WHITE_SPACE_IN_RANGE_STRING							*
 * Folger 07/27/07 USE_OKOC_COMPARE_OBJ_RANGES_WHEN_ADD_RANGE					*
 * Folger 07/27/07 BROWSE_ROWS_IN_PLOT_RANGE									*
 * Folger 07/30/07 IMPROVE_RESOLVE_SOURCE_RANGE_STRING_FROM_DATAPLOT			*
 * Folger 07/31/07 SUPPORT_DRAG&DROP_IN_RANGE_BROWSER_BOTTOM_PANEL				*
 * Folger 12/12/07 FIX_BUGS_OF_RANGE_BROWSER_ROW_SELECTION_DIALOG				*
 *	YuI 07/13/09 QA70-13932 RANGE_DIALOG_FAILS_IF_NAME_IS_QUOTED				*
 *------------------------------------------------------------------------------*/
 
#ifndef __PB_RANGE_LIST_H__
#define __PB_RANGE_LIST_H__

#include <okocUtils.h>
#include <xfutils.h>	///Jasmine 10/31/07 USE_OKXF_FUNCTION_TO_GET_DATAPLOT
 
#define CHAR_RANGE_SEPARATOR	','
#define STR_ENTIRE_COLUMN		"[1:end]"
enum
{
	COL_RANGE, 
	COL_ROWS,
	COL_DESIGNATION,		
};
//------ Folger 07/31/07 SUPPORT_DRAG&DROP_IN_RANGE_BROWSER_BOTTOM_PANEL
//class PBRangeListBase : public GridListControl
class PBRangeListBase : public TreeEditControl
//------ End SUPPORT_DRAG&DROP_IN_RANGE_BROWSER_BOTTOM_PANEL
{
public:
	PBRangeListBase() {}
	virtual void Init(int nID, WndContainer& dlg) {}
	virtual bool AddRow(int nRow, LPCSTR lpcszData)
	{
		return true;
	}
	virtual void OnButtonClick(Control flxControl, int nRow, int nCol) {}
	virtual void OnBeforeEditParaControl(Control flxControl, long nRow, long nCol, BOOL* pCancel) {}
	//------Folger 07/17/07 CLEAN_UP_DUPLICATED_CODES_IN_PROJECT_BROWSER_RANGE_BROWSER
	int AddRows(const vector<string> &vsSelected, vector<string> &vsVals)
	{
		GetColValues(COL_RANGE + GetColOffset(), vsVals, GetRowOffset());
		//------ Folger 07/26/07 TRIM_ALL_WHITE_SPACE_IN_RANGE_STRING
		//------ Folger 07/27/07 USE_OKOC_COMPARE_OBJ_RANGES_WHEN_ADD_RANGE
		int nSize = vsSelected.GetSize();
		for (int ii=0; ii<nSize; ii++)
		//vector<string> vsTrim;
		//vsTrim = vsVals;
		//int nSize = vsTrim.GetSize();
		//for (int ii=0; ii<nSize; ii++)
			//vsTrim[ii].Remove(' ');
		//nSize = vsSelected.GetSize();
		//for (ii=0; ii<nSize; ii++)
		//------ End TRIM_ALL_WHITE_SPACE_IN_RANGE_STRING
		{
			//------ Folger 07/26/07 TRIM_ALL_WHITE_SPACE_IN_RANGE_STRING
			//if (vsVals.Find(vsSelected[ii]) == -1)
			//string strTrim = vsSelected[ii];
			//strTrim.Remove(' ');
			//if (vsTrim.Find(strTrim) == -1)
			//------ End TRIM_ALL_WHITE_SPACE_IN_RANGE_STRING
			if (!FindValues(vsVals, vsSelected[ii]))
			//------ End USE_OKOC_COMPARE_OBJ_RANGES_WHEN_ADD_RANGE
			{
				int nRowStart = GetRows();
				AddRow(nRowStart, vsSelected[ii]);
				vsVals.Add(vsSelected[ii]);
			}
		}
		ResizeCols();
		return vsVals.GetSize();
	}
	int RemoveSelectedRows(vector<string> &vsVals)
	{
		vector<uint> vnRows;
		int nRowOffset = GetRowOffset();
		GetSelRows(vnRows);
		GetColValues(COL_RANGE + GetColOffset(), vsVals, nRowOffset);
		int nSelRow = GetSelectedRow();
		for(int index = vnRows.GetSize() - 1; index >= 0; index--)
		{
			DeleteRow(vnRows[index]);
			vsVals.RemoveAt(vnRows[index] - nRowOffset);
		}
		selectRow(nSelRow);
		return vsVals.GetSize();
	}
	int GetSelection(string& strSelection)
	{
		int nRow = GetSelectedRow();
		strSelection = 	GetCell(nRow, GetColOffset() + COL_RANGE);
		return nRow;
	}
	//-------Folger 07/24/07 CLEAN_UP_DATAPLOT_RANGE_STRING_CODE
	//------ Folger 07/30/07 IMPROVE_RESOLVE_SOURCE_RANGE_STRING_FROM_DATAPLOT
	//void ConvertDataPlotRange(string &strRange)
	//------ Folger 12/12/07 FIX_BUGS_OF_RANGE_BROWSER_ROW_SELECTION_DIALOG
	//DataPlot ConvertDataPlotRange(string &strRange);
	DataPlot ConvertDataPlotRange(string &strRange, int *nPlotFrom = NULL, int *nPlotTo = NULL)
	//------
	//------ End IMPROVE_RESOLVE_SOURCE_RANGE_STRING_FROM_DATAPLOT
	{
		///Jasmine 10/31/07 USE_OKXF_FUNCTION_TO_GET_DATAPLOT
		DataPlot dp;		//------ Folger 07/30/07 IMPROVE_RESOLVE_SOURCE_RANGE_STRING_FROM_DATAPLOT
		BOOL bRet = okxf_resolve_string_get_origin_object(strRange, &dp);
		string strPage, strLayer, strObj;
		//okutil_parse_complete_range_string(strRange, &strPage, &strLayer, &strObj);
		//GraphPage gp(strPage);
		//GraphLayer gl;
		//if (gp)
			//gl = gp.Layers(strLayer);
		//if (gl)
		if(dp)
		{
			string strCol, strR1, strR2;
			okutil_parse_complete_range_string(strRange, &strPage, &strLayer, &strObj);
			okutil_parse_range_string(strObj, &strCol, strR1, NULL, strR2);
			////------ Folger 07/30/07 IMPROVE_RESOLVE_SOURCE_RANGE_STRING_FROM_DATAPLOT
			////int nIndex = _get_index_from_plot_range_string(strObj) - 1;
			//int nIndex = _parse_col_row_from_plot_range_string(strObj, strCol, strR1, strR2) - 1;
			////------ End IMPROVE_RESOLVE_SOURCE_RANGE_STRING_FROM_DATAPLOT
			//dp = gl.DataPlots(nIndex);
		///End USE_OKXF_FUNCTION_TO_GET_DATAPLOT
			//---- CPY 7/24/07 RANGE_BROWSER_NEED_BETTER_RANGE_STR
			//strRange = get_content(dp);
			dp.GetRangeString(strRange, NTYPE_BOOKSHEET_XY_RANGE | NTYPE_ADD_ROW_RANGE);
			//---
			//------ Folger 07/30/07 IMPROVE_RESOLVE_SOURCE_RANGE_STRING_FROM_DATAPLOT
			string strOldR1, strOldR2;
			okutil_parse_complete_range_string(strRange, &strPage, &strLayer, &strObj);
			okutil_parse_range_string(strObj, &strCol, strOldR1, NULL, strOldR2);
			//------ Folger 12/12/07 FIX_BUGS_OF_RANGE_BROWSER_ROW_SELECTION_DIALOG
			if (nPlotFrom != NULL)
				*nPlotFrom = atoi(strOldR1);
			if (nPlotTo != NULL)
				*nPlotTo = atoi(strOldR2);
			//------
			if ((!strR1.IsEmpty() && !strR2.IsEmpty()) &&
				(strR1.CompareNoCase(strOldR1) || strR2.CompareNoCase(strOldR2)))
				okutil_create_complete_range_string_col_row(strRange, strPage, strLayer, strCol, atoi(strR1), strCol, atoi(strR2));
			//------ End IMPROVE_RESOLVE_SOURCE_RANGE_STRING_FROM_DATAPLOT
		}
		return dp;		//------ Folger 07/30/07 IMPROVE_RESOLVE_SOURCE_RANGE_STRING_FROM_DATAPLOT
	}
	//-------End CLEAN_UP_DATAPLOT_RANGE_STRING_CODE
	
	BOOL FindValues(const vector<string> vsVals, string str)
	{
		int nRet;
		int nSize = vsVals.GetSize();
		for (int ii=0; ii<nSize; ii++)
		{
			if ((nRet = okoc_compare_obj_ranges(vsVals[ii], str, false)) == 0)
				return true;
		}
		return false;
	}
	
private:
	void selectRow(int nRow = -1)
	{
		if(GetRows() <= 0)
			return;
		
		while(nRow >= GetRows())
			nRow--;
			
		if(nRow < 0)
			nRow = GetSelectedRow(); // get 1st if multiple selection, -1 if none selected
		if( nRow < 0 )
			nRow = 0;
		
		if (nRow != 0) SelRow(nRow);	
	}
	//------End CLEAN_UP_DUPLICATED_CODES_IN_PROJECT_BROWSER_RANGE_BROWSER
};

static bool _on_check_entire_column_event(TreeNode& myTree, int nRow, int nCol, TreeNode& trNode, DWORD dwCntrl, int nType, WndContainer& theDlg)
{
	bool bEntire = trNode.nVal;
	TreeNode trFrom = myTree.GetNode("FromRow");
	TreeNode trTo = myTree.GetNode("ToRow");
	if(trFrom && trTo)
	{
		trFrom.Enable = !bEntire;
		trTo.Enable = !bEntire;	
		if(bEntire)	
		{
			//------ Folger 12/12/07 FIX_BUGS_OF_RANGE_BROWSER_ROW_SELECTION_DIALOG
			/*
			trFrom.strVal = "1";
			int nRows;
			trNode.GetAttribute(STR_DATA_ATTRIB, nRows);
			trTo.strVal = (string)nRows;
			*/
			string strTmp;
			vector<string> vsTmp;
			trNode.GetAttribute(STR_DATA_ATTRIB, strTmp);
			strTmp.GetTokens(vsTmp, '|');
			trFrom.strVal = vsTmp[0];
			trTo.strVal = vsTmp[1];
			//------
		}
		return true;
	}
	return false;
}

class PageRangeList : public PBRangeListBase
{
public:
	PageRangeList()
	{
	}
	void Init(int nID, WndContainer& dlg)
	{
		GridListControl::Init(nID, dlg);
		SetAllowSelection(true);	///If false , support single selete; else multi seletion
		SetSelection( flexSelectionListBox );
		SetEditable(flexEDKbd);//flexEDKbdMouse
		SetupRowsCols(1, 1, -1, 2);
		SetColHeading(COL_RANGE, _L("Range"));
		ResizeCols();
		SetReady();
	}
	bool AddRow(int nRow, LPCSTR lpcszData)
	{
		SetRows(nRow - GetRowOffset() + 1);
		string strData = lpcszData;
		SetCell(nRow, COL_RANGE + GetColOffset(), strData);
		return true;
	}
};

class SheetRangeList : public PBRangeListBase
{
public:
	SheetRangeList()
	{
	}
	void Init(int nID, WndContainer& dlg)
	{
		GridListControl::Init(nID, dlg);
		SetAllowSelection(true);	///If false , support single selete; else multi seletion
		SetSelection( flexSelectionListBox );
		SetEditable(flexEDKbd);//flexEDKbdMouse
		SetupRowsCols(1, 1, -1, 2);
		SetColHeading(COL_RANGE, _L("Range"));
		ResizeCols();
		SetReady();
	}
	bool AddRow(int nRow, LPCSTR lpcszData)
	{
		SetRows(nRow - GetRowOffset() + 1);
		string strData = lpcszData;
		SetCell(nRow, COL_RANGE + GetColOffset(), strData);
		return true;
	}
};

class ColumnRangeList : public PBRangeListBase
{
public:	
	ColumnRangeList()
	{
	}
	void Init(int nID, WndContainer& dlg)
	{
		//------ Folger 07/31/07 SUPPORT_DRAG&DROP_IN_RANGE_BROWSER_BOTTOM_PANEL
		
		//GridListControl::Init(nID, dlg);
		//SetAllowSelection(true);	///If false , support single selete; else multi seletion
		//SetSelection( flexSelectionListBox );
		//SetEditable(flexEDKbd);//flexEDKbdMouse
		//SetupRowsCols(1, 1, -1, 3);
		//SetColHeading(COL_RANGE, _L("Range"));
		//SetColHeading(COL_ROWS, _L("Rows"));
		//m_flx.ColComboList(COL_ROWS + GetColOffset()) = "...";	//add "..." button
		//ResizeCols();
		//SetReady();
		
		Tree tr;
		TreeEditControl::Init(nID, false, true, NULL, dlg);
		SetAllowSelection(true);
		SetSelection( flexSelectionListBox );
		SetEditable(flexEDKbd);
		SetupRowsCols(0, 0, 1, 2);
		SetTreeNodeMoveRowsAttrib(tr);
		//add an empty treenode in order to construct empty TreeEditControl			
		Tree trPages;
		TreeNode trnode = trPages.AddNode();
		trnode.Range.strVal = "";
		trnode.Rows.strVal = "";
		trnode.Range.SetAttribute(STR_LABEL_ATTRIB, _L("Range"));
		trnode.Rows.SetAttribute(STR_LABEL_ATTRIB, _L("Rows"));
		
		UpdateGrid(trPages);
		SetColComboList(COL_ROWS + GetColOffset(), "...");	//add "..." button
		DeleteRow(GetRowOffset());		//remove the empty row
		ResizeCols();
		SetReady();
		//------ End SUPPORT_DRAG&DROP_IN_RANGE_BROWSER_BOTTOM_PANEL
	}
	bool AddRow(int nRow, LPCSTR lpcszData)
	{
		SetRows(nRow - GetRowOffset() + 1);
		string strData = lpcszData;
		SetCell(nRow, COL_RANGE + GetColOffset(), strData);
		strData = getRowRange(lpcszData);
		SetCell(nRow, COL_ROWS + GetColOffset(), strData);
		return true;
	}
	void OnButtonClick(Control flxControl, int nRow, int nCol)
	{
		if(COL_ROWS + GetColOffset() == nCol)
		{
			string strRange = GetCell(nRow, COL_RANGE + GetColOffset());
			//------ Folger 07/27/07 BROWSE_ROWS_IN_PLOT_RANGE
			string strTmp = strRange;
			//------ Folger 07/30/07 IMPROVE_RESOLVE_SOURCE_RANGE_STRING_FROM_DATAPLOT
			//ConvertDataPlotRange(strRange);
			//------ Folger 12/12/07 FIX_BUGS_OF_RANGE_BROWSER_ROW_SELECTION_DIALOG
			//DataPlot dp = ConvertDataPlotRange(strRange);
			///Sophy CLEAN_CODE_PBLIST_CONTROL
			/*
			int nPlotFrom = 0, nPlotTo = 0;
			DataPlot dp = ConvertDataPlotRange(strRange, &nPlotFrom, &nPlotTo);
			//------
			//------ End IMPROVE_RESOLVE_SOURCE_RANGE_STRING_FROM_DATAPLOT
			if (strRange.CompareNoCase(strTmp) == 0)
				strTmp.Empty();
			//------ End BROWSE_ROWS_IN_PLOT_RANGE
			*/
			///end Sophy CLEAN_CODE_PBLIST_CONTROL
			string strBook, strSheet, strObj;
			//------ Folger 07/30/07 IMPROVE_RESOLVE_SOURCE_RANGE_STRING_FROM_DATAPLOT
		 	string strCol1, strCol2, strR1, strR2;
		 	string strRows;
		 	//------ End IMPROVE_RESOLVE_SOURCE_RANGE_STRING_FROM_DATAPLOT
		 	///Sophy CLEAN_CODE_PBLIST_CONTROL
		 	//bool bOK;
		 	//BOOL bR1Auto = false, bR2Auto = false;
		 	///end Sophy CLEAN_CODE_PBLIST_CONTROL
		 	int nR1 = -1, nR2 = -1;
		 	///Sophy CLEAN_CODE_PBLIST_CONTROL
		 	/*
		 	if(okutil_parse_complete_range_string(strRange, &strBook, &strSheet, &strObj))
		 	{
		 		if(okutil_parse_range_string(strObj, &strCol1, &strR1, &strCol2, &strR2))
		 		{	//------ Folger 07/30/07 IMPROVE_RESOLVE_SOURCE_RANGE_STRING_FROM_DATAPLOT
		 			bOK = true;
		 			//------ Folger 07/30/07 IMPROVE_RESOLVE_SOURCE_RANGE_STRING_FROM_DATAPLOT
		 			if (!strR1.IsEmpty() && !strR2.IsEmpty())
		 			{
		 				strRows = "[" + strR1 + ":" + strR2 + "]";
		 				okutil_parse_row_range(strRows, &nR1, &bR1Auto, &nR2, &bR2Auto);
		 				strR1.Format("%d", nR1 + 1);
		 				strR2.Format("%d", nR2 + 1);
		 			}
		 		}
		 		//------ End IMPROVE_RESOLVE_SOURCE_RANGE_STRING_FROM_DATAPLOT
		 	}
		 	if(!bOK || strCol1.IsEmpty())
		 		return;
		 	Worksheet 		wks;
			WorksheetPage 	wp(strBook);
			if(wp)
				wks = wp.Layers(strSheet);
			//------ Folger 12/12/07 FIX_BUGS_OF_RANGE_BROWSER_ROW_SELECTION_DIALOG
			//if(!wks)
			////------ Folger 07/30/07 IMPROVE_RESOLVE_SOURCE_RANGE_STRING_FROM_DATAPLOT
				////return;
			//{
				//if (dp)
				//{
					//XYRange drXY;
					//dp.GetDataRange(drXY);
					//int r1, r2, c1, c2;
					//if (drXY)
						//drXY.GetRange("Y", r1, c1, r2, c2, wks);
				//}
				//else
					//return;
			//}
			////------ End IMPROVE_RESOLVE_SOURCE_RANGE_STRING_FROM_DATAPLOT
			int nMin, nMax;
			if (dp)
			{
				nMin = nPlotFrom -1 ;
				nMax = nPlotTo - 1;
			}
			else
			{
				wks.GetBounds(nMin, 0, nMax, -1);
			 	//int nRows = wks.GetNumRows();
			}
			bool bEntire;
			//------ Folger 07/30/07 IMPROVE_RESOLVE_SOURCE_RANGE_STRING_FROM_DATAPLOT
			//if(strCol2.IsEmpty() || (strR1.IsEmpty() && strR2.IsEmpty()) || (0 == strR1.CompareNoCase("1") && 0 == strR2.CompareNoCase("end")))
			if(strCol2.IsEmpty() || (strR1.IsEmpty() && strR2.IsEmpty()) || (0 == strR1.CompareNoCase("1") && 0 == strR2.CompareNoCase("end")) ||
				(bR1Auto && bR2Auto))
			//------ End IMPROVE_RESOLVE_SOURCE_RANGE_STRING_FROM_DATAPLOT
			{
				bEntire = true;
				strR1 = (string)(nMin + 1);
			}
			if(bEntire || 0 == strR2.CompareNoCase("end"))
				strR2 = (string)(nMax + 1);
			//------ End FIX_BUGS_OF_RANGE_BROWSER_ROW_SELECTION_DIALOG
			//------ Folger 07/27/07 BROWSE_ROWS_IN_PLOT_RANGE
			if (!strTmp.IsEmpty())
			{
				if(okutil_parse_complete_range_string(strTmp, &strBook, &strSheet, &strObj))
			 	{
			 		okutil_parse_range_string(strObj, &strCol1, &strR1, &strCol2, &strR2);
			 	}
			}
			//------ End BROWSE_ROWS_IN_PLOT_RANGE
			if(trRange.EntireCol.nVal)
			{
				okutil_create_range_string(strRows, strCol1, NULL, strCol2, NULL);
				okutil_create_complete_range_string_obj(&strRange, strBook, strSheet, strRows);
				strRows = STR_ENTIRE_COLUMN;			
			}
			else
			{				
				okutil_create_complete_range_string_col_row(&strRange, strBook, strSheet, strCol1, nR1, strCol2, nR2);
				strRows.Format("[%d:%d]", nR1, nR2);
			}
			
			//------ Folger 12/12/07 FIX_BUGS_OF_RANGE_BROWSER_ROW_SELECTION_DIALOG
			vector<string> vsRanges;
			GetColValues(COL_RANGE + GetColOffset(), vsRanges, GetRowOffset());
			vsRanges.RemoveAt(nRow - GetRowOffset());
			if (FindValues(vsRanges, strRange))
			{
				MessageBox(GetDlgSafeHwnd(), _L("A same range already exists. Please specify again."), NULL, MB_OK);
				return;
			}
			//------
			*/
			///end Sophy CLEAN_CODE_PBLIST_CONTROL
			
			///Sophy CLEAN_CODE_PBLIST_CONTROL
			bool bAuto = false;
			if( !getRangeStrings( strRange, strRows, strBook, strSheet, strObj, strR1, strCol1, strR2, strCol2, nR1, nR2, bAuto) )
				return;
			
			TreeNode trRange;
			trRange = checkGetValidRangeNode( strRange, strR1, strR2, nR1, nR2, strCol2, bAuto );
			
			if (strRange.CompareNoCase(strTmp) == 0)
				strTmp.Empty();

			if( !checkGetValidRangeString( strTmp, strRange, strRows, strBook, strSheet, strObj, nR1, strCol1, nR2, strCol2, nRow, trRange.EntireCol.nVal ) )
				return;
			///end Sophy CLEAN_CODE_PBLIST_CONTROL
			
			SetCell(nRow, COL_RANGE + GetColOffset(), strRange);
			SetCell(nRow, COL_ROWS + GetColOffset(), strRows);		
			ResizeCols();
		}
	}
	
	void OnBeforeEditParaControl(Control flxControl, long nRow, long nCol, BOOL* pCancel)
	{
		if(COL_ROWS + GetColOffset() != nCol)
			*pCancel = true;
	}
private:
	string getRowRange(LPCSTR lpcszData)
	{
	 	string strRows = STR_ENTIRE_COLUMN;
		string strRange(lpcszData);
		string strBook, strSheet, strObj; 	
	 	string strCol1, strCol2, strR1, strR2;
	 	bool bOK;
	 	if(okutil_parse_complete_range_string(strRange, &strBook, &strSheet, &strObj))
	 	{
	 		if(okutil_parse_range_string(strObj, &strCol1, &strR1, &strCol2, &strR2) && !strCol1.IsEmpty())
	 		{
	 			if(strCol2.IsEmpty() || (strR1.IsEmpty() && strR2.IsEmpty()) || (0 == strR1.CompareNoCase("1") && 0 == strR2.CompareNoCase("end")))
					return strRows;		
				strRows.Format("[%s:%s]", strR1, strR2);
	 		}
	 	}
	 	return strRows;
	}
	///Sophy CLEAN_CODE_PBLIST_CONTROL
	TreeNode	checkGetValidRangeNode( string& strRange, string& strR1, string& strR2, int& nR1, int& nR2, string& strCol2, bool bAuto)
	{
		string strBook, strSheet, strObj;
		int nPlotFrom = 0, nPlotTo = 0;
		DataPlot dp = ConvertDataPlotRange(strRange, &nPlotFrom, &nPlotTo);
		
		okutil_parse_complete_range_string(strRange, &strBook, &strSheet, &strObj);
		
		/// YuI 07/13/09 QA70-13932 RANGE_DIALOG_FAILS_IF_NAME_IS_QUOTED
		okutil_check_remove_quotes(&strBook);
		okutil_check_remove_quotes(&strSheet);
		/// end RANGE_DIALOG_FAILS_IF_NAME_IS_QUOTED
		
		Worksheet 		wks;
		WorksheetPage 	wp(strBook);
		if(wp)
			wks = wp.Layers(strSheet);
	
		int nMin, nMax;
		if (dp)
		{
			nMin = nPlotFrom -1 ;
			nMax = nPlotTo - 1;
		}
		else
		{
			wks.GetBounds(nMin, 0, nMax, -1);
		 	//int nRows = wks.GetNumRows();
		}
		bool bEntire;
		//------ Folger 07/30/07 IMPROVE_RESOLVE_SOURCE_RANGE_STRING_FROM_DATAPLOT
		//if(strCol2.IsEmpty() || (strR1.IsEmpty() && strR2.IsEmpty()) || (0 == strR1.CompareNoCase("1") && 0 == strR2.CompareNoCase("end")))
		if(strCol2.IsEmpty() || (strR1.IsEmpty() && strR2.IsEmpty()) || (0 == strR1.CompareNoCase("1") && 0 == strR2.CompareNoCase("end")) || bAuto)
		//------ End IMPROVE_RESOLVE_SOURCE_RANGE_STRING_FROM_DATAPLOT
		{
			bEntire = true;
			strR1 = (string)(nMin + 1);
		}
		if(bEntire || 0 == strR2.CompareNoCase("end"))
			strR2 = (string)(nMax + 1);
		//------ End FIX_BUGS_OF_RANGE_BROWSER_ROW_SELECTION_DIALOG
		
		string strWarn = _L("Input integer should between");
		strWarn.Format("*%s [%d:%d]", strWarn, nMin + 1, nMax + 1);
		GETN_TREE(trRange)
		GETN_STR(Min, _L("Min"), (string)++nMin)	GETN_READ_ONLY_COLOR
		GETN_CURRENT_SUBNODE.Show = false;
		GETN_STR(Max, _L("Max"), (string)++nMax)	GETN_READ_ONLY_COLOR
		GETN_CURRENT_SUBNODE.Show = false;
		//------ Folger 12/12/07 FIX_BUGS_OF_RANGE_BROWSER_ROW_SELECTION_DIALOG
		//GETN_CHECK(EntireCol, _L("Entire Column(s)"), bEntire)	GETN_OPTION_EVENT_EX(_on_check_entire_column_event)
		//GETN_CURRENT_SUBNODE.SetAttribute(STR_DATA_ATTRIB, nRows);
		GETN_CHECK(EntireCol, dp ? _L("Entire Plot") : _L("Entire Column(s)"), bEntire)	GETN_OPTION_EVENT_EX(_on_check_entire_column_event) 
		GETN_CURRENT_SUBNODE.SetAttribute(STR_DATA_ATTRIB, (string)(nMin) + '|' + (string)(nMax));
		//------
		
		GETN_STR(FromRow, _L("From"), strR1) 
		GETN_CURRENT_SUBNODE.Enable = !bEntire;
		GETN_STR(ToRow, _L("To"), strR2)
		GETN_CURRENT_SUBNODE.Enable = !bEntire;
		GETN_STR(Warning, "", strWarn)				GETN_READ_ONLY_COLOR
		
		//int nR1, nR2;		//------ Folger 07/30/07 IMPROVE_RESOLVE_SOURCE_RANGE_STRING_FROM_DATAPLOT
		bool	bOK = false;
		while(!bOK)
		{
			if(!GetNBox(trRange, _L("Range"), NULL, NULL, NULL, GetDlgSafeHwnd()))
				return trRange;
			bOK = true;
			strR1 = trRange.FromRow.strVal;
			strR2 = trRange.ToRow.strVal;
			nR1 = atoi(strR1);
			nR2 = atoi(strR2);	
			//------ Folger 12/12/07 FIX_BUGS_OF_RANGE_BROWSER_ROW_SELECTION_DIALOG
			//if(1 > nR1 || nR1 > nRows || 1 > nR2 || nR2 > nRows)
			if(nMin > nR1 || nR1 > nMax || nMin > nR2 || nR2 > nMax)
				bOK = false;
			//------
		}
		return trRange;
	}
	bool	checkGetValidRangeString( string strTmp, string& strRange, string& strRows, string& strBook, string& strSheet, string& strObj, int& nR1, string& strCol1, int& nR2, string& strCol2, int nRow, int nEntireCol )
	{
		string strR1, strR2;
		//------ Folger 07/27/07 BROWSE_ROWS_IN_PLOT_RANGE
		if (!strTmp.IsEmpty())
		{
			if(okutil_parse_complete_range_string(strTmp, &strBook, &strSheet, &strObj))
		 	{
		 		okutil_parse_range_string(strObj, &strCol1, &strR1, &strCol2, &strR2);
		 	}
		}
		//------ End BROWSE_ROWS_IN_PLOT_RANGE
		if(nEntireCol )
		{
			okutil_create_range_string(&strRows, strCol1, NULL, strCol2, NULL);
			okutil_create_complete_range_string_obj(&strRange, strBook, strSheet, strRows);
			strRows = STR_ENTIRE_COLUMN;			
		}
		else
		{				
			okutil_create_complete_range_string_col_row(&strRange, strBook, strSheet, strCol1, nR1, strCol2, nR2);
			strRows.Format("[%d:%d]", nR1, nR2);
		}
		
		//------ Folger 12/12/07 FIX_BUGS_OF_RANGE_BROWSER_ROW_SELECTION_DIALOG
		vector<string> vsRanges;
		GetColValues(COL_RANGE + GetColOffset(), vsRanges, GetRowOffset());
		vsRanges.RemoveAt(nRow - GetRowOffset());
		if (FindValues(vsRanges, strRange))
		{
			MessageBox(GetDlgSafeHwnd(), _L("A same range already exists. Please specify again."), NULL, MB_OK);
			return false;
		}
		//------
		return true;
	}
	bool	getRangeStrings( string& strRange, string& strRows, string& strBook, string& strSheet, string& strObj, string& strR1,string& strCol1, string& strR2, string& strCol2 ,int& nR1, int& nR2, bool& bAuto )
	{
	 	bool bOK;
	 	BOOL bR1Auto = false, bR2Auto = false;
	 	
	 	if(okutil_parse_complete_range_string(strRange, &strBook, &strSheet, &strObj))
	 	{
	 		if(okutil_parse_range_string(strObj, &strCol1, &strR1, &strCol2, &strR2))
	 		{	//------ Folger 07/30/07 IMPROVE_RESOLVE_SOURCE_RANGE_STRING_FROM_DATAPLOT
	 			bOK = true;
	 			//------ Folger 07/30/07 IMPROVE_RESOLVE_SOURCE_RANGE_STRING_FROM_DATAPLOT
	 			if (!strR1.IsEmpty() && !strR2.IsEmpty())
	 			{
	 				strRows = "[" + strR1 + ":" + strR2 + "]";
	 				okutil_parse_row_range(strRows, &nR1, &bR1Auto, &nR2, &bR2Auto);
	 				strR1.Format("%d", nR1 + 1);
	 				strR2.Format("%d", nR2 + 1);
	 			}
	 		}
	 		//------ End IMPROVE_RESOLVE_SOURCE_RANGE_STRING_FROM_DATAPLOT
	 	}
	 	if(!bOK || strCol1.IsEmpty())
	 		return false;
	 	bAuto = bR1Auto && bR2Auto;
	 	return true;
	}
	///end Sophy CLEAN_CODE_PBLIST_CONTROL
};

class MatObjRangeList : public PBRangeListBase
{
public:	
	MatObjRangeList()
	{
	}
	void Init(int nID, WndContainer& dlg)
	{
		GridListControl::Init(nID, dlg);
		SetAllowSelection(true);	///If false , support single selete; else multi seletion
		SetSelection( flexSelectionListBox );
		SetEditable(flexEDKbd);//flexEDKbdMouse
		SetupRowsCols(1, 1, -1, 2);
		SetColHeading(COL_RANGE, _L("Range"));
		ResizeCols();
		SetReady();
	}
	bool AddRow(int nRow, LPCSTR lpcszData)
	{
		SetRows(nRow - GetRowOffset() + 1);
		string strData = lpcszData;
		SetCell(nRow, COL_RANGE + GetColOffset(), strData);
		return true;
	}
};
//------ Folger 07/30/07 IMPROVE_RESOLVE_SOURCE_RANGE_STRING_FROM_DATAPLOT
////-------Folger 07/24/07 CLEAN_UP_DATAPLOT_RANGE_STRING_CODE
//static int _get_index_from_plot_range_string(string strPlotRange)
//{
	//int nIndex = strPlotRange.Find('[');
	//if (nIndex >= 0)
		//strPlotRange.Delete(nIndex, strPlotRange.GetLength() - nIndex);
	//if ((nIndex = strPlotRange.Find('"')) >= 0)
		//strPlotRange.Delete(nIndex, strPlotRange.GetLength() - nIndex);
	//nIndex = atoi(strPlotRange);
	//if (nIndex <= 0)
	//{
		//nIndex = strPlotRange.Find('(');
		//strPlotRange.Delete(0, nIndex + 1);
		//strPlotRange.TrimRight(')');
		//nIndex = atoi(strPlotRange);
	//}
	//return nIndex;
//}
////-------End CLEAN_UP_DATAPLOT_RANGE_STRING_CODE
static int _parse_col_row_from_plot_range_string(LPCSTR strPlotRange, string &strCol, string& strR1, string& strR2)
{
	okutil_parse_range_string(strPlotRange, &strCol, &strR1, NULL, &strR2);
	//if (nIndex >= 0)
		//strPlotRange.Delete(nIndex, strPlotRange.GetLength() - nIndex);
	int nIndex = atoi(strCol);
	if (nIndex <= 0)
	{
		nIndex = strCol.Find('(');
		strCol.Delete(0, nIndex + 1);
		strCol.TrimRight(')');
		nIndex = atoi(strCol);
	}
	return nIndex;
}
//------ End IMPROVE_RESOLVE_SOURCE_RANGE_STRING_FROM_DATAPLOT
#endif	//__PB_RANGE_LIST_H__