1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/mac/carbon/clipbrd.cpp 
   3 // Purpose:     Clipboard functionality 
   4 // Author:      Stefan Csomor; 
   5 //              Generalized clipboard implementation by Matthew Flatt 
   9 // Copyright:   (c) Stefan Csomor 
  10 // Licence:     wxWindows licence 
  11 ///////////////////////////////////////////////////////////////////////////// 
  13 #include "wx/wxprec.h" 
  17 #include "wx/clipbrd.h" 
  25     #include "wx/bitmap.h" 
  28 #include "wx/metafile.h" 
  34 #include "wx/mac/uma.h" 
  36 #define wxUSE_DATAOBJ 1 
  41 // the trace mask we use with wxLogTrace() - call 
  42 // wxLog::AddTraceMask(TRACE_CLIPBOARD) to enable the trace messages from here 
  43 // (there will be a *lot* of them!) 
  44 static const wxChar 
*TRACE_CLIPBOARD 
= wxT("clipboard"); 
  47 void * wxGetClipboardData( wxDataFormat dataFormat
, long *len 
) 
  53     switch (dataFormat
.GetType()) 
  56         dataFormat 
= wxDF_TEXT
; 
  60     case wxDF_UNICODETEXT
: 
  75     err 
= GetCurrentScrap( &scrapRef 
); 
  76     if ( err 
!= noTypeErr 
&& err 
!= memFullErr 
) 
  78         ScrapFlavorFlags    flavorFlags
; 
  80         err 
= GetScrapFlavorFlags( scrapRef
, dataFormat
.GetFormatId(), &flavorFlags 
); 
  83             err 
= GetScrapFlavorSize( scrapRef
, dataFormat
.GetFormatId(), &byteCount 
); 
  86                 Size allocSize 
= byteCount
; 
  87                 if ( dataFormat
.GetType() == wxDF_TEXT 
) 
  89                 else if ( dataFormat
.GetType() == wxDF_UNICODETEXT 
) 
  92                 data 
= new char[ allocSize 
]; 
  94                 if (( err 
= GetScrapFlavorData( scrapRef
, dataFormat
.GetFormatId(), &byteCount 
, data 
)) == noErr 
) 
  97                     if ( dataFormat
.GetType() == wxDF_TEXT 
) 
  98                         ((char*)data
)[ byteCount 
] = 0; 
  99                     if ( dataFormat
.GetType() == wxDF_UNICODETEXT 
) 
 101                         // "data" format is UTF16, so 2 bytes = one character 
 102                         // wxChar size depends on platform, so just clear last 2 bytes 
 103                         ((char*)data
)[ byteCount 
+ 0 ] = 
 104                         ((char*)data
)[ byteCount 
+ 1 ] = 0; 
 109                     delete [] (char*)data
; 
 118     Handle datahandle 
= NewHandle( 0 ); 
 120     err 
= (OSStatus
)GetScrap( datahandle
, dataFormat
.GetFormatId(), &offset 
); 
 121     HUnlock( datahandle 
); 
 122     if ( GetHandleSize( datahandle 
) > 0 ) 
 124         byteCount 
= GetHandleSize( datahandle 
); 
 125         Size allocSize 
= byteCount
; 
 126         if ( dataFormat
.GetType() == wxDF_TEXT 
) 
 128         else if ( dataFormat
.GetType() == wxDF_UNICODETEXT 
) 
 131         data 
= new char[ allocSize 
]; 
 133         memcpy( (char*) data
, (char*) *datahandle
, byteCount 
); 
 134         if ( dataFormat
.GetType() == wxDF_TEXT 
) 
 135             ((char*)data
)[ byteCount 
] = 0; 
 136         else if ( dataFormat
.GetType() == wxDF_UNICODETEXT 
) 
 137             ((wxChar
*)data
)[ byteCount 
/ 2 ] = 0; 
 141     DisposeHandle( datahandle 
); 
 146         wxLogSysError(wxT("Failed to get clipboard data.")); 
 151     if (dataFormat
.GetType() == wxDF_TEXT
) 
 152         wxMacConvertNewlines10To13( (char*)data 
); 
 157 IMPLEMENT_DYNAMIC_CLASS(wxClipboard
, wxObject
) 
 159 wxClipboard::wxClipboard() 
 165 wxClipboard::~wxClipboard() 
 174 void wxClipboard::Clear() 
 176     if ( IsUsingPrimarySelection() ) 
 187     err 
= ClearCurrentScrap(); 
 195         wxLogSysError( wxT("Failed to empty the clipboard.") ); 
 199 bool wxClipboard::Flush() 
 204 bool wxClipboard::Open() 
 206     wxCHECK_MSG( !m_open
, false, wxT("clipboard already open") ); 
 213 bool wxClipboard::IsOpened() const 
 218 bool wxClipboard::SetData( wxDataObject 
*data 
) 
 220     if ( IsUsingPrimarySelection() ) 
 223     wxCHECK_MSG( m_open
, false, wxT("clipboard not open") ); 
 224     wxCHECK_MSG( data
, false, wxT("data is invalid") ); 
 228     // as we can only store one wxDataObject, 
 229     // this is the same in this implementation 
 230     return AddData( data 
); 
 233 bool wxClipboard::AddData( wxDataObject 
*data 
) 
 235     if ( IsUsingPrimarySelection() ) 
 238     wxCHECK_MSG( m_open
, false, wxT("clipboard not open") ); 
 239     wxCHECK_MSG( data
, false, wxT("data is invalid") ); 
 241     // we can only store one wxDataObject 
 246     // get formats from wxDataObjects 
 247     wxDataFormat 
