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 /////////////////////////////////////////////////////////////////////////////
13 #pragma implementation
14 #pragma implementation "clipbrd.h"
22 #include "wx/bitmap.h"
24 #include "wx/clipbrd.h"
25 #include "wx/dataobj.h"
26 #include "wx/ptr_scpd.h"
29 #pragma message disable nosimpint
32 #include <Xm/CutPaste.h>
34 #pragma message enable nosimpint
37 #include "wx/motif/private.h"
39 bool wxOpenClipboard()
41 return wxTheClipboard
->Open();
44 bool wxCloseClipboard()
46 wxTheClipboard
->Close();
51 bool wxEmptyClipboard()
53 wxTheClipboard
->Clear();
57 bool wxClipboardOpen()
59 return wxTheClipboard
->IsOpened();
62 bool wxIsClipboardFormatAvailable(wxDataFormat dataFormat
)
64 return wxTheClipboard
->IsSupported( dataFormat
);
67 bool wxSetClipboardData(wxDataFormat dataFormat
, wxObject
*obj
,
68 int WXUNUSED(width
), int WXUNUSED(height
))
70 wxDataObject
* dobj
= NULL
;
72 if( dataFormat
== wxDF_TEXT
)
74 wxChar
* data
= (wxChar
*)obj
;
75 dobj
= new wxTextDataObject( data
);
77 else if( dataFormat
= wxDF_BITMAP
)
79 wxBitmap
* data
= (wxBitmap
*)obj
;
80 dobj
= new wxBitmapDataObject( *data
);
86 return wxTheClipboard
->SetData( dobj
);
89 wxObject
*wxGetClipboardData(wxDataFormat dataFormat
, long *len
)
91 wxDataObject
* dobj
= NULL
;
92 wxTextDataObject
* tobj
= NULL
;
93 wxBitmapDataObject
* bobj
= NULL
;
95 if( dataFormat
== wxDF_TEXT
)
97 dobj
= tobj
= new wxTextDataObject
;
99 else if( dataFormat
= wxDF_BITMAP
)
101 dobj
= bobj
= new wxBitmapDataObject
;
104 if( !dobj
|| !wxTheClipboard
->GetData( *dobj
) )
109 wxString text
= tobj
->GetText();
110 wxChar
* buf
= new wxChar
[text
.length() + 1];
112 if( len
) *len
= text
.length();
113 return (wxObject
*)wxStrcpy( buf
, text
.c_str() );
118 return new wxBitmap( bobj
->GetBitmap() );
121 return NULL
; // just in case...
124 wxDataFormat
wxEnumClipboardFormats(wxDataFormat dataFormat
)
126 // Only wxDF_TEXT supported
127 if (dataFormat
== wxDF_TEXT
)
133 wxDataFormat
wxRegisterClipboardFormat(char *WXUNUSED(formatName
))
139 bool wxGetClipboardFormatName(wxDataFormat dataFormat
, char *formatName
,
142 wxStrncpy( formatName
, dataFormat
.GetId().c_str(), maxCount
);
147 //-----------------------------------------------------------------------------
149 //-----------------------------------------------------------------------------
151 struct wxDataIdToDataObject
153 wxDataIdToDataObject( wxDataObject
* o
, long d
, size_t s
)
154 : object( o
), size( s
), dataId( d
) { }
156 wxDataObject
* object
;
161 #include "wx/listimpl.cpp"
163 WX_DEFINE_LIST(wxDataObjectList
);
164 WX_DEFINE_LIST(wxDataIdToDataObjectList
);
166 #if wxCHECK_LESSTIF()
167 static void wxClipboardCallback( Widget widget
, int* data_id
,
168 int* priv
, int* reason
);
170 static void wxClipboardCallback( Widget widget
, long* data_id
,
171 long* priv
, int* reason
);
174 IMPLEMENT_DYNAMIC_CLASS(wxClipboard
,wxObject
)
176 wxClipboard::wxClipboard()
181 wxClipboard::~wxClipboard()
186 void wxClipboard::Clear()
188 wxDataObjectList::Node
* node
= m_data
.GetFirst();
191 delete node
->GetData();
192 node
= node
->GetNext();
196 for( wxDataIdToDataObjectList::Node
* node2
= m_idToObject
.GetFirst();
197 node2
; node2
= node2
->GetNext() )
198 delete node
->GetData();
199 m_idToObject
.Clear();
202 bool wxClipboard::Open()
204 wxCHECK_MSG( !m_open
, false, "clipboard already open" );
211 bool wxClipboard::SetData( wxDataObject
*data
)
213 wxCHECK_MSG( data
, false, "data is invalid" );
214 wxCHECK_MSG( m_open
, false, "clipboard not open" );
218 return AddData( data
);
221 wxDECLARE_SCOPED_ARRAY( wxDataFormat
, wxDataFormatScopedArray
);
222 wxDEFINE_SCOPED_ARRAY( wxDataFormat
, wxDataFormatScopedArray
);
224 #if wxCHECK_LESSTIF()
225 void wxClipboardCallback( Widget xwidget
, int* data_id
,
226 int* priv
, int* reason
)
228 void wxClipboardCallback( Widget xwidget
, long* data_id
,
229 long* priv
, int* reason
)
232 Display
* xdisplay
= XtDisplay( xwidget
);
233 Window xwindow
= XtWindow( xwidget
);
234 wxDataObject
* dobj
= NULL
;
237 for( wxDataIdToDataObjectList::Node
* node2
=
238 wxTheClipboard
->m_idToObject
.GetFirst();
239 node2
; node2
= node2
->GetNext() )
241 wxDataIdToDataObject
* dido
= node2
->GetData();
242 if( dido
->dataId
== *data_id
)
252 wxCharBuffer
buffer(size
);
253 size_t count
= dobj
->GetFormatCount( wxDataObject::Get
);
254 wxDataFormatScopedArray
dfarr( new wxDataFormat
[count
] );
255 dobj
->GetAllFormats( dfarr
.get(), wxDataObject::Get
);
257 if( !dobj
->GetDataHere( dfarr
[*priv
], buffer
.data() ) )
260 while( XmClipboardCopyByName( xdisplay
, xwindow
, *data_id
,
261 buffer
.data(), size
, 0 )
262 == XmClipboardLocked
);
265 bool wxClipboard::AddData( wxDataObject
*data
)
267 wxCHECK_MSG( data
, false, "data is invalid" );
268 wxCHECK_MSG( m_open
, false, "clipboard not open" );
270 m_data
.Append( data
);
272 Display
* xdisplay
= wxGlobalDisplay();
273 Widget xwidget
= (Widget
)wxTheApp
->GetTopLevelWidget();
274 Window xwindow
= XtWindow( xwidget
);
275 wxXmString
label( wxTheApp
->GetAppName() );
276 Time timestamp
= XtLastTimestampProcessed( xdisplay
);
281 while( ( retval
= XmClipboardStartCopy( xdisplay
, xwindow
, label(),
285 == XmClipboardLocked
);
286 if( retval
!= XmClipboardSuccess
)
289 size_t count
= data
->GetFormatCount( wxDataObject::Get
);
290 wxDataFormatScopedArray
dfarr( new wxDataFormat
[count
] );
291 data
->GetAllFormats( dfarr
.get(), wxDataObject::Get
);
293 for( size_t i
= 0; i
< count
; ++i
)
295 size_t size
= data
->GetDataSize( dfarr
[i
] );
297 wxString id
= dfarr
[i
].GetId();
299 while( ( retval
= XmClipboardCopy( xdisplay
, xwindow
, itemId
,
300 wxConstCast(id
.c_str(), char),
301 NULL
, size
, i
, &data_id
) )
302 == XmClipboardLocked
);
304 m_idToObject
.Append( new wxDataIdToDataObject( data
, data_id
, size
) );
307 while( XmClipboardEndCopy( xdisplay
, xwindow
, itemId
)
308 == XmClipboardLocked
);
313 void wxClipboard::Close()
315 wxCHECK_RET( m_open
, "clipboard not open" );
320 bool wxClipboard::IsSupported(const wxDataFormat
& format
)
322 Display
* xdisplay
= wxGlobalDisplay();
323 Window xwindow
= XtWindow( (Widget
)wxTheApp
->GetTopLevelWidget() );
324 bool isSupported
= false;
326 unsigned long max_name_length
;
327 wxString id
= format
.GetId();
329 while( ( retval
= XmClipboardLock( xdisplay
, xwindow
) )
330 == XmClipboardLocked
);
331 if( retval
!= XmClipboardSuccess
)
334 if( XmClipboardInquireCount( xdisplay
, xwindow
, &count
, &max_name_length
)
335 == XmClipboardSuccess
)
337 wxCharBuffer
buf( max_name_length
+ 1 );
338 unsigned long copied
;
340 for( int i
= 0; i
< count
; ++i
)
342 if( XmClipboardInquireFormat( xdisplay
, xwindow
, i
+ 1,
343 (XtPointer
)buf
.data(),
344 max_name_length
, &copied
)
345 != XmClipboardSuccess
)
348 buf
.data()[copied
] = '\0';
358 XmClipboardUnlock( xdisplay
, xwindow
, False
);
363 class wxClipboardEndRetrieve
366 wxClipboardEndRetrieve( Display
* display
, Window window
)
367 : m_display( display
), m_window( window
) { }
368 ~wxClipboardEndRetrieve()
370 while( XmClipboardEndRetrieve( m_display
, m_window
)
371 == XmClipboardLocked
);
378 bool wxClipboard::GetData( wxDataObject
& data
)
380 wxCHECK_MSG( m_open
, false, "clipboard not open" );
382 Display
* xdisplay
= wxGlobalDisplay();
383 Window xwindow
= XtWindow( (Widget
)wxTheApp
->GetTopLevelWidget() );
384 Time timestamp
= XtLastTimestampProcessed( xdisplay
);
386 wxDataFormat chosenFormat
;
389 ///////////////////////////////////////////////////////////////////////////
390 // determine if the cliboard holds any format we like
391 ///////////////////////////////////////////////////////////////////////////
392 while( ( retval
= XmClipboardStartRetrieve( xdisplay
, xwindow
,
394 == XmClipboardLocked
);
395 if( retval
!= XmClipboardSuccess
)
398 wxClipboardEndRetrieve
endRetrieve( xdisplay
, xwindow
);
401 unsigned long max_name_length
;
402 size_t dfcount
= data
.GetFormatCount( wxDataObject::Set
);
403 wxDataFormatScopedArray
dfarr( new wxDataFormat
[dfcount
] );
404 data
.GetAllFormats( dfarr
.get(), wxDataObject::Set
);
406 if( XmClipboardInquireCount( xdisplay
, xwindow
, &count
, &max_name_length
)
407 == XmClipboardSuccess
)
409 wxCharBuffer
buf( max_name_length
+ 1 );
410 unsigned long copied
;
412 for( int i
= 0; i
< count
; ++i
)
414 if( XmClipboardInquireFormat( xdisplay
, xwindow
, i
+ 1,
415 (XtPointer
)buf
.data(),
416 max_name_length
, &copied
)
417 != XmClipboardSuccess
)
420 buf
.data()[copied
] = '\0';
422 // try preferred format
423 if( buf
== data
.GetPreferredFormat( wxDataObject::Set
).GetId() )
425 chosenFormat
= data
.GetPreferredFormat( wxDataObject::Set
);
429 // try all other formats
430 for( size_t i
= 0; i
< dfcount
; ++i
)
432 if( buf
== dfarr
[i
].GetId() )
433 chosenFormat
= dfarr
[i
];
438 if( chosenFormat
== wxDF_INVALID
)
441 ///////////////////////////////////////////////////////////////////////////
442 // now retrieve the data
443 ///////////////////////////////////////////////////////////////////////////
444 unsigned long length
, dummy1
;
446 wxString id
= chosenFormat
.GetId();
448 while( ( retval
= XmClipboardInquireLength( xdisplay
, xwindow
,
449 wxConstCast(id
.c_str(), char),
451 == XmClipboardLocked
);
452 if( retval
!= XmClipboardSuccess
)
455 wxCharBuffer
buf(length
);
457 while( ( retval
= XmClipboardRetrieve( xdisplay
, xwindow
,
458 wxConstCast(id
.c_str(), char),
459 (XtPointer
)buf
.data(),
460 length
, &dummy1
, &dummy2
) )
461 == XmClipboardLocked
);
462 if( retval
!= XmClipboardSuccess
)
465 if( !data
.SetData( chosenFormat
, length
, buf
.data() ) )
471 #endif // wxUSE_CLIPBOARD