1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/motif/clipbrd.cpp
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
26 #include "wx/clipbrd.h"
31 #include "wx/bitmap.h"
32 #include "wx/dataobj.h"
35 #include "wx/ptr_scpd.h"
38 #pragma message disable nosimpint
42 #include <Xm/CutPaste.h>
44 #pragma message enable nosimpint
47 #include "wx/motif/private.h"
49 bool wxOpenClipboard()
51 return wxTheClipboard
->Open();
54 bool wxCloseClipboard()
56 wxTheClipboard
->Close();
61 bool wxEmptyClipboard()
63 wxTheClipboard
->Clear();
67 bool wxClipboardOpen()
69 return wxTheClipboard
->IsOpened();
72 bool wxIsClipboardFormatAvailable(const wxDataFormat
& dataFormat
)
74 return wxTheClipboard
->IsSupported( dataFormat
);
77 bool wxSetClipboardData(wxDataFormat dataFormat
, wxObject
*obj
,
78 int WXUNUSED(width
), int WXUNUSED(height
))
80 wxDataObject
* dobj
= NULL
;
82 if( dataFormat
== wxDF_TEXT
)
84 wxChar
* data
= (wxChar
*)obj
;
85 dobj
= new wxTextDataObject( data
);
87 else if( dataFormat
= wxDF_BITMAP
)
89 wxBitmap
* data
= (wxBitmap
*)obj
;
90 dobj
= new wxBitmapDataObject( *data
);
96 return wxTheClipboard
->SetData( dobj
);
99 wxObject
*wxGetClipboardData(wxDataFormat dataFormat
, long *len
)
101 wxDataObject
* dobj
= NULL
;
102 wxTextDataObject
* tobj
= NULL
;
103 wxBitmapDataObject
* bobj
= NULL
;
105 if( dataFormat
== wxDF_TEXT
)
107 dobj
= tobj
= new wxTextDataObject
;
109 else if( dataFormat
= wxDF_BITMAP
)
111 dobj
= bobj
= new wxBitmapDataObject
;
114 if( !dobj
|| !wxTheClipboard
->GetData( *dobj
) )
119 wxString text
= tobj
->GetText();
120 wxChar
* buf
= new wxChar
[text
.length() + 1];
122 if( len
) *len
= text
.length();
123 return (wxObject
*)wxStrcpy( buf
, text
.c_str() );
128 return new wxBitmap( bobj
->GetBitmap() );
131 return NULL
; // just in case...
134 wxDataFormat
wxEnumClipboardFormats(const wxDataFormat
& dataFormat
)
136 // Only wxDF_TEXT supported
137 if (dataFormat
== wxDF_TEXT
)
143 wxDataFormat
wxRegisterClipboardFormat(char *WXUNUSED(formatName
))
149 bool wxGetClipboardFormatName(const wxDataFormat
& dataFormat
, char *formatName
,
152 wxStrncpy( formatName
, dataFormat
.GetId().c_str(), maxCount
);
157 //-----------------------------------------------------------------------------
159 //-----------------------------------------------------------------------------
161 struct wxDataIdToDataObject
163 wxDataIdToDataObject( wxDataObject
* o
, long d
, size_t s
)
164 : object( o
), size( s
), dataId( d
) { }
166 wxDataObject
* object
;
171 #include "wx/listimpl.cpp"
173 WX_DEFINE_LIST(wxDataObjectList
)
174 WX_DEFINE_LIST(wxDataIdToDataObjectList
)
178 #if wxCHECK_LESSTIF()
179 static void wxClipboardCallback( Widget widget
, int* data_id
,
180 int* priv
, int* reason
);
182 static void wxClipboardCallback( Widget widget
, long* data_id
,
183 long* priv
, int* reason
);
187 IMPLEMENT_DYNAMIC_CLASS(wxClipboard
,wxObject
)
189 wxClipboard::wxClipboard()
194 wxClipboard::~wxClipboard()
199 void wxClipboard::Clear()
201 wxDataObjectList::compatibility_iterator node
= m_data
.GetFirst();
204 delete node
->GetData();
205 node
= node
->GetNext();
209 for( wxDataIdToDataObjectList::compatibility_iterator node2
= m_idToObject
.GetFirst();
210 node2
; node2
= node2
->GetNext() )
212 delete node2
->GetData();
214 m_idToObject
.Clear();
217 bool wxClipboard::Open()
219 wxCHECK_MSG( !m_open
, false, "clipboard already open" );
226 bool wxClipboard::SetData( wxDataObject
*data
)
228 wxCHECK_MSG( data
, false, "data is invalid" );
229 wxCHECK_MSG( m_open
, false, "clipboard not open" );
233 return AddData( data
);
236 wxDECLARE_SCOPED_ARRAY( wxDataFormat
, wxDataFormatScopedArray
)
237 wxDEFINE_SCOPED_ARRAY( wxDataFormat
, wxDataFormatScopedArray
)
239 #if wxCHECK_LESSTIF()
240 void wxClipboardCallback( Widget xwidget
, int* data_id
,
241 int* priv
, int* WXUNUSED(reason
) )
243 void wxClipboardCallback( Widget xwidget
, long* data_id
,
244 long* priv
, int* WXUNUSED(reason
) )
247 Display
* xdisplay
= XtDisplay( xwidget
);
248 Window xwindow
= XtWindow( xwidget
);
249 wxDataObject
* dobj
= NULL
;
252 for( wxDataIdToDataObjectList::compatibility_iterator node2
=
253 wxTheClipboard
->m_idToObject
.GetFirst();
254 node2
; node2
= node2
->GetNext() )
256 wxDataIdToDataObject
* dido
= node2
->GetData();
257 if( dido
->dataId
== *data_id
)
267 wxCharBuffer
buffer(size
);
268 size_t count
= dobj
->GetFormatCount( wxDataObject::Get
);
269 wxDataFormatScopedArray
dfarr( new wxDataFormat
[count
] );
270 dobj
->GetAllFormats( dfarr
.get(), wxDataObject::Get
);
272 if( !dobj
->GetDataHere( dfarr
[*priv
], buffer
.data() ) )
275 while( XmClipboardCopyByName( xdisplay
, xwindow
, *data_id
,
276 buffer
.data(), size
, 0 )
277 == XmClipboardLocked
);
280 bool wxClipboard::AddData( wxDataObject
*data
)
282 wxCHECK_MSG( data
, false, "data is invalid" );
283 wxCHECK_MSG( m_open
, false, "clipboard not open" );
285 m_data
.Append( data
);
287 Display
* xdisplay
= wxGlobalDisplay();
288 Widget xwidget
= (Widget
)wxTheApp
->GetTopLevelRealizedWidget();
289 Window xwindow
= XtWindow( xwidget
);
290 wxXmString
label( wxTheApp
->GetAppName() );
291 Time timestamp
= XtLastTimestampProcessed( xdisplay
);
296 while( ( retval
= XmClipboardStartCopy( xdisplay
, xwindow
, label(),
300 == XmClipboardLocked
);
301 if( retval
!= XmClipboardSuccess
)
304 size_t count
= data
->GetFormatCount( wxDataObject::Get
);
305 wxDataFormatScopedArray
dfarr( new wxDataFormat
[count
] );
306 data
->GetAllFormats( dfarr
.get(), wxDataObject::Get
);
308 for( size_t i
= 0; i
< count
; ++i
)
310 size_t size
= data
->GetDataSize( dfarr
[i
] );
312 wxString id
= dfarr
[i
].GetId();
314 while( ( retval
= XmClipboardCopy( xdisplay
, xwindow
, itemId
,
316 NULL
, size
, i
, &data_id
) )
317 == XmClipboardLocked
);
319 m_idToObject
.Append( new wxDataIdToDataObject( data
, data_id
, size
) );
322 while( XmClipboardEndCopy( xdisplay
, xwindow
, itemId
)
323 == XmClipboardLocked
);
328 void wxClipboard::Close()
330 wxCHECK_RET( m_open
, "clipboard not open" );
335 bool wxClipboard::IsSupported(const wxDataFormat
& format
)
337 Display
* xdisplay
= wxGlobalDisplay();
338 Window xwindow
= XtWindow( (Widget
)wxTheApp
->GetTopLevelRealizedWidget() );
339 bool isSupported
= false;
341 unsigned long max_name_length
;
342 wxString id
= format
.GetId();
344 while( ( retval
= XmClipboardLock( xdisplay
, xwindow
) )
345 == XmClipboardLocked
);
346 if( retval
!= XmClipboardSuccess
)
349 if( XmClipboardInquireCount( xdisplay
, xwindow
, &count
, &max_name_length
)
350 == XmClipboardSuccess
)
352 wxCharBuffer
buf( max_name_length
+ 1 );
353 unsigned long copied
;
355 for( int i
= 0; i
< count
; ++i
)
357 if( XmClipboardInquireFormat( xdisplay
, xwindow
, i
+ 1,
358 (XtPointer
)buf
.data(),
359 max_name_length
, &copied
)
360 != XmClipboardSuccess
)
363 buf
.data()[copied
] = '\0';
373 XmClipboardUnlock( xdisplay
, xwindow
, False
);
378 class wxClipboardEndRetrieve
381 wxClipboardEndRetrieve( Display
* display
, Window window
)
382 : m_display( display
), m_window( window
) { }
383 ~wxClipboardEndRetrieve()
385 while( XmClipboardEndRetrieve( m_display
, m_window
)
386 == XmClipboardLocked
);
393 bool wxClipboard::GetData( wxDataObject
& data
)
395 wxCHECK_MSG( m_open
, false, "clipboard not open" );
397 Display
* xdisplay
= wxGlobalDisplay();
398 Window xwindow
= XtWindow( (Widget
)wxTheApp
->GetTopLevelRealizedWidget() );
399 Time timestamp
= XtLastTimestampProcessed( xdisplay
);
401 wxDataFormat chosenFormat
;
404 ///////////////////////////////////////////////////////////////////////////
405 // determine if the cliboard holds any format we like
406 ///////////////////////////////////////////////////////////////////////////
407 while( ( retval
= XmClipboardStartRetrieve( xdisplay
, xwindow
,
409 == XmClipboardLocked
);
410 if( retval
!= XmClipboardSuccess
)
413 wxClipboardEndRetrieve
endRetrieve( xdisplay
, xwindow
);
416 unsigned long max_name_length
;
417 size_t dfcount
= data
.GetFormatCount( wxDataObject::Set
);
418 wxDataFormatScopedArray
dfarr( new wxDataFormat
[dfcount
] );
419 data
.GetAllFormats( dfarr
.get(), wxDataObject::Set
);
421 if( XmClipboardInquireCount( xdisplay
, xwindow
, &count
, &max_name_length
)
422 == XmClipboardSuccess
)
424 wxCharBuffer
buf( max_name_length
+ 1 );
425 unsigned long copied
;
427 for( int i
= 0; i
< count
; ++i
)
429 if( XmClipboardInquireFormat( xdisplay
, xwindow
, i
+ 1,
430 (XtPointer
)buf
.data(),
431 max_name_length
, &copied
)
432 != XmClipboardSuccess
)
435 buf
.data()[copied
] = '\0';
437 // try preferred format
438 if( buf
== data
.GetPreferredFormat( wxDataObject::Set
).GetId() )
440 chosenFormat
= data
.GetPreferredFormat( wxDataObject::Set
);
444 // try all other formats
445 for( size_t i
= 0; i
< dfcount
; ++i
)
447 if( buf
== dfarr
[i
].GetId() )
448 chosenFormat
= dfarr
[i
];
453 if( chosenFormat
== wxDF_INVALID
)
456 ///////////////////////////////////////////////////////////////////////////
457 // now retrieve the data
458 ///////////////////////////////////////////////////////////////////////////
459 unsigned long length
, dummy1
;
461 wxString id
= chosenFormat
.GetId();
463 while( ( retval
= XmClipboardInquireLength( xdisplay
, xwindow
,
466 == XmClipboardLocked
);
467 if( retval
!= XmClipboardSuccess
)
470 wxCharBuffer
buf(length
);
472 while( ( retval
= XmClipboardRetrieve( xdisplay
, xwindow
,
474 (XtPointer
)buf
.data(),
475 length
, &dummy1
, &dummy2
) )
476 == XmClipboardLocked
);
477 if( retval
!= XmClipboardSuccess
)
480 if( !data
.SetData( chosenFormat
, length
, buf
.data() ) )
486 #endif // wxUSE_CLIPBOARD