/*------------------------------------------------------------------------------*
 * File Name: DataInfoDlg			 											*
 * Creation: CPY 6/15/2005														*
 * Purpose: DataInfo Window for Cursor and Data Reader info display				*
 * Copyright (c) Originlab Corp.	2005, 2006, 2007, 2008, 2009, 2010			*
 * All Rights Reserved															*
 * 																				*
 * Modification Log:															*
 * Jasmine 10/10/06 ADD_INFO_TEXT												*
 * Jasmine 01/10/07 MOVE_TO_SHOW_ALL_CHECK_BOX									*
 * Iris 03/26/2007 V8.0589 SAVE_CHECK_STATUS_INTO_REG							*
 * Jake 04/04/07 HIDE_DATAINFO_WINDOW_WHEN_PAGE_CHANGE							*
 * Jake 04/06/07 ADD_CHECKBOX_FOR_SHOW_LONG_AND_SHORT_NAME						*
 * jake 04/23/07 DEBUG_FOR_R602B_SHOW_DATAINFO_WHEN_CURSOR_MOVE					*
 * Folger 08/15/07 CORRECT_CONTROL_DISPLAY_FOR_BOTH_COLUMN_MATOBJ				*
 * Jasmine 09/19/07 QA80-10385 LOCALIZATION_FOR_NEUTRAL_DIALOG					*
 *	CPY 10/7/07 QA70-10484 FIX_DATA_READER_ONLY_FOR_DATA_INFO					*
 * Folger 10/27/07 SHOULD_UPDATE_DATA_INFO_DIALOG_WHEN_PLOT_CHANGE				*
 * Folger 10/27/07 FIX_BUG_WHEN_INITIALIZE_DATASET_WITH_COLUMN_OF_NON_NUMERIC	*
 *	CPY 11/2/07 CORRECT_LOCALIZATION_COMPILE_ERR								*
 *	CPY 2/29/2008 QA70-9856 DATA_READER_DATA_INFO_WIN_CLEAN_UP					*
 *	YuI 09/03/08 QA70-12127 INIFITE_INVALIDATE_ON_CURSOR_ADDITION				*
 *	YuI 04/06/09 QA70-13336 TERNARY_PLOT_ANNOTATION_SHOULD_SHOW_Z_VALUE			*
 *	YuI 09/21/09 QA70-14346_P1 ANNOTATION_SMARTER_TETHERING_POINT				*
 *	YuI 09/21/09 QA70-14346_P3 ANNOTATION_SCREWED_UP_IF_TERNARY_IS_SCALED		*
 *	YuI 10/05/09 QA70-14409 CURSOR_ON_TERNARY_PROBLEM							*
 *	Folger 06/29/10 ORG-336 ADD_BACK_CURSOR_SUPPORT_FOR_DATA_INFO				*
 *	Folger 07/02/10 ORG-436-P4 DATA_INFO_CURSOR_FAILED_TO_GET_CATEGORICAL_DATA	*
 *	Folger 07/02/10 ORG-436-P3 WRONG_DATA_READER_VALUE_WHEN_DOUBLE_CLICK_TO_ADD_CURSOR
 *	RVD 7/8/2010 org-479 FIX_CURSOR_3D_SCATTER_POSITION							*
 *	Folger 09/03/2010 ORG-502-P7 DATA_INFO_FAILED_TO_SHOW_CURSOR_DIFERENCE_Z_VALUE
 *	Folger 09/06/2010 ORG-960 DATA_INFO_FAILED_TO_READ_CURSOR_INFO_WHEN_SWITCHING_DATA_PLOT
 *------------------------------------------------------------------------------*/
 
 ////////////////////////////////////////////////////////////////////////////////////
// Including the system header file Origin.h should be sufficient for most Origin
// applications and is recommended. Origin.h includes many of the most common system
// header files and is automatically pre-compiled when Origin runs the first time.
// Programs including Origin.h subsequently compile much more quickly as long as
// the size and number of other included header files is minimized. All NAG header
// files are now included in Origin.h and no longer need be separately included.
//
// Right-click on the line below and select 'Open "Origin.h"' to open the Origin.h
// system header file.
#include <Origin.h>
#include "DialogEx.h"
#define BASE_WINDOW ResizeDialog
#include "TreeEditEvents.h"
#include "DataInfoCursor.h"
#define DATAINFO_USE_DIALOG_BAR
#include "DataInfoDlg.h"
#include "grobj_utils.h"
/// YuI 07/26/05 CENTRALIZE_TOOL_EVENTS
#include <Tools.h>
/// end CENTRALIZE_TOOL_EVENTS


#pragma _NOAUTOREMOVE    

#pragma labtalk(0) //--- CPY 2/22/07 hide all functions in this file from LT access, as XF should be used instead

//----Jake 04/06/07 ADD_CHECKBOX_FOR_SHOW_LONG_AND_SHORT_NAME
enum {DIC_TRANSPOSE = 1, DIC_ALL_COLS = 2,DIC_LONG_SHORT_NAME=4};
//----end 04/06/07 ADD_CHECKBOX_FOR_SHOW_LONG_AND_SHORT_NAME
enum {UDI_TRACKING, UDI_REDRAW, UDI_UPDATE, UDI_RESET, UDI_TRACKING_REUSE_OLD};
static bool _update_data_info_dlg(int nMode = UDI_UPDATE, int nTool = 0, int nCursor = 0, int nLayer = 0, int nPlot = 0, int nDataIndex = 0, bool bPageChanged = false);
enum {DICOL_CURSOR, DICOL_PLOT, DICOL_DATA, DICOL_COL, DICOL_WKS, DICOL_WKBOOK, DICOL_TOTAL};
/// Max 11/1/07 CORRECT_LOCALIZATION
/*
static vector<string> s_colTitles = 
	{"Cursor", "Plot", "Value", "Column", "Sheet", "Book"};
*/
static vector<string> s_colTitles;
//----- CPY 11/2/07 CORRECT_LOCALIZATION_COMPILE_ERR
/*
	s_colTitles.SetSize(6);
	s_colTitles[0] = _L("Cursor");
	s_colTitles[1] = _L("Plot");
	s_colTitles[2] = _L("Value");
	s_colTitles[3] = _L("Column"); 
	s_colTitles[4] = _L("Sheet");
	s_colTitles[5] = _L("Book");
*/
//----- end CORRECT_LOCALIZATION_COMPILE_ERR 
/// END CORRECT_LOCALIZATION
class DataInfoWindow;
static DataInfoWindow *s_pDataInfodlg = NULL;
#ifdef DATAINFO_USE_DIALOG_BAR
static  DialogBar s_DataInfoBar;
///------ Folger 06/30/10 ORG-336 ADD_BACK_CURSOR_SUPPORT_FOR_DATA_INFO
#define		SET_DATAINFOBAR_VISIBLE		s_DataInfoBar.Visible = s_pDataInfodlg->IsAllowShow()
///------ End ADD_BACK_CURSOR_SUPPORT_FOR_DATA_INFO
#endif

#define		DLG_NAME								"DataInfo"
#define		CTRL_TRANSPOSED_REG_VALNAME				"Transposed"
#define		CTRL_SHOWALLCOLS_REG_VALNAME			"ShowAllCols"
//----Jake 04/06/07 ADD_CHECKBOX_FOR_SHOW_LONG_AND_SHORT_NAME	
#define     CTRL_SHOWLONGANDSHORTNAME_REG_VALNAME	"ShowLongAndShortName"	
//----end 04/06/07 ADD_CHECKBOX_FOR_SHOW_LONG_AND_SHORT_NAME

