1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: Clipboard functionality
4 // Author: Julian Smart
5 // Modified by: Mattia Barbon (added support for generic wxDataObjects)
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 // For compilers that support precompilation, includes "wx.h".
13 #include "wx/wxprec.h"
16 #include "wx/vms_x_fix.h"
17 #define XtWindow XTWINDOW
18 #define XtScreen XTSCREEN
19 #define XtParent XTPARENT
20 #define XtIsRealized XTISREALIZED
21 #define XtDisplay XTDISPLAY
29 #include "wx/bitmap.h"
31 #include "wx/clipbrd.h"
32 #include "wx/dataobj.h"
33 #include "wx/ptr_scpd.h"
36 #pragma message disable nosimpint
40 #include <Xm/CutPaste.h>
42 #pragma message enable nosimpint
45 #include "wx/motif/private.h"
47 bool wxOpenClipboard()
49 return wxTheClipboard
->Open();
52 bool wxCloseClipboard()
54 wxTheClipboard
->Close();
59 bool wxEmptyClipboard()
61 wxTheClipboard
->Clear();
65 bool wxClipboardOpen()
67 return wxTheClipboard
->IsOpened();
70 bool wxIsClipboardFormatAvailable(const wxDataFormat
& dataFormat
)
72 return wxTheClipboard
->IsSupported( dataFormat
);
75 bool wxSetClipboardData(wxDataFormat dataFormat
, wxObject
*obj
,
76 int WXUNUSED(width
), int WXUNUSED(height
))
78 wxDataObject
* dobj
= NULL
;
80 if( dataFormat
== wxDF_TEXT
)
82 wxChar
* data
= (wxChar
*)obj
;
83 dobj
= new wxTextDataObject( data
);
85 else if( dataFormat
= wxDF_BITMAP
)
87 wxBitmap
* data
= (wxBitmap
*)obj
;
88 dobj
= new wxBitmapDataObject( *data
);
94 return wxTheClipboard
->SetData( dobj
);
97 wxObject
*wxGetClipboardData(wxDataFormat dataFormat
, long *len
)
99 wxDataObject
* dobj
= NULL
;
100 wxTextDataObject
* tobj
= NULL
;
101 wxBitmapDataObject
* bobj
= NULL
;
103 if( dataFormat
== wxDF_TEXT
)
105 dobj
= tobj
= new wxTextDataObject
;
107 else if( dataFormat
= wxDF_BITMAP
)
109 dobj
= bobj
= new wxBitmapDataObject
;
112 if( !dobj
|| !wxTheClipboard
->GetData( *dobj
) )
117 wxString text
= tobj
->GetText();
118 wxChar
* buf
= new wxChar
[text
.length() + 1];
120 if( len
) *len
= text
.length();
121 return (wxObject
*)wxStrcpy( buf
, text
.c_str() );
126 return new wxBitmap( bobj
->GetBitmap() );
129 return NULL
; // just in case...
132 wxDataFormat
wxEnumClipboardFormats(const wxDataFormat
& dataFormat
)
134 // Only wxDF_TEXT supported
135 if (dataFormat
== wxDF_TEXT
)
141 wxDataFormat
wxRegisterClipboardFormat(char *WXUNUSED(formatName
))
147 bool wxGetClipboardFormatName(const wxDataFormat
& dataFormat
, char *formatName
,
150 wxStrncpy( formatName
, dataFormat
.GetId().c_str(), maxCount
);
155 //-----------------------------------------------------------------------------
157 //-----------------------------------------------------------------------------
159 struct wxDataIdToDataObject
161 wxDataIdToDataObject( wxDataObject
* o
, long d
, size_t s
)
162 : object( o
), size( s
), dataId( d
) { }
164 wxDataObject
* object
;
169 #include "wx/listimpl.cpp"
171 WX_DEFINE_LIST(wxDataObjectList
);
172 WX_DEFINE_LIST(wxDataIdToDataObjectList
);
176 #if wxCHECK_LESSTIF()
177 static void wxClipboardCallback( Widget widget
, int* data_id
,
178 int* priv
, int* reason
);
180 static void wxClipboardCallback( Widget widget
, long* data_id
,
181 long* priv
, int* reason
);
185 IMPLEMENT_DYNAMIC_CLASS(wxClipboard
,wxObject
)
187 wxClipboard::wxClipboard()
192 wxClipboard::~wxClipboard()
197 void wxClipboard::Clear()
199 wxDataObjectList::compatibility_iterator node
= m_data
.GetFirst();
202 delete node
->GetData();
203 node
= node
->GetNext();
207 for( wxDataIdToDataObjectList::compatibility_iterator node2
= m_idToObject
.GetFirst();
208 node2
; node2
= node2
->GetNext() )
210 delete node2
->GetData();
212 m_idToObject
.Clear();
215 bool wxClipboard::Open()
217 wxCHECK_MSG( !m_open
, false, "clipboard already open" );
224 bool wxClipboard::SetData( wxDataObject
*data
)
226 wxCHECK_MSG( data
, false, "data is invalid" );
227 wxCHECK_MSG( m_open
, false, "clipboard not open" );
231 return AddData( data
);
234 wxDECLARE_SCOPED_ARRAY( wxDataFormat
, wxDataFormatScopedArray
);
235 wxDEFINE_SCOPED_ARRAY( wxDataFormat
, wxDataFormatScopedArray
);
237 #if wxCHECK_LESSTIF()
238 void wxClipboardCallback( Widget xwidget
, int* data_id
,
239 int* priv
, int* reason
)
241 void wxClipboardCallback( Widget xwidget
, long* data_id
,
242 long* priv
, int* reason
)
245 Display
* xdisplay
= XtDisplay( xwidget
);
246 Window xwindow
= XtWindow( xwidget
);
247 wxDataObject
* dobj
= NULL
;
250 for( wxDataIdToDataObjectList::compatibility_iterator node2
=
251 wxTheClipboard
->m_idToObject
.GetFirst();
252 node2
; node2
= node2
->GetNext() )
254 wxDataIdToDataObject
* dido
= node2
->GetData();
255 if( dido
->dataId
== *data_id
)
265 wxCharBuffer
buffer(size
);
266 size_t count
= dobj
->GetFormatCount( wxDataObject::Get
);
267 wxDataFormatScopedArray
dfarr( new wxDataFormat
[count
] );
268 dobj
->GetAllFormats( dfarr
.get(), wxDataObject::Get
);
270 if( !dobj
->GetDataHere( dfarr
[*priv
], buffer
.data() ) )
273 while( XmClipboardCopyByName( xdisplay
, xwindow
, *data_id
,
274 buffer
.data(), size
, 0 )
275 == XmClipboardLocked
);
278 bool wxClipboard::AddData( wxDataObject
*data
)
280 wxCHECK_MSG( data
, false, "data is invalid" );
281 wxCHECK_MSG( m_open
, false, "clipboard not open" );
283 m_data
.Append( data
);
285 Display
* xdisplay
= wxGlobalDisplay();
286 Widget xwidget
= (Widget
)wxTheApp
->GetTopLevelRealizedWidget();
287 Window xwindow
= XtWindow( xwidget
);
288 wxXmString
label( wxTheApp
->GetAppName() );
289 Time timestamp
= XtLastTimestampProcessed( xdisplay
);
294 while( ( retval
= XmClipboardStartCopy( xdisplay
, xwindow
, label(),
298 == XmClipboardLocked
);
299 if( retval
!= XmClipboardSuccess
)
302 size_t count
= data
->GetFormatCount( wxDataObject::Get
);
303 wxDataFormatScopedArray
dfarr( new wxDataFormat
[count
] );
304 data
->GetAllFormats( dfarr
.get(), wxDataObject::Get
);
306 for( size_t i
= 0; i
< count
; ++i
)
308 size_t size
= data
->GetDataSize( dfarr
[i
] );
310 wxString id
= dfarr
[i
].GetId();
312 while( ( retval
= XmClipboardCopy( xdisplay
, xwindow
, itemId
,
313 wxConstCast(id
.c_str(), char),
314 NULL
, size
, i
, &data_id
) )
315 == XmClipboardLocked
);
317 m_idToObject
.Append( new wxDataIdToDataObject( data
, data_id
, size
) );
320 while( XmClipboardEndCopy( xdisplay
, xwindow
, itemId
)
321 == XmClipboardLocked
);
326 void wxClipboard::Close()
328 wxCHECK_RET( m_open
, "clipboard not open" );
333 bool wxClipboard::IsSupported(const wxDataFormat
& format
)
335 Display
* xdisplay
= wxGlobalDisplay();
336 Window xwindow
= XtWindow( (Widget
)wxTheApp
->GetTopLevelRealizedWidget() );
337 bool isSupported
= false;
339 unsigned long max_name_length
;
340 wxString id
= format
.GetId();
342 while( ( retval
= XmClipboardLock( xdisplay
, xwindow
) )
343 == XmClipboardLocked
);
344 if( retval
!= XmClipboardSuccess
)
347 if( XmClipboardInquireCount( xdisplay
, xwindow
, &count
, &max_name_length
)
348 == XmClipboardSuccess
)
350 wxCharBuffer
buf( max_name_length
+ 1 );
351 unsigned long copied
;
353 for( int i
= 0; i
< count
; ++i
)
355 if( XmClipboardInquireFormat( xdisplay
, xwindow
, i
+ 1,
356 (XtPointer
)buf
.data(),
357 max_name_length
, &copied
)
358 != XmClipboardSuccess
)
361 buf
.data()[copied
] = '\0';
371 XmClipboardUnlock( xdisplay
, xwindow
, False
);
376 class wxClipboardEndRetrieve
379 wxClipboardEndRetrieve( Display
* display
, Window window
)
380 : m_display( display
), m_window( window
) { }
381 ~wxClipboardEndRetrieve()
383 while( XmClipboardEndRetrieve( m_display
, m_window
)
384 == XmClipboardLocked
);
391 bool wxClipboard::GetData( wxDataObject
& data
)
393 wxCHECK_MSG( m_open
, false, "clipboard not open" );
395 Display
* xdisplay
= wxGlobalDisplay();
396 Window xwindow
= XtWindow( (Widget
)wxTheApp
->GetTopLevelRealizedWidget() );
397 Time timestamp
= XtLastTimestampProcessed( xdisplay
);
399 wxDataFormat chosenFormat
;
402 ///////////////////////////////////////////////////////////////////////////
403 // determine if the cliboard holds any format we like
404 ///////////////////////////////////////////////////////////////////////////
405 while( ( retval
= XmClipboardStartRetrieve( xdisplay
, xwindow
,
407 == XmClipboardLocked
);
408 if( retval
!= XmClipboardSuccess
)
411 wxClipboardEndRetrieve
endRetrieve( xdisplay
, xwindow
);
414 unsigned long max_name_length
;
415 size_t dfcount
= data
.GetFormatCount( wxDataObject::Set
);
416 wxDataFormatScopedArray
dfarr( new wxDataFormat
[dfcount
] );
417 data
.GetAllFormats( dfarr
.get(), wxDataObject::Set
);
419 if( XmClipboardInquireCount( xdisplay
, xwindow
, &count
, &max_name_length
)
420 == XmClipboardSuccess
)
422 wxCharBuffer
buf( max_name_length
+ 1 );
423 unsigned long copied
;
425 for( int i
= 0; i
< count
; ++i
)
427 if( XmClipboardInquireFormat( xdisplay
, xwindow
, i
+ 1,
428 (XtPointer
)buf
.data(),
429 max_name_length
, &copied
)
430 != XmClipboardSuccess
)
433 buf
.data()[copied
] = '\0';
435 // try preferred format
436 if( buf
== data
.GetPreferredFormat( wxDataObject::Set
).GetId() )
438 chosenFormat
= data
.GetPreferredFormat( wxDataObject::Set
);
442 // try all other formats
443 for( size_t i
= 0; i
< dfcount
; ++i
)
445 if( buf
== dfarr
[i
].GetId() )
446 chosenFormat
= dfarr
[i
];
451 if( chosenFormat
== wxDF_INVALID
)
454 ///////////////////////////////////////////////////////////////////////////
455 // now retrieve the data
456 ///////////////////////////////////////////////////////////////////////////
457 unsigned long length
, dummy1
;
459 wxString id
= chosenFormat
.GetId();
461 while( ( retval
= XmClipboardInquireLength( xdisplay
, xwindow
,
462 wxConstCast(id
.c_str(), char),
464 == XmClipboardLocked
);
465 if( retval
!= XmClipboardSuccess
)
468 wxCharBuffer
buf(length
);
470 while( ( retval
= XmClipboardRetrieve( xdisplay
, xwindow
,
471 wxConstCast(id
.c_str(), char),
472 (XtPointer
)buf
.data(),
473 length
, &dummy1
, &dummy2
) )
474 == XmClipboardLocked
);
475 if( retval
!= XmClipboardSuccess
)
478 if( !data
.SetData( chosenFormat
, length
, buf
.data() ) )
484 #endif // wxUSE_CLIPBOARD