TDCARR.H

//+----------------------------------------------------------------------- 
//
// TDC Array
// Copyright (C) Microsoft Corporation, 1996, 1997
//
// File: TDCArr.h
//
// Contents: Declaration of the CTDCArr class.
// This class forms the heart of the Tabular Data Control.
// It provides the core 2D array of variant values, plus
// a (possibly filtered/sorted) view of this data for
// presentation through an ISimpleTabularData interface.
//
//------------------------------------------------------------------------

// ;begin_internal
#ifndef TDC_SKEL
// ;end_internal
#include "tarray.h"

//------------------------------------------------------------------------
//
// CTDCCell
//
// This class represents a cell value within the 2D TDC control
//
//------------------------------------------------------------------------

class CTDCCell : public VARIANT
{
public:
CTDCCell()
{
VariantInit(this);
}
~CTDCCell()
{
clear();
}
void clear()
{
VariantClear(this);
}
};

//------------------------------------------------------------------------
//
// TDCDateFmt
//
// This enum represents the 6 meaningful ways to format dates
//
//------------------------------------------------------------------------
typedef enum
{
TDCDF_NULL,
TDCDF_DMY,
TDCDF_DYM,
TDCDF_MDY,
TDCDF_MYD,
TDCDF_YMD,
TDCDF_YDM,
}
TDCDateFmt;

//------------------------------------------------------------------------
//
// CTDCColInfo
//
// This class represents type/formatting information for a column
//
//------------------------------------------------------------------------

class CTDCColInfo
{
public:
VARTYPE vtType;
TDCDateFmt datefmt; // Format string for dates

CTDCColInfo()
{
vtType = VT_EMPTY;
}
};
// ;begin_internal
#endif // TDC_SKEL
// ;end_internal

//------------------------------------------------------------------------
//
// CTDCSortCriterion
//
// This class represents a sorting criterion (sort column and direction)
//
//------------------------------------------------------------------------

class CTDCSortCriterion
{
public:
LONG m_iSortCol;
boolean m_fSortAscending;
CTDCSortCriterion *m_pNext;

CTDCSortCriterion()
{
m_pNext = NULL;
}
~CTDCSortCriterion()
{
if (m_pNext != NULL)
delete m_pNext;
}
};

//------------------------------------------------------------------------
//
// CTDCFilterNode
//
// This class represents a tree node in a filter query.
//
//------------------------------------------------------------------------

class CTDCFilterNode
{
public:
enum NODE_OP
{
NT_AND,
NT_OR,
NT_EQ,
NT_NE,
NT_LT,
NT_GT,
NT_LE,
NT_GE,
NT_ATOM,
NT_NULL,
};
NODE_OP m_type;
CTDCFilterNode *m_pLeft; // NT_AND ... NT_GE
CTDCFilterNode *m_pRight; // NT_AND ... NT_GE
LONG m_iCol; // NT_ATOM, +ve column #, 0 means fixed value
VARIANT m_value; // NT_ATOM, m_iCol == 0: optional fixed value
VARTYPE m_vt; // NT_EQ ... NT_ATOM - type of comparison/atom
boolean m_fWildcard; // True for string literals with '*' wildcard

CTDCFilterNode()
{
m_type = NT_NULL;
m_pLeft = NULL;
m_pRight = NULL;
m_iCol = 0;
m_vt = VT_EMPTY;
VariantInit(&m_value);
}
~CTDCFilterNode()
{
if (m_pLeft != NULL)
delete m_pLeft;
if (m_pRight != NULL)
delete m_pRight;
VariantClear(&m_value);
}
};

class CEventBroker;

//------------------------------------------------------------------------
//
// CTDCArr
//
//------------------------------------------------------------------------

