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/ptr_scpd.h" 
  38 #pragma message disable nosimpint 
  42 #include <Xm/CutPaste.h> 
  44 #pragma message enable nosimpint 
  47 #include "wx/motif/private.h" 
  49 bool wxOpenClipboard() 
  51     return wxTheClipboard
->Open(); 
  54 bool wxCloseClipboard() 
  56     wxTheClipboard
->Close(); 
  61 bool wxEmptyClipboard() 
  63     wxTheClipboard
->Clear(); 
  67 bool wxClipboardOpen() 
  69     return wxTheClipboard
->IsOpened(); 
  72 bool wxIsClipboardFormatAvailable(const wxDataFormat
& dataFormat
) 
  74     return wxTheClipboard
->IsSupported( dataFormat 
); 
  77 bool wxSetClipboardData(wxDataFormat dataFormat
, wxObject 
*obj
, 
  78                         int WXUNUSED(width
), int WXUNUSED(height
)) 
  80     wxDataObject
* dobj 
= NULL
; 
  82     if( dataFormat 
== wxDF_TEXT 
) 
  84         wxChar
* data 
= (wxChar
*)obj
; 
  85         dobj 
= new wxTextDataObject( data 
); 
  87     else if( dataFormat 
= wxDF_BITMAP 
) 
  89         wxBitmap
* data 
= (wxBitmap
*)obj
; 
  90         dobj 
= new wxBitmapDataObject( *data 
); 
  96     return wxTheClipboard
->SetData( dobj 
); 
  99 wxObject 
*wxGetClipboardData(wxDataFormat dataFormat
, long *len
) 
 101     wxDataObject
* dobj 
= NULL
; 
 102     wxTextDataObject
* tobj 
= NULL
; 
 103     wxBitmapDataObject
* bobj 
= NULL
; 
 105     if( dataFormat 
== wxDF_TEXT 
) 
 107         dobj 
= tobj 
= new wxTextDataObject
; 
 109     else if( dataFormat 
= wxDF_BITMAP 
) 
 111         dobj 
= bobj 
= new wxBitmapDataObject
; 
 114     if( !dobj 
|| !wxTheClipboard
->GetData( *dobj 
) ) 
 119         wxString text 
= tobj
->GetText(); 
 120         wxChar
* buf 
= new wxChar
[text
.length() + 1]; 
 122         if( len 
) *len 
= text
.length(); 
 123         return (wxObject
*)wxStrcpy( buf
, text
.c_str() ); 
 128         return new wxBitmap( bobj
->GetBitmap() ); 
 131     return NULL
; // just in case... 
 134 wxDataFormat 
wxEnumClipboardFormats(const wxDataFormat
& dataFormat
) 
 136     // Only wxDF_TEXT supported 
 137     if (dataFormat 
== wxDF_TEXT
) 
 143 wxDataFormat 