class DataInfoWindow : public TreeEditDlg
{
public:
	DataInfoWindow(BOOL bDeleteOnDestroy = FALSE) : TreeEditDlg(IDD_DATA_INFO, "ODlg8" )
	{
		m_bDeleteOnDestroy = bDeleteOnDestroy;
		m_dwCntrl = DIC_TRANSPOSE;
		m_lastIndex = -1;
	}
	DWORD	DoModalEx(HWND hParent)
	{
		InitMsgMap();// will be called from internal later
		int nRet = DoModal(hParent);
		if(IDOK == nRet)
		{
			return 1;
		}
		return 0;
	}
	virtual int  Create(HWND hParent = NULL)
	{
		InitMsgMap();		
		
		/// Iris 03/26/2007 V8.0589 SAVE_CHECK_STATUS_INTO_REG
		loadContrlSettingFromReg(CTRL_TRANSPOSED_REG_VALNAME, DIC_TRANSPOSE);
		loadContrlSettingFromReg(CTRL_SHOWALLCOLS_REG_VALNAME, DIC_ALL_COLS);
		//----Jake 04/06/07 ADD_CHECKBOX_FOR_SHOW_LONG_AND_SHORT_NAME	
		loadContrlSettingFromReg(CTRL_SHOWLONGANDSHORTNAME_REG_VALNAME,DIC_LONG_SHORT_NAME);
		//---- end ADD_CHECKBOX_FOR_SHOW_LONG_AND_SHORT_NAME
		///end SAVE_CHECK_STATUS_INTO_REG
		
		//Launch the modeless dialog
		int nRet = TreeEditDlg::Create(hParent);
		
		return nRet;
	}

	///------ Folger 06/29/10 ORG-336 ADD_BACK_CURSOR_SUPPORT_FOR_DATA_INFO
	BOOL	IsAllowShow()
	{
		double	rNDI = 1;
		LT_get_var("@NDI", &rNDI);
		return rNDI == 0;
	}
	///------ End ADD_BACK_CURSOR_SUPPORT_FOR_DATA_INFO

	void BeforeUpdate()
	{
		m_treeEditCntrl.SetReady(false);
	}
	void AfterUpdate(bool bResizeCols = true)
	{
		if(m_bNewStruct && bResizeCols)
		{
			SetColAlignments();
			m_treeEditCntrl.ResizeCols(0, 3, 7);
		}
		m_treeEditCntrl.SetReady(true);
		m_bNewStruct = false;
	}
	void SetDirectUpdate()
	{
		m_treeEditCntrl.SetRedraw(flexRDDirect);
	}
	void ResetRows()
	{
		m_bNewStruct = true;	
		if(DIC_TRANSPOSE & m_dwCntrl)
			m_treeEditCntrl.SetCols(0, true);
		else
			m_treeEditCntrl.SetRows(0, true);
	}
	void SetMergeCols(vector<int>& vnCols)
	{
		for(int ii = 0; ii < vnCols.GetSize(); ii++)
		{
			if(DIC_TRANSPOSE & m_dwCntrl)
				m_treeEditCntrl.SetMergeRow(vnCols[ii] - 1);
			else				
				m_treeEditCntrl.SetMergeCol(vnCols[ii]);
		}
	}
	bool SetColumn(int nCol, const vector<string>& vsVals)
	{
		if(DIC_TRANSPOSE & m_dwCntrl)
		{
			return m_treeEditCntrl.SetRowValues(nCol - 1, vsVals, 0, true);
		}
		else
			return m_treeEditCntrl.SetColValues(nCol, vsVals, 0, true);
	}
	bool SetColHeading(int nCol, LPCSTR lpcsz)
	{
		if(DIC_TRANSPOSE & m_dwCntrl)
		{
			return m_treeEditCntrl.SetRowHeading(nCol - 1, lpcsz, true);
		}
		else
		{
			return m_treeEditCntrl.SetColHeading(nCol, lpcsz, true);
		}
	}
	void SetColAlignments()
	{
		m_treeEditCntrl.SetFixedColAlignment(-1, flexAlignCenterCenter);
		if(DIC_TRANSPOSE & m_dwCntrl )
		{
			m_treeEditCntrl.SetColAlignment(-1, flexAlignLeftCenter);
		}
		else
		{
			m_treeEditCntrl.SetColAlignment(-1, flexAlignLeftCenter);//flexAlignGeneral);
		}
	}
	void Reset()
	{
		BeforeUpdate();
		m_treeEditCntrl.SetupRowsCols(1);
		ResetRows();
		AfterUpdate(false);
	}
	void InitGrid()
	{
		//----- CPY 11/2/07 CORRECT_LOCALIZATION_COMPILE_ERR
		if(s_colTitles.GetSize() ==0)
		{
			s_colTitles.Add(_L("Cursor"));
			s_colTitles.Add(_L("Plot"));
			s_colTitles.Add(_L("Value"));
			s_colTitles.Add(_L("Column")); 
			s_colTitles.Add(_L("Sheet"));
			s_colTitles.Add(_L("Book"));
		}
		//-----

		Update(UDI_RESET);
		m_treeEditCntrl.SetupRowsCols(1);
		for(int ii = 0; ii < DICOL_TOTAL; ii++)
			SetColHeading(ii, s_colTitles[ii]);
		
		vector<int> vnMergeCols = {DICOL_CURSOR, DICOL_WKBOOK, DICOL_WKS};
		SetMergeCols(vnMergeCols);
	}		
	bool IsShowAllCols() {return (m_dwCntrl & DIC_ALL_COLS)? true:false;}	
	void SetShowAllCols(bool bSet)
	{
		if(bSet)
			m_dwCntrl |= DIC_ALL_COLS;
		else
			m_dwCntrl &= ~DIC_ALL_COLS;
	}
    //----Jake 04/06/07 ADD_CHECKBOX_FOR_SHOW_LONG_AND_SHORT_NAME	
	bool IsShowLongAndShortName(){return (m_dwCntrl & DIC_LONG_SHORT_NAME)? true:false;}
	void SetShowLongAndShortName(bool bSet)
	{
		if(bSet)
			m_dwCntrl |= DIC_LONG_SHORT_NAME;
		else
			m_dwCntrl &= ~DIC_LONG_SHORT_NAME;			
	}
	//----end ADD_CHECKBOX_FOR_SHOW_LONG_AND_SHORT_NAME
	bool Update(int nMode, int nTool = 0, int nCursor = 0, int nLayer = 0, int nPlot = 0, int nDataIndex = 0)
	{
		//------ Folger 10/27/07 SHOULD_UPDATE_DATA_INFO_DIALOG_WHEN_PLOT_CHANGE
		//if(UDI_TRACKING == nMode && nTool > 0 && m_lastIndex == nDataIndex)
		if(UDI_TRACKING == nMode && nTool > 0 && m_nLastPlot == nPlot && m_lastIndex == nDataIndex)
		//------ End SHOULD_UPDATE_DATA_INFO_DIALOG_WHEN_PLOT_CHANGE
			return false;
		
		if(UDI_TRACKING_REUSE_OLD == nMode)
		{
			nMode = UDI_TRACKING;
			nTool = 0;// to indicate reuse last values
		}
		//printf("index = %d\n", nn);
		
		if(!_update_data_info_dlg(nMode, nTool, nCursor, nLayer, nPlot, nDataIndex))
			return false;

		m_nLastPlot = nPlot;		//------ Folger 10/27/07 SHOULD_UPDATE_DATA_INFO_DIALOG_WHEN_PLOT_CHANGE
		m_lastIndex = nDataIndex;
		return true;
	}
	//------ Folger 08/15/07 CORRECT_CONTROL_DISPLAY_FOR_BOTH_COLUMN_MATOBJ
	void SetControlDisplay(bool bVisible = true)
	{
		m_chkViewAddWksCols.Visible = bVisible;
		s_colTitles[3] = bVisible ? _L("Column") : _L("MatObj");
		s_pDataInfodlg->InitGrid();
		_update_data_info_dlg(UDI_REDRAW);
	}
	//------ End CORRECT_CONTROL_DISPLAY_FOR_BOTH_COLUMN_MATOBJ
	
protected:
	
