summaryrefslogtreecommitdiff
path: root/plugins/mTextControl/src/enumformat.cpp
diff options
context:
space:
mode:
authorVadim Dashevskiy <watcherhd@gmail.com>2012-05-15 10:38:20 +0000
committerVadim Dashevskiy <watcherhd@gmail.com>2012-05-15 10:38:20 +0000
commit48540940b6c28bb4378abfeb500ec45a625b37b6 (patch)
tree2ef294c0763e802f91d868bdef4229b6868527de /plugins/mTextControl/src/enumformat.cpp
parent5c350913f011e119127baeb32a6aedeb4f0d33bc (diff)
initial commit
git-svn-id: http://svn.miranda-ng.org/main/trunk@2 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
Diffstat (limited to 'plugins/mTextControl/src/enumformat.cpp')
-rw-r--r--plugins/mTextControl/src/enumformat.cpp232
1 files changed, 232 insertions, 0 deletions
diff --git a/plugins/mTextControl/src/enumformat.cpp b/plugins/mTextControl/src/enumformat.cpp
new file mode 100644
index 0000000000..7daac154d7
--- /dev/null
+++ b/plugins/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;
+}
+