X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/bb5b7285057aa71bd9d86aad6effb00dbfcd1f85..62795f413a7222863b4aee76c08764071f94bd87:/src/gtk/dataobj.cpp diff --git a/src/gtk/dataobj.cpp b/src/gtk/dataobj.cpp index 55d829e2d0..9a3960797d 100644 --- a/src/gtk/dataobj.cpp +++ b/src/gtk/dataobj.cpp @@ -2,7 +2,6 @@ // Name: src/gtk/dataobj.cpp // Purpose: wxDataObject class // Author: Robert Roebling -// Id: $Id$ // Copyright: (c) 1998 Robert Roebling // Licence: wxWindows licence /////////////////////////////////////////////////////////////////////////////// @@ -33,6 +32,7 @@ GdkAtom g_textAtom = 0; GdkAtom g_altTextAtom = 0; GdkAtom g_pngAtom = 0; GdkAtom g_fileAtom = 0; +GdkAtom g_htmlAtom = 0; //------------------------------------------------------------------------- // wxDataFormat @@ -58,13 +58,7 @@ wxDataFormat::wxDataFormat( wxDataFormatId type ) SetType( type ); } -wxDataFormat::wxDataFormat( const wxChar *id ) -{ - PrepareFormats(); - SetId( id ); -} - -wxDataFormat::wxDataFormat( const wxString &id ) +void wxDataFormat::InitFromString( const wxString &id ) { PrepareFormats(); SetId( id ); @@ -87,10 +81,13 @@ void wxDataFormat::SetType( wxDataFormatId type ) m_format = g_textAtom; else if (m_type == wxDF_TEXT) m_format = g_altTextAtom; -#else - if (m_type == wxDF_TEXT || m_type == wxDF_UNICODETEXT) +#else // !wxUSE_UNICODE + // notice that we don't map wxDF_UNICODETEXT to g_textAtom here, this + // would lead the code elsewhere to treat data objects with this format as + // containing UTF-8 data which is not true + if (m_type == wxDF_TEXT) m_format = g_textAtom; -#endif +#endif // wxUSE_UNICODE/!wxUSE_UNICODE else if (m_type == wxDF_BITMAP) m_format = g_pngAtom; @@ -98,6 +95,9 @@ void wxDataFormat::SetType( wxDataFormatId type ) if (m_type == wxDF_FILENAME) m_format = g_fileAtom; else + if (m_type == wxDF_HTML) + m_format = g_htmlAtom; + else { wxFAIL_MSG( wxT("invalid dataformat") ); } @@ -134,38 +134,44 @@ void wxDataFormat::SetId( NativeFormat format ) else if (m_format == g_fileAtom) m_type = wxDF_FILENAME; + else + if (m_format == g_htmlAtom) + m_type = wxDF_HTML; else m_type = wxDF_PRIVATE; } -void wxDataFormat::SetId( const wxChar *id ) +void wxDataFormat::SetId( const wxString& id ) { PrepareFormats(); m_type = wxDF_PRIVATE; - wxString tmp( id ); - m_format = gdk_atom_intern( (const char*) tmp.ToAscii(), FALSE ); + m_format = gdk_atom_intern( id.ToAscii(), FALSE ); } void wxDataFormat::PrepareFormats() { // 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 + // use STRING for text selection when transferring 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) + { #if wxUSE_UNICODE g_textAtom = gdk_atom_intern( "UTF8_STRING", FALSE ); g_altTextAtom = gdk_atom_intern( "STRING", FALSE ); #else g_textAtom = gdk_atom_intern( "STRING" /* "text/plain" */, FALSE ); #endif + } if (!g_pngAtom) g_pngAtom = gdk_atom_intern( "image/png", FALSE ); if (!g_fileAtom) g_fileAtom = gdk_atom_intern( "text/uri-list", FALSE ); + if (!g_htmlAtom) + g_htmlAtom = gdk_atom_intern( "text/html", FALSE ); } //------------------------------------------------------------------------- @@ -211,13 +217,17 @@ bool wxDataObject::IsSupportedFormat(const wxDataFormat& format, Direction dir) // wxTextDataObject // ---------------------------------------------------------------------------- -#if defined(__WXGTK20__) && wxUSE_UNICODE -void wxTextDataObject::GetAllFormats(wxDataFormat *formats, wxDataObjectBase::Direction dir) const +#if wxUSE_UNICODE + +void +wxTextDataObject::GetAllFormats(wxDataFormat *formats, + wxDataObjectBase::Direction WXUNUSED(dir)) const { *formats++ = GetPreferredFormat(); *formats = g_altTextAtom; } -#endif + +#endif // wxUSE_UNICODE // ---------------------------------------------------------------------------- // wxFileDataObject @@ -255,55 +265,56 @@ size_t wxFileDataObject::GetDataSize() const bool wxFileDataObject::SetData(size_t WXUNUSED(size), const void *buf) { + // we get data in the text/uri-list format, i.e. as a sequence of URIs + // (filenames prefixed by "file:") delimited by "\r\n". size includes + // the trailing zero (in theory, not for Nautilus in early GNOME + // versions). + m_filenames.Empty(); - // we get data in the text/uri-list format, i.e. as a sequence of URIs - // (filenames prefixed by "file:") delimited by "\r\n" - wxString filename; - for ( const char *p = (const char *)buf; ; p++ ) + const gchar *nexttemp = (const gchar*) buf; + for ( ; ; ) { - // 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 ) + int len = 0; + const gchar *temp = nexttemp; + for (;;) { - size_t lenPrefix = 5; // strlen("file:") - if ( filename.Left(lenPrefix).MakeLower() == _T("file:") ) + if (temp[len] == 0) { - // sometimes the syntax is "file:filename", sometimes it's - // URL-like: "file://filename" - deal with both - if ( filename[lenPrefix] == _T('/') && - filename[lenPrefix + 1] == _T('/') ) + if (len > 0) { - // skip the slashes - lenPrefix += 2; + // if an app omits '\r''\n' + nexttemp = temp+len; + break; } - - // It would probably be nicer to use a GTK or Glib - // function to unescape the 8-bit strings pointed to - // by buf, but this does the same in wx code. - wxString filename_unicode = wxURI::Unescape(filename.c_str() + lenPrefix); - wxCharBuffer filename_8bit = wxConvISO8859_1.cWX2MB( filename_unicode ); - filename_unicode = wxConvFileName->cMB2WX( filename_8bit ); - AddFile( filename_unicode ); - filename.Empty(); + + return true; } - else if ( !filename.empty() ) + if (temp[len] == '\r') { - wxLogDebug(_T("Unsupported URI \"%s\" in wxFileDataObject"), - filename.c_str()); + if (temp[len+1] == '\n') + nexttemp = temp+len+2; + else + nexttemp = temp+len+1; + break; } + len++; + } - if ( !*p ) - break; + if (len == 0) + break; - // skip '\r' - p++; - } - else + // required to give it a trailing zero + gchar *uri = g_strndup( temp, len ); + + gchar *fn = g_filename_from_uri( uri, NULL, NULL ); + + g_free( uri ); + + if (fn) { - // The string is in ISO-8859-1 according to XDND spec - filename += *p; + AddFile( wxConvFileName->cMB2WX( fn ) ); + g_free( fn ); } } @@ -381,12 +392,12 @@ bool wxBitmapDataObject::SetData(size_t size, const void *buf) m_bitmap = wxBitmap(image); - return m_bitmap.Ok(); + return m_bitmap.IsOk(); } void wxBitmapDataObject::DoConvertToPng() { - if ( !m_bitmap.Ok() ) + if ( !m_bitmap.IsOk() ) return; wxCHECK_RET( wxImage::FindHandler(wxBITMAP_TYPE_PNG) != NULL, @@ -404,4 +415,105 @@ void wxBitmapDataObject::DoConvertToPng() image.SaveFile(mstream, wxBITMAP_TYPE_PNG); } +// ---------------------------------------------------------------------------- +// wxURLDataObject +// ---------------------------------------------------------------------------- + +class wxTextURIListDataObject : public wxDataObjectSimple +{ +public: + wxTextURIListDataObject(const wxString& url) + : wxDataObjectSimple(wxDataFormat(g_fileAtom)), + m_url(url) + { + } + + const wxString& GetURL() const { return m_url; } + void SetURL(const wxString& url) { m_url = url; } + + + virtual size_t GetDataSize() const + { + // It is not totally clear whether we should include "\r\n" at the end + // of the string if there is only one URL or not, but not doing it + // doesn't seem to create any problems, so keep things simple. + return strlen(m_url.utf8_str()) + 1; + } + + virtual bool GetDataHere(void *buf) const + { + char* const dst = static_cast(buf); + + strcpy(dst, m_url.utf8_str()); + + return true; + } + + virtual bool SetData(size_t len, const void *buf) + { + const char* const src = static_cast(buf); + + // The string might be "\r\n"-terminated but this is not necessarily + // the case (e.g. when dragging an URL from Firefox, it isn't). + if ( len > 1 && src[len - 1] == '\n' ) + { + if ( len > 2 && src[len - 2] == '\r' ) + len--; + + len--; + } + + m_url = wxString::FromUTF8(src, len); + + return true; + } + + // Must provide overloads to avoid hiding them (and warnings about it) + virtual size_t GetDataSize(const wxDataFormat&) const + { + return GetDataSize(); + } + virtual bool GetDataHere(const wxDataFormat&, void *buf) const + { + return GetDataHere(buf); + } + virtual bool SetData(const wxDataFormat&, size_t len, const void *buf) + { + return SetData(len, buf); + } + +private: + wxString m_url; +}; + +wxURLDataObject::wxURLDataObject(const wxString& url) : + m_dobjURIList(new wxTextURIListDataObject(url)), + m_dobjText(new wxTextDataObject(url)) +{ + // Use both URL-specific format and a plain text one to ensure that URLs + // can be pasted into any application. + Add(m_dobjURIList, true /* preferred */); + Add(m_dobjText); +} + +void wxURLDataObject::SetURL(const wxString& url) +{ + m_dobjURIList->SetURL(url); + m_dobjText->SetText(url); +} + +wxString wxURLDataObject::GetURL() const +{ + if ( GetReceivedFormat() == g_fileAtom ) + { + // If we received the URL as an URI, use it. + return m_dobjURIList->GetURL(); + } + else // Otherwise we either got it as text or didn't get anything yet. + { + // In either case using the text format should be fine. + return m_dobjText->GetText(); + } +} + #endif // wxUSE_DATAOBJ