	EVENTS_BEGIN
		ON_INIT( OnInitDialog )
		ON_READY(OnReady)
		ON_DESTROY(OnDestroy)
		ON_CHANGE_LAYER( OnActiveLayerChange )
		ON_CHANGE_PAGE( OnActivePageChange )
		ON_CHANGE_SELECTION( OnSelectionChange )
		ON_SIZE(OnDlgResize)
		
		ON_BN_CLICKED(IDC_RG_CHECK1, OnToggleColView)
		ON_BN_CLICKED(IDC_RG_CHECK2, OnToggleShowAllCols)
		//----Jake 04/06/07 ADD_CHECKBOX_FOR_SHOW_LONG_AND_SHORT_NAME	
		ON_BN_CLICKED(IDC_RG_CHECK3, OnToggleShowLongAndShortName)
		//----end ADD_CHECKBOX_FOR_SHOW_LONG_AND_SHORT_NAME
		//ON_GETNDLG_MSGS(IDC_GRID)
		
		ON_USER_MSG(WM_USER_DIALOGBAR_SHOW, OnShow)		//------ CPY 2/29/2008 QA70-9856 DATA_READER_DATA_INFO_WIN_CLEAN_UP

		ON_SYSCOMMAND(OnSystemCommand)
	EVENTS_END
	
protected:
	BOOL OnInitDialog()
	{
		ResizeDialog::OnInitDialog(IDC_GRID, "DataInfoDlg");
		m_treeEditCntrl.Init(IDC_GRID, false, true, NULL, *this);
		m_treeEditCntrl.SetupRowsCols(1);
		m_treeEditCntrl.SetGridLines(flexGridInset);//flexGridInsetVert);
		//uint dwColor = RGB(215, 225, 225);
		//m_treeEditCntrl.SetAlternateRowColors(dwColor);
		GetItem(IDC_DATA_INFO_TEXT).Text = _L("DR = Data Reader, C1 = Cursor 1, C2 = Cursor2 ");	///Jasmine 09/19/07 QA80-10385 LOCALIZATION_FOR_NEUTRAL_DIALOG
		return TRUE;
	}
	BOOL OnReady()
	{
		m_chkViewAsCols = GetItem(IDC_RG_CHECK1);
		m_chkViewAddWksCols = GetItem(IDC_RG_CHECK2);
		//----Jake 04/06/07 ADD_CHECKBOX_FOR_SHOW_LONG_AND_SHORT_NAME
		m_chkViewLongAndShortName = GetItem(IDC_RG_CHECK3);	
		//----end ADD_CHECKBOX_FOR_SHOW_LONG_AND_SHORT_NAME
		if(m_chkViewAsCols)
		{
			m_chkViewAsCols.Text = _L("Transpose");
			m_chkViewAsCols.Check = (DIC_TRANSPOSE & m_dwCntrl)?true:false;
		}
		if(m_chkViewAddWksCols)
		{
			m_chkViewAddWksCols.Text = _L("Show All Columns");
			m_chkViewAddWksCols.Check = (DIC_ALL_COLS & m_dwCntrl)?true:false;
		}		
		//----Jake 04/06/07 ADD_CHECKBOX_FOR_SHOW_LONG_AND_SHORT_NAME
		if(m_chkViewLongAndShortName)
		{
			m_chkViewLongAndShortName.Text = _L("Show Short and Long Name");
			m_chkViewLongAndShortName.Check = (DIC_LONG_SHORT_NAME & m_dwCntrl)?true:false;
		}
		//----end ADD_CHECKBOX_FOR_SHOW_LONG_AND_SHORT_NAME
		SetInitReady();
		ShowWindow(SW_NORMAL);
		notifyDataInfoOpen(true);//---- CPY 10/7/07 QA70-10484 FIX_DATA_READER_ONLY_FOR_DATA_INFO
		return true;
	}
	BOOL OnDestroy(void)
	{
		notifyDataInfoOpen(false);//---- CPY 10/7/07 QA70-10484 FIX_DATA_READER_ONLY_FOR_DATA_INFO

		/// Iris 03/26/2007 V8.0589 SAVE_CHECK_STATUS_INTO_REG
		dlg_save_to_registry(DLG_NAME, CTRL_TRANSPOSED_REG_VALNAME, m_chkViewAsCols.Check);
		dlg_save_to_registry(DLG_NAME, CTRL_SHOWALLCOLS_REG_VALNAME, m_chkViewAddWksCols.Check);
		//----Jake 04/06/07 ADD_CHECKBOX_FOR_SHOW_LONG_AND_SHORT_NAME
		dlg_save_to_registry(DLG_NAME, CTRL_SHOWLONGANDSHORTNAME_REG_VALNAME, m_chkViewLongAndShortName.Check);
		//----end ADD_CHECKBOX_FOR_SHOW_LONG_AND_SHORT_NAME
		///end SAVE_CHECK_STATUS_INTO_REG
		
		TreeEditDlg::OnDestroy();
		if(m_bDeleteOnDestroy)
		{
			if(s_pDataInfodlg)
			{
				delete this;
				s_pDataInfodlg = NULL;
			}
		}
		return true;
	}
	//------ CPY 2/29/2008 QA70-9856 DATA_READER_DATA_INFO_WIN_CLEAN_UP
	BOOL OnShow(BOOL bShow, uint nLParam)
	{
		///------ Folger 06/30/10 ORG-336 ADD_BACK_CURSOR_SUPPORT_FOR_DATA_INFO
		//if(!bShow)// user hiding it from button
		if ( IsAllowShow() && !bShow )
		///------ End ADD_BACK_CURSOR_SUPPORT_FOR_DATA_INFO
			LT_execute(";@DI=0");
		return true;
	}
	//------
	BOOL OnDlgResize(int nType, int cx, int cy)
	{
		if(!IsInitReady())
			return TRUE;
		//--------- add check box to top
		uint nButtonIDs[] = {IDC_RG_CHECK1, IDC_RG_CHECK2,0};//IDC_RG_CHECK3,	///Jasmine 05/28/07 to show all the check boxes, I've moved IDC_RG_CHECK3 to the next row
		int ny = ArrangeControlsLeftRight(nButtonIDs, GetControlGap(), GetControlGap());///Jasmine 01/10/07 MOVE_TO_SHOW_ALL_CHECK_BOX
		///Jasmine 10/10/06 ADD_INFO_TEXT
		RECT rr;
		GetClientRect(GetItem(IDC_DATA_INFO_TEXT), rr);
		fitGridToDlg(cx, cy, rr.bottom);//ny);
		///End ADD_INFO_TEXT
		return TRUE;
	}
	// get the information of GraphLayer
	BOOL OnActiveLayerChange( void )
	{
		
		if(!IsInitReady())
			return TRUE;
		return TRUE;
	}
	// get the name of the page
	BOOL OnActivePageChange( void )
	{
		if(!IsInitReady())
			return TRUE;
		
		double dval = 0;
		LT_get_var("@DI", &dval);
		if(dval > 0)
		{
			///Jake 06/04/07 DEBUG_FOR_WINDOW_FLASH_WHEN_CHANGE_DLG
			_update_active_page_cursors(true);
			_update_data_info_dlg(UDI_UPDATE, 0, 0, 0, 0, 0,true);
			///end DEBUG_FOR_WINDOW_FLASH_WHEN_CHANGE_DLG
		}
		//----Jake 04/04/07 HIDE_DATAINFO_WINDOW_WHEN_PAGE_CHANGE
        if(s_DataInfoBar)
			s_DataInfoBar.Visible=false;
        //---- end HIDE_DATAINFO_WINDOW_WHEN_PAGE_CHANGE
		return TRUE;
	}
	// change the selection 
	BOOL OnSelectionChange(void)
	{
		if(!IsInitReady())
			return TRUE;
		return TRUE;
	}
	BOOL 	OnToggleColView(Control oCntrl)
	{
		if(DIC_TRANSPOSE & m_dwCntrl)
			m_dwCntrl &= ~DIC_TRANSPOSE;
		else
			m_dwCntrl |= DIC_TRANSPOSE;
		
		SetInitReady(false);
		InitGrid();
		_update_data_info_dlg(UDI_REDRAW);
		SetInitReady(true);
		return true;
	}
	
