1 /////////////////////////////////////////////////////////////////////////////// 
   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" 
  13 #include "wx/dataobj.h" 
  19 #include "wx/mstream.h" 
  26 //------------------------------------------------------------------------- 
  28 //------------------------------------------------------------------------- 
  30 GdkAtom  g_textAtom        
= 0; 
  31 GdkAtom  g_altTextAtom     
= 0; 
  32 GdkAtom  g_pngAtom         
= 0; 
  33 GdkAtom  g_fileAtom        
= 0; 
  35 //------------------------------------------------------------------------- 
  37 //------------------------------------------------------------------------- 
  39 wxDataFormat::wxDataFormat() 
  41     // do *not* call PrepareFormats() from here for 2 reasons: 
  43     // 1. we will have time to do it later because some other Set function 
  44     //    must be called before we really need them 
  46     // 2. doing so prevents us from declaring global wxDataFormats because 
  47     //    calling PrepareFormats (and thus gdk_atom_intern) before GDK is 
  48     //    initialised will result in a crash 
  49     m_type 
= wxDF_INVALID
; 
  50     m_format 
= (GdkAtom
) 0; 
  53 wxDataFormat::wxDataFormat( wxDataFormatId type 
) 
  59 wxDataFormat::wxDataFormat( const wxChar 
*id 
) 
  65 wxDataFormat::wxDataFormat( const wxString 
&id 
) 
  71 wxDataFormat::wxDataFormat( NativeFormat format 
) 
  77 void wxDataFormat::SetType( wxDataFormatId type 
) 
  84     if (m_type 
== wxDF_UNICODETEXT
) 
  85         m_format 
= g_textAtom
; 
  86     else if (m_type 
== wxDF_TEXT
) 
  87         m_format 
= g_altTextAtom
; 
  89     if (m_type 
== wxDF_TEXT 
|| m_type 
== wxDF_UNICODETEXT
) 
  90         m_format 
= g_textAtom
; 
  93     if (m_type 
== wxDF_BITMAP
) 
  96     if (m_type 
== wxDF_FILENAME
) 
  97         m_format 
= g_fileAtom
; 
 100        wxFAIL_MSG( wxT("invalid dataformat") ); 
 104 wxDataFormatId 
wxDataFormat::GetType() const 
 109 wxString 
wxDataFormat::GetId() const 
 111     gchar
* atom_name 
= gdk_atom_name( m_format 
); 
 112     wxString ret 
= wxString::FromAscii( atom_name 
); 
 117 void wxDataFormat::SetId( NativeFormat format 
) 
 122     if (m_format 
== g_textAtom
) 
 124         m_type 
= wxDF_UNICODETEXT
; 
 129     if (m_format 
== g_altTextAtom
) 
 132     if (m_format 
== g_pngAtom
) 
 133         m_type 
= wxDF_BITMAP
; 
 135     if (m_format 
== g_fileAtom
) 
 136         m_type 
= wxDF_FILENAME
; 
 138         m_type 
= wxDF_PRIVATE
; 
 141 void wxDataFormat::SetId( const wxChar 
*id 
) 
 144     m_type 
= wxDF_PRIVATE
; 
 146     m_format 
= gdk_atom_intern( (const char*) tmp
.ToAscii(), FALSE 
); 
 149 void wxDataFormat::PrepareFormats() 
 151     // VZ: GNOME included in RedHat 6.1 uses the MIME types below and not the 
 152     //     atoms STRING and file:ALL as the old code was, but normal X apps 
 153     //     use STRING for text selection when transfering the data via 
 154     //     clipboard, for example, so do use STRING for now (GNOME apps will 
 155     //     probably support STRING as well for compatibility anyhow), but use 
 156     //     text/uri-list for file dnd because compatibility is not important 
 160         g_textAtom 
= gdk_atom_intern( "UTF8_STRING", FALSE 
); 
 161         g_altTextAtom 
= gdk_atom_intern( "STRING", FALSE 
); 
 163         g_textAtom 
= gdk_atom_intern( "STRING" /* "text/plain" */, FALSE 
); 
 166         g_pngAtom 
= gdk_atom_intern( "image/png", FALSE 
); 
 168         g_fileAtom 
= gdk_atom_intern( "text/uri-list", FALSE 
); 
 171 //------------------------------------------------------------------------- 
 173 //------------------------------------------------------------------------- 
 175 wxDataObject::wxDataObject() 
 179 wxDataObject::~wxDataObject() 
 181     // dtor is empty but needed for Darwin and AIX -- otherwise it doesn't link 
 184 bool wxDataObject::IsSupportedFormat(const wxDataFormat
& format
, Direction dir
) const 
 186     size_t nFormatCount 
= GetFormatCount(dir
); 
 187     if ( nFormatCount 
== 1 ) 
 189         return format 
== GetPreferredFormat(); 
 193         wxDataFormat 
*formats 
= new wxDataFormat
[nFormatCount
]; 
 194         GetAllFormats(formats
,dir
); 
 197         for ( n 
= 0; n 
< nFormatCount
; n
++ ) 
 199             if ( formats
[n
] == format 
) 
 206         return n 
