Mercurial > foo_out_sdl
diff foosdk/sdk/libPPUI/IDataObjectUtils.h @ 1:20d02a178406 default tip
*: check in everything else
yay
| author | Paper <paper@tflc.us> |
|---|---|
| date | Mon, 05 Jan 2026 02:15:46 -0500 |
| parents | |
| children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/foosdk/sdk/libPPUI/IDataObjectUtils.h Mon Jan 05 02:15:46 2026 -0500 @@ -0,0 +1,230 @@ +#pragma once + +#include <shlobj.h> +#include <ShlDisp.h> // IAsyncOperation +#include "pp-COM-macros.h" + +namespace IDataObjectUtils { + + class ReleaseStgMediumScope { + public: + ReleaseStgMediumScope(STGMEDIUM * medium) : m_medium(medium) {} + ~ReleaseStgMediumScope() {if (m_medium != NULL) ReleaseStgMedium(m_medium);} + private: + STGMEDIUM * m_medium; + + PFC_CLASS_NOT_COPYABLE_EX(ReleaseStgMediumScope) + }; + + static constexpr DWORD DataBlockToSTGMEDIUM_SupportedTymeds = TYMED_ISTREAM | TYMED_HGLOBAL; + static constexpr DWORD ExtractDataObjectContent_SupportedTymeds = TYMED_ISTREAM | TYMED_HGLOBAL; + + HRESULT DataBlockToSTGMEDIUM(const void * blockPtr, t_size blockSize, STGMEDIUM * medium, DWORD tymed, bool bHere) throw(); + + HGLOBAL HGlobalFromMemblock(const void * ptr,t_size size); + + HRESULT ExtractDataObjectContent(pfc::com_ptr_t<IDataObject> obj, UINT format, DWORD aspect, LONG index, pfc::array_t<t_uint8> & out); + HRESULT ExtractDataObjectContent(pfc::com_ptr_t<IDataObject> obj, UINT format, pfc::array_t<t_uint8> & out); + + HRESULT ExtractDataObjectContentTest(pfc::com_ptr_t<IDataObject> obj, UINT format, DWORD aspect, LONG index); + HRESULT ExtractDataObjectContentTest(pfc::com_ptr_t<IDataObject> obj, UINT format); + + HRESULT ExtractDataObjectString(pfc::com_ptr_t<IDataObject> obj, pfc::string_base & out); + HRESULT SetDataObjectString(pfc::com_ptr_t<IDataObject> obj, const char * str); + + HRESULT SetDataObjectContent(pfc::com_ptr_t<IDataObject> obj, UINT format, DWORD aspect, LONG index, const void * data, t_size dataSize); + + HRESULT STGMEDIUMToDataBlock(const STGMEDIUM & med, pfc::array_t<t_uint8> & out); + + HRESULT ExtractDataObjectDWORD(pfc::com_ptr_t<IDataObject> obj, UINT format, DWORD & val); + HRESULT SetDataObjectDWORD(pfc::com_ptr_t<IDataObject> obj, UINT format, DWORD val); + + HRESULT PasteSucceeded(pfc::com_ptr_t<IDataObject> obj, DWORD effect); + + class comparator_FORMATETC { + public: + static int compare(const FORMATETC & v1, const FORMATETC & v2) { + int val; + val = pfc::compare_t(v1.cfFormat,v2.cfFormat); if (val != 0) return val; + val = pfc::compare_t(v1.dwAspect,v2.dwAspect); if (val != 0) return val; + val = pfc::compare_t(v1.lindex, v2.lindex ); if (val != 0) return val; + return 0; + } + }; + + class CDataObjectBase : public IDataObject { + public: + COM_QI_SIMPLE(IDataObject) + + HRESULT STDMETHODCALLTYPE GetData(FORMATETC * formatetc, STGMEDIUM * medium) override { + return GetData_internal(formatetc,medium,false); + } + + HRESULT STDMETHODCALLTYPE GetDataHere(FORMATETC * formatetc, STGMEDIUM * medium) override { + return GetData_internal(formatetc,medium,true); + } + + HRESULT STDMETHODCALLTYPE QueryGetData(FORMATETC * formatetc) override { + if (formatetc == NULL) return E_INVALIDARG; + + if ((DataBlockToSTGMEDIUM_SupportedTymeds & formatetc->tymed) == 0) return DV_E_TYMED; + + try { + return RenderDataTest(formatetc->cfFormat,formatetc->dwAspect,formatetc->lindex); + } PP_COM_CATCH; + } + + + HRESULT STDMETHODCALLTYPE GetCanonicalFormatEtc(FORMATETC * in, FORMATETC * out) override { + //check this again + if (in == NULL || out == NULL) + return E_INVALIDARG; + *out = *in; + return DATA_S_SAMEFORMATETC; + } + + HRESULT STDMETHODCALLTYPE EnumFormatEtc(DWORD dwDirection,IEnumFORMATETC ** ppenumFormatetc) override { + if (dwDirection == DATADIR_GET) { + if (ppenumFormatetc == NULL) return E_INVALIDARG; + return CreateIEnumFORMATETC(ppenumFormatetc); + } else if (dwDirection == DATADIR_SET) { + return E_NOTIMPL; + } else { + return E_INVALIDARG; + } + } + + HRESULT STDMETHODCALLTYPE SetData(FORMATETC * pFormatetc, STGMEDIUM * pmedium, BOOL fRelease) override { + try { + ReleaseStgMediumScope relScope(fRelease ? pmedium : NULL); + if (pFormatetc == NULL || pmedium == NULL) return E_INVALIDARG; + + /*TCHAR buf[256]; + if (GetClipboardFormatName(pFormatetc->cfFormat,buf,PFC_TABSIZE(buf)) > 0) { + buf[PFC_TABSIZE(buf)-1] = 0; + OutputDebugString(TEXT("SetData: ")); OutputDebugString(buf); OutputDebugString(TEXT("\n")); + } else { + OutputDebugString(TEXT("SetData: unknown clipboard format.\n")); + }*/ + + pfc::array_t<t_uint8> temp; + HRESULT state = STGMEDIUMToDataBlock(*pmedium,temp); + if (FAILED(state)) return state; + m_entries.set(*pFormatetc,temp); + return S_OK; + } PP_COM_CATCH; + } + HRESULT STDMETHODCALLTYPE DAdvise(FORMATETC* pFormatetc, DWORD advf, IAdviseSink* pAdvSink, DWORD* pdwConnection) override { (void)pFormatetc; (void)advf; (void)pAdvSink; (void)pdwConnection; return OLE_E_ADVISENOTSUPPORTED; } + HRESULT STDMETHODCALLTYPE DUnadvise(DWORD dwConnection) override { (void)dwConnection; return OLE_E_ADVISENOTSUPPORTED; } + HRESULT STDMETHODCALLTYPE EnumDAdvise(IEnumSTATDATA** ppenumAdvise) override { (void)ppenumAdvise; return OLE_E_ADVISENOTSUPPORTED; } + protected: + typedef pfc::array_t<uint8_t> data_t; + virtual HRESULT RenderData(UINT format,DWORD aspect,LONG dataIndex, data_t & out) const { + FORMATETC fmt = {}; + fmt.cfFormat = (CLIPFORMAT)format; fmt.dwAspect = aspect; fmt.lindex = dataIndex; + const pfc::array_t<t_uint8> * entry = m_entries.query_ptr(fmt); + if (entry != NULL) { + out = * entry; + return S_OK; + } + return DV_E_FORMATETC; + } + virtual HRESULT RenderDataTest(UINT format,DWORD aspect,LONG dataIndex) const { + FORMATETC fmt = {}; + fmt.cfFormat = (CLIPFORMAT)format; fmt.dwAspect = aspect; fmt.lindex = dataIndex; + if (m_entries.have_item(fmt)) return S_OK; + return DV_E_FORMATETC; + } + typedef pfc::list_base_t<FORMATETC> TFormatList; + + static void AddFormat(TFormatList & out,UINT code) { + FORMATETC fmt = {}; + fmt.dwAspect = DVASPECT_CONTENT; + fmt.lindex = -1; + fmt.cfFormat = (CLIPFORMAT)code; + for(t_size medWalk = 0; medWalk < 32; ++medWalk) { + const DWORD med = 1 << medWalk; + if ((DataBlockToSTGMEDIUM_SupportedTymeds & med) != 0) { + fmt.tymed = med; + out.add_item(fmt); + } + } + } + + virtual void EnumFormats(TFormatList & out) const { + pfc::avltree_t<UINT> formats; + for(auto walk = m_entries.cfirst(); walk.is_valid(); ++walk) { + formats.add_item( walk->m_key.cfFormat ); + } + for(auto walk = formats.cfirst(); walk.is_valid(); ++walk) { + AddFormat(out, *walk); + } + } + HRESULT CreateIEnumFORMATETC(IEnumFORMATETC ** outptr) const throw() { + try { + pfc::list_t<FORMATETC> out; + EnumFormats(out); + return SHCreateStdEnumFmtEtc((UINT)out.get_count(), out.get_ptr(), outptr); + } PP_COM_CATCH; + } + private: + HRESULT GetData_internal(FORMATETC * formatetc, STGMEDIUM * medium,bool bHere) { + if (formatetc == NULL || medium == NULL) return E_INVALIDARG; + + try { + data_t out; + HRESULT hr = RenderData(formatetc->cfFormat,formatetc->dwAspect,formatetc->lindex,out); + if (FAILED(hr)) return hr; + return DataBlockToSTGMEDIUM(out.get_ptr(),out.get_size(),medium,formatetc->tymed,bHere); + } PP_COM_CATCH; + } + + typedef pfc::map_t<FORMATETC, pfc::array_t<t_uint8>, comparator_FORMATETC> t_entries; + t_entries m_entries; + }; + +#ifdef __IDataObjectAsyncCapability_INTERFACE_DEFINED__ + typedef IDataObjectAsyncCapability IDataObjectAsyncCapability_t; +#else + typedef IAsyncOperation IDataObjectAsyncCapability_t; +#endif + + class CAsyncDataObjectBase : public CDataObjectBase, public IDataObjectAsyncCapability_t { + BOOL m_inOperation = FALSE; + BOOL m_asyncMode = TRUE; + protected: + COM_QI_BEGIN() + COM_QI_CHAIN(CDataObjectBase) + COM_QI_ENTRY(IDataObjectAsyncCapability_t) + COM_QI_END() + public: + HRESULT STDMETHODCALLTYPE SetAsyncMode(BOOL fDoOpAsync) override { + m_asyncMode = fDoOpAsync; + return S_OK; + } + + HRESULT STDMETHODCALLTYPE GetAsyncMode(BOOL *pfIsOpAsync) override { + if ( pfIsOpAsync == nullptr ) return E_INVALIDARG; + *pfIsOpAsync = m_asyncMode; + return S_OK; + } + + HRESULT STDMETHODCALLTYPE StartOperation(IBindCtx *pbcReserved) override { + (void)pbcReserved; + m_inOperation = TRUE; + return S_OK; + } + + HRESULT STDMETHODCALLTYPE InOperation(BOOL *pfInAsyncOp) override { + if ( pfInAsyncOp == nullptr ) return E_INVALIDARG; + *pfInAsyncOp = m_inOperation; + return S_OK; + } + + HRESULT STDMETHODCALLTYPE EndOperation(HRESULT hResult,IBindCtx *pbcReserved,DWORD dwEffects) override { + (void)hResult; (void)pbcReserved; (void)dwEffects; + m_inOperation = FALSE; + return S_OK; + } + }; +}