	BOOL 	OnToggleShowAllCols(Control oCntrl)
	{
		if(IsShowAllCols())
			SetShowAllCols(false);
		else
			SetShowAllCols(true);

		SetInitReady(false);
		InitGrid();
		if(m_lastIndex >= 0)
		{
			Update(UDI_TRACKING_REUSE_OLD);
		}
		SetInitReady(true);
		return true;
	}	
	//----Jake 04/06/07 ADD_CHECKBOX_FOR_SHOW_LONG_AND_SHORT_NAME	
	BOOL OnToggleShowLongAndShortName(Control oCntrl)
	{
		if(IsShowLongAndShortName())
			SetShowLongAndShortName(false);
		else
			SetShowLongAndShortName(true);
		SetInitReady(false);
		InitGrid();
		if(m_lastIndex >= 0)
		{
			Update(UDI_TRACKING_REUSE_OLD);
			
		}
		SetInitReady(true);
		return true;
	}
    //----end ADD_CHECKBOX_FOR_SHOW_LONG_AND_SHORT_NAME    
private:	
	/// Iris 03/26/2007 V8.0589 SAVE_CHECK_STATUS_INTO_REG
	void loadContrlSettingFromReg(LPCSTR lpcszValName, DWORD dwBit)
	{
		DWORD	dwVal;
		if(dlg_load_registry(DLG_NAME, lpcszValName, dwVal))
		{		
			if(1 == dwVal)
				m_dwCntrl |= dwBit;
			else
				m_dwCntrl &= ~dwBit;
		}
	}
	///end SAVE_CHECK_STATUS_INTO_REG
	
	void fitGridToDlg(int cx, int cy, int ny)
	{
		Control cc = GetItem(IDC_GRID);
		RECT rect;
		rect.left = 0;
		rect.top = ny;
		rect.bottom = cy;
		rect.right = cx;
		MoveControl(cc, rect);
	}
	
	//---- CPY 10/7/07 QA70-10484 FIX_DATA_READER_ONLY_FOR_DATA_INFO
	void notifyDataInfoOpen(bool bOpen)
	{
		if(bOpen)
			LT_execute("@DIO=1");
		else
			LT_execute("@DIO=0");
	}
	//----

private:
	int	m_lastIndex;
	bool m_bNewStruct;
	DWORD m_dwCntrl;
	BOOL m_bDeleteOnDestroy;
	Button m_chkViewAsCols;
	Button m_chkViewAddWksCols;
	//----Jake 04/06/07 ADD_CHECKBOX_FOR_SHOW_LONG_AND_SHORT_NAME
	Button m_chkViewLongAndShortName;
	//----end ADD_CHECKBOX_FOR_SHOW_LONG_AND_SHORT_NAME
	int m_nLastPlot;		//------ Folger 10/27/07 SHOULD_UPDATE_DATA_INFO_DIALOG_WHEN_PLOT_CHANGE
};

// we want the same resource to be used as dialog
/*
void diDlg()
{
	DataInfoWindow myDlg;
	myDlg.DoModalEx(GetWindow());
}

void diDlgModless(BOOL bClose = false)
{
	static DataInfoWindow* s_pDlg;
	if(bClose)
	{
		if(s_pDlg)
		{
			Window winDlg = s_pDlg->GetWindow();
			if(winDlg)
				winDlg.SendMessage(WM_CLOSE);
			delete s_pDlg;
			s_pDlg = NULL;
		}
		return;
	}
	if(s_pDlg)
		diDlgModless(true);
	s_pDlg = new DataInfoWindow;
	
	s_pDlg->Create(GetWindow());
}
*/

// or as a control bar
BOOL dataInfoDlgBar(BOOL bClose)
{
//static    DataInfoDlg s_dlg;
	//DataInfoDlg *pdlg = new DataInfoDlg(TRUE);
	
	if(bClose)
	{
#ifdef DATAINFO_USE_DIALOG_BAR
		if(s_DataInfoBar)
			s_DataInfoBar.Destroy();
#else
		if(s_pDataInfodlg)
		{
			Window winDlg = s_pDataInfodlg->GetWindow();
			if(winDlg)
				winDlg.SendMessage(WM_CLOSE);
			delete s_pDataInfodlg;
			s_pDataInfodlg = NULL;
		}
#endif
		return false;
	}
	if(NULL == s_pDataInfodlg)
		s_pDataInfodlg = new DataInfoWindow(TRUE);

#ifdef DATAINFO_USE_DIALOG_BAR
	if(s_DataInfoBar)
	{
		if(s_DataInfoBar.Visible)
			return true;
		
		dataInfoDlgBar(true);
	}	
	//if(s_dlgBar.CreateControl(s_dlg))
	///------ Folger 06/30/10 ORG-336 ADD_BACK_CURSOR_SUPPORT_FOR_DATA_INFO
	//if(s_DataInfoBar.CreateControl(*s_pDataInfodlg, _L("Data Infos")))
	if(s_DataInfoBar.CreateControl(*s_pDataInfodlg, "Data Infos", s_pDataInfodlg->IsAllowShow() ? 0 : DIALOGBAR_CREATE_HIDDEN))
	///------ End ADD_BACK_CURSOR_SUPPORT_FOR_DATA_INFO
	{
	}
#else
	if(s_pDataInfodlg)
		s_pDataInfodlg->Create(GetWindow());
#endif //DATAINFO_USE_DIALOG_BAR

	if(s_pDataInfodlg)
	{
		s_pDataInfodlg->InitGrid();
		return true;
	}
	return false;
}


