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