]> git.saurik.com Git - wxWidgets.git/blob - src/msw/ole/dataobj.cpp
Some more Unicode changes.
[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/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 // wxDataFormat
106 // ----------------------------------------------------------------------------
107
108 void 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
117 wxString 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
141 BEGIN_IID_TABLE(wxIEnumFORMATETC)
142 ADD_IID(Unknown)
143 ADD_IID(EnumFORMATETC)
144 END_IID_TABLE;
145
146 IMPLEMENT_IUNKNOWN_METHODS(wxIEnumFORMATETC)
147
148 wxIEnumFORMATETC::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
159 STDMETHODIMP 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
178 STDMETHODIMP 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
188 STDMETHODIMP wxIEnumFORMATETC::Reset()
189 {
190 wxLogTrace(_T("wxIEnumFORMATETC::Reset"));
191
192 m_nCurrent = 0;
193
194 return S_OK;
195 }
196
197 STDMETHODIMP 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
212 BEGIN_IID_TABLE(wxIDataObject)
213 ADD_IID(Unknown)
214 ADD_IID(DataObject)
215 END_IID_TABLE;
216
217 IMPLEMENT_IUNKNOWN_METHODS(wxIDataObject)
218
219 wxIDataObject::wxIDataObject(wxDataObject *pDataObject)
220 {
221 m_cRef = 0;
222 m_pDataObject = pDataObject;
223 }
224
225 // get data functions
226 STDMETHODIMP 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
257 STDMETHODIMP 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)
281 STDMETHODIMP 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
290 STDMETHODIMP 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
332 STDMETHODIMP 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
343 STDMETHODIMP 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)
362 STDMETHODIMP wxIDataObject::DAdvise(FORMATETC *pformatetc,
363 DWORD advf,
364 IAdviseSink *pAdvSink,
365 DWORD *pdwConnection)
366 {
367 return OLE_E_ADVISENOTSUPPORTED;
368 }
369
370 STDMETHODIMP wxIDataObject::DUnadvise(DWORD dwConnection)
371 {
372 return OLE_E_ADVISENOTSUPPORTED;
373 }
374
375 STDMETHODIMP wxIDataObject::EnumDAdvise(IEnumSTATDATA **ppenumAdvise)
376 {
377 return OLE_E_ADVISENOTSUPPORTED;
378 }
379
380 // ----------------------------------------------------------------------------
381 // wxDataObject
382 // ----------------------------------------------------------------------------
383
384 wxDataObject::wxDataObject()
385 {
386 m_pIDataObject = new wxIDataObject(this);
387 m_pIDataObject->AddRef();
388 }
389
390 wxDataObject::~wxDataObject()
391 {
392 m_pIDataObject->Release();
393 }
394
395 const 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
439 wxPrivateDataObject::wxPrivateDataObject()
440 {
441 m_size = 0;
442 m_data = NULL;
443 }
444
445 void wxPrivateDataObject::Free()
446 {
447 if ( m_data )
448 free(m_data);
449 }
450
451 void 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
461 void wxPrivateDataObject::WriteData( void *dest ) const
462 {
463 WriteData( m_data, dest );
464 }
465
466 size_t wxPrivateDataObject::GetSize() const
467 {
468 return m_size;
469 }
470
471 void wxPrivateDataObject::WriteData( const void *data, void *dest ) const
472 {
473 memcpy( dest, data, GetSize() );
474 }
475
476 // ----------------------------------------------------------------------------
477 // private functions
478 // ----------------------------------------------------------------------------
479 static 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