]> git.saurik.com Git - wxWidgets.git/blob - src/motif/clipbrd.cpp
wxCocoa: Added preliminary Blit support
[wxWidgets.git] / src / motif / clipbrd.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: clipbrd.cpp
3 // Purpose: Clipboard functionality
4 // Author: Julian Smart
5 // Modified by: Mattia Barbon (added support for generic wxDataObjects)
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
17 #ifdef __VMS
18 #include "wx/vms_x_fix.h"
19 #define XtWindow XTWINDOW
20 #define XtScreen XTSCREEN
21 #define XtParent XTPARENT
22 #define XtIsRealized XTISREALIZED
23 #define XtDisplay XTDISPLAY
24 #endif
25
26 #include "wx/defs.h"
27
28 #if wxUSE_CLIPBOARD
29
30 #include "wx/app.h"
31 #include "wx/bitmap.h"
32 #include "wx/utils.h"
33 #include "wx/clipbrd.h"
34 #include "wx/dataobj.h"
35 #include "wx/ptr_scpd.h"
36
37 #ifdef __VMS__
38 #pragma message disable nosimpint
39
40 #endif
41 #include <Xm/Xm.h>
42 #include <Xm/CutPaste.h>
43 #ifdef __VMS__
44 #pragma message enable nosimpint
45 #endif
46
47 #include "wx/motif/private.h"
48
49 bool wxOpenClipboard()
50 {
51 return wxTheClipboard->Open();
52 }
53
54 bool wxCloseClipboard()
55 {
56 wxTheClipboard->Close();
57
58 return true;
59 }
60
61 bool wxEmptyClipboard()
62 {
63 wxTheClipboard->Clear();
64 return true;
65 }
66
67 bool wxClipboardOpen()
68 {
69 return wxTheClipboard->IsOpened();
70 }
71
72 bool wxIsClipboardFormatAvailable(wxDataFormat dataFormat)
73 {
74 return wxTheClipboard->IsSupported( dataFormat );
75 }
76
77 bool wxSetClipboardData(wxDataFormat dataFormat, wxObject *obj,
78 int WXUNUSED(width), int WXUNUSED(height))
79 {
80 wxDataObject* dobj = NULL;
81
82 if( dataFormat == wxDF_TEXT )
83 {
84 wxChar* data = (wxChar*)obj;
85 dobj = new wxTextDataObject( data );
86 }
87 else if( dataFormat = wxDF_BITMAP )
88 {
89 wxBitmap* data = (wxBitmap*)obj;
90 dobj = new wxBitmapDataObject( *data );
91 }
92
93 if( !dobj )
94 return false;
95
96 return wxTheClipboard->SetData( dobj );
97 }
98
99 wxObject *wxGetClipboardData(wxDataFormat dataFormat, long *len)
100 {
101 wxDataObject* dobj = NULL;
102 wxTextDataObject* tobj = NULL;
103 wxBitmapDataObject* bobj = NULL;
104
105 if( dataFormat == wxDF_TEXT )
106 {
107 dobj = tobj = new wxTextDataObject;
108 }
109 else if( dataFormat = wxDF_BITMAP )
110 {
111 dobj = bobj = new wxBitmapDataObject;
112 }
113
114 if( !dobj || !wxTheClipboard->GetData( *dobj ) )
115 return NULL;
116
117 if( tobj )
118 {
119 wxString text = tobj->GetText();
120 wxChar* buf = new wxChar[text.length() + 1];
121
122 if( len ) *len = text.length();
123 return (wxObject*)wxStrcpy( buf, text.c_str() );
124 }
125 else if( bobj )
126 {
127 if( len ) *len = 0;
128 return new wxBitmap( bobj->GetBitmap() );
129 }
130
131 return NULL; // just in case...
132 }
133
134 wxDataFormat wxEnumClipboardFormats(wxDataFormat dataFormat)
135 {
136 // Only wxDF_TEXT supported
137 if (dataFormat == wxDF_TEXT)
138 return wxDF_TEXT;
139 else
140 return wxDF_INVALID;
141 }
142
143 wxDataFormat wxRegisterClipboardFormat(char *WXUNUSED(formatName))
144 {
145 // Not supported
146 return wxDF_INVALID;
147 }
148
149 bool wxGetClipboardFormatName(wxDataFormat dataFormat, char *formatName,
150 int maxCount)
151 {
152 wxStrncpy( formatName, dataFormat.GetId().c_str(), maxCount );
153
154 return true;
155 }
156
157 //-----------------------------------------------------------------------------
158 // wxClipboard
159 //-----------------------------------------------------------------------------
160
161 struct wxDataIdToDataObject
162 {
163 wxDataIdToDataObject( wxDataObject* o, long d, size_t s )
164 : object( o ), size( s ), dataId( d ) { }
165
166 wxDataObject* object;
167 size_t size;
168 long dataId;
169 };
170
171 #include "wx/listimpl.cpp"
172
173 WX_DEFINE_LIST(wxDataObjectList);
174 WX_DEFINE_LIST(wxDataIdToDataObjectList);
175
176 #if wxCHECK_LESSTIF()
177 static void wxClipboardCallback( Widget widget, int* data_id,
178 int* priv, int* reason );
179 #else
180 static void wxClipboardCallback( Widget widget, long* data_id,
181 long* priv, int* reason );
182 #endif
183
184 IMPLEMENT_DYNAMIC_CLASS(wxClipboard,wxObject)
185
186 wxClipboard::wxClipboard()
187 {
188 m_open = false;
189 }
190
191 wxClipboard::~wxClipboard()
192 {
193 Clear();
194 }
195
196 void wxClipboard::Clear()
197 {
198 wxDataObjectList::compatibility_iterator node = m_data.GetFirst();
199 while (node)
200 {
201 delete node->GetData();
202 node = node->GetNext();
203 }
204 m_data.Clear();
205
206 for( wxDataIdToDataObjectList::compatibility_iterator node2 = m_idToObject.GetFirst();
207 node2; node2 = node2->GetNext() )
208 delete node->GetData();
209 m_idToObject.Clear();
210 }
211
212 bool wxClipboard::Open()
213 {
214 wxCHECK_MSG( !m_open, false, "clipboard already open" );
215
216 m_open = true;
217
218 return true;
219 }
220
221 bool wxClipboard::SetData( wxDataObject *data )
222 {
223 wxCHECK_MSG( data, false, "data is invalid" );
224 wxCHECK_MSG( m_open, false, "clipboard not open" );
225
226 Clear();
227
228 return AddData( data );
229 }
230
231 wxDECLARE_SCOPED_ARRAY( wxDataFormat, wxDataFormatScopedArray );
232 wxDEFINE_SCOPED_ARRAY( wxDataFormat, wxDataFormatScopedArray );
233
234 #if wxCHECK_LESSTIF()
235 void wxClipboardCallback( Widget xwidget, int* data_id,
236 int* priv, int* reason )
237 #else
238 void wxClipboardCallback( Widget xwidget, long* data_id,
239 long* priv, int* reason )
240 #endif
241 {
242 Display* xdisplay = XtDisplay( xwidget );
243 Window xwindow = XtWindow( xwidget );
244 wxDataObject* dobj = NULL;
245 size_t size = 0;
246
247 for( wxDataIdToDataObjectList::compatibility_iterator node2 =
248 wxTheClipboard->m_idToObject.GetFirst();
249 node2; node2 = node2->GetNext() )
250 {
251 wxDataIdToDataObject* dido = node2->GetData();
252 if( dido->dataId == *data_id )
253 {
254 dobj = dido->object;
255 size = dido->size;
256 break;
257 }
258 }
259
260 if( !dobj ) return;
261
262 wxCharBuffer buffer(size);
263 size_t count = dobj->GetFormatCount( wxDataObject::Get );
264 wxDataFormatScopedArray dfarr( new wxDataFormat[count] );
265 dobj->GetAllFormats( dfarr.get(), wxDataObject::Get );
266
267 if( !dobj->GetDataHere( dfarr[*priv], buffer.data() ) )
268 return;
269
270 while( XmClipboardCopyByName( xdisplay, xwindow, *data_id,
271 buffer.data(), size, 0 )
272 == XmClipboardLocked );
273 }
274
275 bool wxClipboard::AddData( wxDataObject *data )
276 {
277 wxCHECK_MSG( data, false, "data is invalid" );
278 wxCHECK_MSG( m_open, false, "clipboard not open" );
279
280 m_data.Append( data );
281
282 Display* xdisplay = wxGlobalDisplay();
283 Widget xwidget = (Widget)wxTheApp->GetTopLevelWidget();
284 Window xwindow = XtWindow( xwidget );
285 wxXmString label( wxTheApp->GetAppName() );
286 Time timestamp = XtLastTimestampProcessed( xdisplay );
287 long itemId;
288
289 int retval;
290
291 while( ( retval = XmClipboardStartCopy( xdisplay, xwindow, label(),
292 timestamp, xwidget,
293 wxClipboardCallback,
294 &itemId ) )
295 == XmClipboardLocked );
296 if( retval != XmClipboardSuccess )
297 return false;
298
299 size_t count = data->GetFormatCount( wxDataObject::Get );
300 wxDataFormatScopedArray dfarr( new wxDataFormat[count] );
301 data->GetAllFormats( dfarr.get(), wxDataObject::Get );
302
303 for( size_t i = 0; i < count; ++i )
304 {
305 size_t size = data->GetDataSize( dfarr[i] );
306 long data_id;
307 wxString id = dfarr[i].GetId();
308
309 while( ( retval = XmClipboardCopy( xdisplay, xwindow, itemId,
310 wxConstCast(id.c_str(), char),
311 NULL, size, i, &data_id ) )
312 == XmClipboardLocked );
313
314 m_idToObject.Append( new wxDataIdToDataObject( data, data_id, size ) );
315 }
316
317 while( XmClipboardEndCopy( xdisplay, xwindow, itemId )
318 == XmClipboardLocked );
319
320 return true;
321 }
322
323 void wxClipboard::Close()
324 {
325 wxCHECK_RET( m_open, "clipboard not open" );
326
327 m_open = false;
328 }
329
330 bool wxClipboard::IsSupported(const wxDataFormat& format)
331 {
332 Display* xdisplay = wxGlobalDisplay();
333 Window xwindow = XtWindow( (Widget)wxTheApp->GetTopLevelWidget() );
334 bool isSupported = false;
335 int retval, count;
336 unsigned long max_name_length;
337 wxString id = format.GetId();
338
339 while( ( retval = XmClipboardLock( xdisplay, xwindow ) )
340 == XmClipboardLocked );
341 if( retval != XmClipboardSuccess )
342 return false;
343
344 if( XmClipboardInquireCount( xdisplay, xwindow, &count, &max_name_length )
345 == XmClipboardSuccess )
346 {
347 wxCharBuffer buf( max_name_length + 1 );
348 unsigned long copied;
349
350 for( int i = 0; i < count; ++i )
351 {
352 if( XmClipboardInquireFormat( xdisplay, xwindow, i + 1,
353 (XtPointer)buf.data(),
354 max_name_length, &copied )
355 != XmClipboardSuccess )
356 continue;
357
358 buf.data()[copied] = '\0';
359
360 if( buf == id )
361 {
362 isSupported = true;
363 break;
364 }
365 }
366 }
367
368 XmClipboardUnlock( xdisplay, xwindow, False );
369
370 return isSupported;
371 }
372
373 class wxClipboardEndRetrieve
374 {
375 public:
376 wxClipboardEndRetrieve( Display* display, Window window )
377 : m_display( display ), m_window( window ) { }
378 ~wxClipboardEndRetrieve()
379 {
380 while( XmClipboardEndRetrieve( m_display, m_window )
381 == XmClipboardLocked );
382 }
383 private:
384 Display* m_display;
385 Window m_window;
386 };
387
388 bool wxClipboard::GetData( wxDataObject& data )
389 {
390 wxCHECK_MSG( m_open, false, "clipboard not open" );
391
392 Display* xdisplay = wxGlobalDisplay();
393 Window xwindow = XtWindow( (Widget)wxTheApp->GetTopLevelWidget() );
394 Time timestamp = XtLastTimestampProcessed( xdisplay );
395
396 wxDataFormat chosenFormat;
397 int retval;
398
399 ///////////////////////////////////////////////////////////////////////////
400 // determine if the cliboard holds any format we like
401 ///////////////////////////////////////////////////////////////////////////
402 while( ( retval = XmClipboardStartRetrieve( xdisplay, xwindow,
403 timestamp ) )
404 == XmClipboardLocked );
405 if( retval != XmClipboardSuccess )
406 return false;
407
408 wxClipboardEndRetrieve endRetrieve( xdisplay, xwindow );
409
410 int count;
411 unsigned long max_name_length;
412 size_t dfcount = data.GetFormatCount( wxDataObject::Set );
413 wxDataFormatScopedArray dfarr( new wxDataFormat[dfcount] );
414 data.GetAllFormats( dfarr.get(), wxDataObject::Set );
415
416 if( XmClipboardInquireCount( xdisplay, xwindow, &count, &max_name_length )
417 == XmClipboardSuccess )
418 {
419 wxCharBuffer buf( max_name_length + 1 );
420 unsigned long copied;
421
422 for( int i = 0; i < count; ++i )
423 {
424 if( XmClipboardInquireFormat( xdisplay, xwindow, i + 1,
425 (XtPointer)buf.data(),
426 max_name_length, &copied )
427 != XmClipboardSuccess )
428 continue;
429
430 buf.data()[copied] = '\0';
431
432 // try preferred format
433 if( buf == data.GetPreferredFormat( wxDataObject::Set ).GetId() )
434 {
435 chosenFormat = data.GetPreferredFormat( wxDataObject::Set );
436 break;
437 }
438
439 // try all other formats
440 for( size_t i = 0; i < dfcount; ++i )
441 {
442 if( buf == dfarr[i].GetId() )
443 chosenFormat = dfarr[i];
444 }
445 }
446 }
447
448 if( chosenFormat == wxDF_INVALID )
449 return false;
450
451 ///////////////////////////////////////////////////////////////////////////
452 // now retrieve the data
453 ///////////////////////////////////////////////////////////////////////////
454 unsigned long length, dummy1;
455 long dummy2;
456 wxString id = chosenFormat.GetId();
457
458 while( ( retval = XmClipboardInquireLength( xdisplay, xwindow,
459 wxConstCast(id.c_str(), char),
460 &length ) )
461 == XmClipboardLocked );
462 if( retval != XmClipboardSuccess )
463 return false;
464
465 wxCharBuffer buf(length);
466
467 while( ( retval = XmClipboardRetrieve( xdisplay, xwindow,
468 wxConstCast(id.c_str(), char),
469 (XtPointer)buf.data(),
470 length, &dummy1, &dummy2 ) )
471 == XmClipboardLocked );
472 if( retval != XmClipboardSuccess )
473 return false;
474
475 if( !data.SetData( chosenFormat, length, buf.data() ) )
476 return false;
477
478 return true;
479 }
480
481 #endif // wxUSE_CLIPBOARD