X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/f0822896b3354f8698835d234ce2655daa640704..77631b1d818c890391b7111a1e499f1317a9ea07:/src/mac/carbon/clipbrd.cpp diff --git a/src/mac/carbon/clipbrd.cpp b/src/mac/carbon/clipbrd.cpp index cb69904f95..cb88eee08a 100644 --- a/src/mac/carbon/clipbrd.cpp +++ b/src/mac/carbon/clipbrd.cpp @@ -1,18 +1,18 @@ ///////////////////////////////////////////////////////////////////////////// -// Name: clipbrd.cpp +// Name: src/mac/carbon/clipbrd.cpp // Purpose: Clipboard functionality -// Author: AUTHOR +// Author: Stefan Csomor; +// Generalized clipboard implementation by Matthew Flatt // Modified by: -// Created: ??/??/98 +// Created: 1998-01-01 // RCS-ID: $Id$ -// Copyright: (c) AUTHOR -// Licence: wxWindows licence +// Copyright: (c) Stefan Csomor +// Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// -#ifdef __GNUG__ -#pragma implementation -#pragma implementation "clipbrd.h" -#endif +#include "wx/wxprec.h" + +#if wxUSE_CLIPBOARD #include "wx/app.h" #include "wx/frame.h" @@ -21,158 +21,186 @@ #include "wx/metafile.h" #include "wx/clipbrd.h" #include "wx/intl.h" +#include "wx/log.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"); +static const wxChar *TRACE_CLIPBOARD = wxT("clipboard"); -void *wxGetClipboardData(wxDataFormat dataFormat, long *len) + +void * wxGetClipboardData( wxDataFormat dataFormat, long *len ) { -#if !TARGET_CARBON - OSErr err = noErr ; -#else - OSStatus err = noErr ; -#endif - void * data = NULL ; - + OSStatus err = noErr; + void * data = NULL; + Size byteCount; + switch (dataFormat.GetType()) { - case wxDF_OEMTEXT: - dataFormat = wxDF_TEXT; - // fall through + case wxDF_OEMTEXT: + dataFormat = wxDF_TEXT; + break; - case wxDF_TEXT: - break; - default: + case wxDF_TEXT: + case wxDF_UNICODETEXT: + break; + + case wxDF_BITMAP: + case wxDF_METAFILE: + break; + + default: + // custom datatype + break; + } + +#if TARGET_CARBON + ScrapRef scrapRef; + + err = GetCurrentScrap( &scrapRef ); + if ( err != noTypeErr && err != memFullErr ) + { + ScrapFlavorFlags flavorFlags; + + err = GetScrapFlavorFlags( scrapRef, dataFormat.GetFormatId(), &flavorFlags ); + if (err == noErr) + { + err = GetScrapFlavorSize( scrapRef, dataFormat.GetFormatId(), &byteCount ); + if (err == noErr) { - wxLogError(_("Unsupported clipboard format.")); - return NULL; + 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 ) + { + // "data" format is UTF16, so 2 bytes = one character + // wxChar size depends on platform, so just clear last 2 bytes + ((char*)data)[ byteCount + 0 ] = + ((char*)data)[ byteCount + 1 ] = 0; + } + } + else + { + delete [] (char*)data; + data = NULL; + } } + } } -#if TARGET_CARBON - 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) - { - if ( dataFormat.GetType() == wxDF_TEXT ) - byteCount++ ; - - data = new char[ byteCount ] ; - if (( err = GetScrapFlavorData( scrapRef, dataFormat.GetFormatId(), &byteCount , data )) == noErr ) - { - *len = byteCount ; - if ( dataFormat.GetType() == wxDF_TEXT ) - ((char*)data)[byteCount] = 0 ; - } - else - { - delete[] data ; - data = NULL ; - } - } - } - } - #else - long offset ; - Handle datahandle = NewHandle(0) ; - HLock( datahandle ) ; - GetScrap( datahandle , dataFormat.GetFormatId() , &offset ) ; - HUnlock( datahandle ) ; - if ( GetHandleSize( datahandle ) > 0 ) - { - long byteCount = GetHandleSize( datahandle ) ; - if ( dataFormat.GetType() == wxDF_TEXT ) - data = new char[ byteCount + 1] ; - else - data = new char[ byteCount ] ; - - memcpy( (char*) data , (char*) *datahandle , byteCount ) ; - if ( dataFormat.GetType() == wxDF_TEXT ) - ((char*)data)[byteCount] = 0 ; - * len = byteCount ; - } - DisposeHandle( datahandle ) ; -#endif - if ( err ) + long offset; + Handle datahandle = NewHandle( 0 ); + HLock( datahandle ); + err = (OSStatus)GetScrap( datahandle, dataFormat.GetFormatId(), &offset ); + HUnlock( datahandle ); + if ( GetHandleSize( datahandle ) > 0 ) { - wxLogSysError(_("Failed to get clipboard data.")); - - return NULL ; + 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; + else if ( dataFormat.GetType() == wxDF_UNICODETEXT ) + ((wxChar*)data)[ byteCount / 2 ] = 0; + *len = byteCount; } - if ( dataFormat.GetType() == wxDF_TEXT && wxApp::s_macDefaultEncodingIsPC ) + + DisposeHandle( datahandle ); +#endif + + if (err != noErr) { - wxMacConvertToPC((char*)data) ; + wxLogSysError(wxT("Failed to get clipboard data.")); + + return NULL; } - return data; -} + if (dataFormat.GetType() == wxDF_TEXT) + wxMacConvertNewlines10To13( (char*)data ); -/* - * Generalized clipboard implementation by Matthew Flatt - */ + return data; +} -IMPLEMENT_DYNAMIC_CLASS(wxClipboard, wxClipboardBase) +IMPLEMENT_DYNAMIC_CLASS(wxClipboard, wxObject) wxClipboard::wxClipboard() { - m_open = false ; - m_data = NULL ; + m_open = false; + m_data = NULL; } wxClipboard::~wxClipboard() { - if (m_data) + if (m_data != NULL) { delete m_data; - m_data = (wxDataObject*) NULL; + m_data = NULL; } } void wxClipboard::Clear() { - if (m_data) + if (m_data != NULL) { delete m_data; - m_data = (wxDataObject*) NULL; + m_data = NULL; } + #if TARGET_CARBON - OSStatus err ; - err = ClearCurrentScrap( ); + OSStatus err; + err = ClearCurrentScrap(); #else - OSErr err ; - err = ZeroScrap( ); + OSErr err; + err = ZeroScrap(); #endif - if ( err ) - { - wxLogSysError(_("Failed to empty the clipboard.")); - } + + if (err != noErr) + { + wxLogSysError( wxT("Failed to empty the clipboard.") ); + } } bool wxClipboard::Flush() { - return FALSE; + return false; } bool wxClipboard::Open() { - wxCHECK_MSG( !m_open, FALSE, wxT("clipboard already open") ); - m_open = true ; - return true ; + wxCHECK_MSG( !m_open, false, wxT("clipboard already open") ); + + m_open = true; + + return true; } bool wxClipboard::IsOpened() const @@ -182,29 +210,27 @@ bool wxClipboard::IsOpened() const bool wxClipboard::SetData( wxDataObject *data ) { - wxCHECK_MSG( m_open, FALSE, wxT("clipboard not open") ); - - wxCHECK_MSG( data, FALSE, wxT("data is invalid") ); + 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") ); + wxCHECK_MSG( m_open, false, wxT("clipboard not open") ); + wxCHECK_MSG( data, false, wxT("data is invalid") ); - wxDataFormat format = data->GetPreferredFormat(); - - /* we can only store one wxDataObject */ + // we can only store one wxDataObject Clear(); m_data = data; - /* get formats from wxDataObjects */ + // get formats from wxDataObjects wxDataFormat *array = new wxDataFormat[ m_data->GetFormatCount() ]; m_data->GetAllFormats( array ); @@ -214,185 +240,192 @@ bool wxClipboard::AddData( wxDataObject *data ) 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 != NULL ) + { + // empty the buffer because in some case GetDataHere does not fill buf + memset( buf, 0, sz + 1 ); + data->GetDataHere( array[ i ], buf ); + OSType mactype = 0; + switch ( array[i].GetType() ) + { + case wxDF_TEXT: + case wxDF_OEMTEXT: + mactype = kScrapFlavorTypeText; + sz -= 1; + break; - switch ( array[i].GetType() ) - { - case wxDF_TEXT: - case wxDF_OEMTEXT: - { - wxTextDataObject* textDataObject = (wxTextDataObject*) data; - wxString str(textDataObject->GetText()); - wxString mac ; - if ( wxApp::s_macDefaultEncodingIsPC ) - { - mac = wxMacMakeMacStringFromPC(textDataObject->GetText()) ; - } - else - { - mac = textDataObject->GetText() ; - } - #if !TARGET_CARBON - err = PutScrap( mac.Length() , 'TEXT' , mac.c_str() ) ; - #else - ScrapRef scrap; - err = GetCurrentScrap (&scrap); - if ( !err ) - { - err = PutScrapFlavor (scrap, 'TEXT', 0, mac.Length(), mac.c_str()); - } - #endif - } +#if wxUSE_UNICODE + case wxDF_UNICODETEXT: + mactype = kScrapFlavorTypeUnicode; + sz -= 2; + break; +#endif #if wxUSE_DRAG_AND_DROP - case wxDF_METAFILE: - { - wxMetafileDataObject* metaFileDataObject = - (wxMetafileDataObject*) data; - wxMetafile metaFile = metaFileDataObject->GetMetafile(); - PicHandle pict = metaFile->GetHMETAFILE() ; - HLock( (Handle) pict ) ; - #if !TARGET_CARBON - err = PutScrap( GetHandleSize( (Handle) pict ) , 'PICT' , *pict ) ; - #else - ScrapRef scrap; - err = GetCurrentScrap (&scrap); - if ( !err ) - { - err = PutScrapFlavor (scrap, 'PICT', 0, GetHandleSize((Handle) pict), *pict); - } - #endif - HUnlock( (Handle) pict ) ; - } + case wxDF_METAFILE: + mactype = kScrapFlavorTypePicture; + break; #endif - case wxDF_BITMAP: - case wxDF_DIB: - default: - break ; - } + case wxDF_BITMAP: + case wxDF_DIB: + mactype = kScrapFlavorTypePicture; + break; + + default: + mactype = (OSType)(array[ i ].GetFormatId()); + break; + } + + UMAPutScrap( sz , mactype , buf ); + free( buf ); + } } - delete[] array; + delete [] array; - return true ; + return true; } void wxClipboard::Close() { - m_open = false ; + wxCHECK_RET( m_open, wxT("clipboard not open") ); + + m_open = false; + + // Get rid of cached object. + // If this is not done, copying data 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 ( m_data ) + return m_data->IsSupported( dataFormat ); + + bool hasData = false; + #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; - + OSStatus err = noErr; + ScrapRef scrapRef; + + err = GetCurrentScrap( &scrapRef ); + if ( err != noTypeErr && err != memFullErr ) + { + ScrapFlavorFlags flavorFlags; + Size byteCount; + + err = GetScrapFlavorFlags( scrapRef, dataFormat.GetFormatId(), &flavorFlags ); + if (err == noErr) + { + err = GetScrapFlavorSize( scrapRef, dataFormat.GetFormatId(), &byteCount ); + if (err == noErr) + hasData = true; + } + else if ( dataFormat.GetType() == wxDF_UNICODETEXT ) + { + err = GetScrapFlavorFlags( scrapRef, 'TEXT', &flavorFlags ); + if (err == noErr) + { + err = GetScrapFlavorSize( scrapRef, 'TEXT', &byteCount ); + if (err == noErr) + hasData = true; + } + } + } + #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 ; + + long offset = 0; + Handle datahandle = NewHandle( 0 ); + HLock( datahandle ); + GetScrap( datahandle, dataFormat.GetFormatId(), &offset ); + HUnlock( datahandle ); + hasData = GetHandleSize( datahandle ) > 0; + DisposeHandle( datahandle ); #endif + + return hasData; } bool wxClipboard::GetData( wxDataObject& data ) { - wxCHECK_MSG( m_open, FALSE, wxT("clipboard not open") ); + wxCHECK_MSG( m_open, false, wxT("clipboard not open") ); - int formatcount = data.GetFormatCount() + 1 ; - wxDataFormat *array = new wxDataFormat[ formatcount ]; + size_t formatcount = data.GetFormatCount() + 1; + wxDataFormat *array = new wxDataFormat[ formatcount ]; array[0] = data.GetPreferredFormat(); data.GetAllFormats( &array[1] ); - bool transferred = false ; + 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) + for (size_t i = 0; !transferred && i < formatcount; i++) + { + wxDataFormat format = array[ i ]; + if ( m_data->IsSupported( format ) ) { - data.SetData(format , 0 , 0 ) ; + int dataSize = m_data->GetDataSize( format ); + transferred = true; + + if (dataSize == 0) + { + data.SetData( format, 0, 0 ); + } + else + { + char *d = new char[ dataSize ]; + m_data->GetDataHere( format, (void*)d ); + data.SetData( format, dataSize, d ); + delete [] d; + } } - 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 ) + + // get formats from wxDataObjects + if ( !transferred ) { - #if !TARGET_CARBON - OSErr err = noErr ; - #else - OSStatus err = noErr ; - #endif - for (size_t i = 0; !transferred && i < formatcount ; i++) - { - wxDataFormat format = array[i] ; - - switch ( format.GetType() ) - { - case wxDF_TEXT: - case wxDF_OEMTEXT: - { - long len ; - char* s = (char*)wxGetClipboardData(format, &len ); - if ( s ) - { - data.SetData( format , len , s ) ; - delete [] s; - - transferred = true ; - } - } - default : - break ; - } - } + for (size_t i = 0; !transferred && i < formatcount; i++) + { + wxDataFormat format = array[ i ]; + + switch ( format.GetType() ) + { + // NOTE: this is usable for all data types + case wxDF_TEXT: + case wxDF_UNICODETEXT: + case wxDF_OEMTEXT: + case wxDF_BITMAP: + case wxDF_METAFILE: + default: + { + long len; + char* s = (char*)wxGetClipboardData( format, &len ); + if (s != NULL) + { + data.SetData( format, len, s ); + delete [] s; + + transferred = true; + } + } + break; + } + } } - delete[] array ; - return transferred ; + delete [] array; + + return transferred; } + +#endif