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 /////////////////////////////////////////////////////////////////////////////
12 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
13 #pragma implementation
14 #pragma implementation "clipbrd.h"
17 // For compilers that support precompilation, includes "wx.h".
18 #include "wx/wxprec.h"
21 #include "wx/vms_x_fix.h"
22 #define XtWindow XTWINDOW
23 #define XtScreen XTSCREEN
24 #define XtParent XTPARENT
25 #define XtIsRealized XTISREALIZED
26 #define XtDisplay XTDISPLAY
34 #include "wx/bitmap.h"
36 #include "wx/clipbrd.h"
37 #include "wx/dataobj.h"
38 #include "wx/ptr_scpd.h"
41 #pragma message disable nosimpint
45 #include <Xm/CutPaste.h>
47 #pragma message enable nosimpint
50 #include "wx/motif/private.h"
52 bool wxOpenClipboard()
54 return wxTheClipboard
->Open();
57 bool wxCloseClipboard()
59 wxTheClipboard
->Close();
64 bool wxEmptyClipboard()
66 wxTheClipboard
->Clear();
70 bool wxClipboardOpen()
72 return wxTheClipboard
->IsOpened();
75 bool wxIsClipboardFormatAvailable(wxDataFormat dataFormat
)
77 return wxTheClipboard
->IsSupported( dataFormat
);
80 bool wxSetClipboardData(wxDataFormat dataFormat
, wxObject
*obj
,
81 int WXUNUSED(width
), int WXUNUSED(height
))
83 wxDataObject
* dobj
= NULL
;
85 if( dataFormat
== wxDF_TEXT
)
87 wxChar
* data
= (wxChar
*)obj
;
88 dobj
= new wxTextDataObject( data
);
90 else if( dataFormat
= wxDF_BITMAP
)
92 wxBitmap
* data
= (wxBitmap
*)obj
;
93 dobj
= new wxBitmapDataObject( *data
);
99 return wxTheClipboard
->SetData( dobj
);
102 wxObject
*wxGetClipboardData(wxDataFormat dataFormat
, long *len
)
104 wxDataObject
* dobj
= NULL
;
105 wxTextDataObject
* tobj
= NULL
;
106 wxBitmapDataObject
* bobj
= NULL
;
108 if( dataFormat
== wxDF_TEXT
)
110 dobj
= tobj
= new wxTextDataObject
;
112 else if( dataFormat
= wxDF_BITMAP
)
114 dobj
= bobj
= new wxBitmapDataObject
;
117 if( !dobj
|| !wxTheClipboard
->GetData( *dobj
) )
122 wxString text
= tobj
->GetText();
123 wxChar
* buf
= new wxChar
[text
.length() + 1];
125 if( len
) *len
= text
.length();
126 return (wxObject
*)wxStrcpy( buf
, text
.c_str() );
131 return new wxBitmap( bobj
->GetBitmap() );
134 return NULL
; // just in case...
137 wxDataFormat
wxEnumClipboardFormats(wxDataFormat dataFormat
)
139 // Only wxDF_TEXT supported
140 if (dataFormat
== wxDF_TEXT
)
146 wxDataFormat
wxRegisterClipboardFormat(char *WXUNUSED(formatName
))
152 bool wxGetClipboardFormatName(wxDataFormat dataFormat
, char *formatName
,
155 wxStrncpy( formatName
, dataFormat
.GetId().c_str(), maxCount
);
160 //-----------------------------------------------------------------------------
162 //-----------------------------------------------------------------------------
164 struct wxDataIdToDataObject
166 wxDataIdToDataObject( wxDataObject
* o
, long d
, size_t s
)
167 : object( o
), size( s
), dataId( d
) { }
169 wxDataObject
* object
;
174 #include "wx/listimpl.cpp"
176 WX_DEFINE_LIST(wxDataObjectList
);
177 WX_DEFINE_LIST(wxDataIdToDataObjectList
);
181 #if wxCHECK_LESSTIF()
182 static void wxClipboardCallback( Widget widget
, int* data_id
,
183 int* priv
, int* reason
);
185 static void wxClipboardCallback( Widget widget
, long* data_id
,
186 long* priv
, int* reason
);
190 IMPLEMENT_DYNAMIC_CLASS(wxClipboard
,wxObject
)
192 wxClipboard::wxClipboard()
197 wxClipboard::~wxClipboard()
202 void wxClipboard::Clear()
204 wxDataObjectList::compatibility_iterator node
= m_data
.GetFirst();
207 delete node
->GetData();
208 node
= node
->GetNext();
212 for( wxDataIdToDataObjectList::compatibility_iterator node2
= m_idToObject
.GetFirst();
213 node2
; node2
= node2
->GetNext() )
215 delete node2
->GetData();
217 m_idToObject
.Clear();
220 bool wxClipboard::Open()
222 wxCHECK_MSG( !m_open
, false, "clipboard already open" );
229 bool wxClipboard::SetData( wxDataObject
*data
)
231 wxCHECK_MSG( data
, false, "data is invalid" );
232 wxCHECK_MSG( m_open
, false, "clipboard not open" );
236 return AddData( data
);
239 wxDECLARE_SCOPED_ARRAY( wxDataFormat
, wxDataFormatScopedArray
);
240 wxDEFINE_SCOPED_ARRAY( wxDataFormat
, wxDataFormatScopedArray
);
242 #if wxCHECK_LESSTIF()
243 void wxClipboardCallback( Widget xwidget
, int* data_id
,
244 int* priv
, int* reason
)
246 void wxClipboardCallback( Widget xwidget
, long* data_id
,
247 long* priv
, int* reason
)
250 Display
* xdisplay
= XtDisplay( xwidget
);
251 Window xwindow
= XtWindow( xwidget
);
252 wxDataObject
* dobj
= NULL
;
255 for( wxDataIdToDataObjectList::compatibility_iterator node2
=
256 wxTheClipboard
->m_idToObject
.GetFirst();
257 node2
; node2
= node2
->GetNext() )
259 wxDataIdToDataObject
* dido
= node2
->GetData();
260 if( dido
->dataId
== *data_id
)
270 wxCharBuffer
buffer(size
);
271 size_t count
= dobj
->GetFormatCount( wxDataObject::Get
);
272 wxDataFormatScopedArray
dfarr( new wxDataFormat
[count
] );
273 dobj
->GetAllFormats( dfarr
.get(), wxDataObject::Get
);
275 if( !dobj
->GetDataHere( dfarr
[*priv
], buffer
.data() ) )
278 while( XmClipboardCopyByName( xdisplay
, xwindow
, *data_id
,
279 buffer
.data(), size
, 0 )
280 == XmClipboardLocked
);
283 bool wxClipboard::AddData( wxDataObject
*data
)
285 wxCHECK_MSG( data
, false, "data is invalid" );
286 wxCHECK_MSG( m_open
, false, "clipboard not open" );
288 m_data
.Append( data
);
290 Display
* xdisplay
= wxGlobalDisplay();
291 Widget xwidget
= (Widget
)wxTheApp
->GetTopLevelRealizedWidget();
292 Window xwindow
= XtWindow( xwidget
);
293 wxXmString
label( wxTheApp
->GetAppName() );
294 Time timestamp
= XtLastTimestampProcessed( xdisplay
);
299 while( ( retval
= XmClipboardStartCopy( xdisplay
, xwindow
, label(),
303 == XmClipboardLocked
);
304 if( retval
!= XmClipboardSuccess
)
307 size_t count
= data
->GetFormatCount( wxDataObject::Get
);
308 wxDataFormatScopedArray
dfarr( new wxDataFormat
[count
] );
309 data
->GetAllFormats( dfarr
.get(), wxDataObject::Get
);
311 for( size_t i
= 0; i
< count
; ++i
)
313 size_t size
= data
->GetDataSize( dfarr
[i
] );
315 wxString id
= dfarr
[i
].GetId();
317 while( ( retval
= XmClipboardCopy( xdisplay
, xwindow
, itemId
,
318 wxConstCast(id
.c_str(), char),
319 NULL
, size
, i
, &data_id
) )
320 == XmClipboardLocked
);
322 m_idToObject
.Append( new wxDataIdToDataObject( data
, data_id
, size
) );
325 while( XmClipboardEndCopy( xdisplay
, xwindow
, itemId
)
326 == XmClipboardLocked
);
331 void wxClipboard::Close()
333 wxCHECK_RET( m_open
, "clipboard not open" );
338 bool wxClipboard::IsSupported(const wxDataFormat
& format
)
340 Display
* xdisplay
= wxGlobalDisplay();
341 Window xwindow
= XtWindow( (Widget
)wxTheApp
->GetTopLevelRealizedWidget() );
342 bool isSupported
= false;
344 unsigned long max_name_length
;
345 wxString id
= format
.GetId();
347 while( ( retval
= XmClipboardLock( xdisplay
, xwindow
) )
348 == XmClipboardLocked
);
349 if( retval
!= XmClipboardSuccess
)
352 if( XmClipboardInquireCount( xdisplay
, xwindow
, &count
, &max_name_length
)
353 == XmClipboardSuccess
)
355 wxCharBuffer
buf( max_name_length
+ 1 );
356 unsigned long copied
;
358 for( int i
= 0; i
< count
; ++i
)
360 if( XmClipboardInquireFormat( xdisplay
, xwindow
, i
+ 1,
361 (XtPointer
)buf
.data(),
362 max_name_length
, &copied
)
363 != XmClipboardSuccess
)
366 buf
.data()[copied
] = '\0';
376 XmClipboardUnlock( xdisplay
, xwindow
, False
);
381 class wxClipboardEndRetrieve
384 wxClipboardEndRetrieve( Display
* display
, Window window
)
385 : m_display( display
), m_window( window
) { }
386 ~wxClipboardEndRetrieve()
388 while( XmClipboardEndRetrieve( m_display
, m_window
)
389 == XmClipboardLocked
);
396 bool wxClipboard::GetData( wxDataObject
& data
)
398 wxCHECK_MSG( m_open
, false, "clipboard not open" );
400 Display
* xdisplay
= wxGlobalDisplay();
401 Window xwindow
= XtWindow( (Widget
)wxTheApp
->GetTopLevelRealizedWidget() );
402 Time timestamp
= XtLastTimestampProcessed( xdisplay
);
404 wxDataFormat chosenFormat
;
407 ///////////////////////////////////////////////////////////////////////////
408 // determine if the cliboard holds any format we like
409 ///////////////////////////////////////////////////////////////////////////
410 while( ( retval
= XmClipboardStartRetrieve( xdisplay
, xwindow
,
412 == XmClipboardLocked
);
413 if( retval
!= XmClipboardSuccess
)
416 wxClipboardEndRetrieve
endRetrieve( xdisplay
, xwindow
);
419 unsigned long max_name_length
;
420 size_t dfcount
= data
.GetFormatCount( wxDataObject::Set
);
421 wxDataFormatScopedArray
dfarr( new wxDataFormat
[dfcount
] );
422 data
.GetAllFormats( dfarr
.get(), wxDataObject::Set
);
424 if( XmClipboardInquireCount( xdisplay
, xwindow
, &count
, &max_name_length
)
425 == XmClipboardSuccess
)
427 wxCharBuffer
buf( max_name_length
+ 1 );
428 unsigned long copied
;
430 for( int i
= 0; i
< count
; ++i
)
432 if( XmClipboardInquireFormat( xdisplay
, xwindow
, i
+ 1,
433 (XtPointer
)buf
.data(),
434 max_name_length
, &copied
)
435 != XmClipboardSuccess
)
438 buf
.data()[copied
] = '\0';
440 // try preferred format
441 if( buf
== data
.GetPreferredFormat( wxDataObject::Set
).GetId() )
443 chosenFormat
= data
.GetPreferredFormat( wxDataObject::Set
);
447 // try all other formats
448 for( size_t i
= 0; i
< dfcount
; ++i
)
450 if( buf
== dfarr
[i
].GetId() )
451 chosenFormat
= dfarr
[i
];
456 if( chosenFormat
== wxDF_INVALID
)
459 ///////////////////////////////////////////////////////////////////////////
460 // now retrieve the data
461 ///////////////////////////////////////////////////////////////////////////
462 unsigned long length
, dummy1
;
464 wxString id
= chosenFormat
.GetId();
466 while( ( retval
= XmClipboardInquireLength( xdisplay
, xwindow
,
467 wxConstCast(id
.c_str(), char),
469 == XmClipboardLocked
);
470 if( retval
!= XmClipboardSuccess
)
473 wxCharBuffer
buf(length
);
475 while( ( retval
= XmClipboardRetrieve( xdisplay
, xwindow
,
476 wxConstCast(id
.c_str(), char),
477 (XtPointer
)buf
.data(),
478 length
, &dummy1
, &dummy2
) )
479 == XmClipboardLocked
);
480 if( retval
!= XmClipboardSuccess
)
483 if( !data
.SetData( chosenFormat
, length
, buf
.data() ) )
489 #endif // wxUSE_CLIPBOARD