]> git.saurik.com Git - wxWidgets.git/blame - src/msw/ole/dataobj.cpp
correction to last commit: don't test unsetenv() return value, it's void under Darwin
[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
689const void* wxDataObject::GetSizeFromBuffer( const void* buffer, size_t* size,
a8e24848 690 const wxDataFormat& format )
e1b435af 691{
24aab8e8
MW
692 // hack: the third parameter is declared non-const in Wine's headers so
693 // cast away the const
694 size_t realsz = ::HeapSize(::GetProcessHeap(), 0,
695 wx_const_cast(void*, buffer));
51d05226 696 if ( realsz == (size_t)-1 )
a8e24848
VZ
697 {
698 // note that HeapSize() does not set last error
699 wxLogApiError(wxT("HeapSize"), 0);
700 return NULL;
701 }
702
703 *size = realsz;
e1b435af 704
a8e24848
VZ
705 // check if this data has its size prepended (as it was by default for wx
706 // programs prior 2.6.3):
707 size_t *p = (size_t *)buffer;
708 if ( *p == realsz )
709 {
710 if ( NeedsVerbatimData(format) )
711 wxLogDebug(wxT("Apparent data format mismatch: size not needed"));
712
713 p++; // this data has its size prepended; skip first DWORD
714 }
715
716 return p;
e1b435af
MB
717}
718
719void* wxDataObject::SetSizeInBuffer( void* buffer, size_t size,
a8e24848 720 const wxDataFormat& format )
e1b435af 721{
a8e24848
VZ
722 size_t* p = (size_t *)buffer;
723 if ( !NeedsVerbatimData(format) )
724 {
725 // prepend the size to the data and skip it
726 *p++ = size;
727 }
e1b435af 728
a8e24848 729 return p;
e1b435af
MB
730}
731
d9317fd4 732#ifdef __WXDEBUG__
8e193f38 733
f6bcfd97 734const wxChar *wxDataObject::GetFormatName(wxDataFormat format)
d9317fd4
VZ
735{
736 // case 'xxx' is not a valid value for switch of enum 'wxDataFormat'
737 #ifdef __VISUALC__
738 #pragma warning(disable:4063)
739 #endif // VC++
740
f6bcfd97 741 static wxChar s_szBuf[256];
d9317fd4 742 switch ( format ) {
f6bcfd97
BP
743 case CF_TEXT: return wxT("CF_TEXT");
744 case CF_BITMAP: return wxT("CF_BITMAP");
f6bcfd97
BP
745 case CF_SYLK: return wxT("CF_SYLK");
746 case CF_DIF: return wxT("CF_DIF");
747 case CF_TIFF: return wxT("CF_TIFF");
748 case CF_OEMTEXT: return wxT("CF_OEMTEXT");
749 case CF_DIB: return wxT("CF_DIB");
750 case CF_PALETTE: return wxT("CF_PALETTE");
751 case CF_PENDATA: return wxT("CF_PENDATA");
752 case CF_RIFF: return wxT("CF_RIFF");
753 case CF_WAVE: return wxT("CF_WAVE");
754 case CF_UNICODETEXT: return wxT("CF_UNICODETEXT");
569f027b
VS
755#ifndef __WXWINCE__
756 case CF_METAFILEPICT: return wxT("CF_METAFILEPICT");
f6bcfd97 757 case CF_ENHMETAFILE: return wxT("CF_ENHMETAFILE");
f6bcfd97 758 case CF_LOCALE: return wxT("CF_LOCALE");
569f027b
VS
759 case CF_HDROP: return wxT("CF_HDROP");
760#endif
8e193f38 761
d9317fd4 762 default:
c77ae1d9 763 if ( !::GetClipboardFormatName(format, s_szBuf, WXSIZEOF(s_szBuf)) )
d9317fd4
VZ
764 {
765 // it must be a new predefined format we don't know the name of
f6bcfd97 766 wxSprintf(s_szBuf, wxT("unknown CF (0x%04x)"), format.GetFormatId());
d9317fd4 767 }
8e193f38 768
d9317fd4 769 return s_szBuf;
8e193f38 770 }
1e8335b0 771
d9317fd4
VZ
772 #ifdef __VISUALC__
773 #pragma warning(default:4063)
774 #endif // VC++
269a5a34
VZ
775}
776
1e8335b0
VZ
777#endif // Debug
778
3f480da3 779// ----------------------------------------------------------------------------
9e2896e5 780// wxBitmapDataObject supports CF_DIB format
3f480da3
VZ
781// ----------------------------------------------------------------------------
782
be69f971
VZ
783// TODO: support CF_DIB under Windows CE as well
784
9e2896e5 785size_t wxBitmapDataObject::GetDataSize() const
3f480da3 786{
be69f971 787#if wxUSE_WXDIB && !defined(__WXWINCE__)
22be0335 788 return wxDIB::ConvertFromBitmap(NULL, GetHbitmapOf(GetBitmap()));
4cb88a72
JS
789#else
790 return 0;
791#endif
3f480da3
VZ
792}
793
9e2896e5 794bool wxBitmapDataObject::GetDataHere(void *buf) const
3f480da3 795{
be69f971 796#if wxUSE_WXDIB && !defined(__WXWINCE__)
22be0335
VZ
797 BITMAPINFO * const pbi = (BITMAPINFO *)buf;
798
799 return wxDIB::ConvertFromBitmap(pbi, GetHbitmapOf(GetBitmap())) != 0;
4cb88a72 800#else
17a6a2e0
WS
801 wxUnusedVar(buf);
802 return false;
4cb88a72 803#endif
3f480da3
VZ
804}
805
33ac7e6f 806bool wxBitmapDataObject::SetData(size_t WXUNUSED(len), const void *buf)
3f480da3 807{
be69f971 808#if wxUSE_WXDIB && !defined(__WXWINCE__)
22be0335 809 const BITMAPINFO * const pbmi = (const BITMAPINFO *)buf;
9e2896e5 810
22be0335 811 HBITMAP hbmp = wxDIB::ConvertToBitmap(pbmi);
3f480da3 812
22be0335
VZ
813 wxCHECK_MSG( hbmp, FALSE, wxT("pasting/dropping invalid bitmap") );
814
815 const BITMAPINFOHEADER * const pbmih = &pbmi->bmiHeader;
816 wxBitmap bitmap(pbmih->biWidth, pbmih->biHeight, pbmih->biBitCount);
817 bitmap.SetHBITMAP((WXHBITMAP)hbmp);
818
819 // TODO: create wxPalette if the bitmap has any
9e2896e5
VZ
820
821 SetBitmap(bitmap);
3f480da3 822
17a6a2e0 823 return true;
4cb88a72 824#else
17a6a2e0
WS
825 wxUnusedVar(buf);
826 return false;
4cb88a72 827#endif
3f480da3
VZ
828}
829
9e2896e5
VZ
830// ----------------------------------------------------------------------------
831// wxBitmapDataObject2 supports CF_BITMAP format
832// ----------------------------------------------------------------------------
833
834// the bitmaps aren't passed by value as other types of data (i.e. by copying
835// the data into a global memory chunk and passing it to the clipboard or
836// another application or whatever), but by handle, so these generic functions
837// don't make much sense to them.
838
839size_t wxBitmapDataObject2::GetDataSize() const
3f480da3 840{
9e2896e5 841 return 0;
3f480da3
VZ
842}
843
9e2896e5 844bool wxBitmapDataObject2::GetDataHere(void *pBuf) const
3f480da3 845{
9e2896e5
VZ
846 // we put a bitmap handle into pBuf
847 *(WXHBITMAP *)pBuf = GetBitmap().GetHBITMAP();
848
17a6a2e0 849 return true;
3f480da3
VZ
850}
851
265b0c07 852bool wxBitmapDataObject2::SetData(size_t WXUNUSED(len), const void *pBuf)
3f480da3 853{
9e2896e5 854 HBITMAP hbmp = *(HBITMAP *)pBuf;
3f480da3 855
9e2896e5
VZ
856 BITMAP bmp;
857 if ( !GetObject(hbmp, sizeof(BITMAP), &bmp) )
858 {
f6bcfd97 859 wxLogLastError(wxT("GetObject(HBITMAP)"));
9e2896e5 860 }
8e193f38 861
9e2896e5
VZ
862 wxBitmap bitmap(bmp.bmWidth, bmp.bmHeight, bmp.bmPlanes);
863 bitmap.SetHBITMAP((WXHBITMAP)hbmp);
d59ceba5 864
9e2896e5
VZ
865 if ( !bitmap.Ok() ) {
866 wxFAIL_MSG(wxT("pasting/dropping invalid bitmap"));
867
17a6a2e0 868 return false;
9e2896e5
VZ
869 }
870
871 SetBitmap(bitmap);
872
17a6a2e0 873 return true;
d59ceba5
VZ
874}
875
9e2896e5 876#if 0
8e193f38
VZ
877
878size_t wxBitmapDataObject::GetDataSize(const wxDataFormat& format) const
879{
d59ceba5
VZ
880 if ( format.GetFormatId() == CF_DIB )
881 {
882 // create the DIB
883 ScreenHDC hdc;
884
885 // shouldn't be selected into a DC or GetDIBits() would fail
886 wxASSERT_MSG( !m_bitmap.GetSelectedInto(),
887 wxT("can't copy bitmap selected into wxMemoryDC") );
888
889 // first get the info
890 BITMAPINFO bi;
891 if ( !GetDIBits(hdc, (HBITMAP)m_bitmap.GetHBITMAP(), 0, 0,
892 NULL, &bi, DIB_RGB_COLORS) )
893 {
f6bcfd97 894 wxLogLastError(wxT("GetDIBits(NULL)"));
d59ceba5
VZ
895
896 return 0;
897 }
898
899 return sizeof(BITMAPINFO) + bi.bmiHeader.biSizeImage;
900 }
901 else // CF_BITMAP
902 {
903 // no data to copy - we don't pass HBITMAP via global memory
904 return 0;
905 }
8e193f38
VZ
906}
907
d59ceba5 908bool wxBitmapDataObject::GetDataHere(const wxDataFormat& format,
8e193f38
VZ
909 void *pBuf) const
910{
d59ceba5
VZ
911 wxASSERT_MSG( m_bitmap.Ok(), wxT("copying invalid bitmap") );
912
913 HBITMAP hbmp = (HBITMAP)m_bitmap.GetHBITMAP();
914 if ( format.GetFormatId() == CF_DIB )
915 {
916 // create the DIB
917 ScreenHDC hdc;
918
919 // shouldn't be selected into a DC or GetDIBits() would fail
920 wxASSERT_MSG( !m_bitmap.GetSelectedInto(),
921 wxT("can't copy bitmap selected into wxMemoryDC") );
922
923 // first get the info
924 BITMAPINFO *pbi = (BITMAPINFO *)pBuf;
925 if ( !GetDIBits(hdc, hbmp, 0, 0, NULL, pbi, DIB_RGB_COLORS) )
926 {
f6bcfd97 927 wxLogLastError(wxT("GetDIBits(NULL)"));
d59ceba5
VZ
928
929 return 0;
930 }
931
932 // and now copy the bits
933 if ( !GetDIBits(hdc, hbmp, 0, pbi->bmiHeader.biHeight, pbi + 1,
934 pbi, DIB_RGB_COLORS) )
935 {
f6bcfd97 936 wxLogLastError(wxT("GetDIBits"));
d59ceba5 937
17a6a2e0 938 return false;
d59ceba5
VZ
939 }
940 }
941 else // CF_BITMAP
942 {
943 // we put a bitmap handle into pBuf
944 *(HBITMAP *)pBuf = hbmp;
945 }
946
17a6a2e0 947 return true;
d59ceba5
VZ
948}
949
9e2896e5
VZ
950bool wxBitmapDataObject::SetData(const wxDataFormat& format,
951 size_t size, const void *pBuf)
d59ceba5
VZ
952{
953 HBITMAP hbmp;
954 if ( format.GetFormatId() == CF_DIB )
955 {
956 // here we get BITMAPINFO struct followed by the actual bitmap bits and
957 // BITMAPINFO starts with BITMAPINFOHEADER followed by colour info
958 ScreenHDC hdc;
959
960 BITMAPINFO *pbmi = (BITMAPINFO *)pBuf;
961 BITMAPINFOHEADER *pbmih = &pbmi->bmiHeader;
962 hbmp = CreateDIBitmap(hdc, pbmih, CBM_INIT,
963 pbmi + 1, pbmi, DIB_RGB_COLORS);
964 if ( !hbmp )
965 {
f6bcfd97 966 wxLogLastError(wxT("CreateDIBitmap"));
d59ceba5
VZ
967 }
968
969 m_bitmap.SetWidth(pbmih->biWidth);
970 m_bitmap.SetHeight(pbmih->biHeight);
971 }
972 else // CF_BITMAP
973 {
974 // it's easy with bitmaps: we pass them by handle
975 hbmp = *(HBITMAP *)pBuf;
976
977 BITMAP bmp;
978 if ( !GetObject(hbmp, sizeof(BITMAP), &bmp) )
979 {
f6bcfd97 980 wxLogLastError(wxT("GetObject(HBITMAP)"));
d59ceba5
VZ
981 }
982
983 m_bitmap.SetWidth(bmp.bmWidth);
984 m_bitmap.SetHeight(bmp.bmHeight);
985 m_bitmap.SetDepth(bmp.bmPlanes);
986 }
987
988 m_bitmap.SetHBITMAP((WXHBITMAP)hbmp);
989
990 wxASSERT_MSG( m_bitmap.Ok(), wxT("pasting invalid bitmap") );
991
17a6a2e0 992 return true;
8e193f38
VZ
993}
994
9e2896e5
VZ
995#endif // 0
996
997// ----------------------------------------------------------------------------
998// wxFileDataObject
999// ----------------------------------------------------------------------------
1000
0c0d1521
WS
1001bool wxFileDataObject::SetData(size_t WXUNUSED(size),
1002 const void *WXUNUSED_IN_WINCE(pData))
9e2896e5 1003{
4676948b 1004#ifndef __WXWINCE__
9e2896e5
VZ
1005 m_filenames.Empty();
1006
1007 // the documentation states that the first member of DROPFILES structure is
1008 // a "DWORD offset of double NUL terminated file list". What they mean by
1009 // this (I wonder if you see it immediately) is that the list starts at
1010 // ((char *)&(pDropFiles.pFiles)) + pDropFiles.pFiles. We're also advised
1011 // to use DragQueryFile to work with this structure, but not told where and
1012 // how to get HDROP.
1013 HDROP hdrop = (HDROP)pData; // NB: it works, but I'm not sure about it
1014
1015 // get number of files (magic value -1)
1016 UINT nFiles = ::DragQueryFile(hdrop, (unsigned)-1, NULL, 0u);
1017
51edda6a
VZ
1018 wxCHECK_MSG ( nFiles != (UINT)-1, FALSE, wxT("wrong HDROP handle") );
1019
9e2896e5
VZ
1020 // for each file get the length, allocate memory and then get the name
1021 wxString str;
1022 UINT len, n;
1023 for ( n = 0; n < nFiles; n++ ) {
1024 // +1 for terminating NUL
1025 len = ::DragQueryFile(hdrop, n, NULL, 0) + 1;
1026
de564874 1027 UINT len2 = ::DragQueryFile(hdrop, n, wxStringBuffer(str, len), len);
9e2896e5
VZ
1028 m_filenames.Add(str);
1029
1030 if ( len2 != len - 1 ) {
f6bcfd97
BP
1031 wxLogDebug(wxT("In wxFileDropTarget::OnDrop DragQueryFile returned\
1032 %d characters, %d expected."), len2, len - 1);
9e2896e5
VZ
1033 }
1034 }
1035
17a6a2e0 1036 return true;
4676948b 1037#else
17a6a2e0 1038 return false;
4676948b 1039#endif
9e2896e5
VZ
1040}
1041
8b85d24e
VZ
1042void wxFileDataObject::AddFile(const wxString& file)
1043{
1044 // just add file to filenames array
1045 // all useful data (such as DROPFILES struct) will be
1046 // created later as necessary
1047 m_filenames.Add(file);
1048}
1049
1050size_t wxFileDataObject::GetDataSize() const
1051{
4676948b 1052#ifndef __WXWINCE__
150194b9
VZ
1053 // size returned will be the size of the DROPFILES structure, plus the list
1054 // of filesnames (null byte separated), plus a double null at the end
8b85d24e
VZ
1055
1056 // if no filenames in list, size is 0
150194b9 1057 if ( m_filenames.empty() )
dd10a646 1058 return 0;
8b85d24e 1059
150194b9
VZ
1060#if wxUSE_UNICODE_MSLU
1061 size_t sizeOfChar;
dddf9e14 1062 if ( wxGetOsVersion() == wxOS_WINDOWS_9X )
150194b9
VZ
1063 {
1064 // Win9x always uses ANSI file names and MSLU doesn't help with this
1065 sizeOfChar = sizeof(char);
1066 }
1067 else
1068 {
1069 sizeOfChar = sizeof(wxChar);
1070 }
1071#else // !wxUSE_UNICODE_MSLU
1072 static const size_t sizeOfChar = sizeof(wxChar);
1073#endif // wxUSE_UNICODE_MSLU/!wxUSE_UNICODE_MSLU
1074
8b85d24e 1075 // inital size of DROPFILES struct + null byte
150194b9 1076 size_t sz = sizeof(DROPFILES) + sizeOfChar;
8b85d24e 1077
150194b9 1078 const size_t count = m_filenames.size();
dd10a646 1079 for ( size_t i = 0; i < count; i++ )
8b85d24e
VZ
1080 {
1081 // add filename length plus null byte
150194b9
VZ
1082 size_t len;
1083#if wxUSE_UNICODE_MSLU
1084 if ( sizeOfChar == sizeof(char) )
e0a050e3 1085 len = strlen(m_filenames[i].mb_str(*wxConvFileName));
150194b9
VZ
1086 else
1087#endif // wxUSE_UNICODE_MSLU
1088 len = m_filenames[i].length();
1089
1090 sz += (len + 1) * sizeOfChar;
8b85d24e 1091 }
dd10a646 1092
8b85d24e 1093 return sz;
4676948b
JS
1094#else
1095 return 0;
1096#endif
8b85d24e
VZ
1097}
1098
0c0d1521 1099bool wxFileDataObject::GetDataHere(void *WXUNUSED_IN_WINCE(pData)) const
8b85d24e 1100{
4676948b 1101#ifndef __WXWINCE__
8b85d24e
VZ
1102 // pData points to an externally allocated memory block
1103 // created using the size returned by GetDataSize()
1104
1105 // if pData is NULL, or there are no files, return
150194b9 1106 if ( !pData || m_filenames.empty() )
17a6a2e0 1107 return false;
8b85d24e
VZ
1108
1109 // convert data pointer to a DROPFILES struct pointer
1110 LPDROPFILES pDrop = (LPDROPFILES) pData;
1111
1112 // initialize DROPFILES struct
1113 pDrop->pFiles = sizeof(DROPFILES);
dd10a646 1114 pDrop->fNC = FALSE; // not non-client coords
150194b9 1115#if wxUSE_UNICODE_MSLU
dddf9e14 1116 pDrop->fWide = wxGetOsVersion() != wxOS_WINDOWS_9X ? TRUE : FALSE;
150194b9
VZ
1117#else
1118 pDrop->fWide = wxUSE_UNICODE;
1119#endif
1120
1121 const size_t sizeOfChar = pDrop->fWide ? sizeof(wchar_t) : sizeof(char);
8b85d24e
VZ
1122
1123 // set start of filenames list (null separated)
150194b9 1124 BYTE *pbuf = (BYTE *)(pDrop + 1);
8b85d24e 1125
150194b9
VZ
1126 const size_t count = m_filenames.size();
1127 for ( size_t i = 0; i < count; i++ )
8b85d24e
VZ
1128 {
1129 // copy filename to pbuf and add null terminator
150194b9
VZ
1130 size_t len;
1131#if wxUSE_UNICODE_MSLU
1132 if ( sizeOfChar == sizeof(char) )
1133 {
e0a050e3 1134 wxCharBuffer buf(m_filenames[i].mb_str(*wxConvFileName));
150194b9
VZ
1135 len = strlen(buf);
1136 memcpy(pbuf, buf, len*sizeOfChar);
1137 }
1138 else
1139#endif // wxUSE_UNICODE_MSLU
1140 {
1141 len = m_filenames[i].length();
1142 memcpy(pbuf, m_filenames[i].c_str(), len*sizeOfChar);
1143 }
1144
1145 pbuf += len*sizeOfChar;
1146
1147 memset(pbuf, 0, sizeOfChar);
1148 pbuf += sizeOfChar;
8b85d24e 1149 }
dd10a646 1150
c5639a87 1151 // add final null terminator
150194b9 1152 memset(pbuf, 0, sizeOfChar);
8b85d24e 1153
17a6a2e0 1154 return true;
4676948b 1155#else
17a6a2e0 1156 return false;
4676948b 1157#endif
8b85d24e
VZ
1158}
1159
444ad3a7
VZ
1160// ----------------------------------------------------------------------------
1161// wxURLDataObject
1162// ----------------------------------------------------------------------------
1163
219b657f
JS
1164// Work around bug in Wine headers
1165#if defined(__WINE__) && defined(CFSTR_SHELLURL) && wxUSE_UNICODE
1166#undef CFSTR_SHELLURL
1167#define CFSTR_SHELLURL _T("CFSTR_SHELLURL")
1168#endif
1169
4a09bc4e 1170class CFSTR_SHELLURLDataObject : public wxCustomDataObject
e1b435af
MB
1171{
1172public:
1173 CFSTR_SHELLURLDataObject() : wxCustomDataObject(CFSTR_SHELLURL) {}
6f02a879 1174
574c939e 1175 virtual size_t GetBufferOffset( const wxDataFormat& WXUNUSED(format) )
e1b435af
MB
1176 {
1177 return 0;
1178 }
1179
1180 virtual const void* GetSizeFromBuffer( const void* buffer, size_t* size,
574c939e 1181 const wxDataFormat& WXUNUSED(format) )
e1b435af
MB
1182 {
1183 // CFSTR_SHELLURL is _always_ ANSI text
1184 *size = strlen( (const char*)buffer );
1185
1186 return buffer;
1187 }
1188
574c939e
KB
1189 virtual void* SetSizeInBuffer( void* buffer, size_t WXUNUSED(size),
1190 const wxDataFormat& WXUNUSED(format) )
e1b435af
MB
1191 {
1192 return buffer;
1193 }
4a09bc4e 1194
e1b435af
MB
1195#if wxUSE_UNICODE
1196 virtual bool GetDataHere( void* buffer ) const
1197 {
1198 // CFSTR_SHELLURL is _always_ ANSI!
1199 wxCharBuffer char_buffer( GetDataSize() );
1200 wxCustomDataObject::GetDataHere( (void*)char_buffer.data() );
2b5f62a0 1201 wxString unicode_buffer( char_buffer, wxConvLibc );
e1b435af
MB
1202 memcpy( buffer, unicode_buffer.c_str(),
1203 ( unicode_buffer.length() + 1 ) * sizeof(wxChar) );
1204
17a6a2e0 1205 return true;
e1b435af 1206 }
7dbfc030
JS
1207 virtual bool GetDataHere(const wxDataFormat& WXUNUSED(format),
1208 void *buf) const
1209 { return GetDataHere(buf); }
e1b435af 1210#endif
2eb10e2a
VZ
1211
1212 DECLARE_NO_COPY_CLASS(CFSTR_SHELLURLDataObject)
e1b435af
MB
1213};
1214
4a09bc4e
RD
1215
1216
0463eea9 1217wxURLDataObject::wxURLDataObject(const wxString& url)
444ad3a7
VZ
1218{
1219 // we support CF_TEXT and CFSTR_SHELLURL formats which are basicly the same
e1b435af 1220 // but it seems that some browsers only provide one of them so we have to
444ad3a7 1221 // support both
444ad3a7 1222 Add(new wxTextDataObject);
e6d318c2 1223 Add(new CFSTR_SHELLURLDataObject());
444ad3a7
VZ
1224
1225 // we don't have any data yet
1226 m_dataObjectLast = NULL;
0463eea9
VZ
1227
1228 if ( !url.empty() )
1229 SetURL(url);
444ad3a7
VZ
1230}
1231
1232bool wxURLDataObject::SetData(const wxDataFormat& format,
1233 size_t len,
1234 const void *buf)
1235{
1236 m_dataObjectLast = GetObject(format);
1237
1238 wxCHECK_MSG( m_dataObjectLast, FALSE,
1239 wxT("unsupported format in wxURLDataObject"));
1240
1241 return m_dataObjectLast->SetData(len, buf);
1242}
1243
1244wxString wxURLDataObject::GetURL() const
1245{
1246 wxString url;
1247 wxCHECK_MSG( m_dataObjectLast, url, _T("no data in wxURLDataObject") );
1248
1249 size_t len = m_dataObjectLast->GetDataSize();
1250
de564874 1251 m_dataObjectLast->GetDataHere(wxStringBuffer(url, len));
444ad3a7
VZ
1252
1253 return url;
1254}
1255
e6d318c2
RD
1256void wxURLDataObject::SetURL(const wxString& url)
1257{
4a09bc4e
RD
1258 SetData(wxDataFormat(wxUSE_UNICODE ? wxDF_UNICODETEXT : wxDF_TEXT),
1259 url.Length()+1, url.c_str());
1260
1261 // CFSTR_SHELLURL is always supposed to be ANSI...
1262 wxWX2MBbuf urlA = (wxWX2MBbuf)url.mbc_str();
1263 size_t len = strlen(urlA);
1264 SetData(wxDataFormat(CFSTR_SHELLURL), len+1, (const char*)urlA);
e6d318c2
RD
1265}
1266
269a5a34
VZ
1267// ----------------------------------------------------------------------------
1268// private functions
1269// ----------------------------------------------------------------------------
8e193f38
VZ
1270
1271#ifdef __WXDEBUG__
1272
d59ceba5
VZ
1273static const wxChar *GetTymedName(DWORD tymed)
1274{
1275 static wxChar s_szBuf[128];
1276 switch ( tymed ) {
1277 case TYMED_HGLOBAL: return wxT("TYMED_HGLOBAL");
1278 case TYMED_FILE: return wxT("TYMED_FILE");
1279 case TYMED_ISTREAM: return wxT("TYMED_ISTREAM");
1280 case TYMED_ISTORAGE: return wxT("TYMED_ISTORAGE");
1281 case TYMED_GDI: return wxT("TYMED_GDI");
1282 case TYMED_MFPICT: return wxT("TYMED_MFPICT");
1283 case TYMED_ENHMF: return wxT("TYMED_ENHMF");
1284 default:
dfd2e675 1285 wxSprintf(s_szBuf, wxT("type of media format %ld (unknown)"), tymed);
d59ceba5
VZ
1286 return s_szBuf;
1287 }
269a5a34 1288}
5260b1c5 1289
8e193f38 1290#endif // Debug
2845ddc2 1291
21709999 1292#else // not using OLE at all
9205cb3f 1293
21709999
JS
1294// ----------------------------------------------------------------------------
1295// wxDataObject
1296// ----------------------------------------------------------------------------
1297
461dae94
VZ
1298#if wxUSE_DATAOBJ
1299
21709999
JS
1300wxDataObject::wxDataObject()
1301{
1302}
1303
1304wxDataObject::~wxDataObject()
1305{
1306}
1307
1308void wxDataObject::SetAutoDelete()
1309{
1310}
1311
bd52bee1 1312#ifdef __WXDEBUG__
9205cb3f 1313const wxChar *wxDataObject::GetFormatName(wxDataFormat WXUNUSED(format))
21709999
JS
1314{
1315 return NULL;
1316}
9205cb3f 1317#endif // __WXDEBUG__
21709999 1318
9205cb3f
VZ
1319#endif // wxUSE_DATAOBJ
1320
1321#endif // wxUSE_OLE/!wxUSE_OLE
5260b1c5 1322
461dae94 1323