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