Mercurial > foo_out_sdl
comparison 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 |
comparison
equal
deleted
inserted
replaced
| 0:e9bb126753e7 | 1:20d02a178406 |
|---|---|
| 1 #pragma once | |
| 2 | |
| 3 #include <shlobj.h> | |
| 4 #include <ShlDisp.h> // IAsyncOperation | |
| 5 #include "pp-COM-macros.h" | |
| 6 | |
| 7 namespace IDataObjectUtils { | |
| 8 | |
| 9 class ReleaseStgMediumScope { | |
| 10 public: | |
| 11 ReleaseStgMediumScope(STGMEDIUM * medium) : m_medium(medium) {} | |
| 12 ~ReleaseStgMediumScope() {if (m_medium != NULL) ReleaseStgMedium(m_medium);} | |
| 13 private: | |
| 14 STGMEDIUM * m_medium; | |
| 15 | |
| 16 PFC_CLASS_NOT_COPYABLE_EX(ReleaseStgMediumScope) | |
| 17 }; | |
| 18 | |
| 19 static constexpr DWORD DataBlockToSTGMEDIUM_SupportedTymeds = TYMED_ISTREAM | TYMED_HGLOBAL; | |
| 20 static constexpr DWORD ExtractDataObjectContent_SupportedTymeds = TYMED_ISTREAM | TYMED_HGLOBAL; | |
| 21 | |
| 22 HRESULT DataBlockToSTGMEDIUM(const void * blockPtr, t_size blockSize, STGMEDIUM * medium, DWORD tymed, bool bHere) throw(); | |
| 23 | |
| 24 HGLOBAL HGlobalFromMemblock(const void * ptr,t_size size); | |
| 25 | |
| 26 HRESULT ExtractDataObjectContent(pfc::com_ptr_t<IDataObject> obj, UINT format, DWORD aspect, LONG index, pfc::array_t<t_uint8> & out); | |
| 27 HRESULT ExtractDataObjectContent(pfc::com_ptr_t<IDataObject> obj, UINT format, pfc::array_t<t_uint8> & out); | |
| 28 | |
| 29 HRESULT ExtractDataObjectContentTest(pfc::com_ptr_t<IDataObject> obj, UINT format, DWORD aspect, LONG index); | |
| 30 HRESULT ExtractDataObjectContentTest(pfc::com_ptr_t<IDataObject> obj, UINT format); | |
| 31 | |
| 32 HRESULT ExtractDataObjectString(pfc::com_ptr_t<IDataObject> obj, pfc::string_base & out); | |
| 33 HRESULT SetDataObjectString(pfc::com_ptr_t<IDataObject> obj, const char * str); | |
| 34 | |
| 35 HRESULT SetDataObjectContent(pfc::com_ptr_t<IDataObject> obj, UINT format, DWORD aspect, LONG index, const void * data, t_size dataSize); | |
| 36 | |
| 37 HRESULT STGMEDIUMToDataBlock(const STGMEDIUM & med, pfc::array_t<t_uint8> & out); | |
| 38 | |
| 39 HRESULT ExtractDataObjectDWORD(pfc::com_ptr_t<IDataObject> obj, UINT format, DWORD & val); | |
| 40 HRESULT SetDataObjectDWORD(pfc::com_ptr_t<IDataObject> obj, UINT format, DWORD val); | |
| 41 | |
| 42 HRESULT PasteSucceeded(pfc::com_ptr_t<IDataObject> obj, DWORD effect); | |
| 43 | |
| 44 class comparator_FORMATETC { | |
| 45 public: | |
| 46 static int compare(const FORMATETC & v1, const FORMATETC & v2) { | |
| 47 int val; | |
| 48 val = pfc::compare_t(v1.cfFormat,v2.cfFormat); if (val != 0) return val; | |
| 49 val = pfc::compare_t(v1.dwAspect,v2.dwAspect); if (val != 0) return val; | |
| 50 val = pfc::compare_t(v1.lindex, v2.lindex ); if (val != 0) return val; | |
| 51 return 0; | |
| 52 } | |
| 53 }; | |
| 54 | |
| 55 class CDataObjectBase : public IDataObject { | |
| 56 public: | |
| 57 COM_QI_SIMPLE(IDataObject) | |
| 58 | |
| 59 HRESULT STDMETHODCALLTYPE GetData(FORMATETC * formatetc, STGMEDIUM * medium) override { | |
| 60 return GetData_internal(formatetc,medium,false); | |
| 61 } | |
| 62 | |
| 63 HRESULT STDMETHODCALLTYPE GetDataHere(FORMATETC * formatetc, STGMEDIUM * medium) override { | |
| 64 return GetData_internal(formatetc,medium,true); | |
| 65 } | |
| 66 | |
| 67 HRESULT STDMETHODCALLTYPE QueryGetData(FORMATETC * formatetc) override { | |
| 68 if (formatetc == NULL) return E_INVALIDARG; | |
| 69 | |
| 70 if ((DataBlockToSTGMEDIUM_SupportedTymeds & formatetc->tymed) == 0) return DV_E_TYMED; | |
| 71 | |
| 72 try { | |
| 73 return RenderDataTest(formatetc->cfFormat,formatetc->dwAspect,formatetc->lindex); | |
| 74 } PP_COM_CATCH; | |
| 75 } | |
| 76 | |
| 77 | |
| 78 HRESULT STDMETHODCALLTYPE GetCanonicalFormatEtc(FORMATETC * in, FORMATETC * out) override { | |
| 79 //check this again | |
| 80 if (in == NULL || out == NULL) | |
| 81 return E_INVALIDARG; | |
| 82 *out = *in; | |
| 83 return DATA_S_SAMEFORMATETC; | |
| 84 } | |
| 85 | |
| 86 HRESULT STDMETHODCALLTYPE EnumFormatEtc(DWORD dwDirection,IEnumFORMATETC ** ppenumFormatetc) override { | |
| 87 if (dwDirection == DATADIR_GET) { | |
| 88 if (ppenumFormatetc == NULL) return E_INVALIDARG; | |
| 89 return CreateIEnumFORMATETC(ppenumFormatetc); | |
| 90 } else if (dwDirection == DATADIR_SET) { | |
| 91 return E_NOTIMPL; | |
| 92 } else { | |
| 93 return E_INVALIDARG; | |
| 94 } | |
| 95 } | |
| 96 | |
| 97 HRESULT STDMETHODCALLTYPE SetData(FORMATETC * pFormatetc, STGMEDIUM * pmedium, BOOL fRelease) override { | |
| 98 try { | |
| 99 ReleaseStgMediumScope relScope(fRelease ? pmedium : NULL); | |
| 100 if (pFormatetc == NULL || pmedium == NULL) return E_INVALIDARG; | |
| 101 | |
| 102 /*TCHAR buf[256]; | |
| 103 if (GetClipboardFormatName(pFormatetc->cfFormat,buf,PFC_TABSIZE(buf)) > 0) { | |
| 104 buf[PFC_TABSIZE(buf)-1] = 0; | |
| 105 OutputDebugString(TEXT("SetData: ")); OutputDebugString(buf); OutputDebugString(TEXT("\n")); | |
| 106 } else { | |
| 107 OutputDebugString(TEXT("SetData: unknown clipboard format.\n")); | |
| 108 }*/ | |
| 109 | |
| 110 pfc::array_t<t_uint8> temp; | |
| 111 HRESULT state = STGMEDIUMToDataBlock(*pmedium,temp); | |
| 112 if (FAILED(state)) return state; | |
| 113 m_entries.set(*pFormatetc,temp); | |
| 114 return S_OK; | |
| 115 } PP_COM_CATCH; | |
| 116 } | |
| 117 HRESULT STDMETHODCALLTYPE DAdvise(FORMATETC* pFormatetc, DWORD advf, IAdviseSink* pAdvSink, DWORD* pdwConnection) override { (void)pFormatetc; (void)advf; (void)pAdvSink; (void)pdwConnection; return OLE_E_ADVISENOTSUPPORTED; } | |
| 118 HRESULT STDMETHODCALLTYPE DUnadvise(DWORD dwConnection) override { (void)dwConnection; return OLE_E_ADVISENOTSUPPORTED; } | |
| 119 HRESULT STDMETHODCALLTYPE EnumDAdvise(IEnumSTATDATA** ppenumAdvise) override { (void)ppenumAdvise; return OLE_E_ADVISENOTSUPPORTED; } | |
| 120 protected: | |
| 121 typedef pfc::array_t<uint8_t> data_t; | |
| 122 virtual HRESULT RenderData(UINT format,DWORD aspect,LONG dataIndex, data_t & out) const { | |
| 123 FORMATETC fmt = {}; | |
| 124 fmt.cfFormat = (CLIPFORMAT)format; fmt.dwAspect = aspect; fmt.lindex = dataIndex; | |
| 125 const pfc::array_t<t_uint8> * entry = m_entries.query_ptr(fmt); | |
| 126 if (entry != NULL) { | |
| 127 out = * entry; | |
| 128 return S_OK; | |
| 129 } | |
| 130 return DV_E_FORMATETC; | |
| 131 } | |
| 132 virtual HRESULT RenderDataTest(UINT format,DWORD aspect,LONG dataIndex) const { | |
| 133 FORMATETC fmt = {}; | |
| 134 fmt.cfFormat = (CLIPFORMAT)format; fmt.dwAspect = aspect; fmt.lindex = dataIndex; | |
| 135 if (m_entries.have_item(fmt)) return S_OK; | |
| 136 return DV_E_FORMATETC; | |
| 137 } | |
| 138 typedef pfc::list_base_t<FORMATETC> TFormatList; | |
| 139 | |
| 140 static void AddFormat(TFormatList & out,UINT code) { | |
| 141 FORMATETC fmt = {}; | |
| 142 fmt.dwAspect = DVASPECT_CONTENT; | |
| 143 fmt.lindex = -1; | |
| 144 fmt.cfFormat = (CLIPFORMAT)code; | |
| 145 for(t_size medWalk = 0; medWalk < 32; ++medWalk) { | |
| 146 const DWORD med = 1 << medWalk; | |
| 147 if ((DataBlockToSTGMEDIUM_SupportedTymeds & med) != 0) { | |
| 148 fmt.tymed = med; | |
| 149 out.add_item(fmt); | |
| 150 } | |
| 151 } | |
| 152 } | |
| 153 | |
| 154 virtual void EnumFormats(TFormatList & out) const { | |
| 155 pfc::avltree_t<UINT> formats; | |
| 156 for(auto walk = m_entries.cfirst(); walk.is_valid(); ++walk) { | |
| 157 formats.add_item( walk->m_key.cfFormat ); | |
| 158 } | |
| 159 for(auto walk = formats.cfirst(); walk.is_valid(); ++walk) { | |
| 160 AddFormat(out, *walk); | |
| 161 } | |
| 162 } | |
| 163 HRESULT CreateIEnumFORMATETC(IEnumFORMATETC ** outptr) const throw() { | |
| 164 try { | |
| 165 pfc::list_t<FORMATETC> out; | |
| 166 EnumFormats(out); | |
| 167 return SHCreateStdEnumFmtEtc((UINT)out.get_count(), out.get_ptr(), outptr); | |
| 168 } PP_COM_CATCH; | |
| 169 } | |
| 170 private: | |
| 171 HRESULT GetData_internal(FORMATETC * formatetc, STGMEDIUM * medium,bool bHere) { | |
| 172 if (formatetc == NULL || medium == NULL) return E_INVALIDARG; | |
| 173 | |
| 174 try { | |
| 175 data_t out; | |
| 176 HRESULT hr = RenderData(formatetc->cfFormat,formatetc->dwAspect,formatetc->lindex,out); | |
| 177 if (FAILED(hr)) return hr; | |
| 178 return DataBlockToSTGMEDIUM(out.get_ptr(),out.get_size(),medium,formatetc->tymed,bHere); | |
| 179 } PP_COM_CATCH; | |
| 180 } | |
| 181 | |
| 182 typedef pfc::map_t<FORMATETC, pfc::array_t<t_uint8>, comparator_FORMATETC> t_entries; | |
| 183 t_entries m_entries; | |
| 184 }; | |
| 185 | |
| 186 #ifdef __IDataObjectAsyncCapability_INTERFACE_DEFINED__ | |
| 187 typedef IDataObjectAsyncCapability IDataObjectAsyncCapability_t; | |
| 188 #else | |
| 189 typedef IAsyncOperation IDataObjectAsyncCapability_t; | |
| 190 #endif | |
| 191 | |
| 192 class CAsyncDataObjectBase : public CDataObjectBase, public IDataObjectAsyncCapability_t { | |
| 193 BOOL m_inOperation = FALSE; | |
| 194 BOOL m_asyncMode = TRUE; | |
| 195 protected: | |
| 196 COM_QI_BEGIN() | |
| 197 COM_QI_CHAIN(CDataObjectBase) | |
| 198 COM_QI_ENTRY(IDataObjectAsyncCapability_t) | |
| 199 COM_QI_END() | |
| 200 public: | |
| 201 HRESULT STDMETHODCALLTYPE SetAsyncMode(BOOL fDoOpAsync) override { | |
| 202 m_asyncMode = fDoOpAsync; | |
| 203 return S_OK; | |
| 204 } | |
| 205 | |
| 206 HRESULT STDMETHODCALLTYPE GetAsyncMode(BOOL *pfIsOpAsync) override { | |
| 207 if ( pfIsOpAsync == nullptr ) return E_INVALIDARG; | |
| 208 *pfIsOpAsync = m_asyncMode; | |
| 209 return S_OK; | |
| 210 } | |
| 211 | |
| 212 HRESULT STDMETHODCALLTYPE StartOperation(IBindCtx *pbcReserved) override { | |
| 213 (void)pbcReserved; | |
| 214 m_inOperation = TRUE; | |
| 215 return S_OK; | |
| 216 } | |
| 217 | |
| 218 HRESULT STDMETHODCALLTYPE InOperation(BOOL *pfInAsyncOp) override { | |
| 219 if ( pfInAsyncOp == nullptr ) return E_INVALIDARG; | |
| 220 *pfInAsyncOp = m_inOperation; | |
| 221 return S_OK; | |
| 222 } | |
| 223 | |
| 224 HRESULT STDMETHODCALLTYPE EndOperation(HRESULT hResult,IBindCtx *pbcReserved,DWORD dwEffects) override { | |
| 225 (void)hResult; (void)pbcReserved; (void)dwEffects; | |
| 226 m_inOperation = FALSE; | |
| 227 return S_OK; | |
| 228 } | |
| 229 }; | |
| 230 } |
