X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/1dd989e1bf4c3667d27b3c27a9cf64a66484ee90..adac097759c089b3d47f48c7756ace4f0b8df879:/src/gtk/dataobj.cpp?ds=sidebyside diff --git a/src/gtk/dataobj.cpp b/src/gtk/dataobj.cpp index 401dca0db0..d591070266 100644 --- a/src/gtk/dataobj.cpp +++ b/src/gtk/dataobj.cpp @@ -17,8 +17,7 @@ #include "wx/mstream.h" #include "wx/image.h" -#include "gdk/gdk.h" - +#include //------------------------------------------------------------------------- // global data @@ -34,7 +33,14 @@ GdkAtom g_fileAtom = 0; wxDataFormat::wxDataFormat() { - PrepareFormats(); + // do *not* call PrepareFormats() from here for 2 reasons: + // + // 1. we will have time to do it later because some other Set function + // must be called before we really need them + // + // 2. doing so prevents us from declaring global wxDataFormats because + // calling PrepareFormats (and thus gdk_atom_intern) before GDK is + // initialised will result in a crash m_type = wxDF_INVALID; m_format = (GdkAtom) 0; } @@ -65,6 +71,7 @@ wxDataFormat::wxDataFormat( NativeFormat format ) void wxDataFormat::SetType( wxDataFormatId type ) { + PrepareFormats(); m_type = type; if (m_type == wxDF_TEXT) @@ -94,6 +101,7 @@ wxString wxDataFormat::GetId() const void wxDataFormat::SetId( NativeFormat format ) { + PrepareFormats(); m_format = format; if (m_format == g_textAtom) @@ -110,6 +118,7 @@ void wxDataFormat::SetId( NativeFormat format ) void wxDataFormat::SetId( const wxChar *id ) { + PrepareFormats(); m_type = wxDF_PRIVATE; wxString tmp( id ); m_format = gdk_atom_intern( wxMBSTRINGCAST tmp.mbc_str(), FALSE ); // what is the string cast for? @@ -117,40 +126,44 @@ void wxDataFormat::SetId( const wxChar *id ) void wxDataFormat::PrepareFormats() { - if (!g_textAtom) - g_textAtom = gdk_atom_intern( "STRING", FALSE ); - if (!g_pngAtom) + // VZ: GNOME included in RedHat 6.1 uses the MIME types below and not the + // atoms STRING and file:ALL as the old code was, but normal X apps + // use STRING for text selection when transfering the data via + // clipboard, for example, so do use STRING for now (GNOME apps will + // probably support STRING as well for compatibility anyhow), but use + // text/uri-list for file dnd because compatibility is not important + // here (with whom?) + if (!g_textAtom) + g_textAtom = gdk_atom_intern( "STRING" /* "text/plain" */, FALSE ); + if (!g_pngAtom) g_pngAtom = gdk_atom_intern( "image/png", FALSE ); - if (!g_fileAtom) - g_fileAtom = gdk_atom_intern( "file:ALL", FALSE ); + if (!g_fileAtom) + g_fileAtom = gdk_atom_intern( "text/uri-list", FALSE ); } //------------------------------------------------------------------------- // wxDataObject //------------------------------------------------------------------------- -IMPLEMENT_ABSTRACT_CLASS( wxDataObject, wxObject ) - wxDataObject::wxDataObject() { } -wxDataObject::~wxDataObject() +bool wxDataObject::IsSupportedFormat(const wxDataFormat& format, Direction dir) const { -} - -bool wxDataObject::IsSupportedFormat(const wxDataFormat& format) const -{ - size_t nFormatCount = GetFormatCount(); - if ( nFormatCount == 1 ) { + size_t nFormatCount = GetFormatCount(dir); + if ( nFormatCount == 1 ) + { return format == GetPreferredFormat(); } - else { + else + { wxDataFormat *formats = new wxDataFormat[nFormatCount]; - GetAllFormats(formats); + GetAllFormats(formats,dir); size_t n; - for ( n = 0; n < nFormatCount; n++ ) { + for ( n = 0; n < nFormatCount; n++ ) + { if ( formats[n] == format ) break; } @@ -162,231 +175,201 @@ bool wxDataObject::IsSupportedFormat(const wxDataFormat& format) const } } - // ---------------------------------------------------------------------------- -// wxTextDataObject +// wxFileDataObject // ---------------------------------------------------------------------------- -IMPLEMENT_DYNAMIC_CLASS( wxTextDataObject, wxDataObject ) - -wxTextDataObject::wxTextDataObject() -{ -} - -wxTextDataObject::wxTextDataObject(const wxString& strText) - : m_strText(strText) -{ -} +bool wxFileDataObject::GetDataHere(void *buf) const +{ + wxString filenames; -size_t wxTextDataObject::GetDataSize(const wxDataFormat& format) const -{ - return m_strText.Len() + 1; // +1 for trailing '\0'of course -} + for (size_t i = 0; i < m_filenames.GetCount(); i++) + { + filenames += m_filenames[i]; + filenames += (wxChar) 0; + } -bool wxTextDataObject::GetDataHere(const wxDataFormat& format, void *buf) const -{ - memcpy(buf, m_strText.c_str(), GetDataSize(format)); - return TRUE; -} + memcpy( buf, filenames.mbc_str(), filenames.Len() + 1 ); -bool wxTextDataObject::SetData(const wxDataFormat& format, const void *buf) -{ - m_strText = (const wxChar *)buf; return TRUE; } -// ---------------------------------------------------------------------------- -// wxFileDataObject -// ---------------------------------------------------------------------------- - -IMPLEMENT_DYNAMIC_CLASS( wxFileDataObject, wxDataObject ) - -wxFileDataObject::wxFileDataObject() +size_t wxFileDataObject::GetDataSize() const { -} + size_t res = 0; -void wxFileDataObject::AddFile( const wxString &file ) -{ - m_files += file; - m_files += (wxChar)0; -} + for (size_t i = 0; i < m_filenames.GetCount(); i++) + { + res += m_filenames[i].Len(); + res += 1; + } -wxString wxFileDataObject::GetFiles() const -{ - return m_files; + return res + 1; } -bool wxFileDataObject::GetDataHere(const wxDataFormat& format, void *buf) const +bool wxFileDataObject::SetData(size_t WXUNUSED(size), const void *buf) { - if (format == wxDF_FILENAME) + // VZ: old format +#if 0 + // filenames are stores as a string with #0 as deliminators + const char *filenames = (const char*) buf; + size_t pos = 0; + for(;;) { - memcpy( buf, m_files.mbc_str(), m_files.Len() + 1 ); - return TRUE; + if (filenames[0] == 0) + break; + if (pos >= size) + break; + wxString file( filenames ); // this returns the first file + AddFile( file ); + pos += file.Len()+1; + filenames += file.Len()+1; } - - return FALSE; -} +#else // 1 + m_filenames.Empty(); + + // the text/uri-list format is a sequence of URIs (filenames prefixed by + // "file:" as far as I see) delimited by "\r\n" of total length size + // (I wonder what happens if the file has '\n' in its filename??) + wxString filename; + for ( const char *p = (const char *)buf; ; p++ ) + { + // some broken programs (testdnd GTK+ sample!) omit the trailing + // "\r\n", so check for '\0' explicitly here instead of doing it in + // the loop statement to account for it + if ( (*p == '\r' && *(p+1) == '\n') || !*p ) + { + size_t lenPrefix = 5; // strlen("file:") + if ( filename.Left(lenPrefix).MakeLower() == _T("file:") ) + { + // sometimes the syntax is "file:filename", sometimes it's + // URL-like: "file://filename" - deal with both + if ( filename[lenPrefix] == _T('/') && + filename[lenPrefix + 1] == _T('/') ) + { + // skip the slashes + lenPrefix += 2; + } + + AddFile(filename.c_str() + lenPrefix); + filename.Empty(); + } + else + { + wxLogDebug(_T("Unsupported URI '%s' in wxFileDataObject"), + filename.c_str()); + } + + if ( !*p ) + break; -size_t wxFileDataObject::GetDataSize(const wxDataFormat& format) const -{ - if (format != wxDF_FILENAME) return 0; - - return m_files.Len() + 1; + // skip '\r' + p++; + } + else + { + filename += *p; + } + } +#endif // 0/1 + + return TRUE; } -bool wxFileDataObject::SetData(const wxDataFormat& format, const void *buf) +void wxFileDataObject::AddFile( const wxString &filename ) { - if (format != wxDF_FILENAME) - return FALSE; - - m_files = (char*)(buf); // this is so ugly, I cannot look at it - - return TRUE; + m_filenames.Add( filename ); } // ---------------------------------------------------------------------------- // wxBitmapDataObject // ---------------------------------------------------------------------------- -IMPLEMENT_DYNAMIC_CLASS( wxBitmapDataObject, wxDataObject ) - wxBitmapDataObject::wxBitmapDataObject() { - m_pngData = (void*)NULL; - m_pngSize = 0; + Init(); } wxBitmapDataObject::wxBitmapDataObject( const wxBitmap& bitmap ) + : wxBitmapDataObjectBase(bitmap) { - m_pngData = (void*)NULL; - m_pngSize = 0; - m_bitmap = bitmap; + Init(); + DoConvertToPng(); } wxBitmapDataObject::~wxBitmapDataObject() { - if (m_pngData) - delete[] m_pngData; + Clear(); } void wxBitmapDataObject::SetBitmap( const wxBitmap &bitmap ) { - if (m_pngData) - delete[] m_pngData; - m_pngData = (void*)NULL; - m_pngSize = 0; - - m_bitmap = bitmap; - DoConvertToPng(); -} + ClearAll(); -size_t wxBitmapDataObject::GetDataSize(const wxDataFormat& format) const -{ - if (format != wxDF_BITMAP) return 0; - - return m_pngSize; + wxBitmapDataObjectBase::SetBitmap(bitmap); + + DoConvertToPng(); } -bool wxBitmapDataObject::GetDataHere(const wxDataFormat& format, void *buf) const +bool wxBitmapDataObject::GetDataHere(void *buf) const { - if (format != wxDF_BITMAP) return FALSE; - - if (m_pngSize > 0) + if ( !m_pngSize ) { - memcpy(buf, m_pngData, m_pngSize); - return TRUE; + wxFAIL_MSG( wxT("attempt to copy empty bitmap failed") ); + + return FALSE; } - - return FALSE; -} -bool wxBitmapDataObject::SetData(const wxDataFormat& format, const void *buf) -{ - if (m_pngData) delete[] m_pngData; - m_pngData = (void*) NULL; - m_pngSize = 0; - m_bitmap = wxNullBitmap; - - return FALSE; + memcpy(buf, m_pngData, m_pngSize); + + return TRUE; } -void wxBitmapDataObject::SetPngData(const void *buf, size_t size) +bool wxBitmapDataObject::SetData(size_t size, const void *buf) { - if (m_pngData) delete[] m_pngData; + Clear(); + +#if wxUSE_LIBPNG m_pngSize = size; - m_pngData = (void*) new char[m_pngSize]; - + m_pngData = malloc(m_pngSize); + memcpy( m_pngData, buf, m_pngSize ); - + wxMemoryInputStream mstream( (char*) m_pngData, m_pngSize ); wxImage image; wxPNGHandler handler; - handler.LoadFile( &image, mstream ); + if ( !handler.LoadFile( &image, mstream ) ) + { + return FALSE; + } + m_bitmap = image.ConvertToBitmap(); + + return m_bitmap.Ok(); +#else + return FALSE; +#endif } void wxBitmapDataObject::DoConvertToPng() { - if (!m_bitmap.Ok()) return; - +#if wxUSE_LIBPNG + if (!m_bitmap.Ok()) + return; + wxImage image( m_bitmap ); wxPNGHandler handler; - + wxCountingOutputStream count; handler.SaveFile( &image, count ); + m_pngSize = count.GetSize() + 100; // sometimes the size seems to vary ??? - m_pngData = (void*) new char[m_pngSize]; - + m_pngData = malloc(m_pngSize); + wxMemoryOutputStream mstream( (char*) m_pngData, m_pngSize ); handler.SaveFile( &image, mstream ); +#endif } -// ---------------------------------------------------------------------------- -// wxPrivateDataObject -// ---------------------------------------------------------------------------- - -IMPLEMENT_CLASS( wxPrivateDataObject, wxDataObject ) - -void wxPrivateDataObject::Free() -{ - if ( m_data ) - free(m_data); -} - -wxPrivateDataObject::wxPrivateDataObject() -{ - wxString id = wxT("application/"); - id += wxTheApp->GetAppName(); - - m_format.SetId( id ); - - m_size = 0; - m_data = (void *)NULL; -} - -void wxPrivateDataObject::SetData( const void *data, size_t size ) -{ - Free(); - - m_size = size; - m_data = malloc(size); - - memcpy( m_data, data, size ); -} - -void wxPrivateDataObject::WriteData( void *dest ) const -{ - WriteData( m_data, dest ); -} - -size_t wxPrivateDataObject::GetSize() const -{ - return m_size; -} - -void wxPrivateDataObject::WriteData( const void *data, void *dest ) const -{ - memcpy( dest, data, GetSize() ); -}