/*------------------------------------------------------------------------------*
 * File Name: WksColLabels.c												*
 * Creation: 																	*
 * Purpose: 																	*
 * Copyright (c) Originlab Corp.	2005, 2006, 2007, 2008, 2009, 2010			*
 * All Rights Reserved															*
 * 																				*
 * Modification Log:															*
 * Jasmine 01/23/07 SUPPORT_DELETE_UDL											*
 * Folger 04/17/07 ADD_FIND_BUILTIN_LABEL										*
 * Folger 04/18/07 ADD_LABEL_HEIGHT												*
 * Folger 04/23/07 SHOW_MSG_WHEN_HEIGHT_INVALID									*
 * Folger 06/14/07 MOVE_FUNCTION_BODY_FORM_H_TO_C								*
 *	CPY 7/25/07 HEADER_ROWS_SHOULD_BE_COL_LABEL_ROWS							*
 * Folger 11/07/07 LOCALIZE_BUILD_IN_LABELS										*
 * Folger 11/09/07 LOCALIZE_BUILD_IN_LABLES										*
 *	Folger 07/31/08 ADD_F1_HELP													*
 *	Kenny 03/12/2009 FIX_BUGS_IN_FIND_BUILTIN_LABEL								*
 * Kenny 03/12/2009 ADD_FUNC_GET_BUILTIN_LABEL_NAME								*
 * Kenny 03/12/2009 GET_LABELS_USING_WRAPPER_CLASS_METHOD						*
 *	Folger 03/25/09 CLEAN_UP_CODES_ABOUT_GET_ALL_SHWON_PARAMETER_NAMES_AND_VALUES
 *	Kyle 04/03/2009 QA80-13385 GET_ALL_LABELS_SHOWN								*
 *	Folger 04/16/09 INCORRECT_WAY_TO_GET_COL_LABEL_VALUES						*
 *  Iris 6/23/2009 QA80-13756-P1 IMPROVE_ERROR_CHECK_FOR_USER_DEFINE_LABEL_NAME	*
 *	Kenny 08/27/2009 QA81-14182 NEW_XF_PLOTTING_GROUPS_OF_COLUMNS				*
 *	Folger 09/04/09 GET_WKS_SHOWN_LABELS_SUPPORT_SKIP_SPECIFIC_TYPES			*
 *	Folger 09/02/09 BATCH_PROCESS_APPEND_LABEL_ROWS_SKIP_EMPTY					*
 *	Kenny 09/27/2009 QA81-14241 INSERT_PARAM_NEED_CORRECT_INDICES_AND_CENTRALIZE_CODES*
 *	Folger 11/06/09 QA81-14609 XF_SUPPORT_LABEL_INDENTIFIER_FROM_LT				*
 *	Folger 11/06/09 QA81-14603 PAMULTIY_SUPPORT_INSERT_DATA_INDENTIFIER_IN_SUMMARY_SHEET
 *	Folger 12/11/09 QA81-14733 PA_MULTIY_SUPPORT_APPEND_FIT_STATS_RESULTS		*
 *	Folger 04/12/10 QA81-14157-P4 WKS_UNSTACK_COLUMNS_FAILED_TO_PICK_UP_PARAMETERS_LABEL_2_TO_10
 *	Folger 05/05/10 ORG-88 BATCH_PROCESS_SUPPORT_DATASET_IDENTIFIER				*
 *	Folger 07/20/10 ORG-502-P4 COL_HEADER_AS_PARAMETER_FAILED_TO_SHOW_IN_DATA_INFO
 *------------------------------------------------------------------------------*/
 
#include <Origin.h>
#include "DialogEx.h"
#include "TreeEditControl.h"
#include "WksColLabels.h"

//----- CPY 7/25/07 HEADER_ROWS_SHOULD_BE_COL_LABEL_ROWS
//#define STR_DLG_NAME		"Header Row Labels"	///Jasmine 07/25/07 WKS_HEADER_LABEL_MODIFICATION
#define STR_DLG_NAME	_L("Column Label Rows")
//----
#define ENABLE_DELETE_UDL	///Jasmine 01/23/07 SUPPORT_DELETE_UDL	

enum{
	LABEL_MENU_ADD, 
#ifdef ENABLE_DELETE_UDL
	LABEL_MENU_DELETE,
#endif// ENABLE_DELETE_UDL	

	LABEL_MENU_LAST_ITEM
};

enum{ 
	LABEL_TYPE = 1,
	LABEL_NAME,
	LABEL_SHOW,
	LABEL_HEIGHT,		///Folger 04/18/07 ADD_LABEL_HEIGHT
	LABEL_LAST
};

class LabelMenu : public Menu
{
public:
	LabelMenu(bool bDelete = true)
	{
		m_nChoice = -1;
				
		Add(_L("Add User-Defined Parameter"), OnMenuItem, MF_STRING);
#ifdef ENABLE_DELETE_UDL
		Add(_L("Delete"), OnMenuItem, MF_STRING | (bDelete? MF_ENABLED : MF_DISABLED | MF_GRAYED))
#endif//ENABLE_DELETE_UDL
	}
	void OnMenuItem(UINT nPos)
	{
		m_nChoice = nPos;
	}	
	bool GetCommand(int& nChoice)
	{
		if(m_nChoice >= LABEL_MENU_ADD && m_nChoice < LABEL_MENU_LAST_ITEM)
		{
			nChoice = m_nChoice;
			return true;
		}
		return false;
	}
	void EmptySepFunc(uint nCmd)
	{
	}
private:
	int	m_nChoice;
};

class ColLabelGrid : public TreeEditControl
{
public:
	ColLabelGrid()
	{
	}
	void InitList(const TreeNode& tr, int nID, WndContainer& dlg)
	{
		if(!tr.IsValid())
			return;
		TreeEditControl::Init(nID, false, true, NULL, dlg);
		SetReady(false);
		SetExtendLastCol(true);	
		SetAllowSelection(false);	
		//SetExplorerBar(flexExSortShow);	//if move rows, don't set this	
		SetupRowsCols(1, 1,  -1, LABEL_LAST);
		SetColDataType(LABEL_TYPE, flexDTString);
		SetColDataType(LABEL_SHOW, flexDTBoolean);
		SetColDataType(LABEL_HEIGHT, flexDTDouble);		///Folger 04/18/07 ADD_LABEL_HEIGHT
		SetTreeNodeMoveRowsAttrib(tr);
		UpdateGrid(tr);
		SetRowHeaderValues();
		///Folger 04/18/07 ADD_LABEL_HEIGHT
		//vector<byte> vbHideCols = {0, 1, 0, 0};//later
		vector<byte> vbHideCols = {0, 1, 0, 0, 0};
		///End ADD_LABEL_HEIGHT
		SetHiddenCols(vbHideCols);
		ResizeCols(0.1, 3.0, 0);
		SetFixedColAlignment(-1, flexAlignCenterCenter);
		SetReady(true);
	}
	void SetShow(vector<int> vnShowTypes)
	{
		int nFixCol = GetColOffset(), nFixRow = GetRowOffset();
		vector<string> vsType, vsVals;
		GetColValues(LABEL_TYPE, vsType, nFixRow);
		for(int ii = vnShowTypes.GetSize() - 1; ii >=0; ii--)
		{
			int nRow = FindRow((string)vnShowTypes[ii], LABEL_TYPE);
			if(nFixRow > nRow)
				continue;
			GetRowValues(nRow, vsVals, nFixCol);
			DeleteRow(nRow);
			SelRow(nFixRow);
			InsertRow();
			if(LABEL_SHOW <= vsVals.GetSize())//avoid exceeding index
				vsVals[LABEL_SHOW - 1] = "1";
			SetRowValues(nFixRow - 1, vsVals);
		}
		SetRowHeaderValues();
	}
	void Reset()
	{
		int nFixCol = GetColOffset(), nFixRow = GetRowOffset(), nRows = GetRows(); 
		vector<string> vsVals;
		vector vnTypes;		
		vector<uint> vnIndeces;
		GetColValues(LABEL_TYPE, vsVals, nFixRow);
		convert_str_vector_to_num_vector(vsVals, vnTypes);
		vnTypes.Sort(SORT_ASCENDING, TRUE, vnIndeces);
		SetReady(false);
		for(int ii = 0; ii < vnIndeces.GetSize(); ii++)
		{
			GetRowValues(vnIndeces[ii] + nFixRow, vsVals, nFixCol);
			SetRowValues(nRows + ii - nFixRow, vsVals, 0, true);
		}
		for(ii = nFixRow; ii < nRows; ii++)
			DeleteRow(nFixRow);
		SetReady(true);
	}
	int GetLabelType(int nRow)
	{
		return atoi(GetCell(nRow, LABEL_TYPE));
	}
	///Folger 04/18/07 ADD_LABEL_HEIGHT
	//void GetShowLabels(vector<int>& vnTypes)
	void GetShowLabels(vector<int>& vnTypes, vector<double> &vnHeight)
	///End ADD_LABEL_HEIGHT
	{
		vnTypes.RemoveAll();
		for(int ii = GetRowOffset(); ii < GetRows(); ii++)
		{
			int nShow = GetCheck(ii, LABEL_SHOW);
			if(nShow)
			{
				vnTypes.Add(atoi(GetCell(ii, LABEL_TYPE)));
				vnHeight.Add(atof(GetCell(ii, LABEL_HEIGHT)));		///Folger 04/18/07 ADD_LABEL_HEIGHT
			}
		}
	}
	bool AddUDL(int nType, LPCSTR lpcszName = NULL, bool bShow = true)//type, name, show...
	{
		vector<string> vsVals;
		vsVals.Add((string)nType);
		vsVals.Add(lpcszName);
		vsVals.Add(bShow? "1" : "0");
		vsVals.Add("1");		///Folger 04/18/07 ADD_LABEL_HEIGHT
		SetRowValues(GetRows() - GetRowOffset(), vsVals, 0, true);
		return true;
	}
#ifdef ENABLE_DELETE_UDL
	bool DeleteLabel(int& nType, string& strName)
	{
		int nRow = GetSelectedRow();
		nType = atoi(GetCell(nRow, LABEL_TYPE));
		strName = GetCell(nRow, LABEL_NAME);
		DeleteRow(nRow);
		return true;
	}
	void ResetUDLsType(const vector<string> vsUDLs)
	{
		int nCount = vsUDLs.GetSize();
		for(int ii = 0; ii < nCount; ii++)
		{
			int nRow = FindRow(vsUDLs[ii], LABEL_NAME);
			SetCell(nRow, LABEL_TYPE, RCLT_UDL + ii);
		}
	}
	///Folger 04/18/07 ADD_LABEL_HEIGHT
	bool isLabelShow(int nRow)
	{
		return GetCheck(nRow, LABEL_SHOW);
	}
	///End ADD_LABEL_HEIGHT
#endif//ENABLE_DELETE_UDL
};

