]> git.saurik.com Git - wxWidgets.git/blame - src/gtk1/clipbrd.cpp
fixed wxXmlDocument::Save() to interpret the indentstep argument correctly
[wxWidgets.git] / src / gtk1 / clipbrd.cpp
CommitLineData
dc86cb34 1/////////////////////////////////////////////////////////////////////////////
e4db172a 2// Name: src/gtk1/clipbrd.cpp
dc86cb34
RR
3// Purpose:
4// Author: Robert Roebling
5// Id: $Id$
6// Copyright: (c) 1998 Robert Roebling
65571936 7// Licence: wxWindows licence
dc86cb34
RR
8/////////////////////////////////////////////////////////////////////////////
9
14f355c2
VS
10// For compilers that support precompilation, includes "wx.h".
11#include "wx/wxprec.h"
12
e4db172a
WS
13#if wxUSE_CLIPBOARD
14
dc86cb34
RR
15#include "wx/clipbrd.h"
16
e4db172a
WS
17#ifndef WX_PRECOMP
18 #include "wx/log.h"
de6185e2 19 #include "wx/utils.h"
28f92d74 20 #include "wx/dataobj.h"
e4db172a 21#endif
ac57418f 22
071a2d78
RR
23#include <glib.h>
24#include <gdk/gdk.h>
25#include <gtk/gtk.h>
83624f79 26
dc86cb34
RR
27//-----------------------------------------------------------------------------
28// data
29//-----------------------------------------------------------------------------
30
fd0eed64 31GdkAtom g_clipboardAtom = 0;
b527aac5 32GdkAtom g_targetsAtom = 0;
d394f0c9 33GdkAtom g_timestampAtom = 0;
fd0eed64 34
61b04ac6
VZ
35// the trace mask we use with wxLogTrace() - call
36// wxLog::AddTraceMask(TRACE_CLIPBOARD) to enable the trace messages from here
37// (there will be a *lot* of them!)
cb1b8d41 38#define TRACE_CLIPBOARD "clipboard"
61b04ac6 39
dc86cb34 40//-----------------------------------------------------------------------------
b527aac5 41// reminder
dc86cb34
RR
42//-----------------------------------------------------------------------------
43
b527aac5 44/* The contents of a selection are returned in a GtkSelectionData
270c23f7 45 structure. selection/target identify the request.
b527aac5
RR
46 type specifies the type of the return; if length < 0, and
47 the data should be ignored. This structure has object semantics -
48 no fields should be modified directly, they should not be created
49 directly, and pointers to them should not be stored beyond the duration of
50 a callback. (If the last is changed, we'll need to add reference
51 counting)
52
53struct _GtkSelectionData
dc86cb34 54{
b527aac5
RR
55 GdkAtom selection;
56 GdkAtom target;
57 GdkAtom type;
61b04ac6 58 gint format;
b527aac5 59 guchar *data;
61b04ac6 60 gint length;
b527aac5
RR
61};
62
63*/
dc86cb34 64
b527aac5
RR
65//-----------------------------------------------------------------------------
66// "selection_received" for targets
67//-----------------------------------------------------------------------------
68
865bb325 69extern "C" {
b527aac5 70static void
270c23f7
VZ
71targets_selection_received( GtkWidget *WXUNUSED(widget),
72 GtkSelectionData *selection_data,
034be888 73 guint32 WXUNUSED(time),
66633398 74 wxClipboard *clipboard )
dc86cb34 75{
270c23f7 76 if ( wxTheClipboard && selection_data->length > 0 )
034be888 77 {
ca11abde 78 // make sure we got the data in the correct form
270c23f7
VZ
79 GdkAtom type = selection_data->type;
80 if ( type != GDK_SELECTION_TYPE_ATOM )
81 {
d394f0c9
MR
82 gchar* atom_name = gdk_atom_name(type);
83 if ( strcmp(atom_name, "TARGETS") )
61b04ac6
VZ
84 {
85 wxLogTrace( TRACE_CLIPBOARD,
9a83f860 86 wxT("got unsupported clipboard target") );
61b04ac6 87
de6185e2 88 clipboard->m_waiting = false;
d394f0c9 89 g_free(atom_name);
61b04ac6
VZ
90 return;
91 }
d394f0c9 92 g_free(atom_name);
270c23f7 93 }
b527aac5 94
270c23f7 95 wxDataFormat clip( selection_data->selection );
61b04ac6
VZ
96 wxLogTrace( TRACE_CLIPBOARD,
97 wxT("selection received for targets, clipboard %s"),
98 clip.GetId().c_str() );
270c23f7
VZ
99
100 // the atoms we received, holding a list of targets (= formats)
101 GdkAtom *atoms = (GdkAtom *)selection_data->data;
11e1c70d 102
270c23f7 103 for (unsigned int i=0; i<selection_data->length/sizeof(GdkAtom); i++)
8b53e5a2 104 {
270c23f7
VZ
105 wxDataFormat format( atoms[i] );
106
61b04ac6
VZ
107 wxLogTrace( TRACE_CLIPBOARD,
108 wxT("selection received for targets, format %s"),
109 format.GetId().c_str() );
270c23f7 110
3d257b8d 111// printf( "format %s requested %s\n",
ca11abde
RR
112// gdk_atom_name( atoms[i] ),
113// gdk_atom_name( clipboard->m_targetRequested ) );
114
270c23f7
VZ
115 if (format == clipboard->m_targetRequested)
116 {
de6185e2
WS
117 clipboard->m_waiting = false;
118 clipboard->m_formatSupported = true;
270c23f7
VZ
119 return;
120 }
8b53e5a2
RR
121 }
122 }
b527aac5 123
de6185e2 124 clipboard->m_waiting = false;
dc86cb34 125}
865bb325 126}
dc86cb34
RR
127
128//-----------------------------------------------------------------------------
b527aac5 129// "selection_received" for the actual data
dc86cb34
RR
130//-----------------------------------------------------------------------------
131
865bb325 132extern "C" {
270c23f7
VZ
133static void
134selection_received( GtkWidget *WXUNUSED(widget),
135 GtkSelectionData *selection_data,
034be888 136 guint32 WXUNUSED(time),
66633398 137 wxClipboard *clipboard )
dc86cb34 138{
034be888
RR
139 if (!wxTheClipboard)
140 {
de6185e2 141 clipboard->m_waiting = false;
034be888
RR
142 return;
143 }
270c23f7 144
8b53e5a2 145 wxDataObject *data_object = clipboard->m_receivedData;
1dd989e1 146
034be888
RR
147 if (!data_object)
148 {
de6185e2 149 clipboard->m_waiting = false;
034be888
RR
150 return;
151 }
270c23f7 152
034be888
RR
153 if (selection_data->length <= 0)
154 {
de6185e2 155 clipboard->m_waiting = false;
034be888
RR
156 return;
157 }
270c23f7 158
b068c4e8 159 wxDataFormat format( selection_data->target );
270c23f7 160
ca11abde 161 // make sure we got the data in the correct format
b068c4e8 162 if (!data_object->IsSupportedFormat( format ) )
034be888 163 {
de6185e2 164 clipboard->m_waiting = false;
034be888
RR
165 return;
166 }
e2acb9ae 167
c7d6d883
RR
168#if 0
169 This seems to cause problems somehow
170 // make sure we got the data in the correct form (selection type).
171 // if so, copy data to target object
e5d6aa22 172 if (selection_data->type != GDK_SELECTION_TYPE_STRING)
8b53e5a2 173 {
de6185e2 174 clipboard->m_waiting = false;
e5d6aa22 175 return;
8b53e5a2 176 }
c7d6d883 177#endif
270c23f7 178
e5d6aa22 179 data_object->SetData( format, (size_t) selection_data->length, (const char*) selection_data->data );
270c23f7 180
de6185e2
WS
181 wxTheClipboard->m_formatSupported = true;
182 clipboard->m_waiting = false;
dc86cb34 183}
865bb325 184}
fd0eed64
RR
185
186//-----------------------------------------------------------------------------
187// "selection_clear"
188//-----------------------------------------------------------------------------
189
865bb325 190extern "C" {
fd0eed64 191static gint
aeeb6a44 192selection_clear_clip( GtkWidget *WXUNUSED(widget), GdkEventSelection *event )
fd0eed64 193{
8b53e5a2 194 if (!wxTheClipboard) return TRUE;
270c23f7 195
aeeb6a44
RR
196 if (event->selection == GDK_SELECTION_PRIMARY)
197 {
de6185e2 198 wxTheClipboard->m_ownsPrimarySelection = false;
aeeb6a44
RR
199 }
200 else
201 if (event->selection == g_clipboardAtom)
202 {
de6185e2 203 wxTheClipboard->m_ownsClipboard = false;
aeeb6a44
RR
204 }
205 else
206 {
de6185e2 207 wxTheClipboard->m_waiting = false;
aeeb6a44
RR
208 return FALSE;
209 }
270c23f7 210
aeeb6a44
RR
211 if ((!wxTheClipboard->m_ownsPrimarySelection) &&
212 (!wxTheClipboard->m_ownsClipboard))
213 {
db2d879a 214 /* the clipboard is no longer in our hands. we can the delete clipboard data. */
1dd989e1 215 if (wxTheClipboard->m_data)
66633398 216 {
47cf53ef 217 wxLogTrace(TRACE_CLIPBOARD, wxT("wxClipboard will get cleared" ));
270c23f7 218
66633398 219 delete wxTheClipboard->m_data;
d3b9f782 220 wxTheClipboard->m_data = NULL;
66633398 221 }
aeeb6a44 222 }
270c23f7 223
de6185e2 224 wxTheClipboard->m_waiting = false;
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{
8b53e5a2 241 if (!wxTheClipboard) return;
270c23f7 242
1dd989e1 243 if (!wxTheClipboard->m_data) return;
270c23f7 244
1dd989e1 245 wxDataObject *data = wxTheClipboard->m_data;
270c23f7 246
d394f0c9
MR
247 // ICCCM says that TIMESTAMP is a required atom.
248 // In particular, it satisfies Klipper, which polls
249 // TIMESTAMP to see if the clipboards content has changed.
250 // It shall return the time which was used to set the data.
251 if (selection_data->target == g_timestampAtom)
252 {
d704d2f5 253 guint timestamp = GPOINTER_TO_UINT (signal_data);
d394f0c9
MR
254 gtk_selection_data_set(selection_data,
255 GDK_SELECTION_TYPE_INTEGER,
256 32,
257 (guchar*)&(timestamp),
258 sizeof(timestamp));
259 wxLogTrace(TRACE_CLIPBOARD,
9a83f860 260 wxT("Clipboard TIMESTAMP requested, returning timestamp=%u"),
d394f0c9
MR
261 timestamp);
262 return;
263 }
264
b068c4e8
RR
265 wxDataFormat format( selection_data->target );
266
ebe47451 267 wxLogTrace(TRACE_CLIPBOARD,
9a83f860 268 wxT("clipboard data in format %s, GtkSelectionData is target=%s type=%s selection=%s timestamp=%u"),
ebe47451
VS
269 format.GetId().c_str(),
270 wxString::FromAscii(gdk_atom_name(selection_data->target)).c_str(),
271 wxString::FromAscii(gdk_atom_name(selection_data->type)).c_str(),
d394f0c9
MR
272 wxString::FromAscii(gdk_atom_name(selection_data->selection)).c_str(),
273 GPOINTER_TO_UINT( signal_data )
ebe47451 274 );
3d257b8d 275
b068c4e8 276 if (!data->IsSupportedFormat( format )) return;
270c23f7 277
b068c4e8 278 int size = data->GetDataSize( format );
270c23f7 279
1dd989e1 280 if (size == 0) return;
270c23f7 281
33754c4d
VZ
282 void *d = malloc(size);
283
ca11abde 284 // Text data will be in UTF8 in Unicode mode.
33754c4d 285 data->GetDataHere( selection_data->target, d );
270c23f7 286
3cbab641 287 gtk_selection_data_set(
ebe47451
VS
288 selection_data,
289 GDK_SELECTION_TYPE_STRING,
3cbab641 290 8 * sizeof(gchar),
ebe47451 291 (unsigned char*) d,
2c906a49 292 size );
33754c4d
VZ
293
294 free(d);
fd0eed64 295}
865bb325 296}
dc86cb34
RR
297
298//-----------------------------------------------------------------------------
299// wxClipboard
300//-----------------------------------------------------------------------------
301
302IMPLEMENT_DYNAMIC_CLASS(wxClipboard,wxObject)
303
304wxClipboard::wxClipboard()
305{
de6185e2
WS
306 m_open = false;
307 m_waiting = false;
8b53e5a2 308
de6185e2
WS
309 m_ownsClipboard = false;
310 m_ownsPrimarySelection = false;
aeeb6a44 311
d3b9f782
VZ
312 m_data = NULL;
313 m_receivedData = NULL;
99c67c77 314
034be888 315 /* we use m_targetsWidget to query what formats are available */
270c23f7 316
034be888
RR
317 m_targetsWidget = gtk_window_new( GTK_WINDOW_POPUP );
318 gtk_widget_realize( m_targetsWidget );
319
270c23f7 320 gtk_signal_connect( GTK_OBJECT(m_targetsWidget),
034be888 321 "selection_received",
270c23f7 322 GTK_SIGNAL_FUNC( targets_selection_received ),
66633398 323 (gpointer) this );
270c23f7 324
034be888 325 /* we use m_clipboardWidget to get and to offer data */
270c23f7 326
8b53e5a2
RR
327 m_clipboardWidget = gtk_window_new( GTK_WINDOW_POPUP );
328 gtk_widget_realize( m_clipboardWidget );
329
270c23f7 330 gtk_signal_connect( GTK_OBJECT(m_clipboardWidget),
034be888 331 "selection_received",
270c23f7 332 GTK_SIGNAL_FUNC( selection_received ),
66633398 333 (gpointer) this );
034be888 334
270c23f7 335 gtk_signal_connect( GTK_OBJECT(m_clipboardWidget),
8b53e5a2 336 "selection_clear_event",
270c23f7 337 GTK_SIGNAL_FUNC( selection_clear_clip ),
66633398 338 (gpointer) NULL );
270c23f7 339
8b53e5a2 340 if (!g_clipboardAtom) g_clipboardAtom = gdk_atom_intern( "CLIPBOARD", FALSE );
8b53e5a2 341 if (!g_targetsAtom) g_targetsAtom = gdk_atom_intern ("TARGETS", FALSE);
d394f0c9 342 if (!g_timestampAtom) g_timestampAtom = gdk_atom_intern ("TIMESTAMP", FALSE);
270c23f7 343
de6185e2 344 m_formatSupported = false;
8b53e5a2 345 m_targetRequested = 0;
dc86cb34
RR
346}
347
348wxClipboard::~wxClipboard()
b527aac5 349{
270c23f7
VZ
350 Clear();
351
8b53e5a2 352 if (m_clipboardWidget) gtk_widget_destroy( m_clipboardWidget );
034be888 353 if (m_targetsWidget) gtk_widget_destroy( m_targetsWidget );
b527aac5
RR
354}
355
356void wxClipboard::Clear()
dc86cb34 357{
1dd989e1
RR
358 if (m_data)
359 {
b453e1b2
RR
360#if wxUSE_THREADS
361 /* disable GUI threads */
b453e1b2 362#endif
270c23f7 363
ca11abde
RR
364 // As we have data we also own the clipboard. Once we no longer own
365 // it, clear_selection is called which will set m_data to zero
aeeb6a44 366 if (gdk_selection_owner_get( g_clipboardAtom ) == m_clipboardWidget->window)
8b53e5a2 367 {
de6185e2 368 m_waiting = true;
270c23f7 369
d3b9f782 370 gtk_selection_owner_set( NULL, g_clipboardAtom,
b02da6b1 371 (guint32) GDK_CURRENT_TIME );
270c23f7 372
e5ea3f7a 373 while (m_waiting) gtk_main_iteration();
8b53e5a2 374 }
270c23f7 375
aeeb6a44
RR
376 if (gdk_selection_owner_get( GDK_SELECTION_PRIMARY ) == m_clipboardWidget->window)
377 {
de6185e2 378 m_waiting = true;
270c23f7 379
d3b9f782 380 gtk_selection_owner_set( NULL, GDK_SELECTION_PRIMARY,
b02da6b1 381 (guint32) GDK_CURRENT_TIME );
270c23f7 382
e5ea3f7a 383 while (m_waiting) gtk_main_iteration();
aeeb6a44 384 }
270c23f7 385
1dd989e1 386 if (m_data)
270c23f7 387 {
66633398 388 delete m_data;
d3b9f782 389 m_data = NULL;
66633398 390 }
270c23f7 391
b453e1b2
RR
392#if wxUSE_THREADS
393 /* re-enable GUI threads */
b453e1b2 394#endif
8b53e5a2 395 }
270c23f7 396
8b53e5a2 397 m_targetRequested = 0;
de6185e2 398 m_formatSupported = false;
8b53e5a2
RR
399}
400
401bool wxClipboard::Open()
402{
de6185e2 403 wxCHECK_MSG( !m_open, false, wxT("clipboard already open") );
270c23f7 404
de6185e2 405 m_open = true;
270c23f7 406
de6185e2 407 return true;
dc86cb34
RR
408}
409
75ce0581 410bool wxClipboard::SetData( wxDataObject *data )
dc86cb34 411{
de6185e2 412 wxCHECK_MSG( m_open, false, wxT("clipboard not open") );
270c23f7 413
de6185e2 414 wxCHECK_MSG( data, false, wxT("data is invalid") );
270c23f7 415
0d2a2b60 416 Clear();
75ce0581
RR
417
418 return AddData( data );
419}
420
421bool wxClipboard::AddData( wxDataObject *data )
422{
de6185e2 423 wxCHECK_MSG( m_open, false, wxT("clipboard not open") );
270c23f7 424
de6185e2 425 wxCHECK_MSG( data, false, wxT("data is invalid") );
270c23f7 426
ca11abde 427 // we can only store one wxDataObject
1dd989e1 428 Clear();
270c23f7 429
1dd989e1
RR
430 m_data = data;
431
ca11abde 432 // get formats from wxDataObjects
b068c4e8
RR
433 wxDataFormat *array = new wxDataFormat[ m_data->GetFormatCount() ];
434 m_data->GetAllFormats( array );
11e1c70d 435
ca11abde 436 // primary selection or clipboard
11e1c70d
RR
437 GdkAtom clipboard = m_usePrimary ? (GdkAtom)GDK_SELECTION_PRIMARY
438 : g_clipboardAtom;
439
d394f0c9
MR
440 // by default provide TIMESTAMP as a target
441 gtk_selection_add_target( GTK_WIDGET(m_clipboardWidget),
442 clipboard,
443 g_timestampAtom,
444 0 );
270c23f7 445
b068c4e8
RR
446 for (size_t i = 0; i < m_data->GetFormatCount(); i++)
447 {
61b04ac6
VZ
448 wxLogTrace( TRACE_CLIPBOARD,
449 wxT("wxClipboard now supports atom %s"),
450 array[i].GetId().c_str() );
11e1c70d 451
3d257b8d 452// printf( "added %s\n",
ca11abde 453// gdk_atom_name( array[i].GetFormatId() ) );
3d257b8d 454
11e1c70d 455 gtk_selection_add_target( GTK_WIDGET(m_clipboardWidget),
270c23f7
VZ
456 clipboard,
457 array[i],
11e1c70d 458 0 ); /* what is info ? */
b068c4e8
RR
459 }
460
461 delete[] array;
270c23f7
VZ
462
463 gtk_signal_connect( GTK_OBJECT(m_clipboardWidget),
d345e841 464 "selection_get",
270c23f7 465 GTK_SIGNAL_FUNC(selection_handler),
4b84311a 466 GUINT_TO_POINTER( gdk_event_get_time(gtk_get_current_event()) ) );
d345e841 467
b453e1b2 468#if wxUSE_THREADS
11e1c70d 469 /* disable GUI threads */
b453e1b2 470#endif
270c23f7 471
75ce0581 472 /* Tell the world we offer clipboard data */
11e1c70d
RR
473 bool res = (gtk_selection_owner_set( m_clipboardWidget,
474 clipboard,
b02da6b1 475 (guint32) GDK_CURRENT_TIME ));
270c23f7 476
11e1c70d
RR
477 if (m_usePrimary)
478 m_ownsPrimarySelection = res;
479 else
480 m_ownsClipboard = res;
270c23f7 481
b453e1b2
RR
482#if wxUSE_THREADS
483 /* re-enable GUI threads */
b453e1b2 484#endif
270c23f7 485
11e1c70d 486 return res;
8b53e5a2 487}
db1b4961 488
8b53e5a2
RR
489void wxClipboard::Close()
490{
223d09f6 491 wxCHECK_RET( m_open, wxT("clipboard not open") );
270c23f7 492
de6185e2 493 m_open = false;
dc86cb34
RR
494}
495
f536e0f2
VZ
496bool wxClipboard::IsOpened() const
497{
498 return m_open;
499}
500
e1ee679c 501bool wxClipboard::IsSupported( const wxDataFormat& format )
b527aac5 502{
e5d6aa22 503 /* reentrance problems */
de6185e2 504 if (m_waiting) return false;
270c23f7 505
e5d6aa22 506 /* store requested format to be asked for by callbacks */
1dd989e1 507 m_targetRequested = format;
270c23f7 508
61b04ac6
VZ
509 wxLogTrace( TRACE_CLIPBOARD,
510 wxT("wxClipboard:IsSupported: requested format: %s"),
511 format.GetId().c_str() );
eff869aa 512
de6185e2 513 wxCHECK_MSG( m_targetRequested, false, wxT("invalid clipboard format") );
270c23f7 514
de6185e2 515 m_formatSupported = false;
270c23f7
VZ
516
517 /* perform query. this will set m_formatSupported to
de6185e2 518 true if m_targetRequested is supported.
270c23f7 519 also, we have to wait for the "answer" from the
034be888 520 clipboard owner which is an asynchronous process.
de6185e2 521 therefore we set m_waiting = true here and wait
270c23f7 522 until the callback "targets_selection_received"
de6185e2 523 sets it to false */
034be888 524
de6185e2 525 m_waiting = true;
ca35e608 526
034be888 527 gtk_selection_convert( m_targetsWidget,
66633398 528 m_usePrimary ? (GdkAtom)GDK_SELECTION_PRIMARY
270c23f7 529 : g_clipboardAtom,
66633398 530 g_targetsAtom,
b02da6b1 531 (guint32) GDK_CURRENT_TIME );
ca35e608 532
034be888 533 while (m_waiting) gtk_main_iteration();
270c23f7 534
ebe47451 535 return m_formatSupported;
270c23f7
VZ
536}
537
e1ee679c 538bool wxClipboard::GetData( wxDataObject& data )
75ce0581 539{
de6185e2 540 wxCHECK_MSG( m_open, false, wxT("clipboard not open") );
270c23f7 541
b068c4e8
RR
542 /* get formats from wxDataObjects */
543 wxDataFormat *array = new wxDataFormat[ data.GetFormatCount() ];
544 data.GetAllFormats( array );
270c23f7 545
b068c4e8
RR
546 for (size_t i = 0; i < data.GetFormatCount(); i++)
547 {
e5d6aa22 548 wxDataFormat format( array[i] );
270c23f7 549
61b04ac6
VZ
550 wxLogTrace( TRACE_CLIPBOARD,
551 wxT("wxClipboard::GetData: requested format: %s"),
552 format.GetId().c_str() );
270c23f7 553
b068c4e8 554 /* is data supported by clipboard ? */
270c23f7 555
11e1c70d
RR
556 /* store requested format to be asked for by callbacks */
557 m_targetRequested = format;
270c23f7 558
de6185e2 559 wxCHECK_MSG( m_targetRequested, false, wxT("invalid clipboard format") );
270c23f7 560
de6185e2 561 m_formatSupported = false;
270c23f7
VZ
562
563 /* perform query. this will set m_formatSupported to
de6185e2 564 true if m_targetRequested is supported.
270c23f7 565 also, we have to wait for the "answer" from the
11e1c70d 566 clipboard owner which is an asynchronous process.
de6185e2 567 therefore we set m_waiting = true here and wait
270c23f7 568 until the callback "targets_selection_received"
de6185e2 569 sets it to false */
11e1c70d 570
de6185e2 571 m_waiting = true;
11e1c70d
RR
572
573 gtk_selection_convert( m_targetsWidget,
574 m_usePrimary ? (GdkAtom)GDK_SELECTION_PRIMARY
270c23f7 575 : g_clipboardAtom,
11e1c70d 576 g_targetsAtom,
b02da6b1 577 (guint32) GDK_CURRENT_TIME );
11e1c70d
RR
578
579 while (m_waiting) gtk_main_iteration();
270c23f7 580
11e1c70d 581 if (!m_formatSupported) continue;
270c23f7 582
b068c4e8
RR
583 /* store pointer to data object to be filled up by callbacks */
584 m_receivedData = &data;
270c23f7 585
b068c4e8 586 /* store requested format to be asked for by callbacks */
e5d6aa22 587 m_targetRequested = format;
270c23f7 588
de6185e2 589 wxCHECK_MSG( m_targetRequested, false, wxT("invalid clipboard format") );
270c23f7 590
b068c4e8 591 /* start query */
de6185e2 592 m_formatSupported = false;
270c23f7
VZ
593
594 /* ask for clipboard contents. this will set
de6185e2 595 m_formatSupported to true if m_targetRequested
b068c4e8 596 is supported.
270c23f7 597 also, we have to wait for the "answer" from the
b068c4e8 598 clipboard owner which is an asynchronous process.
de6185e2 599 therefore we set m_waiting = true here and wait
270c23f7 600 until the callback "targets_selection_received"
de6185e2 601 sets it to false */
b068c4e8 602
de6185e2 603 m_waiting = true;
b068c4e8 604
47cf53ef
VZ
605 wxLogTrace( TRACE_CLIPBOARD,
606 wxT("wxClipboard::GetData: format found, start convert") );
270c23f7 607
b068c4e8 608 gtk_selection_convert( m_clipboardWidget,
66633398 609 m_usePrimary ? (GdkAtom)GDK_SELECTION_PRIMARY
270c23f7 610 : g_clipboardAtom,
66633398 611 m_targetRequested,
b02da6b1 612 (guint32) GDK_CURRENT_TIME );
270c23f7 613
b068c4e8 614 while (m_waiting) gtk_main_iteration();
b527aac5 615
be809e82
VZ
616 /*
617 Normally this is a true error as we checked for the presence of such
618 data before, but there are applications that may return an empty
619 string (e.g. Gnumeric-1.6.1 on Linux if an empty cell is copied)
620 which would produce a false error message here, so we check for the
621 size of the string first. In ansi, GetDataSize returns an extra
622 value (for the closing null?), with unicode, the exact number of
623 tokens is given (that is more than 1 for special characters)
624 (tested with Gnumeric-1.6.1 and OpenOffice.org-2.0.2)
625 */
626#if wxUSE_UNICODE
627 if ( format != wxDF_UNICODETEXT || data.GetDataSize(format) > 0 )
628#else // !UNICODE
629 if ( format != wxDF_TEXT || data.GetDataSize(format) > 1 )
630#endif // UNICODE / !UNICODE
631 {
632 wxCHECK_MSG( m_formatSupported, false,
633 wxT("error retrieving data from clipboard") );
634 }
270c23f7 635
66633398 636 /* return success */
b068c4e8 637 delete[] array;
de6185e2 638 return true;
b068c4e8 639 }
270c23f7 640
47cf53ef
VZ
641 wxLogTrace( TRACE_CLIPBOARD,
642 wxT("wxClipboard::GetData: format not found") );
270c23f7 643
b068c4e8
RR
644 /* return failure */
645 delete[] array;
de6185e2 646 return false;
b527aac5
RR
647}
648
ac57418f 649#endif
ac57418f 650 // wxUSE_CLIPBOARD