]> git.saurik.com Git - wxWidgets.git/blob - src/x11/dataobj.cpp
Implemented a simple modality under X11.
[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 char *t = XGetAtomName ((Display*) wxGetDisplay(), m_format);
101 wxString ret( t ); // this will convert from ascii to Unicode
102 if (t)
103 XFree( t );
104 return ret;
105 }
106
107 void wxDataFormat::SetId( NativeFormat format )
108 {
109 PrepareFormats();
110 m_format = format;
111
112 if (m_format == g_textAtom)
113 m_type = wxDF_TEXT;
114 else
115 if (m_format == g_pngAtom)
116 m_type = wxDF_BITMAP;
117 else
118 if (m_format == g_fileAtom)
119 m_type = wxDF_FILENAME;
120 else
121 m_type = wxDF_PRIVATE;
122 }
123
124 void wxDataFormat::SetId( const wxChar *id )
125 {
126 PrepareFormats();
127 m_type = wxDF_PRIVATE;
128 wxString tmp( id );
129 m_format = XInternAtom( (Display*) wxGetDisplay(), wxMBSTRINGCAST tmp.mbc_str(), FALSE ); // what is the string cast for?
130 }
131
132 void wxDataFormat::PrepareFormats()
133 {
134 if (!g_textAtom)
135 g_textAtom = XInternAtom( (Display*) wxGetDisplay(), "STRING", FALSE );
136 if (!g_pngAtom)
137 g_pngAtom = XInternAtom( (Display*) wxGetDisplay(), "image/png", FALSE );
138 if (!g_fileAtom)
139 g_fileAtom = XInternAtom( (Display*) wxGetDisplay(), "text/uri-list", FALSE );
140 }
141
142 //-------------------------------------------------------------------------
143 // wxDataObject
144 //-------------------------------------------------------------------------
145
146 wxDataObject::wxDataObject()
147 {
148 }
149
150 bool wxDataObject::IsSupportedFormat(const wxDataFormat& format, Direction dir) const
151 {
152 size_t nFormatCount = GetFormatCount(dir);
153 if ( nFormatCount == 1 )
154 {
155 return format == GetPreferredFormat();
156 }
157 else
158 {
159 wxDataFormat *formats = new wxDataFormat[nFormatCount];
160 GetAllFormats(formats,dir);
161
162 size_t n;
163 for ( n = 0; n < nFormatCount; n++ )
164 {
165 if ( formats[n] == format )
166 break;
167 }
168
169 delete [] formats;
170
171 // found?
172 return n < nFormatCount;
173 }
174 }
175
176 // ----------------------------------------------------------------------------
177 // wxFileDataObject
178 // ----------------------------------------------------------------------------
179
180 bool wxFileDataObject::GetDataHere(void *buf) const
181 {
182 wxString filenames;
183
184 for (size_t i = 0; i < m_filenames.GetCount(); i++)
185 {
186 filenames += m_filenames[i];
187 filenames += (wxChar) 0;
188 }
189
190 memcpy( buf, filenames.mbc_str(), filenames.Len() + 1 );
191
192 return TRUE;
193 }
194
195 size_t wxFileDataObject::GetDataSize() const
196 {
197 size_t res = 0;
198
199 for (size_t i = 0; i < m_filenames.GetCount(); i++)
200 {
201 res += m_filenames[i].Len();
202 res += 1;
203 }
204
205 return res + 1;
206 }
207
208 bool wxFileDataObject::SetData(size_t WXUNUSED(size), const void *buf)
209 {
210 // VZ: old format
211 #if 0
212 // filenames are stores as a string with #0 as deliminators
213 const char *filenames = (const char*) buf;
214 size_t pos = 0;
215 for(;;)
216 {
217 if (filenames[0] == 0)
218 break;
219 if (pos >= size)
220 break;
221 wxString file( filenames ); // this returns the first file
222 AddFile( file );
223 pos += file.Len()+1;
224 filenames += file.Len()+1;
225 }
226 #else // 1
227 m_filenames.Empty();
228
229 // the text/uri-list format is a sequence of URIs (filenames prefixed by
230 // "file:" as far as I see) delimited by "\r\n" of total length size
231 // (I wonder what happens if the file has '\n' in its filename??)
232 wxString filename;
233 for ( const char *p = (const char *)buf; ; p++ )
234 {
235 // some broken programs (testdnd GTK+ sample!) omit the trailing
236 // "\r\n", so check for '\0' explicitly here instead of doing it in
237 // the loop statement to account for it
238 if ( (*p == '\r' && *(p+1) == '\n') || !*p )
239 {
240 size_t lenPrefix = 5; // strlen("file:")
241 if ( filename.Left(lenPrefix).MakeLower() == _T("file:") )
242 {
243 // sometimes the syntax is "file:filename", sometimes it's
244 // URL-like: "file://filename" - deal with both
245 if ( filename[lenPrefix] == _T('/') &&
246 filename[lenPrefix + 1] == _T('/') )
247 {
248 // skip the slashes
249 lenPrefix += 2;
250 }
251
252 AddFile(filename.c_str() + lenPrefix);
253 filename.Empty();
254 }
255 else
256 {
257 wxLogDebug(_T("Unsupported URI '%s' in wxFileDataObject"),
258 filename.c_str());
259 }
260
261 if ( !*p )
262 break;
263
264 // skip '\r'
265 p++;
266 }
267 else
268 {
269 filename += *p;
270 }
271 }
272 #endif // 0/1
273
274 return TRUE;
275 }
276
277 void wxFileDataObject::AddFile( const wxString &filename )
278 {
279 m_filenames.Add( filename );
280 }
281
282 // ----------------------------------------------------------------------------
283 // wxBitmapDataObject
284 // ----------------------------------------------------------------------------
285
286 wxBitmapDataObject::wxBitmapDataObject()
287 {
288 Init();
289 }
290
291 wxBitmapDataObject::wxBitmapDataObject( const wxBitmap& bitmap )
292 : wxBitmapDataObjectBase(bitmap)
293 {
294 Init();
295
296 DoConvertToPng();
297 }
298
299 wxBitmapDataObject::~wxBitmapDataObject()
300 {
301 Clear();
302 }
303
304 void wxBitmapDataObject::SetBitmap( const wxBitmap &bitmap )
305 {
306 ClearAll();
307
308 wxBitmapDataObjectBase::SetBitmap(bitmap);
309
310 DoConvertToPng();
311 }
312
313 bool wxBitmapDataObject::GetDataHere(void *buf) const
314 {
315 if ( !m_pngSize )
316 {
317 wxFAIL_MSG( wxT("attempt to copy empty bitmap failed") );
318
319 return FALSE;
320 }
321
322 memcpy(buf, m_pngData, m_pngSize);
323
324 return TRUE;
325 }
326
327 bool wxBitmapDataObject::SetData(size_t size, const void *buf)
328 {
329 Clear();
330
331 #if wxUSE_LIBPNG
332 m_pngSize = size;
333 m_pngData = malloc(m_pngSize);
334
335 memcpy( m_pngData, buf, m_pngSize );
336
337 wxMemoryInputStream mstream( (char*) m_pngData, m_pngSize );
338 wxImage image;
339 wxPNGHandler handler;
340 if ( !handler.LoadFile( &image, mstream ) )
341 {
342 return FALSE;
343 }
344
345 m_bitmap = image.ConvertToBitmap();
346
347 return m_bitmap.Ok();
348 #else
349 return FALSE;
350 #endif
351 }
352
353 void wxBitmapDataObject::DoConvertToPng()
354 {
355 #if wxUSE_LIBPNG
356 if (!m_bitmap.Ok())
357 return;
358
359 wxImage image( m_bitmap );
360 wxPNGHandler handler;
361
362 wxCountingOutputStream count;
363 handler.SaveFile( &image, count );
364
365 m_pngSize = count.GetSize() + 100; // sometimes the size seems to vary ???
366 m_pngData = malloc(m_pngSize);
367
368 wxMemoryOutputStream mstream( (char*) m_pngData, m_pngSize );
369 handler.SaveFile( &image, mstream );
370 #endif
371 }
372