]> git.saurik.com Git - wxWidgets.git/blame - src/gtk/dataobj.cpp
not necessary anymore
[wxWidgets.git] / src / gtk / dataobj.cpp
CommitLineData
8b53e5a2
RR
1///////////////////////////////////////////////////////////////////////////////
2// Name: dataobj.cpp
3// Purpose: wxDataObject class
4// Author: Robert Roebling
5// Id: $Id$
6// Copyright: (c) 1998 Robert Roebling
3f480da3 7// Licence: wxWindows licence
8b53e5a2
RR
8///////////////////////////////////////////////////////////////////////////////
9
10#ifdef __GNUG__
3f480da3 11 #pragma implementation "dataobj.h"
8b53e5a2
RR
12#endif
13
14#include "wx/dataobj.h"
ab8884ac 15#include "wx/app.h"
0d2a2b60 16#include "wx/debug.h"
e2acb9ae
RR
17#include "wx/mstream.h"
18#include "wx/image.h"
0d2a2b60 19
071a2d78 20#include <gdk/gdk.h>
0d2a2b60 21
d6086ea6
RR
22//-------------------------------------------------------------------------
23// global data
24//-------------------------------------------------------------------------
25
26GdkAtom g_textAtom = 0;
e2acb9ae 27GdkAtom g_pngAtom = 0;
1dd989e1 28GdkAtom g_fileAtom = 0;
d6086ea6 29
0d2a2b60
RR
30//-------------------------------------------------------------------------
31// wxDataFormat
32//-------------------------------------------------------------------------
33
cd5bf2a6 34wxDataFormat::wxDataFormat()
0d2a2b60 35{
4b3d29db
VZ
36 // do *not* call PrepareFormats() from here for 2 reasons:
37 //
38 // 1. we will have time to do it later because some other Set function
39 // must be called before we really need them
40 //
41 // 2. doing so prevents us from declaring global wxDataFormats because
42 // calling PrepareFormats (and thus gdk_atom_intern) before GDK is
43 // initialised will result in a crash
cd5bf2a6 44 m_type = wxDF_INVALID;
1dd989e1 45 m_format = (GdkAtom) 0;
cd5bf2a6
RR
46}
47
3f480da3 48wxDataFormat::wxDataFormat( wxDataFormatId type )
cd5bf2a6 49{
e2acb9ae 50 PrepareFormats();
cd5bf2a6 51 SetType( type );
0d2a2b60
RR
52}
53
b5be07d4 54wxDataFormat::wxDataFormat( const wxChar *id )
8a126fcc 55{
e2acb9ae 56 PrepareFormats();
8a126fcc
RR
57 SetId( id );
58}
59
0d2a2b60
RR
60wxDataFormat::wxDataFormat( const wxString &id )
61{
e2acb9ae 62 PrepareFormats();
cd5bf2a6 63 SetId( id );
0d2a2b60
RR
64}
65
1dd989e1 66wxDataFormat::wxDataFormat( NativeFormat format )
0d2a2b60 67{
e2acb9ae 68 PrepareFormats();
1dd989e1 69 SetId( format );
0d2a2b60
RR
70}
71
3f480da3 72void wxDataFormat::SetType( wxDataFormatId type )
cd5bf2a6 73{
4b3d29db 74 PrepareFormats();
ca11abde
RR
75
76 if (type == wxDF_UNICODETEXT)
77 type = wxDF_TEXT;
3f480da3 78
ca11abde
RR
79 m_type = type;
80
cd5bf2a6 81 if (m_type == wxDF_TEXT)
1dd989e1 82 m_format = g_textAtom;
cd5bf2a6
RR
83 else
84 if (m_type == wxDF_BITMAP)
1dd989e1 85 m_format = g_pngAtom;
cd5bf2a6
RR
86 else
87 if (m_type == wxDF_FILENAME)
1dd989e1 88 m_format = g_fileAtom;
cd5bf2a6
RR
89 else
90 {
223d09f6 91 wxFAIL_MSG( wxT("invalid dataformat") );
cd5bf2a6 92 }
cd5bf2a6 93}
3f480da3
VZ
94
95wxDataFormatId wxDataFormat::GetType() const
0d2a2b60
RR
96{
97 return m_type;
98}
99
100wxString wxDataFormat::GetId() const
101{
2e1d7104 102 wxString ret = wxString::FromAscii( gdk_atom_name( m_format ) );
1dd989e1 103 return ret;
0d2a2b60 104}
3f480da3 105
1dd989e1 106void wxDataFormat::SetId( NativeFormat format )
3f480da3 107{
4b3d29db 108 PrepareFormats();
1dd989e1 109 m_format = format;
3f480da3 110
1dd989e1
RR
111 if (m_format == g_textAtom)
112 m_type = wxDF_TEXT;
113 else
114 if (m_format == g_pngAtom)
115 m_type = wxDF_BITMAP;
116 else
117 if (m_format == g_fileAtom)
118 m_type = wxDF_FILENAME;
119 else
120 m_type = wxDF_PRIVATE;
0d2a2b60 121}
3f480da3 122
1dd989e1 123void wxDataFormat::SetId( const wxChar *id )
0d2a2b60 124{
4b3d29db 125 PrepareFormats();
1dd989e1
RR
126 m_type = wxDF_PRIVATE;
127 wxString tmp( id );
2e1d7104 128 m_format = gdk_atom_intern( (const char*) tmp.ToAscii(), FALSE );
0d2a2b60 129}
3f480da3 130
1dd989e1 131void wxDataFormat::PrepareFormats()
0d2a2b60 132{
810b5e1f 133 // VZ: GNOME included in RedHat 6.1 uses the MIME types below and not the
74d38ad8
VZ
134 // atoms STRING and file:ALL as the old code was, but normal X apps
135 // use STRING for text selection when transfering the data via
136 // clipboard, for example, so do use STRING for now (GNOME apps will
137 // probably support STRING as well for compatibility anyhow), but use
138 // text/uri-list for file dnd because compatibility is not important
139 // here (with whom?)
e1ee679c 140 if (!g_textAtom)
2e1d7104 141#if wxUSE_UNICODE
ca11abde 142 g_textAtom = gdk_atom_intern( "UTF8_STRING", FALSE );
2e1d7104 143#else
74d38ad8 144 g_textAtom = gdk_atom_intern( "STRING" /* "text/plain" */, FALSE );
2e1d7104 145#endif
e1ee679c 146 if (!g_pngAtom)
1dd989e1 147 g_pngAtom = gdk_atom_intern( "image/png", FALSE );
e1ee679c 148 if (!g_fileAtom)
810b5e1f 149 g_fileAtom = gdk_atom_intern( "text/uri-list", FALSE );
0d2a2b60 150}
8b53e5a2
RR
151
152//-------------------------------------------------------------------------
153// wxDataObject
154//-------------------------------------------------------------------------
155
0d2a2b60
RR
156wxDataObject::wxDataObject()
157{
0d2a2b60 158}
3f480da3 159
b068c4e8 160bool wxDataObject::IsSupportedFormat(const wxDataFormat& format, Direction dir) const
0d2a2b60 161{
b068c4e8 162 size_t nFormatCount = GetFormatCount(dir);
f2593d0d
RR
163 if ( nFormatCount == 1 )
164 {
1dd989e1
RR
165 return format == GetPreferredFormat();
166 }
f2593d0d
RR
167 else
168 {
1dd989e1 169 wxDataFormat *formats = new wxDataFormat[nFormatCount];
b068c4e8 170 GetAllFormats(formats,dir);
1dd989e1
RR
171
172 size_t n;
f2593d0d
RR
173 for ( n = 0; n < nFormatCount; n++ )
174 {
1dd989e1
RR
175 if ( formats[n] == format )
176 break;
177 }
0d2a2b60 178
1dd989e1 179 delete [] formats;
cd5bf2a6 180
1dd989e1
RR
181 // found?
182 return n < nFormatCount;
183 }
0d2a2b60
RR
184}
185
8b53e5a2
RR
186// ----------------------------------------------------------------------------
187// wxFileDataObject
188// ----------------------------------------------------------------------------
189
e1ee679c 190bool wxFileDataObject::GetDataHere(void *buf) const
0d2a2b60 191{
b068c4e8 192 wxString filenames;
4b3d29db 193
b068c4e8
RR
194 for (size_t i = 0; i < m_filenames.GetCount(); i++)
195 {
196 filenames += m_filenames[i];
4b3d29db 197 filenames += (wxChar) 0;
b068c4e8 198 }
4b3d29db 199
e1ee679c 200 memcpy( buf, filenames.mbc_str(), filenames.Len() + 1 );
0d2a2b60 201
e1ee679c 202 return TRUE;
0d2a2b60 203}
3f480da3 204
e1ee679c 205size_t wxFileDataObject::GetDataSize() const
0d2a2b60 206{
b068c4e8 207 size_t res = 0;
4b3d29db 208
b068c4e8
RR
209 for (size_t i = 0; i < m_filenames.GetCount(); i++)
210 {
211 res += m_filenames[i].Len();
4b3d29db 212 res += 1;
b068c4e8 213 }
4b3d29db 214
b068c4e8 215 return res + 1;
0d2a2b60 216}
3f480da3 217
7941ba11 218bool wxFileDataObject::SetData(size_t WXUNUSED(size), const void *buf)
0d2a2b60 219{
810b5e1f
VZ
220 // VZ: old format
221#if 0
2d68e1b4 222 // filenames are stores as a string with #0 as deliminators
2d68e1b4
RR
223 const char *filenames = (const char*) buf;
224 size_t pos = 0;
225 for(;;)
226 {
227 if (filenames[0] == 0)
810b5e1f
VZ
228 break;
229 if (pos >= size)
230 break;
2d68e1b4
RR
231 wxString file( filenames ); // this returns the first file
232 AddFile( file );
810b5e1f
VZ
233 pos += file.Len()+1;
234 filenames += file.Len()+1;
235 }
236#else // 1
237 m_filenames.Empty();
238
239 // the text/uri-list format is a sequence of URIs (filenames prefixed by
240 // "file:" as far as I see) delimited by "\r\n" of total length size
241 // (I wonder what happens if the file has '\n' in its filename??)
242 wxString filename;
74d38ad8 243 for ( const char *p = (const char *)buf; ; p++ )
810b5e1f 244 {
74d38ad8
VZ
245 // some broken programs (testdnd GTK+ sample!) omit the trailing
246 // "\r\n", so check for '\0' explicitly here instead of doing it in
247 // the loop statement to account for it
248 if ( (*p == '\r' && *(p+1) == '\n') || !*p )
810b5e1f 249 {
74d38ad8 250 size_t lenPrefix = 5; // strlen("file:")
810b5e1f
VZ
251 if ( filename.Left(lenPrefix).MakeLower() == _T("file:") )
252 {
74d38ad8
VZ
253 // sometimes the syntax is "file:filename", sometimes it's
254 // URL-like: "file://filename" - deal with both
255 if ( filename[lenPrefix] == _T('/') &&
256 filename[lenPrefix + 1] == _T('/') )
257 {
258 // skip the slashes
259 lenPrefix += 2;
260 }
261
262 AddFile(filename.c_str() + lenPrefix);
263 filename.Empty();
264 }
265 else
266 {
267 wxLogDebug(_T("Unsupported URI '%s' in wxFileDataObject"),
268 filename.c_str());
810b5e1f
VZ
269 }
270
74d38ad8
VZ
271 if ( !*p )
272 break;
810b5e1f
VZ
273
274 // skip '\r'
275 p++;
276 }
277 else
278 {
279 filename += *p;
280 }
2d68e1b4 281 }
810b5e1f 282#endif // 0/1
3f480da3 283
1dd989e1
RR
284 return TRUE;
285}
286
b068c4e8
RR
287void wxFileDataObject::AddFile( const wxString &filename )
288{
289 m_filenames.Add( filename );
290}
291
8b53e5a2
RR
292// ----------------------------------------------------------------------------
293// wxBitmapDataObject
294// ----------------------------------------------------------------------------
295
0d2a2b60
RR
296wxBitmapDataObject::wxBitmapDataObject()
297{
e1ee679c 298 Init();
0d2a2b60
RR
299}
300
301wxBitmapDataObject::wxBitmapDataObject( const wxBitmap& bitmap )
e1ee679c 302 : wxBitmapDataObjectBase(bitmap)
0d2a2b60 303{
e1ee679c
VZ
304 Init();
305
e2acb9ae
RR
306 DoConvertToPng();
307}
308
309wxBitmapDataObject::~wxBitmapDataObject()
310{
e1ee679c 311 Clear();
0d2a2b60
RR
312}
313
314void wxBitmapDataObject::SetBitmap( const wxBitmap &bitmap )
315{
e1ee679c 316 ClearAll();
0d2a2b60 317
e1ee679c
VZ
318 wxBitmapDataObjectBase::SetBitmap(bitmap);
319
320 DoConvertToPng();
0d2a2b60
RR
321}
322
e1ee679c 323bool wxBitmapDataObject::GetDataHere(void *buf) const
0d2a2b60 324{
e1ee679c 325 if ( !m_pngSize )
1dd989e1 326 {
e1ee679c
VZ
327 wxFAIL_MSG( wxT("attempt to copy empty bitmap failed") );
328
329 return FALSE;
1dd989e1 330 }
0d2a2b60 331
e1ee679c
VZ
332 memcpy(buf, m_pngData, m_pngSize);
333
334 return TRUE;
e2acb9ae
RR
335}
336
e1ee679c 337bool wxBitmapDataObject::SetData(size_t size, const void *buf)
e2acb9ae 338{
e1ee679c
VZ
339 Clear();
340
bd3b7e09
VS
341 wxCHECK_MSG( wxImage::FindHandler(wxBITMAP_TYPE_PNG) != NULL,
342 FALSE, wxT("You must call wxImage::AddHandler(new wxPNGHandler); to be able to use clipboard with bitmaps!") );
343
1dd989e1 344 m_pngSize = size;
e1ee679c
VZ
345 m_pngData = malloc(m_pngSize);
346
bd3b7e09 347 memcpy(m_pngData, buf, m_pngSize);
e1ee679c 348
bd3b7e09 349 wxMemoryInputStream mstream((char*) m_pngData, m_pngSize);
e2acb9ae 350 wxImage image;
bd3b7e09 351 if ( !image.LoadFile( mstream, wxBITMAP_TYPE_PNG ) )
e1ee679c
VZ
352 {
353 return FALSE;
354 }
355
bd3b7e09 356 m_bitmap = wxBitmap(image);
4b3d29db 357
b068c4e8 358 return m_bitmap.Ok();
e2acb9ae
RR
359}
360
361void wxBitmapDataObject::DoConvertToPng()
362{
bd3b7e09 363 if ( !m_bitmap.Ok() )
e1ee679c
VZ
364 return;
365
bd3b7e09
VS
366 wxCHECK_RET( wxImage::FindHandler(wxBITMAP_TYPE_PNG) != NULL,
367 wxT("You must call wxImage::AddHandler(new wxPNGHandler); to be able to use clipboard with bitmaps!") );
368
368d59f0 369 wxImage image = m_bitmap.ConvertToImage();
e1ee679c 370
e2acb9ae 371 wxCountingOutputStream count;
bd3b7e09 372 image.SaveFile(count, wxBITMAP_TYPE_PNG);
e1ee679c 373
e2acb9ae 374 m_pngSize = count.GetSize() + 100; // sometimes the size seems to vary ???
e1ee679c
VZ
375 m_pngData = malloc(m_pngSize);
376
bd3b7e09
VS
377 wxMemoryOutputStream mstream((char*) m_pngData, m_pngSize);
378 image.SaveFile(mstream, wxBITMAP_TYPE_PNG);
0d2a2b60 379}
3f480da3 380
0d2a2b60 381