< nFormatCount
; 
 210 // ---------------------------------------------------------------------------- 
 212 // ---------------------------------------------------------------------------- 
 214 #if defined(__WXGTK20__) && wxUSE_UNICODE 
 215 void wxTextDataObject::GetAllFormats(wxDataFormat 
*formats
, wxDataObjectBase::Direction dir
) const 
 217     *formats
++ = GetPreferredFormat(); 
 218     *formats 
= g_altTextAtom
; 
 222 // ---------------------------------------------------------------------------- 
 224 // ---------------------------------------------------------------------------- 
 226 bool wxFileDataObject::GetDataHere(void *buf
) const 
 230     for (size_t i 
= 0; i 
< m_filenames
.GetCount(); i
++) 
 232         filenames 
+= wxT("file:"); 
 233         filenames 
+= m_filenames
[i
]; 
 234         filenames 
+= wxT("\r\n"); 
 237     memcpy( buf
, filenames
.mbc_str(), filenames
.Len() + 1 ); 
 242 size_t wxFileDataObject::GetDataSize() const 
 246     for (size_t i 
= 0; i 
< m_filenames
.GetCount(); i
++) 
 248         // This is junk in UTF-8 
 249         res 
+= m_filenames
[i
].Len(); 
 250         res 
+= 5 + 2; // "file:" (5) + "\r\n" (2) 
 256 bool wxFileDataObject::SetData(size_t WXUNUSED(size
), const void *buf
) 
 260     // we get data in the text/uri-list format, i.e. as a sequence of URIs 
 261     // (filenames prefixed by "file:") delimited by "\r\n" 
 263     for ( const char *p 
= (const char *)buf
; ; p
++ ) 
 265         // some broken programs (testdnd GTK+ sample!) omit the trailing 
 266         // "\r\n", so check for '\0' explicitly here instead of doing it in 
 267         // the loop statement to account for it 
 268         if ( (*p 
== '\r' && *(p
+1) == '\n') || !*p 
) 
 270             size_t lenPrefix 
= 5; // strlen("file:") 
 271             if ( filename
.Left(lenPrefix
).MakeLower() == _T("file:") ) 
 273                 // sometimes the syntax is "file:filename", sometimes it's 
 274                 // URL-like: "file://filename" - deal with both 
 275                 if ( filename
[lenPrefix
] == _T('/') && 
 276                      filename
[lenPrefix 
+ 1] == _T('/') ) 
 282                 AddFile(wxURI::Unescape(filename
.c_str() + lenPrefix
)); 
 285             else if ( !filename
.empty() ) 
 287                 wxLogDebug(_T("Unsupported URI \"%s\" in wxFileDataObject"), 
 306 void wxFileDataObject::AddFile( const wxString 
&filename 
) 
 308    m_filenames
.Add( filename 
); 
 311 // ---------------------------------------------------------------------------- 
 312 // wxBitmapDataObject 
 313 // ---------------------------------------------------------------------------- 
 315 wxBitmapDataObject::wxBitmapDataObject() 
 320 wxBitmapDataObject::wxBitmapDataObject( const wxBitmap
& bitmap 
) 
 321                   : wxBitmapDataObjectBase(bitmap
) 
 328 wxBitmapDataObject::~wxBitmapDataObject() 
 333 void wxBitmapDataObject::SetBitmap( const wxBitmap 
&bitmap 
) 
 337     wxBitmapDataObjectBase::SetBitmap(bitmap
); 
 342 bool wxBitmapDataObject::GetDataHere(void *buf
) const 
 346         wxFAIL_MSG( wxT("attempt to copy empty bitmap failed") ); 
 351     memcpy(buf
, m_pngData
, m_pngSize
); 
 356 bool wxBitmapDataObject::SetData(size_t size
, const void *buf
) 
 360     wxCHECK_MSG( wxImage::FindHandler(wxBITMAP_TYPE_PNG
) != NULL
, 
 361                  FALSE
, wxT("You must call wxImage::AddHandler(new wxPNGHandler); to be able to use clipboard with bitmaps!") ); 
 364     m_pngData 
= malloc(m_pngSize
); 
 366     memcpy(m_pngData
, buf
, m_pngSize
); 
 368     wxMemoryInputStream 
mstream((char*) m_pngData
, m_pngSize
); 
 370     if ( !image
.LoadFile( mstream
, wxBITMAP_TYPE_PNG 
) ) 
 375     m_bitmap 
= wxBitmap(image
); 
 377     return m_bitmap
.Ok(); 
 380 void wxBitmapDataObject::DoConvertToPng() 
 382     if ( !m_bitmap
.Ok() ) 
 385     wxCHECK_RET( wxImage::FindHandler(wxBITMAP_TYPE_PNG
) != NULL
, 
 386                  wxT("You must call wxImage::AddHandler(new wxPNGHandler); to be able to use clipboard with bitmaps!") ); 
 388     wxImage image 
= m_bitmap
.ConvertToImage(); 
 390     wxCountingOutputStream count
; 
 391     image
.SaveFile(count
, wxBITMAP_TYPE_PNG
); 
 393     m_pngSize 
= count
.GetSize() + 100; // sometimes the size seems to vary ??? 
 394     m_pngData 
= malloc(m_pngSize
); 
 396     wxMemoryOutputStream 
mstream((char*) m_pngData
, m_pngSize
); 
 397     image
.SaveFile(mstream
, wxBITMAP_TYPE_PNG
); 
 400 #endif // wxUSE_DATAOBJ