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/scopedarray.h"
37 typedef wxScopedArray
<wxDataFormat
> wxDataFormatScopedArray
;
40 #pragma message disable nosimpint
44 #include <Xm/CutPaste.h>
46 #pragma message enable nosimpint
49 #include "wx/motif/private.h"
51 bool wxOpenClipboard()
53 return wxTheClipboard
->Open();
56 bool wxCloseClipboard()
58 wxTheClipboard
->Close();
63 bool wxEmptyClipboard()
65 wxTheClipboard
->Clear();
69 bool wxClipboardOpen()
71 return wxTheClipboard
->IsOpened();
74 bool wxIsClipboardFormatAvailable(const wxDataFormat
& dataFormat
)
76 return wxTheClipboard
->IsSupported( dataFormat
);
79 bool wxSetClipboardData(wxDataFormat dataFormat
, wxObject
*obj
,
80 int WXUNUSED(width
), int WXUNUSED(height
))
82 wxDataObject
* dobj
= NULL
;
84 if( dataFormat
== wxDF_TEXT
)
86 wxChar
* data
= (wxChar
*)obj
;
87 dobj
= new wxTextDataObject( data
);
89 else if( dataFormat
= wxDF_BITMAP
)
91 wxBitmap
* data
= (wxBitmap
*)obj
;
92 dobj
= new wxBitmapDataObject( *data
);
98 return wxTheClipboard
->SetData( dobj
);
101 wxObject
*wxGetClipboardData(wxDataFormat dataFormat
, long *len
)
103 wxDataObject
* dobj
= NULL
;
104 wxTextDataObject
* tobj
= NULL
;
105 wxBitmapDataObject
* bobj
= NULL
;
107 if( dataFormat
== wxDF_TEXT
)
109 dobj
= tobj
= new wxTextDataObject
;
111 else if( dataFormat
= wxDF_BITMAP
)
113 dobj
= bobj
= new wxBitmapDataObject
;
116 if( !dobj
|| !wxTheClipboard
->GetData( *dobj
) )
121 wxString text
= tobj
->GetText();
122 wxChar
* buf
= new wxChar
[text
.length() + 1];
124 if( len
) *len
= text
.length();
125 return (wxObject
*)wxStrcpy( buf
, text
.c_str() );
130 return new wxBitmap( bobj
->GetBitmap() );
133 return NULL
; // just in case...
136 wxDataFormat
wxEnumClipboardFormats(const wxDataFormat
& dataFormat
)
138 // Only wxDF_TEXT supported
139 if (dataFormat
== wxDF_TEXT
)
145 wxDataFormat
wxRegisterClipboardFormat(char *WXUNUSED(formatName
))
151 bool wxGetClipboardFormatName(const wxDataFormat
& dataFormat
, char *formatName
,
154 wxStrlcpy( formatName
, dataFormat
.GetId().c_str(), maxCount
);
159 //-----------------------------------------------------------------------------
161 //-----------------------------------------------------------------------------
163 struct wxDataIdToDataObject
165 wxDataIdToDataObject( wxDataObject
* o
, long d
, size_t s
)
166 : object( o
), size( s
), dataId( d
) { }
168 wxDataObject
* object
;
173 #include "wx/listimpl.cpp"
175 WX_DEFINE_LIST(wxDataObjectList
)
176 WX_DEFINE_LIST(wxDataIdToDataObjectList
)
180 #if wxCHECK_LESSTIF()
181 static void wxClipboardCallback( Widget widget
, int* data_id
,
182 int* priv
, int* reason
);
184 static void wxClipboardCallback( Widget widget
, long* data_id
,
185 long* priv
, int* reason
);
189 IMPLEMENT_DYNAMIC_CLASS(wxClipboard
,wxObject
)
191 wxClipboard::wxClipboard()
196 wxClipboard::~wxClipboard()
201 void wxClipboard::Clear()
203 wxDataObjectList::compatibility_iterator node
= m_data
.GetFirst();
206 delete node
->GetData();
207 node
= node
->GetNext();
211 for( wxDataIdToDataObjectList::compatibility_iterator node2
= m_idToObject
.GetFirst();
212 node2
; node2
= node2
->GetNext() )
214 delete node2
->GetData();
216 m_idToObject
.Clear();
219 bool wxClipboard::Open()
221 wxCHECK_MSG( !m_open
, false, "clipboard already open" );
228 bool wxClipboard::SetData( wxDataObject
*data
)
230 wxCHECK_MSG( data
, false, "data is invalid" );
231 wxCHECK_MSG( m_open
, false, "clipboard not open" );
235 return AddData( data
);
238 #if wxCHECK_LESSTIF()
239 void wxClipboardCallback( Widget xwidget
, int* data_id
,
240 int* priv
, int* WXUNUSED(reason
) )
242 void wxClipboardCallback( Widget xwidget
, long* data_id
,
243 long* priv
, int* WXUNUSED(reason
) )
246 Display
* xdisplay
= XtDisplay( xwidget
);
247 Window xwindow
= XtWindow( xwidget
);
248 wxDataObject
* dobj
= NULL
;
251 for( wxDataIdToDataObjectList::compatibility_iterator node2
=
252 wxTheClipboard
->m_idToObject
.GetFirst();
253 node2
; node2
= node2
->GetNext() )
255 wxDataIdToDataObject
* dido
= node2
->GetData();
256 if( dido
->dataId
== *data_id
)
266 wxCharBuffer
buffer(size
);
267 size_t count
= dobj
->GetFormatCount( wxDataObject::Get
);
268 wxDataFormatScopedArray
dfarr( new wxDataFormat
[count
] );
269 dobj
->GetAllFormats( dfarr
.get(), wxDataObject::Get
);
271 if( !dobj
->GetDataHere( dfarr
[*priv
], buffer
.data() ) )
274 while( XmClipboardCopyByName( xdisplay
, xwindow
, *data_id
,
275 buffer
.data(), size
, 0 )
276 == XmClipboardLocked
);
279 bool wxClipboard::AddData( wxDataObject
*data
)
281 wxCHECK_MSG( data
, false, "data is invalid" );
282 wxCHECK_MSG( m_open
, false, "clipboard not open" );
284 m_data
.Append( data
);
286 Display
* xdisplay
= wxGlobalDisplay();
287 Widget xwidget
= (Widget
)wxTheApp
->GetTopLevelRealizedWidget();
288 Window xwindow
= XtWindow( xwidget
);
289 wxXmString
label( wxTheApp
->GetAppDisplayName() );
290 Time timestamp
= XtLastTimestampProcessed( xdisplay
);
295 while( ( retval
= XmClipboardStartCopy( xdisplay
, xwindow
, label(),
299 == XmClipboardLocked
);
300 if( retval
!= XmClipboardSuccess
)
303 size_t count
= data
->GetFormatCount( wxDataObject::Get
);
304 wxDataFormatScopedArray
dfarr( new wxDataFormat
[count
] );
305 data
->GetAllFormats( dfarr
.get(), wxDataObject::Get
);
307 for( size_t i
= 0; i
< count
; ++i
)
309 size_t size
= data
->GetDataSize( dfarr
[i
] );
311 wxString id
= dfarr
[i
].GetId();
313 while( ( retval
= XmClipboardCopy( xdisplay
, xwindow
, itemId
,
315 NULL
, size
, i
, &data_id
) )
316 == XmClipboardLocked
);
318 m_idToObject
.Append( new wxDataIdToDataObject( data
, data_id
, size
) );
321 while( XmClipboardEndCopy( xdisplay
, xwindow
, itemId
)
322 == XmClipboardLocked
);
327 void wxClipboard::Close()
329 wxCHECK_RET( m_open
, "clipboard not open" );
334 bool wxClipboard::IsSupported(const wxDataFormat
& format
)
336 Display
* xdisplay
= wxGlobalDisplay();
337 Window xwindow
= XtWindow( (Widget
)wxTheApp
->GetTopLevelRealizedWidget() );
338 bool isSupported
= false;
340 unsigned long max_name_length
;
341 wxString id
= format
.GetId();
343 while( ( retval
= XmClipboardLock( xdisplay
, xwindow
) )
344 == XmClipboardLocked
);
345 if( retval
!= XmClipboardSuccess
)
348 if( XmClipboardInquireCount( xdisplay
, xwindow
, &count
, &max_name_length
)
349 == XmClipboardSuccess
)
351 wxCharBuffer
buf( max_name_length
+ 1 );
352 unsigned long copied
;
354 for( int i
= 0; i
< count
; ++i
)
356 if( XmClipboardInquireFormat( xdisplay
, xwindow
, i
+ 1,
357 (XtPointer
)buf
.data(),
358 max_name_length
, &copied
)
359 != XmClipboardSuccess
)
362 buf
.data()[copied
] = '\0';
372 XmClipboardUnlock( xdisplay
, xwindow
, False
);
377 class wxClipboardEndRetrieve
380 wxClipboardEndRetrieve( Display
* display
, Window window
)
381 : m_display( display
), m_window( window
) { }
382 ~wxClipboardEndRetrieve()
384 while( XmClipboardEndRetrieve( m_display
, m_window
)
385 == XmClipboardLocked
);
392 bool wxClipboard::GetData( wxDataObject
& data
)
394 wxCHECK_MSG( m_open
, false, "clipboard not open" );
396 Display
* xdisplay
= wxGlobalDisplay();
397 Window xwindow
= XtWindow( (Widget
)wxTheApp
->GetTopLevelRealizedWidget() );
398 Time timestamp
= XtLastTimestampProcessed( xdisplay
);
400 wxDataFormat chosenFormat
;
403 ///////////////////////////////////////////////////////////////////////////
404 // determine if the cliboard holds any format we like
405 ///////////////////////////////////////////////////////////////////////////
406 while( ( retval
= XmClipboardStartRetrieve( xdisplay
, xwindow
,
408 == XmClipboardLocked
);
409 if( retval
!= XmClipboardSuccess
)
412 wxClipboardEndRetrieve
endRetrieve( xdisplay
, xwindow
);
415 unsigned long max_name_length
;
416 size_t dfcount
= data
.GetFormatCount( wxDataObject::Set
);
417 wxDataFormatScopedArray
dfarr( new wxDataFormat
[dfcount
] );
418 data
.GetAllFormats( dfarr
.get(), wxDataObject::Set
);
420 if( XmClipboardInquireCount( xdisplay
, xwindow
, &count
, &max_name_length
)
421 == XmClipboardSuccess
)
423 wxCharBuffer
buf( max_name_length
+ 1 );
424 unsigned long copied
;
426 for( int i
= 0; i
< count
; ++i
)
428 if( XmClipboardInquireFormat( xdisplay
, xwindow
, i
+ 1,
429 (XtPointer
)buf
.data(),
430 max_name_length
, &copied
)
431 != XmClipboardSuccess
)
434 buf
.data()[copied
] = '\0';
436 // try preferred format
437 if( buf
== data
.GetPreferredFormat( wxDataObject::Set
).GetId() )
439 chosenFormat
= data
.GetPreferredFormat( wxDataObject::Set
);
443 // try all other formats
444 for( size_t i
= 0; i
< dfcount
; ++i
)
446 if( buf
== dfarr
[i
].GetId() )
447 chosenFormat
= dfarr
[i
];
452 if( chosenFormat
== wxDF_INVALID
)
455 ///////////////////////////////////////////////////////////////////////////
456 // now retrieve the data
457 ///////////////////////////////////////////////////////////////////////////
458 unsigned long length
, dummy1
;
460 wxString id
= chosenFormat
.GetId();
462 while( ( retval
= XmClipboardInquireLength( xdisplay
, xwindow
,
465 == XmClipboardLocked
);
466 if( retval
!= XmClipboardSuccess
)
469 wxCharBuffer
buf(length
);
471 while( ( retval
= XmClipboardRetrieve( xdisplay
, xwindow
,
473 (XtPointer
)buf
.data(),
474 length
, &dummy1
, &dummy2
) )
475 == XmClipboardLocked
);
476 if( retval
!= XmClipboardSuccess
)
479 if( !data
.SetData( chosenFormat
, length
, buf
.data() ) )
485 #endif // wxUSE_CLIPBOARD