class CTDCArr : public OLEDBSimpleProvider,
public CTDCFieldSink
{
public:
STDMETHOD(QueryInterface) (REFIID, LPVOID FAR*);
STDMETHOD_(ULONG,AddRef) (THIS);
STDMETHOD_(ULONG,Release) (THIS);

CTDCArr();
STDMETHOD(Init)(CEventBroker *pEventBroker, IMultiLanguage *pML);

// CTDCFieldSink methods
//
STDMETHOD(AddField)(LPWCH pwch, DWORD dwSize);
STDMETHOD(EOLN)();
STDMETHOD(EOF)();

// TDC control methods
//
STDMETHOD(StartDataLoad)(boolean fUseHeader,
BSTR bstrSortExpr, BSTR bstrFilterExpr, LCID lcid,
CComObject<CMyBindStatusCallback<CTDCCtl> > *pBSC,
boolean fAppend, boolean fCaseSensitive);
STDMETHOD(SetSortFilterCriteria)(BSTR bstrSortExpr, BSTR bstrFilterExpr,
boolean fCaseSensitive);

// OLEDBSimpleProvider methods
//
STDMETHOD(getRowCount)(LONG *pcRows);
STDMETHOD(getColumnCount)(LONG *pcCols);
STDMETHOD(getRWStatus)(LONG iRow, LONG iCol, OSPRW *prwStatus);
STDMETHOD(getVariant)(LONG iRow, LONG iCol, OSPFORMAT format, VARIANT *pVar);
STDMETHOD(setVariant)(LONG iRow, LONG iCol, OSPFORMAT format, VARIANT Var);
STDMETHOD(getLocale)(BSTR *pbstrLocale);
STDMETHOD(deleteRows)(LONG iRow, LONG cRows, LONG *pcRowsDeleted);
STDMETHOD(insertRows)(LONG iRow, LONG cRows, LONG *pcRowsInserted);
STDMETHOD(find) (LONG iRowStart, LONG iCol, VARIANT val,
OSPFIND findFlags, OSPCOMP compType, LONG *piRowFound);
STDMETHOD(addOLEDBSimpleProviderListener)(OLEDBSimpleProviderListener *pospIListener);
STDMETHOD(removeOLEDBSimpleProviderListener)(OLEDBSimpleProviderListener *pospIListener);
STDMETHOD(getEstimatedRows)(LONG *pcRows);
STDMETHOD(isAsync)(BOOL *pbAsync);
STDMETHOD(stopTransfer)();
// ;begin_internal
STDMETHOD(DeleteColumns)(LONG iCol, LONG cCols, LONG *pcColsDeleted);
STDMETHOD(InsertColumns)(LONG iCol, LONG cCols, LONG *pcColsInserted);
// ;end_internal

// This member is used during a sort operation
//
int SortComp(LONG iRow1, LONG iRow2);

enum LOAD_STATE
{
LS_UNINITIALISED,
LS_LOADING_HEADER_UNAVAILABLE,
LS_LOADING_HEADER_AVAILABLE,
LS_LOADED,
};
LOAD_STATE GetLoadState() { return m_state; }
void SetIsAsync(BOOL fAsync) { m_fAsync = fAsync; }
CEventBroker *m_pEventBroker;
IMultiLanguage *m_pML;

private:


ULONG m_cRef; // interface reference count
LOAD_STATE m_state;
LCID m_lcid; // Default user LCID
LCID m_lcidRead; // User LCID corresponding to LANGUAGE property

~CTDCArr();

// ;begin_internal
#ifndef TDC_SKEL
// ;end_internal
boolean m_fSortFilterDisrupted;
STDMETHOD(ApplySortFilterCriteria)();

// These members are used during a sort operation
//
CTDCSortCriterion *m_pSortList;
BSTR m_bstrSortExpr;
HRESULT CreateSortList(BSTR bstrSortCols);

// These members are used during a filter operation
//
CTDCFilterNode *m_pFilterTree;
BSTR m_bstrFilterExpr;
boolean EvalDataRow(LONG iRow, CTDCFilterNode *pNode);
CTDCFilterNode *FilterParseComplex(LPWCH *ppwch, HRESULT *phr);
CTDCFilterNode *FilterParseSimple(LPWCH *ppwch, HRESULT *phr);
CTDCFilterNode *FilterParseAtom(LPWCH *ppwch, HRESULT *phr);
LONG m_fLastFilter;
// ;begin_internal
#endif // TDC_SKEL
// ;end_internal

// These members are used during a load
//
boolean m_fUseHeader;
boolean m_fSkipRow;
LONG m_iCurrRow;
LONG m_iCurrCol;

LONG m_iDataRows;
LONG m_iFilterRows;
LONG m_iCols;
boolean m_fCaseSensitive;

BOOL m_fAsync; // TRUE iff Async

// These methods and members form the internal array implementation
//
inline boolean fValidDataRow(LONG iRow);
inline boolean fValidFilterRow(LONG iRow);
inline boolean fValidCol(LONG iCol);
inline boolean fValidDataCell(LONG iRow, LONG iCol);
inline boolean fValidFilterCell(LONG iRow, LONG iCol);
inline CTDCCell *GetDataCell(LONG iRow, LONG iCol);
inline CTDCCell *GetFilterCell(LONG iRow, LONG iCol);
inline CTDCColInfo *GetColInfo(LONG iCol);
LONG CalcDataRows();
LONG CalcFilterRows();
LONG CalcCols();

TSTDArray<TSTDArray<CTDCCell> *> m_arrparrCells;
TSTDArray<TSTDArray<CTDCCell> *> m_arrparrFilter;
TSTDArray<CTDCColInfo> m_arrColInfo;

// Misc internal methods
//
LONG FindCol(BSTR bstrColName);
HRESULT GetVariantBSTR(VARIANT *pv, BSTR *pbstr, boolean *pfAllocated);
void RenumberColumnHeadings();
HRESULT CreateNumberedColumnHeadings();
HRESULT ParseColumnHeadings();
HRESULT VariantFromBSTR(VARIANT *pv, BSTR bstr, CTDCColInfo *pColInfo, LCID);
int VariantComp(VARIANT *pVar1, VARIANT *pVar2, VARTYPE type,
boolean fCaseSensitive);
int InsertionSortHelper(int iRow);
};

inline boolean CTDCArr::fValidDataRow(LONG iRow)
{
return iRow >= 0 && iRow <= m_iDataRows;
}

inline boolean CTDCArr::fValidFilterRow(LONG iRow)
{
return iRow >= 0 && iRow <= m_iFilterRows;
}

inline boolean CTDCArr::fValidCol(LONG iCol)
{
return iCol >= 1 && iCol <= m_iCols;
}

inline boolean CTDCArr::fValidDataCell(LONG iRow, LONG iCol)
{
return fValidDataRow(iRow) && fValidCol(iCol);
}

inline boolean CTDCArr::fValidFilterCell(LONG iRow, LONG iCol)
{
return fValidFilterRow(iRow) && fValidCol(iCol);
}

// ;begin_internal
#ifndef TDC_SKEL
// ;end_internal
inline CTDCCell *CTDCArr::GetDataCell(LONG iRow, LONG iCol)
{
return &((*m_arrparrCells[iRow])[iCol - 1]);
}

inline CTDCColInfo *CTDCArr::GetColInfo(LONG iCol)
{
return &m_arrColInfo[iCol - 1];
}

inline CTDCCell *CTDCArr::GetFilterCell(LONG iRow, LONG iCol)
{
return &((*m_arrparrFilter[iRow])[iCol - 1]);
}
// ;begin_internal
#endif // TDC_SKEL
// ;end_internal