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
27 #include "wx/bitmap.h"
29 #include "wx/clipbrd.h"
30 #include "wx/dataobj.h"
31 #include "wx/ptr_scpd.h"
34 #pragma message disable nosimpint
38 #include <Xm/CutPaste.h>
40 #pragma message enable nosimpint
43 #include "wx/motif/private.h"
45 bool wxOpenClipboard()
47 return wxTheClipboard
->Open();
50 bool wxCloseClipboard()
52 wxTheClipboard
->Close();
57 bool wxEmptyClipboard()
59 wxTheClipboard
->Clear();
63 bool wxClipboardOpen()
65 return wxTheClipboard
->IsOpened();
68 bool wxIsClipboardFormatAvailable(const wxDataFormat
& dataFormat
)
70 return wxTheClipboard
->IsSupported( dataFormat
);
73 bool wxSetClipboardData(wxDataFormat dataFormat
, wxObject
*obj
,
74 int WXUNUSED(width
), int WXUNUSED(height
))
76 wxDataObject
* dobj
= NULL
;
78 if( dataFormat
== wxDF_TEXT
)
80 wxChar
* data
= (wxChar
*)obj
;
81 dobj
= new wxTextDataObject( data
);
83 else if( dataFormat
= wxDF_BITMAP
)
85 wxBitmap
* data
= (wxBitmap
*)obj
;
86 dobj
= new wxBitmapDataObject( *data
);
92 return wxTheClipboard
->SetData( dobj
);
95 wxObject
*wxGetClipboardData(wxDataFormat dataFormat
, long *len
)
97 wxDataObject
* dobj
= NULL
;
98 wxTextDataObject
* tobj
= NULL
;
99 wxBitmapDataObject
* bobj
= NULL
;
101 if( dataFormat
== wxDF_TEXT
)
103 dobj
= tobj
= new wxTextDataObject
;
105 else if( dataFormat
= wxDF_BITMAP
)
107 dobj
= bobj
= new wxBitmapDataObject
;
110 if( !dobj
|| !wxTheClipboard
->GetData( *dobj
) )
115 wxString text
= tobj
->GetText();
116 wxChar
* buf
= new wxChar
[text
.length() + 1];
118 if( len
) *len
= text
.length();
119 return (wxObject
*)wxStrcpy( buf
, text
.c_str() );
124 return new wxBitmap( bobj
->GetBitmap() );
127 return NULL
; // just in case...
130 wxDataFormat
wxEnumClipboardFormats(const wxDataFormat
& dataFormat
)
132 // Only wxDF_TEXT supported
133 if (dataFormat
== wxDF_TEXT
)
139 wxDataFormat
wxRegisterClipboardFormat(char *WXUNUSED(formatName
))
145 bool wxGetClipboardFormatName(const wxDataFormat
& dataFormat
, char *formatName
,
148 wxStrncpy( formatName
, dataFormat
.GetId().c_str(), maxCount
);
153 //-----------------------------------------------------------------------------
155 //-----------------------------------------------------------------------------
157 struct wxDataIdToDataObject
159 wxDataIdToDataObject( wxDataObject
* o
, long d
, size_t s
)
160 : object( o
), size( s
), dataId( d
) { }
162 wxDataObject
* object
;
167 #include "wx/listimpl.cpp"
169 WX_DEFINE_LIST(wxDataObjectList
)
170 WX_DEFINE_LIST(wxDataIdToDataObjectList
)
174 #if wxCHECK_LESSTIF()
175 static void wxClipboardCallback( Widget widget
, int* data_id
,
176 int* priv
, int* reason
);
178 static void wxClipboardCallback( Widget widget
, long* data_id
,
179 long* priv
, int* reason
);
183 IMPLEMENT_DYNAMIC_CLASS(wxClipboard
,wxObject
)
185 wxClipboard::wxClipboard()
190 wxClipboard::~wxClipboard()
195 void wxClipboard::Clear()
197 wxDataObjectList::compatibility_iterator node
= m_data
.GetFirst();
200 delete node
->GetData();
201 node
= node
->GetNext();
205 for( wxDataIdToDataObjectList::compatibility_iterator node2
= m_idToObject
.GetFirst();
206 node2
; node2
= node2
->GetNext() )
208 delete node2
->GetData();
210 m_idToObject
.Clear();
213 bool wxClipboard::Open()
215 wxCHECK_MSG( !m_open
, false, "clipboard already open" );
222 bool wxClipboard::SetData( wxDataObject
*data
)
224 wxCHECK_MSG( data
, false, "data is invalid" );
225 wxCHECK_MSG( m_open
, false, "clipboard not open" );
229 return AddData( data
);
232 wxDECLARE_SCOPED_ARRAY( wxDataFormat
, wxDataFormatScopedArray
)
233 wxDEFINE_SCOPED_ARRAY( wxDataFormat
, wxDataFormatScopedArray
)
235 #if wxCHECK_LESSTIF()
236 void wxClipboardCallback( Widget xwidget
, int* data_id
,
237 int* priv
, int* WXUNUSED(reason
) )
239 void wxClipboardCallback( Widget xwidget
, long* data_id
,
240 long* priv
, int* WXUNUSED(reason
) )
243 Display
* xdisplay
= XtDisplay( xwidget
);
244 Window xwindow
= XtWindow( xwidget
);
245 wxDataObject
* dobj
= NULL
;
248 for( wxDataIdToDataObjectList::compatibility_iterator node2
=
249 wxTheClipboard
->m_idToObject
.GetFirst();
250 node2
; node2
= node2
->GetNext() )
252 wxDataIdToDataObject
* dido
= node2
->GetData();
253 if( dido
->dataId
== *data_id
)
263 wxCharBuffer
buffer(size
);
264 size_t count
= dobj
->GetFormatCount( wxDataObject::Get
);
265 wxDataFormatScopedArray
dfarr( new wxDataFormat
[count
] );
266 dobj
->GetAllFormats( dfarr
.get(), wxDataObject::Get
);
268 if( !dobj
->GetDataHere( dfarr
[*priv
], buffer
.data() ) )
271 while( XmClipboardCopyByName( xdisplay
, xwindow
, *data_id
,
272 buffer
.data(), size
, 0 )
273 == XmClipboardLocked
);
276 bool wxClipboard::AddData( wxDataObject
*data
)
278 wxCHECK_MSG( data
, false, "data is invalid" );
279 wxCHECK_MSG( m_open
, false, "clipboard not open" );
281 m_data
.Append( data
);
283 Display
* xdisplay
= wxGlobalDisplay();
284 Widget xwidget
= (Widget
)wxTheApp
->GetTopLevelRealizedWidget();
285 Window xwindow
= XtWindow( xwidget
);
286 wxXmString
label( wxTheApp
->GetAppName() );
287 Time timestamp
= XtLastTimestampProcessed( xdisplay
);
292 while( ( retval
= XmClipboardStartCopy( xdisplay
, xwindow
, label(),
296 == XmClipboardLocked
);
297 if( retval
!= XmClipboardSuccess
)
300 size_t count
= data
->GetFormatCount( wxDataObject::Get
);
301 wxDataFormatScopedArray
dfarr( new wxDataFormat
[count
] );
302 data
->GetAllFormats( dfarr
.get(), wxDataObject::Get
);
304 for( size_t i
= 0; i
< count
; ++i
)
306 size_t size
= data
->GetDataSize( dfarr
[i
] );
308 wxString id
= dfarr
[i
].GetId();
310 while( ( retval
= XmClipboardCopy( xdisplay
, xwindow
, itemId
,
311 wxConstCast(id
.c_str(), char),
312 NULL
, size
, i
, &data_id
) )
313 == XmClipboardLocked
);
315 m_idToObject
.Append( new wxDataIdToDataObject( data
, data_id
, size
) );
318 while( XmClipboardEndCopy( xdisplay
, xwindow
, itemId
)
319 == XmClipboardLocked
);
324 void wxClipboard::Close()
326 wxCHECK_RET( m_open
, "clipboard not open" );
331 bool wxClipboard::IsSupported(const wxDataFormat
& format
)
333 Display
* xdisplay
= wxGlobalDisplay();
334 Window xwindow
= XtWindow( (Widget
)wxTheApp
->GetTopLevelRealizedWidget() );
335 bool isSupported
= false;
337 unsigned long max_name_length
;
338 wxString id
= format
.GetId();
340 while( ( retval
= XmClipboardLock( xdisplay
, xwindow
) )
341 == XmClipboardLocked
);
342 if( retval
!= XmClipboardSuccess
)
345 if( XmClipboardInquireCount( xdisplay
, xwindow
, &count
, &max_name_length
)
346 == XmClipboardSuccess
)
348 wxCharBuffer
buf( max_name_length
+ 1 );
349 unsigned long copied
;
351 for( int i
= 0; i
< count
; ++i
)
353 if( XmClipboardInquireFormat( xdisplay
, xwindow
, i
+ 1,
354 (XtPointer
)buf
.data(),
355 max_name_length
, &copied
)
356 != XmClipboardSuccess
)
359 buf
.data()[copied
] = '\0';
369 XmClipboardUnlock( xdisplay
, xwindow
, False
);
374 class wxClipboardEndRetrieve
377 wxClipboardEndRetrieve( Display
* display
, Window window
)
378 : m_display( display
), m_window( window
) { }
379 ~wxClipboardEndRetrieve()
381 while( XmClipboardEndRetrieve( m_display
, m_window
)
382 == XmClipboardLocked
);
389 bool wxClipboard::GetData( wxDataObject
& data
)
391 wxCHECK_MSG( m_open
, false, "clipboard not open" );
393 Display
* xdisplay
= wxGlobalDisplay();
394 Window xwindow
= XtWindow( (Widget
)wxTheApp
->GetTopLevelRealizedWidget() );
395 Time timestamp
= XtLastTimestampProcessed( xdisplay
);
397 wxDataFormat chosenFormat
;
400 ///////////////////////////////////////////////////////////////////////////
401 // determine if the cliboard holds any format we like
402 ///////////////////////////////////////////////////////////////////////////
403 while( ( retval
= XmClipboardStartRetrieve( xdisplay
, xwindow
,
405 == XmClipboardLocked
);
406 if( retval
!= XmClipboardSuccess
)
409 wxClipboardEndRetrieve
endRetrieve( xdisplay
, xwindow
);
412 unsigned long max_name_length
;
413 size_t dfcount
= data
.GetFormatCount( wxDataObject::Set
);
414 wxDataFormatScopedArray
dfarr( new wxDataFormat
[dfcount
] );
415 data
.GetAllFormats( dfarr
.get(), wxDataObject::Set
);
417 if( XmClipboardInquireCount( xdisplay
, xwindow
, &count
, &max_name_length
)
418 == XmClipboardSuccess
)
420 wxCharBuffer
buf( max_name_length
+ 1 );
421 unsigned long copied
;
423 for( int i
= 0; i
< count
; ++i
)
425 if( XmClipboardInquireFormat( xdisplay
, xwindow
, i
+ 1,
426 (XtPointer
)buf
.data(),
427 max_name_length
, &copied
)
428 != XmClipboardSuccess
)
431 buf
.data()[copied
] = '\0';
433 // try preferred format
434 if( buf
== data
.GetPreferredFormat( wxDataObject::Set
).GetId() )
436 chosenFormat
= data
.GetPreferredFormat( wxDataObject::Set
);
440 // try all other formats
441 for( size_t i
= 0; i
< dfcount
; ++i
)
443 if( buf
== dfarr
[i
].GetId() )
444 chosenFormat
= dfarr
[i
];
449 if( chosenFormat
== wxDF_INVALID
)
452 ///////////////////////////////////////////////////////////////////////////
453 // now retrieve the data
454 ///////////////////////////////////////////////////////////////////////////
455 unsigned long length
, dummy1
;
457 wxString id
= chosenFormat
.GetId();
459 while( ( retval
= XmClipboardInquireLength( xdisplay
, xwindow
,
460 wxConstCast(id
.c_str(), char),
462 == XmClipboardLocked
);
463 if( retval
!= XmClipboardSuccess
)
466 wxCharBuffer
buf(length
);
468 while( ( retval
= XmClipboardRetrieve( xdisplay
, xwindow
,
469 wxConstCast(id
.c_str(), char),
470 (XtPointer
)buf
.data(),
471 length
, &dummy1
, &dummy2
) )
472 == XmClipboardLocked
);
473 if( retval
!= XmClipboardSuccess
)
476 if( !data
.SetData( chosenFormat
, length
, buf
.data() ) )
482 #endif // wxUSE_CLIPBOARD