*array 
= new wxDataFormat
[ m_data
->GetFormatCount() ]; 
 248     m_data
->GetAllFormats( array 
); 
 250     for (size_t i 
= 0; i 
< m_data
->GetFormatCount(); i
++) 
 252         if (array
[i
].IsStandard()) 
 254             wxLogTrace( TRACE_CLIPBOARD
, 
 255                         wxT("wxClipboard now supports standard atom type %d"), 
 256                         array
[i
].GetType() ); 
 260             wxLogTrace( TRACE_CLIPBOARD
, 
 261                         wxT("wxClipboard now supports atom %s"), 
 262                         array
[i
].GetId().c_str() ); 
 265         size_t sz 
= data
->GetDataSize( array
[ i 
] ); 
 266         void* buf 
= malloc( sz 
+ 1 ); 
 269             // empty the buffer because in some case GetDataHere does not fill buf 
 270             memset( buf
, 0, sz 
+ 1 ); 
 271             data
->GetDataHere( array
[ i 
], buf 
); 
 273             switch ( array
[i
].GetType() ) 
 277                 mactype 
= kScrapFlavorTypeText
; 
 282             case wxDF_UNICODETEXT
: 
 283                 mactype 
= kScrapFlavorTypeUnicode
; 
 288 #if wxUSE_DRAG_AND_DROP 
 290                 mactype 
= kScrapFlavorTypePicture
; 
 296                 mactype 
= kScrapFlavorTypePicture
; 
 300                 mactype 
= (OSType
)(array
[ i 
].GetFormatId()); 
 304             UMAPutScrap( sz 
, mactype 
, buf 
); 
 314 void wxClipboard::Close() 
 316     wxCHECK_RET( m_open
, wxT("clipboard not open") ); 
 320     // Get rid of cached object. 
 321     // If this is not done, copying data from 
 322     // another application will only work once 
 326         m_data 
= (wxDataObject
*) NULL
; 
 330 bool wxClipboard::IsSupported( const wxDataFormat 
&dataFormat 
) 
 332     if ( IsUsingPrimarySelection() ) 
 336         return m_data
->IsSupported( dataFormat 
); 
 338     bool hasData 
= false; 
 341     OSStatus err 
= noErr
; 
 344     err 
= GetCurrentScrap( &scrapRef 
); 
 345     if ( err 
!= noTypeErr 
&& err 
!= memFullErr 
) 
 347         ScrapFlavorFlags flavorFlags
; 
 350         err 
= GetScrapFlavorFlags( scrapRef
, dataFormat
.GetFormatId(), &flavorFlags 
); 
 353             err 
= GetScrapFlavorSize( scrapRef
, dataFormat
.GetFormatId(), &byteCount 
); 
 357         else if ( dataFormat
.GetType() == wxDF_UNICODETEXT 
) 
 359             err 
= GetScrapFlavorFlags( scrapRef
, 'TEXT', &flavorFlags 
); 
 362                 err 
= GetScrapFlavorSize( scrapRef
, 'TEXT', &byteCount 
); 
 372     Handle datahandle 
= NewHandle( 0 ); 
 374     GetScrap( datahandle
, dataFormat
.GetFormatId(), &offset 
); 
 375     HUnlock( datahandle 
); 
 376     hasData 
= GetHandleSize( datahandle 
) > 0; 
 377     DisposeHandle( datahandle 
); 
 383 bool wxClipboard::GetData( wxDataObject
& data 
) 
 385     if ( IsUsingPrimarySelection() ) 
 388     wxCHECK_MSG( m_open
, false, wxT("clipboard not open") ); 
 390     size_t formatcount 
= data
.GetFormatCount() + 1; 
 391     wxDataFormat 
*array 
= new wxDataFormat
[ formatcount 
]; 
 392     array
[0] = data
.GetPreferredFormat(); 
 393     data
.GetAllFormats( &array
[1] ); 
 395     bool transferred 
= false; 
 399         for (size_t i 
= 0; !transferred 
&& i 
< formatcount
; i
++) 
 401             wxDataFormat format 
= array
[ i 
]; 
 402             if ( m_data
->IsSupported( format 
) ) 
 404                 int dataSize 
= m_data
->GetDataSize( format 
); 
 409                     data
.SetData( format
, 0, 0 ); 
 413                     char *d 
= new char[ dataSize 
]; 
 414                     m_data
->GetDataHere( format
, (void*)d 
); 
 415                     data
.SetData( format
, dataSize
, d 
); 
 422     // get formats from wxDataObjects 
 425         for (size_t i 
= 0; !transferred 
&& i 
< formatcount
; i
++) 
 427             wxDataFormat format 
= array
[ i 
]; 
 429             switch ( format
.GetType() ) 
 431                 // NOTE: this is usable for all data types 
 433                 case wxDF_UNICODETEXT
: 
 440                     char* s 
= (char*)wxGetClipboardData( format
, &len 
); 
 443                         data
.SetData( format
, len
, s 
);