static DataInfoCursor s_DataReader, s_Cursor1, s_Cursor2;
static DataInfoCursor s_DRC1, s_C1C2;

///------ Folger 06/29/10 ORG-336 ADD_BACK_CURSOR_SUPPORT_FOR_DATA_INFO
DataInfoCursor&		DataCursor(int nType)
{
	switch ( nType )
	{
	case DIC_READER:
		return s_DataReader;

	case DIC_CURSOR1:
		return s_Cursor1;

	case DIC_CURSOR2:
		return s_Cursor2;

	case DIC_DRC1:
		return s_DRC1;

	case DIC_C1C2:
		return s_C1C2;

	default:
		O_A_FAIL;
		break;
	}

	DataInfoCursor	dummy;
	return dummy;
}
///------ End ADD_BACK_CURSOR_SUPPORT_FOR_DATA_INFO

static void _update_cursor_differences()
{
	if(s_DataReader.IsValid() && s_Cursor1.IsValid())
		s_DRC1.GetDifferences(s_Cursor1, s_DataReader);
	if(s_Cursor1.IsValid() && s_Cursor2.IsValid())
		s_C1C2.GetDifferences(s_Cursor1, s_Cursor2);	
}
static void _reset_data_range_and_cursors()
{
	s_DataReader.Reset();
	s_Cursor1.Reset();
	s_Cursor2.Reset();
	s_DRC1.Reset();
	s_C1C2.Reset();
}	
static bool _update_active_page_cursors(bool bPageChanged = false)///Jake 06/04/07 DEBUG_FOR_WINDOW_FLASH_WHEN_CHANGE_DLG
{
	_reset_data_range_and_cursors();
	int nCount = 0;
	vector<int> vnLayers;
	vector<uint> vnPlots, vnDataIndices;
	Page pg = Project.Pages();
	if(pg.IsValid() && pg.FindCursors(vnLayers, vnPlots, vnDataIndices))
	{
		for(int nCursor = 0; nCursor < vnLayers.GetSize(); nCursor++)
		{
			if(vnLayers[nCursor] >= 0)
			{
				_update_data_info_dlg(UDI_TRACKING, -1, nCursor, vnLayers[nCursor], vnPlots[nCursor], vnDataIndices[nCursor],bPageChanged);
				nCount++;
			}
		}
	}
	if(nCount)
		_update_cursor_differences();
	
	return nCount;
}

///------ Folger 07/02/10 ORG-436-P3 WRONG_DATA_READER_VALUE_WHEN_DOUBLE_CLICK_TO_ADD_CURSOR
static	BOOL	_is_allow_update_info_dlg()
{
	return s_pDataInfodlg && s_pDataInfodlg->IsAllowShow();
}
///------ End WRONG_DATA_READER_VALUE_WHEN_DOUBLE_CLICK_TO_ADD_CURSOR

static bool _update_data_info_dlg(int nMode, int nTool, int nCursor, int nLayer, int nPlot, int nDataIndex, bool bPageChanged)
{
	static int s_nCount = -1;
	if(UDI_RESET == nMode)
	{
		s_nCount = -1;
		return false;
	}

	///------ Folger 06/30/10 ORG-336 ADD_BACK_CURSOR_SUPPORT_FOR_DATA_INFO
	//bool bAllCols = s_pDataInfodlg->IsShowAllCols();
	////----Jake 04/06/07 ADD_CHECKBOX_FOR_SHOW_LONG_AND_SHORT_NAME
	//bool bLongAndShortName = s_pDataInfodlg->IsShowLongAndShortName();
	////----end ADD_CHECKBOX_FOR_SHOW_LONG_AND_SHORT_NAME
	bool bAllCols = s_pDataInfodlg ? s_pDataInfodlg->IsShowAllCols() : TRUE;
	bool bLongAndShortName = s_pDataInfodlg ? s_pDataInfodlg->IsShowLongAndShortName() : TRUE;
	///------ End ADD_BACK_CURSOR_SUPPORT_FOR_DATA_INFO
	if(UDI_REDRAW == nMode)
		s_nCount = -1;
		
	if(UDI_TRACKING == nMode)
	{
		if(0==nTool) // use current (last) indices of each cursor
		{
			//----Jake 04/06/07 ADD_CHECKBOX_FOR_SHOW_LONG_AND_SHORT_NAME
			s_DataReader.UpdateUsingLastIndex(bAllCols, bLongAndShortName);
			s_Cursor1.UpdateUsingLastIndex(bAllCols, bLongAndShortName);
			s_Cursor2.UpdateUsingLastIndex(bAllCols, bLongAndShortName);
			//----end ADD_CHECKBOX_FOR_SHOW_LONG_AND_SHORT_NAME
		}
		else
		{
			if(nTool < 0)
			{
				if(nCursor > 0)
					//----Jake 04/06/07 ADD_CHECKBOX_FOR_SHOW_LONG_AND_SHORT_NAME
					s_Cursor2.GetPlotWksInfo(nCursor, nLayer, nPlot, nDataIndex, bAllCols, bLongAndShortName);
				else
					s_Cursor1.GetPlotWksInfo(nCursor, nLayer, nPlot, nDataIndex, bAllCols, bLongAndShortName);
			}
			else if(nTool > 0)// nTool == 0 to reuse old cursor info
				s_DataReader.GetPlotWksInfo(-1, nLayer, nPlot, nDataIndex, bAllCols, bLongAndShortName);
			       //----end ADD_CHECKBOX_FOR_SHOW_LONG_AND_SHORT_NAME
		}
		_update_cursor_differences();			
	}
	
	//----Jake 04/11/07 FOR_DEBUG_IN_IR597_IN_EXP_04_09_07
	else if( UDI_UPDATE == nMode)
	{
		s_DataReader.GetPlotWksInfo(-1, nLayer, nPlot, nDataIndex, bAllCols, bLongAndShortName);
	}
	//----end FOR_DEBUG_IN_IR597_IN_EXP_04_09_07
	
	int nCount = 0;
	vector<string> vsCursor, vsBook, vsWks, vsPlot, vsName, vsVal;
	if(s_DataReader.IsValid())
		nCount += s_DataReader.Append(vsCursor, vsBook, vsWks, vsPlot, vsName, vsVal);
	if(s_Cursor1.IsValid())
		nCount += s_Cursor1.Append(vsCursor, vsBook, vsWks, vsPlot, vsName, vsVal);
	if(s_Cursor2.IsValid())
		nCount += s_Cursor2.Append(vsCursor, vsBook, vsWks, vsPlot, vsName, vsVal);
	if(s_DRC1.IsValid())
		nCount += s_DRC1.Append(vsCursor, vsBook, vsWks, vsPlot, vsName, vsVal);
	if(s_C1C2.IsValid())
		nCount += s_C1C2.Append(vsCursor, vsBook, vsWks, vsPlot, vsName, vsVal);

	///------ Folger 06/30/10 ORG-336 ADD_BACK_CURSOR_SUPPORT_FOR_DATA_INFO
	if ( !_is_allow_update_info_dlg() )
		return TRUE;
	///------ End ADD_BACK_CURSOR_SUPPORT_FOR_DATA_INFO

	//----jake 04/23/07 DEBUG_FOR_R602B_SHOW_DATAINFO_WHEN_CURSOR_MOVE
	if(s_DataInfoBar && !s_DataInfoBar.Visible && !bPageChanged)///Jake 06/04/07 DEBUG_FOR_WINDOW_FLASH_WHEN_CHANGE_DLG
		///------ Folger 06/29/10 ORG-336 ADD_BACK_CURSOR_SUPPORT_FOR_DATA_INFO
		//s_DataInfoBar.Visible = true;
		SET_DATAINFOBAR_VISIBLE;
	///------ End ADD_BACK_CURSOR_SUPPORT_FOR_DATA_INFO
	//----end DEBUG_FOR_R602B_SHOW_DATAINFO_WHEN_CURSOR_MOVE
		
	if(vsPlot.GetSize() > 0)
	{
		s_pDataInfodlg->BeforeUpdate();
		
		s_pDataInfodlg->ResetRows();///Jake 04/09/07 DEBUG_FOR_IR596H_IN_EXP_04_06_07
		
		if(nCount != s_nCount)
		{
			///Jake 04/09/07 DEBUG_FOR_IR596H_IN_EXP_04_06_07
			//s_pDataInfodlg->ResetRows();
			///end DEBUG_FOR_IR596H_IN_EXP_04_06_07
			
			s_nCount = nCount;
		}
		s_pDataInfodlg->SetColumn(DICOL_CURSOR, vsCursor);
		s_pDataInfodlg->SetColumn(DICOL_WKBOOK, vsBook);
		s_pDataInfodlg->SetColumn(DICOL_WKS, vsWks);
		s_pDataInfodlg->SetColumn(DICOL_PLOT, vsPlot);
		s_pDataInfodlg->SetColumn(DICOL_COL, vsName);
		s_pDataInfodlg->SetDirectUpdate(); // need to show value changes while moving 
		s_pDataInfodlg->SetColumn(DICOL_DATA, vsVal);
		s_pDataInfodlg->AfterUpdate();
		return true;
	}
	return false;
}

