]> git.saurik.com Git - wxWidgets.git/blame - src/msw/ole/dataobj.cpp
Better fix
[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
3f4a0c5b 5// Modified by:
269a5a34
VZ
6// Created: 10.05.98
7// RCS-ID: $Id$
8// Copyright: (c) 1998 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
65571936 9// Licence: wxWindows licence
269a5a34
VZ
10///////////////////////////////////////////////////////////////////////////////
11
12// ============================================================================
13// declarations
14// ============================================================================
15
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
19
269a5a34
VZ
20// For compilers that support precompilation, includes "wx.h".
21#include "wx/wxprec.h"
22
23#if defined(__BORLANDC__)
0d0512bd 24 #pragma hdrstop
269a5a34 25#endif
0d0512bd 26
7dee726c 27#ifndef WX_PRECOMP
0d0512bd
VZ
28 #include "wx/intl.h"
29 #include "wx/log.h"
daac16bb 30 #include "wx/utils.h"
193d0c93 31 #include "wx/wxcrtvararg.h"
7dee726c 32#endif
5260b1c5 33
3f480da3 34#include "wx/dataobj.h"
17b74d79 35
21709999
JS
36#if wxUSE_OLE && defined(__WIN32__) && !defined(__GNUWIN32_OLD__)
37
0d0512bd
VZ
38#include "wx/msw/private.h" // includes <windows.h>
39
4676948b
JS
40#ifdef __WXWINCE__
41#include <winreg.h>
42#endif
43
a7b4607f 44// for some compilers, the entire ole2.h must be included, not only oleauto.h
4676948b 45#if wxUSE_NORLANDER_HEADERS || defined(__WATCOMC__) || defined(__WXWINCE__)
7dee726c
RS
46 #include <ole2.h>
47#endif
269a5a34 48
a7b4607f 49#include <oleauto.h>
8b85d24e
VZ
50#include <shlobj.h>
51
0d0512bd
VZ
52#include "wx/msw/ole/oleutils.h"
53
54#include "wx/msw/dib.h"
17b74d79 55
dcbd7ce2
VS
56#ifndef CFSTR_SHELLURL
57#define CFSTR_SHELLURL _T("UniformResourceLocator")
58#endif
59
269a5a34
VZ
60// ----------------------------------------------------------------------------
61// functions
62// ----------------------------------------------------------------------------
63
8e193f38 64#ifdef __WXDEBUG__
d59ceba5 65 static const wxChar *GetTymedName(DWORD tymed);
1e8335b0 66#else // !Debug
fda7962d 67 #define GetTymedName(tymed) wxEmptyString
1e8335b0 68#endif // Debug/!Debug
269a5a34
VZ
69
70// ----------------------------------------------------------------------------
71// wxIEnumFORMATETC interface implementation
72// ----------------------------------------------------------------------------
8e193f38 73
269a5a34
VZ
74class wxIEnumFORMATETC : public IEnumFORMATETC
75{
76public:
8e193f38 77 wxIEnumFORMATETC(const wxDataFormat* formats, ULONG nCount);
33ac7e6f 78 virtual ~wxIEnumFORMATETC() { delete [] m_formats; }
269a5a34 79
8e193f38
VZ
80 // IEnumFORMATETC
81 STDMETHODIMP Next(ULONG celt, FORMATETC *rgelt, ULONG *pceltFetched);
82 STDMETHODIMP Skip(ULONG celt);
83 STDMETHODIMP Reset();
84 STDMETHODIMP Clone(IEnumFORMATETC **ppenum);
269a5a34 85
6f02a879
VZ
86 DECLARE_IUNKNOWN_METHODS;
87
269a5a34 88private:
8e193f38
VZ
89 CLIPFORMAT *m_formats; // formats we can provide data in
90 ULONG m_nCount, // number of formats we support
91 m_nCurrent; // current enum position
22f3361e
VZ
92
93 DECLARE_NO_COPY_CLASS(wxIEnumFORMATETC)
269a5a34
VZ
94};
95
96// ----------------------------------------------------------------------------
97// wxIDataObject implementation of IDataObject interface
98// ----------------------------------------------------------------------------
8e193f38 99
269a5a34
VZ
100class wxIDataObject : public IDataObject
101{
102public:
8e193f38 103 wxIDataObject(wxDataObject *pDataObject);
33ac7e6f 104 virtual ~wxIDataObject();
d59ceba5
VZ
105
106 // normally, wxDataObject controls our lifetime (i.e. we're deleted when it
3103e8a9 107 // is), but in some cases, the situation is reversed, that is we delete it
d59ceba5 108 // when this object is deleted - setting this flag enables such logic
17a6a2e0 109 void SetDeleteFlag() { m_mustDelete = true; }
269a5a34 110
8e193f38
VZ
111 // IDataObject
112 STDMETHODIMP GetData(FORMATETC *pformatetcIn, STGMEDIUM *pmedium);
113 STDMETHODIMP GetDataHere(FORMATETC *pformatetc, STGMEDIUM *pmedium);
114 STDMETHODIMP QueryGetData(FORMATETC *pformatetc);
115 STDMETHODIMP GetCanonicalFormatEtc(FORMATETC *In, FORMATETC *pOut);
116 STDMETHODIMP SetData(FORMATETC *pfetc, STGMEDIUM *pmedium, BOOL fRelease);
117 STDMETHODIMP EnumFormatEtc(DWORD dwDirection, IEnumFORMATETC **ppenumFEtc);
118 STDMETHODIMP DAdvise(FORMATETC *pfetc, DWORD ad, IAdviseSink *p, DWORD *pdw);
119 STDMETHODIMP DUnadvise(DWORD dwConnection);
120 STDMETHODIMP EnumDAdvise(IEnumSTATDATA **ppenumAdvise);
269a5a34 121
6f02a879
VZ
122 DECLARE_IUNKNOWN_METHODS;
123
269a5a34 124private:
8e193f38 125 wxDataObject *m_pDataObject; // pointer to C++ class we belong to
d59ceba5
VZ
126
127 bool m_mustDelete;
22f3361e
VZ
128
129 DECLARE_NO_COPY_CLASS(wxIDataObject)
d59ceba5
VZ
130};
131
269a5a34
VZ
132// ============================================================================
133// implementation
134// ============================================================================
135
3f480da3
VZ
136// ----------------------------------------------------------------------------
137// wxDataFormat
138// ----------------------------------------------------------------------------
139
a1eb65c2 140void wxDataFormat::SetId(const wxString& format)
3f480da3 141{
e0a050e3 142 m_format = (wxDataFormat::NativeFormat)::RegisterClipboardFormat(format.wx_str());
3f480da3
VZ
143 if ( !m_format )
144 {
145 wxLogError(_("Couldn't register clipboard format '%s'."), format);
146 }
147}
148
149wxString wxDataFormat::GetId() const
150{
151 static const int max = 256;
152
153 wxString s;
154
155 wxCHECK_MSG( !IsStandard(), s,
223d09f6 156 wxT("name of predefined format cannot be retrieved") );
3f480da3 157
de564874 158 int len = ::GetClipboardFormatName(m_format, wxStringBuffer(s, max), max);
3f480da3
VZ
159
160 if ( !len )
161 {
162 wxLogError(_("The clipboard format '%d' doesn't exist."), m_format);
5712281c 163 return wxEmptyString;
3f480da3
VZ
164 }
165
166 return s;
167}
168
269a5a34
VZ
169// ----------------------------------------------------------------------------
170// wxIEnumFORMATETC
171// ----------------------------------------------------------------------------
172
173BEGIN_IID_TABLE(wxIEnumFORMATETC)
8e193f38
VZ
174 ADD_IID(Unknown)
175 ADD_IID(EnumFORMATETC)
269a5a34
VZ
176END_IID_TABLE;
177
178IMPLEMENT_IUNKNOWN_METHODS(wxIEnumFORMATETC)
179
8e193f38 180wxIEnumFORMATETC::wxIEnumFORMATETC(const wxDataFormat *formats, ULONG nCount)
269a5a34 181{
8e193f38
VZ
182 m_nCurrent = 0;
183 m_nCount = nCount;
184 m_formats = new CLIPFORMAT[nCount];
185 for ( ULONG n = 0; n < nCount; n++ ) {
186 m_formats[n] = formats[n].GetFormatId();
187 }
269a5a34
VZ
188}
189
190STDMETHODIMP wxIEnumFORMATETC::Next(ULONG celt,
191 FORMATETC *rgelt,
1f1c4210 192 ULONG *pceltFetched)
269a5a34 193{
8e193f38 194 wxLogTrace(wxTRACE_OleCalls, wxT("wxIEnumFORMATETC::Next"));
269a5a34 195
1f1c4210
VZ
196 ULONG numFetched = 0;
197 while (m_nCurrent < m_nCount && numFetched < celt) {
8e193f38
VZ
198 FORMATETC format;
199 format.cfFormat = m_formats[m_nCurrent++];
200 format.ptd = NULL;
201 format.dwAspect = DVASPECT_CONTENT;
202 format.lindex = -1;
203 format.tymed = TYMED_HGLOBAL;
269a5a34 204
1f1c4210
VZ
205 *rgelt++ = format;
206 numFetched++;
8e193f38 207 }
1f1c4210
VZ
208
209 if (pceltFetched)
210 *pceltFetched = numFetched;
211
212 return numFetched == celt ? S_OK : S_FALSE;
269a5a34
VZ
213}
214
215STDMETHODIMP wxIEnumFORMATETC::Skip(ULONG celt)
216{
8e193f38
VZ
217 wxLogTrace(wxTRACE_OleCalls, wxT("wxIEnumFORMATETC::Skip"));
218
219 m_nCurrent += celt;
220 if ( m_nCurrent < m_nCount )
221 return S_OK;
269a5a34 222
8e193f38
VZ
223 // no, can't skip this many elements
224 m_nCurrent -= celt;
269a5a34 225
8e193f38 226 return S_FALSE;
269a5a34
VZ
227}
228
229STDMETHODIMP wxIEnumFORMATETC::Reset()
230{
8e193f38 231 wxLogTrace(wxTRACE_OleCalls, wxT("wxIEnumFORMATETC::Reset"));
269a5a34 232
8e193f38 233 m_nCurrent = 0;
269a5a34 234
8e193f38 235 return S_OK;
269a5a34
VZ
236}
237
238STDMETHODIMP wxIEnumFORMATETC::Clone(IEnumFORMATETC **ppenum)
239{
8e193f38
VZ
240 wxLogTrace(wxTRACE_OleCalls, wxT("wxIEnumFORMATETC::Clone"));
241
242 // unfortunately, we can't reuse the code in ctor - types are different
243 wxIEnumFORMATETC *pNew = new wxIEnumFORMATETC(NULL, 0);
244 pNew->m_nCount = m_nCount;
245 pNew->m_formats = new CLIPFORMAT[m_nCount];
246 for ( ULONG n = 0; n < m_nCount; n++ ) {
247 pNew->m_formats[n] = m_formats[n];
248 }
249 pNew->AddRef();
250 *ppenum = pNew;
269a5a34 251
8e193f38 252 return S_OK;
269a5a34
VZ
253}
254
255// ----------------------------------------------------------------------------
256// wxIDataObject
257// ----------------------------------------------------------------------------
258
259BEGIN_IID_TABLE(wxIDataObject)
8e193f38
VZ
260 ADD_IID(Unknown)
261 ADD_IID(DataObject)
269a5a34
VZ
262END_IID_TABLE;
263
264IMPLEMENT_IUNKNOWN_METHODS(wxIDataObject)
265
266wxIDataObject::wxIDataObject(wxDataObject *pDataObject)
267{
8e193f38 268 m_pDataObject = pDataObject;
17a6a2e0 269 m_mustDelete = false;
d59ceba5
VZ
270}
271
272wxIDataObject::~wxIDataObject()
273{
274 if ( m_mustDelete )
275 {
276 delete m_pDataObject;
277 }
269a5a34
VZ
278}
279
280// get data functions
281STDMETHODIMP wxIDataObject::GetData(FORMATETC *pformatetcIn, STGMEDIUM *pmedium)
282{
8e193f38 283 wxLogTrace(wxTRACE_OleCalls, wxT("wxIDataObject::GetData"));
269a5a34 284
8e193f38
VZ
285 // is data is in our format?
286 HRESULT hr = QueryGetData(pformatetcIn);
287 if ( FAILED(hr) )
288 return hr;
269a5a34 289
8e193f38
VZ
290 // for the bitmaps and metafiles we use the handles instead of global memory
291 // to pass the data
f4d0cce0 292 wxDataFormat format = (wxDataFormat::NativeFormat)pformatetcIn->cfFormat;
269a5a34 293
8e193f38
VZ
294 switch ( format )
295 {
296 case wxDF_BITMAP:
297 pmedium->tymed = TYMED_GDI;
298 break;
299
d9317fd4
VZ
300 case wxDF_ENHMETAFILE:
301 pmedium->tymed = TYMED_ENHMF;
302 break;
303
4676948b 304#ifndef __WXWINCE__
8e193f38 305 case wxDF_METAFILE:
265b0c07
VZ
306 pmedium->hGlobal = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE,
307 sizeof(METAFILEPICT));
308 if ( !pmedium->hGlobal ) {
f6bcfd97 309 wxLogLastError(wxT("GlobalAlloc"));
265b0c07
VZ
310 return E_OUTOFMEMORY;
311 }
8e193f38
VZ
312 pmedium->tymed = TYMED_MFPICT;
313 break;
4676948b 314#endif
8e193f38
VZ
315 default:
316 // alloc memory
317 size_t size = m_pDataObject->GetDataSize(format);
318 if ( !size ) {
319 // it probably means that the method is just not implemented
320 wxLogDebug(wxT("Invalid data size - can't be 0"));
321
322 return DV_E_FORMATETC;
323 }
324
a8e24848
VZ
325 // we may need extra space for the buffer size
326 size += m_pDataObject->GetBufferOffset( format );
9e2896e5 327
8e193f38
VZ
328 HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, size);
329 if ( hGlobal == NULL ) {
f6bcfd97 330 wxLogLastError(wxT("GlobalAlloc"));
8e193f38
VZ
331 return E_OUTOFMEMORY;
332 }
333
334 // copy data
335 pmedium->tymed = TYMED_HGLOBAL;
336 pmedium->hGlobal = hGlobal;
337 }
269a5a34 338
8e193f38
VZ
339 pmedium->pUnkForRelease = NULL;
340
341 // do copy the data
342 hr = GetDataHere(pformatetcIn, pmedium);
343 if ( FAILED(hr) ) {
344 // free resources we allocated
265b0c07 345 if ( pmedium->tymed & (TYMED_HGLOBAL | TYMED_MFPICT) ) {
8e193f38
VZ
346 GlobalFree(pmedium->hGlobal);
347 }
348
349 return hr;
350 }
269a5a34 351
8e193f38 352 return S_OK;
269a5a34
VZ
353}
354
355STDMETHODIMP wxIDataObject::GetDataHere(FORMATETC *pformatetc,
356 STGMEDIUM *pmedium)
357{
8e193f38 358 wxLogTrace(wxTRACE_OleCalls, wxT("wxIDataObject::GetDataHere"));
269a5a34 359
8e193f38
VZ
360 // put data in caller provided medium
361 switch ( pmedium->tymed )
362 {
363 case TYMED_GDI:
d59ceba5
VZ
364 if ( !m_pDataObject->GetDataHere(wxDF_BITMAP, &pmedium->hBitmap) )
365 return E_UNEXPECTED;
8e193f38
VZ
366 break;
367
d9317fd4
VZ
368 case TYMED_ENHMF:
369 if ( !m_pDataObject->GetDataHere(wxDF_ENHMETAFILE,
370 &pmedium->hEnhMetaFile) )
371 return E_UNEXPECTED;
372 break;
373
8e193f38 374 case TYMED_MFPICT:
d9317fd4
VZ
375 // fall through - we pass METAFILEPICT through HGLOBAL
376
8e193f38
VZ
377 case TYMED_HGLOBAL:
378 {
379 // copy data
9e2896e5
VZ
380 HGLOBAL hGlobal = pmedium->hGlobal;
381 void *pBuf = GlobalLock(hGlobal);
8e193f38
VZ
382 if ( pBuf == NULL ) {
383 wxLogLastError(wxT("GlobalLock"));
384 return E_OUTOFMEMORY;
385 }
386
e1b435af 387 wxDataFormat format = pformatetc->cfFormat;
a8e24848
VZ
388
389 // possibly put the size in the beginning of the buffer
390 pBuf = m_pDataObject->SetSizeInBuffer
391 (
392 pBuf,
393 ::GlobalSize(hGlobal),
394 format
395 );
9e2896e5 396
d59ceba5
VZ
397 if ( !m_pDataObject->GetDataHere(format, pBuf) )
398 return E_UNEXPECTED;
8e193f38 399
9e2896e5 400 GlobalUnlock(hGlobal);
8e193f38
VZ
401 }
402 break;
403
404 default:
405 return DV_E_TYMED;
406 }
269a5a34 407
8e193f38 408 return S_OK;
269a5a34
VZ
409}
410
d26fad77 411
9e2896e5 412// set data functions
269a5a34
VZ
413STDMETHODIMP wxIDataObject::SetData(FORMATETC *pformatetc,
414 STGMEDIUM *pmedium,
415 BOOL fRelease)
416{
d59ceba5 417 wxLogTrace(wxTRACE_OleCalls, wxT("wxIDataObject::SetData"));
8e193f38 418
d59ceba5
VZ
419 switch ( pmedium->tymed )
420 {
421 case TYMED_GDI:
9e2896e5 422 m_pDataObject->SetData(wxDF_BITMAP, 0, &pmedium->hBitmap);
d59ceba5
VZ
423 break;
424
d9317fd4
VZ
425 case TYMED_ENHMF:
426 m_pDataObject->SetData(wxDF_ENHMETAFILE, 0, &pmedium->hEnhMetaFile);
427 break;
428
d59ceba5 429 case TYMED_MFPICT:
d9317fd4 430 // fall through - we pass METAFILEPICT through HGLOBAL
d59ceba5
VZ
431 case TYMED_HGLOBAL:
432 {
51edda6a
VZ
433 wxDataFormat format = pformatetc->cfFormat;
434
435 // this is quite weird, but for file drag and drop, explorer
436 // calls our SetData() with the formats we do *not* support!
437 //
438 // as we can't fix this bug in explorer (it's a bug because it
439 // should only use formats returned by EnumFormatEtc), do the
440 // check here
5015e022 441 if ( !m_pDataObject->IsSupported(format, wxDataObject::Set) ) {
51edda6a
VZ
442 // go away!
443 return DV_E_FORMATETC;
444 }
445
d59ceba5 446 // copy data
e1b435af 447 const void *pBuf = GlobalLock(pmedium->hGlobal);
d59ceba5 448 if ( pBuf == NULL ) {
f6bcfd97 449 wxLogLastError(wxT("GlobalLock"));
d59ceba5
VZ
450
451 return E_OUTOFMEMORY;
452 }
453
9e2896e5
VZ
454 // we've got a problem with SetData() here because the base
455 // class version requires the size parameter which we don't
456 // have anywhere in OLE data transfer - so we need to
457 // synthetise it for known formats and we suppose that all data
458 // in custom formats starts with a DWORD containing the size
459 size_t size;
51edda6a 460 switch ( format )
9e2896e5
VZ
461 {
462 case CF_TEXT:
463 case CF_OEMTEXT:
464 size = strlen((const char *)pBuf);
465 break;
afd23c22 466#if !(defined(__BORLANDC__) && (__BORLANDC__ < 0x500))
9e2896e5 467 case CF_UNICODETEXT:
de85a884
VZ
468#if ( defined(__BORLANDC__) && (__BORLANDC__ > 0x530) ) \
469 || ( defined(__MWERKS__) && defined(__WXMSW__) )
e1b435af 470 size = std::wcslen((const wchar_t *)pBuf) * sizeof(wchar_t);
d834f22c 471#else
17ebae65 472 size = wxWcslen((const wchar_t *)pBuf) * sizeof(wchar_t);
d834f22c 473#endif
9e2896e5 474 break;
4d85bcd1 475#endif
9e2896e5 476 case CF_BITMAP:
4676948b 477#ifndef __WXWINCE__
9e2896e5
VZ
478 case CF_HDROP:
479 // these formats don't use size at all, anyhow (but
480 // pass data by handle, which is always a single DWORD)
481 size = 0;
482 break;
4676948b 483#endif
9e2896e5 484
8ee9d618
VZ
485 case CF_DIB:
486 // the handler will calculate size itself (it's too
487 // complicated to do it here)
488 size = 0;
489 break;
490
4676948b 491#ifndef __WXWINCE__
265b0c07
VZ
492 case CF_METAFILEPICT:
493 size = sizeof(METAFILEPICT);
494 break;
4676948b 495#endif
9e2896e5 496 default:
a8e24848
VZ
497 pBuf = m_pDataObject->
498 GetSizeFromBuffer(pBuf, &size, format);
499 size -= m_pDataObject->GetBufferOffset(format);
9e2896e5
VZ
500 }
501
9e2896e5 502 bool ok = m_pDataObject->SetData(format, size, pBuf);
d59ceba5
VZ
503
504 GlobalUnlock(pmedium->hGlobal);
9e2896e5
VZ
505
506 if ( !ok ) {
507 return E_UNEXPECTED;
508 }
d59ceba5
VZ
509 }
510 break;
511
512 default:
513 return DV_E_TYMED;
514 }
515
516 if ( fRelease ) {
265b0c07
VZ
517 // we own the medium, so we must release it - but do *not* free any
518 // data we pass by handle because we have copied it elsewhere
519 switch ( pmedium->tymed )
d59ceba5 520 {
265b0c07
VZ
521 case TYMED_GDI:
522 pmedium->hBitmap = 0;
523 break;
524
525 case TYMED_MFPICT:
526 pmedium->hMetaFilePict = 0;
527 break;
d9317fd4
VZ
528
529 case TYMED_ENHMF:
530 pmedium->hEnhMetaFile = 0;
531 break;
d59ceba5
VZ
532 }
533
534 ReleaseStgMedium(pmedium);
535 }
536
537 return S_OK;
269a5a34
VZ
538}
539
540// information functions
541STDMETHODIMP wxIDataObject::QueryGetData(FORMATETC *pformatetc)
542{
d59ceba5
VZ
543 // do we accept data in this format?
544 if ( pformatetc == NULL ) {
545 wxLogTrace(wxTRACE_OleCalls,
546 wxT("wxIDataObject::QueryGetData: invalid ptr."));
8e193f38 547
d59ceba5
VZ
548 return E_INVALIDARG;
549 }
269a5a34 550
d59ceba5
VZ
551 // the only one allowed by current COM implementation
552 if ( pformatetc->lindex != -1 ) {
553 wxLogTrace(wxTRACE_OleCalls,
9b601c24 554 wxT("wxIDataObject::QueryGetData: bad lindex %ld"),
d59ceba5 555 pformatetc->lindex);
269a5a34 556
d59ceba5
VZ
557 return DV_E_LINDEX;
558 }
269a5a34 559
d59ceba5
VZ
560 // we don't support anything other (THUMBNAIL, ICON, DOCPRINT...)
561 if ( pformatetc->dwAspect != DVASPECT_CONTENT ) {
562 wxLogTrace(wxTRACE_OleCalls,
9b601c24 563 wxT("wxIDataObject::QueryGetData: bad dwAspect %ld"),
d59ceba5
VZ
564 pformatetc->dwAspect);
565
566 return DV_E_DVASPECT;
567 }
568
569 // and now check the type of data requested
9e2896e5 570 wxDataFormat format = pformatetc->cfFormat;
d59ceba5 571 if ( m_pDataObject->IsSupportedFormat(format) ) {
d59ceba5 572 wxLogTrace(wxTRACE_OleCalls, wxT("wxIDataObject::QueryGetData: %s ok"),
1e8335b0 573 wxGetFormatName(format));
d59ceba5
VZ
574 }
575 else {
576 wxLogTrace(wxTRACE_OleCalls,
577 wxT("wxIDataObject::QueryGetData: %s unsupported"),
1e8335b0 578 wxGetFormatName(format));
9e2896e5 579
d59ceba5
VZ
580 return DV_E_FORMATETC;
581 }
582
583 // we only transfer data by global memory, except for some particular cases
584 DWORD tymed = pformatetc->tymed;
585 if ( (format == wxDF_BITMAP && !(tymed & TYMED_GDI)) &&
586 !(tymed & TYMED_HGLOBAL) ) {
587 // it's not what we're waiting for
d59ceba5
VZ
588 wxLogTrace(wxTRACE_OleCalls,
589 wxT("wxIDataObject::QueryGetData: %s != %s"),
590 GetTymedName(tymed),
591 GetTymedName(format == wxDF_BITMAP ? TYMED_GDI
592 : TYMED_HGLOBAL));
d59ceba5
VZ
593
594 return DV_E_TYMED;
595 }
596
269a5a34 597 return S_OK;
269a5a34
VZ
598}
599
33ac7e6f 600STDMETHODIMP wxIDataObject::GetCanonicalFormatEtc(FORMATETC *WXUNUSED(pFormatetcIn),
269a5a34
VZ
601 FORMATETC *pFormatetcOut)
602{
8e193f38
VZ
603 wxLogTrace(wxTRACE_OleCalls, wxT("wxIDataObject::GetCanonicalFormatEtc"));
604
605 // TODO we might want something better than this trivial implementation here
606 if ( pFormatetcOut != NULL )
607 pFormatetcOut->ptd = NULL;
269a5a34 608
8e193f38 609 return DATA_S_SAMEFORMATETC;
269a5a34
VZ
610}
611
9e2896e5 612STDMETHODIMP wxIDataObject::EnumFormatEtc(DWORD dwDir,
269a5a34
VZ
613 IEnumFORMATETC **ppenumFormatEtc)
614{
8e193f38 615 wxLogTrace(wxTRACE_OleCalls, wxT("wxIDataObject::EnumFormatEtc"));
269a5a34 616
9e2896e5
VZ
617 wxDataObject::Direction dir = dwDir == DATADIR_GET ? wxDataObject::Get
618 : wxDataObject::Set;
269a5a34 619
4a10ea8b 620 ULONG nFormatCount = wx_truncate_cast(ULONG, m_pDataObject->GetFormatCount(dir));
33ac7e6f 621 wxDataFormat format;
c5639a87 622 wxDataFormat *formats;
9e2896e5
VZ
623 formats = nFormatCount == 1 ? &format : new wxDataFormat[nFormatCount];
624 m_pDataObject->GetAllFormats(formats, dir);
8e193f38
VZ
625
626 wxIEnumFORMATETC *pEnum = new wxIEnumFORMATETC(formats, nFormatCount);
627 pEnum->AddRef();
628 *ppenumFormatEtc = pEnum;
629
630 if ( formats != &format ) {
631 delete [] formats;
632 }
269a5a34 633
8e193f38 634 return S_OK;
269a5a34
VZ
635}
636
9e2896e5 637// ----------------------------------------------------------------------------
269a5a34 638// advise sink functions (not implemented)
9e2896e5
VZ
639// ----------------------------------------------------------------------------
640
33ac7e6f
KB
641STDMETHODIMP wxIDataObject::DAdvise(FORMATETC *WXUNUSED(pformatetc),
642 DWORD WXUNUSED(advf),
643 IAdviseSink *WXUNUSED(pAdvSink),
644 DWORD *WXUNUSED(pdwConnection))
269a5a34
VZ
645{
646 return OLE_E_ADVISENOTSUPPORTED;
647}
648
33ac7e6f 649STDMETHODIMP wxIDataObject::DUnadvise(DWORD WXUNUSED(dwConnection))
269a5a34
VZ
650{
651 return OLE_E_ADVISENOTSUPPORTED;
652}
653
33ac7e6f 654STDMETHODIMP wxIDataObject::EnumDAdvise(IEnumSTATDATA **WXUNUSED(ppenumAdvise))
269a5a34
VZ
655{
656 return OLE_E_ADVISENOTSUPPORTED;
657}
658
659// ----------------------------------------------------------------------------
660// wxDataObject
661// ----------------------------------------------------------------------------
662
663wxDataObject::wxDataObject()
664{
d59ceba5
VZ
665 m_pIDataObject = new wxIDataObject(this);
666 m_pIDataObject->AddRef();
269a5a34
VZ
667}
668
669wxDataObject::~wxDataObject()
670{
d59ceba5
VZ
671 ReleaseInterface(m_pIDataObject);
672}
673
674void wxDataObject::SetAutoDelete()
675{
676 ((wxIDataObject *)m_pIDataObject)->SetDeleteFlag();
677 m_pIDataObject->Release();
678
679 // so that the dtor doesnt' crash
680 m_pIDataObject = NULL;
269a5a34
VZ
681}
682
a8e24848 683size_t wxDataObject::GetBufferOffset(const wxDataFormat& format )
e1b435af 684{
a8e24848
VZ
685 // if we prepend the size of the data to the buffer itself, account for it
686 return NeedsVerbatimData(format) ? 0 : sizeof(size_t);
e1b435af
MB
687}
688
abb88ef3
VZ
689const void *wxDataObject::GetSizeFromBuffer(const void *buffer,
690 size_t *size,
cb626df2 691 const wxDataFormat& WXUNUSED(format))
e1b435af 692{
24aab8e8
MW
693 // hack: the third parameter is declared non-const in Wine's headers so
694 // cast away the const
abb88ef3
VZ
695 const size_t realsz = ::HeapSize(::GetProcessHeap(), 0,
696 wx_const_cast(void*, buffer));
51d05226 697 if ( realsz == (size_t)-1 )
a8e24848
VZ
698 {
699 // note that HeapSize() does not set last error
700 wxLogApiError(wxT("HeapSize"), 0);
701 return NULL;
702 }
703
704 *size = realsz;
e1b435af 705
abb88ef3 706 return buffer;
e1b435af
MB
707}
708
709void* wxDataObject::SetSizeInBuffer( void* buffer, size_t size,
a8e24848 710 const wxDataFormat& format )
e1b435af 711{
a8e24848
VZ
712 size_t* p = (size_t *)buffer;
713 if ( !NeedsVerbatimData(format) )
714 {
715 // prepend the size to the data and skip it
716 *p++ = size;
717 }
e1b435af 718
a8e24848 719 return p;
e1b435af
MB
720}
721
d9317fd4 722#ifdef __WXDEBUG__
8e193f38 723
f6bcfd97 724const wxChar *wxDataObject::GetFormatName(wxDataFormat format)
d9317fd4
VZ
725{
726 // case 'xxx' is not a valid value for switch of enum 'wxDataFormat'
727 #ifdef __VISUALC__
728 #pragma warning(disable:4063)
729 #endif // VC++
730
f6bcfd97 731 static wxChar s_szBuf[256];
d9317fd4 732 switch ( format ) {
f6bcfd97
BP
733 case CF_TEXT: return wxT("CF_TEXT");
734 case CF_BITMAP: return wxT("CF_BITMAP");
f6bcfd97
BP
735 case CF_SYLK: return wxT("CF_SYLK");
736 case CF_DIF: return wxT("CF_DIF");
737 case CF_TIFF: return wxT("CF_TIFF");
738 case CF_OEMTEXT: return wxT("CF_OEMTEXT");
739 case CF_DIB: return wxT("CF_DIB");
740 case CF_PALETTE: return wxT("CF_PALETTE");
741 case CF_PENDATA: return wxT("CF_PENDATA");
742 case CF_RIFF: return wxT("CF_RIFF");
743 case CF_WAVE: return wxT("CF_WAVE");
744 case CF_UNICODETEXT: return wxT("CF_UNICODETEXT");
569f027b
VS
745#ifndef __WXWINCE__
746 case CF_METAFILEPICT: return wxT("CF_METAFILEPICT");
f6bcfd97 747 case CF_ENHMETAFILE: return wxT("CF_ENHMETAFILE");
f6bcfd97 748 case CF_LOCALE: return wxT("CF_LOCALE");
569f027b
VS
749 case CF_HDROP: return wxT("CF_HDROP");
750#endif
8e193f38 751
d9317fd4 752 default:
c77ae1d9 753 if ( !::GetClipboardFormatName(format, s_szBuf, WXSIZEOF(s_szBuf)) )
d9317fd4
VZ
754 {
755 // it must be a new predefined format we don't know the name of
f6bcfd97 756 wxSprintf(s_szBuf, wxT("unknown CF (0x%04x)"), format.GetFormatId());
d9317fd4 757 }
8e193f38 758
d9317fd4 759 return s_szBuf;
8e193f38 760 }
1e8335b0 761
d9317fd4
VZ
762 #ifdef __VISUALC__
763 #pragma warning(default:4063)
764 #endif // VC++
269a5a34
VZ
765}
766
1e8335b0
VZ
767#endif // Debug
768
3f480da3 769// ----------------------------------------------------------------------------
9e2896e5 770// wxBitmapDataObject supports CF_DIB format
3f480da3
VZ
771// ----------------------------------------------------------------------------
772
be69f971
VZ
773// TODO: support CF_DIB under Windows CE as well
774
9e2896e5 775size_t wxBitmapDataObject::GetDataSize() const
3f480da3 776{
be69f971 777#if wxUSE_WXDIB && !defined(__WXWINCE__)
22be0335 778 return wxDIB::ConvertFromBitmap(NULL, GetHbitmapOf(GetBitmap()));
4cb88a72
JS
779#else
780 return 0;
781#endif
3f480da3
VZ
782}
783
9e2896e5 784bool wxBitmapDataObject::GetDataHere(void *buf) const
3f480da3 785{
be69f971 786#if wxUSE_WXDIB && !defined(__WXWINCE__)
22be0335
VZ
787 BITMAPINFO * const pbi = (BITMAPINFO *)buf;
788
789 return wxDIB::ConvertFromBitmap(pbi, GetHbitmapOf(GetBitmap())) != 0;
4cb88a72 790#else
17a6a2e0
WS
791 wxUnusedVar(buf);
792 return false;
4cb88a72 793#endif
3f480da3
VZ
794}
795
33ac7e6f 796bool wxBitmapDataObject::SetData(size_t WXUNUSED(len), const void *buf)
3f480da3 797{
be69f971 798#if wxUSE_WXDIB && !defined(__WXWINCE__)
22be0335 799 const BITMAPINFO * const pbmi = (const BITMAPINFO *)buf;
9e2896e5 800
22be0335 801 HBITMAP hbmp = wxDIB::ConvertToBitmap(pbmi);
3f480da3 802
22be0335
VZ
803 wxCHECK_MSG( hbmp, FALSE, wxT("pasting/dropping invalid bitmap") );
804
805 const BITMAPINFOHEADER * const pbmih = &pbmi->bmiHeader;
806 wxBitmap bitmap(pbmih->biWidth, pbmih->biHeight, pbmih->biBitCount);
807 bitmap.SetHBITMAP((WXHBITMAP)hbmp);
808
809 // TODO: create wxPalette if the bitmap has any
9e2896e5
VZ
810
811 SetBitmap(bitmap);
3f480da3 812
17a6a2e0 813 return true;
4cb88a72 814#else
17a6a2e0
WS
815 wxUnusedVar(buf);
816 return false;
4cb88a72 817#endif
3f480da3
VZ
818}
819
9e2896e5
VZ
820// ----------------------------------------------------------------------------
821// wxBitmapDataObject2 supports CF_BITMAP format
822// ----------------------------------------------------------------------------
823
824// the bitmaps aren't passed by value as other types of data (i.e. by copying
825// the data into a global memory chunk and passing it to the clipboard or
826// another application or whatever), but by handle, so these generic functions
827// don't make much sense to them.
828
829size_t wxBitmapDataObject2::GetDataSize() const
3f480da3 830{
9e2896e5 831 return 0;
3f480da3
VZ
832}
833
9e2896e5 834bool wxBitmapDataObject2::GetDataHere(void *pBuf) const
3f480da3 835{
9e2896e5
VZ
836 // we put a bitmap handle into pBuf
837 *(WXHBITMAP *)pBuf = GetBitmap().GetHBITMAP();
838
17a6a2e0 839 return true;
3f480da3
VZ
840}
841
265b0c07 842bool wxBitmapDataObject2::SetData(size_t WXUNUSED(len), const void *pBuf)
3f480da3 843{
9e2896e5 844 HBITMAP hbmp = *(HBITMAP *)pBuf;
3f480da3 845
9e2896e5
VZ
846 BITMAP bmp;
847 if ( !GetObject(hbmp, sizeof(BITMAP), &bmp) )
848 {
f6bcfd97 849 wxLogLastError(wxT("GetObject(HBITMAP)"));
9e2896e5 850 }
8e193f38 851
9e2896e5
VZ
852 wxBitmap bitmap(bmp.bmWidth, bmp.bmHeight, bmp.bmPlanes);
853 bitmap.SetHBITMAP((WXHBITMAP)hbmp);
d59ceba5 854
9e2896e5
VZ
855 if ( !bitmap.Ok() ) {
856 wxFAIL_MSG(wxT("pasting/dropping invalid bitmap"));
857
17a6a2e0 858 return false;
9e2896e5
VZ
859 }
860
861 SetBitmap(bitmap);
862
17a6a2e0 863 return true;
d59ceba5
VZ
864}
865
9e2896e5 866#if 0
8e193f38
VZ
867
868size_t wxBitmapDataObject::GetDataSize(const wxDataFormat& format) const
869{
d59ceba5
VZ
870 if ( format.GetFormatId() == CF_DIB )
871 {
872 // create the DIB
873 ScreenHDC hdc;
874
875 // shouldn't be selected into a DC or GetDIBits() would fail
876 wxASSERT_MSG( !m_bitmap.GetSelectedInto(),
877 wxT("can't copy bitmap selected into wxMemoryDC") );
878
879 // first get the info
880 BITMAPINFO bi;
881 if ( !GetDIBits(hdc, (HBITMAP)m_bitmap.GetHBITMAP(), 0, 0,
882 NULL, &bi, DIB_RGB_COLORS) )
883 {
f6bcfd97 884 wxLogLastError(wxT("GetDIBits(NULL)"));
d59ceba5
VZ
885
886 return 0;
887 }
888
889 return sizeof(BITMAPINFO) + bi.bmiHeader.biSizeImage;
890 }
891 else // CF_BITMAP
892 {
893 // no data to copy - we don't pass HBITMAP via global memory
894 return 0;
895 }
8e193f38
VZ
896}
897
d59ceba5 898bool wxBitmapDataObject::GetDataHere(const wxDataFormat& format,
8e193f38
VZ
899 void *pBuf) const
900{
d59ceba5
VZ
901 wxASSERT_MSG( m_bitmap.Ok(), wxT("copying invalid bitmap") );
902
903 HBITMAP hbmp = (HBITMAP)m_bitmap.GetHBITMAP();
904 if ( format.GetFormatId() == CF_DIB )
905 {
906 // create the DIB
907 ScreenHDC hdc;
908
909 // shouldn't be selected into a DC or GetDIBits() would fail
910 wxASSERT_MSG( !m_bitmap.GetSelectedInto(),
911 wxT("can't copy bitmap selected into wxMemoryDC") );
912
913 // first get the info
914 BITMAPINFO *pbi = (BITMAPINFO *)pBuf;
915 if ( !GetDIBits(hdc, hbmp, 0, 0, NULL, pbi, DIB_RGB_COLORS) )
916 {
f6bcfd97 917 wxLogLastError(wxT("GetDIBits(NULL)"));
d59ceba5
VZ
918
919 return 0;
920 }
921
922 // and now copy the bits
923 if ( !GetDIBits(hdc, hbmp, 0, pbi->bmiHeader.biHeight, pbi + 1,
924 pbi, DIB_RGB_COLORS) )
925 {
f6bcfd97 926 wxLogLastError(wxT("GetDIBits"));
d59ceba5 927
17a6a2e0 928 return false;
d59ceba5
VZ
929 }
930 }
931 else // CF_BITMAP
932 {
933 // we put a bitmap handle into pBuf
934 *(HBITMAP *)pBuf = hbmp;
935 }
936
17a6a2e0 937 return true;
d59ceba5
VZ
938}
939
9e2896e5
VZ
940bool wxBitmapDataObject::SetData(const wxDataFormat& format,
941 size_t size, const void *pBuf)
d59ceba5
VZ
942{
943 HBITMAP hbmp;
944 if ( format.GetFormatId() == CF_DIB )
945 {
946 // here we get BITMAPINFO struct followed by the actual bitmap bits and
947 // BITMAPINFO starts with BITMAPINFOHEADER followed by colour info
948 ScreenHDC hdc;
949
950 BITMAPINFO *pbmi = (BITMAPINFO *)pBuf;
951 BITMAPINFOHEADER *pbmih = &pbmi->bmiHeader;
952 hbmp = CreateDIBitmap(hdc, pbmih, CBM_INIT,
953 pbmi + 1, pbmi, DIB_RGB_COLORS);
954 if ( !hbmp )
955 {
f6bcfd97 956 wxLogLastError(wxT("CreateDIBitmap"));
d59ceba5
VZ
957 }
958
959 m_bitmap.SetWidth(pbmih->biWidth);
960 m_bitmap.SetHeight(pbmih->biHeight);
961 }
962 else // CF_BITMAP
963 {
964 // it's easy with bitmaps: we pass them by handle
965 hbmp = *(HBITMAP *)pBuf;
966
967 BITMAP bmp;
968 if ( !GetObject(hbmp, sizeof(BITMAP), &bmp) )
969 {
f6bcfd97 970 wxLogLastError(wxT("GetObject(HBITMAP)"));
d59ceba5
VZ
971 }
972
973 m_bitmap.SetWidth(bmp.bmWidth);
974 m_bitmap.SetHeight(bmp.bmHeight);
975 m_bitmap.SetDepth(bmp.bmPlanes);
976 }
977
978 m_bitmap.SetHBITMAP((WXHBITMAP)hbmp);
979
980 wxASSERT_MSG( m_bitmap.Ok(), wxT("pasting invalid bitmap") );
981
17a6a2e0 982 return true;
8e193f38
VZ
983}
984
9e2896e5
VZ
985#endif // 0
986
987// ----------------------------------------------------------------------------
988// wxFileDataObject
989// ----------------------------------------------------------------------------
990
0c0d1521
WS
991bool wxFileDataObject::SetData(size_t WXUNUSED(size),
992 const void *WXUNUSED_IN_WINCE(pData))
9e2896e5 993{
4676948b 994#ifndef __WXWINCE__
9e2896e5
VZ
995 m_filenames.Empty();
996
997 // the documentation states that the first member of DROPFILES structure is
998 // a "DWORD offset of double NUL terminated file list". What they mean by
999 // this (I wonder if you see it immediately) is that the list starts at
1000 // ((char *)&(pDropFiles.pFiles)) + pDropFiles.pFiles. We're also advised
1001 // to use DragQueryFile to work with this structure, but not told where and
1002 // how to get HDROP.
1003 HDROP hdrop = (HDROP)pData; // NB: it works, but I'm not sure about it
1004
1005 // get number of files (magic value -1)
1006 UINT nFiles = ::DragQueryFile(hdrop, (unsigned)-1, NULL, 0u);
1007
51edda6a
VZ
1008 wxCHECK_MSG ( nFiles != (UINT)-1, FALSE, wxT("wrong HDROP handle") );
1009
9e2896e5
VZ
1010 // for each file get the length, allocate memory and then get the name
1011 wxString str;
1012 UINT len, n;
1013 for ( n = 0; n < nFiles; n++ ) {
1014 // +1 for terminating NUL
1015 len = ::DragQueryFile(hdrop, n, NULL, 0) + 1;
1016
de564874 1017 UINT len2 = ::DragQueryFile(hdrop, n, wxStringBuffer(str, len), len);
9e2896e5
VZ
1018 m_filenames.Add(str);
1019
1020 if ( len2 != len - 1 ) {
f6bcfd97
BP
1021 wxLogDebug(wxT("In wxFileDropTarget::OnDrop DragQueryFile returned\
1022 %d characters, %d expected."), len2, len - 1);
9e2896e5
VZ
1023 }
1024 }
1025
17a6a2e0 1026 return true;
4676948b 1027#else
17a6a2e0 1028 return false;
4676948b 1029#endif
9e2896e5
VZ
1030}
1031
8b85d24e
VZ
1032void wxFileDataObject::AddFile(const wxString& file)
1033{
1034 // just add file to filenames array
1035 // all useful data (such as DROPFILES struct) will be
1036 // created later as necessary
1037 m_filenames.Add(file);
1038}
1039
1040size_t wxFileDataObject::GetDataSize() const
1041{
4676948b 1042#ifndef __WXWINCE__
150194b9
VZ
1043 // size returned will be the size of the DROPFILES structure, plus the list
1044 // of filesnames (null byte separated), plus a double null at the end
8b85d24e
VZ
1045
1046 // if no filenames in list, size is 0
150194b9 1047 if ( m_filenames.empty() )
dd10a646 1048 return 0;
8b85d24e 1049
150194b9
VZ
1050#if wxUSE_UNICODE_MSLU
1051 size_t sizeOfChar;
dddf9e14 1052 if ( wxGetOsVersion() == wxOS_WINDOWS_9X )
150194b9
VZ
1053 {
1054 // Win9x always uses ANSI file names and MSLU doesn't help with this
1055 sizeOfChar = sizeof(char);
1056 }
1057 else
1058 {
1059 sizeOfChar = sizeof(wxChar);
1060 }
1061#else // !wxUSE_UNICODE_MSLU
1062 static const size_t sizeOfChar = sizeof(wxChar);
1063#endif // wxUSE_UNICODE_MSLU/!wxUSE_UNICODE_MSLU
1064
8b85d24e 1065 // inital size of DROPFILES struct + null byte
150194b9 1066 size_t sz = sizeof(DROPFILES) + sizeOfChar;
8b85d24e 1067
150194b9 1068 const size_t count = m_filenames.size();
dd10a646 1069 for ( size_t i = 0; i < count; i++ )
8b85d24e
VZ
1070 {
1071 // add filename length plus null byte
150194b9
VZ
1072 size_t len;
1073#if wxUSE_UNICODE_MSLU
1074 if ( sizeOfChar == sizeof(char) )
e0a050e3 1075 len = strlen(m_filenames[i].mb_str(*wxConvFileName));
150194b9
VZ
1076 else
1077#endif // wxUSE_UNICODE_MSLU
1078 len = m_filenames[i].length();
1079
1080 sz += (len + 1) * sizeOfChar;
8b85d24e 1081 }
dd10a646 1082
8b85d24e 1083 return sz;
4676948b
JS
1084#else
1085 return 0;
1086#endif
8b85d24e
VZ
1087}
1088
0c0d1521 1089bool wxFileDataObject::GetDataHere(void *WXUNUSED_IN_WINCE(pData)) const
8b85d24e 1090{
4676948b 1091#ifndef __WXWINCE__
8b85d24e
VZ
1092 // pData points to an externally allocated memory block
1093 // created using the size returned by GetDataSize()
1094
1095 // if pData is NULL, or there are no files, return
150194b9 1096 if ( !pData || m_filenames.empty() )
17a6a2e0 1097 return false;
8b85d24e
VZ
1098
1099 // convert data pointer to a DROPFILES struct pointer
1100 LPDROPFILES pDrop = (LPDROPFILES) pData;
1101
1102 // initialize DROPFILES struct
1103 pDrop->pFiles = sizeof(DROPFILES);
dd10a646 1104 pDrop->fNC = FALSE; // not non-client coords
150194b9 1105#if wxUSE_UNICODE_MSLU
dddf9e14 1106 pDrop->fWide = wxGetOsVersion() != wxOS_WINDOWS_9X ? TRUE : FALSE;
150194b9
VZ
1107#else
1108 pDrop->fWide = wxUSE_UNICODE;
1109#endif
1110
1111 const size_t sizeOfChar = pDrop->fWide ? sizeof(wchar_t) : sizeof(char);
8b85d24e
VZ
1112
1113 // set start of filenames list (null separated)
150194b9 1114 BYTE *pbuf = (BYTE *)(pDrop + 1);
8b85d24e 1115
150194b9
VZ
1116 const size_t count = m_filenames.size();
1117 for ( size_t i = 0; i < count; i++ )
8b85d24e
VZ
1118 {
1119 // copy filename to pbuf and add null terminator
150194b9
VZ
1120 size_t len;
1121#if wxUSE_UNICODE_MSLU
1122 if ( sizeOfChar == sizeof(char) )
1123 {
e0a050e3 1124 wxCharBuffer buf(m_filenames[i].mb_str(*wxConvFileName));
150194b9
VZ
1125 len = strlen(buf);
1126 memcpy(pbuf, buf, len*sizeOfChar);
1127 }
1128 else
1129#endif // wxUSE_UNICODE_MSLU
1130 {
1131 len = m_filenames[i].length();
07662700 1132 memcpy(pbuf, m_filenames[i].wx_str(), len*sizeOfChar);
150194b9
VZ
1133 }
1134
1135 pbuf += len*sizeOfChar;
1136
1137 memset(pbuf, 0, sizeOfChar);
1138 pbuf += sizeOfChar;
8b85d24e 1139 }
dd10a646 1140
c5639a87 1141 // add final null terminator
150194b9 1142 memset(pbuf, 0, sizeOfChar);
8b85d24e 1143
17a6a2e0 1144 return true;
4676948b 1145#else
17a6a2e0 1146 return false;
4676948b 1147#endif
8b85d24e
VZ
1148}
1149
444ad3a7
VZ
1150// ----------------------------------------------------------------------------
1151// wxURLDataObject
1152// ----------------------------------------------------------------------------
1153
219b657f
JS
1154// Work around bug in Wine headers
1155#if defined(__WINE__) && defined(CFSTR_SHELLURL) && wxUSE_UNICODE
1156#undef CFSTR_SHELLURL
1157#define CFSTR_SHELLURL _T("CFSTR_SHELLURL")
1158#endif
1159
4a09bc4e 1160class CFSTR_SHELLURLDataObject : public wxCustomDataObject
e1b435af
MB
1161{
1162public:
1163 CFSTR_SHELLURLDataObject() : wxCustomDataObject(CFSTR_SHELLURL) {}
6f02a879 1164
574c939e 1165 virtual size_t GetBufferOffset( const wxDataFormat& WXUNUSED(format) )
e1b435af
MB
1166 {
1167 return 0;
1168 }
1169
1170 virtual const void* GetSizeFromBuffer( const void* buffer, size_t* size,
574c939e 1171 const wxDataFormat& WXUNUSED(format) )
e1b435af
MB
1172 {
1173 // CFSTR_SHELLURL is _always_ ANSI text
1174 *size = strlen( (const char*)buffer );
1175
1176 return buffer;
1177 }
1178
574c939e
KB
1179 virtual void* SetSizeInBuffer( void* buffer, size_t WXUNUSED(size),
1180 const wxDataFormat& WXUNUSED(format) )
e1b435af
MB
1181 {
1182 return buffer;
1183 }
4a09bc4e 1184
e1b435af
MB
1185#if wxUSE_UNICODE
1186 virtual bool GetDataHere( void* buffer ) const
1187 {
1188 // CFSTR_SHELLURL is _always_ ANSI!
1189 wxCharBuffer char_buffer( GetDataSize() );
1190 wxCustomDataObject::GetDataHere( (void*)char_buffer.data() );
2b5f62a0 1191 wxString unicode_buffer( char_buffer, wxConvLibc );
e1b435af
MB
1192 memcpy( buffer, unicode_buffer.c_str(),
1193 ( unicode_buffer.length() + 1 ) * sizeof(wxChar) );
1194
17a6a2e0 1195 return true;
e1b435af 1196 }
7dbfc030
JS
1197 virtual bool GetDataHere(const wxDataFormat& WXUNUSED(format),
1198 void *buf) const
1199 { return GetDataHere(buf); }
e1b435af 1200#endif
2eb10e2a
VZ
1201
1202 DECLARE_NO_COPY_CLASS(CFSTR_SHELLURLDataObject)
e1b435af
MB
1203};
1204
4a09bc4e
RD
1205
1206
0463eea9 1207wxURLDataObject::wxURLDataObject(const wxString& url)
444ad3a7 1208{
ab250e5c
VZ
1209 // we support CF_TEXT and CFSTR_SHELLURL formats which are basically the
1210 // same but it seems that some browsers only provide one of them so we have
1211 // to support both
444ad3a7 1212 Add(new wxTextDataObject);
e6d318c2 1213 Add(new CFSTR_SHELLURLDataObject());
444ad3a7
VZ
1214
1215 // we don't have any data yet
1216 m_dataObjectLast = NULL;
0463eea9
VZ
1217
1218 if ( !url.empty() )
1219 SetURL(url);
444ad3a7
VZ
1220}
1221
1222bool wxURLDataObject::SetData(const wxDataFormat& format,
1223 size_t len,
1224 const void *buf)
1225{
1226 m_dataObjectLast = GetObject(format);
1227
1228 wxCHECK_MSG( m_dataObjectLast, FALSE,
1229 wxT("unsupported format in wxURLDataObject"));
1230
1231 return m_dataObjectLast->SetData(len, buf);
1232}
1233
1234wxString wxURLDataObject::GetURL() const
1235{
1236 wxString url;
1237 wxCHECK_MSG( m_dataObjectLast, url, _T("no data in wxURLDataObject") );
1238
1239 size_t len = m_dataObjectLast->GetDataSize();
1240
de564874 1241 m_dataObjectLast->GetDataHere(wxStringBuffer(url, len));
444ad3a7
VZ
1242
1243 return url;
1244}
1245
e6d318c2
RD
1246void wxURLDataObject::SetURL(const wxString& url)
1247{
ab250e5c
VZ
1248 wxCharBuffer urlMB(url.mb_str());
1249 if ( urlMB )
1250 {
1251 const size_t len = strlen(urlMB) + 1; // size with trailing NUL
b9a5faed 1252#if !wxUSE_UNICODE
ab250e5c 1253 SetData(wxDF_TEXT, len, urlMB);
b9a5faed 1254#endif
ab250e5c
VZ
1255 SetData(wxDataFormat(CFSTR_SHELLURL), len, urlMB);
1256 }
4a09bc4e 1257
b9a5faed 1258#if wxUSE_UNICODE
ab250e5c 1259 SetData(wxDF_UNICODETEXT, url.length() + 1, url.wc_str());
b9a5faed 1260#endif
e6d318c2
RD
1261}
1262
269a5a34
VZ
1263// ----------------------------------------------------------------------------
1264// private functions
1265// ----------------------------------------------------------------------------
8e193f38
VZ
1266
1267#ifdef __WXDEBUG__
1268
d59ceba5
VZ
1269static const wxChar *GetTymedName(DWORD tymed)
1270{
1271 static wxChar s_szBuf[128];
1272 switch ( tymed ) {
1273 case TYMED_HGLOBAL: return wxT("TYMED_HGLOBAL");
1274 case TYMED_FILE: return wxT("TYMED_FILE");
1275 case TYMED_ISTREAM: return wxT("TYMED_ISTREAM");
1276 case TYMED_ISTORAGE: return wxT("TYMED_ISTORAGE");
1277 case TYMED_GDI: return wxT("TYMED_GDI");
1278 case TYMED_MFPICT: return wxT("TYMED_MFPICT");
1279 case TYMED_ENHMF: return wxT("TYMED_ENHMF");
1280 default:
dfd2e675 1281 wxSprintf(s_szBuf, wxT("type of media format %ld (unknown)"), tymed);
d59ceba5
VZ
1282 return s_szBuf;
1283 }
269a5a34 1284}
5260b1c5 1285
8e193f38 1286#endif // Debug
2845ddc2 1287
21709999 1288#else // not using OLE at all
9205cb3f 1289
21709999
JS
1290// ----------------------------------------------------------------------------
1291// wxDataObject
1292// ----------------------------------------------------------------------------
1293
461dae94
VZ
1294#if wxUSE_DATAOBJ
1295
21709999
JS
1296wxDataObject::wxDataObject()
1297{
1298}
1299
1300wxDataObject::~wxDataObject()
1301{
1302}
1303
1304void wxDataObject::SetAutoDelete()
1305{
1306}
1307
bd52bee1 1308#ifdef __WXDEBUG__
9205cb3f 1309const wxChar *wxDataObject::GetFormatName(wxDataFormat WXUNUSED(format))
21709999
JS
1310{
1311 return NULL;
1312}
9205cb3f 1313#endif // __WXDEBUG__
21709999 1314
9205cb3f
VZ
1315#endif // wxUSE_DATAOBJ
1316
1317#endif // wxUSE_OLE/!wxUSE_OLE
5260b1c5 1318
461dae94 1319