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