class WksLabels : public ResizeDialog
{
public:
	WksLabels(Worksheet& wks) : ResizeDialog(IDD_RESIZE_GRID, "ODlg8")
	{
		m_wks = wks;
	}
	DWORD	DoModalEx(HWND hParent)
	{
		InitMsgMap();
		int nRet = DoModal(hParent);
		if(IDOK == nRet)
		{
			return 1;
		}
		return 0;
	}
protected:	
EVENTS_BEGIN
	ON_INIT(OnInitDialog)
	ON_DESTROY(OnDestroy)
	ON_SIZE(OnDlgResize)	
	ON_READY(OnReady)
	ON_SYSCOMMAND(OnSystemCommand)
	ON_OK(OnClickOK)
	ON_BN_CLICKED(IDC_RG_BUTTON1, OnReset)
	ON_BN_CLICKED(IDC_RG_BUTTON2, OnApply)
	ON_CONTEXTMENU(OnShowMenu)	
	ON_GRID_BEFORE_EDIT(IDC_GRID, OnBeforeEdit)
	ON_GRID_AFTER_EDIT(IDC_GRID, OnAfterEdit)
	ON_GRID_AFTER_MOVE_ROWS(IDC_GRID, OnAfterMoveRows)
	
	ON_HELPINFO(OnHelp)		//------ Folger 07/31/08 ADD_F1_HELP
EVENTS_END
	
protected:
	BOOL OnInitDialog()
	{
		ResizeDialog::OnInitDialog(0, STR_DLG_NAME);		
		Text = STR_DLG_NAME;
		GetItem(IDC_TEXT).Visible = true;
		GetItem(IDC_RG_BUTTON1).Text = _L("Reset Order");
		GetItem(IDC_RG_BUTTON1).Visible = true;
		m_btnApply = GetItem(IDC_RG_BUTTON2);
		m_btnApply.Text = _L("Apply");
		m_btnApply.Visible = true;
		m_btnApply.Enable = false;
		GetItem(IDOK).Visible = true;
		InitGrid();
		return TRUE;
	}
	BOOL OnDestroy(void)
	{
		return ResizeDialog::OnDestroy();
	}
	BOOL OnDlgResize(int nType, int cx, int cy)
	{
		vector<uint> vnButtons = {IDC_RG_BUTTON1, IDC_RG_BUTTON2, IDOK, IDCANCEL, 0};
		ArrangeMainItemAndControls(vnButtons, IDC_GRID, NULL, true);
		return TRUE;
	}
	BOOL OnReady()
	{
		vector<int> vnShowTypes;
		Grid grid;   
		if(grid.Attach(m_wks))
			grid.GetShowLabels(vnShowTypes);
		m_grid.SetShow(vnShowTypes);
		return TRUE;
	}
	BOOL OnClickOK()
	{
		if(m_btnApply.Enable)
		{
			Control ctrl;
			OnApply(ctrl);
		}
		return TRUE;
	}
	bool OnReset(Control ctrl)
	{
		m_grid.Reset();
		m_btnApply.Enable = true;
		return true;		
	}
	bool OnApply(Control ctrl)
	{
		Grid grid; 
		if(!grid.Attach(m_wks))
			return false;
		///Jasmine 01/23/07 SUPPORT_DELETE_UDL
		_delete_user_parameters(m_vnDelUDLs);
		//set user defined labels
		grid.SetUserDefinedLabelNames(m_vsUDLs);
		m_grid.ResetUDLsType(m_vsUDLs);//after SetUserDefinedLabelNames, types will change
		///End SUPPORT_DELETE_UDL
		//reorder and show/hide
		vector<int> vnType;
		vector<double> vnHeight;		///Folger 04/18/07 ADD_LABEL_HEIGHT
		///Folger 04/18/07 ADD_LABEL_HEIGHT
		//m_grid.GetShowLabels(vnType);
		m_grid.GetShowLabels(vnType, vnHeight);
		///End ADD_LABEL_HEIGHT
		bool bRet = grid.SetShowLabels(vnType);
		///Folger 04/18/07 ADD_LABEL_HEIGHT
		int nSize = vnType.GetSize();
		for (int ii=0; ii<nSize; ii++)
		{
			wks_set_col_label_heights(m_wks, vnType[ii], vnHeight[ii] * 100);
		}
		///End ADD_LABEL_HEIGHT
		m_wks.GetPage().Refresh();
		m_btnApply.Enable = false;
		return true;		
	}
	BOOL OnShowMenu(UINT nResIDCtrl, int nx, int ny)
	{
		if(IDC_GRID != nResIDCtrl)
			return FALSE;
		int nClickRow, nClickCol;
		m_grid.GetMouseCell(nClickRow, nClickCol);
		if(0 <= nClickRow)
			m_grid.SelRow(nClickRow);
		bool bDelete = isEditable(m_grid.GetLabelType(nClickRow));
		int nCmd;		
		LabelMenu 	myMenu(bDelete);
		myMenu.TrackPopupMenu(0,  nx, ny, GetSafeHwnd());
		if(myMenu.GetCommand(nCmd))
		{
			switch(nCmd)
			{
			case LABEL_MENU_ADD: 
				AddUDL();
				break;
			#ifdef ENABLE_DELETE_UDL
			case LABEL_MENU_DELETE: 
				DeleteLabel();
				break;
			#endif//ENABLE_DELETE_UDL
			default:
				return FALSE;
			}		
			return TRUE;
		}
		return FALSE;
	}
	void OnBeforeEdit(Control flxControl, long nRow, long nCol, BOOL* pCancel)
	{
		bool	bEditable = true;
		if(nCol == LABEL_NAME)
		{
			bEditable = isEditable(m_grid.GetLabelType(nRow));
			m_strOldValue = m_grid.GetCell(nRow, nCol);
		}
		///Folger 04/18/07 ADD_LABEL_HEIGHT
		else if (nCol == LABEL_HEIGHT)
		{
			bEditable = m_grid.isLabelShow(nRow);
			m_strOldHeight = m_grid.GetCell(nRow, nCol);		///Folger 04/23/07 SHOW_MSG_WHEN_HEIGHT_INVALID
		}
		///End ADD_LABEL_HEIGHT
		if(!bEditable)
			*pCancel = true;
		return;
		
	}
	void OnAfterEdit(Control flxControl, int nRow, int nCol)
	{
		m_btnApply.Enable = true;		
		///Folger 04/18/07 ADD_LABEL_HEIGHT
		if (nCol == LABEL_SHOW)
		{
			if (m_grid.GetCheck(nRow, LABEL_SHOW) && m_grid.GetCell(nRow, LABEL_HEIGHT) == "0")
			{
				m_grid.SetCell(nRow, LABEL_HEIGHT, 1);
			}
		}
		///Folger 04/23/07 SHOW_MSG_WHEN_HEIGHT_INVALID
		if (nCol == LABEL_HEIGHT)
		{
			string str = m_grid.GetCell(nRow, nCol);
			if (str[0] == '-' || atof(str) == NANUM)
			{
				MessageBox(GetSafeHwnd(), _L("The Height value is invalid."), NULL, MB_OK);
				m_grid.SetCell(nRow, nCol, m_strOldHeight);
				str = m_strOldHeight;
			}
			m_btnApply.Enable = str.Compare(m_strOldHeight);
		}
		///End SHOW_MSG_WHEN_HEIGHT_INVALID
		///End ADD_LABEL_HEIGHT
		if(nCol != LABEL_NAME) 
			return;
		string strNewValue = m_grid.GetCell(nRow, nCol);
		//---- CPY 4/18/07 FIND_BUILT_IN_LABEL_NEED_MORE_CLEAN_UP
		//vector<string> vsBuiltIn = {"Long Name", "Units", "Comments", "Sampling Interval", "Sparklines" };
		//----
		int nIndex = m_vsUDLs.Find(m_strOldValue), nRepeat = m_vsUDLs.Find(strNewValue);
		bool bOK = true;
		if(strNewValue.IsEmpty())
			bOK = false;
		if(nRepeat > -1 && nRepeat != nIndex)
		{
			bOK = false;
			MessageBox(GetSafeHwnd(), _L("The name you specified already exists. Please specify a different label name."), NULL, MB_OK);
		}
		///Folger 04/17/07 ADD_FIND_BUILTIN_LABEL
		//if(-1 < vsBuiltIn.Find(strNewValue) || 0 == strNewValue.Find("Parameters"))
		if (find_builtin_label(strNewValue) != -1)
		///End ADD_FIND_BUILTIN_LABEL
		{
			bOK = false;
			MessageBox(GetSafeHwnd(), _L("Cannot rename as a built-in label name. Please specify a different label name."), NULL, MB_OK);
		}
		if(!bOK)
		{
			strNewValue = m_strOldValue;
			m_grid.SetCell(nRow, nCol, strNewValue);
		}
		else
			m_vsUDLs[nIndex] = strNewValue;
		m_btnApply.Enable = strNewValue.Compare(m_strOldValue);
	}
	void OnAfterMoveRows(Control ctrl, long nRow, long *pnPosition)
	{
		m_btnApply.Enable = true;
	}
	
