]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/msw/ole/dataobj.cpp
1. minor fixes in wxDynLib
[wxWidgets.git] / src / msw / ole / dataobj.cpp
... / ...
CommitLineData
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/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
52static const char *GetTymedName(DWORD tymed);
53
54// ----------------------------------------------------------------------------
55// wxIEnumFORMATETC interface implementation
56// ----------------------------------------------------------------------------
57class wxIEnumFORMATETC : public IEnumFORMATETC
58{
59public:
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
70private:
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// ----------------------------------------------------------------------------
78class wxIDataObject : public IDataObject
79{
80public:
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
96private:
97 wxDataObject *m_pDataObject; // pointer to C++ class we belong to
98};
99
100// ============================================================================
101// implementation
102// ============================================================================
103
104// ----------------------------------------------------------------------------
105// wxDataFormat
106// ----------------------------------------------------------------------------
107
108void wxDataFormat::SetId(const wxChar *format)
109{
110 m_format = ::RegisterClipboardFormat(format);
111 if ( !m_format )
112 {
113 wxLogError(_("Couldn't register clipboard format '%s'."), format);
114 }
115}
116
117wxString wxDataFormat::GetId() const
118{
119 static const int max = 256;
120
121 wxString s;
122
123 wxCHECK_MSG( !IsStandard(), s,
124 _T("name of predefined format cannot be retrieved") );
125
126 int len = ::GetClipboardFormatName(m_format, s.GetWriteBuf(max), max);
127 s.UngetWriteBuf();
128
129 if ( !len )
130 {
131 wxLogError(_("The clipboard format '%d' doesn't exist."), m_format);
132 }
133
134 return s;
135}
136
137// ----------------------------------------------------------------------------
138// wxIEnumFORMATETC
139// ----------------------------------------------------------------------------
140
141BEGIN_IID_TABLE(wxIEnumFORMATETC)
142 ADD_IID(Unknown)
143 ADD_IID(EnumFORMATETC)
144END_IID_TABLE;
145
146IMPLEMENT_IUNKNOWN_METHODS(wxIEnumFORMATETC)
147
148wxIEnumFORMATETC::wxIEnumFORMATETC(CLIPFORMAT cf)
149{
150 m_format.cfFormat = cf;
151 m_format.ptd = NULL;
152 m_format.dwAspect = DVASPECT_CONTENT;
153 m_format.lindex = -1;
154 m_format.tymed = TYMED_HGLOBAL;
155 m_cRef = 0;
156 m_nCurrent = 0;
157}
158
159STDMETHODIMP wxIEnumFORMATETC::Next(ULONG celt,
160 FORMATETC *rgelt,
161 ULONG *pceltFetched)
162{
163 wxLogTrace(_T("wxIEnumFORMATETC::Next"));
164
165 if ( celt > 1 )
166 return S_FALSE;
167
168 if ( m_nCurrent == 0 ) {
169 *rgelt = m_format;
170 m_nCurrent++;
171
172 return S_OK;
173 }
174 else
175 return S_FALSE;
176}
177
178STDMETHODIMP wxIEnumFORMATETC::Skip(ULONG celt)
179{
180 wxLogTrace(_T("wxIEnumFORMATETC::Skip"));
181
182 if ( m_nCurrent == 0 )
183 m_nCurrent++;
184
185 return S_FALSE;
186}
187
188STDMETHODIMP wxIEnumFORMATETC::Reset()
189{
190 wxLogTrace(_T("wxIEnumFORMATETC::Reset"));
191
192 m_nCurrent = 0;
193
194 return S_OK;
195}
196
197STDMETHODIMP wxIEnumFORMATETC::Clone(IEnumFORMATETC **ppenum)
198{
199 wxLogTrace(_T("wxIEnumFORMATETC::Clone"));
200
201 wxIEnumFORMATETC *pNew = new wxIEnumFORMATETC(m_format.cfFormat);
202 pNew->AddRef();
203 *ppenum = pNew;
204
205 return S_OK;
206}
207
208// ----------------------------------------------------------------------------
209// wxIDataObject
210// ----------------------------------------------------------------------------
211
212BEGIN_IID_TABLE(wxIDataObject)
213 ADD_IID(Unknown)
214 ADD_IID(DataObject)
215END_IID_TABLE;
216
217IMPLEMENT_IUNKNOWN_METHODS(wxIDataObject)
218
219wxIDataObject::wxIDataObject(wxDataObject *pDataObject)
220{
221 m_cRef = 0;
222 m_pDataObject = pDataObject;
223}
224
225// get data functions
226STDMETHODIMP wxIDataObject::GetData(FORMATETC *pformatetcIn, STGMEDIUM *pmedium)
227{
228 wxLogTrace(_T("wxIDataObject::GetData"));
229
230 // is data is in our format?
231 HRESULT hr = QueryGetData(pformatetcIn);
232 if ( FAILED(hr) )
233 return hr;
234
235 // alloc memory
236 HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE,
237 m_pDataObject->GetDataSize());
238 if ( hGlobal == NULL ) {
239 wxLogLastError("GlobalAlloc");
240 return E_OUTOFMEMORY;
241 }
242
243 // copy data
244 pmedium->tymed = TYMED_HGLOBAL;
245 pmedium->hGlobal = hGlobal;
246 pmedium->pUnkForRelease = NULL;
247
248 hr = GetDataHere(pformatetcIn, pmedium);
249 if ( FAILED(hr) ) {
250 GlobalFree(hGlobal);
251 return hr;
252 }
253
254 return S_OK;
255}
256
257STDMETHODIMP wxIDataObject::GetDataHere(FORMATETC *pformatetc,
258 STGMEDIUM *pmedium)
259{
260 wxLogTrace(_T("wxIDataObject::GetDataHere"));
261
262 // put data in caller provided medium
263 if ( pmedium->tymed != TYMED_HGLOBAL )
264 return DV_E_TYMED;
265
266 // copy data
267 void *pBuf = GlobalLock(pmedium->hGlobal);
268 if ( pBuf == NULL ) {
269 wxLogLastError(_T("GlobalLock"));
270 return E_OUTOFMEMORY;
271 }
272
273 m_pDataObject->GetDataHere(pBuf);
274
275 GlobalUnlock(pmedium->hGlobal);
276
277 return S_OK;
278}
279
280// set data functions (not implemented)
281STDMETHODIMP wxIDataObject::SetData(FORMATETC *pformatetc,
282 STGMEDIUM *pmedium,
283 BOOL fRelease)
284{
285 wxLogTrace(_T("wxIDataObject::SetData"));
286 return E_NOTIMPL;
287}
288
289// information functions
290STDMETHODIMP wxIDataObject::QueryGetData(FORMATETC *pformatetc)
291{
292 // do we accept data in this format?
293 if ( pformatetc == NULL ) {
294 wxLogTrace(_T("wxIDataObject::QueryGetData: invalid ptr."));
295 return E_INVALIDARG;
296 }
297
298 // the only one allowed by current COM implementation
299 if ( pformatetc->lindex != -1 ) {
300 wxLogTrace(_T("wxIDataObject::QueryGetData: bad lindex %d"),
301 pformatetc->lindex);
302 return DV_E_LINDEX;
303 }
304
305 // we don't support anything other (THUMBNAIL, ICON, DOCPRINT...)
306 if ( pformatetc->dwAspect != DVASPECT_CONTENT ) {
307 wxLogTrace(_T("wxIDataObject::QueryGetData: bad dwAspect %d"),
308 pformatetc->dwAspect);
309 return DV_E_DVASPECT;
310 }
311
312 // @@ we only transfer data by global memory (bad for large amounts of it!)
313 if ( !(pformatetc->tymed & TYMED_HGLOBAL) ) {
314 wxLogTrace(_T("wxIDataObject::QueryGetData: %s != TYMED_HGLOBAL."),
315 GetTymedName(pformatetc->tymed));
316 return DV_E_TYMED;
317 }
318
319 // and now check the type of data requested
320 if ( m_pDataObject->IsSupportedFormat((wxDataFormatId)pformatetc->cfFormat) ) {
321 wxLogTrace(_T("wxIDataObject::QueryGetData: %s ok"),
322 wxDataObject::GetFormatName((wxDataFormatId)pformatetc->cfFormat));
323 return S_OK;
324 }
325 else {
326 wxLogTrace(_T("wxIDataObject::QueryGetData: %s unsupported"),
327 wxDataObject::GetFormatName((wxDataFormatId)pformatetc->cfFormat));
328 return DV_E_FORMATETC;
329 }
330}
331
332STDMETHODIMP wxIDataObject::GetCanonicalFormatEtc(FORMATETC *pFormatetcIn,
333 FORMATETC *pFormatetcOut)
334{
335 wxLogTrace(_T("wxIDataObject::GetCanonicalFormatEtc"));
336
337 // @@ implementation is trivial, we might want something better here
338 if ( pFormatetcOut != NULL )
339 pFormatetcOut->ptd = NULL;
340 return DATA_S_SAMEFORMATETC;
341}
342
343STDMETHODIMP wxIDataObject::EnumFormatEtc(DWORD dwDirection,
344 IEnumFORMATETC **ppenumFormatEtc)
345{
346 wxLogTrace(_T("wxIDataObject::EnumFormatEtc"));
347
348 if ( dwDirection == DATADIR_SET ) {
349 // we don't allow setting of data anyhow
350 return E_NOTIMPL;
351 }
352
353 wxIEnumFORMATETC *pEnum =
354 new wxIEnumFORMATETC(m_pDataObject->GetPreferredFormat());
355 pEnum->AddRef();
356 *ppenumFormatEtc = pEnum;
357
358 return S_OK;
359}
360
361// advise sink functions (not implemented)
362STDMETHODIMP wxIDataObject::DAdvise(FORMATETC *pformatetc,
363 DWORD advf,
364 IAdviseSink *pAdvSink,
365 DWORD *pdwConnection)
366{
367 return OLE_E_ADVISENOTSUPPORTED;
368}
369
370STDMETHODIMP wxIDataObject::DUnadvise(DWORD dwConnection)
371{
372 return OLE_E_ADVISENOTSUPPORTED;
373}
374
375STDMETHODIMP wxIDataObject::EnumDAdvise(IEnumSTATDATA **ppenumAdvise)
376{
377 return OLE_E_ADVISENOTSUPPORTED;
378}
379
380// ----------------------------------------------------------------------------
381// wxDataObject
382// ----------------------------------------------------------------------------
383
384wxDataObject::wxDataObject()
385{
386 m_pIDataObject = new wxIDataObject(this);
387 m_pIDataObject->AddRef();
388}
389
390wxDataObject::~wxDataObject()
391{
392 m_pIDataObject->Release();
393}
394
395const char *wxDataObject::GetFormatName(wxDataFormat format)
396{
397#ifdef __WXDEBUG__
398 // case 'xxx' is not a valid value for switch of enum 'wxDataFormat'
399 #ifdef __VISUALC__
400 #pragma warning(disable:4063)
401 #endif // VC++
402
403 static char s_szBuf[128];
404 switch ( format ) {
405 case CF_TEXT: return "CF_TEXT";
406 case CF_BITMAP: return "CF_BITMAP";
407 case CF_METAFILEPICT: return "CF_METAFILEPICT";
408 case CF_SYLK: return "CF_SYLK";
409 case CF_DIF: return "CF_DIF";
410 case CF_TIFF: return "CF_TIFF";
411 case CF_OEMTEXT: return "CF_OEMTEXT";
412 case CF_DIB: return "CF_DIB";
413 case CF_PALETTE: return "CF_PALETTE";
414 case CF_PENDATA: return "CF_PENDATA";
415 case CF_RIFF: return "CF_RIFF";
416 case CF_WAVE: return "CF_WAVE";
417 case CF_UNICODETEXT: return "CF_UNICODETEXT";
418 case CF_ENHMETAFILE: return "CF_ENHMETAFILE";
419 case CF_HDROP: return "CF_HDROP";
420 case CF_LOCALE: return "CF_LOCALE";
421 default:
422 sprintf(s_szBuf, "clipboard format %d (unknown)", format);
423 return s_szBuf;
424 }
425
426 #ifdef __VISUALC__
427 #pragma warning(default:4063)
428 #endif // VC++
429
430#else // !Debug
431 return "";
432#endif // Debug
433}
434
435// ----------------------------------------------------------------------------
436// wxPrivateDataObject
437// ----------------------------------------------------------------------------
438
439wxPrivateDataObject::wxPrivateDataObject()
440{
441 m_size = 0;
442 m_data = NULL;
443}
444
445void wxPrivateDataObject::Free()
446{
447 if ( m_data )
448 free(m_data);
449}
450
451void wxPrivateDataObject::SetData( const void *data, size_t size )
452{
453 Free();
454
455 m_size = size;
456 m_data = malloc(size);
457
458 memcpy( m_data, data, size );
459}
460
461void wxPrivateDataObject::WriteData( void *dest ) const
462{
463 WriteData( m_data, dest );
464}
465
466size_t wxPrivateDataObject::GetSize() const
467{
468 return m_size;
469}
470
471void wxPrivateDataObject::WriteData( const void *data, void *dest ) const
472{
473 memcpy( dest, data, GetSize() );
474}
475
476// ----------------------------------------------------------------------------
477// private functions
478// ----------------------------------------------------------------------------
479static const char *GetTymedName(DWORD tymed)
480{
481 static char s_szBuf[128];
482 switch ( tymed ) {
483 case TYMED_HGLOBAL: return "TYMED_HGLOBAL";
484 case TYMED_FILE: return "TYMED_FILE";
485 case TYMED_ISTREAM: return "TYMED_ISTREAM";
486 case TYMED_ISTORAGE: return "TYMED_ISTORAGE";
487 case TYMED_GDI: return "TYMED_GDI";
488 case TYMED_MFPICT: return "TYMED_MFPICT";
489 case TYMED_ENHMF: return "TYMED_ENHMF";
490 default:
491 sprintf(s_szBuf, "type of media format %d (unknown)", tymed);
492 return s_szBuf;
493 }
494}
495
496// TODO: OLE parts of wxBitmap/File/MetafileDataObject
497
498#endif
499