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