]> git.saurik.com Git - wxWidgets.git/blame - src/x11/dataobj.cpp
Bitmap updates
[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
7// Licence: wxWindows licence
8///////////////////////////////////////////////////////////////////////////////
9
10#ifdef __GNUG__
9691c806 11 #pragma implementation "dataobj.h"
83df96d6
JS
12#endif
13
14#include "wx/defs.h"
15
83df96d6 16#include "wx/dataobj.h"
9691c806 17#include "wx/mstream.h"
83df96d6 18#include "wx/app.h"
9691c806 19#include "wx/image.h"
83df96d6 20
83df96d6 21#include "wx/utils.h"
7266b672 22#include "wx/x11/private.h"
83df96d6
JS
23
24//-------------------------------------------------------------------------
25// global data
26//-------------------------------------------------------------------------
27
28Atom g_textAtom = 0;
29Atom g_pngAtom = 0;
30Atom g_fileAtom = 0;
31
32//-------------------------------------------------------------------------
33// wxDataFormat
34//-------------------------------------------------------------------------
35
36wxDataFormat::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
50wxDataFormat::wxDataFormat( wxDataFormatId type )
51{
52 PrepareFormats();
53 SetType( type );
54}
55
56wxDataFormat::wxDataFormat( const wxChar *id )
57{
58 PrepareFormats();
59 SetId( id );
60}
61
62wxDataFormat::wxDataFormat( const wxString &id )
63{
64 PrepareFormats();
65 SetId( id );
66}
67
68wxDataFormat::wxDataFormat( NativeFormat format )
69{
70 PrepareFormats();
71 SetId( format );
72}
73
74void 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
93wxDataFormatId wxDataFormat::GetType() const
94{
95 return m_type;
96}
97
98wxString wxDataFormat::GetId() const
99{
70b8ab77
JS
100#if wxUSE_NANOX
101 return wxEmptyString;
102#else
83df96d6
JS
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;
70b8ab77 108#endif
83df96d6
JS
109}
110
111void 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
128void wxDataFormat::SetId( const wxChar *id )
129{
70b8ab77 130#if !wxUSE_NANOX
83df96d6
JS
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?
70b8ab77 135#endif
83df96d6
JS
136}
137
138void wxDataFormat::PrepareFormats()
139{
70b8ab77 140#if !wxUSE_NANOX
83df96d6
JS
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)
9691c806 146 g_fileAtom = XInternAtom( (Display*) wxGetDisplay(), "text/uri-list", FALSE );
70b8ab77 147#endif
83df96d6
JS
148}
149
9691c806
RR
150//-------------------------------------------------------------------------
151// wxDataObject
152//-------------------------------------------------------------------------
153
154wxDataObject::wxDataObject()
155{
156}
157
158bool 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}
83df96d6
JS
183
184// ----------------------------------------------------------------------------
9691c806 185// wxFileDataObject
83df96d6
JS
186// ----------------------------------------------------------------------------
187
9691c806
RR
188bool 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}
83df96d6 202
9691c806 203size_t wxFileDataObject::GetDataSize() const
83df96d6 204{
9691c806
RR
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;
83df96d6
JS
214}
215
9691c806 216bool wxFileDataObject::SetData(size_t WXUNUSED(size), const void *buf)
83df96d6 217{
9691c806
RR
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
83df96d6 281
9691c806
RR
282 return TRUE;
283}
83df96d6 284
9691c806
RR
285void wxFileDataObject::AddFile( const wxString &filename )
286{
287 m_filenames.Add( filename );
83df96d6
JS
288}
289
9691c806
RR
290// ----------------------------------------------------------------------------
291// wxBitmapDataObject
292// ----------------------------------------------------------------------------
293
294wxBitmapDataObject::wxBitmapDataObject()
83df96d6 295{
9691c806
RR
296 Init();
297}
83df96d6 298
9691c806
RR
299wxBitmapDataObject::wxBitmapDataObject( const wxBitmap& bitmap )
300 : wxBitmapDataObjectBase(bitmap)
301{
302 Init();
83df96d6 303
9691c806 304 DoConvertToPng();
83df96d6
JS
305}
306
9691c806 307wxBitmapDataObject::~wxBitmapDataObject()
83df96d6 308{
9691c806 309 Clear();
83df96d6
JS
310}
311
9691c806 312void wxBitmapDataObject::SetBitmap( const wxBitmap &bitmap )
83df96d6 313{
9691c806
RR
314 ClearAll();
315
316 wxBitmapDataObjectBase::SetBitmap(bitmap);
317
318 DoConvertToPng();
83df96d6
JS
319}
320
9691c806 321bool wxBitmapDataObject::GetDataHere(void *buf) const
83df96d6 322{
9691c806
RR
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;
83df96d6
JS
333}
334
9691c806
RR
335bool 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
361void 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}
83df96d6 380