	//------ Folger 07/31/08 ADD_F1_HELP
	BOOL 	OnHelp(int &nHelpID, int nIdCtrlFocus)
	{
		nHelpID = IDD_WKS_COL_LABELS;
		return true;
	}
	//------ End ADD_F1_HELP
	
	bool AddUDL()
	{
		int nPostfix = get_list_enum_number(m_vsUDLs, STR_UDL_PREFIX);
		string strName = STR_UDL_PREFIX;
		if(nPostfix)
			strName += nPostfix;
		//m_nUDLs: indicate adding sequence
		m_grid.AddUDL(RCLT_UDL + (m_nUDLs++), strName, true);//type, name, show...
		m_vsUDLs.Add(strName);
		m_btnApply.Enable = true;
		return true;
	}
	#ifdef ENABLE_DELETE_UDL
	bool DeleteLabel()
	{
		int	nType;
		string strName;
		m_grid.DeleteLabel(nType, strName);
		m_vnDelUDLs.Add(nType);
		int nIndex = m_vsUDLs.Find(strName);
		if(nIndex > -1)
			m_vsUDLs.RemoveAt(nIndex);
		m_btnApply.Enable = true;
		return true;
	}
	#endif//ENABLE_DELETE_UDL
	void InitGrid()
	{
		ConstructTree();
		m_grid.InitList(m_trLabels, IDC_GRID, *this);
	}
	void ConstructTree()
	{
		Grid grid;   
		if(!grid.Attach(m_wks))
			return;
		vector<uint> vnIndeces;
		//built-in labels
		//------ Folger 11/09/07 LOCALIZE_BUILD_IN_LABLES
		//vector<string> vsNames = {"Long Name", "Units", "Comments", "Parameters"};//, "Sampling Interval", "Sparkline" };
		///Kenny 03/12/2009 GET_LABELS_USING_WRAPPER_CLASS_METHOD
		//vector<string> vsNames;
		//vsNames.Add(GetLocalized(E_STR_LONGNAME));
		//vsNames.Add(GetLocalized(E_STR_UNITS));
		//vsNames.Add(GetLocalized(E_STR_COMMENTS));
		//vsNames.Add(GetLocalized(E_STR_PARAMETERS));
		////------ End LOCALIZE_BUILD_IN_LABLES
		//vector<int> vnTypes = { RCLT_LONG_NAME, RCLT_UNIT, RCLT_COMMENT, 
								//RCLT_PARAM};//, RCLT_SAMPLE_RATE, RCLT_SPARKLINE };
		//for(int ii = 2; ii <= PARAMS_MAX_NUM; ii++)
		//{
		////------ Folger 11/09/07 LOCALIZE_BUILD_IN_LABLES
		////vsNames.Add("Parameters " + ii);
		//vsNames.Add(GetLocalized(E_STR_PARAMETERS) + ' ' + ii);
		////------ End LOCALIZE_BUILD_IN_LABLES
		//vnTypes.Add(RCLT_PARAM + ii - 1);
		//}
		////------ Folger 11/09/07 LOCALIZE_BUILD_IN_LABLES
		////vsNames.Add("Sampling Interval"); vsNames.Add("Sparklines");
		//vsNames.Add(GetLocalized(E_STR_SAMPLING_INTERVAL));
		//vsNames.Add(GetLocalized(E_STR_SPARKLINES));
		////------ End LOCALIZE_BUILD_IN_LABLES
		//vnTypes.Add(RCLT_SAMPLE_RATE); vnTypes.Add(RCLT_SPARKLINE); 
		vector<string>* pvsNames = NULL;
		vector<int>* pvnTypes = NULL;
		WksBuiltinLabelsHolder& holder = _get_wks_builtin_labels_holder();
		holder.GetAllLabelRef(pvsNames, pvnTypes);
		ASSERT(pvsNames && pvnTypes);
		if (!pvsNames || !pvnTypes)
		{
			out_str("Failed in ConstructTree!");
			return;
		}
		vector<string>& vsNames = *pvsNames;
		vector<int>& vnTypes = *pvnTypes;
		int ii;
		///End GET_LABELS_USING_WRAPPER_CLASS_METHOD
		m_trLabels.SetAttribute(STR_ATTRIB_EDITCOL_ALIGN, "1|2|0");		///Folger 04/18/07 ADD_LABEL_HEIGHT
		for(ii = 0; ii < vsNames.GetSize(); ii++)
		{
			TreeNode trLabel = m_trLabels.AddNode("Label"+(ii+1));
			trLabel.AddTextNode((string)vnTypes[ii], _L("LabelType"));
			trLabel.AddTextNode(vsNames[ii], _L("Labels"));
			trLabel.AddNumericNode(0, _L("Show"), TRGP_CHECK);
			trLabel.AddNumericNode((double)(wks_get_col_label_heights(m_wks, vnTypes[ii])) / 100, _L("Height"), TRGP_DOUBLE);	///Folger 04/18/07 ADD_LABEL_HEIGHT
		}
		//user defined labels
		grid.GetUserDefinedLabelNames(m_vsUDLs);
		m_nUDLs = m_vsUDLs.GetSize();
		for(ii = 0; ii < m_nUDLs; ii++)	
		{
			TreeNode trUDL = m_trLabels.AddNode("UDL"+(ii+1));
			trUDL.AddTextNode((string)(RCLT_UDL+ii), _L("LabelType"));
			trUDL.AddTextNode(m_vsUDLs[ii], _L("Labels"));
			trUDL.AddNumericNode(0, _L("Show"), TRGP_CHECK);
			trUDL.AddNumericNode((double)(wks_get_col_label_heights(m_wks, RCLT_UDL + ii)) / 100, _L("Height"), TRGP_DOUBLE);	///Folger 04/18/07 ADD_LABEL_HEIGHT
		}
	}
private:
	bool isEditable(int nType)
	{
		return (nType >= RCLT_UDL && nType <= RCLT_MAX_TYPE);
	}
private:
	Button			m_btnApply;
	ColLabelGrid	m_grid;
	Tree			m_trLabels;
	Worksheet	 	m_wks;
	vector<int>		m_vnDelUDLs;
	vector<string>	m_vsUDLs;
	int 			m_nUDLs;	
	string			m_strOldValue;
	string			m_strOldHeight;				///Folger 04/23/07 SHOW_MSG_WHEN_HEIGHT_INVALID
};
///Jasmine 01/23/07 SUPPORT_DELETE_UDL
#define STR_SEP 			"\r\n##" 
static void _delete_user_parameters(const vector<int>& vnDelTypes)
{
	if(!vnDelTypes.GetSize())
		return;
	vnDelTypes.Sort();
	
	Worksheet wks = Project.ActiveLayer();
	Grid grid;
	if(!grid.Attach(wks))
		return;
	vector<string> vsNames, vsValues, vsNewNames;
	grid.GetUserDefinedLabelNames(vsNames);
	int nCount = vsNames.GetSize();
	for(int ii = vnDelTypes.GetSize() - 1; ii >= 0; ii--)
	{//remove nonexistent type
		if(nCount <= vnDelTypes[ii] - RCLT_UDL)
			vnDelTypes.RemoveAt(ii);
	}	
	//get parameter values
	foreach(Column col in wks.Columns)
	{
		vector<string> vsValuesTemp;
		get_user_parameters(col, vsNames, vsValuesTemp, true);
		string strValue = str_combine(vsValuesTemp, STR_SEP);
		vsValues.Add(strValue);		
	}
	vsNewNames = vsNames;
	
	vector<int> vnType, vnMoveType, vR1;
	grid.GetShowLabels(vnType);
	vnMoveType = vnType;
	vector<uint> vecIndex;
	for(ii = vnDelTypes.GetSize() - 1; ii >= 0; ii--)
	{
		int nDelType = vnDelTypes[ii], nUpType = RCLT_UDL + nCount - 1 - ii;
		if(0 < vnMoveType.Find(vecIndex, nUpType))
			vnMoveType.RemoveAt(vecIndex[0]);
		vnMoveType.InsertAt(0, nUpType);
		if(0 < vnType.Find(vecIndex, nDelType))
			vnType.RemoveAt(vecIndex[0]);
		vsNewNames.RemoveAt(nDelType - RCLT_UDL);
		vR1.Add(ii);
	}
	grid.SetShowLabels(vnMoveType);//move the last UDLs to top to delete
	//delete row from wks
	if(vR1.GetSize())
	{
		vR1.Sort();
		BOOL flag = grid.SetSelection(vR1, NULL, NULL, NULL, false);
		if(grid.CanDelete())
			grid.Delete(true);	
	}
	//delete UDL
	grid.SetUserDefinedLabelNames(vsNewNames);	
	//set parameter values
	foreach(Column cc in wks.Columns)
	{
		vector<string> vsValuesTemp;
		str_separate(vsValues[0], STR_SEP, vsValuesTemp);
		for(ii = vnDelTypes.GetSize() - 1; ii >= 0; ii--)
		{
			int nDelType = vnDelTypes[ii];
			vsValuesTemp.RemoveAt(nDelType - RCLT_UDL);
		}
		int nCount = set_user_parameters(cc, vsNewNames, vsValuesTemp);
		vsValues.RemoveAt(0);		
	}
	//set show label and set show order
	for(ii = 0; ii < vnType.GetSize(); ii++)
	{
		int nType = vnType[ii], nNewType;
		if(RCLT_UDL <= nType)
		{
			nNewType = vsNewNames.Find(vsNames[nType - RCLT_UDL]);
			if(-1 < nNewType)
				vnType[ii] = nNewType + RCLT_UDL;
		}
	}
	bool bRet = grid.SetShowLabels(vnType);
	wks.GetPage().Refresh();
}
///End SUPPORT_DELETE_UDL	
int WksColLabels(int nMsg=0, DWORD dwCntrl=0, LPVOID lpData = NULL)
{
	HWND hParent = lpData;
	if(NULL == hParent)
		hParent = GetWindow();
	Worksheet wks = Project.ActiveLayer();
	if(!wks)
		return -1;
	WksLabels myDlg(wks);
	int nRet = myDlg.DoModalEx(hParent);
	if(nRet == IDCANCEL)
		return 0;
	
	return 1;
}