wxRegisterClipboardFormat(char *WXUNUSED(formatName
)) 
 149 bool wxGetClipboardFormatName(const wxDataFormat
& dataFormat
, char *formatName
, 
 152     wxStrncpy( formatName
, dataFormat
.GetId().c_str(), maxCount 
); 
 157 //----------------------------------------------------------------------------- 
 159 //----------------------------------------------------------------------------- 
 161 struct wxDataIdToDataObject
 
 163     wxDataIdToDataObject( wxDataObject
* o
, long d
, size_t s 
) 
 164         : object( o 
), size( s 
), dataId( d 
) { } 
 166     wxDataObject
* object
; 
 171 #include "wx/listimpl.cpp" 
 173 WX_DEFINE_LIST(wxDataObjectList
) 
 174 WX_DEFINE_LIST(wxDataIdToDataObjectList
) 
 178 #if wxCHECK_LESSTIF() 
 179 static void wxClipboardCallback( Widget widget
, int* data_id
, 
 180                                  int* priv
, int* reason 
); 
 182 static void wxClipboardCallback( Widget widget
, long* data_id
, 
 183                                  long* priv
, int* reason 
); 
 187 IMPLEMENT_DYNAMIC_CLASS(wxClipboard
,wxObject
) 
 189 wxClipboard::wxClipboard() 
 194 wxClipboard::~wxClipboard() 
 199 void wxClipboard::Clear() 
 201     wxDataObjectList::compatibility_iterator node 
= m_data
.GetFirst(); 
 204         delete node
->GetData(); 
 205         node 
= node
->GetNext(); 
 209     for( wxDataIdToDataObjectList::compatibility_iterator node2 
= m_idToObject
.GetFirst(); 
 210          node2
; node2 
= node2
->GetNext() ) 
 212         delete node2
->GetData(); 
 214     m_idToObject
.Clear(); 
 217 bool wxClipboard::Open() 
 219     wxCHECK_MSG( !m_open
, false, "clipboard already open" ); 
 226 bool wxClipboard::SetData( wxDataObject 
*data 
) 
 228     wxCHECK_MSG( data
, false, "data is invalid" ); 
 229     wxCHECK_MSG( m_open
, false, "clipboard not open" ); 
 233     return AddData( data 
); 
 236 wxDECLARE_SCOPED_ARRAY( wxDataFormat
, wxDataFormatScopedArray 
) 
 237 wxDEFINE_SCOPED_ARRAY( wxDataFormat
, wxDataFormatScopedArray 
) 
 239 #if wxCHECK_LESSTIF() 
 240 void wxClipboardCallback( Widget xwidget
, int* data_id
, 
 241                           int* priv
, int* WXUNUSED(reason
) ) 
 243 void wxClipboardCallback( Widget xwidget
, long* data_id
, 
 244                           long* priv
, int* WXUNUSED(reason
) ) 
 247     Display
* xdisplay 
= XtDisplay( xwidget 
); 
 248     Window xwindow 
= XtWindow( xwidget 
); 
 249     wxDataObject
* dobj 
= NULL
; 
 252     for( wxDataIdToDataObjectList::compatibility_iterator node2 
= 
 253              wxTheClipboard
->m_idToObject
.GetFirst(); 
 254          node2
; node2 
= node2
->GetNext() ) 
 256         wxDataIdToDataObject
* dido 
= node2
->GetData(); 
 257         if( dido
->dataId 
== *data_id 
) 
 267     wxCharBuffer 
buffer(size
); 
 268     size_t count 
= dobj
->GetFormatCount( wxDataObject::Get 
); 
 269     wxDataFormatScopedArray 
dfarr( new wxDataFormat
[count
] ); 
 270     dobj
->GetAllFormats( dfarr
.get(), wxDataObject::Get 
); 
 272     if( !dobj
->GetDataHere( dfarr
[*priv
], buffer
.data() ) ) 
 275     while( XmClipboardCopyByName( xdisplay
, xwindow
, *data_id
, 
 276                                   buffer
.data(), size
, 0 ) 
 277            == XmClipboardLocked 
); 
 280 bool wxClipboard::AddData( wxDataObject 
*data 
) 
 282     wxCHECK_MSG( data
, false, "data is invalid" ); 
 283     wxCHECK_MSG( m_open
, false, "clipboard not open" ); 
 285     m_data
.Append( data 
); 
 287     Display
* xdisplay 
= wxGlobalDisplay(); 
 288     Widget xwidget 
= (Widget
)wxTheApp
->GetTopLevelRealizedWidget(); 
 289     Window xwindow 
= XtWindow( xwidget 
); 
 290     wxXmString 
label( wxTheApp
->GetAppDisplayName() ); 
 291     Time timestamp 
= XtLastTimestampProcessed( xdisplay 
); 
 296     while( ( retval 
= XmClipboardStartCopy( xdisplay
, xwindow
, label(), 
 300            == XmClipboardLocked 
); 
 301     if( retval 
!= XmClipboardSuccess 
) 
 304     size_t count 
= data
->GetFormatCount( wxDataObject::Get 
); 
 305     wxDataFormatScopedArray 
dfarr( new wxDataFormat
[count
] ); 
 306     data
->GetAllFormats( dfarr
.get(), wxDataObject::Get 
); 
 308     for( size_t i 
= 0; i 
< count
; ++i 
) 
 310         size_t size 
= data
->GetDataSize( dfarr
[i
] ); 
 312         wxString id 
= dfarr
[i
].GetId(); 
 314         while( ( retval 
= XmClipboardCopy( xdisplay
, xwindow
, itemId
, 
 316                                            NULL
, size
, i
, &data_id 
) ) 
 317                == XmClipboardLocked 
); 
 319         m_idToObject
.Append( new wxDataIdToDataObject( data
, data_id
, size 
) ); 
 322     while( XmClipboardEndCopy( xdisplay
, xwindow
, itemId 
) 
 323            == XmClipboardLocked 
); 
 328 void wxClipboard::Close() 
 330     wxCHECK_RET( m_open
, "clipboard not open" ); 
 335 bool wxClipboard::IsSupported(const wxDataFormat
& format
) 
 337     Display
* xdisplay 
= wxGlobalDisplay(); 
 338     Window xwindow 
= XtWindow( (Widget
)wxTheApp
->GetTopLevelRealizedWidget() ); 
 339     bool isSupported 
= false; 
 341     unsigned long  max_name_length
; 
 342     wxString id 
= format
.GetId(); 
 344     while( ( retval 
= XmClipboardLock( xdisplay
, xwindow 
) ) 
 345            == XmClipboardLocked 
); 
 346     if( retval 
!= XmClipboardSuccess 
) 
 349     if( XmClipboardInquireCount( xdisplay
, xwindow
, &count
, &max_name_length 
) 
 350         == XmClipboardSuccess 
) 
 352         wxCharBuffer 
buf( max_name_length 
+ 1 ); 
 353         unsigned long copied
; 
 355         for( int i 
= 0; i 
< count
; ++i 
) 
 357             if( XmClipboardInquireFormat( xdisplay
, xwindow
, i 
+ 1, 
 358                                           (XtPointer
)buf
.data(), 
 359                                           max_name_length
, &copied 
) 
 360                 != XmClipboardSuccess 
) 
 363             buf
.data()[copied
] = '\0'; 
 373     XmClipboardUnlock( xdisplay
, xwindow
, False 
); 
 378 class wxClipboardEndRetrieve
 
 381     wxClipboardEndRetrieve( Display
* display
, Window window 
) 
 382         : m_display( display 
), m_window( window 
) { } 
 383     ~wxClipboardEndRetrieve() 
 385         while( XmClipboardEndRetrieve( m_display
, m_window 
) 
 386                == XmClipboardLocked 
); 
 393 bool wxClipboard::GetData( wxDataObject
& data 
) 
 395     wxCHECK_MSG( m_open
, false, "clipboard not open" ); 
 397     Display
* xdisplay 
= wxGlobalDisplay(); 
 398     Window xwindow 
= XtWindow( (Widget
)wxTheApp
->GetTopLevelRealizedWidget() ); 
 399     Time timestamp 
= XtLastTimestampProcessed( xdisplay 
); 
 401     wxDataFormat chosenFormat
; 
 404     /////////////////////////////////////////////////////////////////////////// 
 405     // determine if the cliboard holds any format we like 
 406     /////////////////////////////////////////////////////////////////////////// 
 407     while( ( retval 
= XmClipboardStartRetrieve( xdisplay
, xwindow
, 
 409            == XmClipboardLocked 
); 
 410     if( retval 
!= XmClipboardSuccess 
) 
 413     wxClipboardEndRetrieve 
endRetrieve( xdisplay
, xwindow 
); 
 416     unsigned long max_name_length
; 
 417     size_t dfcount 
= data
.GetFormatCount( wxDataObject::Set 
); 
 418     wxDataFormatScopedArray 
dfarr( new wxDataFormat
[dfcount
] ); 
 419     data
.GetAllFormats( dfarr
.get(), wxDataObject::Set 
); 
 421     if( XmClipboardInquireCount( xdisplay
, xwindow
, &count
, &max_name_length 
) 
 422         == XmClipboardSuccess 
) 
 424         wxCharBuffer 
buf( max_name_length 
+ 1 ); 
 425         unsigned long copied
; 
 427         for( int i 
= 0; i 
< count
; ++i 
) 
 429             if( XmClipboardInquireFormat( xdisplay
, xwindow
, i 
+ 1, 
 430                                           (XtPointer
)buf
.data(), 
 431                                           max_name_length
, &copied 
) 
 432                 != XmClipboardSuccess 
) 
 435             buf
.data()[copied
] = '\0'; 
 437             // try preferred format 
 438             if( buf 
== data
.GetPreferredFormat( wxDataObject::Set 
).GetId() ) 
 440                 chosenFormat 
= data
.GetPreferredFormat( wxDataObject::Set 
); 
 444             // try all other formats 
 445             for( size_t i 
= 0; i 
< dfcount
; ++i 
) 
 447                 if( buf 
== dfarr
[i
].GetId() ) 
 448                     chosenFormat 
= dfarr
[i
]; 
 453     if( chosenFormat 
== wxDF_INVALID 
) 
 456     /////////////////////////////////////////////////////////////////////////// 
 457     // now retrieve the data 
 458     /////////////////////////////////////////////////////////////////////////// 
 459     unsigned long length
, dummy1
; 
 461     wxString id 
= chosenFormat
.GetId(); 
 463     while( ( retval 
= XmClipboardInquireLength( xdisplay
, xwindow
, 
 466            == XmClipboardLocked 
); 
 467     if( retval 
!= XmClipboardSuccess 
) 
 470     wxCharBuffer 
buf(length
); 
 472     while( ( retval 
= XmClipboardRetrieve( xdisplay
, xwindow
, 
 474                                            (XtPointer
)buf
.data(), 
 475                                            length
, &dummy1
, &dummy2 
) ) 
 476            == XmClipboardLocked 
); 
 477     if( retval 
!= XmClipboardSuccess 
) 
 480     if( !data
.SetData( chosenFormat
, length
, buf
.data() ) ) 
 486 #endif // wxUSE_CLIPBOARD