/// YuI 07/26/05 CENTRALIZE_TOOL_EVENTS
//---- CPY 2/22/2007 QA70-9290 ANNOTATION_TOOL_DEFAULT_TO_SHOW_XY
//#define	DEFAULT_DATAPLOT_ANNOTATION	_L("Annotation")

/// YuI 03/27/07 per Greg and Easwar request I am changing the default string
//	#define	DEFAULT_DATAPLOT_ANNOTATION	"x=$(x), y=$(y), i=$(i)"
#define	DEFAULT_DATAPLOT_ANNOTATION	"($(x), $(y))[$(i)]"
/// end YuI

/// YuI 04/06/09 QA70-13336 TERNARY_PLOT_ANNOTATION_SHOULD_SHOW_Z_VALUE
#define	DEFAULT_XYZ_DATAPLOT_ANNOTATION		"($(x), $(y), $(z))[$(i)]"
/// end TERNARY_PLOT_ANNOTATION_SHOULD_SHOW_Z_VALUE

//----
static BOOL	_add_annotation_to_data_plot(DataPlot& dp, int nPointIndex)
{
	GraphLayer gl;
	dp.GetParent(gl);
	if( !gl )
		return FALSE;
	
	GraphObject grAnnotation = gl.CreateGraphObject(GROT_TEXT);
	if( !grAnnotation )
		return FALSE;
	
	double dX;
	double dY;
	/// YuI 09/21/09 QA70-14346_P3 ANNOTATION_SCREWED_UP_IF_TERNARY_IS_SCALED
	//	if( !dp.GetDataPoint(nPointIndex, &dX, &dY) )
	//		return FALSE;
	double dZ;
	if( !dp.GetDataPoint(nPointIndex, &dX, &dY, &dZ) )
		return FALSE;
	
	BOOL bNormalizeNeeded = FALSE;
	/// end ANNOTATION_SCREWED_UP_IF_TERNARY_IS_SCALED
	
	/// YuI 04/06/09 QA70-13336 TERNARY_PLOT_ANNOTATION_SHOULD_SHOW_Z_VALUE
	BOOL bXYZText = FALSE;
	BOOL bShowConnector = TRUE;
	if( gl.GetCoordinateType() == FRAME_COOR_TERNARY )
	{
		bXYZText = TRUE;
		/// YuI 09/21/09 QA70-14346_P3 ANNOTATION_SCREWED_UP_IF_TERNARY_IS_SCALED
		bNormalizeNeeded = TRUE;
		/// end ANNOTATION_SCREWED_UP_IF_TERNARY_IS_SCALED	
	}
	
	int nPlotId = dp.GetPlotType();
	if( nPlotId == IDM_PLOT_TERNARY_CONTOUR || nPlotId == IDM_PLOT_3D_LINE || nPlotId == ID_3D_GRAPH_SCATTER || nPlotId == IDM_PLOT_TRI_CONTOUR || nPlotId == IDM_PLOT_XYZ_TRIANGULAR)
	{
		bXYZText = TRUE;
		bShowConnector = FALSE;
	}
	/// end TERNARY_PLOT_ANNOTATION_SHOULD_SHOW_Z_VALUE

	/// YuI 09/21/09 QA70-14346_P3 ANNOTATION_SCREWED_UP_IF_TERNARY_IS_SCALED
	if( IDM_PLOT_TERNARY_CONTOUR == nPlotId || IDM_PLOT_XYZ_TRIANGULAR == nPlotId )
	{
		bNormalizeNeeded = TRUE;
	}
	
	if( bNormalizeNeeded )
	{
		okutil_normalize_ternary_coordinates(&dX, &dY, &dZ);
	}
	/// end ANNOTATION_SCREWED_UP_IF_TERNARY_IS_SCALED

	/// YuI 04/06/09 QA70-13336 TERNARY_PLOT_ANNOTATION_SHOULD_SHOW_Z_VALUE
	//	grAnnotation.Text = DEFAULT_DATAPLOT_ANNOTATION;
	grAnnotation.Text = bXYZText ? DEFAULT_XYZ_DATAPLOT_ANNOTATION : DEFAULT_DATAPLOT_ANNOTATION;
	/// end TERNARY_PLOT_ANNOTATION_SHOULD_SHOW_Z_VALUE
	/// YuI 09/21/09 QA70-14346_P3 ANNOTATION_SCREWED_UP_IF_TERNARY_IS_SCALED
	//	grAnnotation.X = dX + grAnnotation.DX / 2;
	//	grAnnotation.Y = dY + grAnnotation.DY / 2;
	grAnnotation.X = dX;
	grAnnotation.Y = dY;
	if( !bNormalizeNeeded )
	{
		grAnnotation.X += grAnnotation.DX / 2;
		grAnnotation.Y += grAnnotation.DY / 2;
	}
	/// end ANNOTATION_SCREWED_UP_IF_TERNARY_IS_SCALED
	
	//---- CPY 2/22/2007 QA70-9290 ANNOTATION_TOOL_DEFAULT_TO_SHOW_XY
	grAnnotation.Attach = 2;//axis scale, can allow rescale to auto reposition better
	set_text_link_LT_var(grAnnotation, true, 16);
	//----
	
	/// YuI 11/27/06 QA70-9156 MORE_OPTIONS_TO_CONNECTING_OBJECTS
	//	dp.ConnectTo(grAnnotation, -1, nPointIndex, TRUE, FALSE);
	
	/// YuI 04/06/09 QA70-13336 TERNARY_PLOT_ANNOTATION_SHOULD_SHOW_Z_VALUE
	//	dp.ConnectTo(grAnnotation, -1, nPointIndex, TRUE, 0);
	dp.ConnectTo(grAnnotation, CTP_AUTO, nPointIndex, bShowConnector, 0);
	/// end ANNOTATION_SMARTER_TETHERING_POINT
	
	/// end TERNARY_PLOT_ANNOTATION_SHOULD_SHOW_Z_VALUE
	/// end MORE_OPTIONS_TO_CONNECTING_OBJECTS
	/// YuI 03/14/07 QA70-9490 CURSOR_ISSUES
	/// by Easwar's request keeping tool active
	//	Project.ResetTools();
	/// end CURSOR_ISSUES
	
	return TRUE;
}