//-------------WksColLabels.h--------------//
bool get_wks_UDL_showtype(const Worksheet &wks, vector<int> &vnTypes, vector<string> &vsUDLs)
{
	Grid grid;
	if (!grid.Attach(wks))
	{
		return false;
	}
	if (vsUDLs != NULL)
		grid.GetUserDefinedLabelNames(vsUDLs);	
	if (vnTypes != NULL)
		grid.GetShowLabels(vnTypes);
	return true;
}

bool set_wks_UDL_showtype(Worksheet &wks, const vector<int> &vnTypes, const vector<string> &vsUDLs)
{
	Grid grid;
	if (!grid.Attach(wks))
	{
		return false;
	}
	if (vsUDLs != NULL)
		grid.SetUserDefinedLabelNames(vsUDLs);
	if (vnTypes != NULL)
		grid.SetShowLabels(vnTypes);
	return true;
}
///Folger 06/14/07 MOVE_FUNCTION_BODY_FORM_H_TO_C
//---- CPY 4/18/07 FIND_BUILT_IN_LABEL_NEED_MORE_CLEAN_UP
//moved find_builtin_label here from page_utils as this function seems not of any general purpose and will need to be cleaned up
//1. change to _find_builtin_label and make static
//2. still need to think about why it is done this way, how to resolve localization
///Folger 04/17/07 FIND_BUILTIN_LABEL 
int find_builtin_label(string strName)
{
	//------ Folger 11/07/07 LOCALIZE_BUILD_IN_LABELS
	//vector<string> strBuiltin = {"LongName", "Units", "Comments", "Parameters", "Parameters2",
								 //"Parameters3", "Parameters4", "Parameters5", "Parameters6",
								 //"Parameters7", "Parameters8", "Parameters9", "Parameters10",
								 //"SamplingInterval", "Sparklines",
								 //"L", "U", "C", "P", "P2",
								 //"P3", "P4", "P5", "P6",
								 //"P7", "P8", "P9", "P10"};
	//strName.Remove(' ');
	//return strBuiltin.Find(strName) % BUILD_IN;
	
	///Kenny 03/12/2009 FIX_BUGS_IN_FIND_BUILTIN_LABEL
	//vector<string> strBuildinLetter = {"L", "U", "C", "P"};

	//int nIndex = strBuildinLetter.Find(strName);
	//if (nIndex >= 0)
		//return nIndex;
	//string strTmp1 = strName, strTmp2 = strName;
	//strTmp1.TrimLeft("P");
	//strTmp2.TrimLeft("p");
	//if (atoi(strTmp1) != 0 || atoi(strTmp2) != 0)
		//return 0;
	const string strBuiltinLetter = "LUCP";
	/// Iris 6/23/2009 QA80-13756-P1 IMPROVE_ERROR_CHECK_FOR_USER_DEFINE_LABEL_NAME		
	#ifdef IMPROVE_ERROR_CHECK_FOR_USER_DEFINE_LABEL_NAME
	string	strBuiltinLetterLower = strBuiltinLetter;
	strBuiltinLetterLower.MakeLower();
	#endif /// IMPROVE_ERROR_CHECK_FOR_USER_DEFINE_LABEL_NAME
	/// End IMPROVE_ERROR_CHECK_FOR_USER_DEFINE_LABEL_NAME		
	int iNameLen = strName.GetLength();
	if (iNameLen <= 0)
		return -1;
	if (1 == iNameLen)	// checks to see if it's in {"L", "U", "C", "P"}
	{
		#ifndef IMPROVE_ERROR_CHECK_FOR_USER_DEFINE_LABEL_NAME
		return strName.FindOneOf(strBuiltinLetter);
		#else	/// IMPROVE_ERROR_CHECK_FOR_USER_DEFINE_LABEL_NAME
		if ( strName.CompareNoCase("D") == 0 )
			return RCLT_UDL;
		return strName.FindOneOf(strBuiltinLetter) || strName.FindOneOf(strBuiltinLetterLower);
		#endif	/// IMPROVE_ERROR_CHECK_FOR_USER_DEFINE_LABEL_NAME
	}
	/// Iris 6/23/2009 QA80-13756-P1 IMPROVE_ERROR_CHECK_FOR_USER_DEFINE_LABEL_NAME		
	#ifndef IMPROVE_ERROR_CHECK_FOR_USER_DEFINE_LABEL_NAME
	else if (iNameLen <= 3)	// checks to see if it's "P2" <-> "P10"
	#else	/// IMPROVE_ERROR_CHECK_FOR_USER_DEFINE_LABEL_NAME
	else if (iNameLen <= 4)	// checks to see if it's "P2" <-> "P10", and "D0" <-> "D127"
	#ifndef /// IMPROVE_ERROR_CHECK_FOR_USER_DEFINE_LABEL_NAME
	{
		char ch1 = strName.GetAt(0);
		/// Iris 6/23/2009 QA80-13756-P1 IMPROVE_ERROR_CHECK_FOR_USER_DEFINE_LABEL_NAME		
		//if ('p' == ch1 || 'P' == ch1)
		#ifndef IMPROVE_ERROR_CHECK_FOR_USER_DEFINE_LABEL_NAME
		if ('p' == ch1 || 'P' == ch1)
		#else
		ch1 |= (1 << 5);		/// to lower
		if ('p' == ch1 || 'd' == ch1 )
		#endif
		///end IMPROVE_ERROR_CHECK_FOR_USER_DEFINE_LABEL_NAME
		{
			string strTmp = strName.Right(iNameLen-1);
			int iNum = atoi(strTmp);
			/// Iris 6/23/2009 QA80-13756-P1 IMPROVE_ERROR_CHECK_FOR_USER_DEFINE_LABEL_NAME
			//if (2 <= iNum && iNum <= PARAMS_MAX_NUM)
			#ifndef IMPROVE_ERROR_CHECK_FOR_USER_DEFINE_LABEL_NAME
			if (2 <= iNum && iNum <= PARAMS_MAX_NUM)
				return 0;
			#else
			// P0 and P1 will be treated same as P, so cannot allow too. For example try col(a)[P0]$="Param0" the rsult same as col(a)[P]
			if ( is_numeric(strTmp) )
			{
				int		nBase = 'p' == ch1 ? RCLT_PARAM : RCLT_UDL;
				int		nUpper = 'p' == ch1 ? PARAMS_MAX_NUM : UDL_MAX_NUM - 1;
				if ( 0 <= iNum && iNum <= nUpper )
					return nBase + ( 0 == iNum ? 0 : iNum - 1 );
			}
			#endif
			///end IMPROVE_ERROR_CHECK_FOR_USER_DEFINE_LABEL_NAME
		}
		return -1;
	}
	///End FIX_BUGS_IN_FIND_BUILTIN_LABEL
	
	vector<string> strBuildin(RCLT_SPARKLINE + 1);
	strBuildin[RCLT_LONG_NAME] = E_STR_LONGNAME;
	strBuildin[RCLT_UNIT] = E_STR_UNITS;
	strBuildin[RCLT_COMMENT] = E_STR_COMMENTS;
	///------ Folger 07/20/10 ORG-502-P4 COL_HEADER_AS_PARAMETER_FAILED_TO_SHOW_IN_DATA_INFO
	strBuildin[RCLT_PARAM] = E_STR_PARAMETERS;
	///------ End COL_HEADER_AS_PARAMETER_FAILED_TO_SHOW_IN_DATA_INFO
	strBuildin[RCLT_SAMPLE_RATE] = E_STR_SAMPLING_INTERVAL;
	strBuildin[RCLT_SPARKLINE] = E_STR_SPARKLINES;
	
	for (int ii=0; ii<strBuildin.GetSize(); ii++)
	{
		if (compare_string_localization(strName, strBuildin[ii], true))
			return ii;
	}
	///Kenny 03/12/2009 FIX_BUGS_IN_FIND_BUILTIN_LABEL
	//strTmp1 = strTmp2 = strName;
	//if (find_string_localization(strName, strBuildin[3]) == 0)	//Find "Parameters" at begin of strName
	//{
		//strTmp1.TrimLeft(strBuildin[3]);
		//strTmp2.TrimLeft(GetLocalized(strBuildin[3]));
		//if (atoi(strTmp1) != 0 || atoi(strTmp2) != 0)
			//return 0;
	//}
	const string strParametersPrefix = E_STR_PARAMETERS + ' ';
	if (find_string_localization(strName, strParametersPrefix) == 0)	//Find "Parameters" at begin of strName
	{
		string strTmp = strName.Right(iNameLen-strParametersPrefix.GetLength());
		int iNum = atoi(strTmp);
		if (2 <= iNum && iNum <= PARAMS_MAX_NUM)
			///------ Folger 04/12/10 QA81-14157-P4 WKS_UNSTACK_COLUMNS_FAILED_TO_PICK_UP_PARAMETERS_LABEL_2_TO_10
			//return 0;
			return RCLT_PARAM + iNum - 1;
			///------ End WKS_UNSTACK_COLUMNS_FAILED_TO_PICK_UP_PARAMETERS_LABEL_2_TO_10
	}
	///End FIX_BUGS_IN_FIND_BUILTIN_LABEL
		
	return -1
	//------ End LOCALIZE_BUILD_IN_LABELS
}
///End FIND_BUILTIN_LABEL

