From 4283465f23806ae4b8ad7344949f55698c16a203 Mon Sep 17 00:00:00 2001 From: watcherhd Date: Thu, 21 Apr 2011 20:19:47 +0000 Subject: MTextControl - text render API for different plugins git-svn-id: http://miranda-plugins.googlecode.com/svn/trunk@12 e753b5eb-9565-29b2-b5c5-2cc6f99dfbcb --- mTextControl/src/enumformat.cpp | 232 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 232 insertions(+) create mode 100644 mTextControl/src/enumformat.cpp (limited to 'mTextControl/src/enumformat.cpp') diff --git a/mTextControl/src/enumformat.cpp b/mTextControl/src/enumformat.cpp new file mode 100644 index 0000000..7daac15 --- /dev/null +++ b/mTextControl/src/enumformat.cpp @@ -0,0 +1,232 @@ +// +// ENUMFORMAT.CPP +// +// By J Brown 2004 +// +// www.catch22.net +// +// Implementation of the IEnumFORMATETC interface +// +// For Win2K and above look at the SHCreateStdEnumFmtEtc API call!! +// +// Apparently the order of formats in an IEnumFORMATETC object must be +// the same as those that were stored in the clipboard +// +// + +//#define STRICT + +#include "headers.h" + +class CEnumFormatEtc : public IEnumFORMATETC +{ +public: + + // + // IUnknown members + // + HRESULT __stdcall QueryInterface (REFIID iid, void ** ppvObject); + ULONG __stdcall AddRef (void); + ULONG __stdcall Release (void); + + // + // IEnumFormatEtc members + // + HRESULT __stdcall Next (ULONG celt, FORMATETC * rgelt, ULONG * pceltFetched); + HRESULT __stdcall Skip (ULONG celt); + HRESULT __stdcall Reset (void); + HRESULT __stdcall Clone (IEnumFORMATETC ** ppEnumFormatEtc); + + // + // Construction / Destruction + // + CEnumFormatEtc(FORMATETC *pFormatEtc, int nNumFormats); + ~CEnumFormatEtc(); + +private: + + LONG m_lRefCount; // Reference count for this COM interface + ULONG m_nIndex; // current enumerator index + ULONG m_nNumFormats; // number of FORMATETC members + FORMATETC * m_pFormatEtc; // array of FORMATETC objects +}; + +// +// "Drop-in" replacement for SHCreateStdEnumFmtEtc. Called by CDataObject::EnumFormatEtc +// +HRESULT CreateEnumFormatEtc(UINT nNumFormats, FORMATETC *pFormatEtc, IEnumFORMATETC **ppEnumFormatEtc) +{ + if(nNumFormats == 0 || pFormatEtc == 0 || ppEnumFormatEtc == 0) + return E_INVALIDARG; + + *ppEnumFormatEtc = new CEnumFormatEtc(pFormatEtc, nNumFormats); + + return (*ppEnumFormatEtc) ? S_OK : E_OUTOFMEMORY; +} + +// +// Helper function to perform a "deep" copy of a FORMATETC +// +static void DeepCopyFormatEtc(FORMATETC *dest, FORMATETC *source) +{ + // copy the source FORMATETC into dest + *dest = *source; + + if(source->ptd) + { + // allocate memory for the DVTARGETDEVICE if necessary + dest->ptd = (DVTARGETDEVICE*)CoTaskMemAlloc(sizeof(DVTARGETDEVICE)); + + // copy the contents of the source DVTARGETDEVICE into dest->ptd + *(dest->ptd) = *(source->ptd); + } +} + +// +// Constructor +// +CEnumFormatEtc::CEnumFormatEtc(FORMATETC *pFormatEtc, int nNumFormats) +{ + m_lRefCount = 1; + m_nIndex = 0; + m_nNumFormats = nNumFormats; + m_pFormatEtc = new FORMATETC[nNumFormats]; + + // copy the FORMATETC structures + for(int i = 0; i < nNumFormats; i++) + { + DeepCopyFormatEtc(&m_pFormatEtc[i], &pFormatEtc[i]); + } +} + +// +// Destructor +// +CEnumFormatEtc::~CEnumFormatEtc() +{ + if(m_pFormatEtc) + { + for(ULONG i = 0; i < m_nNumFormats; i++) + { + if(m_pFormatEtc[i].ptd) + CoTaskMemFree(m_pFormatEtc[i].ptd); + } + + delete[] m_pFormatEtc; + } +} + +// +// IUnknown::AddRef +// +ULONG __stdcall CEnumFormatEtc::AddRef(void) +{ + // increment object reference count + return InterlockedIncrement(&m_lRefCount); +} + +// +// IUnknown::Release +// +ULONG __stdcall CEnumFormatEtc::Release(void) +{ + // decrement object reference count + LONG count = InterlockedDecrement(&m_lRefCount); + + if(count == 0) + { + delete this; + return 0; + } + else + { + return count; + } +} + +// +// IUnknown::QueryInterface +// +HRESULT __stdcall CEnumFormatEtc::QueryInterface(REFIID iid, void **ppvObject) +{ + // check to see what interface has been requested + if(iid == IID_IEnumFORMATETC || iid == IID_IUnknown) + { + AddRef(); + *ppvObject = this; + return S_OK; + } + else + { + *ppvObject = 0; + return E_NOINTERFACE; + } +} + +// +// IEnumFORMATETC::Next +// +// If the returned FORMATETC structure contains a non-null "ptd" member, then +// the caller must free this using CoTaskMemFree (stated in the COM documentation) +// +HRESULT __stdcall CEnumFormatEtc::Next(ULONG celt, FORMATETC *pFormatEtc, ULONG * pceltFetched) +{ + ULONG copied = 0; + + // validate arguments + if(celt == 0 || pFormatEtc == 0) + return E_INVALIDARG; + + // copy FORMATETC structures into caller's buffer + while(m_nIndex < m_nNumFormats && copied < celt) + { + DeepCopyFormatEtc(&pFormatEtc[copied], &m_pFormatEtc[m_nIndex]); + copied++; + m_nIndex++; + } + + // store result + if(pceltFetched != 0) + *pceltFetched = copied; + + // did we copy all that was requested? + return (copied == celt) ? S_OK : S_FALSE; +} + +// +// IEnumFORMATETC::Skip +// +HRESULT __stdcall CEnumFormatEtc::Skip(ULONG celt) +{ + m_nIndex += celt; + return (m_nIndex <= m_nNumFormats) ? S_OK : S_FALSE; +} + +// +// IEnumFORMATETC::Reset +// +HRESULT __stdcall CEnumFormatEtc::Reset(void) +{ + m_nIndex = 0; + return S_OK; +} + +// +// IEnumFORMATETC::Clone +// +HRESULT __stdcall CEnumFormatEtc::Clone(IEnumFORMATETC ** ppEnumFormatEtc) +{ + HRESULT hResult; + + // make a duplicate enumerator + hResult = CreateEnumFormatEtc(m_nNumFormats, m_pFormatEtc, ppEnumFormatEtc); + + if(hResult == S_OK) + { + // manually set the index state + ((CEnumFormatEtc *) *ppEnumFormatEtc)->m_nIndex = m_nIndex; + } + + return hResult; +} + -- cgit v1.2.3