1 /////////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/gtk/dataobj.cpp 
   3 // Purpose:     wxDataObject class 
   4 // Author:      Robert Roebling 
   6 // Copyright:   (c) 1998 Robert Roebling 
   7 // Licence:     wxWindows licence 
   8 /////////////////////////////////////////////////////////////////////////////// 
  10 // For compilers that support precompilation, includes "wx.h". 
  11 #include "wx/wxprec.h" 
  15 #include "wx/dataobj.h" 
  23 #include "wx/mstream.h" 
  28 //------------------------------------------------------------------------- 
  30 //------------------------------------------------------------------------- 
  32 GdkAtom  g_textAtom        
= 0; 
  33 GdkAtom  g_altTextAtom     
= 0; 
  34 GdkAtom  g_pngAtom         
= 0; 
  35 GdkAtom  g_fileAtom        
= 0; 
  37 //------------------------------------------------------------------------- 
  39 //------------------------------------------------------------------------- 
  41 wxDataFormat::wxDataFormat() 
  43     // do *not* call PrepareFormats() from here for 2 reasons: 
  45     // 1. we will have time to do it later because some other Set function 
  46     //    must be called before we really need them 
  48     // 2. doing so prevents us from declaring global wxDataFormats because 
  49     //    calling PrepareFormats (and thus gdk_atom_intern) before GDK is 
  50     //    initialised will result in a crash 
  51     m_type 
= wxDF_INVALID
; 
  52     m_format 
= (GdkAtom
) 0; 
  55 wxDataFormat::wxDataFormat( wxDataFormatId type 
) 
  61 wxDataFormat::wxDataFormat( const wxChar 
*id 
) 
  67 wxDataFormat::wxDataFormat( const wxString 
&id 
) 
  73 wxDataFormat::wxDataFormat( NativeFormat format 
) 
  79 void wxDataFormat::SetType( wxDataFormatId type 
) 
  86     if (m_type 
== wxDF_UNICODETEXT
) 
  87         m_format 
= g_textAtom
; 
  88     else if (m_type 
== wxDF_TEXT
) 
  89         m_format 
= g_altTextAtom
; 
  91     if (m_type 
== wxDF_TEXT 
|| m_type 
== wxDF_UNICODETEXT
) 
  92         m_format 
= g_textAtom
; 
  95     if (m_type 
== wxDF_BITMAP
) 
  98     if (m_type 
== wxDF_FILENAME
) 
  99         m_format 
= g_fileAtom
; 
 102        wxFAIL_MSG( wxT("invalid dataformat") ); 
 106 wxDataFormatId 
wxDataFormat::GetType() const 
 111 wxString 
wxDataFormat::GetId() const 
 113     gchar
* atom_name 
= gdk_atom_name( m_format 
); 
 114     wxString ret 
= wxString::FromAscii( atom_name 
); 
 119 void wxDataFormat::SetId( NativeFormat format 
) 
 124     if (m_format 
== g_textAtom
) 
 126         m_type 
= wxDF_UNICODETEXT
; 
 131     if (m_format 
== g_altTextAtom
) 
 134     if (m_format 
== g_pngAtom
) 
 135         m_type 
= wxDF_BITMAP
; 
 137     if (m_format 
== g_fileAtom
) 
 138         m_type 
= wxDF_FILENAME
; 
 140         m_type 
= wxDF_PRIVATE
; 
 143 void wxDataFormat::SetId( const wxChar 
*id 
) 
 146     m_type 
= wxDF_PRIVATE
; 
 148     m_format 
= gdk_atom_intern( (const char*) tmp
.ToAscii(), FALSE 
); 
 151 void wxDataFormat::PrepareFormats() 
 153     // VZ: GNOME included in RedHat 6.1 uses the MIME types below and not the 
 154     //     atoms STRING and file:ALL as the old code was, but normal X apps 
 155     //     use STRING for text selection when transfering the data via 
 156     //     clipboard, for example, so do use STRING for now (GNOME apps will 
 157     //     probably support STRING as well for compatibility anyhow), but use 
 158     //     text/uri-list for file dnd because compatibility is not important 
 162         g_textAtom 
= gdk_atom_intern( "UTF8_STRING", FALSE 
); 
 163         g_altTextAtom 
= gdk_atom_intern( "STRING", FALSE 
); 
 165         g_textAtom 
= gdk_atom_intern( "STRING" /* "text/plain" */, FALSE 
); 
 168         g_pngAtom 
= gdk_atom_intern( "image/png", FALSE 
); 
 170         g_fileAtom 
= gdk_atom_intern( "text/uri-list", FALSE 
); 
 173 //------------------------------------------------------------------------- 
 175 //------------------------------------------------------------------------- 
 177 wxDataObject::wxDataObject() 
 181 wxDataObject::~wxDataObject() 
 183     // dtor is empty but needed for Darwin and AIX -- otherwise it doesn't link 
 186 bool wxDataObject::IsSupportedFormat(const wxDataFormat
& format
, Direction dir
) const 
 188     size_t nFormatCount 
= GetFormatCount(dir
); 
 189     if ( nFormatCount 
== 1 ) 
 191         return format 
== GetPreferredFormat(); 
 195         wxDataFormat 
*formats 
= new wxDataFormat
[nFormatCount
]; 
 196         GetAllFormats(formats
,dir
); 
 199         for ( n 
= 0; n 
< nFormatCount
; n
++ ) 
 201             if ( formats
[n
] == format 
) 
 208         return n 