int find_UDL_label(const vector<string> &vsUDLs, string strName)
{
	int nSize = vsUDLs.GetSize();
	int nLength = strName.GetLength();
	int nFirst = -1;
	for (int ii=0; ii<nSize; ii++)
	{
		if (strName.CompareNoCase(vsUDLs[ii]) == 0)
		{
			return ii;
		}
		else if (nFirst == -1 && strName.CompareNoCase(vsUDLs[ii].Mid(0, nLength)) == 0)
		{
			nFirst = ii;
		}
	}
	return nFirst;
}

///Kenny 03/12/2009 ADD_FUNC_GET_BUILTIN_LABEL_NAME

class WksBuiltinLabelsHolder
{
private:
	WksBuiltinLabelsHolder();
	~WksBuiltinLabelsHolder();
	void	InitData();
public:
	// Kenny: By designed, user should only call the other public methods by GetInstance(), and there's only
	// one single instance of this class exist in the memory all the time.
	// This helps preventing creating the member data over and over when constructing the instances of this class 
	// but this is not supported by OC currently, so we have to use _get_wks_builtin_labels_holder() instead.
	
	//static WksBuiltinLabelsHolder& GetInstance();
	string	GetLabelName(int nType);
	int		GetLabelType(const string& strName);
	
	void	GetAllLabelRef(const vector<string>*& pvsNames, const vector<int>*& pvnTypes);
private:
	/*static */vector<string>	s_vsNames;
	/*static */vector<int>		s_vnTypes;
};

WksBuiltinLabelsHolder::WksBuiltinLabelsHolder()
{
	InitData();
}

WksBuiltinLabelsHolder::~WksBuiltinLabelsHolder()
{
	
}

