]> git.saurik.com Git - wxWidgets.git/blame - src/gtk1/clipbrd.cpp
enabled _vsnprintf for mingw with norlander headers
[wxWidgets.git] / src / gtk1 / clipbrd.cpp
CommitLineData
dc86cb34
RR
1/////////////////////////////////////////////////////////////////////////////
2// Name: clipbrd.cpp
3// Purpose:
4// Author: Robert Roebling
5// Id: $Id$
6// Copyright: (c) 1998 Robert Roebling
66633398 7// Licence: wxWindows licence
dc86cb34
RR
8/////////////////////////////////////////////////////////////////////////////
9
10#ifdef __GNUG__
11#pragma implementation "clipbrd.h"
12#endif
13
14#include "wx/clipbrd.h"
15
06cfab17 16#if wxUSE_CLIPBOARD
ac57418f 17
e1ee679c 18#include "wx/dataobj.h"
034be888 19#include "wx/utils.h"
b068c4e8 20#include "wx/log.h"
034be888 21
83624f79
RR
22#include "glib.h"
23#include "gdk/gdk.h"
24#include "gtk/gtk.h"
25
b453e1b2
RR
26//-----------------------------------------------------------------------------
27// thread system
28//-----------------------------------------------------------------------------
29
30#if wxUSE_THREADS
31extern void wxapp_install_thread_wakeup();
32extern void wxapp_uninstall_thread_wakeup();
33#endif
34
dc86cb34
RR
35//-----------------------------------------------------------------------------
36// data
37//-----------------------------------------------------------------------------
38
fd0eed64 39GdkAtom g_clipboardAtom = 0;
b527aac5 40GdkAtom g_targetsAtom = 0;
fd0eed64 41
dc86cb34 42//-----------------------------------------------------------------------------
b527aac5 43// reminder
dc86cb34
RR
44//-----------------------------------------------------------------------------
45
b527aac5 46/* The contents of a selection are returned in a GtkSelectionData
270c23f7 47 structure. selection/target identify the request.
b527aac5
RR
48 type specifies the type of the return; if length < 0, and
49 the data should be ignored. This structure has object semantics -
50 no fields should be modified directly, they should not be created
51 directly, and pointers to them should not be stored beyond the duration of
52 a callback. (If the last is changed, we'll need to add reference
53 counting)
54
55struct _GtkSelectionData
dc86cb34 56{
b527aac5
RR
57 GdkAtom selection;
58 GdkAtom target;
59 GdkAtom type;
66633398 60 gint format;
b527aac5 61 guchar *data;
66633398 62 gint length;
b527aac5
RR
63};
64
65*/
dc86cb34 66
b527aac5
RR
67//-----------------------------------------------------------------------------
68// "selection_received" for targets
69//-----------------------------------------------------------------------------
70
71static void
270c23f7
VZ
72targets_selection_received( GtkWidget *WXUNUSED(widget),
73 GtkSelectionData *selection_data,
034be888
RR
74#if (GTK_MINOR_VERSION > 0)
75 guint32 WXUNUSED(time),
76#endif
66633398 77 wxClipboard *clipboard )
dc86cb34 78{
270c23f7 79 if ( wxTheClipboard && selection_data->length > 0 )
034be888 80 {
270c23f7 81 /* make sure we got the data in the correct form */
270c23f7
VZ
82 GdkAtom type = selection_data->type;
83 if ( type != GDK_SELECTION_TYPE_ATOM )
84 {
eff869aa
RR
85 clipboard->m_waiting = FALSE;
86 return;
270c23f7 87 }
b527aac5 88
eff869aa 89/*
270c23f7
VZ
90 wxDataFormat clip( selection_data->selection );
91 wxLogDebug( wxT("selection received for targets, clipboard %s"), clip.GetId().c_str() );
eff869aa 92*/
270c23f7
VZ
93
94 // the atoms we received, holding a list of targets (= formats)
95 GdkAtom *atoms = (GdkAtom *)selection_data->data;
11e1c70d 96
270c23f7 97 for (unsigned int i=0; i<selection_data->length/sizeof(GdkAtom); i++)
8b53e5a2 98 {
270c23f7
VZ
99 wxDataFormat format( atoms[i] );
100
eff869aa 101/*
270c23f7 102 wxLogDebug( wxT("selection received for targets, format %s"), format.GetId().c_str() );
eff869aa 103*/
270c23f7
VZ
104
105 if (format == clipboard->m_targetRequested)
106 {
107 clipboard->m_waiting = FALSE;
108 clipboard->m_formatSupported = TRUE;
109 return;
110 }
8b53e5a2
RR
111 }
112 }
b527aac5 113
034be888 114 clipboard->m_waiting = FALSE;
dc86cb34
RR
115}
116
117//-----------------------------------------------------------------------------
b527aac5 118// "selection_received" for the actual data
dc86cb34
RR
119//-----------------------------------------------------------------------------
120
270c23f7
VZ
121static void
122selection_received( GtkWidget *WXUNUSED(widget),
123 GtkSelectionData *selection_data,
034be888
RR
124#if (GTK_MINOR_VERSION > 0)
125 guint32 WXUNUSED(time),
126#endif
66633398 127 wxClipboard *clipboard )
dc86cb34 128{
034be888
RR
129 if (!wxTheClipboard)
130 {
131 clipboard->m_waiting = FALSE;
132 return;
133 }
270c23f7 134
8b53e5a2 135 wxDataObject *data_object = clipboard->m_receivedData;
1dd989e1 136
034be888
RR
137 if (!data_object)
138 {
139 clipboard->m_waiting = FALSE;
140 return;
141 }
270c23f7 142
034be888
RR
143 if (selection_data->length <= 0)
144 {
145 clipboard->m_waiting = FALSE;
146 return;
147 }
270c23f7 148
b068c4e8 149 wxDataFormat format( selection_data->target );
270c23f7 150
034be888 151 /* make sure we got the data in the correct format */
b068c4e8 152 if (!data_object->IsSupportedFormat( format ) )
034be888
RR
153 {
154 clipboard->m_waiting = FALSE;
155 return;
156 }
e2acb9ae 157
034be888
RR
158 /* make sure we got the data in the correct form (selection type).
159 if so, copy data to target object */
e5d6aa22 160 if (selection_data->type != GDK_SELECTION_TYPE_STRING)
8b53e5a2 161 {
e5d6aa22
RR
162 clipboard->m_waiting = FALSE;
163 return;
8b53e5a2 164 }
270c23f7 165
e5d6aa22 166 data_object->SetData( format, (size_t) selection_data->length, (const char*) selection_data->data );
270c23f7 167
8b53e5a2 168 wxTheClipboard->m_formatSupported = TRUE;
034be888 169 clipboard->m_waiting = FALSE;
dc86cb34 170}
fd0eed64
RR
171
172//-----------------------------------------------------------------------------
173// "selection_clear"
174//-----------------------------------------------------------------------------
175
176static gint
aeeb6a44 177selection_clear_clip( GtkWidget *WXUNUSED(widget), GdkEventSelection *event )
fd0eed64 178{
8b53e5a2 179 if (!wxTheClipboard) return TRUE;
270c23f7 180
aeeb6a44
RR
181 if (event->selection == GDK_SELECTION_PRIMARY)
182 {
183 wxTheClipboard->m_ownsPrimarySelection = FALSE;
184 }
185 else
186 if (event->selection == g_clipboardAtom)
187 {
188 wxTheClipboard->m_ownsClipboard = FALSE;
189 }
190 else
191 {
e5ea3f7a 192 wxTheClipboard->m_waiting = FALSE;
aeeb6a44
RR
193 return FALSE;
194 }
270c23f7 195
aeeb6a44
RR
196 if ((!wxTheClipboard->m_ownsPrimarySelection) &&
197 (!wxTheClipboard->m_ownsClipboard))
198 {
db2d879a 199 /* the clipboard is no longer in our hands. we can the delete clipboard data. */
1dd989e1 200 if (wxTheClipboard->m_data)
66633398 201 {
270c23f7
VZ
202 wxLogDebug( wxT("wxClipboard will get cleared" ) );
203
66633398
VZ
204 delete wxTheClipboard->m_data;
205 wxTheClipboard->m_data = (wxDataObject*) NULL;
206 }
aeeb6a44 207 }
270c23f7 208
e5ea3f7a 209 wxTheClipboard->m_waiting = FALSE;
8b53e5a2 210 return TRUE;
fd0eed64
RR
211}
212
213//-----------------------------------------------------------------------------
214// selection handler for supplying data
215//-----------------------------------------------------------------------------
216
217static void
19d89516
VZ
218selection_handler( GtkWidget *WXUNUSED(widget),
219 GtkSelectionData *selection_data,
220 guint WXUNUSED(info),
221 guint WXUNUSED(time),
222 gpointer WXUNUSED(data) )
fd0eed64 223{
8b53e5a2 224 if (!wxTheClipboard) return;
270c23f7 225
1dd989e1 226 if (!wxTheClipboard->m_data) return;
270c23f7 227
1dd989e1 228 wxDataObject *data = wxTheClipboard->m_data;
270c23f7 229
b068c4e8
RR
230 wxDataFormat format( selection_data->target );
231
232 if (!data->IsSupportedFormat( format )) return;
270c23f7 233
e5d6aa22 234 /* this will fail for composite formats */
b068c4e8 235 if (format.GetType() == wxDF_TEXT)
8b53e5a2 236 {
66633398
VZ
237 wxTextDataObject *text_object = (wxTextDataObject*) data;
238 wxString text( text_object->GetText() );
1dd989e1 239
93c5dd39 240#if wxUSE_UNICODE
66633398
VZ
241 const wxWX2MBbuf s = text.mbc_str();
242 int len = strlen(s);
93c5dd39 243#else // more efficient in non-Unicode
66633398
VZ
244 const char *s = text.c_str();
245 int len = (int) text.Length();
93c5dd39 246#endif
270c23f7
VZ
247 gtk_selection_data_set(
248 selection_data,
249 GDK_SELECTION_TYPE_STRING,
66633398
VZ
250 8*sizeof(gchar),
251 (unsigned char*) (const char*) s,
270c23f7
VZ
252 len );
253
66633398 254 return;
1dd989e1
RR
255 }
256
b068c4e8 257 int size = data->GetDataSize( format );
270c23f7 258
1dd989e1 259 if (size == 0) return;
270c23f7 260
1dd989e1 261 char *d = new char[size];
270c23f7 262
1dd989e1
RR
263 data->GetDataHere( selection_data->target, (void*) d );
264
270c23f7
VZ
265 gtk_selection_data_set(
266 selection_data,
267 GDK_SELECTION_TYPE_STRING,
268 8*sizeof(gchar),
66633398 269 (unsigned char*) d,
270c23f7 270 size );
fd0eed64 271}
dc86cb34
RR
272
273//-----------------------------------------------------------------------------
274// wxClipboard
275//-----------------------------------------------------------------------------
276
277IMPLEMENT_DYNAMIC_CLASS(wxClipboard,wxObject)
278
279wxClipboard::wxClipboard()
280{
8b53e5a2
RR
281 m_open = FALSE;
282
aeeb6a44
RR
283 m_ownsClipboard = FALSE;
284 m_ownsPrimarySelection = FALSE;
285
1dd989e1 286 m_data = (wxDataObject*) NULL;
8b53e5a2 287 m_receivedData = (wxDataObject*) NULL;
99c67c77 288
034be888 289 /* we use m_targetsWidget to query what formats are available */
270c23f7 290
034be888
RR
291 m_targetsWidget = gtk_window_new( GTK_WINDOW_POPUP );
292 gtk_widget_realize( m_targetsWidget );
293
270c23f7 294 gtk_signal_connect( GTK_OBJECT(m_targetsWidget),
034be888 295 "selection_received",
270c23f7 296 GTK_SIGNAL_FUNC( targets_selection_received ),
66633398 297 (gpointer) this );
270c23f7 298
034be888 299 /* we use m_clipboardWidget to get and to offer data */
270c23f7 300
8b53e5a2
RR
301 m_clipboardWidget = gtk_window_new( GTK_WINDOW_POPUP );
302 gtk_widget_realize( m_clipboardWidget );
303
270c23f7 304 gtk_signal_connect( GTK_OBJECT(m_clipboardWidget),
034be888 305 "selection_received",
270c23f7 306 GTK_SIGNAL_FUNC( selection_received ),
66633398 307 (gpointer) this );
034be888 308
270c23f7 309 gtk_signal_connect( GTK_OBJECT(m_clipboardWidget),
8b53e5a2 310 "selection_clear_event",
270c23f7 311 GTK_SIGNAL_FUNC( selection_clear_clip ),
66633398 312 (gpointer) NULL );
270c23f7 313
8b53e5a2 314 if (!g_clipboardAtom) g_clipboardAtom = gdk_atom_intern( "CLIPBOARD", FALSE );
8b53e5a2 315 if (!g_targetsAtom) g_targetsAtom = gdk_atom_intern ("TARGETS", FALSE);
270c23f7 316
8b53e5a2
RR
317 m_formatSupported = FALSE;
318 m_targetRequested = 0;
270c23f7 319
7e2c43b8 320 m_usePrimary = FALSE;
dc86cb34
RR
321}
322
323wxClipboard::~wxClipboard()
b527aac5 324{
270c23f7
VZ
325 Clear();
326
8b53e5a2 327 if (m_clipboardWidget) gtk_widget_destroy( m_clipboardWidget );
034be888 328 if (m_targetsWidget) gtk_widget_destroy( m_targetsWidget );
b527aac5
RR
329}
330
331void wxClipboard::Clear()
dc86cb34 332{
1dd989e1
RR
333 if (m_data)
334 {
b453e1b2
RR
335#if wxUSE_THREADS
336 /* disable GUI threads */
337 wxapp_uninstall_thread_wakeup();
338#endif
270c23f7 339
8b53e5a2
RR
340 /* As we have data we also own the clipboard. Once we no longer own
341 it, clear_selection is called which will set m_data to zero */
aeeb6a44 342 if (gdk_selection_owner_get( g_clipboardAtom ) == m_clipboardWidget->window)
8b53e5a2 343 {
e5ea3f7a 344 m_waiting = TRUE;
270c23f7 345
b02da6b1
VZ
346 gtk_selection_owner_set( (GtkWidget*) NULL, g_clipboardAtom,
347 (guint32) GDK_CURRENT_TIME );
270c23f7 348
e5ea3f7a 349 while (m_waiting) gtk_main_iteration();
8b53e5a2 350 }
270c23f7 351
aeeb6a44
RR
352 if (gdk_selection_owner_get( GDK_SELECTION_PRIMARY ) == m_clipboardWidget->window)
353 {
e5ea3f7a 354 m_waiting = TRUE;
270c23f7 355
b02da6b1
VZ
356 gtk_selection_owner_set( (GtkWidget*) NULL, GDK_SELECTION_PRIMARY,
357 (guint32) GDK_CURRENT_TIME );
270c23f7 358
e5ea3f7a 359 while (m_waiting) gtk_main_iteration();
aeeb6a44 360 }
270c23f7 361
1dd989e1 362 if (m_data)
270c23f7 363 {
66633398
VZ
364 delete m_data;
365 m_data = (wxDataObject*) NULL;
366 }
270c23f7 367
b453e1b2
RR
368#if wxUSE_THREADS
369 /* re-enable GUI threads */
370 wxapp_install_thread_wakeup();
371#endif
8b53e5a2 372 }
270c23f7 373
8b53e5a2 374 m_targetRequested = 0;
8b53e5a2
RR
375 m_formatSupported = FALSE;
376}
377
378bool wxClipboard::Open()
379{
223d09f6 380 wxCHECK_MSG( !m_open, FALSE, wxT("clipboard already open") );
270c23f7 381
8b53e5a2 382 m_open = TRUE;
270c23f7 383
8b53e5a2 384 return TRUE;
dc86cb34
RR
385}
386
75ce0581 387bool wxClipboard::SetData( wxDataObject *data )
dc86cb34 388{
223d09f6 389 wxCHECK_MSG( m_open, FALSE, wxT("clipboard not open") );
270c23f7 390
223d09f6 391 wxCHECK_MSG( data, FALSE, wxT("data is invalid") );
270c23f7 392
0d2a2b60 393 Clear();
75ce0581
RR
394
395 return AddData( data );
396}
397
398bool wxClipboard::AddData( wxDataObject *data )
399{
223d09f6 400 wxCHECK_MSG( m_open, FALSE, wxT("clipboard not open") );
270c23f7 401
223d09f6 402 wxCHECK_MSG( data, FALSE, wxT("data is invalid") );
270c23f7 403
b068c4e8 404 /* we can only store one wxDataObject */
1dd989e1 405 Clear();
270c23f7 406
1dd989e1
RR
407 m_data = data;
408
b068c4e8
RR
409 /* get formats from wxDataObjects */
410 wxDataFormat *array = new wxDataFormat[ m_data->GetFormatCount() ];
411 m_data->GetAllFormats( array );
11e1c70d
RR
412
413 /* primary selection or clipboard */
414 GdkAtom clipboard = m_usePrimary ? (GdkAtom)GDK_SELECTION_PRIMARY
415 : g_clipboardAtom;
416
270c23f7 417
b068c4e8
RR
418 for (size_t i = 0; i < m_data->GetFormatCount(); i++)
419 {
11e1c70d
RR
420 wxLogDebug( wxT("wxClipboard now supports atom %s"), array[i].GetId().c_str() );
421
422 gtk_selection_add_target( GTK_WIDGET(m_clipboardWidget),
270c23f7
VZ
423 clipboard,
424 array[i],
11e1c70d 425 0 ); /* what is info ? */
b068c4e8
RR
426 }
427
428 delete[] array;
270c23f7
VZ
429
430 gtk_signal_connect( GTK_OBJECT(m_clipboardWidget),
d345e841 431 "selection_get",
270c23f7 432 GTK_SIGNAL_FUNC(selection_handler),
66633398 433 (gpointer) NULL );
d345e841 434
b453e1b2 435#if wxUSE_THREADS
11e1c70d
RR
436 /* disable GUI threads */
437 wxapp_uninstall_thread_wakeup();
b453e1b2 438#endif
270c23f7 439
75ce0581 440 /* Tell the world we offer clipboard data */
11e1c70d
RR
441 bool res = (gtk_selection_owner_set( m_clipboardWidget,
442 clipboard,
b02da6b1 443 (guint32) GDK_CURRENT_TIME ));
270c23f7 444
11e1c70d
RR
445 if (m_usePrimary)
446 m_ownsPrimarySelection = res;
447 else
448 m_ownsClipboard = res;
270c23f7 449
b453e1b2
RR
450#if wxUSE_THREADS
451 /* re-enable GUI threads */
452 wxapp_install_thread_wakeup();
453#endif
270c23f7 454
11e1c70d 455 return res;
8b53e5a2 456}
db1b4961 457
8b53e5a2
RR
458void wxClipboard::Close()
459{
223d09f6 460 wxCHECK_RET( m_open, wxT("clipboard not open") );
270c23f7 461
8b53e5a2 462 m_open = FALSE;
dc86cb34
RR
463}
464
f536e0f2
VZ
465bool wxClipboard::IsOpened() const
466{
467 return m_open;
468}
469
e1ee679c 470bool wxClipboard::IsSupported( const wxDataFormat& format )
b527aac5 471{
e5d6aa22 472 /* reentrance problems */
eff869aa 473 if (m_waiting) return FALSE;
270c23f7 474
e5d6aa22 475 /* store requested format to be asked for by callbacks */
1dd989e1 476 m_targetRequested = format;
270c23f7 477
eff869aa
RR
478 wxLogDebug( wxT("wxClipboard:IsSupported: requested format: %s"), format.GetId().c_str() );
479
223d09f6 480 wxCHECK_MSG( m_targetRequested, FALSE, wxT("invalid clipboard format") );
270c23f7 481
8b53e5a2 482 m_formatSupported = FALSE;
270c23f7
VZ
483
484 /* perform query. this will set m_formatSupported to
034be888 485 TRUE if m_targetRequested is supported.
270c23f7 486 also, we have to wait for the "answer" from the
034be888
RR
487 clipboard owner which is an asynchronous process.
488 therefore we set m_waiting = TRUE here and wait
270c23f7 489 until the callback "targets_selection_received"
034be888
RR
490 sets it to FALSE */
491
492 m_waiting = TRUE;
ca35e608 493
034be888 494 gtk_selection_convert( m_targetsWidget,
66633398 495 m_usePrimary ? (GdkAtom)GDK_SELECTION_PRIMARY
270c23f7 496 : g_clipboardAtom,
66633398 497 g_targetsAtom,
b02da6b1 498 (guint32) GDK_CURRENT_TIME );
ca35e608 499
034be888 500 while (m_waiting) gtk_main_iteration();
270c23f7 501
8b53e5a2 502 if (!m_formatSupported) return FALSE;
270c23f7 503
75ce0581 504 return TRUE;
270c23f7
VZ
505}
506
e1ee679c 507bool wxClipboard::GetData( wxDataObject& data )
75ce0581 508{
223d09f6 509 wxCHECK_MSG( m_open, FALSE, wxT("clipboard not open") );
270c23f7 510
b068c4e8
RR
511 /* get formats from wxDataObjects */
512 wxDataFormat *array = new wxDataFormat[ data.GetFormatCount() ];
513 data.GetAllFormats( array );
270c23f7 514
b068c4e8
RR
515 for (size_t i = 0; i < data.GetFormatCount(); i++)
516 {
e5d6aa22 517 wxDataFormat format( array[i] );
270c23f7 518
11e1c70d 519 wxLogDebug( wxT("wxClipboard::GetData: requested format: %s"), format.GetId().c_str() );
270c23f7 520
b068c4e8 521 /* is data supported by clipboard ? */
270c23f7 522
11e1c70d
RR
523 /* store requested format to be asked for by callbacks */
524 m_targetRequested = format;
270c23f7 525
11e1c70d 526 wxCHECK_MSG( m_targetRequested, FALSE, wxT("invalid clipboard format") );
270c23f7 527
11e1c70d 528 m_formatSupported = FALSE;
270c23f7
VZ
529
530 /* perform query. this will set m_formatSupported to
11e1c70d 531 TRUE if m_targetRequested is supported.
270c23f7 532 also, we have to wait for the "answer" from the
11e1c70d
RR
533 clipboard owner which is an asynchronous process.
534 therefore we set m_waiting = TRUE here and wait
270c23f7 535 until the callback "targets_selection_received"
11e1c70d
RR
536 sets it to FALSE */
537
538 m_waiting = TRUE;
539
540 gtk_selection_convert( m_targetsWidget,
541 m_usePrimary ? (GdkAtom)GDK_SELECTION_PRIMARY
270c23f7 542 : g_clipboardAtom,
11e1c70d 543 g_targetsAtom,
b02da6b1 544 (guint32) GDK_CURRENT_TIME );
11e1c70d
RR
545
546 while (m_waiting) gtk_main_iteration();
270c23f7 547
11e1c70d 548 if (!m_formatSupported) continue;
270c23f7 549
b068c4e8
RR
550 /* store pointer to data object to be filled up by callbacks */
551 m_receivedData = &data;
270c23f7 552
b068c4e8 553 /* store requested format to be asked for by callbacks */
e5d6aa22 554 m_targetRequested = format;
270c23f7 555
b068c4e8 556 wxCHECK_MSG( m_targetRequested, FALSE, wxT("invalid clipboard format") );
270c23f7 557
b068c4e8
RR
558 /* start query */
559 m_formatSupported = FALSE;
270c23f7
VZ
560
561 /* ask for clipboard contents. this will set
562 m_formatSupported to TRUE if m_targetRequested
b068c4e8 563 is supported.
270c23f7 564 also, we have to wait for the "answer" from the
b068c4e8
RR
565 clipboard owner which is an asynchronous process.
566 therefore we set m_waiting = TRUE here and wait
270c23f7 567 until the callback "targets_selection_received"
b068c4e8
RR
568 sets it to FALSE */
569
570 m_waiting = TRUE;
571
e5d6aa22 572 wxLogDebug( wxT("wxClipboard::GetData: format found, start convert") );
270c23f7 573
b068c4e8 574 gtk_selection_convert( m_clipboardWidget,
66633398 575 m_usePrimary ? (GdkAtom)GDK_SELECTION_PRIMARY
270c23f7 576 : g_clipboardAtom,
66633398 577 m_targetRequested,
b02da6b1 578 (guint32) GDK_CURRENT_TIME );
270c23f7 579
b068c4e8 580 while (m_waiting) gtk_main_iteration();
b527aac5 581
b068c4e8
RR
582 /* this is a true error as we checked for the presence of such data before */
583 wxCHECK_MSG( m_formatSupported, FALSE, wxT("error retrieving data from clipboard") );
270c23f7 584
66633398 585 /* return success */
b068c4e8
RR
586 delete[] array;
587 return TRUE;
588 }
270c23f7 589
11e1c70d 590 wxLogDebug( wxT("wxClipboard::GetData: format not found") );
270c23f7 591
b068c4e8
RR
592 /* return failure */
593 delete[] array;
594 return FALSE;
b527aac5
RR
595}
596
ac57418f 597#endif
ac57418f
RR
598 // wxUSE_CLIPBOARD
599