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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 32 - (hide annotations) (download)
Tue Sep 7 03:29:01 2010 UTC (10 years ago) by william
File size: 39673 byte(s)
branching from upstream revision (http://pcsx2.googlecode.com/svn/trunk
): r3113 to
https://svn.netsolutions.dnsalias.com/websvn/ps2/pcsx2/pcsx2_0.9.7/branch/r3113_0.9.7_beta
1 william 31 ///////////////////////////////////////////////////////////////////////////////
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