void WksBuiltinLabelsHolder::InitData()
{	
	s_vsNames.Add(GetLocalized(E_STR_LONGNAME));
	s_vsNames.Add(GetLocalized(E_STR_UNITS));
	s_vsNames.Add(GetLocalized(E_STR_COMMENTS));
	s_vsNames.Add(GetLocalized(E_STR_PARAMETERS));

	s_vnTypes.Add(RCLT_LONG_NAME);
	s_vnTypes.Add(RCLT_UNIT);
	s_vnTypes.Add(RCLT_COMMENT);
	s_vnTypes.Add(RCLT_PARAM);
	
	for(int ii = 2; ii <= PARAMS_MAX_NUM; ++ii)
	{
		s_vsNames.Add(GetLocalized(E_STR_PARAMETERS) + ' ' + ii);
		s_vnTypes.Add(RCLT_PARAM + ii - 1);
	}
	
	s_vsNames.Add(GetLocalized(E_STR_SAMPLING_INTERVAL));
	s_vsNames.Add(GetLocalized(E_STR_SPARKLINES));
	
	s_vnTypes.Add(RCLT_SAMPLE_RATE);
	s_vnTypes.Add(RCLT_SPARKLINE); 
}

string WksBuiltinLabelsHolder::GetLabelName( int nType )
{
	if (RCLT_MAX_TYPE < nType)
		return NULL;
	
	vector<uint> vIndex;
	const int wBitwiseOption =  MATREPL_TEST_EQUAL;
	int nRet = s_vnTypes.Find( wBitwiseOption, nType, vIndex);
	if (nRet > 0 && vIndex.GetSize() > 0)
	{
		ASSERT(1 == nRet);
		int iIndex = vIndex[0];
		ASSERT(0 <= iIndex && iIndex < s_vsNames.GetSize());
		return s_vsNames[iIndex];
	}
	return NULL;
}

int WksBuiltinLabelsHolder::GetLabelType( const string& strName )
{
	int iIndex = s_vsNames.Find(strName);
	if (iIndex >= 0 && iIndex < s_vnTypes.GetSize())
		return s_vnTypes[iIndex];
	return RCLT_INVALID;
}

void WksBuiltinLabelsHolder::GetAllLabelRef( const vector<string>*& pvsNames, const vector<int>*& pvnTypes )
{
	pvsNames = &s_vsNames;
	pvnTypes = &s_vnTypes;
}

//WksBuiltinLabelsHolder& WksBuiltinLabelsHolder::GetInstance()
//{
	//// Single instance
	//static WksBuiltinLabelsHolder holder;
	//return holder;
//}

static WksBuiltinLabelsHolder& _get_wks_builtin_labels_holder()
{
	static WksBuiltinLabelsHolder holder;
	return holder;
}

string get_builtin_label_name( int nType )
{
	return _get_wks_builtin_labels_holder().GetLabelName(nType);
}
///End ADD_FUNC_GET_BUILTIN_LABEL_NAME

///MOVE_FUNCTION_BODY_FORM_H_TO_C

///------ Folger 03/25/09 CLEAN_UP_CODES_ABOUT_GET_ALL_SHWON_PARAMETER_NAMES_AND_VALUES
int	get_all_shown_parameters_names_and_values(Column& col, vector<string>* pvsNames, vector<string>* pvsValues, vector<int>* pvnTypes/* = NULL*/)
{
	if ( NULL == pvsNames && NULL == pvsValues )
		return 0;
	
	vector<int> vnIDs;
	Worksheet wks;
	col.GetParent(wks);
	wks_get_show_labels(wks, vnIDs);
	
	if ( pvsNames )
		pvsNames->SetSize(0);
	if ( pvsValues )
		pvsValues->SetSize(0);
	
	WksBuiltinLabelsHolder& clHolder = _get_wks_builtin_labels_holder();
	for(int ii = 0; ii <vnIDs.GetSize(); ii++)
	{
		///Kyle 04/03/2009 QA80-13385 GET_ALL_LABELS_SHOWN
		//if(vnIDs[ii] >= RCLT_PARAM && vnIDs[ii] < RCLT_PARAM + PARAMS_MAX_NUM)
		if(vnIDs[ii] > RCLT_INVALID && vnIDs[ii] < RCLT_PARAM + PARAMS_MAX_NUM)
		///End GET_ALL_LABELS_SHOWN
		{
			string	str;
			if ( pvsNames )
			{
				pvsNames->Add(clHolder.GetLabelName(vnIDs[ii]));
			}
			if ( pvsValues )
			{
				string	str;
				///------ Folger 04/16/09 INCORRECT_WAY_TO_GET_COL_LABEL_VALUES
				/// this code will make w2m fails to use column labels as FirstRow/FirsrCol
				//col.GetParameter(str, vnIDs[ii]-RCLT_PARAM);				
				col.GetExtendedLabel(str, vnIDs[ii]);
				///------ End INCORRECT_WAY_TO_GET_COL_LABEL_VALUES
				pvsValues->Add(str);
			}
			if ( pvnTypes )
				pvnTypes->Add(vnIDs[ii]);
		}
	}

	vector<string> vsValues, vStr;
	get_user_parameters(col, vStr, vsValues, true);
	
	if ( pvsNames )
		pvsNames->Append(vStr);
	if ( pvsValues )
		pvsValues->Append(vsValues);
	if ( pvnTypes )
	{
		vector<int>		vn;
		vn.Data(RCLT_UDL, RCLT_UDL + vStr.GetSize() - 1);
		pvnTypes->Append(vn);
	}
	
	return ( pvsNames ? pvsNames->GetSize() : pvsValues->GetSize() );
}
///------ End CLEAN_UP_CODES_ABOUT_GET_ALL_SHWON_PARAMETER_NAMES_AND_VALUES

/// Kenny 08/27/2009 QA81-14182 NEW_XF_PLOTTING_GROUPS_OF_COLUMNS
int get_label_type_by_name( const Worksheet& wks, LPCTSTR lpcszLabelName )
{
	int nType = RCLT_INVALID;
	string strLabelName = lpcszLabelName;
	if ( !strLabelName.IsEmpty() )
	{
		nType = find_builtin_label(strLabelName);
		if ( nType < 0 )
		{
			Grid grid;
			if ( grid.Attach(wks) )
			{
				vector<string> vsUDLNames;
				BOOL bRet = grid.GetUserDefinedLabelNames(vsUDLNames);
				ASSERT(bRet);
				int nOffset = vsUDLNames.Find(strLabelName);
				if ( nOffset >= 0 )
				{
					nType = RCLT_UDL + nOffset;
				}
			}
		}
	}
	return nType;
}

///------ Folger 11/06/09 QA81-14609 XF_SUPPORT_LABEL_INDENTIFIER_FROM_LT
int	get_label_type_by_name_or_indentifier(const Worksheet& wks, LPCTSTR lpcszLabel)
{
	vector<int>		vnTypes;
	okutil_convert_labels_string_to_indices(lpcszLabel, &vnTypes);
	if ( vnTypes.GetSize() > 0 )
		return vnTypes[0];
	
	return get_label_type_by_name(wks, lpcszLabel);
}

int	get_wks_shown_col_label_info_skip_specials(const Worksheet& wks, vector<string>& vsNames, vector<int>& vnTypes)
{
	vector<int>		vnTypesToSkip = { RCLT_SAMPLE_RATE
		, RCLT_SPARKLINE
	};

	return get_wks_shown_col_label_info(wks, vsNames, vnTypes, &vnTypesToSkip);
}
///------ End XF_SUPPORT_LABEL_INDENTIFIER_FROM_LT

