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 static void wxClipboardCallback( Widget widget
, long* data_id
,
167 long* priv
, int* reason
);
170 IMPLEMENT_DYNAMIC_CLASS(wxClipboard
,wxObject
)
172 wxClipboard::wxClipboard()
177 wxClipboard::~wxClipboard()
182 void wxClipboard::Clear()
184 wxDataObjectList::Node
* node
= m_data
.GetFirst();
187 delete node
->GetData();
188 node
= node
->GetNext();
192 for( wxDataIdToDataObjectList::Node
* node2
= m_idToObject
.GetFirst();
193 node2
; node2
= node2
->GetNext() )
194 delete node
->GetData();
195 m_idToObject
.Clear();
198 bool wxClipboard::Open()
200 wxCHECK_MSG( !m_open
, false, "clipboard already open" );
207 bool wxClipboard::SetData( wxDataObject
*data
)
209 wxCHECK_MSG( data
, false, "data is invalid" );
210 wxCHECK_MSG( m_open
, false, "clipboard not open" );
214 return AddData( data
);
217 wxDECLARE_SCOPED_ARRAY( wxDataFormat
, wxDataFormatScopedArray
);
218 wxDEFINE_SCOPED_ARRAY( wxDataFormat
, wxDataFormatScopedArray
);
220 void wxClipboardCallback( Widget xwidget
, long* data_id
,
221 long* priv
, int* reason
)
223 Display
* xdisplay
= XtDisplay( xwidget
);
224 Window xwindow
= XtWindow( xwidget
);
225 wxDataObject
* dobj
= NULL
;
228 for( wxDataIdToDataObjectList::Node
* node2
=
229 wxTheClipboard
->m_idToObject
.GetFirst();
230 node2
; node2
= node2
->GetNext() )
232 wxDataIdToDataObject
* dido
= node2
->GetData();
233 if( dido
->dataId
== *data_id
)
243 wxCharBuffer
buffer(size
);
244 size_t count
= dobj
->GetFormatCount( wxDataObject::Get
);
245 wxDataFormatScopedArray
dfarr( new wxDataFormat
[count
] );
246 dobj
->GetAllFormats( dfarr
.get(), wxDataObject::Get
);
248 if( !dobj
->GetDataHere( dfarr
[*priv
], buffer
.data() ) )
251 while( XmClipboardCopyByName( xdisplay
, xwindow
, *data_id
,
252 buffer
.data(), size
, 0 )
253 == XmClipboardLocked
);
256 bool wxClipboard::AddData( wxDataObject
*data
)
258 wxCHECK_MSG( data
, false, "data is invalid" );
259 wxCHECK_MSG( m_open
, false, "clipboard not open" );
261 m_data
.Append( data
);
263 Display
* xdisplay
= wxGlobalDisplay();
264 Widget xwidget
= (Widget
)wxTheApp
->GetTopLevelWidget();
265 Window xwindow
= XtWindow( xwidget
);
266 wxXmString
label( wxTheApp
->GetAppName() );
267 Time timestamp
= XtLastTimestampProcessed( xdisplay
);
272 while( ( retval
= XmClipboardStartCopy( xdisplay
, xwindow
, label(),
276 == XmClipboardLocked
);
277 if( retval
!= XmClipboardSuccess
)
280 size_t count
= data
->GetFormatCount( wxDataObject::Get
);
281 wxDataFormatScopedArray
dfarr( new wxDataFormat
[count
] );
282 data
->GetAllFormats( dfarr
.get(), wxDataObject::Get
);
284 for( size_t i
= 0; i
< count
; ++i
)
286 size_t size
= data
->GetDataSize( dfarr
[i
] );
288 wxString id
= dfarr
[i
].GetId();
290 while( ( retval
= XmClipboardCopy( xdisplay
, xwindow
, itemId
,
291 wxConstCast(id
.c_str(), char),
292 NULL
, size
, i
, &data_id
) )
293 == XmClipboardLocked
);
295 m_idToObject
.Append( new wxDataIdToDataObject( data
, data_id
, size
) );
298 while( XmClipboardEndCopy( xdisplay
, xwindow
, itemId
)
299 == XmClipboardLocked
);
304 void wxClipboard::Close()
306 wxCHECK_RET( m_open
, "clipboard not open" );
311 bool wxClipboard::IsSupported(const wxDataFormat
& format
)
313 Display
* xdisplay
= wxGlobalDisplay();
314 Window xwindow
= XtWindow( (Widget
)wxTheApp
->GetTopLevelWidget() );
315 bool isSupported
= false;
317 unsigned long max_name_length
;
318 wxString id
= format
.GetId();
320 while( ( retval
= XmClipboardLock( xdisplay
, xwindow
) )
321 == XmClipboardLocked
);
322 if( retval
!= XmClipboardSuccess
)
325 if( XmClipboardInquireCount( xdisplay
, xwindow
, &count
, &max_name_length
)
326 == XmClipboardSuccess
)
328 wxCharBuffer
buf( max_name_length
+ 1 );
329 unsigned long copied
;
331 for( int i
= 0; i
< count
; ++i
)
333 if( XmClipboardInquireFormat( xdisplay
, xwindow
, i
+ 1,
334 (XtPointer
)buf
.data(),
335 max_name_length
, &copied
)
336 != XmClipboardSuccess
)
339 buf
.data()[copied
] = '\0';
349 XmClipboardUnlock( xdisplay
, xwindow
, False
);
354 class wxClipboardEndRetrieve
357 wxClipboardEndRetrieve( Display
* display
, Window window
)
358 : m_display( display
), m_window( window
) { }
359 ~wxClipboardEndRetrieve()
361 while( XmClipboardEndRetrieve( m_display
, m_window
)
362 == XmClipboardLocked
);
369 bool wxClipboard::GetData( wxDataObject
& data
)
371 wxCHECK_MSG( m_open
, false, "clipboard not open" );
373 Display
* xdisplay
= wxGlobalDisplay();
374 Window xwindow
= XtWindow( (Widget
)wxTheApp
->GetTopLevelWidget() );
375 Time timestamp
= XtLastTimestampProcessed( xdisplay
);
377 wxDataFormat chosenFormat
;
380 ///////////////////////////////////////////////////////////////////////////
381 // determine if the cliboard holds any format we like
382 ///////////////////////////////////////////////////////////////////////////
383 while( ( retval
= XmClipboardStartRetrieve( xdisplay
, xwindow
,
385 == XmClipboardLocked
);
386 if( retval
!= XmClipboardSuccess
)
389 wxClipboardEndRetrieve
endRetrieve( xdisplay
, xwindow
);
392 unsigned long max_name_length
;
393 size_t dfcount
= data
.GetFormatCount( wxDataObject::Set
);
394 wxDataFormatScopedArray
dfarr( new wxDataFormat
[dfcount
] );
395 data
.GetAllFormats( dfarr
.get(), wxDataObject::Set
);
397 if( XmClipboardInquireCount( xdisplay
, xwindow
, &count
, &max_name_length
)
398 == XmClipboardSuccess
)
400 wxCharBuffer
buf( max_name_length
+ 1 );
401 unsigned long copied
;
403 for( int i
= 0; i
< count
; ++i
)
405 if( XmClipboardInquireFormat( xdisplay
, xwindow
, i
+ 1,
406 (XtPointer
)buf
.data(),
407 max_name_length
, &copied
)
408 != XmClipboardSuccess
)
411 buf
.data()[copied
] = '\0';
413 // try preferred format
414 if( buf
== data
.GetPreferredFormat( wxDataObject::Set
).GetId() )
416 chosenFormat
= data
.GetPreferredFormat( wxDataObject::Set
);
420 // try all other formats
421 for( size_t i
= 0; i
< dfcount
; ++i
)
423 if( buf
== dfarr
[i
].GetId() )
424 chosenFormat
= dfarr
[i
];
429 if( chosenFormat
== wxDF_INVALID
)
432 ///////////////////////////////////////////////////////////////////////////
433 // now retrieve the data
434 ///////////////////////////////////////////////////////////////////////////
435 unsigned long length
, dummy1
;
437 wxString id
= chosenFormat
.GetId();
439 while( ( retval
= XmClipboardInquireLength( xdisplay
, xwindow
,
440 wxConstCast(id
.c_str(), char),
442 == XmClipboardLocked
);
443 if( retval
!= XmClipboardSuccess
)
446 wxCharBuffer
buf(length
);
448 while( ( retval
= XmClipboardRetrieve( xdisplay
, xwindow
,
449 wxConstCast(id
.c_str(), char),
450 (XtPointer
)buf
.data(),
451 length
, &dummy1
, &dummy2
) )
452 == XmClipboardLocked
);
453 if( retval
!= XmClipboardSuccess
)
456 if( !data
.SetData( chosenFormat
, length
, buf
.data() ) )
462 #endif // wxUSE_CLIPBOARD