]> git.saurik.com Git - wxWidgets.git/blob - src/x11/dataobj.cpp
simplify/cleanup wxTheXXXList and wxGDIObject code (patch 1452023 from Paul Cornett)
[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 #include "wx/defs.h"
11
12 #if wxUSE_DATAOBJ
13
14 #include "wx/dataobj.h"
15 #include "wx/mstream.h"
16 #include "wx/app.h"
17 #include "wx/image.h"
18 #include "wx/log.h"
19
20 #include "wx/utils.h"
21 #include "wx/x11/private.h"
22
23 //-------------------------------------------------------------------------
24 // global data
25 //-------------------------------------------------------------------------
26
27 Atom g_textAtom = 0;
28 Atom g_pngAtom = 0;
29 Atom g_fileAtom = 0;
30
31 //-------------------------------------------------------------------------
32 // wxDataFormat
33 //-------------------------------------------------------------------------
34
35 wxDataFormat::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
49 wxDataFormat::wxDataFormat( wxDataFormatId type )
50 {
51 PrepareFormats();
52 SetType( type );
53 }
54
55 wxDataFormat::wxDataFormat( const wxChar *id )
56 {
57 PrepareFormats();
58 SetId( id );
59 }
60
61 wxDataFormat::wxDataFormat( const wxString &id )
62 {
63 PrepareFormats();
64 SetId( id );
65 }
66
67 wxDataFormat::wxDataFormat( NativeFormat format )
68 {
69 PrepareFormats();
70 SetId( format );
71 }
72
73 void 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
92 wxDataFormatId wxDataFormat::GetType() const
93 {
94 return m_type;
95 }
96
97 wxString wxDataFormat::GetId() const
98 {
99 #if wxUSE_NANOX
100 return wxEmptyString;
101 #else
102 char *t = XGetAtomName ((Display*) wxGetDisplay(), m_format);
103 wxString ret = wxString::FromAscii( t );
104 if (t)
105 XFree( t );
106 return ret;
107 #endif
108 }
109
110 void 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
127 void wxDataFormat::SetId( const wxChar *id )
128 {
129 #if !wxUSE_NANOX
130 PrepareFormats();
131 m_type = wxDF_PRIVATE;
132 wxString tmp( id );
133 m_format = XInternAtom( (Display*) wxGetDisplay(), tmp.ToAscii(), FALSE );
134 #endif
135 }
136
137 void wxDataFormat::PrepareFormats()
138 {
139 #if !wxUSE_NANOX
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)
145 g_fileAtom = XInternAtom( (Display*) wxGetDisplay(), "text/uri-list", FALSE );
146 #endif
147 }
148
149 //-------------------------------------------------------------------------
150 // wxDataObject
151 //-------------------------------------------------------------------------
152
153 wxDataObject::wxDataObject()
154 {
155 }
156
157 bool 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 }
182
183 // ----------------------------------------------------------------------------
184 // wxFileDataObject
185 // ----------------------------------------------------------------------------
186
187 bool 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 }
201
202 size_t wxFileDataObject::GetDataSize() const
203 {
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;
213 }
214
215 bool wxFileDataObject::SetData(size_t WXUNUSED(size), const void *buf)
216 {
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
280
281 return TRUE;
282 }
283
284 void wxFileDataObject::AddFile( const wxString &filename )
285 {
286 m_filenames.Add( filename );
287 }
288
289 // ----------------------------------------------------------------------------
290 // wxBitmapDataObject
291 // ----------------------------------------------------------------------------
292
293 wxBitmapDataObject::wxBitmapDataObject()
294 {
295 Init();
296 }
297
298 wxBitmapDataObject::wxBitmapDataObject( const wxBitmap& bitmap )
299 : wxBitmapDataObjectBase(bitmap)
300 {
301 Init();
302
303 DoConvertToPng();
304 }
305
306 wxBitmapDataObject::~wxBitmapDataObject()
307 {
308 Clear();
309 }
310
311 void wxBitmapDataObject::SetBitmap( const wxBitmap &bitmap )
312 {
313 ClearAll();
314
315 wxBitmapDataObjectBase::SetBitmap(bitmap);
316
317 DoConvertToPng();
318 }
319
320 bool wxBitmapDataObject::GetDataHere(void *buf) const
321 {
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;
332 }
333
334 bool 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
352 m_bitmap = image;
353
354 return m_bitmap.Ok();
355 #else
356 return FALSE;
357 #endif
358 }
359
360 void wxBitmapDataObject::DoConvertToPng()
361 {
362 #if wxUSE_LIBPNG
363 if (!m_bitmap.Ok())
364 return;
365
366 wxImage image = m_bitmap.ConvertToImage();
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 }
379
380 #endif // wxUSE_DATAOBJ
381