///------ Folger 09/04/09 GET_WKS_SHOWN_LABELS_SUPPORT_SKIP_SPECIFIC_TYPES
//bool get_wks_shown_col_label_info( const Worksheet& wks, vector<string>& vsNames, vector<int>& vnTypes )
bool get_wks_shown_col_label_info( const Worksheet& wks, vector<string>& vsNames, vector<int>& vnTypes, vector<int>* pvnTypesToSkip/* = NULL*/ )
///------ End GET_WKS_SHOWN_LABELS_SUPPORT_SKIP_SPECIFIC_TYPES
{
	vsNames.SetSize(0);
	vnTypes.SetSize(0);

	Grid grid;
	if ( !grid.Attach(wks) )
		return false;

	if ( grid.GetShowLabels(vnTypes) )
	{
		const int nSize = vnTypes.GetSize();
		vsNames.SetSize(nSize);
		ASSERT( vsNames.GetSize() == vnTypes.GetSize() );
		vector<string> vsUDLNames;
		bool bUDLNamesRetrieved = false;
		///------ Folger 09/04/09 GET_WKS_SHOWN_LABELS_SUPPORT_SKIP_SPECIFIC_TYPES
		//for (int ii = 0; ii < nSize; ++ii)
		for (int ii = nSize-1; ii >= 0; --ii)
		///------ End GET_WKS_SHOWN_LABELS_SUPPORT_SKIP_SPECIFIC_TYPES
		{
			int nType = vnTypes[ii];
			///------ Folger 09/04/09 GET_WKS_SHOWN_LABELS_SUPPORT_SKIP_SPECIFIC_TYPES
			if ( pvnTypesToSkip )
			{
				vector<uint>	vnIndices;
				if (  pvnTypesToSkip->Find(vnIndices, nType) > 0 )
				{
					vnTypes.RemoveAt(ii);
					vsNames.RemoveAt(ii);
					continue;
				}
			}
			///------ End GET_WKS_SHOWN_LABELS_SUPPORT_SKIP_SPECIFIC_TYPES
			if ( nType >= RCLT_UDL )
			{
				ASSERT( nType <= RCLT_MAX_TYPE );
				int nOffset = nType - RCLT_UDL;
				if ( !bUDLNamesRetrieved )
				{
					BOOL bRet = grid.GetUserDefinedLabelNames(vsUDLNames);
					ASSERT(bRet);
					bUDLNamesRetrieved = true;
				}
				if ( nOffset < vsUDLNames.GetSize() )
					vsNames[ii] = vsUDLNames[nOffset];
			}
			else
			{
				vsNames[ii] = get_builtin_label_name( nType );
			}
		}
		return true;
	}

	return false;
}

///------ Folger 11/06/09 QA81-14603 PAMULTIY_SUPPORT_INSERT_DATA_INDENTIFIER_IN_SUMMARY_SHEET
//int get_wks_common_col_label_info( const Worksheet& wks, vector<string>& vsNames, vector<int>& vnTypes, bool bIsFirstWks /*= true*/ )
#define		CHECK_GET_WKS_SHOWN_COL_LABEL_INFO(_bNoError, _vsNames, _vnTypes) \
			bNoError = bSkipSpecials ? get_wks_shown_col_label_info_skip_specials(wks, _vsNames, _vnTypes) : get_wks_shown_col_label_info(wks, _vsNames, _vnTypes)

int get_wks_common_col_label_info( const Worksheet& wks, vector<string>& vsNames, vector<int>& vnTypes, bool bIsFirstWks /*= true*/, BOOL bSkipSpecials/* = TRUE*/ )
///------ End PAMULTIY_SUPPORT_INSERT_DATA_INDENTIFIER_IN_SUMMARY_SHEET
{
	bool bNoError = false;
	bool bNoCommon = false;
	if ( bIsFirstWks )
	{
		///------ Folger 11/06/09 QA81-14603 PAMULTIY_SUPPORT_INSERT_DATA_INDENTIFIER_IN_SUMMARY_SHEET
		//bNoError = get_wks_shown_col_label_info(wks, vsNames, vnTypes);
		CHECK_GET_WKS_SHOWN_COL_LABEL_INFO(bNoError, vsNames, vnTypes);
		///------ End PAMULTIY_SUPPORT_INSERT_DATA_INDENTIFIER_IN_SUMMARY_SHEET
	}
	else
	{
		ASSERT( vsNames.GetSize() == vnTypes.GetSize() );
		const int nSize = vsNames.GetSize();
		if ( 0 == nSize )
		{
			bNoCommon = true;
		}
		else
		{
			vector<string>	vsCurWksLabelNames;
			vector<int>		vnCurWksLabelTypes;
			///------ Folger 11/06/09 QA81-14603 PAMULTIY_SUPPORT_INSERT_DATA_INDENTIFIER_IN_SUMMARY_SHEET
			//bNoError = get_wks_shown_col_label_info(wks, vsCurWksLabelNames, vnCurWksLabelTypes);
			CHECK_GET_WKS_SHOWN_COL_LABEL_INFO(bNoError, vsCurWksLabelNames, vnCurWksLabelTypes);
			///------ End PAMULTIY_SUPPORT_INSERT_DATA_INDENTIFIER_IN_SUMMARY_SHEET

			if ( bNoError )
			{
				if ( vsCurWksLabelNames.GetSize() <= 0 )
				{
					bNoCommon = true;
				}
				else
				{
					ASSERT( vsCurWksLabelNames.GetSize() == vnCurWksLabelTypes.GetSize() );
					for (int ii = nSize-1; ii >= 0; --ii)
					{
						const int nType = vnTypes[ii];
						bool bNotFoundInCurLabels;
						if ( nType >= RCLT_UDL )
						{
							bNotFoundInCurLabels = vsCurWksLabelNames.Find( vsNames[ii] ) < 0;
						}
						else
						{
							vector<uint> vIndex;
							bNotFoundInCurLabels = vnCurWksLabelTypes.Find( MATREPL_TEST_EQUAL, nType, vIndex ) <= 0;
						}
						if ( bNotFoundInCurLabels )
						{
							vsNames.RemoveAt(ii);
							vnTypes.RemoveAt(ii);
						}
					}
				}
			}
		}
	}
	bNoCommon |= 0 == vsNames.GetSize();
	if ( bNoCommon )
	{
		vsNames.SetSize(0);
		vnTypes.SetSize(0);
	}
	return bNoError ? (bNoCommon ? GET_COMMON_LABEL_NO_COMMON : GET_COMMON_LABEL_OK) : GET_COMMON_LABEL_ERROR;
}

///------ Folger 11/06/09 QA81-14603 PAMULTIY_SUPPORT_INSERT_DATA_INDENTIFIER_IN_SUMMARY_SHEET
//int WksCommonColLabelHelper::UpdateCommonColLabelInfo( const Worksheet& wks )
int WksCommonColLabelHelper::UpdateCommonColLabelInfo( const Worksheet& wks, BOOL bSkipSpecials/* = TRUE*/ )
///------ End PAMULTIY_SUPPORT_INSERT_DATA_INDENTIFIER_IN_SUMMARY_SHEET
{
	bool bIsFirstWks = 0 == m_vnWksUID.GetSize();
	UINT nWksUID = wks.GetUID();
	vector<uint> vIndex;
	if ( bIsFirstWks || m_vnWksUID.Find(MATREPL_TEST_EQUAL, nWksUID, vIndex) <= 0 )
	{
		m_vnWksUID.Add(nWksUID);
		///------ Folger 11/06/09 QA81-14603 PAMULTIY_SUPPORT_INSERT_DATA_INDENTIFIER_IN_SUMMARY_SHEET
		return get_wks_common_col_label_info(wks, m_vsLabelNames, m_vnLabelTypes, bIsFirstWks);
		///------ End PAMULTIY_SUPPORT_INSERT_DATA_INDENTIFIER_IN_SUMMARY_SHEET
	}
	return GET_COMMON_LABEL_OK;
}

void WksCommonColLabelHelper::Reset()
{
	m_vnWksUID.RemoveAll();
	m_vsLabelNames.RemoveAll();
	m_vnLabelTypes.RemoveAll();
}
/// End QA81-14182 NEW_XF_PLOTTING_GROUPS_OF_COLUMNS