static BOOL	_add_cursor_to_data_plot(DataPlot& dp, int nPointIndex)
{
	GraphLayer gl;
	dp.GetParent(gl);
	if( !gl )
		return FALSE;
	
	PolylineGraphObject grCursor;
	grCursor = (PolylineGraphObject) gl.CreateGraphObject(GROT_CURSOR);
	
	/// RVD 7/8/2010 org-479 FIX_CURSOR_3D_SCATTER_POSITION
	// cursor should never handle position as it is complicated in 3D
	// and unnecessary because it is always connected to dataplot
	/*
	double dX;
	double dY;
	double dZ;
	if( !dp.GetDataPoint(nPointIndex, &dX, &dY, &dZ) )
		return FALSE;
	
	/// YuI 10/05/09 QA70-14409 CURSOR_ON_TERNARY_PROBLEM
	if( gl.GetCoordinateType() == FRAME_COOR_TERNARY )
	{
		okutil_normalize_ternary_coordinates(&dX, &dY, &dZ);
	}
	/// end CURSOR_ON_TERNARY_PROBLEM

	vector vX;
	vector vY;
	vX.Add(dX);
	vY.Add(dY);
	grCursor.SetPoints(vX, vY);
	*/
	grCursor.ConnectTo(dp, nPointIndex, -1, FALSE, OCR_SITE1 | OCR_SITE2);
	/// end FIX_CURSOR_3D_SCATTER_POSITION
	
	/// YuI 11/27/06 QA70-9156 MORE_OPTIONS_TO_CONNECTING_OBJECTS
	//	grCursor.ConnectTo(dp, nPointIndex, -1, FALSE, TRUE);
	/// YuI 09/03/08 QA70-12127 INIFITE_INVALIDATE_ON_CURSOR_ADDITION
	// this call (legacy) is not really needed, although was harmless until recently
	// cursor is always connected to the nearest point upon the UpdateData (this way we can drag it by mouse)
	// so it is enough to set cursor coordinates and on first UpdateData it would connect to the plot and this ConnectTo would simply update
	// existing connection
	// some change (do not know where) has changed the order of execution so that now code comes here
	// before it has chance to properly connect cursor to plot
	//	grCursor.ConnectTo(dp, nPointIndex, -1, FALSE, OCR_SITE1 | OCR_SITE2);
	/// end INIFITE_INVALIDATE_ON_CURSOR_ADDITION
	/// end MORE_OPTIONS_TO_CONNECTING_OBJECTS

	/// RVD 7/8/2010 org-479 FIX_CURSOR_3D_SCATTER_POSITION
	// theme what for? cursor is using icon, not symbol
	/*
	TreeNode tr = grCursor.GetFormat(FPB_ALL, FOB_ALL, true, true);
	TreeNode trSymbol = tr.Root.Symbol;
	if( !trSymbol )
		return FALSE;
		
	trSymbol.Size.nVal = 15;
	trSymbol.Shape.nVal = 2;
	trSymbol.EdgeColor.nVal = 3;
	trSymbol.Interior.nVal = 4;//5;
	grCursor.ApplyFormat(tr, true, true);
	*/
	/// end FIX_CURSOR_3D_SCATTER_POSITION
	
	Project.ResetTools();
	Selection.Add(grCursor);
	return TRUE;
}

static int _on_tool_action(int nTool, int nPlot, UINT nDataIndex, int nLayer)
{
	// this code is for DataReader tool only
	if( nTool == OTT_DATA_READER )
	{
		Page pg = Project.Pages();
		if( !pg )
			return -1;
		
		GraphLayer ll = pg.Layers(nLayer);
		if( !ll )
			return -1;
		
		DataPlot dp = ll.DataPlots(nPlot);
		if( !dp )
			return -1;
		
		DataReaderTool dsTool;
		dsTool = Project.GetTool(OTT_DATA_READER);
		if( dsTool )
		{
			int nReturn = 0;
			int nToolMode = dsTool.GetMode();
			switch( nToolMode )
			{
			case 0:
				break;
				
			case 1:
				nReturn = _add_annotation_to_data_plot(dp, nDataIndex) ? 0 : -1;
				break;
				
			case 2:
				nReturn = _add_cursor_to_data_plot(dp, nDataIndex) ? 0 : -1;
				break;
			}
			
			return nReturn;
		}
	}
	
	return -1;
}

int	on_tool_event(int nTool, int nMsg, int nPlot, UINT nDataIndex, int nLayer)
{
	switch( nMsg )
	{
	case OE_TOOL_ACTION:
		return _on_tool_action(nTool, nPlot, nDataIndex, nLayer);
	}
	
	return -1;
}
/// end CENTRALIZE_TOOL_EVENTS

static BOOL	_is_data_info_related_message(int nMsg)
{
	//out_int("cursor msg = ", nMsg);
	switch( nMsg )
	{
	case OE_TOOL_START:
	case OE_TOOL_FINISH:
	case OE_TOOL_MOVE:
	case OE_TOOL_CLOSE: 	///Arvin 07/04/07 OPEN_OR_CLOSE_DATA_INFO_DLG
		return TRUE;
	}
	//out_int("not cursor msg = ", nMsg);
	
	return FALSE;
}
/// end CENTRALIZE_TOOL_EVENTS

///------ Folger 06/29/10 ORG-336 ADD_BACK_CURSOR_SUPPORT_FOR_DATA_INFO
static	void	__Reset_Cursors(int nCursor)
{
	if(0==nCursor)
	{
		s_Cursor1.Reset();
		s_DRC1.Reset();
		s_C1C2.Reset();
	}
	else if(1==nCursor)
	{
		s_Cursor2.Reset();
		s_C1C2.Reset();
	}
	else
	{
		_update_active_page_cursors();
	}
}
///------ End ADD_BACK_CURSOR_SUPPORT_FOR_DATA_INFO

