/[pcsx2_0.9.7]/branch/r3113_0.9.7_beta/3rdparty/wxWidgets/src/msw/ole/dataobj.cpp
ViewVC logotype

Contents of /branch/r3113_0.9.7_beta/3rdparty/wxWidgets/src/msw/ole/dataobj.cpp

Parent Directory Parent Directory | Revision Log Revision Log


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

  ViewVC Help
Powered by ViewVC 1.1.22