///------ Folger 09/02/09 BATCH_PROCESS_APPEND_LABEL_ROWS_SKIP_EMPTY
///------ Folger 12/11/09 QA81-14733 PA_MULTIY_SUPPORT_APPEND_FIT_STATS_RESULTS
//void	append_label_rows(Worksheet& wksSummary, Worksheet& wksSrc, int nColOffset/* = 0*/)
void	append_label_rows(Worksheet& wksSummary, Worksheet& wksSrc, int nColOffset/* = 0*/, int nRowStart/* = -1*/)
///------ End PA_MULTIY_SUPPORT_APPEND_FIT_STATS_RESULTS
{
	Grid	grid;
	grid.Attach(wksSrc);
	
	vector<int>		vnTypes;
	grid.GetShowLabels(vnTypes);
	vector<int>		vnTypesToSkip = { RCLT_SAMPLE_RATE
		, RCLT_SPARKLINE
	};
	
	if ( -1 == nRowStart )
	{
		int		nR1;
		wksSummary.GetBounds(nR1, 0, nRowStart, -1);
		++nRowStart;
	}
	
	for ( int ii=0; ii<vnTypes.GetSize(); ++ii )
	{
		vector<uint>	vnIndices;
		if ( vnTypesToSkip.Find(vnIndices, vnTypes[ii]) > 0 )
			continue;
		
		vector<string>		vsValues;
		grid.GetLabelsByType(vsValues, vnTypes[ii]);
		
		string		strJunk;
		strJunk.SetTokens(vsValues, '|');
		if ( strJunk.GetLength() < vsValues.GetSize() )
			continue;
		
		if ( nColOffset > 0 )
			vsValues.InsertAt(0, "", nColOffset);
		///------ Folger 12/11/09 QA81-14733 PA_MULTIY_SUPPORT_APPEND_FIT_STATS_RESULTS
		//wksSummary.SetCells(vsValues);
		wksSummary.SetCells(vsValues, ii == 0 ? nRowStart : -1);
		///------ End PA_MULTIY_SUPPORT_APPEND_FIT_STATS_RESULTS
	}
}

///------ End BATCH_PROCESS_APPEND_LABEL_ROWS_SKIP_EMPTY

/// Kenny 09/27/2009 QA81-14241 INSERT_PARAM_NEED_CORRECT_INDICES_AND_CENTRALIZE_CODES
string get_label_name_by_type( const int nType, const Worksheet& wks /*= NULL*/ )
{
	WksColLabelHelper helper(wks);
	return helper.GetNameByType(nType);
}

WksColLabelHelper::WksColLabelHelper( const Worksheet& wks /*= NULL*/ )
{
	Attach(wks);
}

BOOL WksColLabelHelper::Attach( const Worksheet& wks )
{
	m_wks = wks;
	return TRUE;
}

int WksColLabelHelper::UpdateUDLInfo()
{
	m_vsUDLNames.RemoveAll();
	if ( !m_wks.IsValid() )
		return -1;
	Grid grid;
	if ( !grid.Attach(m_wks) )
		return -2;
	BOOL bRet = grid.GetUserDefinedLabelNames( m_vsUDLNames );
	ASSERT(bRet);
	return m_vsUDLNames.GetSize();
}

int WksColLabelHelper::GetTypeByName( LPCTSTR lpcszLabelName )
{
	int nType = RCLT_INVALID;
	string strLabelName = lpcszLabelName;
	const int nLen = strLabelName.GetLength();
	if ( nLen > 0 )
	{
		if ( 1 == nLen )
			nType = okutil_cvt_col_label_char_to_type( strLabelName.GetAt(0) );
		else
			nType = _get_wks_builtin_labels_holder().GetLabelType(strLabelName);

		if ( RCLT_INVALID == nType )
		{
			if ( 0 == m_vsUDLNames.GetSize() )
				 UpdateUDLInfo();

			const int nUDLNamesSize = m_vsUDLNames.GetSize();
			if ( nUDLNamesSize > 0 )
			{
				for (int ii = 0; ii < nUDLNamesSize; ++ii)
				{
					if ( strLabelName.CompareNoCase( m_vsUDLNames[ii] ) == 0 )
						break;
				}
			}
		}
	}
	return nType;
}

string WksColLabelHelper::GetNameByType( int nType )
{
	string strLabelName;
	if ( nType >= RCLT_UDL )
	{
		if ( 0 == m_vsUDLNames.GetSize() )
			UpdateUDLInfo();
		const int nOffset = nType - RCLT_UDL;
		const int nUDLNamesSize = m_vsUDLNames.GetSize();
		if ( nUDLNamesSize > 0 && nOffset < nUDLNamesSize )
		{
			strLabelName = m_vsUDLNames[nOffset];
		}
	}
	else
	{
		strLabelName = get_builtin_label_name(nType);
	}
	return strLabelName;
}
/// End QA81-14241 INSERT_PARAM_NEED_CORRECT_INDICES_AND_CENTRALIZE_CODES

///------ Folger 05/05/10 ORG-88 BATCH_PROCESS_SUPPORT_DATASET_IDENTIFIER
#include <xfutils.h>

#define		BATCH_STR_RANGE_E				"Range"
#define		BATCH_STR_BOOK_E				"Book Name"
#define		BATCH_STR_SHEET_E				"Sheet Name"

int		batch_get_label_type_by_name(Worksheet& wks, LPCSTR lpcszLabel)
{
	if ( compare_string_localization(lpcszLabel, BATCH_STR_RANGE_E, true) )
		return BATCH_RCLT_RANGE;
	if ( compare_string_localization(lpcszLabel, BATCH_STR_BOOK_E, true) )
		return BATCH_RCLT_BOOK;
	if ( compare_string_localization(lpcszLabel, BATCH_STR_SHEET_E, true) )
		return BATCH_RCLT_SHEET;
	
	return get_label_type_by_name_or_indentifier(wks, lpcszLabel);
}

void	batch_update_data_indentifiers(TreeNode& trGetN, LPCSTR lpcszTag, BOOL bAddNone/* = FALSE*/)
{
	TreeNode		trXY = trGetN.iy;
	XYRange			xy;
	string			strCombo = " |";
	string			strDefault = " ";
	TreeNode		trDataId = trGetN.GetNode(lpcszTag);
	if ( !trDataId )
	{
		ASSERT(FALSE);
		return;
	}
	if ( okxf_resolve_tree_construct_range(&trXY, &xy) && xy )
	{
		MultipleXYRangesWksCommonLabelHelper	clHelper(xy);
		
		vector<string>		vsLabelNames;
		vsLabelNames = GET_LABEL_NAMES(clHelper);
		vsLabelNames.InsertAt(0, GetLocalized(BATCH_STR_SHEET_E));
		vsLabelNames.InsertAt(0, GetLocalized(BATCH_STR_BOOK_E));
		vsLabelNames.InsertAt(0, GetLocalized(BATCH_STR_RANGE_E));
		if ( bAddNone )
			vsLabelNames.InsertAt(0, GetLocalized(BATCH_STR_NONE_E));
		strCombo.SetTokens(vsLabelNames, '|');
		strCombo += "|";
		if ( vsLabelNames.Find(trDataId.strVal) >= 0 )
			strDefault = trDataId.strVal;
		else
			strDefault = vsLabelNames[0];
	}
	
	trDataId.SetAttribute(STR_COMBO_ATTRIB, strCombo);
	trDataId.strVal = strDefault;
}

string	batch_get_data_identifier_string(XYRange& xy, int nLabelType)
{
	string	str;
	switch ( nLabelType )
	{
	case BATCH_RCLT_RANGE:
		xy.GetRangeString(str);
		break;
		
	case BATCH_RCLT_BOOK:
	case BATCH_RCLT_SHEET:
		{
			Worksheet	wks;
			int			c1, c2;
			xy.GetRange(wks, c1, c2);
			if ( wks )
			{
				string	strBook, strSheet;
				okutil_get_book_sheet_names(wks.m_strBookSheet, &strBook, &strSheet);
				str = BATCH_RCLT_BOOK == nLabelType ? strBook : strSheet;
			}
			else
			{
				ASSERT(FALSE);
			}
		}
		break;
		
	default:
		{
			Column		colY;
			if ( xy.GetYColumn(colY) && colY )
			{
				colY.GetExtendedLabel(str, nLabelType);
			}
		}
		break;
	}
	
	return str;
}

BOOL	batch_check_append_col_results(Worksheet& wks, int nCol, int nSize, LPCSTR lpcsz, int nRowStart)
{
	Dataset			dsS(wks, nCol);
	if ( !dsS )
		return FALSE;
	
	vector<string>		vsValues(nSize);
	for ( int ii=0; ii<nSize; ++ii )
		vsValues[ii] = lpcsz;
	
	vector<string>	vs;
	dsS.GetStringArray(vs);
	if ( nRowStart > 0 )
		vs.SetSize(nRowStart);
	vs.Append(vsValues);
	dsS.PutStringArray(vs);
	return TRUE;
}
///------ End BATCH_PROCESS_SUPPORT_DATASET_IDENTIFIER