// return 1 to abort tool
int DataInfoDlg(int nTool, int nMsg, int nPlot, UINT nDataIndex, int nLayer)
{
	/// YuI 07/26/05 CENTRALIZE_TOOL_EVENTS
	if( !_is_data_info_related_message(nMsg) )
		return on_tool_event(nTool, nMsg, nPlot, nDataIndex, nLayer);
	/// end CENTRALIZE_TOOL_EVENTS
	BOOL bIsDataReader = false;
	//if nTool < 0, then cursors
	//printf("nTool=%d, nMsg=%d, nPlot=%d, nRow = %d\n", nTool, nMsg, nPlot, nDataIndex);
	int nCursor = -1;
	if(nTool < 0)
	{
		nCursor = (nTool * -1) - 1;		
		// temp code
		if(nPlot > 1000) // something wrong
		{
			out_int("invalid cursor, changed to 0 for now, was ", nPlot);
			nPlot = 0;
		}
	}
	
	bool bInit = false;		//------ Folger 08/15/07 CORRECT_CONTROL_DISPLAY_FOR_BOTH_COLUMN_MATOBJ
	
	if( nMsg == OE_TOOL_START )
	{
		bIsDataReader = (nTool == 3)? true:false;
		if(bIsDataReader || nCursor>=0)
		{
			///------ Folger 06/29/10 ORG-336 ADD_BACK_CURSOR_SUPPORT_FOR_DATA_INFO
			__Reset_Cursors(-1);	/// force update Cursors
			///------ End ADD_BACK_CURSOR_SUPPORT_FOR_DATA_INFO

			if(NULL == s_pDataInfodlg)
				dataInfoDlgBar(false);
#ifdef DATAINFO_USE_DIALOG_BAR
			else if(!s_DataInfoBar.Visible)
				///------ Folger 06/29/10 ORG-336 ADD_BACK_CURSOR_SUPPORT_FOR_DATA_INFO
				//s_DataInfoBar.Visible = true;
				SET_DATAINFOBAR_VISIBLE;
				///------ End ADD_BACK_CURSOR_SUPPORT_FOR_DATA_INFO

#else
			if(s_pDataInfodlg)
				s_pDataInfodlg->ShowDialog(); // in case it was rollled up
#endif
		}
		nMsg = OE_TOOL_MOVE;		
		bInit = true;	//------ Folger 08/15/07 CORRECT_CONTROL_DISPLAY_FOR_BOTH_COLUMN_MATOBJ
	}
	else if(nMsg == OE_TOOL_FINISH)
	{
		///------ Folger 07/02/10 ORG-436-P3 WRONG_DATA_READER_VALUE_WHEN_DOUBLE_CLICK_TO_ADD_CURSOR
		if ( _is_allow_update_info_dlg() )
		///------ End WRONG_DATA_READER_VALUE_WHEN_DOUBLE_CLICK_TO_ADD_CURSOR
			__Reset_Cursors(nCursor);
		if(!s_DataReader.IsValid() && !s_Cursor1.IsValid() && !s_Cursor2.IsValid() && s_pDataInfodlg)
		{
#ifdef DATAINFO_USE_DIALOG_BAR
			if(s_DataInfoBar.IsFloating())
				dataInfoDlgBar(true);
			else
				s_pDataInfodlg->Reset();
#else
				dataInfoDlgBar(true);
#endif
		}
		else
		{
			///------ Folger 07/02/10 ORG-436-P3 WRONG_DATA_READER_VALUE_WHEN_DOUBLE_CLICK_TO_ADD_CURSOR
			if ( _is_allow_update_info_dlg() )
			///------ End WRONG_DATA_READER_VALUE_WHEN_DOUBLE_CLICK_TO_ADD_CURSOR
				_update_data_info_dlg();
		}
		return 0;
	}
	///Arvin 07/04/07 OPEN_OR_CLOSE_DATA_INFO_DLG
	else if(nMsg == OE_TOOL_CLOSE)
	{
		dataInfoDlgBar(true);
	}
	///end OPEN_OR_CLOSE_DATA_INFO_DLG
	if(nMsg == OE_TOOL_MOVE)
	{
		if(s_pDataInfodlg)
		{		//------ Folger 08/15/07 CORRECT_CONTROL_DISPLAY_FOR_BOTH_COLUMN_MATOBJ
			s_pDataInfodlg->Update(UDI_TRACKING, nTool, nCursor, nLayer, nPlot, nDataIndex);
		//------ Folger 08/15/07 CORRECT_CONTROL_DISPLAY_FOR_BOTH_COLUMN_MATOBJ
			if (bInit)
				s_pDataInfodlg->SetControlDisplay(s_DataReader.GetPlotSrcType() == EXIST_WKS);
		}
		//------ End CORRECT_CONTROL_DISPLAY_FOR_BOTH_COLUMN_MATOBJ
		///------ Folger 06/29/10 ORG-336 ADD_BACK_CURSOR_SUPPORT_FOR_DATA_INFO
		if ( s_DataReader.IsValid() )
		{
			static	int		l_nPlotUID = 0;
			int				nIndex = -1;
			int				nPlotUID = s_DataReader.GetLastPlotUID(&nIndex);
			///------ Folger 09/06/2010 ORG-960 DATA_INFO_FAILED_TO_READ_CURSOR_INFO_WHEN_SWITCHING_DATA_PLOT
			if ( 0 == nPlotUID )		/// just in case s_DataReader is reseted
			{
				nPlotUID = l_nPlotUID;
			}
			else
			{
				l_nPlotUID = nPlotUID;
			}
			///------ End DATA_INFO_FAILED_TO_READ_CURSOR_INFO_WHEN_SWITCHING_DATA_PLOT
			if ( nIndex < 0 )
			{
				nIndex = 0;
			}
			UpdateDataInfoWindow(nPlotUID, nIndex);
		}
		///------ End ADD_BACK_CURSOR_SUPPORT_FOR_DATA_INFO
	}
	else
	{
		// other messages
		//printf("tool = %d, msg = %d\n", nTool, nMsg);
	}
	
	return 0;
}

bool get_dataplot_value(int nColDesign, DataPlotStrings& dps, int nRow, double& x)
{
	LPCSTR lpcsz = get_plot_dataset_ptr(&dps, nColDesign);
	string str = lpcsz;
	if(str.IsEmpty() )
		return false;
		
	Dataset ds(str);
	//------ Folger 10/27/07 FIX_BUG_WHEN_INITIALIZE_DATASET_WITH_COLUMN_OF_NON_NUMERIC
	if (!ds.IsValid())
	{
		x = NANUM;
		return true;
	}
	//------ End FIX_BUG_WHEN_INITIALIZE_DATASET_WITH_COLUMN_OF_NON_NUMERIC
	if(nRow < 0 || nRow >= ds.GetSize())
			return false;
	
	x = ds[nRow];
	return true;
}

///------ Folger 07/02/10 ORG-436-P4 DATA_INFO_CURSOR_FAILED_TO_GET_CATEGORICAL_DATA
//int get_xyz_values(DataPlotStrings& dps, int nRow, double& x, double& y, double& z)
//{
	//if(get_dataplot_value(COLDESIG_X, dps, nRow, x))
	//{
		//if(get_dataplot_value(COLDESIG_Y, dps, nRow, y))
		//{
			//if(get_dataplot_value(COLDESIG_Z, dps, nRow, z))
				//return 3;
			//
			//return 2;
		//}
	//}
	//return 0;
//}
int					get_xyz_values(DataPlot& dp, int nRow, double& x, double& y, double& z)
{
	z = NANUM;
	if ( !dp.GetDataPoint(nRow, &x, &y, &z, NULL) )
		return 0;
	
	///------ Folger 09/03/2010 ORG-502-P7 DATA_INFO_FAILED_TO_SHOW_CURSOR_DIFERENCE_Z_VALUE
	//return is_missing_value(z) ? 3 : 2;
	return is_missing_value(z) ? 2 : 3;
	///------ End DATA_INFO_FAILED_TO_SHOW_CURSOR_DIFERENCE_Z_VALUE
}
///------ End DATA_INFO_CURSOR_FAILED_TO_GET_CATEGORICAL_DATA