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