1 /////////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/gtk1/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" 
  22 #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 bool wxFileDataObject::GetDataHere(void *buf
) const 
 220     for (size_t i 
= 0; i 
< m_filenames
.GetCount(); i
++) 
 222         filenames 
+= wxT("file:"); 
 223         filenames 
+= m_filenames
[i
]; 
 224         filenames 
+= wxT("\r\n"); 
 227     memcpy( buf
, filenames
.mbc_str(), filenames
.Len() + 1 ); 
 232 size_t wxFileDataObject::GetDataSize() const 
 236     for (size_t i 
= 0; i 
< m_filenames
.GetCount(); i
++) 
 238         // This is junk in UTF-8 
 239         res 
+= m_filenames
[i
].Len(); 
 240         res 
+= 5 + 2; // "file:" (5) + "\r\n" (2) 
 246 bool wxFileDataObject::SetData(size_t WXUNUSED(size
), const void *buf
) 
 250     // we get data in the text/uri-list format, i.e. as a sequence of URIs 
 251     // (filenames prefixed by "file:") delimited by "\r\n" 
 253     for ( const char *p 
= (const char *)buf
; ; p
++ ) 
 255         // some broken programs (testdnd GTK+ sample!) omit the trailing 
 256         // "\r\n", so check for '\0' explicitly here instead of doing it in 
 257         // the loop statement to account for it 
 258         if ( (*p 
== '\r' && *(p
+1) == '\n') || !*p 
) 
 260             size_t lenPrefix 
= 5; // strlen("file:") 
 261             if ( filename
.Left(lenPrefix
).MakeLower() == _T("file:") ) 
 263                 // sometimes the syntax is "file:filename", sometimes it's 
 264                 // URL-like: "file://filename" - deal with both 
 265                 if ( filename
[lenPrefix
] == _T('/') && 
 266                      filename
[lenPrefix 
+ 1] == _T('/') ) 
 272                 AddFile(wxURI::Unescape(filename
.c_str() + lenPrefix
)); 
 277                 wxLogDebug(_T("Unsupported URI '%s' in wxFileDataObject"), 
 296 void wxFileDataObject::AddFile( const wxString 
&filename 
) 
 298    m_filenames
.Add( filename 
); 
 301 // ---------------------------------------------------------------------------- 
 302 // wxBitmapDataObject 
 303 // ---------------------------------------------------------------------------- 
 305 wxBitmapDataObject::wxBitmapDataObject() 
 310 wxBitmapDataObject::wxBitmapDataObject( const wxBitmap
& bitmap 
) 
 311                   : wxBitmapDataObjectBase(bitmap
) 
 318 wxBitmapDataObject::~wxBitmapDataObject() 
 323 void wxBitmapDataObject::SetBitmap( const wxBitmap 
&bitmap 
) 
 327     wxBitmapDataObjectBase::SetBitmap(bitmap
); 
 332 bool wxBitmapDataObject::GetDataHere(void *buf
) const 
 336         wxFAIL_MSG( wxT("attempt to copy empty bitmap failed") ); 
 341     memcpy(buf
, m_pngData
, m_pngSize
); 
 346 bool wxBitmapDataObject::SetData(size_t size
, const void *buf
) 
 350     wxCHECK_MSG( wxImage::FindHandler(wxBITMAP_TYPE_PNG
) != NULL
, 
 351                  false, wxT("You must call wxImage::AddHandler(new wxPNGHandler); to be able to use clipboard with bitmaps!") ); 
 354     m_pngData 
= malloc(m_pngSize
); 
 356     memcpy(m_pngData
, buf
, m_pngSize
); 
 358     wxMemoryInputStream 
mstream((char*) m_pngData
, m_pngSize
); 
 360     if ( !image
.LoadFile( mstream
, wxBITMAP_TYPE_PNG 
) ) 
 365     m_bitmap 
= wxBitmap(image
); 
 367     return m_bitmap
.Ok(); 
 370 void wxBitmapDataObject::DoConvertToPng() 
 372     if ( !m_bitmap
.Ok() ) 
 375     wxCHECK_RET( wxImage::FindHandler(wxBITMAP_TYPE_PNG
) != NULL
, 
 376                  wxT("You must call wxImage::AddHandler(new wxPNGHandler); to be able to use clipboard with bitmaps!") ); 
 378     wxImage image 
= m_bitmap
.ConvertToImage(); 
 380     wxCountingOutputStream count
; 
 381     image
.SaveFile(count
, wxBITMAP_TYPE_PNG
); 
 383     m_pngSize 
= count
.GetSize() + 100; // sometimes the size seems to vary ??? 
 384     m_pngData 
= malloc(m_pngSize
); 
 386     wxMemoryOutputStream 
mstream((char*) m_pngData
, m_pngSize
); 
 387     image
.SaveFile(mstream
, wxBITMAP_TYPE_PNG
); 
 390 #endif // wxUSE_DATAOBJ