]> git.saurik.com Git - wxWidgets.git/blame - src/motif/clipbrd.cpp
use alpha channel in Blit() as well and not only in DrawBitmap()
[wxWidgets.git] / src / motif / clipbrd.cpp
CommitLineData
4bb6408c
JS
1/////////////////////////////////////////////////////////////////////////////
2// Name: clipbrd.cpp
3// Purpose: Clipboard functionality
4// Author: Julian Smart
dd38c875 5// Modified by: Mattia Barbon (added support for generic wxDataObjects)
4bb6408c
JS
6// Created: 17/09/98
7// RCS-ID: $Id$
8// Copyright: (c) Julian Smart
9// Licence: wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
12#ifdef __GNUG__
13#pragma implementation
14#pragma implementation "clipbrd.h"
15#endif
16
dfe1eee3
VZ
17#include "wx/defs.h"
18
19#if wxUSE_CLIPBOARD
20
4bb6408c 21#include "wx/app.h"
4bb6408c
JS
22#include "wx/bitmap.h"
23#include "wx/utils.h"
4bb6408c 24#include "wx/clipbrd.h"
2d120f83 25#include "wx/dataobj.h"
dd38c875 26#include "wx/ptr_scpd.h"
2d120f83 27
fd304d98
MB
28#include "wx/listimpl.cpp"
29WX_DEFINE_LIST(wxDataObjectList);
30
338dd992
JJ
31#ifdef __VMS__
32#pragma message disable nosimpint
33#endif
2d120f83
JS
34#include <Xm/Xm.h>
35#include <Xm/CutPaste.h>
338dd992
JJ
36#ifdef __VMS__
37#pragma message enable nosimpint
38#endif
4bb6408c 39
dd38c875 40#include "wx/motif/private.h"
2d120f83 41
4bb6408c
JS
42bool wxOpenClipboard()
43{
dd38c875 44 return wxTheClipboard->Open();
4bb6408c
JS
45}
46
47bool wxCloseClipboard()
48{
dd38c875
MB
49 wxTheClipboard->Close();
50
51 return true;
4bb6408c
JS
52}
53
54bool wxEmptyClipboard()
55{
dd38c875
MB
56 wxTheClipboard->Clear();
57 return true;
4bb6408c
JS
58}
59
60bool wxClipboardOpen()
61{
dd38c875 62 return wxTheClipboard->IsOpened();
4bb6408c
JS
63}
64
2d120f83 65bool wxIsClipboardFormatAvailable(wxDataFormat dataFormat)
4bb6408c 66{
dd38c875
MB
67 return wxTheClipboard->IsSupported( dataFormat );
68}
2d120f83 69
dd38c875
MB
70bool wxSetClipboardData(wxDataFormat dataFormat, wxObject *obj,
71 int WXUNUSED(width), int WXUNUSED(height))
72{
73 wxDataObject* dobj = NULL;
2d120f83 74
dd38c875
MB
75 if( dataFormat == wxDF_TEXT )
76 {
77 wxChar* data = (wxChar*)obj;
78 dobj = new wxTextDataObject( data );
79 }
80 else if( dataFormat = wxDF_BITMAP )
81 {
82 wxBitmap* data = (wxBitmap*)obj;
83 dobj = new wxBitmapDataObject( *data );
84 }
2d120f83 85
dd38c875
MB
86 if( !dobj )
87 return false;
4bb6408c 88
dd38c875 89 return wxTheClipboard->SetData( dobj );
4bb6408c
JS
90}
91
2d120f83 92wxObject *wxGetClipboardData(wxDataFormat dataFormat, long *len)
4bb6408c 93{
dd38c875
MB
94 wxDataObject* dobj = NULL;
95 wxTextDataObject* tobj = NULL;
96 wxBitmapDataObject* bobj = NULL;
2d120f83 97
dd38c875
MB
98 if( dataFormat == wxDF_TEXT )
99 {
100 dobj = tobj = new wxTextDataObject;
101 }
102 else if( dataFormat = wxDF_BITMAP )
103 {
104 dobj = bobj = new wxBitmapDataObject;
105 }
2d120f83 106
dd38c875
MB
107 if( !dobj || !wxTheClipboard->GetData( *dobj ) )
108 return NULL;
2d120f83 109
dd38c875 110 if( tobj )
2d120f83 111 {
dd38c875
MB
112 wxString text = tobj->GetText();
113 wxChar* buf = new wxChar[text.length() + 1];
114
115 if( len ) *len = text.length();
116 return (wxObject*)wxStrcpy( buf, text.c_str() );
117 }
118 else if( bobj )
119 {
120 if( len ) *len = 0;
121 return new wxBitmap( bobj->GetBitmap() );
2d120f83
JS
122 }
123
dd38c875 124 return NULL; // just in case...
4bb6408c
JS
125}
126
dd38c875 127wxDataFormat wxEnumClipboardFormats(wxDataFormat dataFormat)
4bb6408c 128{
2d120f83 129 // Only wxDF_TEXT supported
da175b2c 130 if (dataFormat == wxDF_TEXT)
2d120f83
JS
131 return wxDF_TEXT;
132 else
da175b2c 133 return wxDF_INVALID;
4bb6408c
JS
134}
135
dd38c875 136wxDataFormat wxRegisterClipboardFormat(char *WXUNUSED(formatName))
4bb6408c 137{
2d120f83 138 // Not supported
dd38c875 139 return wxDF_INVALID;
4bb6408c
JS
140}
141
dd38c875
MB
142bool wxGetClipboardFormatName(wxDataFormat dataFormat, char *formatName,
143 int maxCount)
4bb6408c 144{
dd38c875
MB
145 wxStrncpy( formatName, dataFormat.GetId().c_str(), maxCount );
146
147 return true;
4bb6408c
JS
148}
149
2d120f83
JS
150//-----------------------------------------------------------------------------
151// wxClipboard
152//-----------------------------------------------------------------------------
4bb6408c 153
2d120f83 154IMPLEMENT_DYNAMIC_CLASS(wxClipboard,wxObject)
4bb6408c 155
4bb6408c
JS
156wxClipboard::wxClipboard()
157{
dd38c875 158 m_open = false;
4bb6408c
JS
159}
160
161wxClipboard::~wxClipboard()
162{
2d120f83 163 Clear();
4bb6408c
JS
164}
165
2d120f83 166void wxClipboard::Clear()
4bb6408c 167{
fd304d98 168 wxDataObjectList::Node* node = m_data.GetFirst();
2d120f83
JS
169 while (node)
170 {
fd304d98 171 wxDataObject* data = node->GetData();
2d120f83 172 delete data;
fd304d98 173 node = node->GetNext();
2d120f83
JS
174 }
175 m_data.Clear();
4bb6408c
JS
176}
177
2d120f83 178bool wxClipboard::Open()
4bb6408c 179{
dd38c875 180 wxCHECK_MSG( !m_open, false, "clipboard already open" );
2d120f83 181
dd38c875 182 m_open = true;
4bb6408c 183
dd38c875 184 return true;
2d120f83 185}
4bb6408c 186
2d120f83
JS
187bool wxClipboard::SetData( wxDataObject *data )
188{
dd38c875
MB
189 wxCHECK_MSG( data, false, "data is invalid" );
190 wxCHECK_MSG( m_open, false, "clipboard not open" );
2d120f83 191
12db77ca
VZ
192 Clear();
193
194 return AddData( data );
195}
196
dd38c875
MB
197wxDECLARE_SCOPED_ARRAY( wxDataFormat, wxDataFormatScopedArray );
198wxDEFINE_SCOPED_ARRAY( wxDataFormat, wxDataFormatScopedArray );
199
12db77ca
VZ
200bool wxClipboard::AddData( wxDataObject *data )
201{
dd38c875
MB
202 wxCHECK_MSG( data, false, "data is invalid" );
203 wxCHECK_MSG( m_open, false, "clipboard not open" );
204
205 m_data.Append( data );
206
207 Display* xdisplay = wxGlobalDisplay();
208 Window xwindow = XtWindow( (Widget)wxTheApp->GetTopLevelWidget() );
209 wxXmString label( wxTheApp->GetAppName() );
210 Time timestamp = XtLastTimestampProcessed( xdisplay );
211 long itemId;
212
213 int retval;
12db77ca 214
dd38c875
MB
215 while( ( retval = XmClipboardStartCopy( xdisplay, xwindow, label(),
216 timestamp, (Widget)NULL,
217 (XmCutPasteProc)NULL,
218 &itemId ) )
219 == XmClipboardLocked );
220 if( retval != XmClipboardSuccess )
221 return false;
222
223 size_t count = data->GetFormatCount( wxDataObject::Get );
224 wxDataFormatScopedArray dfarr( new wxDataFormat[count] );
225 data->GetAllFormats( dfarr.get(), wxDataObject::Get );
226
227 for( size_t i = 0; i < count; ++i )
2d120f83 228 {
dd38c875
MB
229 size_t size = data->GetDataSize( dfarr[i] );
230 wxCharBuffer buffer(size);
231
232 if( !data->GetDataHere( dfarr[i], buffer.data() ) )
233 continue;
234
235 wxString id = dfarr[i].GetId();
236
237 while( ( retval = XmClipboardCopy( xdisplay, xwindow, itemId,
238 wxConstCast(id.c_str(), char),
239 buffer.data(), size, 0, NULL ) )
240 == XmClipboardLocked );
2d120f83 241 }
dd38c875
MB
242
243 while( XmClipboardEndCopy( xdisplay, xwindow, itemId )
244 == XmClipboardLocked );
245
246 return true;
2d120f83 247}
4bb6408c 248
2d120f83
JS
249void wxClipboard::Close()
250{
251 wxCHECK_RET( m_open, "clipboard not open" );
252
dd38c875 253 m_open = false;
4bb6408c
JS
254}
255
dd38c875 256bool wxClipboard::IsSupported(const wxDataFormat& format)
4bb6408c 257{
dd38c875
MB
258 Display* xdisplay = wxGlobalDisplay();
259 Window xwindow = XtWindow( (Widget)wxTheApp->GetTopLevelWidget() );
260 bool isSupported = false;
261 int retval, count;
262 unsigned long max_name_length;
263 wxString id = format.GetId();
264
265 while( ( retval = XmClipboardLock( xdisplay, xwindow ) )
266 == XmClipboardLocked );
267 if( retval != XmClipboardSuccess )
268 return false;
269
270 if( XmClipboardInquireCount( xdisplay, xwindow, &count, &max_name_length )
271 == XmClipboardSuccess )
2d120f83 272 {
dd38c875
MB
273 wxCharBuffer buf( max_name_length + 1 );
274 unsigned long copied;
275
276 for( int i = 0; i < count; ++i )
2d120f83 277 {
dd38c875
MB
278 if( XmClipboardInquireFormat( xdisplay, xwindow, i + 1,
279 (XtPointer)buf.data(),
280 max_name_length, &copied )
281 != XmClipboardSuccess )
282 continue;
283
284 buf.data()[copied] = '\0';
285
286 if( buf == id )
2d120f83 287 {
dd38c875
MB
288 isSupported = true;
289 break;
2d120f83 290 }
2d120f83
JS
291 }
292 }
4bb6408c 293
dd38c875 294 XmClipboardUnlock( xdisplay, xwindow, False );
2d120f83 295
dd38c875 296 return isSupported;
2d120f83 297}
4bb6408c 298
dd38c875 299class wxClipboardEndRetrieve
2d120f83 300{
dd38c875
MB
301public:
302 wxClipboardEndRetrieve( Display* display, Window window )
303 : m_display( display ), m_window( window ) { }
304 ~wxClipboardEndRetrieve()
305 {
306 while( XmClipboardEndRetrieve( m_display, m_window )
307 == XmClipboardLocked );
308 }
309private:
310 Display* m_display;
311 Window m_window;
312};
2d120f83 313
dd38c875 314bool wxClipboard::GetData( wxDataObject& data )
4bb6408c 315{
dd38c875
MB
316 wxCHECK_MSG( m_open, false, "clipboard not open" );
317
318 Display* xdisplay = wxGlobalDisplay();
319 Window xwindow = XtWindow( (Widget)wxTheApp->GetTopLevelWidget() );
320 Time timestamp = XtLastTimestampProcessed( xdisplay );
321
322 wxDataFormat chosenFormat;
323 int retval;
324
325 ///////////////////////////////////////////////////////////////////////////
326 // determine if the cliboard holds any format we like
327 ///////////////////////////////////////////////////////////////////////////
328 while( ( retval = XmClipboardStartRetrieve( xdisplay, xwindow,
329 timestamp ) )
330 == XmClipboardLocked );
331 if( retval != XmClipboardSuccess )
332 return false;
333
334 wxClipboardEndRetrieve endRetrieve( xdisplay, xwindow );
335
336 int count;
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 );
2d120f83 341
dd38c875
MB
342 if( XmClipboardInquireCount( xdisplay, xwindow, &count, &max_name_length )
343 == XmClipboardSuccess )
344 {
345 wxCharBuffer buf( max_name_length + 1 );
346 unsigned long copied;
4bb6408c 347
dd38c875
MB
348 for( int i = 0; i < count; ++i )
349 {
350 if( XmClipboardInquireFormat( xdisplay, xwindow, i + 1,
351 (XtPointer)buf.data(),
352 max_name_length, &copied )
353 != XmClipboardSuccess )
354 continue;
4bb6408c 355
dd38c875 356 buf.data()[copied] = '\0';
4bb6408c 357
dd38c875
MB
358 // try preferred format
359 if( buf == data.GetPreferredFormat( wxDataObject::Set ).GetId() )
360 {
361 chosenFormat = data.GetPreferredFormat( wxDataObject::Set );
362 break;
363 }
2d120f83 364
dd38c875
MB
365 // try all other formats
366 for( size_t i = 0; i < dfcount; ++i )
367 {
368 if( buf == dfarr[i].GetId() )
369 chosenFormat = dfarr[i];
370 }
371 }
2d120f83 372 }
4bb6408c 373
dd38c875
MB
374 if( chosenFormat == wxDF_INVALID )
375 return false;
376
377 ///////////////////////////////////////////////////////////////////////////
378 // now retrieve the data
379 ///////////////////////////////////////////////////////////////////////////
380 unsigned long length, dummy1;
381 long dummy2;
382 wxString id = chosenFormat.GetId();
383
384 while( ( retval = XmClipboardInquireLength( xdisplay, xwindow,
385 wxConstCast(id.c_str(), char),
386 &length ) )
387 == XmClipboardLocked );
388 if( retval != XmClipboardSuccess )
389 return false;
390
391 wxCharBuffer buf(length);
392
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 )
399 return false;
400
401 if( !data.SetData( chosenFormat, length, buf.data() ) )
402 return false;
403
404 return true;
4bb6408c
JS
405}
406
dfe1eee3 407#endif // wxUSE_CLIPBOARD