]> git.saurik.com Git - wxWidgets.git/blame - src/msw/ole/dataobj.cpp
wxCHECK change
[wxWidgets.git] / src / msw / ole / dataobj.cpp
CommitLineData
269a5a34
VZ
1///////////////////////////////////////////////////////////////////////////////
2// Name: msw/ole/dataobj.cpp
3// Purpose: implementation of wx[I]DataObject class
4// Author: Vadim Zeitlin
5// Modified by:
6// Created: 10.05.98
7// RCS-ID: $Id$
8// Copyright: (c) 1998 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
9// Licence: wxWindows license
10///////////////////////////////////////////////////////////////////////////////
11
12// ============================================================================
13// declarations
14// ============================================================================
15
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
19
20#ifdef __GNUG__
21 #pragma implementation "dataobj.h"
22#endif
23
24// For compilers that support precompilation, includes "wx.h".
25#include "wx/wxprec.h"
26
27#if defined(__BORLANDC__)
28 #pragma hdrstop
29#endif
30
31#include <wx/log.h>
32#include <wx/msw/ole/oleutils.h>
33#include <wx/msw/ole/dataobj.h>
34
35#ifndef __WIN32__
36 #include <ole2.h>
37 #include <olestd.h>
38#endif
39
40// ----------------------------------------------------------------------------
41// functions
42// ----------------------------------------------------------------------------
43
40e1a9c0 44static const char *GetTymedName(DWORD tymed);
269a5a34
VZ
45
46// ----------------------------------------------------------------------------
47// wxIEnumFORMATETC interface implementation
48// ----------------------------------------------------------------------------
49class wxIEnumFORMATETC : public IEnumFORMATETC
50{
51public:
52 wxIEnumFORMATETC(CLIPFORMAT cf);
53
54 DECLARE_IUNKNOWN_METHODS;
55
56 // IEnumFORMATETC
57 STDMETHODIMP Next(ULONG celt, FORMATETC *rgelt, ULONG *pceltFetched);
58 STDMETHODIMP Skip(ULONG celt);
59 STDMETHODIMP Reset();
60 STDMETHODIMP Clone(IEnumFORMATETC **ppenum);
61
62private:
63 FORMATETC m_format; // (unique @@@) format we can provide data in
64 ULONG m_nCurrent; // current enum position (currently either 0 or 1)
65};
66
67// ----------------------------------------------------------------------------
68// wxIDataObject implementation of IDataObject interface
69// ----------------------------------------------------------------------------
70class wxIDataObject : public IDataObject
71{
72public:
73 wxIDataObject(wxDataObject *pDataObject);
74
75 DECLARE_IUNKNOWN_METHODS;
76
77 // IDataObject
78 STDMETHODIMP GetData(FORMATETC *pformatetcIn, STGMEDIUM *pmedium);
79 STDMETHODIMP GetDataHere(FORMATETC *pformatetc, STGMEDIUM *pmedium);
80 STDMETHODIMP QueryGetData(FORMATETC *pformatetc);
81 STDMETHODIMP GetCanonicalFormatEtc(FORMATETC *In, FORMATETC *pOut);
82 STDMETHODIMP SetData(FORMATETC *pfetc, STGMEDIUM *pmedium, BOOL fRelease);
83 STDMETHODIMP EnumFormatEtc(DWORD dwDirection, IEnumFORMATETC **ppenumFEtc);
84 STDMETHODIMP DAdvise(FORMATETC *pfetc, DWORD ad, IAdviseSink *p, DWORD *pdw);
85 STDMETHODIMP DUnadvise(DWORD dwConnection);
86 STDMETHODIMP EnumDAdvise(IEnumSTATDATA **ppenumAdvise);
87
88private:
89 wxDataObject *m_pDataObject; // pointer to C++ class we belong to
90};
91
92// ============================================================================
93// implementation
94// ============================================================================
95
96// ----------------------------------------------------------------------------
97// wxIEnumFORMATETC
98// ----------------------------------------------------------------------------
99
100BEGIN_IID_TABLE(wxIEnumFORMATETC)
101 ADD_IID(Unknown)
102 ADD_IID(EnumFORMATETC)
103END_IID_TABLE;
104
105IMPLEMENT_IUNKNOWN_METHODS(wxIEnumFORMATETC)
106
107wxIEnumFORMATETC::wxIEnumFORMATETC(CLIPFORMAT cf)
108{
109 m_format.cfFormat = cf;
110 m_format.ptd = NULL;
111 m_format.dwAspect = DVASPECT_CONTENT;
112 m_format.lindex = -1;
113 m_format.tymed = TYMED_HGLOBAL;
114 m_cRef = 0;
115 m_nCurrent = 0;
116}
117
118STDMETHODIMP wxIEnumFORMATETC::Next(ULONG celt,
119 FORMATETC *rgelt,
120 ULONG *pceltFetched)
121{
122 wxLogTrace("wxIEnumFORMATETC::Next");
123
124 if ( celt > 1 )
125 return S_FALSE;
126
127 if ( m_nCurrent == 0 ) {
128 *rgelt = m_format;
129 m_nCurrent++;
130
131 return S_OK;
132 }
133 else
134 return S_FALSE;
135}
136
137STDMETHODIMP wxIEnumFORMATETC::Skip(ULONG celt)
138{
139 wxLogTrace("wxIEnumFORMATETC::Skip");
140
141 if ( m_nCurrent == 0 )
142 m_nCurrent++;
143
144 return S_FALSE;
145}
146
147STDMETHODIMP wxIEnumFORMATETC::Reset()
148{
149 wxLogTrace("wxIEnumFORMATETC::Reset");
150
151 m_nCurrent = 0;
152
153 return S_OK;
154}
155
156STDMETHODIMP wxIEnumFORMATETC::Clone(IEnumFORMATETC **ppenum)
157{
158 wxLogTrace("wxIEnumFORMATETC::Clone");
159
160 wxIEnumFORMATETC *pNew = new wxIEnumFORMATETC(m_format.cfFormat);
161 pNew->AddRef();
162 *ppenum = pNew;
163
164 return S_OK;
165}
166
167// ----------------------------------------------------------------------------
168// wxIDataObject
169// ----------------------------------------------------------------------------
170
171BEGIN_IID_TABLE(wxIDataObject)
172 ADD_IID(Unknown)
173 ADD_IID(DataObject)
174END_IID_TABLE;
175
176IMPLEMENT_IUNKNOWN_METHODS(wxIDataObject)
177
178wxIDataObject::wxIDataObject(wxDataObject *pDataObject)
179{
180 m_cRef = 0;
181 m_pDataObject = pDataObject;
182}
183
184// get data functions
185STDMETHODIMP wxIDataObject::GetData(FORMATETC *pformatetcIn, STGMEDIUM *pmedium)
186{
187 wxLogTrace("wxIDataObject::GetData");
188
189 // is data is in our format?
190 HRESULT hr = QueryGetData(pformatetcIn);
191 if ( FAILED(hr) )
192 return hr;
193
194 // alloc memory
195 HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE,
196 m_pDataObject->GetDataSize());
197 if ( hGlobal == NULL ) {
198 wxLogLastError("GlobalAlloc");
199 return E_OUTOFMEMORY;
200 }
201
202 // copy data
203 pmedium->tymed = TYMED_HGLOBAL;
204 pmedium->hGlobal = hGlobal;
205 pmedium->pUnkForRelease = NULL;
206
207 hr = GetDataHere(pformatetcIn, pmedium);
208 if ( FAILED(hr) ) {
209 GlobalFree(hGlobal);
210 return hr;
211 }
212
213 return S_OK;
214}
215
216STDMETHODIMP wxIDataObject::GetDataHere(FORMATETC *pformatetc,
217 STGMEDIUM *pmedium)
218{
219 wxLogTrace("wxIDataObject::GetDataHere");
220
221 // put data in caller provided medium
222 if ( pmedium->tymed != TYMED_HGLOBAL )
223 return DV_E_TYMED;
224
225 // copy data
226 void *pBuf = GlobalLock(pmedium->hGlobal);
227 if ( pBuf == NULL ) {
228 wxLogLastError("GlobalLock");
229 return E_OUTOFMEMORY;
230 }
231
232 m_pDataObject->GetDataHere(pBuf);
233
234 GlobalUnlock(pmedium->hGlobal);
235
236 return S_OK;
237}
238
239// set data functions (not implemented)
240STDMETHODIMP wxIDataObject::SetData(FORMATETC *pformatetc,
241 STGMEDIUM *pmedium,
242 BOOL fRelease)
243{
244 wxLogTrace("wxIDataObject::SetData");
245 return E_NOTIMPL;
246}
247
248// information functions
249STDMETHODIMP wxIDataObject::QueryGetData(FORMATETC *pformatetc)
250{
251 // do we accept data in this format?
252 if ( pformatetc == NULL ) {
253 wxLogTrace("wxIDataObject::QueryGetData: invalid ptr.");
254 return E_INVALIDARG;
255 }
256
257 // the only one allowed by current COM implementation
258 if ( pformatetc->lindex != -1 ) {
259 wxLogTrace("wxIDataObject::QueryGetData: bad lindex %d",
260 pformatetc->lindex);
261 return DV_E_LINDEX;
262 }
263
264 // we don't support anything other (THUMBNAIL, ICON, DOCPRINT...)
265 if ( pformatetc->dwAspect != DVASPECT_CONTENT ) {
266 wxLogTrace("wxIDataObject::QueryGetData: bad dwAspect %d",
267 pformatetc->dwAspect);
268 return DV_E_DVASPECT;
269 }
270
271 // @@ we only transfer data by global memory (bad for large amounts of it!)
272 if ( !(pformatetc->tymed & TYMED_HGLOBAL) ) {
273 wxLogTrace("wxIDataObject::QueryGetData: %s != TYMED_HGLOBAL.",
274 GetTymedName(pformatetc->tymed));
275 return DV_E_TYMED;
276 }
277
278 // and now check the type of data requested
279 if ( m_pDataObject->IsSupportedFormat(pformatetc->cfFormat) ) {
280 wxLogTrace("wxIDataObject::QueryGetData: %s ok",
281 wxDataObject::GetFormatName(pformatetc->cfFormat));
282 return S_OK;
283 }
284 else {
285 wxLogTrace("wxIDataObject::QueryGetData: %s unsupported",
286 wxDataObject::GetFormatName(pformatetc->cfFormat));
287 return DV_E_FORMATETC;
288 }
289}
290
291STDMETHODIMP wxIDataObject::GetCanonicalFormatEtc(FORMATETC *pFormatetcIn,
292 FORMATETC *pFormatetcOut)
293{
294 wxLogTrace("wxIDataObject::GetCanonicalFormatEtc");
295
296 // @@ implementation is trivial, we might want something better here
297 if ( pFormatetcOut != NULL )
298 pFormatetcOut->ptd = NULL;
299 return DATA_S_SAMEFORMATETC;
300}
301
302STDMETHODIMP wxIDataObject::EnumFormatEtc(DWORD dwDirection,
303 IEnumFORMATETC **ppenumFormatEtc)
304{
305 wxLogTrace("wxIDataObject::EnumFormatEtc");
306
307 if ( dwDirection == DATADIR_SET ) {
308 // we don't allow setting of data anyhow
309 return E_NOTIMPL;
310 }
311
312 wxIEnumFORMATETC *pEnum =
313 new wxIEnumFORMATETC(m_pDataObject->GetPreferredFormat());
314 pEnum->AddRef();
315 *ppenumFormatEtc = pEnum;
316
317 return S_OK;
318}
319
320// advise sink functions (not implemented)
321STDMETHODIMP wxIDataObject::DAdvise(FORMATETC *pformatetc,
322 DWORD advf,
323 IAdviseSink *pAdvSink,
324 DWORD *pdwConnection)
325{
326 return OLE_E_ADVISENOTSUPPORTED;
327}
328
329STDMETHODIMP wxIDataObject::DUnadvise(DWORD dwConnection)
330{
331 return OLE_E_ADVISENOTSUPPORTED;
332}
333
334STDMETHODIMP wxIDataObject::EnumDAdvise(IEnumSTATDATA **ppenumAdvise)
335{
336 return OLE_E_ADVISENOTSUPPORTED;
337}
338
339// ----------------------------------------------------------------------------
340// wxDataObject
341// ----------------------------------------------------------------------------
342
343wxDataObject::wxDataObject()
344{
345 m_pIDataObject = new wxIDataObject(this);
346 m_pIDataObject->AddRef();
347}
348
349wxDataObject::~wxDataObject()
350{
351 m_pIDataObject->Release();
352}
353
269a5a34
VZ
354const char *wxDataObject::GetFormatName(wxDataFormat format)
355{
40e1a9c0 356#ifdef __DEBUG__
269a5a34
VZ
357 static char s_szBuf[128];
358 switch ( format ) {
359 case CF_TEXT: return "CF_TEXT";
360 case CF_BITMAP: return "CF_BITMAP";
361 case CF_METAFILEPICT: return "CF_METAFILEPICT";
362 case CF_SYLK: return "CF_SYLK";
363 case CF_DIF: return "CF_DIF";
364 case CF_TIFF: return "CF_TIFF";
365 case CF_OEMTEXT: return "CF_OEMTEXT";
366 case CF_DIB: return "CF_DIB";
367 case CF_PALETTE: return "CF_PALETTE";
368 case CF_PENDATA: return "CF_PENDATA";
369 case CF_RIFF: return "CF_RIFF";
370 case CF_WAVE: return "CF_WAVE";
371 case CF_UNICODETEXT: return "CF_UNICODETEXT";
372 case CF_ENHMETAFILE: return "CF_ENHMETAFILE";
373 case CF_HDROP: return "CF_HDROP";
374 case CF_LOCALE: return "CF_LOCALE";
375 default:
376 sprintf(s_szBuf, "clipboard format %d (unknown)", format);
377 return s_szBuf;
378 }
40e1a9c0
JS
379 #else
380 return "";
381#endif
269a5a34
VZ
382}
383
384// ----------------------------------------------------------------------------
385// private functions
386// ----------------------------------------------------------------------------
387static const char *GetTymedName(DWORD tymed)
388{
389 static char s_szBuf[128];
390 switch ( tymed ) {
391 case TYMED_HGLOBAL: return "TYMED_HGLOBAL";
392 case TYMED_FILE: return "TYMED_FILE";
393 case TYMED_ISTREAM: return "TYMED_ISTREAM";
394 case TYMED_ISTORAGE: return "TYMED_ISTORAGE";
395 case TYMED_GDI: return "TYMED_GDI";
396 case TYMED_MFPICT: return "TYMED_MFPICT";
397 case TYMED_ENHMF: return "TYMED_ENHMF";
398 default:
399 sprintf(s_szBuf, "type of media format %d (unknown)", tymed);
400 return s_szBuf;
401 }
402}