< nFormatCount
; 
 212 // ---------------------------------------------------------------------------- 
 214 // ---------------------------------------------------------------------------- 
 216 #if defined(__WXGTK20__) && wxUSE_UNICODE 
 217 void wxTextDataObject::GetAllFormats(wxDataFormat 
*formats
, wxDataObjectBase::Direction dir
) const 
 219     *formats
++ = GetPreferredFormat(); 
 220     *formats 
= g_altTextAtom
; 
 224 // ---------------------------------------------------------------------------- 
 226 // ---------------------------------------------------------------------------- 
 228 bool wxFileDataObject::GetDataHere(void *buf
) const 
 232     for (size_t i 
= 0; i 
< m_filenames
.GetCount(); i
++) 
 234         filenames 
+= wxT("file:"); 
 235         filenames 
+= m_filenames
[i
]; 
 236         filenames 
+= wxT("\r\n"); 
 239     memcpy( buf
, filenames
.mbc_str(), filenames
.length() + 1 ); 
 244 size_t wxFileDataObject::GetDataSize() const 
 248     for (size_t i 
= 0; i 
< m_filenames
.GetCount(); i
++) 
 250         // This is junk in UTF-8 
 251         res 
+= m_filenames
[i
].length(); 
 252         res 
+= 5 + 2; // "file:" (5) + "\r\n" (2) 
 258 bool wxFileDataObject::SetData(size_t WXUNUSED(size
), const void *buf
) 
 262     // we get data in the text/uri-list format, i.e. as a sequence of URIs 
 263     // (filenames prefixed by "file:") delimited by "\r\n" 
 265     for ( const char *p 
= (const char *)buf
; ; p
++ ) 
 267         // some broken programs (testdnd GTK+ sample!) omit the trailing 
 268         // "\r\n", so check for '\0' explicitly here instead of doing it in 
 269         // the loop statement to account for it 
 270         if ( (*p 
== '\r' && *(p
+1) == '\n') || !*p 
) 
 272             size_t lenPrefix 
= 5; // strlen("file:") 
 273             if ( filename
.Left(lenPrefix
).MakeLower() == _T("file:") ) 
 275                 // sometimes the syntax is "file:filename", sometimes it's 
 276                 // URL-like: "file://filename" - deal with both 
 277                 if ( filename
[lenPrefix
] == _T('/') && 
 278                      filename
[lenPrefix 
+ 1] == _T('/') ) 
 284                 AddFile(wxURI::Unescape(filename
.c_str() + lenPrefix
)); 
 287             else if ( !filename
.empty() ) 
 289                 wxLogDebug(_T("Unsupported URI \"%s\" in wxFileDataObject"), 
 308 void wxFileDataObject::AddFile( const wxString 
&filename 
) 
 310    m_filenames
.Add( filename 
); 
 313 // ---------------------------------------------------------------------------- 
 314 // wxBitmapDataObject 
 315 // ---------------------------------------------------------------------------- 
 317 wxBitmapDataObject::wxBitmapDataObject() 
 322 wxBitmapDataObject::wxBitmapDataObject( const wxBitmap
& bitmap 
) 
 323                   : wxBitmapDataObjectBase(bitmap
) 
 330 wxBitmapDataObject::~wxBitmapDataObject() 
 335 void wxBitmapDataObject::SetBitmap( const wxBitmap 
&bitmap 
) 
 339     wxBitmapDataObjectBase::SetBitmap(bitmap
); 
 344 bool wxBitmapDataObject::GetDataHere(void *buf
) const 
 348         wxFAIL_MSG( wxT("attempt to copy empty bitmap failed") ); 
 353     memcpy(buf
, m_pngData
, m_pngSize
); 
 358 bool wxBitmapDataObject::SetData(size_t size
, const void *buf
) 
 362     wxCHECK_MSG( wxImage::FindHandler(wxBITMAP_TYPE_PNG
) != NULL
, 
 363                  false, wxT("You must call wxImage::AddHandler(new wxPNGHandler); to be able to use clipboard with bitmaps!") ); 
 366     m_pngData 
= malloc(m_pngSize
); 
 368     memcpy(m_pngData
, buf
, m_pngSize
); 
 370     wxMemoryInputStream 
mstream((char*) m_pngData
, m_pngSize
); 
 372     if ( !image
.LoadFile( mstream
, wxBITMAP_TYPE_PNG 
) ) 
 377     m_bitmap 
= wxBitmap(image
); 
 379     return m_bitmap
.Ok(); 
 382 void wxBitmapDataObject::DoConvertToPng() 
 384     if ( !m_bitmap
.Ok() ) 
 387     wxCHECK_RET( wxImage::FindHandler(wxBITMAP_TYPE_PNG
) != NULL
, 
 388                  wxT("You must call wxImage::AddHandler(new wxPNGHandler); to be able to use clipboard with bitmaps!") ); 
 390     wxImage image 
= m_bitmap
.ConvertToImage(); 
 392     wxCountingOutputStream count
; 
 393     image
.SaveFile(count
, wxBITMAP_TYPE_PNG
); 
 395     m_pngSize 
= count
.GetSize() + 100; // sometimes the size seems to vary ??? 
 396     m_pngData 
= malloc(m_pngSize
); 
 398     wxMemoryOutputStream 
mstream((char*) m_pngData
, m_pngSize
); 
 399     image
.SaveFile(mstream
, wxBITMAP_TYPE_PNG
); 
 402 #endif // wxUSE_DATAOBJ