1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: src/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 // For compilers that support precompilation, includes "wx.h".
13 #include "wx/wxprec.h"
21 #include "wx/dataobj.h"
27 // ----------------------------------------------------------------------------
29 // ----------------------------------------------------------------------------
31 #include "wx/listimpl.cpp"
33 WX_DEFINE_LIST(wxSimpleDataObjectList
)
35 // ----------------------------------------------------------------------------
37 // ----------------------------------------------------------------------------
39 static wxDataFormat dataFormatInvalid
;
40 WXDLLEXPORT
const wxDataFormat
& wxFormatInvalid
= dataFormatInvalid
;
42 // ============================================================================
44 // ============================================================================
46 // ----------------------------------------------------------------------------
48 // ----------------------------------------------------------------------------
50 wxDataObjectBase
::~wxDataObjectBase()
54 bool wxDataObjectBase
::IsSupported(const wxDataFormat
& format
,
57 size_t nFormatCount
= GetFormatCount( dir
);
58 if ( nFormatCount
== 1 )
60 return format
== GetPreferredFormat( dir
);
64 wxDataFormat
*formats
= new wxDataFormat
[nFormatCount
];
65 GetAllFormats( formats
, dir
);
68 for ( n
= 0; n
< nFormatCount
; n
++ )
70 if ( formats
[n
] == format
)
77 return n
< nFormatCount
;
81 // ----------------------------------------------------------------------------
82 // wxDataObjectComposite
83 // ----------------------------------------------------------------------------
85 wxDataObjectComposite
::wxDataObjectComposite()
88 m_receivedFormat
= wxFormatInvalid
;
91 wxDataObjectComposite
::~wxDataObjectComposite()
93 WX_CLEAR_LIST( wxSimpleDataObjectList
, m_dataObjects
);
97 wxDataObjectComposite
::GetObject(const wxDataFormat
& format
) const
99 wxSimpleDataObjectList
::compatibility_iterator node
= m_dataObjects
.GetFirst();
102 wxDataObjectSimple
*dataObj
= node
->GetData();
104 if ( dataObj
->GetFormat() == format
)
109 node
= node
->GetNext();
115 void wxDataObjectComposite
::Add(wxDataObjectSimple
*dataObject
, bool preferred
)
118 m_preferred
= m_dataObjects
.GetCount();
120 m_dataObjects
.Append( dataObject
);
123 wxDataFormat wxDataObjectComposite
::GetReceivedFormat() const
125 return m_receivedFormat
;
129 wxDataObjectComposite
::GetPreferredFormat(Direction
WXUNUSED(dir
)) const
131 wxSimpleDataObjectList
::compatibility_iterator node
= m_dataObjects
.Item( m_preferred
);
133 wxCHECK_MSG( node
, wxFormatInvalid
, wxT("no preferred format") );
135 wxDataObjectSimple
* dataObj
= node
->GetData();
137 return dataObj
->GetFormat();
140 #if defined(__WXMSW__)
142 size_t wxDataObjectComposite
::GetBufferOffset( const wxDataFormat
& format
)
144 wxDataObjectSimple
*dataObj
= GetObject(format
);
146 wxCHECK_MSG( dataObj
, 0,
147 wxT("unsupported format in wxDataObjectComposite"));
149 return dataObj
->GetBufferOffset( format
);
153 const void* wxDataObjectComposite
::GetSizeFromBuffer( const void* buffer
,
155 const wxDataFormat
& format
)
157 wxDataObjectSimple
*dataObj
= GetObject(format
);
159 wxCHECK_MSG( dataObj
, NULL
,
160 wxT("unsupported format in wxDataObjectComposite"));
162 return dataObj
->GetSizeFromBuffer( buffer
, size
, format
);
166 void* wxDataObjectComposite
::SetSizeInBuffer( void* buffer
, size_t size
,
167 const wxDataFormat
& format
)
169 wxDataObjectSimple
*dataObj
= GetObject( format
);
171 wxCHECK_MSG( dataObj
, NULL
,
172 wxT("unsupported format in wxDataObjectComposite"));
174 return dataObj
->SetSizeInBuffer( buffer
, size
, format
);
179 size_t wxDataObjectComposite
::GetFormatCount(Direction
WXUNUSED(dir
)) const
181 // TODO what about the Get/Set only formats?
182 return m_dataObjects
.GetCount();
185 void wxDataObjectComposite
::GetAllFormats(wxDataFormat
*formats
,
189 wxSimpleDataObjectList
::compatibility_iterator node
;
191 for ( node
= m_dataObjects
.GetFirst(); node
; node
= node
->GetNext() )
193 node
->GetData()->GetAllFormats(formats
+index
,dir
);
194 index
+= node
->GetData()->GetFormatCount(dir
);
198 size_t wxDataObjectComposite
::GetDataSize(const wxDataFormat
& format
) const
200 wxDataObjectSimple
*dataObj
= GetObject(format
);
202 wxCHECK_MSG( dataObj
, 0,
203 wxT("unsupported format in wxDataObjectComposite"));
205 return dataObj
->GetDataSize();
208 bool wxDataObjectComposite
::GetDataHere(const wxDataFormat
& format
,
211 wxDataObjectSimple
*dataObj
= GetObject( format
);
213 wxCHECK_MSG( dataObj
, false,
214 wxT("unsupported format in wxDataObjectComposite"));
216 return dataObj
->GetDataHere( buf
);
219 bool wxDataObjectComposite
::SetData(const wxDataFormat
& format
,
223 wxDataObjectSimple
*dataObj
= GetObject( format
);
225 wxCHECK_MSG( dataObj
, false,
226 wxT("unsupported format in wxDataObjectComposite"));
228 m_receivedFormat
= format
;
229 return dataObj
->SetData( len
, buf
);
232 // ----------------------------------------------------------------------------
234 // ----------------------------------------------------------------------------
236 #ifdef wxNEEDS_UTF8_FOR_TEXT_DATAOBJ
238 // FIXME-UTF8: we should be able to merge wchar_t and UTF-8 versions once we
239 // have a way to get UTF-8 string (and its length) in both builds
240 // without loss of efficiency (i.e. extra buffer copy/strlen call)
242 #if wxUSE_UNICODE_WCHAR
244 static inline wxMBConv
& GetConv(const wxDataFormat
& format
)
246 // use UTF8 for wxDF_UNICODETEXT and UCS4 for wxDF_TEXT
247 return format
== wxDF_UNICODETEXT ? wxConvUTF8
: wxConvLibc
;
250 size_t wxTextDataObject
::GetDataSize(const wxDataFormat
& format
) const
252 wxCharBuffer buffer
= GetConv(format
).cWX2MB( GetText().c_str() );
254 return buffer ?
strlen( buffer
) : 0;
257 bool wxTextDataObject
::GetDataHere(const wxDataFormat
& format
, void *buf
) const
262 wxCharBuffer buffer
= GetConv(format
).cWX2MB( GetText().c_str() );
266 memcpy( (char*) buf
, buffer
, GetDataSize(format
) );
267 // strcpy( (char*) buf, buffer );
272 bool wxTextDataObject
::SetData(const wxDataFormat
& format
,
273 size_t WXUNUSED(len
), const void *buf
)
278 wxWCharBuffer buffer
= GetConv(format
).cMB2WX( (const char*)buf
);
285 #else // wxUSE_UNICODE_UTF8
287 size_t wxTextDataObject
::GetDataSize(const wxDataFormat
& format
) const
289 if ( format
== wxDF_UNICODETEXT
|| wxLocaleIsUtf8
)
291 return m_text
.utf8_length();
295 const wxCharBuffer
buf(wxConvLocal
.cWC2MB(m_text
.wc_str()));
296 return buf ?
strlen(buf
) : 0;
300 bool wxTextDataObject
::GetDataHere(const wxDataFormat
& format
, void *buf
) const
305 if ( format
== wxDF_UNICODETEXT
|| wxLocaleIsUtf8
)
307 memcpy(buf
, m_text
.utf8_str(), m_text
.utf8_length());
311 const wxCharBuffer
bufLocal(wxConvLocal
.cWC2MB(m_text
.wc_str()));
315 memcpy(buf
, bufLocal
, strlen(bufLocal
));
321 bool wxTextDataObject
::SetData(const wxDataFormat
& format
,
322 size_t len
, const void *buf_
)
324 const char * const buf
= static_cast<const char *>(buf_
);
329 if ( format
== wxDF_UNICODETEXT
|| wxLocaleIsUtf8
)
331 // normally the data is in UTF-8 so we could use FromUTF8Unchecked()
332 // but it's not absolutely clear what GTK+ does if the clipboard data
333 // is not in UTF-8 so do an extra check for tranquility, it shouldn't
334 // matter much if we lose a bit of performance when pasting from
336 m_text
= wxString
::FromUTF8(buf
, len
);
338 else // wxDF_TEXT, convert from current (non-UTF8) locale
340 m_text
= wxConvLocal
.cMB2WC(buf
, len
, NULL
);
346 #endif // wxUSE_UNICODE_WCHAR/wxUSE_UNICODE_UTF8
348 #elif defined(wxNEEDS_UTF16_FOR_TEXT_DATAOBJ)
350 static wxMBConvUTF16 sUTF16Converter
;
352 static inline wxMBConv
& GetConv(const wxDataFormat
& format
)
355 format
== wxDF_UNICODETEXT
356 ?
(wxMBConv
&) sUTF16Converter
357 : (wxMBConv
&) wxConvLocal
;
360 size_t wxTextDataObject
::GetDataSize(const wxDataFormat
& format
) const
362 size_t len
= GetConv(format
).WC2MB( NULL
, GetText().c_str(), 0 );
363 len
+= (format
== wxDF_UNICODETEXT ?
2 : 1);
368 bool wxTextDataObject
::GetDataHere(const wxDataFormat
& format
, void *buf
) const
373 wxCharBuffer buffer
= GetConv(format
).cWX2MB( GetText().c_str() );
375 size_t len
= GetConv(format
).WC2MB( NULL
, GetText().c_str(), 0 );
376 len
+= (format
== wxDF_UNICODETEXT ?
2 : 1);
378 // trailing (uni)char 0
379 memcpy( (char*)buf
, (const char*)buffer
, len
);
384 bool wxTextDataObject
::SetData(const wxDataFormat
& format
,
385 size_t WXUNUSED(len
), const void *buf
)
390 wxWCharBuffer buffer
= GetConv(format
).cMB2WX( (const char*)buf
);
397 #else // !wxNEEDS_UTF{8,16}_FOR_TEXT_DATAOBJ
399 size_t wxTextDataObject
::GetDataSize() const
401 return GetTextLength() * sizeof(wxChar
);
404 bool wxTextDataObject
::GetDataHere(void *buf
) const
406 wxStrcpy( (wxChar
*)buf
, GetText().c_str() );
411 bool wxTextDataObject
::SetData(size_t WXUNUSED(len
), const void *buf
)
413 SetText( wxString((const wxChar
*)buf
) );
418 #endif // different wxTextDataObject implementations
420 // ----------------------------------------------------------------------------
421 // wxCustomDataObject
422 // ----------------------------------------------------------------------------
424 wxCustomDataObject
::wxCustomDataObject(const wxDataFormat
& format
)
425 : wxDataObjectSimple(format
)
431 wxCustomDataObject
::~wxCustomDataObject()
436 void wxCustomDataObject
::TakeData(size_t size
, void *data
)
444 void *wxCustomDataObject
::Alloc(size_t size
)
446 return (void *)new char[size
];
449 void wxCustomDataObject
::Free()
451 delete [] (char*)m_data
;
456 size_t wxCustomDataObject
::GetDataSize() const
461 bool wxCustomDataObject
::GetDataHere(void *buf
) const
466 void *data
= GetData();
470 memcpy( buf
, data
, GetSize() );
475 bool wxCustomDataObject
::SetData(size_t size
, const void *buf
)
479 m_data
= Alloc(size
);
480 if ( m_data
== NULL
)
484 memcpy( m_data
, buf
, m_size
);
489 // ============================================================================
490 // some common dnd related code
491 // ============================================================================
493 #if wxUSE_DRAG_AND_DROP
497 // ----------------------------------------------------------------------------
499 // ----------------------------------------------------------------------------
501 // NB: we can't use "new" in ctor initializer lists because this provokes an
502 // internal compiler error with VC++ 5.0 (hey, even gcc compiles this!),
503 // so use SetDataObject() instead
505 wxTextDropTarget
::wxTextDropTarget()
507 SetDataObject(new wxTextDataObject
);
510 wxDragResult wxTextDropTarget
::OnData(wxCoord x
, wxCoord y
, wxDragResult def
)
515 wxTextDataObject
*dobj
= (wxTextDataObject
*)m_dataObject
;
516 return OnDropText( x
, y
, dobj
->GetText() ) ? def
: wxDragNone
;
519 // ----------------------------------------------------------------------------
521 // ----------------------------------------------------------------------------
523 wxFileDropTarget
::wxFileDropTarget()
525 SetDataObject(new wxFileDataObject
);
528 wxDragResult wxFileDropTarget
::OnData(wxCoord x
, wxCoord y
, wxDragResult def
)
533 wxFileDataObject
*dobj
= (wxFileDataObject
*)m_dataObject
;
534 return OnDropFiles( x
, y
, dobj
->GetFilenames() ) ? def
: wxDragNone
;
537 #endif // wxUSE_DRAG_AND_DROP
539 #endif // wxUSE_DATAOBJ