diff options
Diffstat (limited to 'libs/mTextControl/src/dataobject.cpp')
-rw-r--r-- | libs/mTextControl/src/dataobject.cpp | 276 |
1 files changed, 276 insertions, 0 deletions
diff --git a/libs/mTextControl/src/dataobject.cpp b/libs/mTextControl/src/dataobject.cpp new file mode 100644 index 0000000000..1d14d28afb --- /dev/null +++ b/libs/mTextControl/src/dataobject.cpp @@ -0,0 +1,276 @@ +// +// DATAOBJECT.CPP +// +// Implementation of the IDataObject COM interface +// +// By J Brown 2004 +// +// www.catch22.net +// + +//#define STRICT + +#include "stdafx.h" + +const ULONG MAX_FORMATS = 100; + +HRESULT CreateEnumFormatEtc(UINT nNumFormats, FORMATETC *pFormatEtc, IEnumFORMATETC **ppEnumFormatEtc); + +class CDataObject : public IDataObject +{ +public: + // + // IUnknown members + // + HRESULT __stdcall QueryInterface(REFIID iid, void ** ppvObject); + ULONG __stdcall AddRef(void); + ULONG __stdcall Release(void); + + // + // IDataObject members + // + HRESULT __stdcall GetData(FORMATETC *pFormatEtc, STGMEDIUM *pMedium); + HRESULT __stdcall GetDataHere(FORMATETC *pFormatEtc, STGMEDIUM *pMedium); + HRESULT __stdcall QueryGetData(FORMATETC *pFormatEtc); + HRESULT __stdcall GetCanonicalFormatEtc(FORMATETC *pFormatEct, FORMATETC *pFormatEtcOut); + HRESULT __stdcall SetData(FORMATETC *pFormatEtc, STGMEDIUM *pMedium, BOOL fRelease); + HRESULT __stdcall EnumFormatEtc(DWORD dwDirection, IEnumFORMATETC **ppEnumFormatEtc); + HRESULT __stdcall DAdvise(FORMATETC *pFormatEtc, DWORD advf, IAdviseSink *pAdvSink, DWORD *pdwConnection); + HRESULT __stdcall DUnadvise(DWORD dwConnection); + HRESULT __stdcall EnumDAdvise(IEnumSTATDATA **ppEnumAdvise); + + // + // Constructor / Destructor + // + CDataObject(const FORMATETC *fmt, const STGMEDIUM *stgmed, int count); + ~CDataObject(); + +private: + + int LookupFormatEtc(FORMATETC *pFormatEtc); + + // + // any private members and functions + // + LONG m_lRefCount; + + FORMATETC *m_pFormatEtc; + STGMEDIUM *m_pStgMedium; + LONG m_nNumFormats; + +}; + +// +// Constructor +// +CDataObject::CDataObject(const FORMATETC *fmtetc, const STGMEDIUM *stgmed, int count) +{ + m_lRefCount = 1; + m_nNumFormats = count; + + m_pFormatEtc = new FORMATETC[count]; + m_pStgMedium = new STGMEDIUM[count]; + + for (int i = 0; i < count; i++) { + m_pFormatEtc[i] = fmtetc[i]; + m_pStgMedium[i] = stgmed[i]; + } +} + +// +// Destructor +// +CDataObject::~CDataObject() +{ + // cleanup + for (int i = 0; i < m_nNumFormats; i++) { + // ReleaseStgMedium(&m_pStgMedium[i]); + } + + if (m_pFormatEtc) delete[] m_pFormatEtc; + if (m_pStgMedium) delete[] m_pStgMedium; +} + +// +// IUnknown::AddRef +// +ULONG __stdcall CDataObject::AddRef(void) +{ + // increment object reference count + return InterlockedIncrement(&m_lRefCount); +} + +// +// IUnknown::Release +// +ULONG __stdcall CDataObject::Release(void) +{ + // decrement object reference count + LONG count = InterlockedDecrement(&m_lRefCount); + + if (count == 0) { + delete this; + return 0; + } + + return count; +} + +// +// IUnknown::QueryInterface +// +HRESULT __stdcall CDataObject::QueryInterface(REFIID iid, void **ppvObject) +{ + // check to see what interface has been requested + if (iid == IID_IDataObject || iid == IID_IUnknown) { + AddRef(); + *ppvObject = this; + return S_OK; + } + + *ppvObject = nullptr; + return E_NOINTERFACE; +} + +int CDataObject::LookupFormatEtc(FORMATETC *pFormatEtc) +{ + for (int i = 0; i < m_nNumFormats; i++) { + if ((pFormatEtc->tymed & m_pFormatEtc[i].tymed) && + pFormatEtc->cfFormat == m_pFormatEtc[i].cfFormat && + pFormatEtc->dwAspect == m_pFormatEtc[i].dwAspect) { + return i; + } + } + + return -1; +} + +// +// IDataObject::GetData +// +HRESULT __stdcall CDataObject::GetData(FORMATETC *pFormatEtc, STGMEDIUM *pMedium) +{ + int idx; + + // + // try to match the requested FORMATETC with one of our supported formats + // + if ((idx = LookupFormatEtc(pFormatEtc)) == -1) { + return DV_E_FORMATETC; + } + + // + // found a match! transfer the data into the supplied storage-medium + // + pMedium->tymed = m_pFormatEtc[idx].tymed; + pMedium->pUnkForRelease = nullptr; + + switch (pMedium->tymed) { + case TYMED_HGLOBAL: + case TYMED_GDI: + case TYMED_ENHMF: + // pMedium->hBitmap = (HBITMAP)OleDuplicateData(m_pStgMedium[idx].hBitmap, pFormatEtc->cfFormat, 0); + pMedium->hBitmap = m_pStgMedium[idx].hBitmap; + break; + + default: + return DV_E_FORMATETC; + } + if (pMedium->hBitmap == nullptr) return STG_E_MEDIUMFULL; + + return S_OK; +} + +// +// IDataObject::GetDataHere +// +HRESULT __stdcall CDataObject::GetDataHere(FORMATETC *, STGMEDIUM *) +{ + // GetDataHere is only required for IStream and IStorage mediums + // It is an error to call GetDataHere for things like HGLOBAL and other clipboard formats + // + // OleFlushClipboard + // + return DATA_E_FORMATETC; +} + +// +// IDataObject::QueryGetData +// +// Called to see if the IDataObject supports the specified format of data +// +HRESULT __stdcall CDataObject::QueryGetData(FORMATETC *pFormatEtc) +{ + return (LookupFormatEtc(pFormatEtc) == -1) ? DV_E_FORMATETC : S_OK; +} + +// +// IDataObject::GetCanonicalFormatEtc +// +HRESULT __stdcall CDataObject::GetCanonicalFormatEtc(FORMATETC *, FORMATETC *pFormatEtcOut) +{ + // Apparently we have to set this field to NULL even though we don't do anything else + pFormatEtcOut->ptd = nullptr; + return E_NOTIMPL; +} + +// +// IDataObject::SetData +// +HRESULT __stdcall CDataObject::SetData(FORMATETC *, STGMEDIUM *, BOOL) +{ + return E_NOTIMPL; +} + +// +// IDataObject::EnumFormatEtc +// +HRESULT __stdcall CDataObject::EnumFormatEtc(DWORD dwDirection, IEnumFORMATETC **ppEnumFormatEtc) +{ + if (dwDirection == DATADIR_GET) { + // for Win2k+ you can use the SHCreateStdEnumFmtEtc API call, however + // to support all Windows platforms we need to implement IEnumFormatEtc ourselves. + return CreateEnumFormatEtc(m_nNumFormats, m_pFormatEtc, ppEnumFormatEtc); + } + else { + // the direction specified is not support for drag+drop + return E_NOTIMPL; + } +} + +// +// IDataObject::DAdvise +// +HRESULT __stdcall CDataObject::DAdvise(FORMATETC *, DWORD, IAdviseSink *, DWORD *) +{ + return OLE_E_ADVISENOTSUPPORTED; +} + +// +// IDataObject::DUnadvise +// +HRESULT __stdcall CDataObject::DUnadvise(DWORD) +{ + return OLE_E_ADVISENOTSUPPORTED; +} + +// +// IDataObject::EnumDAdvise +// +HRESULT __stdcall CDataObject::EnumDAdvise(IEnumSTATDATA **) +{ + return OLE_E_ADVISENOTSUPPORTED; +} + +// +// Helper function +// +HRESULT CreateDataObject(const FORMATETC *fmtetc, const STGMEDIUM *stgmeds, UINT count, IDataObject **ppDataObject) +{ + if (ppDataObject == nullptr) + return E_INVALIDARG; + + *ppDataObject = new CDataObject(fmtetc, stgmeds, count); + + return (*ppDataObject) ? S_OK : E_OUTOFMEMORY; +} |