///////////////////////////////////////////////////////////////////////////// // Name: src/mac/classic/clipbrd.cpp // Purpose: Clipboard functionality // Author: Stefan Csomor // Modified by: // Created: 1998-01-01 // RCS-ID: $Id: clipbrd.cpp 39710 2006-06-14 10:02:19Z ABX $ // Copyright: (c) Stefan Csomor // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// #include "wx/wxprec.h" #include "wx/clipbrd.h" #ifndef WX_PRECOMP #include "wx/intl.h" #include "wx/log.h" #include "wx/app.h" #include "wx/utils.h" #include "wx/frame.h" #include "wx/bitmap.h" #endif #include "wx/metafile.h" #ifndef __DARWIN__ #include #endif #include "wx/mac/uma.h" #define wxUSE_DATAOBJ 1 #include // the trace mask we use with wxLogTrace() - call // wxLog::AddTraceMask(TRACE_CLIPBOARD) to enable the trace messages from here // (there will be a *lot* of them!) static const wxChar *TRACE_CLIPBOARD = _T("clipboard"); void *wxGetClipboardData(wxDataFormat dataFormat, long *len) { #if !TARGET_CARBON OSErr err = noErr ; #else OSStatus err = noErr ; #endif void * data = NULL ; Size byteCount; switch (dataFormat.GetType()) { case wxDF_OEMTEXT: dataFormat = wxDF_TEXT; // fall through case wxDF_TEXT: break; case wxDF_UNICODETEXT: break; case wxDF_BITMAP : case wxDF_METAFILE : break ; default: { wxLogError(_("Unsupported clipboard format.")); return NULL; } } #if TARGET_CARBON ScrapRef scrapRef; err = GetCurrentScrap( &scrapRef ); if ( err != noTypeErr && err != memFullErr ) { ScrapFlavorFlags flavorFlags; if (( err = GetScrapFlavorFlags( scrapRef, dataFormat.GetFormatId(), &flavorFlags )) == noErr) { if (( err = GetScrapFlavorSize( scrapRef, dataFormat.GetFormatId(), &byteCount )) == noErr) { Size allocSize = byteCount ; if ( dataFormat.GetType() == wxDF_TEXT ) allocSize += 1 ; else if ( dataFormat.GetType() == wxDF_UNICODETEXT ) allocSize += 2 ; data = new char[ allocSize ] ; if (( err = GetScrapFlavorData( scrapRef, dataFormat.GetFormatId(), &byteCount , data )) == noErr ) { *len = allocSize ; if ( dataFormat.GetType() == wxDF_TEXT ) ((char*)data)[byteCount] = 0 ; if ( dataFormat.GetType() == wxDF_UNICODETEXT ) ((wxChar*)data)[byteCount/2] = 0 ; } else { delete[] ((char *)data) ; data = NULL ; } } } } #else long offset ; Handle datahandle = NewHandle(0) ; HLock( datahandle ) ; GetScrap( datahandle , dataFormat.GetFormatId() , &offset ) ; HUnlock( datahandle ) ; if ( GetHandleSize( datahandle ) > 0 ) { byteCount = GetHandleSize( datahandle ) ; Size allocSize = byteCount ; if ( dataFormat.GetType() == wxDF_TEXT ) allocSize += 1 ; else if ( dataFormat.GetType() == wxDF_UNICODETEXT ) allocSize += 2 ; data = new char[ allocSize ] ; memcpy( (char*) data , (char*) *datahandle , byteCount ) ; if ( dataFormat.GetType() == wxDF_TEXT ) ((char*)data)[byteCount] = 0 ; if ( dataFormat.GetType() == wxDF_UNICODETEXT ) ((wxChar*)data)[byteCount/2] = 0 ; *len = byteCount ; } DisposeHandle( datahandle ) ; #endif if ( err ) { wxLogSysError(_("Failed to get clipboard data.")); return NULL ; } if ( dataFormat.GetType() == wxDF_TEXT ) { wxMacConvertNewlines10To13( (char*) data ) ; } return data; } /* * Generalized clipboard implementation by Matthew Flatt */ IMPLEMENT_DYNAMIC_CLASS(wxClipboard, wxObject) wxClipboard::wxClipboard() { m_open = false ; m_data = NULL ; } wxClipboard::~wxClipboard() { if (m_data) { delete m_data; m_data = (wxDataObject*) NULL; } } void wxClipboard::Clear() { if (m_data) { delete m_data; m_data = (wxDataObject*) NULL; } #if TARGET_CARBON OSStatus err ; err = ClearCurrentScrap( ); #else OSErr err ; err = ZeroScrap( ); #endif if ( err ) { wxLogSysError(_("Failed to empty the clipboard.")); } } bool wxClipboard::Flush() { return false; } bool wxClipboard::Open() { wxCHECK_MSG( !m_open, false, wxT("clipboard already open") ); m_open = true ; return true ; } bool wxClipboard::IsOpened() const { return m_open; } bool wxClipboard::SetData( wxDataObject *data ) { wxCHECK_MSG( m_open, false, wxT("clipboard not open") ); wxCHECK_MSG( data, false, wxT("data is invalid") ); Clear(); // as we can only store one wxDataObject, this is the same in this // implementation return AddData( data ); } bool wxClipboard::AddData( wxDataObject *data ) { wxCHECK_MSG( m_open, false, wxT("clipboard not open") ); wxCHECK_MSG( data, false, wxT("data is invalid") ); /* we can only store one wxDataObject */ Clear(); m_data = data; /* get formats from wxDataObjects */ wxDataFormat *array = new wxDataFormat[ m_data->GetFormatCount() ]; m_data->GetAllFormats( array ); for (size_t i = 0; i < m_data->GetFormatCount(); i++) { wxLogTrace( TRACE_CLIPBOARD, wxT("wxClipboard now supports atom %s"), array[i].GetId().c_str() ); #if !TARGET_CARBON OSErr err = noErr ; #else OSStatus err = noErr ; #endif size_t sz = data->GetDataSize( array[i] ) ; void* buf = malloc( sz + 1 ) ; if ( buf ) { data->GetDataHere( array[i] , buf ) ; OSType mactype = 0 ; switch ( array[i].GetType() ) { case wxDF_TEXT: case wxDF_OEMTEXT: mactype = kScrapFlavorTypeText ; break ; #if wxUSE_UNICODE case wxDF_UNICODETEXT : mactype = kScrapFlavorTypeUnicode ; break ; #endif #if wxUSE_DRAG_AND_DROP case wxDF_METAFILE: mactype = kScrapFlavorTypePicture ; break ; #endif case wxDF_BITMAP: case wxDF_DIB: mactype = kScrapFlavorTypePicture ; break ; default: break ; } UMAPutScrap( sz , mactype , buf ) ; free( buf ) ; } } delete[] array; return true ; } void wxClipboard::Close() { wxCHECK_RET( m_open, wxT("clipboard not open") ); m_open = false ; // Get rid of cached object. If this is not done copying from another application will // only work once if (m_data) { delete m_data; m_data = (wxDataObject*) NULL; } } bool wxClipboard::IsSupported( const wxDataFormat &dataFormat ) { if ( m_data ) { return m_data->IsSupported( dataFormat ) ; } #if TARGET_CARBON OSStatus err = noErr; ScrapRef scrapRef; err = GetCurrentScrap( &scrapRef ); if ( err != noTypeErr && err != memFullErr ) { ScrapFlavorFlags flavorFlags; Size byteCount; if (( err = GetScrapFlavorFlags( scrapRef, dataFormat.GetFormatId(), &flavorFlags )) == noErr) { if (( err = GetScrapFlavorSize( scrapRef, dataFormat.GetFormatId(), &byteCount )) == noErr) { return true ; } } } return false; #else long offset ; Handle datahandle = NewHandle(0) ; HLock( datahandle ) ; GetScrap( datahandle , dataFormat.GetFormatId() , &offset ) ; HUnlock( datahandle ) ; bool hasData = GetHandleSize( datahandle ) > 0 ; DisposeHandle( datahandle ) ; return hasData ; #endif } bool wxClipboard::GetData( wxDataObject& data ) { wxCHECK_MSG( m_open, false, wxT("clipboard not open") ); size_t formatcount = data.GetFormatCount() + 1 ; wxDataFormat *array = new wxDataFormat[ formatcount ]; array[0] = data.GetPreferredFormat(); data.GetAllFormats( &array[1] ); bool transferred = false ; if ( m_data ) { for (size_t i = 0; !transferred && i < formatcount ; i++) { wxDataFormat format = array[i] ; if ( m_data->IsSupported( format ) ) { int size = m_data->GetDataSize( format ); transferred = true ; if (size == 0) { data.SetData(format , 0 , 0 ) ; } else { char *d = new char[size]; m_data->GetDataHere( format , (void*) d ); data.SetData( format , size , d ) ; delete[] d ; } } } } /* get formats from wxDataObjects */ if ( !transferred ) { for (size_t i = 0; !transferred && i < formatcount ; i++) { wxDataFormat format = array[i] ; switch ( format.GetType() ) { case wxDF_TEXT : case wxDF_OEMTEXT : case wxDF_BITMAP : case wxDF_METAFILE : { long len ; char* s = (char*)wxGetClipboardData(format, &len ); if ( s ) { data.SetData( format , len , s ) ; delete [] s; transferred = true ; } } break ; default : break ; } } } delete[] array ; return transferred ; }