1 /////////////////////////////////////////////////////////////////////////////// 
   2 // Name:        common/dobjcmn.cpp 
   3 // Purpose:     implementation of data object methods common to all platforms 
   4 // Author:      Vadim Zeitlin, Robert Roebling 
   8 // Copyright:   (c) wxWidgets Team 
   9 // Licence:     wxWindows licence 
  10 /////////////////////////////////////////////////////////////////////////////// 
  12 // ============================================================================ 
  14 // ============================================================================ 
  16 // ---------------------------------------------------------------------------- 
  18 // ---------------------------------------------------------------------------- 
  20 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) 
  21     #pragma implementation "dataobjbase.h" 
  24 #include "wx/wxprec.h" 
  37 #include "wx/dataobj.h" 
  39 // ---------------------------------------------------------------------------- 
  41 // ---------------------------------------------------------------------------- 
  43 #include "wx/listimpl.cpp" 
  45 WX_DEFINE_LIST(wxSimpleDataObjectList
); 
  47 // ---------------------------------------------------------------------------- 
  49 // ---------------------------------------------------------------------------- 
  51 static wxDataFormat dataFormatInvalid
; 
  52 WXDLLEXPORT 
const wxDataFormat
& wxFormatInvalid 
= dataFormatInvalid
; 
  54 // ============================================================================ 
  56 // ============================================================================ 
  58 // ---------------------------------------------------------------------------- 
  60 // ---------------------------------------------------------------------------- 
  62 wxDataObjectBase::~wxDataObjectBase() 
  66 bool wxDataObjectBase::IsSupported(const wxDataFormat
& format
, 
  69     size_t nFormatCount 
= GetFormatCount(dir
); 
  70     if ( nFormatCount 
== 1 ) 
  72         return format 
== GetPreferredFormat(dir
); 
  76         wxDataFormat 
*formats 
= new wxDataFormat
[nFormatCount
]; 
  77         GetAllFormats(formats
, dir
); 
  80         for ( n 
= 0; n 
< nFormatCount
; n
++ ) 
  82             if ( formats
[n
] == format 
) 
  89         return n 
< nFormatCount
; 
  93 // ---------------------------------------------------------------------------- 
  94 // wxDataObjectComposite 
  95 // ---------------------------------------------------------------------------- 
  97 wxDataObjectComposite::wxDataObjectComposite() 
 102 wxDataObjectComposite::~wxDataObjectComposite() 
 104     WX_CLEAR_LIST(wxSimpleDataObjectList
, m_dataObjects
); 
 108 wxDataObjectComposite::GetObject(const wxDataFormat
& format
) const 
 110     wxSimpleDataObjectList::compatibility_iterator node 
= m_dataObjects
.GetFirst(); 
 113         wxDataObjectSimple 
*dataObj 
= node
->GetData(); 
 115         if ( dataObj
->GetFormat() == format 
) 
 120         node 
= node
->GetNext(); 
 123     return (wxDataObjectSimple 
*)NULL
; 
 126 void wxDataObjectComposite::Add(wxDataObjectSimple 
*dataObject
, bool preferred
) 
 129         m_preferred 
= m_dataObjects
.GetCount(); 
 131     m_dataObjects
.Append( dataObject 
); 
 135 wxDataObjectComposite::GetPreferredFormat(Direction 
WXUNUSED(dir
)) const 
 137     wxSimpleDataObjectList::compatibility_iterator node 
= m_dataObjects
.Item( m_preferred 
); 
 139     wxCHECK_MSG( node
, wxFormatInvalid
, wxT("no preferred format") ); 
 141     wxDataObjectSimple
* dataObj 
= node
->GetData(); 
 143     return dataObj
->GetFormat(); 
 146 #if defined(__WXMSW__) 
 148 size_t wxDataObjectComposite::GetBufferOffset( const wxDataFormat
& format 
) 
 150     wxDataObjectSimple 
*dataObj 
= GetObject(format
); 
 152     wxCHECK_MSG( dataObj
, 0, 
 153                  wxT("unsupported format in wxDataObjectComposite")); 
 155     return dataObj
->GetBufferOffset( format 
); 
 159 const void* wxDataObjectComposite::GetSizeFromBuffer( const void* buffer
, 
 161                                                       const wxDataFormat
& format 
) 
 163     wxDataObjectSimple 
*dataObj 
= GetObject(format
); 
 165     wxCHECK_MSG( dataObj
, NULL
, 
 166                  wxT("unsupported format in wxDataObjectComposite")); 
 168     return dataObj
->GetSizeFromBuffer( buffer
, size
, format 
); 
 172 void* wxDataObjectComposite::SetSizeInBuffer( void* buffer
, size_t size
, 
 173                                               const wxDataFormat
& format 
) 
 175     wxDataObjectSimple 
*dataObj 
= GetObject(format
); 
 177     wxCHECK_MSG( dataObj
, NULL
, 
 178                  wxT("unsupported format in wxDataObjectComposite")); 
 180     return dataObj
->SetSizeInBuffer( buffer
, size
, format 
); 
 185 size_t wxDataObjectComposite::GetFormatCount(Direction 
WXUNUSED(dir
)) const 
 187     // TODO what about the Get/Set only formats? 
 188     return m_dataObjects
.GetCount(); 
 191 void wxDataObjectComposite::GetAllFormats(wxDataFormat 
*formats
, 
 192                                           Direction 
WXUNUSED(dir
)) const 
 195     wxSimpleDataObjectList::compatibility_iterator node
; 
 196     for ( node 
= m_dataObjects
.GetFirst(); node
; node 
= node
->GetNext() ) 
 198         // TODO if ( !outputOnlyToo ) && this one counts ... 
 199         formats
[n
++] = node
->GetData()->GetFormat(); 
 203 size_t wxDataObjectComposite::GetDataSize(const wxDataFormat
& format
) const 
 205     wxDataObjectSimple 
*dataObj 
= GetObject(format
); 
 207     wxCHECK_MSG( dataObj
, 0, 
 208                  wxT("unsupported format in wxDataObjectComposite")); 
 210     return dataObj
->GetDataSize(); 
 213 bool wxDataObjectComposite::GetDataHere(const wxDataFormat
& format
, 
 216     wxDataObjectSimple 
*dataObj 
= GetObject(format
); 
 218     wxCHECK_MSG( dataObj
, false, 
 219                  wxT("unsupported format in wxDataObjectComposite")); 
 221     return dataObj
->GetDataHere(buf
); 
 224 bool wxDataObjectComposite::SetData(const wxDataFormat
& format
, 
 228     wxDataObjectSimple 
*dataObj 
= GetObject(format
); 
 230     wxCHECK_MSG( dataObj
, false, 
 231                  wxT("unsupported format in wxDataObjectComposite")); 
 233     return dataObj
->SetData(len
, buf
); 
 236 // ---------------------------------------------------------------------------- 
 238 // ---------------------------------------------------------------------------- 
 240 #if defined(__WXGTK20__) && wxUSE_UNICODE 
 242 static inline wxMBConv
& GetConv(const wxDataFormat
& format
) 
 244     // use UTF8 for wxDF_UNICODETEXT and UCS4 for wxDF_TEXT 
 245     return format 
== wxDF_UNICODETEXT 
? wxConvUTF8 
: wxConvLibc
; 
 248 size_t wxTextDataObject::GetDataSize(const wxDataFormat
& format
) const 
 250     wxCharBuffer buffer 
= GetConv(format
).cWX2MB( GetText().c_str() ); 
 251     return buffer 
? strlen(buffer
) + 1 : 0; 
 254 bool wxTextDataObject::GetDataHere(const wxDataFormat
& format
, void *buf
) const 
 256     wxCharBuffer buffer 
= GetConv(format
).cWX2MB( GetText().c_str() ); 
 260     strcpy( (char*) buf
, buffer 
); 
 265 bool wxTextDataObject::SetData(const wxDataFormat
& format
, 
 266                                size_t WXUNUSED(len
), const void *buf
) 
 268     wxWCharBuffer buffer 
= GetConv(format
).cMB2WX((const char *)buf
); 
 277 #elif wxUSE_UNICODE && defined(__WXMAC__) 
 279 size_t wxTextDataObject::GetDataSize(const wxDataFormat
& format
) const 
 281     if (format 
== wxDF_UNICODETEXT
) 
 283         // host native is UTF16 
 284         wxMBConvUTF16BE converter 
; 
 285         return converter
.WC2MB( NULL 
, GetText().c_str() , 0 ) + 2; // add space for trailing unichar 0 
 289         wxCharBuffer buffer 
= wxConvLibc
.cWX2MB( GetText().c_str() ); 
 290         return strlen( (const char*) buffer 
) + 1; 
 294 bool wxTextDataObject::GetDataHere(const wxDataFormat
& format
, void *buf
) const 
 296     if (format 
== wxDF_UNICODETEXT
) 
 298         // host native is UTF16 
 299         wxMBConvUTF16BE converter 
; 
 300         size_t len 
= converter
.WC2MB( NULL 
, GetText().c_str() , 0 ) ; 
 301         wxCharBuffer buffer 
= converter
.cWX2MB( GetText().c_str() ); 
 302         memcpy( (char*) buf
, (const char*) buffer 
, len 
+ 2); // trailing unichar 0 
 306         wxCharBuffer buffer 
= wxConvLibc
.cWX2MB( GetText().c_str() ); 
 307         strcpy( (char*) buf
, (const char*) buffer 
); 
 313 bool wxTextDataObject::SetData(const wxDataFormat
& format
, 
 314                                size_t WXUNUSED(len
), const void *buf
) 
 316     if (format 
== wxDF_UNICODETEXT
) 
 318         // host native is UTF16 
 319         wxMBConvUTF16BE converter 
; 
 320         SetText( converter
.cMB2WX( (const char*) buf 
) ); 
 323         SetText( wxConvLibc
.cMB2WX( (const char*) buf 
) ); 
 330 size_t wxTextDataObject::GetDataSize() const 
 332     return GetTextLength() * sizeof(wxChar
); 
 335 bool wxTextDataObject::GetDataHere(void *buf
) const 
 337     wxStrcpy((wxChar 
*)buf
, GetText().c_str()); 
 342 bool wxTextDataObject::SetData(size_t WXUNUSED(len
), const void *buf
) 
 344     SetText(wxString((const wxChar 
*)buf
)); 
 351 // ---------------------------------------------------------------------------- 
 352 // wxFileDataObjectBase 
 353 // ---------------------------------------------------------------------------- 
 355 // VZ: I don't need this in MSW finally, so if it is needed in wxGTK, it should 
 356 //     be moved to gtk/dataobj.cpp 
 359 wxString 
wxFileDataObjectBase::GetFilenames() const 
 362     size_t count 
= m_filenames
.GetCount(); 
 363     for ( size_t n 
= 0; n 
< count
; n
++ ) 
 365         str 
<< m_filenames
[n
] << wxT('\0'); 
 371 void wxFileDataObjectBase::SetFilenames(const wxChar
* filenames
) 
 376     for ( const wxChar 
*pc 
= filenames
; ; pc
++ ) 
 386                 // 2 consecutive NULs - this is the end of the string 
 390             m_filenames
.Add(current
); 
 398 // ---------------------------------------------------------------------------- 
 399 // wxCustomDataObject 
 400 // ---------------------------------------------------------------------------- 
 402 wxCustomDataObject::wxCustomDataObject(const wxDataFormat
& format
) 
 403     : wxDataObjectSimple(format
) 
 405     m_data 
= (void *)NULL
; 
 408 wxCustomDataObject::~wxCustomDataObject() 
 413 void wxCustomDataObject::TakeData(size_t size
, void *data
) 
 421 void *wxCustomDataObject::Alloc(size_t size
) 
 423     return (void *)new char[size
]; 
 426 void wxCustomDataObject::Free() 
 428     delete [] (char *)m_data
; 
 430     m_data 
= (void *)NULL
; 
 433 size_t wxCustomDataObject::GetDataSize() const 
 438 bool wxCustomDataObject::GetDataHere(void *buf
) const 
 440     void *data 
= GetData(); 
 444     memcpy(buf
, data
, GetSize()); 
 449 bool wxCustomDataObject::SetData(size_t size
, const void *buf
) 
 453     m_data 
= Alloc(size
); 
 457     memcpy(m_data
, buf
, m_size 
= size
); 
 462 // ============================================================================ 
 463 // some common dnd related code 
 464 // ============================================================================ 
 466 #if wxUSE_DRAG_AND_DROP 
 470 // ---------------------------------------------------------------------------- 
 472 // ---------------------------------------------------------------------------- 
 474 // NB: we can't use "new" in ctor initializer lists because this provokes an 
 475 //     internal compiler error with VC++ 5.0 (hey, even gcc compiles this!), 
 476 //     so use SetDataObject() instead 
 478 wxTextDropTarget::wxTextDropTarget() 
 480     SetDataObject(new wxTextDataObject
); 
 483 wxDragResult 
wxTextDropTarget::OnData(wxCoord x
, wxCoord y
, wxDragResult def
) 
 488     wxTextDataObject 
*dobj 
= (wxTextDataObject 
*)m_dataObject
; 
 489     return OnDropText(x
, y
, dobj
->GetText()) ? def 
: wxDragNone
; 
 492 // ---------------------------------------------------------------------------- 
 494 // ---------------------------------------------------------------------------- 
 496 wxFileDropTarget::wxFileDropTarget() 
 498     SetDataObject(new wxFileDataObject
); 
 501 wxDragResult 
wxFileDropTarget::OnData(wxCoord x
, wxCoord y
, wxDragResult def
) 
 506     wxFileDataObject 
*dobj 
= (wxFileDataObject 
*)m_dataObject
; 
 507     return OnDropFiles(x
, y
, dobj
->GetFilenames()) ? def 
: wxDragNone
; 
 510 #endif // wxUSE_DRAG_AND_DROP 
 512 #endif // wxUSE_DATAOBJ