]> git.saurik.com Git - wxWidgets.git/blob - src/msw/ole/dataobj.cpp
made GetStrings() const (patch 1655975)
[wxWidgets.git] / src / msw / ole / dataobj.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: msw/ole/dataobj.cpp
3 // Purpose: implementation of wx[I]DataObject class
4 // Author: Vadim Zeitlin
5 // Modified by:
6 // Created: 10.05.98
7 // RCS-ID: $Id$
8 // Copyright: (c) 1998 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
9 // Licence: wxWindows licence
10 ///////////////////////////////////////////////////////////////////////////////
11
12 // ============================================================================
13 // declarations
14 // ============================================================================
15
16 // ----------------------------------------------------------------------------
17 // headers
18 // ----------------------------------------------------------------------------
19
20 // For compilers that support precompilation, includes "wx.h".
21 #include "wx/wxprec.h"
22
23 #if defined(__BORLANDC__)
24 #pragma hdrstop
25 #endif
26
27 #ifndef WX_PRECOMP
28 #include "wx/intl.h"
29 #include "wx/log.h"
30 #include "wx/utils.h"
31 #endif
32
33 #include "wx/dataobj.h"
34
35 #if wxUSE_OLE && defined(__WIN32__) && !defined(__GNUWIN32_OLD__)
36
37 #include "wx/msw/private.h" // includes <windows.h>
38
39 #ifdef __WXWINCE__
40 #include <winreg.h>
41 #endif
42
43 // for some compilers, the entire ole2.h must be included, not only oleauto.h
44 #if wxUSE_NORLANDER_HEADERS || defined(__WATCOMC__) || defined(__WXWINCE__)
45 #include <ole2.h>
46 #endif
47
48 #include <oleauto.h>
49 #include <shlobj.h>
50
51 #include "wx/msw/ole/oleutils.h"
52
53 #include "wx/msw/dib.h"
54
55 #ifndef CFSTR_SHELLURL
56 #define CFSTR_SHELLURL _T("UniformResourceLocator")
57 #endif
58
59 // ----------------------------------------------------------------------------
60 // functions
61 // ----------------------------------------------------------------------------
62
63 #ifdef __WXDEBUG__
64 static const wxChar *GetTymedName(DWORD tymed);
65 #else // !Debug
66 #define GetTymedName(tymed) wxEmptyString
67 #endif // Debug/!Debug
68
69 // ----------------------------------------------------------------------------
70 // wxIEnumFORMATETC interface implementation
71 // ----------------------------------------------------------------------------
72
73 class wxIEnumFORMATETC : public IEnumFORMATETC
74 {
75 public:
76 wxIEnumFORMATETC(const wxDataFormat* formats, ULONG nCount);
77 virtual ~wxIEnumFORMATETC() { delete [] m_formats; }
78
79 // IEnumFORMATETC
80 STDMETHODIMP Next(ULONG celt, FORMATETC *rgelt, ULONG *pceltFetched);
81 STDMETHODIMP Skip(ULONG celt);
82 STDMETHODIMP Reset();
83 STDMETHODIMP Clone(IEnumFORMATETC **ppenum);
84
85 DECLARE_IUNKNOWN_METHODS;
86
87 private:
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
91
92 DECLARE_NO_COPY_CLASS(wxIEnumFORMATETC)
93 };
94
95 // ----------------------------------------------------------------------------
96 // wxIDataObject implementation of IDataObject interface
97 // ----------------------------------------------------------------------------
98
99 class wxIDataObject : public IDataObject
100 {
101 public:
102 wxIDataObject(wxDataObject *pDataObject);
103 virtual ~wxIDataObject();
104
105 // normally, wxDataObject controls our lifetime (i.e. we're deleted when it
106 // is), but in some cases, the situation is reversed, that is we delete it
107 // when this object is deleted - setting this flag enables such logic
108 void SetDeleteFlag() { m_mustDelete = true; }
109
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);
120
121 DECLARE_IUNKNOWN_METHODS;
122
123 private:
124 wxDataObject *m_pDataObject; // pointer to C++ class we belong to
125
126 bool m_mustDelete;
127
128 DECLARE_NO_COPY_CLASS(wxIDataObject)
129 };
130
131 // ============================================================================
132 // implementation
133 // ============================================================================
134
135 // ----------------------------------------------------------------------------
136 // wxDataFormat
137 // ----------------------------------------------------------------------------
138
139 void wxDataFormat::SetId(const wxChar *format)
140 {
141 m_format = (wxDataFormat::NativeFormat)::RegisterClipboardFormat(format);
142 if ( !m_format )
143 {
144 wxLogError(_("Couldn't register clipboard format '%s'."), format);
145 }
146 }
147
148 wxString wxDataFormat::GetId() const
149 {
150 static const int max = 256;
151
152 wxString s;
153
154 wxCHECK_MSG( !IsStandard(), s,
155 wxT("name of predefined format cannot be retrieved") );
156
157 int len = ::GetClipboardFormatName(m_format, wxStringBuffer(s, max), max);
158
159 if ( !len )
160 {
161 wxLogError(_("The clipboard format '%d' doesn't exist."), m_format);
162 return wxEmptyString;
163 }
164
165 return s;
166 }
167
168 // ----------------------------------------------------------------------------
169 // wxIEnumFORMATETC
170 // ----------------------------------------------------------------------------
171
172 BEGIN_IID_TABLE(wxIEnumFORMATETC)
173 ADD_IID(Unknown)
174 ADD_IID(EnumFORMATETC)
175 END_IID_TABLE;
176
177 IMPLEMENT_IUNKNOWN_METHODS(wxIEnumFORMATETC)
178
179 wxIEnumFORMATETC::wxIEnumFORMATETC(const wxDataFormat *formats, ULONG nCount)
180 {
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 }
187 }
188
189 STDMETHODIMP wxIEnumFORMATETC::Next(ULONG celt,
190 FORMATETC *rgelt,
191 ULONG *pceltFetched)
192 {
193 wxLogTrace(wxTRACE_OleCalls, wxT("wxIEnumFORMATETC::Next"));
194
195 ULONG numFetched = 0;
196 while (m_nCurrent < m_nCount && numFetched < celt) {
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;
203
204 *rgelt++ = format;
205 numFetched++;
206 }
207
208 if (pceltFetched)
209 *pceltFetched = numFetched;
210
211 return numFetched == celt ? S_OK : S_FALSE;
212 }
213
214 STDMETHODIMP wxIEnumFORMATETC::Skip(ULONG celt)
215 {
216 wxLogTrace(wxTRACE_OleCalls, wxT("wxIEnumFORMATETC::Skip"));
217
218 m_nCurrent += celt;
219 if ( m_nCurrent < m_nCount )
220 return S_OK;
221
222 // no, can't skip this many elements
223 m_nCurrent -= celt;
224
225 return S_FALSE;
226 }
227
228 STDMETHODIMP wxIEnumFORMATETC::Reset()
229 {
230 wxLogTrace(wxTRACE_OleCalls, wxT("wxIEnumFORMATETC::Reset"));
231
232 m_nCurrent = 0;
233
234 return S_OK;
235 }
236
237 STDMETHODIMP wxIEnumFORMATETC::Clone(IEnumFORMATETC **ppenum)
238 {
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;
250
251 return S_OK;
252 }
253
254 // ----------------------------------------------------------------------------
255 // wxIDataObject
256 // ----------------------------------------------------------------------------
257
258 BEGIN_IID_TABLE(wxIDataObject)
259 ADD_IID(Unknown)
260 ADD_IID(DataObject)
261 END_IID_TABLE;
262
263 IMPLEMENT_IUNKNOWN_METHODS(wxIDataObject)
264
265 wxIDataObject::wxIDataObject(wxDataObject *pDataObject)
266 {
267 m_pDataObject = pDataObject;
268 m_mustDelete = false;
269 }
270
271 wxIDataObject::~wxIDataObject()
272 {
273 if ( m_mustDelete )
274 {
275 delete m_pDataObject;
276 }
277 }
278
279 // get data functions
280 STDMETHODIMP wxIDataObject::GetData(FORMATETC *pformatetcIn, STGMEDIUM *pmedium)
281 {
282 wxLogTrace(wxTRACE_OleCalls, wxT("wxIDataObject::GetData"));
283
284 // is data is in our format?
285 HRESULT hr = QueryGetData(pformatetcIn);
286 if ( FAILED(hr) )
287 return hr;
288
289 // for the bitmaps and metafiles we use the handles instead of global memory
290 // to pass the data
291 wxDataFormat format = (wxDataFormat::NativeFormat)pformatetcIn->cfFormat;
292
293 switch ( format )
294 {
295 case wxDF_BITMAP:
296 pmedium->tymed = TYMED_GDI;
297 break;
298
299 case wxDF_ENHMETAFILE:
300 pmedium->tymed = TYMED_ENHMF;
301 break;
302
303 #ifndef __WXWINCE__
304 case wxDF_METAFILE:
305 pmedium->hGlobal = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE,
306 sizeof(METAFILEPICT));
307 if ( !pmedium->hGlobal ) {
308 wxLogLastError(wxT("GlobalAlloc"));
309 return E_OUTOFMEMORY;
310 }
311 pmedium->tymed = TYMED_MFPICT;
312 break;
313 #endif
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
324 // we may need extra space for the buffer size
325 size += m_pDataObject->GetBufferOffset( format );
326
327 HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, size);
328 if ( hGlobal == NULL ) {
329 wxLogLastError(wxT("GlobalAlloc"));
330 return E_OUTOFMEMORY;
331 }
332
333 // copy data
334 pmedium->tymed = TYMED_HGLOBAL;
335 pmedium->hGlobal = hGlobal;
336 }
337
338 pmedium->pUnkForRelease = NULL;
339
340 // do copy the data
341 hr = GetDataHere(pformatetcIn, pmedium);
342 if ( FAILED(hr) ) {
343 // free resources we allocated
344 if ( pmedium->tymed & (TYMED_HGLOBAL | TYMED_MFPICT) ) {
345 GlobalFree(pmedium->hGlobal);
346 }
347
348 return hr;
349 }
350
351 return S_OK;
352 }
353
354 STDMETHODIMP wxIDataObject::GetDataHere(FORMATETC *pformatetc,
355 STGMEDIUM *pmedium)
356 {
357 wxLogTrace(wxTRACE_OleCalls, wxT("wxIDataObject::GetDataHere"));
358
359 // put data in caller provided medium
360 switch ( pmedium->tymed )
361 {
362 case TYMED_GDI:
363 if ( !m_pDataObject->GetDataHere(wxDF_BITMAP, &pmedium->hBitmap) )
364 return E_UNEXPECTED;
365 break;
366
367 case TYMED_ENHMF:
368 if ( !m_pDataObject->GetDataHere(wxDF_ENHMETAFILE,
369 &pmedium->hEnhMetaFile) )
370 return E_UNEXPECTED;
371 break;
372
373 case TYMED_MFPICT:
374 // fall through - we pass METAFILEPICT through HGLOBAL
375
376 case TYMED_HGLOBAL:
377 {
378 // copy data
379 HGLOBAL hGlobal = pmedium->hGlobal;
380 void *pBuf = GlobalLock(hGlobal);
381 if ( pBuf == NULL ) {
382 wxLogLastError(wxT("GlobalLock"));
383 return E_OUTOFMEMORY;
384 }
385
386 wxDataFormat format = pformatetc->cfFormat;
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 );
395
396 if ( !m_pDataObject->GetDataHere(format, pBuf) )
397 return E_UNEXPECTED;
398
399 GlobalUnlock(hGlobal);
400 }
401 break;
402
403 default:
404 return DV_E_TYMED;
405 }
406
407 return S_OK;
408 }
409
410
411 // set data functions
412 STDMETHODIMP wxIDataObject::SetData(FORMATETC *pformatetc,
413 STGMEDIUM *pmedium,
414 BOOL fRelease)
415 {
416 wxLogTrace(wxTRACE_OleCalls, wxT("wxIDataObject::SetData"));
417
418 switch ( pmedium->tymed )
419 {
420 case TYMED_GDI:
421 m_pDataObject->SetData(wxDF_BITMAP, 0, &pmedium->hBitmap);
422 break;
423
424 case TYMED_ENHMF:
425 m_pDataObject->SetData(wxDF_ENHMETAFILE, 0, &pmedium->hEnhMetaFile);
426 break;
427
428 case TYMED_MFPICT:
429 // fall through - we pass METAFILEPICT through HGLOBAL
430 case TYMED_HGLOBAL:
431 {
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
440 if ( !m_pDataObject->IsSupported(format, wxDataObject::Set) ) {
441 // go away!
442 return DV_E_FORMATETC;
443 }
444
445 // copy data
446 const void *pBuf = GlobalLock(pmedium->hGlobal);
447 if ( pBuf == NULL ) {
448 wxLogLastError(wxT("GlobalLock"));
449
450 return E_OUTOFMEMORY;
451 }
452
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;
459 switch ( format )
460 {
461 case CF_TEXT:
462 case CF_OEMTEXT:
463 size = strlen((const char *)pBuf);
464 break;
465 #if !(defined(__BORLANDC__) && (__BORLANDC__ < 0x500))
466 case CF_UNICODETEXT:
467 #if ( defined(__BORLANDC__) && (__BORLANDC__ > 0x530) ) \
468 || ( defined(__MWERKS__) && defined(__WXMSW__) )
469 size = std::wcslen((const wchar_t *)pBuf) * sizeof(wchar_t);
470 #else
471 size = wxWcslen((const wchar_t *)pBuf) * sizeof(wchar_t);
472 #endif
473 break;
474 #endif
475 case CF_BITMAP:
476 #ifndef __WXWINCE__
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;
482 #endif
483
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
490 #ifndef __WXWINCE__
491 case CF_METAFILEPICT:
492 size = sizeof(METAFILEPICT);
493 break;
494 #endif
495 default:
496 pBuf = m_pDataObject->
497 GetSizeFromBuffer(pBuf, &size, format);
498 size -= m_pDataObject->GetBufferOffset(format);
499 }
500
501 bool ok = m_pDataObject->SetData(format, size, pBuf);
502
503 GlobalUnlock(pmedium->hGlobal);
504
505 if ( !ok ) {
506 return E_UNEXPECTED;
507 }
508 }
509 break;
510
511 default:
512 return DV_E_TYMED;
513 }
514
515 if ( fRelease ) {
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 )
519 {
520 case TYMED_GDI:
521 pmedium->hBitmap = 0;
522 break;
523
524 case TYMED_MFPICT:
525 pmedium->hMetaFilePict = 0;
526 break;
527
528 case TYMED_ENHMF:
529 pmedium->hEnhMetaFile = 0;
530 break;
531 }
532
533 ReleaseStgMedium(pmedium);
534 }
535
536 return S_OK;
537 }
538
539 // information functions
540 STDMETHODIMP wxIDataObject::QueryGetData(FORMATETC *pformatetc)
541 {
542 // do we accept data in this format?
543 if ( pformatetc == NULL ) {
544 wxLogTrace(wxTRACE_OleCalls,
545 wxT("wxIDataObject::QueryGetData: invalid ptr."));
546
547 return E_INVALIDARG;
548 }
549
550 // the only one allowed by current COM implementation
551 if ( pformatetc->lindex != -1 ) {
552 wxLogTrace(wxTRACE_OleCalls,
553 wxT("wxIDataObject::QueryGetData: bad lindex %ld"),
554 pformatetc->lindex);
555
556 return DV_E_LINDEX;
557 }
558
559 // we don't support anything other (THUMBNAIL, ICON, DOCPRINT...)
560 if ( pformatetc->dwAspect != DVASPECT_CONTENT ) {
561 wxLogTrace(wxTRACE_OleCalls,
562 wxT("wxIDataObject::QueryGetData: bad dwAspect %ld"),
563 pformatetc->dwAspect);
564
565 return DV_E_DVASPECT;
566 }
567
568 // and now check the type of data requested
569 wxDataFormat format = pformatetc->cfFormat;
570 if ( m_pDataObject->IsSupportedFormat(format) ) {
571 wxLogTrace(wxTRACE_OleCalls, wxT("wxIDataObject::QueryGetData: %s ok"),
572 wxGetFormatName(format));
573 }
574 else {
575 wxLogTrace(wxTRACE_OleCalls,
576 wxT("wxIDataObject::QueryGetData: %s unsupported"),
577 wxGetFormatName(format));
578
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
587 wxLogTrace(wxTRACE_OleCalls,
588 wxT("wxIDataObject::QueryGetData: %s != %s"),
589 GetTymedName(tymed),
590 GetTymedName(format == wxDF_BITMAP ? TYMED_GDI
591 : TYMED_HGLOBAL));
592
593 return DV_E_TYMED;
594 }
595
596 return S_OK;
597 }
598
599 STDMETHODIMP wxIDataObject::GetCanonicalFormatEtc(FORMATETC *WXUNUSED(pFormatetcIn),
600 FORMATETC *pFormatetcOut)
601 {
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;
607
608 return DATA_S_SAMEFORMATETC;
609 }
610
611 STDMETHODIMP wxIDataObject::EnumFormatEtc(DWORD dwDir,
612 IEnumFORMATETC **ppenumFormatEtc)
613 {
614 wxLogTrace(wxTRACE_OleCalls, wxT("wxIDataObject::EnumFormatEtc"));
615
616 wxDataObject::Direction dir = dwDir == DATADIR_GET ? wxDataObject::Get
617 : wxDataObject::Set;
618
619 ULONG nFormatCount = wx_truncate_cast(ULONG, m_pDataObject->GetFormatCount(dir));
620 wxDataFormat format;
621 wxDataFormat *formats;
622 formats = nFormatCount == 1 ? &format : new wxDataFormat[nFormatCount];
623 m_pDataObject->GetAllFormats(formats, dir);
624
625 wxIEnumFORMATETC *pEnum = new wxIEnumFORMATETC(formats, nFormatCount);
626 pEnum->AddRef();
627 *ppenumFormatEtc = pEnum;
628
629 if ( formats != &format ) {
630 delete [] formats;
631 }
632
633 return S_OK;
634 }
635
636 // ----------------------------------------------------------------------------
637 // advise sink functions (not implemented)
638 // ----------------------------------------------------------------------------
639
640 STDMETHODIMP wxIDataObject::DAdvise(FORMATETC *WXUNUSED(pformatetc),
641 DWORD WXUNUSED(advf),
642 IAdviseSink *WXUNUSED(pAdvSink),
643 DWORD *WXUNUSED(pdwConnection))
644 {
645 return OLE_E_ADVISENOTSUPPORTED;
646 }
647
648 STDMETHODIMP wxIDataObject::DUnadvise(DWORD WXUNUSED(dwConnection))
649 {
650 return OLE_E_ADVISENOTSUPPORTED;
651 }
652
653 STDMETHODIMP wxIDataObject::EnumDAdvise(IEnumSTATDATA **WXUNUSED(ppenumAdvise))
654 {
655 return OLE_E_ADVISENOTSUPPORTED;
656 }
657
658 // ----------------------------------------------------------------------------
659 // wxDataObject
660 // ----------------------------------------------------------------------------
661
662 wxDataObject::wxDataObject()
663 {
664 m_pIDataObject = new wxIDataObject(this);
665 m_pIDataObject->AddRef();
666 }
667
668 wxDataObject::~wxDataObject()
669 {
670 ReleaseInterface(m_pIDataObject);
671 }
672
673 void wxDataObject::SetAutoDelete()
674 {
675 ((wxIDataObject *)m_pIDataObject)->SetDeleteFlag();
676 m_pIDataObject->Release();
677
678 // so that the dtor doesnt' crash
679 m_pIDataObject = NULL;
680 }
681
682 size_t wxDataObject::GetBufferOffset(const wxDataFormat& format )
683 {
684 // if we prepend the size of the data to the buffer itself, account for it
685 return NeedsVerbatimData(format) ? 0 : sizeof(size_t);
686 }
687
688 const void* wxDataObject::GetSizeFromBuffer( const void* buffer, size_t* size,
689 const wxDataFormat& format )
690 {
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));
695 if ( realsz == (size_t)-1 )
696 {
697 // note that HeapSize() does not set last error
698 wxLogApiError(wxT("HeapSize"), 0);
699 return NULL;
700 }
701
702 *size = realsz;
703
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;
716 }
717
718 void* wxDataObject::SetSizeInBuffer( void* buffer, size_t size,
719 const wxDataFormat& format )
720 {
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 }
727
728 return p;
729 }
730
731 #ifdef __WXDEBUG__
732
733 const wxChar *wxDataObject::GetFormatName(wxDataFormat format)
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
740 static wxChar s_szBuf[256];
741 switch ( format ) {
742 case CF_TEXT: return wxT("CF_TEXT");
743 case CF_BITMAP: return wxT("CF_BITMAP");
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");
754 #ifndef __WXWINCE__
755 case CF_METAFILEPICT: return wxT("CF_METAFILEPICT");
756 case CF_ENHMETAFILE: return wxT("CF_ENHMETAFILE");
757 case CF_LOCALE: return wxT("CF_LOCALE");
758 case CF_HDROP: return wxT("CF_HDROP");
759 #endif
760
761 default:
762 if ( !::GetClipboardFormatName(format, s_szBuf, WXSIZEOF(s_szBuf)) )
763 {
764 // it must be a new predefined format we don't know the name of
765 wxSprintf(s_szBuf, wxT("unknown CF (0x%04x)"), format.GetFormatId());
766 }
767
768 return s_szBuf;
769 }
770
771 #ifdef __VISUALC__
772 #pragma warning(default:4063)
773 #endif // VC++
774 }
775
776 #endif // Debug
777
778 // ----------------------------------------------------------------------------
779 // wxBitmapDataObject supports CF_DIB format
780 // ----------------------------------------------------------------------------
781
782 // TODO: support CF_DIB under Windows CE as well
783
784 size_t wxBitmapDataObject::GetDataSize() const
785 {
786 #if wxUSE_WXDIB && !defined(__WXWINCE__)
787 return wxDIB::ConvertFromBitmap(NULL, GetHbitmapOf(GetBitmap()));
788 #else
789 return 0;
790 #endif
791 }
792
793 bool wxBitmapDataObject::GetDataHere(void *buf) const
794 {
795 #if wxUSE_WXDIB && !defined(__WXWINCE__)
796 BITMAPINFO * const pbi = (BITMAPINFO *)buf;
797
798 return wxDIB::ConvertFromBitmap(pbi, GetHbitmapOf(GetBitmap())) != 0;
799 #else
800 wxUnusedVar(buf);
801 return false;
802 #endif
803 }
804
805 bool wxBitmapDataObject::SetData(size_t WXUNUSED(len), const void *buf)
806 {
807 #if wxUSE_WXDIB && !defined(__WXWINCE__)
808 const BITMAPINFO * const pbmi = (const BITMAPINFO *)buf;
809
810 HBITMAP hbmp = wxDIB::ConvertToBitmap(pbmi);
811
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
819
820 SetBitmap(bitmap);
821
822 return true;
823 #else
824 wxUnusedVar(buf);
825 return false;
826 #endif
827 }
828
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
838 size_t wxBitmapDataObject2::GetDataSize() const
839 {
840 return 0;
841 }
842
843 bool wxBitmapDataObject2::GetDataHere(void *pBuf) const
844 {
845 // we put a bitmap handle into pBuf
846 *(WXHBITMAP *)pBuf = GetBitmap().GetHBITMAP();
847
848 return true;
849 }
850
851 bool wxBitmapDataObject2::SetData(size_t WXUNUSED(len), const void *pBuf)
852 {
853 HBITMAP hbmp = *(HBITMAP *)pBuf;
854
855 BITMAP bmp;
856 if ( !GetObject(hbmp, sizeof(BITMAP), &bmp) )
857 {
858 wxLogLastError(wxT("GetObject(HBITMAP)"));
859 }
860
861 wxBitmap bitmap(bmp.bmWidth, bmp.bmHeight, bmp.bmPlanes);
862 bitmap.SetHBITMAP((WXHBITMAP)hbmp);
863
864 if ( !bitmap.Ok() ) {
865 wxFAIL_MSG(wxT("pasting/dropping invalid bitmap"));
866
867 return false;
868 }
869
870 SetBitmap(bitmap);
871
872 return true;
873 }
874
875 #if 0
876
877 size_t wxBitmapDataObject::GetDataSize(const wxDataFormat& format) const
878 {
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 {
893 wxLogLastError(wxT("GetDIBits(NULL)"));
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 }
905 }
906
907 bool wxBitmapDataObject::GetDataHere(const wxDataFormat& format,
908 void *pBuf) const
909 {
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 {
926 wxLogLastError(wxT("GetDIBits(NULL)"));
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 {
935 wxLogLastError(wxT("GetDIBits"));
936
937 return false;
938 }
939 }
940 else // CF_BITMAP
941 {
942 // we put a bitmap handle into pBuf
943 *(HBITMAP *)pBuf = hbmp;
944 }
945
946 return true;
947 }
948
949 bool wxBitmapDataObject::SetData(const wxDataFormat& format,
950 size_t size, const void *pBuf)
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 {
965 wxLogLastError(wxT("CreateDIBitmap"));
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 {
979 wxLogLastError(wxT("GetObject(HBITMAP)"));
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
991 return true;
992 }
993
994 #endif // 0
995
996 // ----------------------------------------------------------------------------
997 // wxFileDataObject
998 // ----------------------------------------------------------------------------
999
1000 bool wxFileDataObject::SetData(size_t WXUNUSED(size),
1001 const void *WXUNUSED_IN_WINCE(pData))
1002 {
1003 #ifndef __WXWINCE__
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
1017 wxCHECK_MSG ( nFiles != (UINT)-1, FALSE, wxT("wrong HDROP handle") );
1018
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
1026 UINT len2 = ::DragQueryFile(hdrop, n, wxStringBuffer(str, len), len);
1027 m_filenames.Add(str);
1028
1029 if ( len2 != len - 1 ) {
1030 wxLogDebug(wxT("In wxFileDropTarget::OnDrop DragQueryFile returned\
1031 %d characters, %d expected."), len2, len - 1);
1032 }
1033 }
1034
1035 return true;
1036 #else
1037 return false;
1038 #endif
1039 }
1040
1041 void 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
1049 size_t wxFileDataObject::GetDataSize() const
1050 {
1051 #ifndef __WXWINCE__
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
1054
1055 // if no filenames in list, size is 0
1056 if ( m_filenames.empty() )
1057 return 0;
1058
1059 #if wxUSE_UNICODE_MSLU
1060 size_t sizeOfChar;
1061 if ( wxGetOsVersion() == wxOS_WINDOWS_9X )
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
1074 // inital size of DROPFILES struct + null byte
1075 size_t sz = sizeof(DROPFILES) + sizeOfChar;
1076
1077 const size_t count = m_filenames.size();
1078 for ( size_t i = 0; i < count; i++ )
1079 {
1080 // add filename length plus null byte
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;
1090 }
1091
1092 return sz;
1093 #else
1094 return 0;
1095 #endif
1096 }
1097
1098 bool wxFileDataObject::GetDataHere(void *WXUNUSED_IN_WINCE(pData)) const
1099 {
1100 #ifndef __WXWINCE__
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
1105 if ( !pData || m_filenames.empty() )
1106 return false;
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);
1113 pDrop->fNC = FALSE; // not non-client coords
1114 #if wxUSE_UNICODE_MSLU
1115 pDrop->fWide = wxGetOsVersion() != wxOS_WINDOWS_9X ? TRUE : FALSE;
1116 #else
1117 pDrop->fWide = wxUSE_UNICODE;
1118 #endif
1119
1120 const size_t sizeOfChar = pDrop->fWide ? sizeof(wchar_t) : sizeof(char);
1121
1122 // set start of filenames list (null separated)
1123 BYTE *pbuf = (BYTE *)(pDrop + 1);
1124
1125 const size_t count = m_filenames.size();
1126 for ( size_t i = 0; i < count; i++ )
1127 {
1128 // copy filename to pbuf and add null terminator
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;
1148 }
1149
1150 // add final null terminator
1151 memset(pbuf, 0, sizeOfChar);
1152
1153 return true;
1154 #else
1155 return false;
1156 #endif
1157 }
1158
1159 // ----------------------------------------------------------------------------
1160 // wxURLDataObject
1161 // ----------------------------------------------------------------------------
1162
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
1169 class CFSTR_SHELLURLDataObject : public wxCustomDataObject
1170 {
1171 public:
1172 CFSTR_SHELLURLDataObject() : wxCustomDataObject(CFSTR_SHELLURL) {}
1173
1174 virtual size_t GetBufferOffset( const wxDataFormat& WXUNUSED(format) )
1175 {
1176 return 0;
1177 }
1178
1179 virtual const void* GetSizeFromBuffer( const void* buffer, size_t* size,
1180 const wxDataFormat& WXUNUSED(format) )
1181 {
1182 // CFSTR_SHELLURL is _always_ ANSI text
1183 *size = strlen( (const char*)buffer );
1184
1185 return buffer;
1186 }
1187
1188 virtual void* SetSizeInBuffer( void* buffer, size_t WXUNUSED(size),
1189 const wxDataFormat& WXUNUSED(format) )
1190 {
1191 return buffer;
1192 }
1193
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() );
1200 wxString unicode_buffer( char_buffer, wxConvLibc );
1201 memcpy( buffer, unicode_buffer.c_str(),
1202 ( unicode_buffer.length() + 1 ) * sizeof(wxChar) );
1203
1204 return true;
1205 }
1206 virtual bool GetDataHere(const wxDataFormat& WXUNUSED(format),
1207 void *buf) const
1208 { return GetDataHere(buf); }
1209 #endif
1210
1211 DECLARE_NO_COPY_CLASS(CFSTR_SHELLURLDataObject)
1212 };
1213
1214
1215
1216 wxURLDataObject::wxURLDataObject(const wxString& url)
1217 {
1218 // we support CF_TEXT and CFSTR_SHELLURL formats which are basicly the same
1219 // but it seems that some browsers only provide one of them so we have to
1220 // support both
1221 Add(new wxTextDataObject);
1222 Add(new CFSTR_SHELLURLDataObject());
1223
1224 // we don't have any data yet
1225 m_dataObjectLast = NULL;
1226
1227 if ( !url.empty() )
1228 SetURL(url);
1229 }
1230
1231 bool 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
1243 wxString 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
1250 m_dataObjectLast->GetDataHere(wxStringBuffer(url, len));
1251
1252 return url;
1253 }
1254
1255 void wxURLDataObject::SetURL(const wxString& url)
1256 {
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);
1264 }
1265
1266 // ----------------------------------------------------------------------------
1267 // private functions
1268 // ----------------------------------------------------------------------------
1269
1270 #ifdef __WXDEBUG__
1271
1272 static 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:
1284 wxSprintf(s_szBuf, wxT("type of media format %ld (unknown)"), tymed);
1285 return s_szBuf;
1286 }
1287 }
1288
1289 #endif // Debug
1290
1291 #else // not using OLE at all
1292
1293 // ----------------------------------------------------------------------------
1294 // wxDataObject
1295 // ----------------------------------------------------------------------------
1296
1297 #if wxUSE_DATAOBJ
1298
1299 wxDataObject::wxDataObject()
1300 {
1301 }
1302
1303 wxDataObject::~wxDataObject()
1304 {
1305 }
1306
1307 void wxDataObject::SetAutoDelete()
1308 {
1309 }
1310
1311 #ifdef __WXDEBUG__
1312 const wxChar *wxDataObject::GetFormatName(wxDataFormat WXUNUSED(format))
1313 {
1314 return NULL;
1315 }
1316 #endif // __WXDEBUG__
1317
1318 #endif // wxUSE_DATAOBJ
1319
1320 #endif // wxUSE_OLE/!wxUSE_OLE
1321
1322