]> git.saurik.com Git - wxWidgets.git/blame - src/gtk/clipbrd.cpp
removing obsolete contribs (partly moved to wxCode)
[wxWidgets.git] / src / gtk / clipbrd.cpp
CommitLineData
dc86cb34 1/////////////////////////////////////////////////////////////////////////////
e4db172a 2// Name: src/gtk/clipbrd.cpp
06f5d975 3// Purpose: wxClipboard implementation for wxGTK
eddb9644 4// Author: Robert Roebling, Vadim Zeitlin
dc86cb34
RR
5// Id: $Id$
6// Copyright: (c) 1998 Robert Roebling
eddb9644 7// (c) 2007 Vadim Zeitlin
65571936 8// Licence: wxWindows licence
dc86cb34
RR
9/////////////////////////////////////////////////////////////////////////////
10
06f5d975
VZ
11// ============================================================================
12// declarations
13// ============================================================================
14
15// ----------------------------------------------------------------------------
16// headers
17// ----------------------------------------------------------------------------
18
14f355c2
VS
19// For compilers that support precompilation, includes "wx.h".
20#include "wx/wxprec.h"
21
e4db172a
WS
22#if wxUSE_CLIPBOARD
23
dc86cb34
RR
24#include "wx/clipbrd.h"
25
e4db172a
WS
26#ifndef WX_PRECOMP
27 #include "wx/log.h"
de6185e2 28 #include "wx/utils.h"
28f92d74 29 #include "wx/dataobj.h"
e4db172a 30#endif
ac57418f 31
eddb9644 32#include "wx/ptr_scpd.h"
06f5d975
VZ
33#include "wx/scopeguard.h"
34
67756da4 35#include "wx/gtk/private.h"
83624f79 36
eddb9644
VZ
37wxDECLARE_SCOPED_ARRAY(wxDataFormat, wxDataFormatArray)
38wxDEFINE_SCOPED_ARRAY(wxDataFormat, wxDataFormatArray)
39
40// ----------------------------------------------------------------------------
dc86cb34 41// data
eddb9644 42// ----------------------------------------------------------------------------
dc86cb34 43
06f5d975
VZ
44static GdkAtom g_clipboardAtom = 0;
45static GdkAtom g_targetsAtom = 0;
46static GdkAtom g_timestampAtom = 0;
fd0eed64 47
5e081315 48#if wxUSE_UNICODE
c7d6d883
RR
49extern GdkAtom g_altTextAtom;
50#endif
51
61b04ac6
VZ
52// the trace mask we use with wxLogTrace() - call
53// wxLog::AddTraceMask(TRACE_CLIPBOARD) to enable the trace messages from here
54// (there will be a *lot* of them!)
1457f12c 55#define TRACE_CLIPBOARD _T("clipboard")
61b04ac6 56
06f5d975
VZ
57// ----------------------------------------------------------------------------
58// wxClipboardSync: used to perform clipboard operations synchronously
59// ----------------------------------------------------------------------------
b527aac5 60
06f5d975
VZ
61// constructing this object on stack will wait wait until the latest clipboard
62// operation is finished on block exit
63//
64// notice that there can be no more than one such object alive at any moment,
65// i.e. reentrancies are not allowed
66class wxClipboardSync
dc86cb34 67{
06f5d975
VZ
68public:
69 wxClipboardSync(wxClipboard& clipboard)
70 {
71 wxASSERT_MSG( !ms_clipboard, _T("reentrancy in clipboard code") );
72 ms_clipboard = &clipboard;
73 }
74
75 ~wxClipboardSync()
76 {
77 while ( ms_clipboard )
78 gtk_main_iteration();
79 }
80
81 // this method must be called by GTK+ callbacks to indicate that we got the
82 // result for our clipboard operation
83 static void OnDone(wxClipboard *clipboard)
84 {
85 wxASSERT_MSG( clipboard == ms_clipboard,
86 _T("got notification for alien clipboard") );
87
88 ms_clipboard = NULL;
89 }
90
91private:
92 static wxClipboard *ms_clipboard;
93
94 DECLARE_NO_COPY_CLASS(wxClipboardSync)
b527aac5
RR
95};
96
06f5d975 97wxClipboard *wxClipboardSync::ms_clipboard = NULL;
dc86cb34 98
eddb9644
VZ
99// ============================================================================
100// clipboard ca;backs implementation
101// ============================================================================
102
b527aac5
RR
103//-----------------------------------------------------------------------------
104// "selection_received" for targets
105//-----------------------------------------------------------------------------
106
865bb325 107extern "C" {
b527aac5 108static void
270c23f7
VZ
109targets_selection_received( GtkWidget *WXUNUSED(widget),
110 GtkSelectionData *selection_data,
034be888 111 guint32 WXUNUSED(time),
66633398 112 wxClipboard *clipboard )
dc86cb34 113{
eddb9644
VZ
114 if ( !clipboard )
115 return;
116
06f5d975
VZ
117 wxON_BLOCK_EXIT1(wxClipboardSync::OnDone, clipboard);
118
eddb9644
VZ
119 if ( !selection_data || selection_data->length <= 0 )
120 return;
121
122 // make sure we got the data in the correct form
123 GdkAtom type = selection_data->type;
124 if ( type != GDK_SELECTION_TYPE_ATOM )
034be888 125 {
eddb9644 126 if ( strcmp(wxGtkString(gdk_atom_name(type)), "TARGETS") != 0 )
270c23f7 127 {
eddb9644
VZ
128 wxLogTrace( TRACE_CLIPBOARD,
129 _T("got unsupported clipboard target") );
61b04ac6 130
eddb9644 131 return;
270c23f7 132 }
eddb9644 133 }
b527aac5 134
61b04ac6 135#ifdef __WXDEBUG__
eddb9644
VZ
136 // it's not really a format, of course, but we can reuse its GetId() method
137 // to format this atom as string
138 wxDataFormat clip(selection_data->selection);
139 wxLogTrace( TRACE_CLIPBOARD,
140 wxT("Received available formats for clipboard %s"),
141 clip.GetId().c_str() );
61b04ac6 142#endif // __WXDEBUG__
270c23f7 143
eddb9644
VZ
144 // the atoms we received, holding a list of targets (= formats)
145 const GdkAtom * const atoms = (GdkAtom *)selection_data->data;
146 for ( size_t i = 0; i < selection_data->length/sizeof(GdkAtom); i++ )
147 {
148 const wxDataFormat format(atoms[i]);
11e1c70d 149
eddb9644 150 wxLogTrace(TRACE_CLIPBOARD, wxT("\t%s"), format.GetId().c_str());
270c23f7 151
eddb9644
VZ
152 if ( clipboard->GTKOnTargetReceived(format) )
153 return;
8b53e5a2 154 }
dc86cb34 155}
865bb325 156}
dc86cb34 157
eddb9644
VZ
158bool wxClipboard::GTKOnTargetReceived(const wxDataFormat& format)
159{
160 if ( format != m_targetRequested )
161 return false;
162
163 m_formatSupported = true;
164 return true;
165}
166
dc86cb34 167//-----------------------------------------------------------------------------
b527aac5 168// "selection_received" for the actual data
dc86cb34
RR
169//-----------------------------------------------------------------------------
170
865bb325 171extern "C" {
270c23f7
VZ
172static void
173selection_received( GtkWidget *WXUNUSED(widget),
174 GtkSelectionData *selection_data,
034be888 175 guint32 WXUNUSED(time),
66633398 176 wxClipboard *clipboard )
dc86cb34 177{
eddb9644 178 if ( !clipboard )
034be888 179 return;
270c23f7 180
eddb9644 181 wxON_BLOCK_EXIT1(wxClipboardSync::OnDone, clipboard);
270c23f7 182
eddb9644 183 if ( !selection_data || selection_data->length <= 0 )
e5d6aa22 184 return;
270c23f7 185
eddb9644 186 clipboard->GTKOnSelectionReceived(*selection_data);
dc86cb34 187}
865bb325 188}
fd0eed64
RR
189
190//-----------------------------------------------------------------------------
191// "selection_clear"
192//-----------------------------------------------------------------------------
193
865bb325 194extern "C" {
fd0eed64 195static gint
aeeb6a44 196selection_clear_clip( GtkWidget *WXUNUSED(widget), GdkEventSelection *event )
fd0eed64 197{
eddb9644
VZ
198 wxClipboard * const clipboard = wxTheClipboard;
199 if ( !clipboard )
200 return TRUE;
06f5d975 201
eddb9644 202 wxON_BLOCK_EXIT1(wxClipboardSync::OnDone, clipboard);
270c23f7 203
eddb9644 204 wxClipboard::Kind kind;
aeeb6a44
RR
205 if (event->selection == GDK_SELECTION_PRIMARY)
206 {
eddb9644
VZ
207 wxLogTrace(TRACE_CLIPBOARD, wxT("Lost primary selection" ));
208
209 kind = wxClipboard::Primary;
aeeb6a44 210 }
eddb9644 211 else if (event->selection == g_clipboardAtom)
aeeb6a44 212 {
eddb9644
VZ
213 wxLogTrace(TRACE_CLIPBOARD, wxT("Lost clipboard" ));
214
215 kind = wxClipboard::Clipboard;
aeeb6a44 216 }
eddb9644 217 else // some other selection, we're not concerned
aeeb6a44
RR
218 {
219 return FALSE;
220 }
270c23f7 221
eddb9644
VZ
222 // the clipboard is no longer in our hands, we don't need data any more
223 clipboard->GTKClearData(kind);
270c23f7 224
8b53e5a2 225 return TRUE;
fd0eed64 226}
865bb325 227}
fd0eed64
RR
228
229//-----------------------------------------------------------------------------
230// selection handler for supplying data
231//-----------------------------------------------------------------------------
232
865bb325 233extern "C" {
fd0eed64 234static void
19d89516
VZ
235selection_handler( GtkWidget *WXUNUSED(widget),
236 GtkSelectionData *selection_data,
237 guint WXUNUSED(info),
238 guint WXUNUSED(time),
d394f0c9 239 gpointer signal_data )
fd0eed64 240{
eddb9644
VZ
241 wxClipboard * const clipboard = wxTheClipboard;
242 if ( !clipboard )
243 return;
270c23f7 244
eddb9644
VZ
245 wxDataObject * const data = clipboard->GTKGetDataObject();
246 if ( !data )
247 return;
270c23f7 248
d394f0c9
MR
249 // ICCCM says that TIMESTAMP is a required atom.
250 // In particular, it satisfies Klipper, which polls
251 // TIMESTAMP to see if the clipboards content has changed.
252 // It shall return the time which was used to set the data.
253 if (selection_data->target == g_timestampAtom)
254 {
d704d2f5 255 guint timestamp = GPOINTER_TO_UINT (signal_data);
d394f0c9
MR
256 gtk_selection_data_set(selection_data,
257 GDK_SELECTION_TYPE_INTEGER,
258 32,
259 (guchar*)&(timestamp),
260 sizeof(timestamp));
261 wxLogTrace(TRACE_CLIPBOARD,
262 _T("Clipboard TIMESTAMP requested, returning timestamp=%u"),
263 timestamp);
264 return;
265 }
266
b068c4e8
RR
267 wxDataFormat format( selection_data->target );
268
ebe47451
VS
269#ifdef __WXDEBUG__
270 wxLogTrace(TRACE_CLIPBOARD,
d394f0c9 271 _T("clipboard data in format %s, GtkSelectionData is target=%s type=%s selection=%s timestamp=%u"),
ebe47451 272 format.GetId().c_str(),
67756da4
MR
273 wxString::FromAscii(wxGtkString(gdk_atom_name(selection_data->target))).c_str(),
274 wxString::FromAscii(wxGtkString(gdk_atom_name(selection_data->type))).c_str(),
275 wxString::FromAscii(wxGtkString(gdk_atom_name(selection_data->selection))).c_str(),
d394f0c9 276 GPOINTER_TO_UINT( signal_data )
ebe47451
VS
277 );
278#endif
3d257b8d 279
b068c4e8 280 if (!data->IsSupportedFormat( format )) return;
270c23f7 281
b068c4e8 282 int size = data->GetDataSize( format );
270c23f7 283
1dd989e1 284 if (size == 0) return;
270c23f7 285
33754c4d 286 void *d = malloc(size);
eddb9644 287 wxON_BLOCK_EXIT1(free, d);
33754c4d 288
ca11abde 289 // Text data will be in UTF8 in Unicode mode.
33754c4d 290 data->GetDataHere( selection_data->target, d );
270c23f7 291
ebe47451
VS
292 // NB: GTK+ requires special treatment of UTF8_STRING data, the text
293 // would show as UTF-8 data interpreted as latin1 (?) in other
294 // GTK+ apps if we used gtk_selection_data_set()
295 if (format == wxDataFormat(wxDF_UNICODETEXT))
296 {
297 gtk_selection_data_set_text(
298 selection_data,
299 (const gchar*)d,
2c906a49 300 size );
ebe47451
VS
301 }
302 else
ebe47451
VS
303 {
304 gtk_selection_data_set(
305 selection_data,
306 GDK_SELECTION_TYPE_STRING,
307 8*sizeof(gchar),
308 (unsigned char*) d,
2c906a49 309 size );
ebe47451 310 }
fd0eed64 311}
865bb325 312}
dc86cb34 313
eddb9644
VZ
314void wxClipboard::GTKOnSelectionReceived(const GtkSelectionData& sel)
315{
316 wxCHECK_RET( m_receivedData, _T("should be inside GetData()") );
317
318 const wxDataFormat format(sel.target);
319 wxLogTrace(TRACE_CLIPBOARD, _T("Received selection %s"),
320 format.GetId().c_str());
321
322 if ( !m_receivedData->IsSupportedFormat(format) )
323 return;
324
325 m_receivedData->SetData(format, sel.length, sel.data);
326 m_formatSupported = true;
327}
328
329// ============================================================================
330// wxClipboard implementation
331// ============================================================================
332
333// ----------------------------------------------------------------------------
334// wxClipboard ctor/dtor
335// ----------------------------------------------------------------------------
dc86cb34
RR
336
337IMPLEMENT_DYNAMIC_CLASS(wxClipboard,wxObject)
338
339wxClipboard::wxClipboard()
340{
de6185e2 341 m_open = false;
8b53e5a2 342
eddb9644
VZ
343 m_dataPrimary =
344 m_dataClipboard =
345 m_receivedData = NULL;
aeeb6a44 346
eddb9644
VZ
347 m_formatSupported = false;
348 m_targetRequested = 0;
99c67c77 349
eddb9644 350 // we use m_targetsWidget to query what formats are available
034be888
RR
351 m_targetsWidget = gtk_window_new( GTK_WINDOW_POPUP );
352 gtk_widget_realize( m_targetsWidget );
353
9fa72bd2
MR
354 g_signal_connect (m_targetsWidget, "selection_received",
355 G_CALLBACK (targets_selection_received), this);
270c23f7 356
eddb9644 357 // we use m_clipboardWidget to get and to offer data
8b53e5a2
RR
358 m_clipboardWidget = gtk_window_new( GTK_WINDOW_POPUP );
359 gtk_widget_realize( m_clipboardWidget );
360
9fa72bd2
MR
361 g_signal_connect (m_clipboardWidget, "selection_received",
362 G_CALLBACK (selection_received), this);
034be888 363
9fa72bd2
MR
364 g_signal_connect (m_clipboardWidget, "selection_clear_event",
365 G_CALLBACK (selection_clear_clip), NULL);
270c23f7 366
eddb9644
VZ
367 // initialize atoms we use if not done yet
368 if ( !g_clipboardAtom )
369 g_clipboardAtom = gdk_atom_intern( "CLIPBOARD", FALSE );
370 if ( !g_targetsAtom )
371 g_targetsAtom = gdk_atom_intern ("TARGETS", FALSE);
372 if ( !g_timestampAtom )
373 g_timestampAtom = gdk_atom_intern ("TIMESTAMP", FALSE);
dc86cb34
RR
374}
375
376wxClipboard::~wxClipboard()
b527aac5 377{
270c23f7
VZ
378 Clear();
379
eddb9644
VZ
380 if ( m_clipboardWidget )
381 gtk_widget_destroy( m_clipboardWidget );
382 if ( m_targetsWidget )
383 gtk_widget_destroy( m_targetsWidget );
b527aac5
RR
384}
385
eddb9644
VZ
386// ----------------------------------------------------------------------------
387// wxClipboard helper functions
388// ----------------------------------------------------------------------------
389
390GdkAtom wxClipboard::GTKGetClipboardAtom() const
391{
392 return m_usePrimary ? (GdkAtom)GDK_SELECTION_PRIMARY
393 : g_clipboardAtom;
394}
395
396void wxClipboard::GTKClearData(Kind kind)
dc86cb34 397{
eddb9644
VZ
398 wxDataObject *&data = Data();
399 if ( data )
1dd989e1 400 {
eddb9644
VZ
401 delete data;
402 data = NULL;
403 }
404}
270c23f7 405
eddb9644
VZ
406bool wxClipboard::SetSelectionOwner(bool set)
407{
408 bool rc = gtk_selection_owner_set
409 (
410 set ? m_clipboardWidget : NULL,
411 GTKGetClipboardAtom(),
412 (guint32)GDK_CURRENT_TIME
413 );
414
415 if ( !rc )
416 {
417 wxLogTrace(TRACE_CLIPBOARD, _T("Failed to %sset selection owner"),
418 set ? _T("") : _T("un"));
419 }
270c23f7 420
eddb9644
VZ
421 return rc;
422}
270c23f7 423
eddb9644
VZ
424void wxClipboard::AddSupportedTarget(GdkAtom atom)
425{
426 gtk_selection_add_target
427 (
428 GTK_WIDGET(m_clipboardWidget),
429 GTKGetClipboardAtom(),
430 atom,
431 0 // info (same as client data) unused
432 );
433}
434
435bool wxClipboard::DoIsSupported(const wxDataFormat& format)
436{
437 wxCHECK_MSG( format, false, wxT("invalid clipboard format") );
270c23f7 438
eddb9644
VZ
439 wxLogTrace(TRACE_CLIPBOARD, wxT("Checking if format %s is available"),
440 format.GetId().c_str());
441
442 // these variables will be used by our GTKOnTargetReceived()
443 m_targetRequested = format;
444 m_formatSupported = false;
445
446 // block until m_formatSupported is set from targets_selection_received
447 // callback
448 {
449 wxClipboardSync sync(*this);
450
451 gtk_selection_convert( m_targetsWidget,
452 GTKGetClipboardAtom(),
453 g_targetsAtom,
454 (guint32) GDK_CURRENT_TIME );
455 }
456
457 return m_formatSupported;
458}
459
460// ----------------------------------------------------------------------------
461// wxClipboard public API implementation
462// ----------------------------------------------------------------------------
463
464void wxClipboard::Clear()
465{
466 if ( gdk_selection_owner_get(GTKGetClipboardAtom()) ==
467 m_clipboardWidget->window )
468 {
469 wxClipboardSync sync(*this);
470
471 // this will result in selection_clear_clip callback being called and
472 // it will free our data
473 SetSelectionOwner(false);
8b53e5a2 474 }
270c23f7 475
8b53e5a2 476 m_targetRequested = 0;
de6185e2 477 m_formatSupported = false;
8b53e5a2
RR
478}
479
480bool wxClipboard::Open()
481{
de6185e2 482 wxCHECK_MSG( !m_open, false, wxT("clipboard already open") );
270c23f7 483
de6185e2 484 m_open = true;
270c23f7 485
de6185e2 486 return true;
dc86cb34
RR
487}
488
75ce0581 489bool wxClipboard::SetData( wxDataObject *data )
dc86cb34 490{
de6185e2 491 wxCHECK_MSG( m_open, false, wxT("clipboard not open") );
270c23f7 492
de6185e2 493 wxCHECK_MSG( data, false, wxT("data is invalid") );
270c23f7 494
0d2a2b60 495 Clear();
75ce0581
RR
496
497 return AddData( data );
498}
499
500bool wxClipboard::AddData( wxDataObject *data )
501{
de6185e2 502 wxCHECK_MSG( m_open, false, wxT("clipboard not open") );
270c23f7 503
de6185e2 504 wxCHECK_MSG( data, false, wxT("data is invalid") );
270c23f7 505
eddb9644 506 // we can only store one wxDataObject so clear the old one
1dd989e1 507 Clear();
270c23f7 508
eddb9644 509 Data() = data;
1dd989e1 510
ca11abde 511 // get formats from wxDataObjects
eddb9644
VZ
512 const size_t count = data->GetFormatCount();
513 wxDataFormatArray formats(new wxDataFormat[count]);
514 data->GetAllFormats(formats.get());
11e1c70d 515
eddb9644
VZ
516 // always provide TIMESTAMP as a target, see comments in selection_handler
517 // for explanation
518 AddSupportedTarget(g_timestampAtom);
11e1c70d 519
eddb9644 520 for ( size_t i = 0; i < count; i++ )
b068c4e8 521 {
eddb9644 522 const wxDataFormat format(formats[i]);
11e1c70d 523
eddb9644
VZ
524 wxLogTrace(TRACE_CLIPBOARD, wxT("Adding support for %s"),
525 format.GetId().c_str());
3d257b8d 526
eddb9644 527 AddSupportedTarget(format);
b068c4e8
RR
528 }
529
9fa72bd2 530 g_signal_connect (m_clipboardWidget, "selection_get",
d394f0c9
MR
531 G_CALLBACK (selection_handler),
532 GUINT_TO_POINTER (gtk_get_current_event_time()) );
d345e841 533
eddb9644
VZ
534 // tell the world we offer clipboard data
535 return SetSelectionOwner();
8b53e5a2 536}
db1b4961 537
8b53e5a2
RR
538void wxClipboard::Close()
539{
223d09f6 540 wxCHECK_RET( m_open, wxT("clipboard not open") );
270c23f7 541
de6185e2 542 m_open = false;
dc86cb34
RR
543}
544
f536e0f2
VZ
545bool wxClipboard::IsOpened() const
546{
547 return m_open;
548}
549
e1ee679c 550bool wxClipboard::IsSupported( const wxDataFormat& format )
b527aac5 551{
eddb9644
VZ
552 if ( DoIsSupported(format) )
553 return true;
270c23f7 554
5e081315 555#if wxUSE_UNICODE
eddb9644 556 if ( format == wxDF_UNICODETEXT )
c7d6d883 557 {
eddb9644
VZ
558 // also with plain STRING format
559 return DoIsSupported(g_altTextAtom);
c7d6d883 560 }
eddb9644 561#endif // wxUSE_UNICODE
c7d6d883 562
eddb9644 563 return false;
270c23f7
VZ
564}
565
e1ee679c 566bool wxClipboard::GetData( wxDataObject& data )
75ce0581 567{
de6185e2 568 wxCHECK_MSG( m_open, false, wxT("clipboard not open") );
270c23f7 569
eddb9644
VZ
570 // get all supported formats from wxDataObjects
571 const size_t count = data.GetFormatCount();
572 wxDataFormatArray formats(new wxDataFormat[count]);
573 data.GetAllFormats(formats.get());
270c23f7 574
eddb9644 575 for ( size_t i = 0; i < count; i++ )
b068c4e8 576 {
eddb9644 577 const wxDataFormat format(formats[i]);
11e1c70d 578
eddb9644
VZ
579 // is this format supported by clipboard ?
580 if ( !DoIsSupported(format) )
581 continue;
270c23f7 582
eddb9644
VZ
583 wxLogTrace(TRACE_CLIPBOARD, wxT("Requesting format %s"),
584 format.GetId().c_str());
270c23f7 585
eddb9644 586 // these variables will be used by our GTKOnSelectionReceived()
b068c4e8 587 m_receivedData = &data;
de6185e2 588 m_formatSupported = false;
270c23f7 589
06f5d975
VZ
590 {
591 wxClipboardSync sync(*this);
592
eddb9644
VZ
593 gtk_selection_convert(m_clipboardWidget,
594 GTKGetClipboardAtom(),
595 format,
596 (guint32) GDK_CURRENT_TIME );
06f5d975 597 } // wait until we get the results
b527aac5 598
be809e82
VZ
599 /*
600 Normally this is a true error as we checked for the presence of such
601 data before, but there are applications that may return an empty
602 string (e.g. Gnumeric-1.6.1 on Linux if an empty cell is copied)
603 which would produce a false error message here, so we check for the
eddb9644 604 size of the string first. With ANSI, GetDataSize returns an extra
be809e82 605 value (for the closing null?), with unicode, the exact number of
eddb9644 606 tokens is given (that is more than 1 for non-ASCII characters)
be809e82
VZ
607 (tested with Gnumeric-1.6.1 and OpenOffice.org-2.0.2)
608 */
609#if wxUSE_UNICODE
610 if ( format != wxDF_UNICODETEXT || data.GetDataSize(format) > 0 )
611#else // !UNICODE
612 if ( format != wxDF_TEXT || data.GetDataSize(format) > 1 )
613#endif // UNICODE / !UNICODE
614 {
615 wxCHECK_MSG( m_formatSupported, false,
616 wxT("error retrieving data from clipboard") );
617 }
270c23f7 618
de6185e2 619 return true;
b068c4e8 620 }
270c23f7 621
eddb9644 622 wxLogTrace(TRACE_CLIPBOARD, wxT("GetData(): format not found"));
270c23f7 623
de6185e2 624 return false;
b527aac5
RR
625}
626
eddb9644 627#endif // wxUSE_CLIPBOARD