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"
28 #include "wx/listimpl.cpp"
29 WX_DEFINE_LIST(wxDataObjectList
);
32 #pragma message disable nosimpint
35 #include <Xm/CutPaste.h>
37 #pragma message enable nosimpint
40 #include "wx/motif/private.h"
42 bool wxOpenClipboard()
44 return wxTheClipboard
->Open();
47 bool wxCloseClipboard()
49 wxTheClipboard
->Close();
54 bool wxEmptyClipboard()
56 wxTheClipboard
->Clear();
60 bool wxClipboardOpen()
62 return wxTheClipboard
->IsOpened();
65 bool wxIsClipboardFormatAvailable(wxDataFormat dataFormat
)
67 return wxTheClipboard
->IsSupported( dataFormat
);
70 bool wxSetClipboardData(wxDataFormat dataFormat
, wxObject
*obj
,
71 int WXUNUSED(width
), int WXUNUSED(height
))
73 wxDataObject
* dobj
= NULL
;
75 if( dataFormat
== wxDF_TEXT
)
77 wxChar
* data
= (wxChar
*)obj
;
78 dobj
= new wxTextDataObject( data
);
80 else if( dataFormat
= wxDF_BITMAP
)
82 wxBitmap
* data
= (wxBitmap
*)obj
;
83 dobj
= new wxBitmapDataObject( *data
);
89 return wxTheClipboard
->SetData( dobj
);
92 wxObject
*wxGetClipboardData(wxDataFormat dataFormat
, long *len
)
94 wxDataObject
* dobj
= NULL
;
95 wxTextDataObject
* tobj
= NULL
;
96 wxBitmapDataObject
* bobj
= NULL
;
98 if( dataFormat
== wxDF_TEXT
)
100 dobj
= tobj
= new wxTextDataObject
;
102 else if( dataFormat
= wxDF_BITMAP
)
104 dobj
= bobj
= new wxBitmapDataObject
;
107 if( !dobj
|| !wxTheClipboard
->GetData( *dobj
) )
112 wxString text
= tobj
->GetText();
113 wxChar
* buf
= new wxChar
[text
.length() + 1];
115 if( len
) *len
= text
.length();
116 return (wxObject
*)wxStrcpy( buf
, text
.c_str() );
121 return new wxBitmap( bobj
->GetBitmap() );
124 return NULL
; // just in case...
127 wxDataFormat
wxEnumClipboardFormats(wxDataFormat dataFormat
)
129 // Only wxDF_TEXT supported
130 if (dataFormat
== wxDF_TEXT
)
136 wxDataFormat
wxRegisterClipboardFormat(char *WXUNUSED(formatName
))
142 bool wxGetClipboardFormatName(wxDataFormat dataFormat
, char *formatName
,
145 wxStrncpy( formatName
, dataFormat
.GetId().c_str(), maxCount
);
150 //-----------------------------------------------------------------------------
152 //-----------------------------------------------------------------------------
154 IMPLEMENT_DYNAMIC_CLASS(wxClipboard
,wxObject
)
156 wxClipboard::wxClipboard()
161 wxClipboard::~wxClipboard()
166 void wxClipboard::Clear()
168 wxDataObjectList::Node
* node
= m_data
.GetFirst();
171 wxDataObject
* data
= node
->GetData();
173 node
= node
->GetNext();
178 bool wxClipboard::Open()
180 wxCHECK_MSG( !m_open
, false, "clipboard already open" );
187 bool wxClipboard::SetData( wxDataObject
*data
)
189 wxCHECK_MSG( data
, false, "data is invalid" );
190 wxCHECK_MSG( m_open
, false, "clipboard not open" );
194 return AddData( data
);
197 wxDECLARE_SCOPED_ARRAY( wxDataFormat
, wxDataFormatScopedArray
);
198 wxDEFINE_SCOPED_ARRAY( wxDataFormat
, wxDataFormatScopedArray
);
200 bool wxClipboard::AddData( wxDataObject
*data
)
202 wxCHECK_MSG( data
, false, "data is invalid" );
203 wxCHECK_MSG( m_open
, false, "clipboard not open" );
205 m_data
.Append( data
);
207 Display
* xdisplay
= wxGlobalDisplay();
208 Window xwindow
= XtWindow( (Widget
)wxTheApp
->GetTopLevelWidget() );
209 wxXmString
label( wxTheApp
->GetAppName() );
210 Time timestamp
= XtLastTimestampProcessed( xdisplay
);
215 while( ( retval
= XmClipboardStartCopy( xdisplay
, xwindow
, label(),
216 timestamp
, (Widget
)NULL
,
217 (XmCutPasteProc
)NULL
,
219 == XmClipboardLocked
);
220 if( retval
!= XmClipboardSuccess
)
223 size_t count
= data
->GetFormatCount( wxDataObject::Get
);
224 wxDataFormatScopedArray
dfarr( new wxDataFormat
[count
] );
225 data
->GetAllFormats( dfarr
.get(), wxDataObject::Get
);
227 for( size_t i
= 0; i
< count
; ++i
)
229 size_t size
= data
->GetDataSize( dfarr
[i
] );
230 wxCharBuffer
buffer(size
);
232 if( !data
->GetDataHere( dfarr
[i
], buffer
.data() ) )
235 wxString id
= dfarr
[i
].GetId();
237 while( ( retval
= XmClipboardCopy( xdisplay
, xwindow
, itemId
,
238 wxConstCast(id
.c_str(), char),
239 buffer
.data(), size
, 0, NULL
) )
240 == XmClipboardLocked
);
243 while( XmClipboardEndCopy( xdisplay
, xwindow
, itemId
)
244 == XmClipboardLocked
);
249 void wxClipboard::Close()
251 wxCHECK_RET( m_open
, "clipboard not open" );
256 bool wxClipboard::IsSupported(const wxDataFormat
& format
)
258 Display
* xdisplay
= wxGlobalDisplay();
259 Window xwindow
= XtWindow( (Widget
)wxTheApp
->GetTopLevelWidget() );
260 bool isSupported
= false;
262 unsigned long max_name_length
;
263 wxString id
= format
.GetId();
265 while( ( retval
= XmClipboardLock( xdisplay
, xwindow
) )
266 == XmClipboardLocked
);
267 if( retval
!= XmClipboardSuccess
)
270 if( XmClipboardInquireCount( xdisplay
, xwindow
, &count
, &max_name_length
)
271 == XmClipboardSuccess
)
273 wxCharBuffer
buf( max_name_length
+ 1 );
274 unsigned long copied
;
276 for( int i
= 0; i
< count
; ++i
)
278 if( XmClipboardInquireFormat( xdisplay
, xwindow
, i
+ 1,
279 (XtPointer
)buf
.data(),
280 max_name_length
, &copied
)
281 != XmClipboardSuccess
)
284 buf
.data()[copied
] = '\0';
294 XmClipboardUnlock( xdisplay
, xwindow
, False
);
299 class wxClipboardEndRetrieve
302 wxClipboardEndRetrieve( Display
* display
, Window window
)
303 : m_display( display
), m_window( window
) { }
304 ~wxClipboardEndRetrieve()
306 while( XmClipboardEndRetrieve( m_display
, m_window
)
307 == XmClipboardLocked
);
314 bool wxClipboard::GetData( wxDataObject
& data
)
316 wxCHECK_MSG( m_open
, false, "clipboard not open" );
318 Display
* xdisplay
= wxGlobalDisplay();
319 Window xwindow
= XtWindow( (Widget
)wxTheApp
->GetTopLevelWidget() );
320 Time timestamp
= XtLastTimestampProcessed( xdisplay
);
322 wxDataFormat chosenFormat
;
325 ///////////////////////////////////////////////////////////////////////////
326 // determine if the cliboard holds any format we like
327 ///////////////////////////////////////////////////////////////////////////
328 while( ( retval
= XmClipboardStartRetrieve( xdisplay
, xwindow
,
330 == XmClipboardLocked
);
331 if( retval
!= XmClipboardSuccess
)
334 wxClipboardEndRetrieve
endRetrieve( xdisplay
, xwindow
);
337 unsigned long max_name_length
;
338 size_t dfcount
= data
.GetFormatCount( wxDataObject::Set
);
339 wxDataFormatScopedArray
dfarr( new wxDataFormat
[dfcount
] );
340 data
.GetAllFormats( dfarr
.get(), wxDataObject::Set
);
342 if( XmClipboardInquireCount( xdisplay
, xwindow
, &count
, &max_name_length
)
343 == XmClipboardSuccess
)
345 wxCharBuffer
buf( max_name_length
+ 1 );
346 unsigned long copied
;
348 for( int i
= 0; i
< count
; ++i
)
350 if( XmClipboardInquireFormat( xdisplay
, xwindow
, i
+ 1,
351 (XtPointer
)buf
.data(),
352 max_name_length
, &copied
)
353 != XmClipboardSuccess
)
356 buf
.data()[copied
] = '\0';
358 // try preferred format
359 if( buf
== data
.GetPreferredFormat( wxDataObject::Set
).GetId() )
361 chosenFormat
= data
.GetPreferredFormat( wxDataObject::Set
);
365 // try all other formats
366 for( size_t i
= 0; i
< dfcount
; ++i
)
368 if( buf
== dfarr
[i
].GetId() )
369 chosenFormat
= dfarr
[i
];
374 if( chosenFormat
== wxDF_INVALID
)
377 ///////////////////////////////////////////////////////////////////////////
378 // now retrieve the data
379 ///////////////////////////////////////////////////////////////////////////
380 unsigned long length
, dummy1
;
382 wxString id
= chosenFormat
.GetId();
384 while( ( retval
= XmClipboardInquireLength( xdisplay
, xwindow
,
385 wxConstCast(id
.c_str(), char),
387 == XmClipboardLocked
);
388 if( retval
!= XmClipboardSuccess
)
391 wxCharBuffer
buf(length
);
393 while( ( retval
= XmClipboardRetrieve( xdisplay
, xwindow
,
394 wxConstCast(id
.c_str(), char),
395 (XtPointer
)buf
.data(),
396 length
, &dummy1
, &dummy2
) )
397 == XmClipboardLocked
);
398 if( retval
!= XmClipboardSuccess
)
401 if( !data
.SetData( chosenFormat
, length
, buf
.data() ) )
407 #endif // wxUSE_CLIPBOARD