git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@23579 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
416 lines
10 KiB
C++
416 lines
10 KiB
C++
/////////////////////////////////////////////////////////////////////////////
|
|
// Name: clipbrd.cpp
|
|
// Purpose: Clipboard functionality
|
|
// Author: Stefan Csomor
|
|
// Modified by:
|
|
// Created: 1998-01-01
|
|
// RCS-ID: $Id$
|
|
// Copyright: (c) Stefan Csomor
|
|
// Licence: wxWindows licence
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
#ifdef __GNUG__
|
|
#pragma implementation "clipbrd.h"
|
|
#endif
|
|
|
|
#include "wx/app.h"
|
|
#include "wx/frame.h"
|
|
#include "wx/bitmap.h"
|
|
#include "wx/utils.h"
|
|
#include "wx/metafile.h"
|
|
#include "wx/clipbrd.h"
|
|
#include "wx/intl.h"
|
|
#include "wx/log.h"
|
|
|
|
#ifndef __DARWIN__
|
|
#include <Scrap.h>
|
|
#endif
|
|
#include "wx/mac/uma.h"
|
|
|
|
#define wxUSE_DATAOBJ 1
|
|
|
|
#include <string.h>
|
|
|
|
// 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 )
|
|
{
|
|
char * buf = (char*) data ;
|
|
while( (buf=strchr(buf,0x0a)) != NULL )
|
|
{
|
|
*buf = 13 ;
|
|
buf++ ;
|
|
}
|
|
}
|
|
|
|
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 )
|
|
{
|
|
// 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
|
|
|
|
switch ( array[i].GetType() )
|
|
{
|
|
case wxDF_TEXT:
|
|
case wxDF_OEMTEXT:
|
|
{
|
|
wxTextDataObject* textDataObject = (wxTextDataObject*) data;
|
|
wxCharBuffer buf = textDataObject->GetText().mb_str() ;
|
|
err = UMAPutScrap( strlen(buf) , kScrapFlavorTypeText , (void*) buf.data() ) ;
|
|
}
|
|
break ;
|
|
#if wxUSE_UNICODE
|
|
case wxDF_UNICODETEXT :
|
|
{
|
|
wxTextDataObject* textDataObject = (wxTextDataObject*) data;
|
|
wxString str(textDataObject->GetText());
|
|
err = UMAPutScrap( str.Length() * sizeof(wxChar) , kScrapFlavorTypeUnicode , (void*) str.wc_str() ) ;
|
|
}
|
|
break ;
|
|
#endif
|
|
#if wxUSE_DRAG_AND_DROP
|
|
case wxDF_METAFILE:
|
|
{
|
|
wxMetafileDataObject* metaFileDataObject =
|
|
(wxMetafileDataObject*) data;
|
|
wxMetafile metaFile = metaFileDataObject->GetMetafile();
|
|
PicHandle pict = (PicHandle) metaFile.GetHMETAFILE() ;
|
|
HLock( (Handle) pict ) ;
|
|
err = UMAPutScrap( GetHandleSize( (Handle) pict ) , kScrapFlavorTypePicture , *pict ) ;
|
|
HUnlock( (Handle) pict ) ;
|
|
}
|
|
break ;
|
|
#endif
|
|
case wxDF_BITMAP:
|
|
case wxDF_DIB:
|
|
{
|
|
bool created = false ;
|
|
PicHandle pict = NULL ;
|
|
|
|
wxBitmapDataObject* bitmapDataObject = (wxBitmapDataObject*) data ;
|
|
pict = (PicHandle) bitmapDataObject->GetBitmap().GetPict( &created ) ;
|
|
|
|
HLock( (Handle) pict ) ;
|
|
err = UMAPutScrap( GetHandleSize( (Handle) pict ) , kScrapFlavorTypePicture , *pict ) ;
|
|
HUnlock( (Handle) pict ) ;
|
|
if ( created )
|
|
KillPicture( pict ) ;
|
|
}
|
|
default:
|
|
break ;
|
|
}
|
|
|
|
}
|
|
|
|
delete[] array;
|
|
|
|
return true ;
|
|
}
|
|
|
|
void wxClipboard::Close()
|
|
{
|
|
m_open = false ;
|
|
}
|
|
|
|
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 ;
|
|
}
|