]> git.saurik.com Git - wxWidgets.git/blame - src/gtk/clipbrd.cpp
Some more doc beauty,
[wxWidgets.git] / src / gtk / 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
7// Licence: wxWindows licence
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
034be888
RR
18#include "wx/utils.h"
19
83624f79
RR
20#include "glib.h"
21#include "gdk/gdk.h"
22#include "gtk/gtk.h"
23
b453e1b2
RR
24//-----------------------------------------------------------------------------
25// thread system
26//-----------------------------------------------------------------------------
27
28#if wxUSE_THREADS
29extern void wxapp_install_thread_wakeup();
30extern void wxapp_uninstall_thread_wakeup();
31#endif
32
dc86cb34
RR
33//-----------------------------------------------------------------------------
34// data
35//-----------------------------------------------------------------------------
36
37wxClipboard *wxTheClipboard = (wxClipboard*) NULL;
38
fd0eed64 39GdkAtom g_clipboardAtom = 0;
b527aac5 40GdkAtom g_targetsAtom = 0;
fd0eed64 41
dc86cb34 42//-----------------------------------------------------------------------------
b527aac5 43// reminder
dc86cb34
RR
44//-----------------------------------------------------------------------------
45
b527aac5
RR
46/* The contents of a selection are returned in a GtkSelectionData
47 structure. selection/target identify the request.
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;
60 gint format;
61 guchar *data;
62 gint length;
63};
64
65*/
dc86cb34 66
b527aac5
RR
67//-----------------------------------------------------------------------------
68// "selection_received" for targets
69//-----------------------------------------------------------------------------
70
71static void
72targets_selection_received( GtkWidget *WXUNUSED(widget),
73 GtkSelectionData *selection_data,
034be888
RR
74#if (GTK_MINOR_VERSION > 0)
75 guint32 WXUNUSED(time),
76#endif
b527aac5 77 wxClipboard *clipboard )
dc86cb34 78{
034be888
RR
79 if (!wxTheClipboard)
80 {
81 clipboard->m_waiting = FALSE;
82 return;
83 }
b527aac5 84
034be888
RR
85 if (selection_data->length <= 0)
86 {
87 clipboard->m_waiting = FALSE;
88 return;
89 }
90
91 /* make sure we got the data in the correct form */
92 if (selection_data->type != GDK_SELECTION_TYPE_ATOM)
93 {
94 clipboard->m_waiting = FALSE;
95 return;
96 }
b527aac5 97
8b53e5a2
RR
98 // the atoms we received, holding a list of targets (= formats)
99 GdkAtom *atoms = (GdkAtom *)selection_data->data;
b527aac5 100
8b53e5a2
RR
101 for (unsigned int i=0; i<selection_data->length/sizeof(GdkAtom); i++)
102 {
7e2c43b8 103/* char *name = gdk_atom_name (atoms[i]);
ca35e608 104 if (name) printf( "Format available: %s.\n", name ); */
3c1b65a4 105
8b53e5a2
RR
106 if (atoms[i] == clipboard->m_targetRequested)
107 {
034be888 108 clipboard->m_waiting = FALSE;
8b53e5a2
RR
109 clipboard->m_formatSupported = TRUE;
110 return;
111 }
112 }
b527aac5 113
034be888 114 clipboard->m_waiting = FALSE;
8b53e5a2 115 return;
dc86cb34
RR
116}
117
118//-----------------------------------------------------------------------------
b527aac5 119// "selection_received" for the actual data
dc86cb34
RR
120//-----------------------------------------------------------------------------
121
fd0eed64 122static void
b527aac5
RR
123selection_received( GtkWidget *WXUNUSED(widget),
124 GtkSelectionData *selection_data,
034be888
RR
125#if (GTK_MINOR_VERSION > 0)
126 guint32 WXUNUSED(time),
127#endif
b527aac5 128 wxClipboard *clipboard )
dc86cb34 129{
034be888
RR
130 if (!wxTheClipboard)
131 {
132 clipboard->m_waiting = FALSE;
133 return;
134 }
b527aac5 135
8b53e5a2
RR
136 wxDataObject *data_object = clipboard->m_receivedData;
137
034be888
RR
138 if (!data_object)
139 {
140 clipboard->m_waiting = FALSE;
141 return;
142 }
8b53e5a2 143
034be888
RR
144 if (selection_data->length <= 0)
145 {
146 clipboard->m_waiting = FALSE;
147 return;
148 }
b527aac5 149
034be888
RR
150 /* make sure we got the data in the correct format */
151 if (data_object->GetFormat().GetAtom() != selection_data->target)
152 {
153 clipboard->m_waiting = FALSE;
154 return;
155 }
8b53e5a2 156
034be888
RR
157 /* make sure we got the data in the correct form (selection type).
158 if so, copy data to target object */
8b53e5a2 159
0d2a2b60 160 switch (data_object->GetFormat().GetType())
8b53e5a2
RR
161 {
162 case wxDF_TEXT:
163 {
034be888
RR
164 if (selection_data->type != GDK_SELECTION_TYPE_STRING)
165 {
166 clipboard->m_waiting = FALSE;
167 return;
168 }
8b53e5a2
RR
169
170 wxTextDataObject *text_object = (wxTextDataObject *) data_object;
171
172 wxString text = (const char*) selection_data->data;
173
174 text_object->SetText( text );
175
176 break;
177 }
178
179 case wxDF_BITMAP:
180 {
034be888
RR
181 if (selection_data->type != GDK_SELECTION_TYPE_BITMAP)
182 {
183 clipboard->m_waiting = FALSE;
184 return;
185 }
8b53e5a2
RR
186
187 break;
188 }
189
190 case wxDF_PRIVATE:
191 {
034be888
RR
192 if (selection_data->type != GDK_SELECTION_TYPE_STRING)
193 {
194 clipboard->m_waiting = FALSE;
195 return;
196 }
8b53e5a2
RR
197
198 wxPrivateDataObject *private_object = (wxPrivateDataObject *) data_object;
199
200 private_object->SetData( (const char*) selection_data->data, (size_t) selection_data->length );
201
202 break;
203 }
204
205 default:
206 {
034be888 207 clipboard->m_waiting = FALSE;
8b53e5a2
RR
208 return;
209 }
210 }
211
212 wxTheClipboard->m_formatSupported = TRUE;
034be888 213 clipboard->m_waiting = FALSE;
dc86cb34 214}
fd0eed64
RR
215
216//-----------------------------------------------------------------------------
217// "selection_clear"
218//-----------------------------------------------------------------------------
219
220static gint
aeeb6a44 221selection_clear_clip( GtkWidget *WXUNUSED(widget), GdkEventSelection *event )
fd0eed64 222{
8b53e5a2 223 if (!wxTheClipboard) return TRUE;
2830bf19 224
aeeb6a44
RR
225 if (event->selection == GDK_SELECTION_PRIMARY)
226 {
227 wxTheClipboard->m_ownsPrimarySelection = FALSE;
228 }
229 else
230 if (event->selection == g_clipboardAtom)
231 {
232 wxTheClipboard->m_ownsClipboard = FALSE;
233 }
234 else
235 {
e5ea3f7a 236 wxTheClipboard->m_waiting = FALSE;
aeeb6a44
RR
237 return FALSE;
238 }
239
240 if ((!wxTheClipboard->m_ownsPrimarySelection) &&
241 (!wxTheClipboard->m_ownsClipboard))
242 {
db2d879a 243 /* the clipboard is no longer in our hands. we can the delete clipboard data. */
0d2a2b60
RR
244 if (wxTheClipboard->m_dataBroker)
245 {
246 delete wxTheClipboard->m_dataBroker;
247 wxTheClipboard->m_dataBroker = (wxDataBroker*) NULL;
248 }
aeeb6a44 249 }
fd0eed64 250
e5ea3f7a 251 wxTheClipboard->m_waiting = FALSE;
8b53e5a2 252 return TRUE;
fd0eed64
RR
253}
254
255//-----------------------------------------------------------------------------
256// selection handler for supplying data
257//-----------------------------------------------------------------------------
258
259static void
260selection_handler( GtkWidget *WXUNUSED(widget), GtkSelectionData *selection_data, gpointer WXUNUSED(data) )
261{
8b53e5a2 262 if (!wxTheClipboard) return;
fd0eed64 263
0d2a2b60
RR
264 if (!wxTheClipboard->m_dataBroker) return;
265
266 wxNode *node = wxTheClipboard->m_dataBroker->m_dataObjects.First();
8b53e5a2
RR
267
268 while (node)
269 {
270 wxDataObject *data_object = (wxDataObject *)node->Data();
271
0d2a2b60 272 if (data_object->GetFormat().GetAtom() != selection_data->target)
8b53e5a2
RR
273 {
274 node = node->Next();
3874d10d 275 continue;
8b53e5a2
RR
276 }
277
0d2a2b60 278 switch (data_object->GetFormat().GetType())
8b53e5a2
RR
279 {
280 case wxDF_TEXT:
281 {
282 wxTextDataObject *text_object = (wxTextDataObject*) data_object;
283
284 wxString text = text_object->GetText();
285
93c5dd39
OK
286#if wxUSE_UNICODE
287 const wxWX2MBbuf s = text.mbc_str();
288 int len = strlen(s);
289#else // more efficient in non-Unicode
290 const char *s = text.c_str();
8b53e5a2 291 int len = (int) text.Length();
93c5dd39 292#endif
8b53e5a2
RR
293
294 gtk_selection_data_set(
295 selection_data,
296 GDK_SELECTION_TYPE_STRING,
297 8*sizeof(gchar),
93c5dd39 298 (unsigned char*) (const char*) s,
8b53e5a2
RR
299 len );
300
301 break;
302 }
303
304 case wxDF_BITMAP:
305 {
306 // wxBitmapDataObject *private_object = (wxBitmapDataObject*) data_object;
307
308 // how do we do that ?
309
310 break;
311 }
312
313 case wxDF_PRIVATE:
314 {
315 wxPrivateDataObject *private_object = (wxPrivateDataObject*) data_object;
316
0d2a2b60 317 if (private_object->GetSize() == 0) return;
8b53e5a2
RR
318
319 gtk_selection_data_set(
320 selection_data,
321 GDK_SELECTION_TYPE_STRING,
322 8*sizeof(gchar),
323 (unsigned char*) private_object->GetData(),
0d2a2b60 324 (int) private_object->GetSize() );
8b53e5a2
RR
325 }
326
327 default:
328 break;
329 }
330
331 node = node->Next();
332 }
fd0eed64 333}
dc86cb34
RR
334
335//-----------------------------------------------------------------------------
336// wxClipboard
337//-----------------------------------------------------------------------------
338
339IMPLEMENT_DYNAMIC_CLASS(wxClipboard,wxObject)
340
341wxClipboard::wxClipboard()
342{
8b53e5a2
RR
343 m_open = FALSE;
344
aeeb6a44
RR
345 m_ownsClipboard = FALSE;
346 m_ownsPrimarySelection = FALSE;
347
0d2a2b60 348 m_dataBroker = (wxDataBroker*) NULL;
fd0eed64 349
8b53e5a2 350 m_receivedData = (wxDataObject*) NULL;
99c67c77 351
034be888
RR
352 /* we use m_targetsWidget to query what formats are available */
353
354 m_targetsWidget = gtk_window_new( GTK_WINDOW_POPUP );
355 gtk_widget_realize( m_targetsWidget );
356
357 gtk_signal_connect( GTK_OBJECT(m_targetsWidget),
358 "selection_received",
359 GTK_SIGNAL_FUNC( targets_selection_received ),
360 (gpointer) this );
361
362 /* we use m_clipboardWidget to get and to offer data */
363
8b53e5a2
RR
364 m_clipboardWidget = gtk_window_new( GTK_WINDOW_POPUP );
365 gtk_widget_realize( m_clipboardWidget );
366
034be888
RR
367 gtk_signal_connect( GTK_OBJECT(m_clipboardWidget),
368 "selection_received",
369 GTK_SIGNAL_FUNC( selection_received ),
370 (gpointer) this );
371
8b53e5a2
RR
372 gtk_signal_connect( GTK_OBJECT(m_clipboardWidget),
373 "selection_clear_event",
aeeb6a44 374 GTK_SIGNAL_FUNC( selection_clear_clip ),
8b53e5a2 375 (gpointer) NULL );
fd0eed64 376
8b53e5a2 377 if (!g_clipboardAtom) g_clipboardAtom = gdk_atom_intern( "CLIPBOARD", FALSE );
8b53e5a2
RR
378 if (!g_targetsAtom) g_targetsAtom = gdk_atom_intern ("TARGETS", FALSE);
379
380 m_formatSupported = FALSE;
381 m_targetRequested = 0;
7e2c43b8
RR
382
383 m_usePrimary = FALSE;
dc86cb34
RR
384}
385
386wxClipboard::~wxClipboard()
b527aac5 387{
8b53e5a2 388 Clear();
b527aac5 389
8b53e5a2 390 if (m_clipboardWidget) gtk_widget_destroy( m_clipboardWidget );
034be888 391 if (m_targetsWidget) gtk_widget_destroy( m_targetsWidget );
b527aac5
RR
392}
393
394void wxClipboard::Clear()
dc86cb34 395{
0d2a2b60 396 if (m_dataBroker)
8b53e5a2 397 {
b453e1b2
RR
398#if wxUSE_THREADS
399 /* disable GUI threads */
400 wxapp_uninstall_thread_wakeup();
401#endif
402
8b53e5a2
RR
403 /* As we have data we also own the clipboard. Once we no longer own
404 it, clear_selection is called which will set m_data to zero */
aeeb6a44 405 if (gdk_selection_owner_get( g_clipboardAtom ) == m_clipboardWidget->window)
8b53e5a2 406 {
e5ea3f7a
RR
407 m_waiting = TRUE;
408
8b53e5a2 409 gtk_selection_owner_set( (GtkWidget*) NULL, g_clipboardAtom, GDK_CURRENT_TIME );
e5ea3f7a
RR
410
411 while (m_waiting) gtk_main_iteration();
8b53e5a2 412 }
db1b4961 413
aeeb6a44
RR
414 if (gdk_selection_owner_get( GDK_SELECTION_PRIMARY ) == m_clipboardWidget->window)
415 {
e5ea3f7a
RR
416 m_waiting = TRUE;
417
aeeb6a44 418 gtk_selection_owner_set( (GtkWidget*) NULL, GDK_SELECTION_PRIMARY, GDK_CURRENT_TIME );
e5ea3f7a
RR
419
420 while (m_waiting) gtk_main_iteration();
aeeb6a44
RR
421 }
422
0d2a2b60
RR
423 if (m_dataBroker)
424 {
425 delete m_dataBroker;
426 m_dataBroker = (wxDataBroker*) NULL;
427 }
b453e1b2
RR
428
429#if wxUSE_THREADS
430 /* re-enable GUI threads */
431 wxapp_install_thread_wakeup();
432#endif
8b53e5a2 433 }
b527aac5 434
8b53e5a2 435 m_targetRequested = 0;
b527aac5 436
8b53e5a2
RR
437 m_formatSupported = FALSE;
438}
439
440bool wxClipboard::Open()
441{
93c5dd39 442 wxCHECK_MSG( !m_open, FALSE, _T("clipboard already open") );
b527aac5 443
8b53e5a2 444 m_open = TRUE;
cee6127e 445
8b53e5a2 446 return TRUE;
dc86cb34
RR
447}
448
75ce0581 449bool wxClipboard::SetData( wxDataObject *data )
dc86cb34 450{
93c5dd39 451 wxCHECK_MSG( m_open, FALSE, _T("clipboard not open") );
75ce0581 452
93c5dd39 453 wxCHECK_MSG( data, FALSE, _T("data is invalid") );
db1b4961 454
0d2a2b60 455 Clear();
75ce0581
RR
456
457 return AddData( data );
458}
459
460bool wxClipboard::AddData( wxDataObject *data )
461{
93c5dd39 462 wxCHECK_MSG( m_open, FALSE, _T("clipboard not open") );
0d2a2b60 463
93c5dd39 464 wxCHECK_MSG( data, FALSE, _T("data is invalid") );
2830bf19 465
75ce0581 466 /* if clipboard has been cleared before, create new data broker */
75ce0581 467 if (!m_dataBroker) m_dataBroker = new wxDataBroker();
8b53e5a2 468
75ce0581 469 /* add new data to list of offered data objects */
75ce0581
RR
470 m_dataBroker->Add( data );
471
472 /* get native format id of new data object */
75ce0581 473 GdkAtom format = data->GetFormat().GetAtom();
8b53e5a2 474
93c5dd39 475 wxCHECK_MSG( format, FALSE, _T("data has invalid format") );
75ce0581
RR
476
477 /* This should happen automatically, but to be on the safe side */
75ce0581
RR
478 m_ownsClipboard = FALSE;
479 m_ownsPrimarySelection = FALSE;
aeeb6a44 480
75ce0581 481 /* Add handlers if someone requests data */
d345e841
RR
482
483#if (GTK_MINOR_VERSION > 0)
484
485 gtk_selection_add_target( GTK_WIDGET(m_clipboardWidget),
486 GDK_SELECTION_PRIMARY,
487 format,
488 0 ); /* what is info ? */
489
490 gtk_selection_add_target( GTK_WIDGET(m_clipboardWidget),
491 g_clipboardAtom,
492 format,
493 0 ); /* what is info ? */
494
495 gtk_signal_connect( GTK_OBJECT(m_clipboardWidget),
496 "selection_get",
497 GTK_SIGNAL_FUNC(selection_handler),
498 (gpointer) NULL );
499
500#else
501
75ce0581 502 gtk_selection_add_handler( m_clipboardWidget,
8b53e5a2 503 g_clipboardAtom,
0d2a2b60 504 format,
8b53e5a2 505 selection_handler,
0d2a2b60 506 (gpointer) NULL );
8b53e5a2 507
75ce0581 508 gtk_selection_add_handler( m_clipboardWidget,
aeeb6a44 509 GDK_SELECTION_PRIMARY,
0d2a2b60 510 format,
aeeb6a44 511 selection_handler,
0d2a2b60 512 (gpointer) NULL );
d345e841 513#endif
db2d879a 514
b453e1b2
RR
515#if wxUSE_THREADS
516 /* disable GUI threads */
517 wxapp_uninstall_thread_wakeup();
518#endif
519
75ce0581 520 /* Tell the world we offer clipboard data */
75ce0581 521 if (!gtk_selection_owner_set( m_clipboardWidget,
8b53e5a2
RR
522 g_clipboardAtom,
523 GDK_CURRENT_TIME ))
75ce0581 524 {
b453e1b2
RR
525#if wxUSE_THREADS
526 /* re-enable GUI threads */
527 wxapp_install_thread_wakeup();
528#endif
75ce0581
RR
529 return FALSE;
530 }
531 m_ownsClipboard = TRUE;
aeeb6a44 532
75ce0581 533 if (!gtk_selection_owner_set( m_clipboardWidget,
aeeb6a44
RR
534 GDK_SELECTION_PRIMARY,
535 GDK_CURRENT_TIME ))
75ce0581 536 {
b453e1b2
RR
537#if wxUSE_THREADS
538 /* re-enable GUI threads */
539 wxapp_install_thread_wakeup();
540#endif
75ce0581 541 return FALSE;
aeeb6a44 542 }
75ce0581 543 m_ownsPrimarySelection = TRUE;
b453e1b2
RR
544
545#if wxUSE_THREADS
546 /* re-enable GUI threads */
547 wxapp_install_thread_wakeup();
548#endif
75ce0581 549
8b53e5a2
RR
550 return TRUE;
551}
db1b4961 552
8b53e5a2
RR
553void wxClipboard::Close()
554{
93c5dd39 555 wxCHECK_RET( m_open, _T("clipboard not open") );
8b53e5a2
RR
556
557 m_open = FALSE;
dc86cb34
RR
558}
559
5f699c22 560bool wxClipboard::IsSupported( wxDataFormat format )
b527aac5 561{
93c5dd39 562 wxCHECK_MSG( m_open, FALSE, _T("clipboard not open") );
0d2a2b60 563
75ce0581 564 /* store requested format to be asked for by callbacks */
0d2a2b60 565
5f699c22 566 m_targetRequested = format.GetAtom();
b527aac5 567
93c5dd39 568 wxCHECK_MSG( m_targetRequested, FALSE, _T("invalid clipboard format") );
0d2a2b60 569
8b53e5a2 570 m_formatSupported = FALSE;
b527aac5 571
0d2a2b60 572 /* perform query. this will set m_formatSupported to
034be888
RR
573 TRUE if m_targetRequested is supported.
574 alsom we have to wait for the "answer" from the
575 clipboard owner which is an asynchronous process.
576 therefore we set m_waiting = TRUE here and wait
577 until the callback "targets_selection_received"
578 sets it to FALSE */
579
580 m_waiting = TRUE;
ca35e608 581
034be888 582 gtk_selection_convert( m_targetsWidget,
cee6127e 583 m_usePrimary?GDK_SELECTION_PRIMARY:g_clipboardAtom,
8b53e5a2
RR
584 g_targetsAtom,
585 GDK_CURRENT_TIME );
ca35e608 586
034be888
RR
587 while (m_waiting) gtk_main_iteration();
588
8b53e5a2 589 if (!m_formatSupported) return FALSE;
75ce0581
RR
590
591 return TRUE;
592}
593
5f699c22 594bool wxClipboard::GetData( wxDataObject *data )
75ce0581 595{
93c5dd39 596 wxCHECK_MSG( m_open, FALSE, _T("clipboard not open") );
75ce0581
RR
597
598 /* is data supported by clipboard ? */
599
5f699c22 600 if (!IsSupported( data->GetFormat() )) return FALSE;
75ce0581
RR
601
602 /* store pointer to data object to be filled up by callbacks */
603
5f699c22 604 m_receivedData = data;
75ce0581
RR
605
606 /* store requested format to be asked for by callbacks */
607
5f699c22 608 m_targetRequested = data->GetFormat().GetAtom();
b527aac5 609
93c5dd39 610 wxCHECK_MSG( m_targetRequested, FALSE, _T("invalid clipboard format") );
75ce0581
RR
611
612 /* start query */
8b53e5a2 613
8b53e5a2 614 m_formatSupported = FALSE;
b527aac5 615
034be888
RR
616 /* ask for clipboard contents. this will set
617 m_formatSupported to TRUE if m_targetRequested
618 is supported.
619 also, we have to wait for the "answer" from the
620 clipboard owner which is an asynchronous process.
621 therefore we set m_waiting = TRUE here and wait
622 until the callback "targets_selection_received"
623 sets it to FALSE */
b527aac5 624
034be888 625 m_waiting = TRUE;
75ce0581 626
8b53e5a2 627 gtk_selection_convert( m_clipboardWidget,
cee6127e 628 m_usePrimary?GDK_SELECTION_PRIMARY:g_clipboardAtom,
8b53e5a2
RR
629 m_targetRequested,
630 GDK_CURRENT_TIME );
b527aac5 631
034be888 632 while (m_waiting) gtk_main_iteration();
b527aac5 633
0d2a2b60
RR
634 /* this is a true error as we checked for the presence of such data before */
635
93c5dd39 636 wxCHECK_MSG( m_formatSupported, FALSE, _T("error retrieving data from clipboard") );
8b53e5a2
RR
637
638 return TRUE;
b527aac5
RR
639}
640
b527aac5
RR
641//-----------------------------------------------------------------------------
642// wxClipboardModule
643//-----------------------------------------------------------------------------
644
645IMPLEMENT_DYNAMIC_CLASS(wxClipboardModule,wxModule)
646
647bool wxClipboardModule::OnInit()
648{
8b53e5a2 649 wxTheClipboard = new wxClipboard();
b527aac5 650
8b53e5a2 651 return TRUE;
b527aac5
RR
652}
653
654void wxClipboardModule::OnExit()
dc86cb34 655{
8b53e5a2
RR
656 if (wxTheClipboard) delete wxTheClipboard;
657 wxTheClipboard = (wxClipboard*) NULL;
dc86cb34 658}
ac57418f
RR
659
660#endif
661
662 // wxUSE_CLIPBOARD
663