diff options
Diffstat (limited to 'dtrans/source/win32/dtobj')
23 files changed, 5392 insertions, 0 deletions
diff --git a/dtrans/source/win32/dtobj/APNDataObject.cxx b/dtrans/source/win32/dtobj/APNDataObject.cxx new file mode 100644 index 000000000000..775e952ac885 --- /dev/null +++ b/dtrans/source/win32/dtobj/APNDataObject.cxx @@ -0,0 +1,378 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_dtrans.hxx" + +//------------------------------------------------------------------------ +// includes +//------------------------------------------------------------------------ +#include "APNDataObject.hxx" +#include <osl/diagnose.h> + +#include <systools/win32/comtools.hxx> +#ifdef __MINGW32__ +#define __uuidof(I) IID_##I +#endif + +//------------------------------------------------------------------------ +// defines +//------------------------------------------------------------------------ + +#define FREE_HGLOB_ON_RELEASE TRUE +#define KEEP_HGLOB_ON_RELEASE FALSE + +//------------------------------------------------------------------------ +// ctor +//------------------------------------------------------------------------ + +CAPNDataObject::CAPNDataObject( IDataObjectPtr rIDataObject ) : + m_rIDataObjectOrg( rIDataObject ), + m_hGlobal( NULL ), + m_nRefCnt( 0 ) +{ + + OSL_ENSURE( m_rIDataObjectOrg.get( ), "constructing CAPNDataObject with empty data object" ); + + // we marshal the IDataObject interface pointer here so + // that it can be unmarshaled multiple times when this + // class will be used from another apartment + IStreamPtr pStm; + HRESULT hr = CreateStreamOnHGlobal( 0, KEEP_HGLOB_ON_RELEASE, &pStm ); + + OSL_ENSURE( E_INVALIDARG != hr, "invalid args passed to CreateStreamOnHGlobal" ); + + if ( SUCCEEDED( hr ) ) + { + HRESULT hr_marshal = CoMarshalInterface( + pStm.get(), + __uuidof(IDataObject), + static_cast<LPUNKNOWN>(m_rIDataObjectOrg.get()), + MSHCTX_LOCAL, + NULL, + MSHLFLAGS_TABLEWEAK ); + + OSL_ENSURE( CO_E_NOTINITIALIZED != hr_marshal, "COM is not initialized" ); + + // marshalling may fail if COM is not initialized + // for the calling thread which is a program time + // error or because of stream errors which are runtime + // errors for instance E_OUTOFMEMORY etc. + + hr = GetHGlobalFromStream(pStm.get(), &m_hGlobal ); + + OSL_ENSURE( E_INVALIDARG != hr, "invalid stream passed to GetHGlobalFromStream" ); + + // if the marshalling failed we free the + // global memory again and set m_hGlobal + // to a defined value + if (FAILED(hr_marshal)) + { + OSL_ENSURE(sal_False, "marshalling failed"); + + #if OSL_DEBUG_LEVEL > 0 + HGLOBAL hGlobal = + #endif + GlobalFree(m_hGlobal); + OSL_ENSURE(NULL == hGlobal, "GlobalFree failed"); + m_hGlobal = NULL; + } + } +} + +CAPNDataObject::~CAPNDataObject( ) +{ + if (m_hGlobal) + { + IStreamPtr pStm; + HRESULT hr = CreateStreamOnHGlobal(m_hGlobal, FREE_HGLOB_ON_RELEASE, &pStm); + + OSL_ENSURE( E_INVALIDARG != hr, "invalid args passed to CreateStreamOnHGlobal" ); + + if (SUCCEEDED(hr)) + { + hr = CoReleaseMarshalData(pStm.get()); + OSL_ENSURE(SUCCEEDED(hr), "CoReleaseMarshalData failed"); + } + } +} + +//------------------------------------------------------------------------ +// IUnknown->QueryInterface +//------------------------------------------------------------------------ + +STDMETHODIMP CAPNDataObject::QueryInterface( REFIID iid, LPVOID* ppvObject ) +{ + OSL_ASSERT( NULL != ppvObject ); + + if ( NULL == ppvObject ) + return E_INVALIDARG; + + HRESULT hr = E_NOINTERFACE; + *ppvObject = NULL; + + if ( ( __uuidof( IUnknown ) == iid ) || ( __uuidof( IDataObject ) == iid ) ) + { + *ppvObject = static_cast< IUnknown* >( this ); + ( (LPUNKNOWN)*ppvObject )->AddRef( ); + hr = S_OK; + } + + return hr; +} + +//------------------------------------------------------------------------ +// IUnknown->AddRef +//------------------------------------------------------------------------ + +STDMETHODIMP_(ULONG) CAPNDataObject::AddRef( ) +{ + return static_cast< ULONG >( InterlockedIncrement( &m_nRefCnt ) ); +} + +//------------------------------------------------------------------------ +// IUnknown->Release +//------------------------------------------------------------------------ + +STDMETHODIMP_(ULONG) CAPNDataObject::Release( ) +{ + // we need a helper variable because it's not allowed to access + // a member variable after an object is destroyed + ULONG nRefCnt = static_cast< ULONG >( InterlockedDecrement( &m_nRefCnt ) ); + + if ( 0 == nRefCnt ) + delete this; + + return nRefCnt; +} + +//------------------------------------------------------------------------ +// IDataObject->GetData +//------------------------------------------------------------------------ + +STDMETHODIMP CAPNDataObject::GetData( LPFORMATETC pFormatetc, LPSTGMEDIUM pmedium ) +{ + HRESULT hr = m_rIDataObjectOrg->GetData( pFormatetc, pmedium ); + + if (RPC_E_WRONG_THREAD == hr) + { + IDataObjectPtr pIDOTmp; + hr = MarshalIDataObjectIntoCurrentApartment(&pIDOTmp); + + if (SUCCEEDED(hr)) + hr = pIDOTmp->GetData(pFormatetc, pmedium); + } + return hr; +} + +//------------------------------------------------------------------------ +// IDataObject->EnumFormatEtc +//------------------------------------------------------------------------ + +STDMETHODIMP CAPNDataObject::EnumFormatEtc( DWORD dwDirection, IEnumFORMATETC** ppenumFormatetc ) +{ + HRESULT hr = m_rIDataObjectOrg->EnumFormatEtc(dwDirection, ppenumFormatetc); + + if (RPC_E_WRONG_THREAD == hr) + { + IDataObjectPtr pIDOTmp; + hr = MarshalIDataObjectIntoCurrentApartment(&pIDOTmp); + + if (SUCCEEDED(hr)) + hr = pIDOTmp->EnumFormatEtc(dwDirection, ppenumFormatetc); + } + return hr; +} + +//------------------------------------------------------------------------ +// IDataObject->QueryGetData +//------------------------------------------------------------------------ + +STDMETHODIMP CAPNDataObject::QueryGetData( LPFORMATETC pFormatetc ) +{ + HRESULT hr = m_rIDataObjectOrg->QueryGetData( pFormatetc ); + + if (RPC_E_WRONG_THREAD == hr) + { + IDataObjectPtr pIDOTmp; + hr = MarshalIDataObjectIntoCurrentApartment( &pIDOTmp ); + + if (SUCCEEDED(hr)) + hr = pIDOTmp->QueryGetData(pFormatetc); + } + return hr; +} + +//------------------------------------------------------------------------ +// IDataObject->GetDataHere +//------------------------------------------------------------------------ + +STDMETHODIMP CAPNDataObject::GetDataHere( LPFORMATETC pFormatetc, LPSTGMEDIUM pmedium ) +{ + HRESULT hr = m_rIDataObjectOrg->GetDataHere(pFormatetc, pmedium); + + if (RPC_E_WRONG_THREAD == hr) + { + IDataObjectPtr pIDOTmp; + hr = MarshalIDataObjectIntoCurrentApartment(&pIDOTmp); + + if (SUCCEEDED(hr)) + hr = pIDOTmp->GetDataHere(pFormatetc, pmedium); + } + return hr; +} + +//------------------------------------------------------------------------ +// IDataObject->GetCanonicalFormatEtc +//------------------------------------------------------------------------ + +STDMETHODIMP CAPNDataObject::GetCanonicalFormatEtc(LPFORMATETC pFormatectIn, LPFORMATETC pFormatetcOut) +{ + HRESULT hr = m_rIDataObjectOrg->GetCanonicalFormatEtc( pFormatectIn, pFormatetcOut ); + + if (RPC_E_WRONG_THREAD == hr) + { + IDataObjectPtr pIDOTmp; + hr = MarshalIDataObjectIntoCurrentApartment(&pIDOTmp); + + if (SUCCEEDED(hr)) + hr = pIDOTmp->GetCanonicalFormatEtc(pFormatectIn, pFormatetcOut); + } + return hr; +} + +//------------------------------------------------------------------------ +// IDataObject->SetData +//------------------------------------------------------------------------ + +STDMETHODIMP CAPNDataObject::SetData( LPFORMATETC pFormatetc, LPSTGMEDIUM pmedium, BOOL fRelease ) +{ + HRESULT hr = m_rIDataObjectOrg->SetData( pFormatetc, pmedium, fRelease ); + + if (RPC_E_WRONG_THREAD == hr) + { + IDataObjectPtr pIDOTmp; + hr = MarshalIDataObjectIntoCurrentApartment(&pIDOTmp); + + if (SUCCEEDED(hr)) + hr = pIDOTmp->SetData(pFormatetc, pmedium, fRelease); + } + return hr; +} + +//------------------------------------------------------------------------ +// IDataObject->DAdvise +//------------------------------------------------------------------------ + +STDMETHODIMP CAPNDataObject::DAdvise( LPFORMATETC pFormatetc, DWORD advf, LPADVISESINK pAdvSink, DWORD * pdwConnection ) +{ + HRESULT hr = m_rIDataObjectOrg->DAdvise(pFormatetc, advf, pAdvSink, pdwConnection); + + if (RPC_E_WRONG_THREAD == hr) + { + IDataObjectPtr pIDOTmp; + hr = MarshalIDataObjectIntoCurrentApartment(&pIDOTmp); + + if (SUCCEEDED(hr)) + hr = pIDOTmp->DAdvise(pFormatetc, advf, pAdvSink, pdwConnection); + } + return hr; +} + +//------------------------------------------------------------------------ +// IDataObject->DUnadvise +//------------------------------------------------------------------------ + +STDMETHODIMP CAPNDataObject::DUnadvise( DWORD dwConnection ) +{ + HRESULT hr = m_rIDataObjectOrg->DUnadvise( dwConnection ); + + if (RPC_E_WRONG_THREAD == hr) + { + IDataObjectPtr pIDOTmp; + hr = MarshalIDataObjectIntoCurrentApartment(&pIDOTmp); + + if (SUCCEEDED(hr)) + hr = pIDOTmp->DUnadvise(dwConnection); + } + return hr; +} + +//------------------------------------------------------------------------ +// IDataObject->EnumDAdvise +//------------------------------------------------------------------------ + +STDMETHODIMP CAPNDataObject::EnumDAdvise( LPENUMSTATDATA * ppenumAdvise ) +{ + HRESULT hr = m_rIDataObjectOrg->EnumDAdvise(ppenumAdvise); + + if (RPC_E_WRONG_THREAD == hr) + { + IDataObjectPtr pIDOTmp; + hr = MarshalIDataObjectIntoCurrentApartment(&pIDOTmp); + + if (SUCCEEDED(hr)) + hr = pIDOTmp->EnumDAdvise(ppenumAdvise); + } + return hr; +} + +//------------------------------------------------------------------------ +// for our convenience +//------------------------------------------------------------------------ + +CAPNDataObject::operator IDataObject*( ) +{ + return static_cast< IDataObject* >( this ); +} + +//------------------------------------------------------------------------ +// helper function +//------------------------------------------------------------------------ + +HRESULT CAPNDataObject::MarshalIDataObjectIntoCurrentApartment( IDataObject** ppIDataObj ) +{ + OSL_ASSERT(NULL != ppIDataObj); + + *ppIDataObj = NULL; + HRESULT hr = E_FAIL; + + if (m_hGlobal) + { + IStreamPtr pStm; + hr = CreateStreamOnHGlobal(m_hGlobal, KEEP_HGLOB_ON_RELEASE, &pStm); + + OSL_ENSURE(E_INVALIDARG != hr, "CreateStreamOnHGlobal with invalid args called"); + + if (SUCCEEDED(hr)) + { + hr = CoUnmarshalInterface(pStm.get(), __uuidof(IDataObject), (void**)ppIDataObj); + OSL_ENSURE(CO_E_NOTINITIALIZED != hr, "COM is not initialized"); + } + } + return hr; +} diff --git a/dtrans/source/win32/dtobj/APNDataObject.hxx b/dtrans/source/win32/dtobj/APNDataObject.hxx new file mode 100644 index 000000000000..990e38236e66 --- /dev/null +++ b/dtrans/source/win32/dtobj/APNDataObject.hxx @@ -0,0 +1,89 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + + +#ifndef _APNDATAOBJECT_HXX_ +#define _APNDATAOBJECT_HXX_ + +#include <systools/win32/comtools.hxx> + +//------------------------------------------------------------------------ +// deklarations +//------------------------------------------------------------------------ + +/* + an APartment Neutral dataobject wrapper; this wrapper of a IDataObject + pointer can be used from any apartment without RPC_E_WRONG_THREAD + which normally occurs if an apartment tries to use an interface + pointer of another apartment; we use containment to hold the original + DataObject +*/ +class CAPNDataObject : public IDataObject +{ +public: + CAPNDataObject( IDataObjectPtr rIDataObject ); + virtual ~CAPNDataObject( ); + + //----------------------------------------------------------------- + //IUnknown interface methods + //----------------------------------------------------------------- + + STDMETHODIMP QueryInterface(REFIID iid, LPVOID* ppvObject); + STDMETHODIMP_( ULONG ) AddRef( ); + STDMETHODIMP_( ULONG ) Release( ); + + //----------------------------------------------------------------- + // IDataObject interface methods + //----------------------------------------------------------------- + + STDMETHODIMP GetData( LPFORMATETC pFormatetc, LPSTGMEDIUM pmedium ); + STDMETHODIMP GetDataHere( LPFORMATETC pFormatetc, LPSTGMEDIUM pmedium ); + STDMETHODIMP QueryGetData( LPFORMATETC pFormatetc ); + STDMETHODIMP GetCanonicalFormatEtc( LPFORMATETC pFormatectIn, LPFORMATETC pFormatetcOut ); + STDMETHODIMP SetData( LPFORMATETC pFormatetc, LPSTGMEDIUM pmedium, BOOL fRelease ); + STDMETHODIMP EnumFormatEtc( DWORD dwDirection, IEnumFORMATETC** ppenumFormatetc ); + STDMETHODIMP DAdvise( LPFORMATETC pFormatetc, DWORD advf, LPADVISESINK pAdvSink, DWORD* pdwConnection ); + STDMETHODIMP DUnadvise( DWORD dwConnection ); + STDMETHODIMP EnumDAdvise( LPENUMSTATDATA* ppenumAdvise ); + + operator IDataObject*( ); + +private: + HRESULT MarshalIDataObjectIntoCurrentApartment( IDataObject** ppIDataObj ); + +private: + IDataObjectPtr m_rIDataObjectOrg; + HGLOBAL m_hGlobal; + LONG m_nRefCnt; + +// prevent copy and assignment +private: + CAPNDataObject( const CAPNDataObject& theOther ); + CAPNDataObject& operator=( const CAPNDataObject& theOther ); +}; + +#endif diff --git a/dtrans/source/win32/dtobj/DOTransferable.cxx b/dtrans/source/win32/dtobj/DOTransferable.cxx new file mode 100644 index 000000000000..951c3a69d291 --- /dev/null +++ b/dtrans/source/win32/dtobj/DOTransferable.cxx @@ -0,0 +1,605 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_dtrans.hxx" + +//------------------------------------------------------------------------ +// includes +//------------------------------------------------------------------------ +#include <sal/types.h> +#include <rtl/process.h> + +#ifndef _DOWRAPPERTRANSFERABLE_HXX_ +#include "DOTransferable.hxx" +#endif +#include "..\misc\ImplHelper.hxx" +#include "..\misc\WinClip.hxx" +#include "DTransHelper.hxx" +#include "..\misc\ImplHelper.hxx" +#include "TxtCnvtHlp.hxx" +#include "MimeAttrib.hxx" +#include "FmtFilter.hxx" +#include "Fetc.hxx" + + +#if(_MSC_VER < 1300) && !defined(__MINGW32__) +#include <olestd.h> +#endif + +#define STR2(x) #x +#define STR(x) STR2(x) +#define PRAGMA_MSG( msg ) message( __FILE__ "(" STR(__LINE__) "): " #msg ) + +//------------------------------------------------------------------------ +// namespace directives +//------------------------------------------------------------------------ + +using namespace rtl; +using namespace std; +using namespace osl; +using namespace cppu; +using namespace com::sun::star::uno; +using namespace com::sun::star::datatransfer; +using namespace com::sun::star::io; +using namespace com::sun::star::lang; +using namespace com::sun::star::container; + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +namespace +{ + const Type CPPUTYPE_SEQINT8 = getCppuType( ( Sequence< sal_Int8 >* )0 ); + const Type CPPUTYPE_OUSTRING = getCppuType( (OUString*)0 ); + + inline + sal_Bool isValidFlavor( const DataFlavor& aFlavor ) + { + return ( aFlavor.MimeType.getLength( ) && + ( ( aFlavor.DataType == CPPUTYPE_SEQINT8 ) || + ( aFlavor.DataType == CPPUTYPE_OUSTRING ) ) ); + } + +} // end namespace + + +//------------------------------------------------------------------------ +// ctor +//------------------------------------------------------------------------ + +CDOTransferable::CDOTransferable( + const Reference< XMultiServiceFactory >& ServiceManager, IDataObjectPtr rDataObject ) : + m_rDataObject( rDataObject ), + m_SrvMgr( ServiceManager ), + m_DataFormatTranslator( m_SrvMgr ), + m_bUnicodeRegistered( sal_False ), + m_TxtFormatOnClipboard( CF_INVALID ) +{ +} + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +Any SAL_CALL CDOTransferable::getTransferData( const DataFlavor& aFlavor ) + throw( UnsupportedFlavorException, IOException, RuntimeException ) +{ + OSL_ASSERT( isValidFlavor( aFlavor ) ); + + MutexGuard aGuard( m_aMutex ); + + //------------------------------------------------ + // convert dataflavor to formatetc + //------------------------------------------------ + + CFormatEtc fetc = m_DataFormatTranslator.getFormatEtcFromDataFlavor( aFlavor ); + OSL_ASSERT( CF_INVALID != fetc.getClipformat() ); + + //------------------------------------------------ + // get the data from clipboard in a byte stream + //------------------------------------------------ + + ByteSequence_t clipDataStream; + + try + { + clipDataStream = getClipboardData( fetc ); + } + catch( UnsupportedFlavorException& ) + { + if ( m_DataFormatTranslator.isUnicodeTextFormat( fetc.getClipformat( ) ) && + m_bUnicodeRegistered ) + { + OUString aUnicodeText = synthesizeUnicodeText( ); + Any aAny = makeAny( aUnicodeText ); + return aAny; + } + else + throw; // pass through exception + } + + //------------------------------------------------ + // return the data as any + //------------------------------------------------ + + return byteStreamToAny( clipDataStream, aFlavor.DataType ); +} + +//------------------------------------------------------------------------ +// getTransferDataFlavors +//------------------------------------------------------------------------ + +Sequence< DataFlavor > SAL_CALL CDOTransferable::getTransferDataFlavors( ) + throw( RuntimeException ) +{ + return m_FlavorList; +} + +//------------------------------------------------------------------------ +// isDataFlavorSupported +// returns true if we find a DataFlavor with the same MimeType and +// DataType +//------------------------------------------------------------------------ + +sal_Bool SAL_CALL CDOTransferable::isDataFlavorSupported( const DataFlavor& aFlavor ) + throw( RuntimeException ) +{ + OSL_ASSERT( isValidFlavor( aFlavor ) ); + + for ( sal_Int32 i = 0; i < m_FlavorList.getLength( ); i++ ) + if ( compareDataFlavors( aFlavor, m_FlavorList[i] ) ) + return sal_True; + + return sal_False; +} + +//------------------------------------------------------------------------ +// helper function +// the list of datafalvors currently on the clipboard will be initialized +// only once; if the client of this Transferable will hold a reference +// to it und the underlying clipboard content changes, the client does +// possible operate on a invalid list +// if there is only text on the clipboard we will also offer unicode text +// an synthesize this format on the fly if requested, to accomplish this +// we save the first offered text format which we will later use for the +// conversion +//------------------------------------------------------------------------ + +void SAL_CALL CDOTransferable::initFlavorList( ) +{ + IEnumFORMATETCPtr pEnumFormatEtc; + HRESULT hr = m_rDataObject->EnumFormatEtc( DATADIR_GET, &pEnumFormatEtc ); + if ( SUCCEEDED( hr ) ) + { + pEnumFormatEtc->Reset( ); + + FORMATETC fetc; + while ( S_FALSE != pEnumFormatEtc->Next( 1, &fetc, NULL ) ) + { + // we use locales only to determine the + // charset if there is text on the cliboard + // we don't offer this format + if ( CF_LOCALE == fetc.cfFormat ) + continue; + + DataFlavor aFlavor = formatEtcToDataFlavor( fetc ); + + // if text or oemtext is offered we also pretend to have unicode text + if ( m_DataFormatTranslator.isOemOrAnsiTextFormat( fetc.cfFormat ) && + !m_bUnicodeRegistered ) + { + addSupportedFlavor( aFlavor ); + + m_TxtFormatOnClipboard = fetc.cfFormat; + m_bUnicodeRegistered = sal_True; + + // register unicode text as accompany format + aFlavor = formatEtcToDataFlavor( + m_DataFormatTranslator.getFormatEtcForClipformat( CF_UNICODETEXT ) ); + addSupportedFlavor( aFlavor ); + } + else if ( (CF_UNICODETEXT == fetc.cfFormat) && !m_bUnicodeRegistered ) + { + addSupportedFlavor( aFlavor ); + m_bUnicodeRegistered = sal_True; + } + else + addSupportedFlavor( aFlavor ); + + // see MSDN IEnumFORMATETC + CoTaskMemFree( fetc.ptd ); + } + } +} + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +inline +void SAL_CALL CDOTransferable::addSupportedFlavor( const DataFlavor& aFlavor ) +{ + // we ignore all formats that couldn't be translated + if ( aFlavor.MimeType.getLength( ) ) + { + OSL_ASSERT( isValidFlavor( aFlavor ) ); + + m_FlavorList.realloc( m_FlavorList.getLength( ) + 1 ); + m_FlavorList[m_FlavorList.getLength( ) - 1] = aFlavor; + } +} + +//------------------------------------------------------------------------ +// helper function +//------------------------------------------------------------------------ + +//inline +DataFlavor SAL_CALL CDOTransferable::formatEtcToDataFlavor( const FORMATETC& aFormatEtc ) +{ + DataFlavor aFlavor; + LCID lcid = 0; + + // for non-unicode text format we must provid a locale to get + // the character-set of the text, if there is no locale on the + // clipboard we assume the text is in a charset appropriate for + // the current thread locale + if ( (CF_TEXT == aFormatEtc.cfFormat) || (CF_OEMTEXT == aFormatEtc.cfFormat) ) + lcid = getLocaleFromClipboard( ); + + return m_DataFormatTranslator.getDataFlavorFromFormatEtc( aFormatEtc, lcid ); +} + +//------------------------------------------------------------------------ +// returns the current locale on clipboard; if there is no locale on +// clipboard the function returns the current thread locale +//------------------------------------------------------------------------ + +LCID SAL_CALL CDOTransferable::getLocaleFromClipboard( ) +{ + LCID lcid = GetThreadLocale( ); + + try + { + CFormatEtc fetc = m_DataFormatTranslator.getFormatEtcForClipformat( CF_LOCALE ); + ByteSequence_t aLCIDSeq = getClipboardData( fetc ); + lcid = *(reinterpret_cast<LCID*>( aLCIDSeq.getArray( ) ) ); + + // because of a Win95/98 Bug; there the high word + // of a locale has the same value as the + // low word e.g. 0x07040704 that's not right + // correct is 0x00000704 + lcid &= 0x0000FFFF; + } + catch(...) + { + // we take the default locale + } + + return lcid; +} + +//------------------------------------------------------------------------ +// i think it's not necessary to call ReleaseStgMedium +// in case of failures because nothing should have been +// allocated etc. +//------------------------------------------------------------------------ + +CDOTransferable::ByteSequence_t SAL_CALL CDOTransferable::getClipboardData( CFormatEtc& aFormatEtc ) +{ + STGMEDIUM stgmedium; + HRESULT hr = m_rDataObject->GetData( aFormatEtc, &stgmedium ); + + // in case of failure to get a WMF metafile handle, try to get a memory block + if( FAILED( hr ) && + ( CF_METAFILEPICT == aFormatEtc.getClipformat() ) && + ( TYMED_MFPICT == aFormatEtc.getTymed() ) ) + { + CFormatEtc aTempFormat( aFormatEtc ); + aTempFormat.setTymed( TYMED_HGLOBAL ); + hr = m_rDataObject->GetData( aTempFormat, &stgmedium ); + } + + if ( FAILED( hr ) ) + { + OSL_ASSERT( (hr != E_INVALIDARG) && + (hr != DV_E_DVASPECT) && + (hr != DV_E_LINDEX) && + (hr != DV_E_TYMED) ); + + if ( DV_E_FORMATETC == hr ) + throw UnsupportedFlavorException( ); + else if ( STG_E_MEDIUMFULL == hr ) + throw IOException( ); + else + throw RuntimeException( ); + } + + ByteSequence_t byteStream; + + try + { + if ( CF_ENHMETAFILE == aFormatEtc.getClipformat() ) + byteStream = WinENHMFPictToOOMFPict( stgmedium.hEnhMetaFile ); + else if (CF_HDROP == aFormatEtc.getClipformat()) + byteStream = CF_HDROPToFileList(stgmedium.hGlobal); + else + { + clipDataToByteStream( aFormatEtc.getClipformat( ), stgmedium, byteStream ); + + // format conversion if necessary + if ( CF_DIB == aFormatEtc.getClipformat() ) + byteStream = WinDIBToOOBMP( byteStream ); + else if ( CF_METAFILEPICT == aFormatEtc.getClipformat() ) + byteStream = WinMFPictToOOMFPict( byteStream ); + } + + ReleaseStgMedium( &stgmedium ); + } + catch( CStgTransferHelper::CStgTransferException& ) + { + ReleaseStgMedium( &stgmedium ); + throw IOException( ); + } + + return byteStream; +} + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +OUString SAL_CALL CDOTransferable::synthesizeUnicodeText( ) +{ + ByteSequence_t aTextSequence; + CFormatEtc fetc; + LCID lcid = getLocaleFromClipboard( ); + sal_uInt32 cpForTxtCnvt = 0; + + if ( CF_TEXT == m_TxtFormatOnClipboard ) + { + fetc = m_DataFormatTranslator.getFormatEtcForClipformat( CF_TEXT ); + aTextSequence = getClipboardData( fetc ); + + // determine the codepage used for text conversion + cpForTxtCnvt = getWinCPFromLocaleId( lcid, LOCALE_IDEFAULTANSICODEPAGE ).toInt32( ); + } + else if ( CF_OEMTEXT == m_TxtFormatOnClipboard ) + { + fetc = m_DataFormatTranslator.getFormatEtcForClipformat( CF_OEMTEXT ); + aTextSequence = getClipboardData( fetc ); + + // determine the codepage used for text conversion + cpForTxtCnvt = getWinCPFromLocaleId( lcid, LOCALE_IDEFAULTCODEPAGE ).toInt32( ); + } + else + OSL_ASSERT( sal_False ); + + CStgTransferHelper stgTransferHelper; + + // convert the text + MultiByteToWideCharEx( cpForTxtCnvt, + reinterpret_cast<char*>( aTextSequence.getArray( ) ), + sal::static_int_cast<sal_uInt32>(-1), // Huh ? + stgTransferHelper, + sal_False); + + CRawHGlobalPtr ptrHGlob(stgTransferHelper); + sal_Unicode* pWChar = reinterpret_cast<sal_Unicode*>(ptrHGlob.GetMemPtr()); + + return OUString(pWChar); +} + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +void CDOTransferable::clipDataToByteStream( CLIPFORMAT cf, STGMEDIUM stgmedium, ByteSequence_t& aByteSequence ) +{ + CStgTransferHelper memTransferHelper; + + switch( stgmedium.tymed ) + { + case TYMED_HGLOBAL: + memTransferHelper.init( stgmedium.hGlobal ); + break; + + case TYMED_MFPICT: + memTransferHelper.init( stgmedium.hMetaFilePict ); + break; + + case TYMED_ENHMF: + memTransferHelper.init( stgmedium.hEnhMetaFile ); + break; + + case TYMED_ISTREAM: + #ifdef _MSC_VER + #pragma PRAGMA_MSG( Has to be implemented ) + #endif + break; + + default: + throw UnsupportedFlavorException( ); + break; + } + + int nMemSize = memTransferHelper.memSize( cf ); + aByteSequence.realloc( nMemSize ); + memTransferHelper.read( aByteSequence.getArray( ), nMemSize ); +} + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +inline +Any CDOTransferable::byteStreamToAny( ByteSequence_t& aByteStream, const Type& aRequestedDataType ) +{ + Any aAny; + + if ( aRequestedDataType == CPPUTYPE_OUSTRING ) + { + OUString str = byteStreamToOUString( aByteStream ); + aAny = makeAny( str ); + } + else + aAny = makeAny( aByteStream ); + + return aAny; +} + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +inline +OUString CDOTransferable::byteStreamToOUString( ByteSequence_t& aByteStream ) +{ + sal_Int32 nWChars; + sal_Int32 nMemSize = aByteStream.getLength( ); + + // if there is a trailing L"\0" substract 1 from length + if ( 0 == aByteStream[ aByteStream.getLength( ) - 2 ] && + 0 == aByteStream[ aByteStream.getLength( ) - 1 ] ) + nWChars = static_cast< sal_Int32 >( nMemSize / sizeof( sal_Unicode ) ) - 1; + else + nWChars = static_cast< sal_Int32 >( nMemSize / sizeof( sal_Unicode ) ); + + return OUString( reinterpret_cast< sal_Unicode* >( aByteStream.getArray( ) ), nWChars ); +} + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +sal_Bool SAL_CALL CDOTransferable::compareDataFlavors( + const DataFlavor& lhs, const DataFlavor& rhs ) +{ + if ( !m_rXMimeCntFactory.is( ) ) + { + m_rXMimeCntFactory = Reference< XMimeContentTypeFactory >( m_SrvMgr->createInstance( + OUString::createFromAscii( "com.sun.star.datatransfer.MimeContentTypeFactory" ) ), UNO_QUERY ); + } + OSL_ASSERT( m_rXMimeCntFactory.is( ) ); + + sal_Bool bRet = sal_False; + + try + { + Reference< XMimeContentType > xLhs( m_rXMimeCntFactory->createMimeContentType( lhs.MimeType ) ); + Reference< XMimeContentType > xRhs( m_rXMimeCntFactory->createMimeContentType( rhs.MimeType ) ); + + if ( cmpFullMediaType( xLhs, xRhs ) ) + { + bRet = cmpAllContentTypeParameter( xLhs, xRhs ); + } + } + catch( IllegalArgumentException& ) + { + OSL_ENSURE( sal_False, "Invalid content type detected" ); + bRet = sal_False; + } + + return bRet; +} + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +sal_Bool SAL_CALL CDOTransferable::cmpFullMediaType( + const Reference< XMimeContentType >& xLhs, const Reference< XMimeContentType >& xRhs ) const +{ + return xLhs->getFullMediaType().equalsIgnoreAsciiCase( xRhs->getFullMediaType( ) ); +} + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +sal_Bool SAL_CALL CDOTransferable::cmpAllContentTypeParameter( + const Reference< XMimeContentType >& xLhs, const Reference< XMimeContentType >& xRhs ) const +{ + Sequence< OUString > xLhsFlavors = xLhs->getParameters( ); + Sequence< OUString > xRhsFlavors = xRhs->getParameters( ); + sal_Bool bRet = sal_True; + + try + { + if ( xLhsFlavors.getLength( ) == xRhsFlavors.getLength( ) ) + { + OUString pLhs; + OUString pRhs; + + for ( sal_Int32 i = 0; i < xLhsFlavors.getLength( ); i++ ) + { + pLhs = xLhs->getParameterValue( xLhsFlavors[i] ); + pRhs = xRhs->getParameterValue( xLhsFlavors[i] ); + + if ( !pLhs.equalsIgnoreAsciiCase( pRhs ) ) + { + bRet = sal_False; + break; + } + } + } + else + bRet = sal_False; + } + catch( NoSuchElementException& ) + { + bRet = sal_False; + } + catch( IllegalArgumentException& ) + { + bRet = sal_False; + } + + return bRet; +} + +::com::sun::star::uno::Any SAL_CALL CDOTransferable::getData( const Sequence< sal_Int8>& aProcessId ) + throw (::com::sun::star::uno::RuntimeException) +{ + Any retVal; + + sal_uInt8 * arProcCaller= (sal_uInt8*)(sal_Int8*) aProcessId.getConstArray(); + sal_uInt8 arId[16]; + rtl_getGlobalProcessId(arId); + if( ! memcmp( arId, arProcCaller,16)) + { + if (m_rDataObject.is()) + { + IDataObject* pObj= m_rDataObject.get(); + pObj->AddRef(); + retVal.setValue( &pObj, getCppuType((sal_uInt32*)0)); + } + } + return retVal; +} + diff --git a/dtrans/source/win32/dtobj/DOTransferable.hxx b/dtrans/source/win32/dtobj/DOTransferable.hxx new file mode 100644 index 000000000000..dd99e857b908 --- /dev/null +++ b/dtrans/source/win32/dtobj/DOTransferable.hxx @@ -0,0 +1,133 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + + +#ifndef _DOTRANSFERABLE_HXX_ +#define _DOTRANSFERABLE_HXX_ + +//------------------------------------------------------------------------ +// includes +//------------------------------------------------------------------------ + +#include <com/sun/star/datatransfer/XTransferable.hpp> + +#ifndef _CPPUHELPER_IMPLBASE1_HXX_ +#include <cppuhelper/implbase2.hxx> +#endif +#include "DataFmtTransl.hxx" +#include <com/sun/star/datatransfer/XMimeContentTypeFactory.hpp> +#include <com/sun/star/datatransfer/XMimeContentType.hpp> +#include <com/sun/star/datatransfer/XSystemTransferable.hpp> + +#include <systools/win32/comtools.hxx> + +//------------------------------------------------------------------------ +// deklarations +//------------------------------------------------------------------------ + +// forward +class CDTransObjFactory; +class CFormatEtc; + +class CDOTransferable : public ::cppu::WeakImplHelper2< ::com::sun::star::datatransfer::XTransferable, + ::com::sun::star::datatransfer::XSystemTransferable> +{ +public: + typedef com::sun::star::uno::Sequence< sal_Int8 > ByteSequence_t; + + //------------------------------------------------------------------------ + // XTransferable + //------------------------------------------------------------------------ + + virtual ::com::sun::star::uno::Any SAL_CALL getTransferData( const ::com::sun::star::datatransfer::DataFlavor& aFlavor ) + throw( ::com::sun::star::datatransfer::UnsupportedFlavorException, ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException ); + + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::datatransfer::DataFlavor > SAL_CALL getTransferDataFlavors( ) + throw( ::com::sun::star::uno::RuntimeException ); + + virtual sal_Bool SAL_CALL isDataFlavorSupported( const ::com::sun::star::datatransfer::DataFlavor& aFlavor ) + throw( ::com::sun::star::uno::RuntimeException ); + //------------------------------------------------------------------------ + // XSystemTransferable + //------------------------------------------------------------------------ + virtual ::com::sun::star::uno::Any SAL_CALL getData( const com::sun::star::uno::Sequence<sal_Int8>& aProcessId ) throw + (::com::sun::star::uno::RuntimeException); + + +private: + // should be created only by CDTransObjFactory + explicit CDOTransferable( + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& ServiceManager, + IDataObjectPtr rDataObject ); + + //------------------------------------------------------------------------ + // some helper functions + //------------------------------------------------------------------------ + + void SAL_CALL initFlavorList( ); + + void SAL_CALL addSupportedFlavor( const com::sun::star::datatransfer::DataFlavor& aFlavor ); + com::sun::star::datatransfer::DataFlavor SAL_CALL formatEtcToDataFlavor( const FORMATETC& aFormatEtc ); + + ByteSequence_t SAL_CALL getClipboardData( CFormatEtc& aFormatEtc ); + rtl::OUString SAL_CALL synthesizeUnicodeText( ); + + void SAL_CALL clipDataToByteStream( CLIPFORMAT cf, STGMEDIUM stgmedium, ByteSequence_t& aByteSequence ); + + ::com::sun::star::uno::Any SAL_CALL byteStreamToAny( ByteSequence_t& aByteStream, const com::sun::star::uno::Type& aRequestedDataType ); + rtl::OUString SAL_CALL byteStreamToOUString( ByteSequence_t& aByteStream ); + + LCID SAL_CALL getLocaleFromClipboard( ); + + sal_Bool SAL_CALL compareDataFlavors( const com::sun::star::datatransfer::DataFlavor& lhs, + const com::sun::star::datatransfer::DataFlavor& rhs ); + + sal_Bool SAL_CALL cmpFullMediaType( const com::sun::star::uno::Reference< com::sun::star::datatransfer::XMimeContentType >& xLhs, + const com::sun::star::uno::Reference< com::sun::star::datatransfer::XMimeContentType >& xRhs ) const; + + sal_Bool SAL_CALL cmpAllContentTypeParameter( const com::sun::star::uno::Reference< com::sun::star::datatransfer::XMimeContentType >& xLhs, + const com::sun::star::uno::Reference< com::sun::star::datatransfer::XMimeContentType >& xRhs ) const; + +private: + IDataObjectPtr m_rDataObject; + com::sun::star::uno::Sequence< com::sun::star::datatransfer::DataFlavor > m_FlavorList; + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > m_SrvMgr; + CDataFormatTranslator m_DataFormatTranslator; + com::sun::star::uno::Reference< com::sun::star::datatransfer::XMimeContentTypeFactory > m_rXMimeCntFactory; + ::osl::Mutex m_aMutex; + sal_Bool m_bUnicodeRegistered; + CLIPFORMAT m_TxtFormatOnClipboard; + +// non supported operations +private: + CDOTransferable( const CDOTransferable& ); + CDOTransferable& operator=( const CDOTransferable& ); + + friend class CDTransObjFactory; +}; + +#endif diff --git a/dtrans/source/win32/dtobj/DTransHelper.cxx b/dtrans/source/win32/dtobj/DTransHelper.cxx new file mode 100644 index 000000000000..30370fdaf3c8 --- /dev/null +++ b/dtrans/source/win32/dtobj/DTransHelper.cxx @@ -0,0 +1,239 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_dtrans.hxx" + +//------------------------------------------------------------------------ +// includes +//------------------------------------------------------------------------ +#include <rtl/ustring.h> +#include <osl/diagnose.h> +#include "DTransHelper.hxx" + +//------------------------------------------------------------------------ +// implementation +//------------------------------------------------------------------------ + +CStgTransferHelper::CStgTransferHelper( sal_Bool bAutoInit, + HGLOBAL hGlob, + sal_Bool bDelStgOnRelease ) : + m_lpStream( NULL ), + m_bDelStgOnRelease( bDelStgOnRelease ) +{ + if ( bAutoInit ) + init( hGlob, m_bDelStgOnRelease ); +} + +//------------------------------------------------------------------------ +// dtor +//------------------------------------------------------------------------ + + +CStgTransferHelper::~CStgTransferHelper( ) +{ + if ( m_lpStream ) + m_lpStream->Release( ); +} + +//------------------------------------------------------------------------ +// TransferData into the +//------------------------------------------------------------------------ + +void SAL_CALL CStgTransferHelper::write( const void* lpData, ULONG cb, ULONG* cbWritten ) +{ + HRESULT hr = E_FAIL; + + if ( m_lpStream ) + hr = m_lpStream->Write( lpData, cb, cbWritten ); + + if ( FAILED( hr ) ) + throw CStgTransferException( hr ); + +#if OSL_DEBUG_LEVEL > 0 + HGLOBAL hGlob; + hr = GetHGlobalFromStream( m_lpStream, &hGlob ); + OSL_ASSERT( SUCCEEDED( hr ) ); + + /*DWORD dwSize =*/ GlobalSize( hGlob ); + /*LPVOID lpdbgData =*/ GlobalLock( hGlob ); + GlobalUnlock( hGlob ); +#endif +} + +//------------------------------------------------------------------------ +// read +//------------------------------------------------------------------------ + +void SAL_CALL CStgTransferHelper::read( LPVOID pv, ULONG cb, ULONG* pcbRead ) +{ + HRESULT hr = E_FAIL; + + if ( m_lpStream ) + hr = m_lpStream->Read( pv, cb , pcbRead ); + + if ( FAILED( hr ) ) + throw CStgTransferException( hr ); +} + +//------------------------------------------------------------------------ +// GetHGlobal +//------------------------------------------------------------------------ + +HGLOBAL SAL_CALL CStgTransferHelper::getHGlobal( ) const +{ + OSL_ASSERT( m_lpStream ); + + HGLOBAL hGlob = NULL; + + if ( m_lpStream ) + { + HRESULT hr = GetHGlobalFromStream( m_lpStream, &hGlob ); + if ( FAILED( hr ) ) + hGlob = NULL; + } + + return hGlob; +} + +//------------------------------------------------------------------------ +// getIStream +//------------------------------------------------------------------------ + +void SAL_CALL CStgTransferHelper::getIStream( LPSTREAM* ppStream ) +{ + OSL_ASSERT( ppStream ); + *ppStream = m_lpStream; + if ( *ppStream ) + static_cast< LPUNKNOWN >( *ppStream )->AddRef( ); +} + +//------------------------------------------------------------------------ +// Init +//------------------------------------------------------------------------ + +void SAL_CALL CStgTransferHelper::init( SIZE_T newSize, + sal_uInt32 uiFlags, + sal_Bool bDelStgOnRelease ) +{ + cleanup( ); + + m_bDelStgOnRelease = bDelStgOnRelease; + + HGLOBAL hGlob = GlobalAlloc( uiFlags, newSize ); + if ( NULL == hGlob ) + throw CStgTransferException( STG_E_MEDIUMFULL ); + + HRESULT hr = CreateStreamOnHGlobal( hGlob, m_bDelStgOnRelease, &m_lpStream ); + if ( FAILED( hr ) ) + { + GlobalFree( hGlob ); + m_lpStream = NULL; + throw CStgTransferException( hr ); + } + +#if OSL_DEBUG_LEVEL > 0 + STATSTG statstg; + hr = m_lpStream->Stat( &statstg, STATFLAG_DEFAULT ); + OSL_ASSERT( SUCCEEDED( hr ) ); +#endif +} + +//------------------------------------------------------------------------ +// Init +//------------------------------------------------------------------------ + +void SAL_CALL CStgTransferHelper::init( HGLOBAL hGlob, + sal_Bool bDelStgOnRelease ) +{ + cleanup( ); + + m_bDelStgOnRelease = bDelStgOnRelease; + + HRESULT hr = CreateStreamOnHGlobal( hGlob, m_bDelStgOnRelease, &m_lpStream ); + if ( FAILED( hr ) ) + throw CStgTransferException( hr ); +} + +//------------------------------------------------------------------------ +// free the global memory and invalidate the stream pointer +//------------------------------------------------------------------------ + +void SAL_CALL CStgTransferHelper::cleanup( ) +{ + if ( m_lpStream && !m_bDelStgOnRelease ) + { + HGLOBAL hGlob; + GetHGlobalFromStream( m_lpStream, &hGlob ); + GlobalFree( hGlob ); + } + + if ( m_lpStream ) + { + m_lpStream->Release( ); + m_lpStream = NULL; + } +} + +//------------------------------------------------------------------------ +// return the size of memory we point to +//------------------------------------------------------------------------ + +sal_uInt32 SAL_CALL CStgTransferHelper::memSize( CLIPFORMAT cf ) const +{ + DWORD dwSize = 0; + + if ( NULL != m_lpStream ) + { + HGLOBAL hGlob; + GetHGlobalFromStream( m_lpStream, &hGlob ); + + if ( CF_TEXT == cf || RegisterClipboardFormat( "HTML Format" ) == cf ) + { + sal_Char* pText = static_cast< sal_Char* >( GlobalLock( hGlob ) ); + if ( pText ) + { + dwSize = strlen(pText) + 1; // strlen + trailing '\0' + GlobalUnlock( hGlob ); + } + } + else if ( CF_UNICODETEXT == cf ) + { + sal_Unicode* pText = static_cast< sal_Unicode* >( GlobalLock( hGlob ) ); + if ( pText ) + { + dwSize = rtl_ustr_getLength( pText ) * sizeof( sal_Unicode ); + GlobalUnlock( hGlob ); + } + } + else + dwSize = GlobalSize( hGlob ); + } + + return dwSize; +} + diff --git a/dtrans/source/win32/dtobj/DTransHelper.hxx b/dtrans/source/win32/dtobj/DTransHelper.hxx new file mode 100644 index 000000000000..7975b84eec57 --- /dev/null +++ b/dtrans/source/win32/dtobj/DTransHelper.hxx @@ -0,0 +1,214 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + + +#ifndef _DTRANSHELPER_HXX_ +#define _DTRANSHELPER_HXX_ + +//------------------------------------------------------------------------ +// includes +//------------------------------------------------------------------------ + +#if defined _MSC_VER +#pragma warning(push,1) +#endif +#include <windows.h> +#if defined _MSC_VER +#pragma warning(pop) +#endif +#include "..\misc\WinClip.hxx" + +//------------------------------------------------------------------------ +// defines +//------------------------------------------------------------------------ + +#define AUTO_INIT TRUE +#define NO_AUTO_INIT FALSE +#define MEM_DESTROY_ON_RELEASE TRUE +#define NO_MEM_DESTROY_ON_RELEASE FALSE + +//------------------------------------------------------------------------ +// deklarations +//------------------------------------------------------------------------ + + +//------------------------------------------------------------------------- +// a helper class to manage a global memory area, the clients can write +// into the global memory area and extract the handle to the global mem +// note: not thread-safe +//------------------------------------------------------------------------- + +class CStgTransferHelper +{ +public: + // will be thrown in case of failures + class CStgTransferException + { + public: + HRESULT m_hr; + CStgTransferException( HRESULT hr ) : m_hr( hr ) {}; + }; + +public: + CStgTransferHelper( + sal_Bool bAutoInit = sal_False, + HGLOBAL hGlob = NULL, + sal_Bool bDelStgOnRelease = sal_False ); + + ~CStgTransferHelper( ); + + void SAL_CALL write( const void* lpData, ULONG cb, ULONG* cbWritten = NULL ); + void SAL_CALL read( LPVOID pv, ULONG cb, ULONG* pcbRead = NULL ); + + HGLOBAL SAL_CALL getHGlobal( ) const; + void SAL_CALL getIStream( LPSTREAM* ppStream ); + + void SAL_CALL init( + SIZE_T newSize, + sal_uInt32 uiFlags = GHND, + sal_Bool bDelStgOnRelease = sal_False ); + + void SAL_CALL init( + HGLOBAL hGlob, + sal_Bool bDelStgOnRelease = sal_False ); + + // returns the size of the managed memory + sal_uInt32 SAL_CALL memSize( CLIPFORMAT cf = CF_INVALID ) const; + + // free the global memory and necessary + // release the internal stream pointer + void SAL_CALL cleanup( ); + +private: + LPSTREAM m_lpStream; + sal_Bool m_bDelStgOnRelease; + +private: + CStgTransferHelper( const CStgTransferHelper& ); + CStgTransferHelper& operator=( const CStgTransferHelper& ); +}; + +//------------------------------------------------------------------------- +// something like an auto-pointer - allows access to the memory belonging +// to a HGLOBAL and automatically unlocks a global memory at destruction +// time +//------------------------------------------------------------------------- + +class CRawHGlobalPtr +{ +public: + + //--------------------------------------------- + // ctor + //--------------------------------------------- + + CRawHGlobalPtr( HGLOBAL hGlob ) : + m_hGlob( hGlob ), + m_bIsLocked( FALSE ), + m_pGlobMem( NULL ) + { + } + + + //--------------------------------------------- + // ctor + //--------------------------------------------- + + CRawHGlobalPtr( const CStgTransferHelper& theHGlobalHelper ) : + m_hGlob( theHGlobalHelper.getHGlobal( ) ), + m_bIsLocked( FALSE ), + m_pGlobMem( NULL ) + { + } + + //--------------------------------------------- + // dtor + //--------------------------------------------- + + ~CRawHGlobalPtr( ) + { + if ( m_bIsLocked ) + GlobalUnlock( m_hGlob ); + } + + //--------------------------------------------- + // lock the global memory (initializes a + // pointer to this memory) + //--------------------------------------------- + + BOOL Lock( ) + { + if ( !m_bIsLocked && ( NULL != m_hGlob ) ) + { + m_pGlobMem = GlobalLock( m_hGlob ); + m_bIsLocked = ( NULL != m_pGlobMem ); + } + + return m_bIsLocked; + } + + //--------------------------------------------- + // unlock the global memory (invalidates the + // pointer to this memory) + //--------------------------------------------- + + BOOL Unlock( ) + { + GlobalUnlock( m_hGlob ); + m_bIsLocked = FALSE; + m_pGlobMem = NULL; + + return ( NO_ERROR == GetLastError( ) ); + } + + //--------------------------------------------- + // locks the global memory and returns a + // pointer to this memory + //--------------------------------------------- + + LPVOID GetMemPtr( ) + { + Lock( ); + return m_pGlobMem; + } + + //--------------------------------------------- + // size of mem we point to + //--------------------------------------------- + + int MemSize( ) const + { + return GlobalSize( m_hGlob ); + } + +private: + HGLOBAL m_hGlob; + BOOL m_bIsLocked; + LPVOID m_pGlobMem; +}; + +#endif diff --git a/dtrans/source/win32/dtobj/DataFmtTransl.cxx b/dtrans/source/win32/dtobj/DataFmtTransl.cxx new file mode 100644 index 000000000000..f72e8bb714a7 --- /dev/null +++ b/dtrans/source/win32/dtobj/DataFmtTransl.cxx @@ -0,0 +1,336 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_dtrans.hxx" + +//------------------------------------------------------------------------ +// includes +//------------------------------------------------------------------------ +#include "DataFmtTransl.hxx" +#include <rtl/string.hxx> +#include <osl/diagnose.h> +#include <rtl/tencinfo.h> +#include "..\misc\ImplHelper.hxx" +#include "..\misc\WinClip.hxx" +#include "MimeAttrib.hxx" +#include "DTransHelper.hxx" +#include <rtl/string.h> +#include "Fetc.hxx" + +#if defined _MSC_VER +#pragma warning(push,1) +#pragma warning(disable:4917) +#endif +#include <windows.h> +#if (_MSC_VER < 1300) && !defined(__MINGW32__) +#include <olestd.h> +#endif +#include <shlobj.h> +#if defined _MSC_VER +#pragma warning(pop) +#endif + + +//------------------------------------------------------------------------ +// namespace directives +//------------------------------------------------------------------------ + +using namespace rtl; +using namespace std; +using namespace com::sun::star::uno; +using namespace com::sun::star::datatransfer; +using namespace com::sun::star::lang; + +//------------------------------------------------------------------------ +// const +//------------------------------------------------------------------------ + +const Type CPPUTYPE_SALINT32 = getCppuType((sal_Int32*)0); +const Type CPPUTYPE_SALINT8 = getCppuType((sal_Int8*)0); +const Type CPPUTYPE_OUSTRING = getCppuType((OUString*)0); +const Type CPPUTYPE_SEQSALINT8 = getCppuType((Sequence< sal_Int8>*)0); +const sal_Int32 MAX_CLIPFORMAT_NAME = 256; + +const OUString TEXT_PLAIN_CHARSET = OUString::createFromAscii( "text/plain;charset=" ); +const OUString HPNAME_OEM_ANSI_TEXT = OUString::createFromAscii( "OEM/ANSI Text" ); + +const OUString HTML_FORMAT_NAME_WINDOWS = OUString::createFromAscii( "HTML Format" ); +const OUString HTML_FORMAT_NAME_SOFFICE = OUString::createFromAscii( "HTML (HyperText Markup Language)" ); + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +CDataFormatTranslator::CDataFormatTranslator( const Reference< XMultiServiceFactory >& aServiceManager ) : + m_SrvMgr( aServiceManager ) +{ + m_XDataFormatTranslator = Reference< XDataFormatTranslator >( + m_SrvMgr->createInstance( OUString::createFromAscii( "com.sun.star.datatransfer.DataFormatTranslator" ) ), UNO_QUERY ); +} + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +CFormatEtc CDataFormatTranslator::getFormatEtcFromDataFlavor( const DataFlavor& aDataFlavor ) const +{ + sal_Int32 cf = CF_INVALID; + + try + { + if( m_XDataFormatTranslator.is( ) ) + { + Any aFormat = m_XDataFormatTranslator->getSystemDataTypeFromDataFlavor( aDataFlavor ); + + if ( aFormat.hasValue( ) ) + { + if ( aFormat.getValueType( ) == CPPUTYPE_SALINT32 ) + { + aFormat >>= cf; + OSL_ENSURE( CF_INVALID != cf, "Invalid Clipboard format delivered" ); + } + else if ( aFormat.getValueType( ) == CPPUTYPE_OUSTRING ) + { + OUString aClipFmtName; + aFormat >>= aClipFmtName; + + OSL_ASSERT( aClipFmtName.getLength( ) ); + cf = RegisterClipboardFormatW( reinterpret_cast<LPCWSTR>(aClipFmtName.getStr( )) ); + + OSL_ENSURE( CF_INVALID != cf, "RegisterClipboardFormat failed" ); + } + else + OSL_ENSURE( sal_False, "Wrong Any-Type detected" ); + } + } + } + catch( ... ) + { + OSL_ENSURE( sal_False, "Unexpected error" ); + } + + return sal::static_int_cast<CFormatEtc>(getFormatEtcForClipformat( sal::static_int_cast<CLIPFORMAT>(cf) )); +} + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +DataFlavor CDataFormatTranslator::getDataFlavorFromFormatEtc( const FORMATETC& aFormatEtc, LCID lcid ) const +{ + DataFlavor aFlavor; + + try + { + CLIPFORMAT aClipformat = aFormatEtc.cfFormat; + + Any aAny; + aAny <<= static_cast< sal_Int32 >( aClipformat ); + + if ( isOemOrAnsiTextFormat( aClipformat ) ) + { + aFlavor.MimeType = TEXT_PLAIN_CHARSET; + aFlavor.MimeType += getTextCharsetFromLCID( lcid, aClipformat ); + + aFlavor.HumanPresentableName = HPNAME_OEM_ANSI_TEXT; + aFlavor.DataType = CPPUTYPE_SEQSALINT8; + } + else if ( CF_INVALID != aClipformat ) + { + if ( m_XDataFormatTranslator.is( ) ) + { + aFlavor = m_XDataFormatTranslator->getDataFlavorFromSystemDataType( aAny ); + + if ( !aFlavor.MimeType.getLength( ) ) + { + // lookup of DataFlavor from clipboard format id + // failed, so we try to resolve via clipboard + // format name + OUString clipFormatName = getClipboardFormatName( aClipformat ); + + // if we could not get a clipboard format name an + // error must have occured or it is a standard + // clipboard format that we don't translate, e.g. + // CF_BITMAP (the office only uses CF_DIB) + if ( clipFormatName.getLength( ) ) + { + aAny <<= clipFormatName; + aFlavor = m_XDataFormatTranslator->getDataFlavorFromSystemDataType( aAny ); + } + } + } + } + } + catch( ... ) + { + OSL_ENSURE( sal_False, "Unexpected error" ); + } + + return aFlavor; +} + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +CFormatEtc SAL_CALL CDataFormatTranslator::getFormatEtcForClipformatName( const OUString& aClipFmtName ) const +{ + // check parameter + if ( !aClipFmtName.getLength( ) ) + return CFormatEtc( CF_INVALID ); + + CLIPFORMAT cf = sal::static_int_cast<CLIPFORMAT>(RegisterClipboardFormatW( reinterpret_cast<LPCWSTR>(aClipFmtName.getStr( )) )); + return getFormatEtcForClipformat( cf ); +} + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +OUString CDataFormatTranslator::getClipboardFormatName( CLIPFORMAT aClipformat ) const +{ + OSL_PRECOND( CF_INVALID != aClipformat, "Invalid clipboard format" ); + + sal_Unicode wBuff[ MAX_CLIPFORMAT_NAME ]; + sal_Int32 nLen = GetClipboardFormatNameW( aClipformat, reinterpret_cast<LPWSTR>(wBuff), MAX_CLIPFORMAT_NAME ); + + return OUString( wBuff, nLen ); +} + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +CFormatEtc SAL_CALL CDataFormatTranslator::getFormatEtcForClipformat( CLIPFORMAT cf ) const +{ + CFormatEtc fetc( cf, TYMED_NULL, NULL, DVASPECT_CONTENT ); + + switch( cf ) + { + case CF_METAFILEPICT: + fetc.setTymed( TYMED_MFPICT ); + break; + + case CF_ENHMETAFILE: + fetc.setTymed( TYMED_ENHMF ); + break; + + default: + fetc.setTymed( TYMED_HGLOBAL /*| TYMED_ISTREAM*/ ); + } + + /* + hack: in order to paste urls copied by Internet Explorer + with "copy link" we set the lindex member to 0 + but if we really want to support CFSTR_FILECONTENT and + the accompany format CFSTR_FILEDESCRIPTOR (FileGroupDescriptor) + the client of the clipboard service has to provide a id + of which FileContents it wants to paste + see MSDN: "Handling Shell Data Transfer Scenarios" + */ + if ( cf == RegisterClipboardFormatA( CFSTR_FILECONTENTS ) ) + fetc.setLindex( 0 ); + + return fetc; +} + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +sal_Bool SAL_CALL CDataFormatTranslator::isOemOrAnsiTextFormat( CLIPFORMAT cf ) const +{ + return ( (cf == CF_TEXT) || (cf == CF_OEMTEXT) ); +} + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +sal_Bool SAL_CALL CDataFormatTranslator::isUnicodeTextFormat( CLIPFORMAT cf ) const +{ + return ( cf == CF_UNICODETEXT ); +} + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +sal_Bool SAL_CALL CDataFormatTranslator::isTextFormat( CLIPFORMAT cf ) const +{ + return ( isOemOrAnsiTextFormat( cf ) || isUnicodeTextFormat( cf ) ); +} + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +sal_Bool SAL_CALL CDataFormatTranslator::isHTMLFormat( CLIPFORMAT cf ) const +{ + OUString clipFormatName = getClipboardFormatName( cf ); + return ( clipFormatName == HTML_FORMAT_NAME_WINDOWS ); +} + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +sal_Bool SAL_CALL CDataFormatTranslator::isTextHtmlFormat( CLIPFORMAT cf ) const +{ + OUString clipFormatName = getClipboardFormatName( cf ); + return ( clipFormatName.equalsIgnoreAsciiCase( HTML_FORMAT_NAME_SOFFICE ) ); +} + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +OUString SAL_CALL CDataFormatTranslator::getTextCharsetFromLCID( LCID lcid, CLIPFORMAT aClipformat ) const +{ + OSL_ASSERT( isOemOrAnsiTextFormat( aClipformat ) ); + + OUString charset; + if ( CF_TEXT == aClipformat ) + { + charset = getMimeCharsetFromLocaleId( + lcid, + LOCALE_IDEFAULTANSICODEPAGE, + PRE_WINDOWS_CODEPAGE ); + } + else if ( CF_OEMTEXT == aClipformat ) + { + charset = getMimeCharsetFromLocaleId( + lcid, + LOCALE_IDEFAULTCODEPAGE, + PRE_OEM_CODEPAGE ); + } + else // CF_UNICODE + OSL_ASSERT( sal_False ); + + return charset; +} diff --git a/dtrans/source/win32/dtobj/DataFmtTransl.hxx b/dtrans/source/win32/dtobj/DataFmtTransl.hxx new file mode 100644 index 000000000000..70982ccaf6b9 --- /dev/null +++ b/dtrans/source/win32/dtobj/DataFmtTransl.hxx @@ -0,0 +1,83 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + + +#ifndef _DATAFMTTRANSL_HXX_ +#define _DATAFMTTRANSL_HXX_ + +//----------------------------------------------- +// includes +//----------------------------------------------- + +#include <cppuhelper/servicefactory.hxx> +#include <com/sun/star/datatransfer/XDataFormatTranslator.hpp> +#include <com/sun/star/datatransfer/XTransferable.hpp> +#include <sal/types.h> +#include <rtl/ustring.hxx> + +#if defined _MSC_VER +#pragma warning(push,1) +#endif +#include <windows.h> +#if defined _MSC_VER +#pragma warning(pop) +#endif + +//----------------------------------------------- +// declaration +//----------------------------------------------- + +class CFormatEtc; + +class CDataFormatTranslator +{ +public: + CDataFormatTranslator( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& aServiceManager ); + + CFormatEtc getFormatEtcFromDataFlavor( const com::sun::star::datatransfer::DataFlavor& aDataFlavor ) const; + com::sun::star::datatransfer::DataFlavor getDataFlavorFromFormatEtc( + const FORMATETC& aFormatEtc, LCID lcid = GetThreadLocale( ) ) const; + + CFormatEtc SAL_CALL getFormatEtcForClipformat( CLIPFORMAT cf ) const; + CFormatEtc SAL_CALL getFormatEtcForClipformatName( const rtl::OUString& aClipFmtName ) const; + rtl::OUString SAL_CALL getClipboardFormatName( CLIPFORMAT aClipformat ) const; + + sal_Bool SAL_CALL isHTMLFormat( CLIPFORMAT cf ) const; + sal_Bool SAL_CALL isTextHtmlFormat( CLIPFORMAT cf ) const; + sal_Bool SAL_CALL isOemOrAnsiTextFormat( CLIPFORMAT cf ) const; + sal_Bool SAL_CALL isUnicodeTextFormat( CLIPFORMAT cf ) const; + sal_Bool SAL_CALL isTextFormat( CLIPFORMAT cf ) const; + +private: + rtl::OUString SAL_CALL getTextCharsetFromLCID( LCID lcid, CLIPFORMAT aClipformat ) const; + +private: + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > m_SrvMgr; + com::sun::star::uno::Reference< com::sun::star::datatransfer::XDataFormatTranslator > m_XDataFormatTranslator; +}; + +#endif diff --git a/dtrans/source/win32/dtobj/DtObjFactory.cxx b/dtrans/source/win32/dtobj/DtObjFactory.cxx new file mode 100644 index 000000000000..e6cadec92983 --- /dev/null +++ b/dtrans/source/win32/dtobj/DtObjFactory.cxx @@ -0,0 +1,74 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_dtrans.hxx" + +//------------------------------------------------------------------------ +// includes +//------------------------------------------------------------------------ +#include "..\..\inc\DtObjFactory.hxx" + +#ifndef _TWRAPPERDATAOBJECT_HXX_ +#include "XTDataObject.hxx" +#endif + +#ifndef _DOWRAPPERTRANSFERABLE_HXX_ +#include "DOTransferable.hxx" +#endif + +//------------------------------------------------------------------------ +// namespace directives +//------------------------------------------------------------------------ + +using namespace com::sun::star::uno; +using namespace com::sun::star::datatransfer; +using namespace com::sun::star::lang; + +//------------------------------------------------------------------------ +// implementation +//------------------------------------------------------------------------ + +IDataObjectPtr SAL_CALL CDTransObjFactory::createDataObjFromTransferable(const Reference<XMultiServiceFactory>& aServiceManager, + const Reference< XTransferable >& refXTransferable) +{ + return (IDataObjectPtr(new CXTDataObject(aServiceManager, refXTransferable))); +} + +Reference< XTransferable > SAL_CALL CDTransObjFactory::createTransferableFromDataObj( const Reference< XMultiServiceFactory >& aServiceManager, + IDataObjectPtr pIDataObject ) +{ + CDOTransferable* pTransf = new CDOTransferable(aServiceManager, pIDataObject); + Reference<XTransferable> refDOTransf(pTransf); + + pTransf->acquire(); + pTransf->initFlavorList(); + pTransf->release(); + + return refDOTransf; +} + diff --git a/dtrans/source/win32/dtobj/Fetc.cxx b/dtrans/source/win32/dtobj/Fetc.cxx new file mode 100644 index 000000000000..525bfd58be4d --- /dev/null +++ b/dtrans/source/win32/dtobj/Fetc.cxx @@ -0,0 +1,259 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_dtrans.hxx" + +//------------------------------------------------------------------------ +// includes +//------------------------------------------------------------------------ +#include <osl/diagnose.h> +#include "Fetc.hxx" +#include "..\misc\ImplHelper.hxx" + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +CFormatEtc::CFormatEtc( ) +{ + m_FormatEtc.cfFormat = 0; + m_FormatEtc.ptd = NULL; + m_FormatEtc.dwAspect = 0; + m_FormatEtc.lindex = -1; + m_FormatEtc.tymed = TYMED_NULL; +} + +//------------------------------------------------------------------------ +// transfer of ownership +//------------------------------------------------------------------------ + +CFormatEtc::CFormatEtc( const FORMATETC& aFormatEtc ) +{ + CopyFormatEtc( &m_FormatEtc, &const_cast< FORMATETC& >( aFormatEtc ) ); +} + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +CFormatEtc::~CFormatEtc( ) +{ + DeleteTargetDevice( m_FormatEtc.ptd ); +} + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +CFormatEtc::CFormatEtc( CLIPFORMAT cf, DWORD tymed, DVTARGETDEVICE* ptd, DWORD dwAspect, LONG lindex ) +{ + m_FormatEtc.cfFormat = cf; + m_FormatEtc.ptd = CopyTargetDevice( ptd ); + m_FormatEtc.dwAspect = dwAspect; + m_FormatEtc.lindex = lindex; + m_FormatEtc.tymed = tymed; +} + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +CFormatEtc::CFormatEtc( const CFormatEtc& theOther ) +{ + m_FormatEtc.cfFormat = theOther.m_FormatEtc.cfFormat; + m_FormatEtc.ptd = CopyTargetDevice( theOther.m_FormatEtc.ptd ); + m_FormatEtc.dwAspect = theOther.m_FormatEtc.dwAspect; + m_FormatEtc.lindex = theOther.m_FormatEtc.lindex; + m_FormatEtc.tymed = theOther.m_FormatEtc.tymed; +} + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +CFormatEtc& CFormatEtc::operator=( const CFormatEtc& theOther ) +{ + if ( this != &theOther ) + { + DeleteTargetDevice( m_FormatEtc.ptd ); + + m_FormatEtc.cfFormat = theOther.m_FormatEtc.cfFormat; + m_FormatEtc.ptd = CopyTargetDevice( theOther.m_FormatEtc.ptd ); + m_FormatEtc.dwAspect = theOther.m_FormatEtc.dwAspect; + m_FormatEtc.lindex = theOther.m_FormatEtc.lindex; + m_FormatEtc.tymed = theOther.m_FormatEtc.tymed; + } + + return *this; +} + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +CFormatEtc::operator FORMATETC*( ) +{ + return &m_FormatEtc; +} + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +CFormatEtc::operator FORMATETC( ) +{ + return m_FormatEtc; +} + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +void CFormatEtc::getFORMATETC( LPFORMATETC lpFormatEtc ) +{ + OSL_ASSERT( lpFormatEtc ); + OSL_ASSERT( !IsBadWritePtr( lpFormatEtc, sizeof( FORMATETC ) ) ); + + CopyFormatEtc( lpFormatEtc, &m_FormatEtc ); +} + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +CLIPFORMAT CFormatEtc::getClipformat( ) const +{ + return m_FormatEtc.cfFormat; +} + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +DWORD CFormatEtc::getTymed( ) const +{ + return m_FormatEtc.tymed; +} + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +void CFormatEtc::getTargetDevice( DVTARGETDEVICE** lpDvTargetDevice ) const +{ + OSL_ASSERT( lpDvTargetDevice ); + OSL_ASSERT( !IsBadWritePtr( lpDvTargetDevice, sizeof( DVTARGETDEVICE ) ) ); + + *lpDvTargetDevice = NULL; + + if ( m_FormatEtc.ptd ) + *lpDvTargetDevice = CopyTargetDevice( m_FormatEtc.ptd ); +} + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +DWORD CFormatEtc::getDvAspect( ) const +{ + return m_FormatEtc.dwAspect; +} + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +LONG CFormatEtc::getLindex( ) const +{ + return m_FormatEtc.lindex; +} + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +void CFormatEtc::setClipformat( CLIPFORMAT cf ) +{ + m_FormatEtc.cfFormat = cf; +} + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +void CFormatEtc::setTymed( DWORD tymed ) +{ + m_FormatEtc.tymed = tymed; +} + +//------------------------------------------------------------------------ +// transfer of ownership! +//------------------------------------------------------------------------ + +void CFormatEtc::setTargetDevice( DVTARGETDEVICE* ptd ) +{ + DeleteTargetDevice( m_FormatEtc.ptd ); + m_FormatEtc.ptd = ptd; +} + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +void CFormatEtc::setDvAspect( DWORD dwAspect ) +{ + m_FormatEtc.dwAspect = dwAspect; +} + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +void CFormatEtc::setLindex( LONG lindex ) +{ + m_FormatEtc.lindex = lindex; +} + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +sal_Int32 operator==( const CFormatEtc& lhs, const CFormatEtc& rhs ) +{ + return CompareFormatEtc( &lhs.m_FormatEtc, &rhs.m_FormatEtc ); +} + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +sal_Int32 operator!=( const CFormatEtc& lhs, const CFormatEtc& rhs ) +{ + return ( ( lhs == rhs ) != 1 ); +} + diff --git a/dtrans/source/win32/dtobj/Fetc.hxx b/dtrans/source/win32/dtobj/Fetc.hxx new file mode 100644 index 000000000000..a0af6dead8c1 --- /dev/null +++ b/dtrans/source/win32/dtobj/Fetc.hxx @@ -0,0 +1,93 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + + +#ifndef _FETC_HXX_ +#define _FETC_HXX_ + +//------------------------------------------------------------------------ +// includes +//------------------------------------------------------------------------ + +#include <sal/types.h> + +#if defined _MSC_VER +#pragma warning(push,1) +#endif +#include <windows.h> +#if defined _MSC_VER +#pragma warning(pop) +#endif + +/********************************************************************** + stl container elements must fulfill the following requirements: + 1. they need a copy ctor and assignement operator(?) + 2. they must be compareable + because the FORMATETC structure has a pointer to a TARGETDEVICE + structure we need a simple wrapper class to fulfill these needs +***********************************************************************/ + +class CFormatEtc +{ +public: + CFormatEtc( ); + CFormatEtc( const FORMATETC& aFormatEtc ); + CFormatEtc( CLIPFORMAT cf, DWORD tymed = TYMED_HGLOBAL, DVTARGETDEVICE* ptd = NULL, DWORD dwAspect = DVASPECT_CONTENT, LONG lindex = -1 ); + CFormatEtc( const CFormatEtc& theOther ); + + ~CFormatEtc( ); + + CFormatEtc& operator=( const CFormatEtc& theOther ); + operator FORMATETC*( ); + operator FORMATETC( ); + + void getFORMATETC( LPFORMATETC lpFormatEtc ); + + CLIPFORMAT getClipformat( ) const; + DWORD getTymed( ) const; + void getTargetDevice( DVTARGETDEVICE** ptd ) const; + DWORD getDvAspect( ) const; + LONG getLindex( ) const; + + void setClipformat( CLIPFORMAT cf ); + void setTymed( DWORD tymed ); + void setTargetDevice( DVTARGETDEVICE* ptd ); + void setDvAspect( DWORD dwAspect ); + void setLindex( LONG lindex ); + +private: + FORMATETC m_FormatEtc; + + friend sal_Int32 operator==( const CFormatEtc& lhs, const CFormatEtc& rhs ); + friend sal_Int32 operator!=( const CFormatEtc& lhs, const CFormatEtc& rhs ); +}; + +sal_Int32 operator==( const CFormatEtc& lhs, const CFormatEtc& rhs ); +sal_Int32 operator!=( const CFormatEtc& lhs, const CFormatEtc& rhs ); + + +#endif diff --git a/dtrans/source/win32/dtobj/FetcList.cxx b/dtrans/source/win32/dtobj/FetcList.cxx new file mode 100644 index 000000000000..8deb2296ad80 --- /dev/null +++ b/dtrans/source/win32/dtobj/FetcList.cxx @@ -0,0 +1,480 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_dtrans.hxx" + +//------------------------------------------------------------------------ +// includes +//------------------------------------------------------------------------ +#include <osl/diagnose.h> +#include "FetcList.hxx" +#include "Fetc.hxx" +#include <com/sun/star/datatransfer/XMimeContentTypeFactory.hpp> +#include <com/sun/star/datatransfer/XMimeContentType.hpp> + +#ifndef _DATAFORMATTRANSLATOR_HXX_ +#include "DataFmtTransl.hxx" +#endif +#include "..\misc\ImplHelper.hxx" +#include "..\misc\WinClip.hxx" + +#include <algorithm> + +#include "MimeAttrib.hxx" + +//------------------------------------------------------------------------ +// namespace directives +//------------------------------------------------------------------------ + +using namespace com::sun::star::uno; +using namespace com::sun::star::datatransfer; +using namespace com::sun::star::lang; +using namespace com::sun::star::container; +using namespace rtl; +using namespace std; + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +LCID CFormatRegistrar::m_TxtLocale = 0; +sal_uInt32 CFormatRegistrar::m_TxtCodePage = GetACP( ); + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +CFormatEtcContainer::CFormatEtcContainer( ) +{ + m_EnumIterator = m_FormatMap.begin( ); +} + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +void CFormatEtcContainer::addFormatEtc( const CFormatEtc& fetc ) +{ + m_FormatMap.push_back( CFormatEtc( fetc ) ); +} + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +void SAL_CALL CFormatEtcContainer::removeFormatEtc( const CFormatEtc& fetc ) +{ + FormatEtcMap_t::iterator iter = + find( m_FormatMap.begin(), m_FormatMap.end(), fetc ); + + if ( iter != m_FormatMap.end( ) ) + m_FormatMap.erase( iter ); +} + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +void SAL_CALL CFormatEtcContainer::removeAllFormatEtc( ) +{ + m_FormatMap.clear( ); +} + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +sal_Bool CFormatEtcContainer::hasFormatEtc( const CFormatEtc& fetc ) const +{ + FormatEtcMap_t::const_iterator iter = + find( m_FormatMap.begin(), m_FormatMap.end(), fetc ); + + return ( iter != m_FormatMap.end( ) ); +} + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +sal_Bool CFormatEtcContainer::hasElements( ) const +{ + return ( m_FormatMap.size( ) > 0 ); +} + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +void CFormatEtcContainer::beginEnumFormatEtc( ) +{ + m_EnumIterator = m_FormatMap.begin( ); +} + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +sal_uInt32 SAL_CALL CFormatEtcContainer::nextFormatEtc( LPFORMATETC lpFetc, + sal_uInt32 aNum ) +{ + OSL_ASSERT( lpFetc ); + OSL_ASSERT( !IsBadWritePtr( lpFetc, sizeof( FORMATETC ) * aNum ) ); + + sal_uInt32 nFetched = 0; + + if ( m_EnumIterator != m_FormatMap.end( ) ) + { + for ( sal_uInt32 i = 0; i < aNum; i++, nFetched++, lpFetc++, ++m_EnumIterator ) + CopyFormatEtc( lpFetc, *m_EnumIterator ); + } + + return nFetched; +} + + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +sal_Bool SAL_CALL CFormatEtcContainer::skipFormatEtc( sal_uInt32 aNum ) +{ + FormatEtcMap_t::const_iterator iter_end = m_FormatMap.end( ); + for ( sal_uInt32 i = 0; + (i < aNum) && (m_EnumIterator != iter_end); + i++, ++m_EnumIterator ) + ;/* intentionally left empty */ + + return ( m_EnumIterator != m_FormatMap.end( ) ); +} + + +//######################################################################### + + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +CFormatRegistrar::CFormatRegistrar( const Reference< XMultiServiceFactory >& ServiceManager, + const CDataFormatTranslator& aDataFormatTranslator ) : + m_DataFormatTranslator( aDataFormatTranslator ), + m_bHasSynthesizedLocale( sal_False ), + m_SrvMgr( ServiceManager ) +{ +} + +// ---------------------------------------------------------------------------------------- +// this function converts all DataFlavors of the given FlavorList into +// an appropriate FORMATETC structure, for some formats like unicodetext, +// text and text/html we will offer an accompany format e.g.: +// +// DataFlavor | Registered Clipformat | Registered accompany clipformat +// -------------------------|---------------------------|----------------------------------- +// text/plain;charset=ansi | CF_TEXT | CF_UNICODETEXT +// | | CF_LOCALE (if charset != GetACP() +// | | +// text/plain;charset=oem | CF_OEMTEXT | CF_UNICODETEXT +// | | CF_LOCALE (if charset != GetOEMCP() +// | | +// text/plain;charset=utf-16| CF_UNICODETEXT | CF_TEXT +// | | +// text/html | HTML (Hypertext ...) | HTML Format +// | | +// +// if some tries to register different text formats with different charsets the last +// registered wins and the others are ignored +// ---------------------------------------------------------------------------------------- + +void SAL_CALL CFormatRegistrar::RegisterFormats( + const Reference< XTransferable >& aXTransferable, CFormatEtcContainer& aFormatEtcContainer ) +{ + Sequence< DataFlavor > aFlavorList = aXTransferable->getTransferDataFlavors( ); + sal_Int32 nFlavors = aFlavorList.getLength( ); + sal_Bool bUnicodeRegistered = sal_False; + DataFlavor aFlavor; + + for( sal_Int32 i = 0; i < nFlavors; i++ ) + { + aFlavor = aFlavorList[i]; + CFormatEtc fetc = m_DataFormatTranslator.getFormatEtcFromDataFlavor( aFlavor ); + + // maybe an internal format so we ignore it + if ( CF_INVALID == fetc.getClipformat( ) ) + continue; + + if ( !needsToSynthesizeAccompanyFormats( fetc ) ) + aFormatEtcContainer.addFormatEtc( fetc ); + else + { + // if we haven't registered any text format up to now + if ( m_DataFormatTranslator.isTextFormat( fetc.getClipformat() ) && !bUnicodeRegistered ) + { + // if the transferable supports unicode text we ignore + // any further text format the transferable offers + // because we can create it from Unicode text in addition + // we register CF_TEXT for non unicode clients + if ( m_DataFormatTranslator.isUnicodeTextFormat( fetc.getClipformat() ) ) + { + aFormatEtcContainer.addFormatEtc( fetc ); // add CF_UNICODE + aFormatEtcContainer.addFormatEtc( + m_DataFormatTranslator.getFormatEtcForClipformat( CF_TEXT ) ); // add CF_TEXT + bUnicodeRegistered = sal_True; + } + else if ( !hasUnicodeFlavor( aXTransferable ) ) + { + // we try to investigate the charset and make a valid + // windows codepage from this charset the default + // return value is the result of GetACP( ) + OUString charset = getCharsetFromDataFlavor( aFlavor ); + sal_uInt32 txtCP = getWinCPFromMimeCharset( charset ); + + // we try to get a Locale appropriate for this codepage + if ( findLocaleForTextCodePage( ) ) + { + m_TxtCodePage = txtCP; + + aFormatEtcContainer.addFormatEtc( + m_DataFormatTranslator.getFormatEtcForClipformat( CF_UNICODETEXT ) ); + + if ( !IsOEMCP( m_TxtCodePage ) ) + aFormatEtcContainer.addFormatEtc( + m_DataFormatTranslator.getFormatEtcForClipformat( CF_TEXT ) ); + else + aFormatEtcContainer.addFormatEtc( + m_DataFormatTranslator.getFormatEtcForClipformat( CF_OEMTEXT ) ); + + aFormatEtcContainer.addFormatEtc( + m_DataFormatTranslator.getFormatEtcForClipformat( CF_LOCALE ) ); + + // we save the flavor so it's easier when + // queried for it in XTDataObject::GetData(...) + m_RegisteredTextFlavor = aFlavor; + m_bHasSynthesizedLocale = sal_True; + } + } + } + else if ( m_DataFormatTranslator.isTextHtmlFormat( fetc.getClipformat( ) ) ) // Html (Hyper Text...) + { + // we add text/html ( HTML (HyperText Markup Language) ) + aFormatEtcContainer.addFormatEtc( fetc ); + + // and HTML Format + OUString htmlFormat( OUString::createFromAscii( "HTML Format" ) ); + aFormatEtcContainer.addFormatEtc( + m_DataFormatTranslator.getFormatEtcForClipformatName( htmlFormat ) ); + } + } + } +} + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +sal_Bool SAL_CALL CFormatRegistrar::hasSynthesizedLocale( ) const +{ + return m_bHasSynthesizedLocale; +} + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +LCID SAL_CALL CFormatRegistrar::getSynthesizedLocale( ) const +{ + return m_TxtLocale; +} + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +sal_uInt32 SAL_CALL CFormatRegistrar::getRegisteredTextCodePage( ) const +{ + return m_TxtCodePage; +} + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +DataFlavor SAL_CALL CFormatRegistrar::getRegisteredTextFlavor( ) const +{ + return m_RegisteredTextFlavor; +} + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +sal_Bool SAL_CALL CFormatRegistrar::isSynthesizeableFormat( const CFormatEtc& aFormatEtc ) const +{ + return ( m_DataFormatTranslator.isOemOrAnsiTextFormat( aFormatEtc.getClipformat() ) || + m_DataFormatTranslator.isUnicodeTextFormat( aFormatEtc.getClipformat() ) || + m_DataFormatTranslator.isHTMLFormat( aFormatEtc.getClipformat() ) ); +} + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +inline +sal_Bool SAL_CALL CFormatRegistrar::needsToSynthesizeAccompanyFormats( const CFormatEtc& aFormatEtc ) const +{ + return ( m_DataFormatTranslator.isOemOrAnsiTextFormat( aFormatEtc.getClipformat() ) || + m_DataFormatTranslator.isUnicodeTextFormat( aFormatEtc.getClipformat() ) || + m_DataFormatTranslator.isTextHtmlFormat( aFormatEtc.getClipformat( ) ) ); +} + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +OUString SAL_CALL CFormatRegistrar::getCharsetFromDataFlavor( const DataFlavor& aFlavor ) +{ + OUString charset; + + try + { + Reference< XMimeContentTypeFactory > xMimeFac( + m_SrvMgr->createInstance( OUString::createFromAscii( \ + "com.sun.star.datatransfer.MimeContentTypeFactory" ) ), UNO_QUERY ); + + if( xMimeFac.is( ) ) + { + Reference< XMimeContentType > xMimeType( xMimeFac->createMimeContentType( aFlavor.MimeType ) ); + if ( xMimeType->hasParameter( TEXTPLAIN_PARAM_CHARSET ) ) + charset = xMimeType->getParameterValue( TEXTPLAIN_PARAM_CHARSET ); + else + charset = getMimeCharsetFromWinCP( GetACP( ), PRE_WINDOWS_CODEPAGE ); + } + } + catch(NoSuchElementException&) + { + OSL_ENSURE( sal_False, "Unexpected" ); + } + catch(...) + { + OSL_ENSURE( sal_False, "Invalid data flavor" ); + } + + return charset; +} + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +sal_Bool SAL_CALL CFormatRegistrar::hasUnicodeFlavor( const Reference< XTransferable >& aXTransferable ) const +{ + CFormatEtc fetc( CF_UNICODETEXT ); + + DataFlavor aFlavor = + m_DataFormatTranslator.getDataFlavorFromFormatEtc( fetc ); + + return aXTransferable->isDataFlavorSupported( aFlavor ); +} + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +inline +sal_Bool CFormatRegistrar::isEqualCurrentSystemCodePage( sal_uInt32 aCodePage ) const +{ + return ( (aCodePage == GetOEMCP()) || (aCodePage == GetACP()) ); +} + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +sal_Bool SAL_CALL CFormatRegistrar::findLocaleForTextCodePage( ) +{ + m_TxtLocale = 0; + EnumSystemLocalesA( CFormatRegistrar::EnumLocalesProc, LCID_INSTALLED ); + return ( IsValidLocale( m_TxtLocale, LCID_INSTALLED ) ) ? sal_True : sal_False; +} + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +sal_Bool SAL_CALL CFormatRegistrar::isLocaleCodePage( LCID lcid, LCTYPE lctype, sal_uInt32 codepage ) +{ + char buff[6]; + sal_uInt32 localeCodePage; + + OSL_ASSERT( IsValidLocale( lcid, LCID_INSTALLED ) ); + + // get the ansi codepage of the current locale + GetLocaleInfoA( lcid, lctype, buff, sizeof( buff ) ); + localeCodePage = atol( buff ); + + return ( localeCodePage == codepage ); +} + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +inline +sal_Bool SAL_CALL CFormatRegistrar::isLocaleOemCodePage( LCID lcid, sal_uInt32 codepage ) +{ + return isLocaleCodePage( lcid, LOCALE_IDEFAULTCODEPAGE, codepage ); +} + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +inline +sal_Bool SAL_CALL CFormatRegistrar::isLocaleAnsiCodePage( LCID lcid, sal_uInt32 codepage ) +{ + return isLocaleCodePage( lcid, LOCALE_IDEFAULTANSICODEPAGE, codepage ); +} + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +BOOL CALLBACK CFormatRegistrar::EnumLocalesProc( LPSTR lpLocaleStr ) +{ + // the lpLocaleStr parametere is hexadecimal + LCID lcid = strtol( lpLocaleStr, NULL, 16 ); + + if ( isLocaleAnsiCodePage( lcid, CFormatRegistrar::m_TxtCodePage ) || + isLocaleOemCodePage( lcid, CFormatRegistrar::m_TxtCodePage ) ) + { + CFormatRegistrar::m_TxtLocale = lcid; + return sal_False; // stop enumerating + } + + return sal_True; +} + diff --git a/dtrans/source/win32/dtobj/FetcList.hxx b/dtrans/source/win32/dtobj/FetcList.hxx new file mode 100644 index 000000000000..c5105a8662b6 --- /dev/null +++ b/dtrans/source/win32/dtobj/FetcList.hxx @@ -0,0 +1,156 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + + +#ifndef _FETCLIST_HXX_ +#define _FETCLIST_HXX_ + +//------------------------------------------------------------------------ +// includes +//------------------------------------------------------------------------ + +#include <sal/types.h> +#include <cppuhelper/servicefactory.hxx> +#include <com/sun/star/datatransfer/XTransferable.hpp> +#include "Fetc.hxx" + +#if defined _MSC_VER +#pragma warning(push,1) +#endif +#include <windows.h> +#if defined _MSC_VER +#pragma warning(pop) +#endif +#include <vector> + +/***************************************************************** + a simple container for FORMATECT structures + instances of this class are not thread-safe +*****************************************************************/ + +class CFormatEtcContainer +{ +public: + CFormatEtcContainer( ); + + // duplicates not allowed + void SAL_CALL addFormatEtc( const CFormatEtc& fetc ); + + // removes the specified formatetc + void SAL_CALL removeFormatEtc( const CFormatEtc& fetc ); + + // removes the formatetc at pos + void SAL_CALL removeAllFormatEtc( ); + + sal_Bool SAL_CALL hasFormatEtc( const CFormatEtc& fetc ) const; + + sal_Bool SAL_CALL hasElements( ) const; + + // begin enumeration + void SAL_CALL beginEnumFormatEtc( ); + + // copies the specified number of formatetc structures starting + // at the current enum position + // the return value is the number of copied elements; if the + // current enum position is at the end the return value is 0 + sal_uInt32 SAL_CALL nextFormatEtc( LPFORMATETC lpFetc, sal_uInt32 aNum = 1 ); + + // skips the specified number of elements in the container + sal_Bool SAL_CALL skipFormatEtc( sal_uInt32 aNum ); + +protected: + typedef std::vector< CFormatEtc > FormatEtcMap_t; + +private: + FormatEtcMap_t m_FormatMap; + FormatEtcMap_t::iterator m_EnumIterator; +}; + +/***************************************************************** + a helper class which converts data flavors to clipformats, + creates an appropriate formatetc structures and if possible + synthesizes clipboard formats if necessary, e.g. if text + is provided a locale will also be provided; + the class registers the formatetc within a CFormatEtcContainer + + instances of this class are not thread-safe and multiple + instances of this class would use the same static variables + that's why this class should not be used by multiple threads, + only one thread of a process should use it +*****************************************************************/ + +// forward +class CDataFormatTranslator; + +class CFormatRegistrar +{ +public: + CFormatRegistrar( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& ServiceManager, + const CDataFormatTranslator& aDataFormatTranslator ); + + void SAL_CALL RegisterFormats( const com::sun::star::uno::Reference< com::sun::star::datatransfer::XTransferable >& aXTransferable, + CFormatEtcContainer& aFormatEtcContainer ); + + sal_Bool SAL_CALL hasSynthesizedLocale( ) const; + LCID SAL_CALL getSynthesizedLocale( ) const; + sal_uInt32 SAL_CALL getRegisteredTextCodePage( ) const; + com::sun::star::datatransfer::DataFlavor SAL_CALL getRegisteredTextFlavor( ) const; + + sal_Bool SAL_CALL isSynthesizeableFormat( const CFormatEtc& aFormatEtc ) const; + sal_Bool SAL_CALL needsToSynthesizeAccompanyFormats( const CFormatEtc& aFormatEtc ) const; + +private: + sal_Bool SAL_CALL isEqualCurrentSystemCodePage( sal_uInt32 aCodePage ) const; + rtl::OUString SAL_CALL getCharsetFromDataFlavor( const com::sun::star::datatransfer::DataFlavor& aFlavor ); + + sal_Bool SAL_CALL hasUnicodeFlavor( + const com::sun::star::uno::Reference< com::sun::star::datatransfer::XTransferable >& aXTransferable ) const; + + sal_Bool SAL_CALL findLocaleForTextCodePage( ); + + static sal_Bool SAL_CALL isLocaleOemCodePage( LCID lcid, sal_uInt32 codepage ); + static sal_Bool SAL_CALL isLocaleAnsiCodePage( LCID lcid, sal_uInt32 codepage ); + static sal_Bool SAL_CALL isLocaleCodePage( LCID lcid, LCTYPE lctype, sal_uInt32 codepage ); + + static BOOL CALLBACK EnumLocalesProc( LPSTR lpLocaleStr ); + +private: + const CDataFormatTranslator& m_DataFormatTranslator; + sal_Bool m_bHasSynthesizedLocale; + com::sun::star::datatransfer::DataFlavor m_RegisteredTextFlavor; + + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > m_SrvMgr; + + static LCID m_TxtLocale; + static sal_uInt32 m_TxtCodePage; + +private: + CFormatRegistrar( const CFormatRegistrar& ); + CFormatRegistrar& operator=( const CFormatRegistrar& ); +}; + +#endif diff --git a/dtrans/source/win32/dtobj/FmtFilter.cxx b/dtrans/source/win32/dtobj/FmtFilter.cxx new file mode 100644 index 000000000000..c8a8743647a9 --- /dev/null +++ b/dtrans/source/win32/dtobj/FmtFilter.cxx @@ -0,0 +1,536 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_dtrans.hxx" +#include "FmtFilter.hxx" +#include <osl/diagnose.h> +#include <comphelper/sequence.hxx> + +#if defined _MSC_VER +#pragma warning(push,1) +#pragma warning(disable:4917) +#endif +#include <Shobjidl.h> +#include <shlguid.h> +#include <ObjIdl.h> +#include <shellapi.h> +#if defined _MSC_VER +#pragma warning(pop) +#endif + +#include <string> +#include <sstream> +#include <vector> +#include <iomanip> + +#include <systools/win32/comtools.hxx> + +using namespace com::sun::star::uno; +using rtl::OString; + +#pragma pack(2) +struct METAFILEHEADER +{ + DWORD key; + short hmf; + SMALL_RECT bbox; + WORD inch; + DWORD reserved; + WORD checksum; +}; +#pragma pack() + +//------------------------------------------------------------------------ +// convert a windows metafile picture to a openoffice metafile picture +//------------------------------------------------------------------------ + +Sequence< sal_Int8 > SAL_CALL WinMFPictToOOMFPict( Sequence< sal_Int8 >& aMetaFilePict ) +{ + OSL_ASSERT( aMetaFilePict.getLength( ) == sizeof( METAFILEPICT ) ); + + Sequence< sal_Int8 > mfpictStream; + METAFILEPICT* pMFPict = reinterpret_cast< METAFILEPICT* >( aMetaFilePict.getArray( ) ); + HMETAFILE hMf = pMFPict->hMF; + sal_uInt32 nCount = GetMetaFileBitsEx( hMf, 0, NULL ); + + if ( nCount > 0 ) + { + mfpictStream.realloc( nCount + sizeof( METAFILEHEADER ) ); + + METAFILEHEADER* pMFHeader = reinterpret_cast< METAFILEHEADER* >( mfpictStream.getArray( ) ); + SMALL_RECT aRect = { 0, + 0, + static_cast< short >( pMFPict->xExt ), + static_cast< short >( pMFPict->yExt ) }; + USHORT nInch; + + switch( pMFPict->mm ) + { + case MM_TEXT: + nInch = 72; + break; + + case MM_LOMETRIC: + nInch = 100; + break; + + case MM_HIMETRIC: + nInch = 1000; + break; + + case MM_LOENGLISH: + nInch = 254; + break; + + case MM_HIENGLISH: + case MM_ISOTROPIC: + case MM_ANISOTROPIC: + nInch = 2540; + break; + + case MM_TWIPS: + nInch = 1440; + break; + + default: + nInch = 576; + } + + pMFHeader->key = 0x9AC6CDD7L; + pMFHeader->hmf = 0; + pMFHeader->bbox = aRect; + pMFHeader->inch = nInch; + pMFHeader->reserved = 0; + pMFHeader->checksum = 0; + + char* pMFBuff = reinterpret_cast< char* >( mfpictStream.getArray( ) ); + + nCount = GetMetaFileBitsEx( pMFPict->hMF, nCount, pMFBuff + sizeof( METAFILEHEADER ) ); + OSL_ASSERT( nCount > 0 ); + } + + return mfpictStream; +} + +//------------------------------------------------------------- +// convert a windows enhanced metafile to a openoffice metafile +//------------------------------------------------------------- + +Sequence< sal_Int8 > SAL_CALL WinENHMFPictToOOMFPict( HENHMETAFILE hEnhMetaFile ) +{ + Sequence< sal_Int8 > aRet; + UINT nSize = 0; + + if( hEnhMetaFile && + ( ( nSize = GetEnhMetaFileBits( hEnhMetaFile, 0, NULL ) ) != 0 ) ) + { + aRet.realloc( nSize ); + + if( GetEnhMetaFileBits( hEnhMetaFile, nSize, (sal_uChar*) aRet.getArray() ) != nSize ) + aRet.realloc( 0 ); + } + + return aRet; +} + +//------------------------------------------------------------------------ +// convert a openoffice metafile picture to a windows metafile picture +//------------------------------------------------------------------------ + +HMETAFILEPICT SAL_CALL OOMFPictToWinMFPict( Sequence< sal_Int8 >& aOOMetaFilePict ) +{ + HMETAFILEPICT hPict = NULL; + HMETAFILE hMtf = SetMetaFileBitsEx( aOOMetaFilePict.getLength(), (sal_uChar*) aOOMetaFilePict.getConstArray() ); + + if( hMtf ) + { + METAFILEPICT* pPict = (METAFILEPICT*) GlobalLock( hPict = GlobalAlloc( GHND, sizeof( METAFILEPICT ) ) ); + + pPict->mm = 8; + pPict->xExt = 0; + pPict->yExt = 0; + pPict->hMF = hMtf; + + GlobalUnlock( hPict ); + } + + return hPict; +} + +//----------------------------------------------------------------------------- +// convert a openoffice metafile picture to a windows enhanced metafile picture +//----------------------------------------------------------------------------- + +HENHMETAFILE SAL_CALL OOMFPictToWinENHMFPict( Sequence< sal_Int8 >& aOOMetaFilePict ) +{ + HENHMETAFILE hEnhMtf = SetEnhMetaFileBits( aOOMetaFilePict.getLength(), (sal_uChar*) aOOMetaFilePict.getConstArray() ); + + return hEnhMtf; +} + +//------------------------------------------------------------------------ +// convert a windows device independent bitmap into a openoffice bitmap +//------------------------------------------------------------------------ + +Sequence< sal_Int8 > SAL_CALL WinDIBToOOBMP( const Sequence< sal_Int8 >& aWinDIB ) +{ + OSL_ASSERT( aWinDIB.getLength( ) > sizeof( BITMAPINFOHEADER ) ); + + Sequence< sal_Int8 > ooBmpStream; + + ooBmpStream.realloc( aWinDIB.getLength( ) + sizeof(BITMAPFILEHEADER) ); + + const BITMAPINFOHEADER *pBmpInfoHdr = (const BITMAPINFOHEADER*)aWinDIB.getConstArray(); + BITMAPFILEHEADER *pBmpFileHdr = reinterpret_cast< BITMAPFILEHEADER* >( ooBmpStream.getArray() ); + DWORD nOffset = sizeof( BITMAPFILEHEADER ) + sizeof( BITMAPINFOHEADER ); + + rtl_copyMemory( pBmpFileHdr + 1, pBmpInfoHdr, aWinDIB.getLength( ) ); + + if( pBmpInfoHdr->biBitCount <= 8 ) + nOffset += ( pBmpInfoHdr->biClrUsed ? pBmpInfoHdr->biClrUsed : ( 1 << pBmpInfoHdr->biBitCount ) ) << 2; + else if( ( BI_BITFIELDS == pBmpInfoHdr->biCompression ) && ( ( 16 == pBmpInfoHdr->biBitCount ) || ( 32 == pBmpInfoHdr->biBitCount ) ) ) + nOffset += 12; + + pBmpFileHdr->bfType = 'MB'; + pBmpFileHdr->bfSize = 0; // maybe: nMemSize + sizeof(BITMAPFILEHEADER) + pBmpFileHdr->bfReserved1 = 0; + pBmpFileHdr->bfReserved2 = 0; + pBmpFileHdr->bfOffBits = nOffset; + + return ooBmpStream; +} + +//------------------------------------------------------------------------ +// convert a openoffice bitmap into a windows device independent bitmap +//------------------------------------------------------------------------ + +Sequence< sal_Int8 > SAL_CALL OOBmpToWinDIB( Sequence< sal_Int8 >& aOOBmp ) +{ + OSL_ASSERT( aOOBmp.getLength( ) > + ( sizeof( BITMAPFILEHEADER ) + sizeof( BITMAPINFOHEADER ) ) ); + + Sequence< sal_Int8 > winDIBStream( aOOBmp.getLength( ) - sizeof( BITMAPFILEHEADER ) ); + + rtl_copyMemory( winDIBStream.getArray( ), + aOOBmp.getArray( ) + sizeof( BITMAPFILEHEADER ), + aOOBmp.getLength( ) - sizeof( BITMAPFILEHEADER ) ); + + return winDIBStream; +} + +//------------------------------------------------------------------------------ +// converts the openoffice text/html clipboard format to the HTML Format +// well known under MS Windows +// the MS HTML Format has a header before the real html data +// +// Version:1.0 Version number of the clipboard. Staring is 0.9 +// StartHTML: Byte count from the beginning of the clipboard to the start +// of the context, or -1 if no context +// EndHTML: Byte count from the beginning of the clipboard to the end +// of the context, or -1 if no context +// StartFragment: Byte count from the beginning of the clipboard to the +// start of the fragment +// EndFragment: Byte count from the beginning of the clipboard to the +// end of the fragment +// StartSelection: Byte count from the beginning of the clipboard to the +// start of the selection +// EndSelection: Byte count from the beginning of the clipboard to the +// end of the selection +// +// StartSelection and EndSelection are optional +// The fragment should be preceded and followed by the HTML comments +// <!--StartFragment--> and <!--EndFragment--> (no space between !-- and the +// text +//------------------------------------------------------------------------------ +/* +Sequence< sal_Int8 > SAL_CALL TextHtmlToHTMLFormat( Sequence< sal_Int8 >& aTextHtml ) +{ + OSL_ASSERT( aTextHtml.getLength( ) > 0 ); + + // check parameter + if ( !(aTextHtml.getLength( ) > 0) ) + return Sequence< sal_Int8 >( ); + + // we create a buffer with the approximated size of + // the HTML Format header + char aHTMLFmtHdr[120]; + + rtl_zeroMemory( aHTMLFmtHdr, sizeof( aHTMLFmtHdr ) ); + + // fill the buffer with dummy values to calc the + // exact length + + wsprintf( + aHTMLFmtHdr, + "Version:1.0\nStartHTML:%010d\r\nnEndHTML:%010d\r\nStartFragment:%010\r\nnEndFragment:%010d\r\n", 0, 0, 0, 0 ); + + sal_uInt32 lHTMLFmtHdr = rtl_str_getLength( aHTMLFmtHdr ); + + // the office allways writes the start + // and end html tag in upper cases and + // without spaces + // both tags don't allow parameters + OString startHtmlTag( "<HTML>" ); + OString endHtmlTag( "</HTML>" ); + + // we don't include '>' into the search + // because the body tag allows parameters + // e.g. <BODY param> + // #92840# + OString startBodyTag( "<BODY" ); + OString endBodyTag( "</BODY" ); + + OString textHtml( + reinterpret_cast< const sal_Char* >( aTextHtml.getConstArray( ) ), + aTextHtml.getLength( ) ); + + sal_Int32 nStartHtml = textHtml.indexOf( startHtmlTag ); + sal_Int32 nEndHtml = textHtml.indexOf( endHtmlTag ); + sal_Int32 nStartFrgmt = textHtml.indexOf( startBodyTag ); + sal_Int32 nEndFrgmt = textHtml.indexOf( endBodyTag ); + + OSL_ASSERT( (nStartHtml >= 0) && (nEndHtml > nStartHtml) && (nStartFrgmt > nStartHtml) && (nEndFrgmt > nStartFrgmt) ); + + Sequence< sal_Int8 > aHTMLFmtSequence; + + if ( (nStartHtml > -1) && (nEndHtml > -1) && (nStartFrgmt > -1) && (nEndFrgmt > -1) ) + { + nStartHtml = nStartHtml + lHTMLFmtHdr - 1; // we start one before <HTML> Word 2000 does also so + nEndHtml = nEndHtml + lHTMLFmtHdr + endHtmlTag.getLength( ) + 1; // our SOffice 5.2 wants 2 behind </HTML>? + nStartFrgmt = nStartFrgmt + startBodyTag.getLength( ) + lHTMLFmtHdr; // after the <BODY> tag + nEndFrgmt = nEndFrgmt + lHTMLFmtHdr; + + // fill the html header + rtl_zeroMemory( aHTMLFmtHdr, sizeof( aHTMLFmtHdr ) ); + + wsprintf( + aHTMLFmtHdr, + "Version:1.0\nStartHTML:%010d\r\nEndHTML:%010d\r\nStartFragment:%010d\r\nEndFragment:%010d\r\n", + nStartHtml, nEndHtml, nStartFrgmt, nEndFrgmt ); + + // we add space for a trailing \0 + aHTMLFmtSequence.realloc( lHTMLFmtHdr + aTextHtml.getLength( ) + 1 ); + rtl_zeroMemory( aHTMLFmtSequence.getArray( ), aHTMLFmtSequence.getLength( ) ); + + // copy the HTML Format header + rtl_copyMemory( + static_cast< LPVOID >( aHTMLFmtSequence.getArray( ) ), + static_cast< LPVOID >( aHTMLFmtHdr ), lHTMLFmtHdr ); + + // concat the text/html + rtl_copyMemory( + static_cast< LPVOID >( aHTMLFmtSequence.getArray( ) + lHTMLFmtHdr ), + static_cast< LPVOID >( aTextHtml.getArray( ) ), + aTextHtml.getLength( ) ); + } + + return aHTMLFmtSequence; +} +*/ + +std::string GetHtmlFormatHeader(size_t startHtml, size_t endHtml, size_t startFragment, size_t endFragment) +{ + std::ostringstream htmlHeader; + htmlHeader << "Version:1.0" << '\r' << '\n'; + htmlHeader << "StartHTML:" << std::setw(10) << std::setfill('0') << std::dec << startHtml << '\r' << '\n'; + htmlHeader << "EndHTML:" << std::setw(10) << std::setfill('0') << std::dec << endHtml << '\r' << '\n'; + htmlHeader << "StartFragment:" << std::setw(10) << std::setfill('0') << std::dec << startFragment << '\r' << '\n'; + htmlHeader << "EndFragment:" << std::setw(10) << std::setfill('0') << std::dec << endFragment << '\r' << '\n'; + return htmlHeader.str(); +} + +// the office allways writes the start and end html tag in upper cases and +// without spaces both tags don't allow parameters +const std::string TAG_HTML = std::string("<HTML>"); +const std::string TAG_END_HTML = std::string("</HTML>"); + +// The body tag may have parameters so we need to search for the +// closing '>' manually e.g. <BODY param> #92840# +const std::string TAG_BODY = std::string("<BODY"); +const std::string TAG_END_BODY = std::string("</BODY"); + +Sequence<sal_Int8> SAL_CALL TextHtmlToHTMLFormat(Sequence<sal_Int8>& aTextHtml) +{ + OSL_ASSERT(aTextHtml.getLength() > 0); + + if (!(aTextHtml.getLength() > 0)) + return Sequence<sal_Int8>(); + + // fill the buffer with dummy values to calc the exact length + std::string dummyHtmlHeader = GetHtmlFormatHeader(0, 0, 0, 0); + size_t lHtmlFormatHeader = dummyHtmlHeader.length(); + + std::string textHtml( + reinterpret_cast<const sal_Char*>(aTextHtml.getConstArray()), + reinterpret_cast<const sal_Char*>(aTextHtml.getConstArray()) + aTextHtml.getLength()); + + std::string::size_type nStartHtml = textHtml.find(TAG_HTML) + lHtmlFormatHeader - 1; // we start one before '<HTML>' Word 2000 does also so + std::string::size_type nEndHtml = textHtml.find(TAG_END_HTML) + lHtmlFormatHeader + TAG_END_HTML.length() + 1; // our SOffice 5.2 wants 2 behind </HTML>? + + // The body tag may have parameters so we need to search for the + // closing '>' manually e.g. <BODY param> #92840# + std::string::size_type nStartFragment = textHtml.find(">", textHtml.find(TAG_BODY)) + lHtmlFormatHeader + 1; + std::string::size_type nEndFragment = textHtml.find(TAG_END_BODY) + lHtmlFormatHeader; + + std::string htmlFormat = GetHtmlFormatHeader(nStartHtml, nEndHtml, nStartFragment, nEndFragment); + htmlFormat += textHtml; + + Sequence<sal_Int8> byteSequence(htmlFormat.length() + 1); // space the trailing '\0' + rtl_zeroMemory(byteSequence.getArray(), byteSequence.getLength()); + + rtl_copyMemory( + static_cast<void*>(byteSequence.getArray()), + static_cast<const void*>(htmlFormat.c_str()), + htmlFormat.length()); + + return byteSequence; +} + +std::wstring getFileExtension(const std::wstring& aFilename) +{ + std::wstring::size_type idx = aFilename.rfind(L"."); + if ((idx != std::wstring::npos)) + { + return std::wstring(aFilename, idx); + } + return std::wstring(); +} + +const std::wstring SHELL_LINK_FILE_EXTENSION = L".lnk"; + +bool isShellLink(const std::wstring& aFilename) +{ + std::wstring ext = getFileExtension(aFilename); + return (_wcsicmp(ext.c_str(), SHELL_LINK_FILE_EXTENSION.c_str()) == 0); +} + +/** Resolve a Windows Shell Link (lnk) file. If a resolution + is not possible simply return the provided name of the + lnk file. */ +std::wstring getShellLinkTarget(const std::wstring& aLnkFile) +{ + OSL_ASSERT(isShellLink(aLnkFile)); + + std::wstring target = aLnkFile; + + try + { + sal::systools::COMReference<IShellLinkA> pIShellLink; + HRESULT hr = CoCreateInstance( + CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, reinterpret_cast<LPVOID*>(&pIShellLink)); + if (FAILED(hr)) + return target; + + sal::systools::COMReference<IPersistFile> pIPersistFile = + pIShellLink.QueryInterface<IPersistFile>(IID_IPersistFile); + + hr = pIPersistFile->Load(aLnkFile.c_str(), STGM_READ); + if (FAILED(hr)) + return target; + + hr = pIShellLink->Resolve(NULL, SLR_UPDATE | SLR_NO_UI); + if (FAILED(hr)) + return target; + + char pathA[MAX_PATH]; + WIN32_FIND_DATA wfd; + hr = pIShellLink->GetPath(pathA, MAX_PATH, &wfd, SLGP_RAWPATH); + if (FAILED(hr)) + return target; + + wchar_t pathW[MAX_PATH]; + MultiByteToWideChar(CP_ACP, 0, pathA, -1, pathW, MAX_PATH); + target = pathW; + } + catch(sal::systools::ComError& ex) + { + OSL_ENSURE(false, ex.what()); + ex = ex; + } + return target; +} + +typedef std::vector<std::wstring> FileList_t; +typedef FileList_t::value_type FileList_ValueType_t; +typedef Sequence<sal_Int8> ByteSequence_t; + +/* Calculate the size required for turning a string list into + a double '\0' terminated string buffer */ +size_t CalcSizeForStringListBuffer(const FileList_t& fileList) +{ + if (fileList.size() == 0) + return 0; + + size_t size = 1; // one for the very final '\0' + FileList_t::const_iterator iter_end = fileList.end(); + for (FileList_t::const_iterator iter = fileList.begin(); iter != iter_end; ++iter) + { + size += iter->length() + 1; // length including terminating '\0' + } + return (size * sizeof(FileList_ValueType_t::value_type)); +} + +ByteSequence_t FileListToByteSequence(const FileList_t& fileList) +{ + ByteSequence_t bseq; + size_t size = CalcSizeForStringListBuffer(fileList); + + if (size > 0) + { + bseq.realloc(size); + wchar_t* p = reinterpret_cast<wchar_t*>(bseq.getArray()); + ZeroMemory(p, size); + + FileList_t::const_iterator iter; + FileList_t::const_iterator iter_end = fileList.end(); + for (iter = fileList.begin(); iter != iter_end; ++iter) + { + wcsncpy(p, iter->c_str(), iter->length()); + p += (iter->length() + 1); + } + } + return bseq; +} + +ByteSequence_t CF_HDROPToFileList(HGLOBAL hGlobal) +{ + UINT nFiles = DragQueryFileW((HDROP)hGlobal, 0xFFFFFFFF, NULL, 0); + FileList_t files; + + for (UINT i = 0; i < nFiles; i++) + { + wchar_t buff[MAX_PATH]; + /*UINT size =*/ DragQueryFileW((HDROP)hGlobal, i, buff, MAX_PATH); + std::wstring filename = buff; + if (isShellLink(filename)) + filename = getShellLinkTarget(filename); + files.push_back(filename); + } + return FileListToByteSequence(files); +} + diff --git a/dtrans/source/win32/dtobj/FmtFilter.hxx b/dtrans/source/win32/dtobj/FmtFilter.hxx new file mode 100644 index 000000000000..3f433561a3b1 --- /dev/null +++ b/dtrans/source/win32/dtobj/FmtFilter.hxx @@ -0,0 +1,90 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + + +#ifndef _FMTFILTER_HXX_ +#define _FMTFILTER_HXX_ + +#include <sal/types.h> + +#ifndef _COM_SUN_STAR_UNO_SEQUENCE_H_ +#include <com/sun/star/uno/Sequence.hxx> +#endif + +#if defined _MSC_VER +#pragma warning(push,1) +#endif +#include <windows.h> +#if defined _MSC_VER +#pragma warning(pop) +#endif + +/*------------------------------------------------------------------------ + input: + aMetaFilePict - a sequence of bytes containing a METAFILEPICT struct +------------------------------------------------------------------------*/ +com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL WinMFPictToOOMFPict( com::sun::star::uno::Sequence< sal_Int8 >& aMetaFilePict ); +com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL WinENHMFPictToOOMFPict( HENHMETAFILE hEnhMetaFile ); + +/*------------------------------------------------------------------------ + input: + aByteStream - a sequence of bytes containing a openoffice metafile + picture with a leading METAFILEHEADER +------------------------------------------------------------------------*/ +HMETAFILEPICT SAL_CALL OOMFPictToWinMFPict( com::sun::star::uno::Sequence< sal_Int8 >& aOOMetaFilePict ); +HENHMETAFILE SAL_CALL OOMFPictToWinENHMFPict( com::sun::star::uno::Sequence< sal_Int8 >& aOOMetaFilePict ); + +/*------------------------------------------------------------------------ + input: + aWinDIB - sequence of bytes containing a windows device independent + bitmap +------------------------------------------------------------------------*/ +com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL WinDIBToOOBMP( const com::sun::star::uno::Sequence< sal_Int8 >& aWinDIB ); + +/*------------------------------------------------------------------------ + input: + aOOBmp - sequence of bytes containing a openoffice bitmap +------------------------------------------------------------------------*/ +com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL OOBmpToWinDIB( com::sun::star::uno::Sequence< sal_Int8 >& aOOBmp ); + +/*------------------------------------------------------------------------ + input: + aTextHtml - a sequence of text/html which will be converted to the + HTML Format; the HTML Format has header before the real html data + the Format is described in the MSDN Library under HTML Clipboard + Format +------------------------------------------------------------------------*/ +com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL TextHtmlToHTMLFormat( com::sun::star::uno::Sequence< sal_Int8 >& aTextHtml ); + +/** + Return a FileList in which Windows Shell Links (lnk) are resolved. + If for what ever reason a resolution is not possible leave the + original lnk file. +*/ +com::sun::star::uno::Sequence< sal_Int8 > CF_HDROPToFileList(HGLOBAL hGlobal); + +#endif diff --git a/dtrans/source/win32/dtobj/MimeAttrib.hxx b/dtrans/source/win32/dtobj/MimeAttrib.hxx new file mode 100644 index 000000000000..7bd631cc79d5 --- /dev/null +++ b/dtrans/source/win32/dtobj/MimeAttrib.hxx @@ -0,0 +1,50 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + + +#ifndef _MIMEATTRIB_HXX_ +#define _MIMEATTRIB_HXX_ + +//------------------------------------------------------------------------ +// includes +//------------------------------------------------------------------------ + +#include <rtl/ustring.hxx> + +//------------------------------------------------------------------------ +// deklarations +//------------------------------------------------------------------------ + +const rtl::OUString TEXTPLAIN_PARAM_CHARSET = rtl::OUString::createFromAscii( "charset" ); + +const rtl::OUString PRE_WINDOWS_CODEPAGE = rtl::OUString::createFromAscii( "windows" ); +const rtl::OUString PRE_OEM_CODEPAGE = rtl::OUString::createFromAscii( "cp" ); +const rtl::OUString CHARSET_UTF16 = rtl::OUString::createFromAscii( "utf-16" ); +const rtl::OUString CHARSET_UNICODE = rtl::OUString::createFromAscii( "unicode" ); + + +#endif diff --git a/dtrans/source/win32/dtobj/TxtCnvtHlp.cxx b/dtrans/source/win32/dtobj/TxtCnvtHlp.cxx new file mode 100644 index 000000000000..3eecad271567 --- /dev/null +++ b/dtrans/source/win32/dtobj/TxtCnvtHlp.cxx @@ -0,0 +1,145 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_dtrans.hxx" + +//------------------------------------------------------------------------ +// includes +//------------------------------------------------------------------------ +#include <osl/diagnose.h> +#include "TxtCnvtHlp.hxx" +#include "DTransHelper.hxx" +#include "..\misc\ImplHelper.hxx" + +using namespace ::com::sun::star::datatransfer; +using namespace ::com::sun::star::uno; + +//------------------------------------------------------------------ +// assuming a '\0' terminated string if no length specified +//------------------------------------------------------------------ + +int CalcBuffSizeForTextConversion( UINT code_page, LPCSTR lpMultiByteString, int nLen = -1 ) +{ + return ( MultiByteToWideChar( code_page, + 0, + lpMultiByteString, + nLen, + NULL, + 0 ) * sizeof( sal_Unicode ) ); +} + +//------------------------------------------------------------------ +// assuming a '\0' terminated string if no length specified +//------------------------------------------------------------------ + +int CalcBuffSizeForTextConversion( UINT code_page, LPCWSTR lpWideCharString, int nLen = -1 ) +{ + return WideCharToMultiByte( code_page, + 0, + lpWideCharString, + nLen, + NULL, + 0, + NULL, + NULL ); +} + +//------------------------------------------------------------------ +// converts text in one code page into unicode text +// automatically calculates the necessary buffer size and allocates +// the buffer +//------------------------------------------------------------------ + +int MultiByteToWideCharEx( UINT cp_src, + LPCSTR lpMultiByteString, + sal_uInt32 lenStr, + CStgTransferHelper& refDTransHelper, + BOOL bEnsureTrailingZero ) +{ + OSL_ASSERT( IsValidCodePage( cp_src ) ); + OSL_ASSERT( NULL != lpMultiByteString ); + + // calculate the required buff size + int reqSize = CalcBuffSizeForTextConversion( cp_src, lpMultiByteString, lenStr ); + + if ( bEnsureTrailingZero ) + reqSize += sizeof( sal_Unicode ); + + // initialize the data-transfer helper + refDTransHelper.init( reqSize ); + + // setup a global memory pointer + CRawHGlobalPtr ptrHGlob( refDTransHelper ); + + // do the converssion an return + return MultiByteToWideChar( cp_src, + 0, + lpMultiByteString, + lenStr, + static_cast< LPWSTR >( ptrHGlob.GetMemPtr( ) ), + ptrHGlob.MemSize( ) ); +} + +//------------------------------------------------------------------ +// converts unicode text into text of the specified code page +// automatically calculates the necessary buffer size and allocates +// the buffer +//------------------------------------------------------------------ + +int WideCharToMultiByteEx( UINT cp_dest, + LPCWSTR lpWideCharString, + sal_uInt32 lenStr, + CStgTransferHelper& refDTransHelper, + BOOL bEnsureTrailingZero ) +{ + OSL_ASSERT( IsValidCodePage( cp_dest ) ); + OSL_ASSERT( NULL != lpWideCharString ); + + // calculate the required buff size + int reqSize = CalcBuffSizeForTextConversion( cp_dest, lpWideCharString, lenStr ); + + if ( bEnsureTrailingZero ) + reqSize += sizeof( sal_Int8 ); + + // initialize the data-transfer helper + refDTransHelper.init( reqSize ); + + // setup a global memory pointer + CRawHGlobalPtr ptrHGlob( refDTransHelper ); + + // do the converssion an return + return WideCharToMultiByte( cp_dest, + 0, + lpWideCharString, + lenStr, + static_cast< LPSTR >( ptrHGlob.GetMemPtr( ) ), + ptrHGlob.MemSize( ), + NULL, + NULL ); +} + diff --git a/dtrans/source/win32/dtobj/TxtCnvtHlp.hxx b/dtrans/source/win32/dtobj/TxtCnvtHlp.hxx new file mode 100644 index 000000000000..a4d59a69284e --- /dev/null +++ b/dtrans/source/win32/dtobj/TxtCnvtHlp.hxx @@ -0,0 +1,63 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + + +#ifndef _TXTCNVTHLP_HXX_ +#define _TXTCNVTHLP_HXX_ + +#include <com/sun/star/datatransfer/DataFlavor.hpp> + +#ifndef _COM_SUN_STAR_UNO_SEQUENCE_HPP_ +#include <com/sun/star/uno/Sequence.h> +#endif +#include "DTransHelper.hxx" + +#if defined _MSC_VER +#pragma warning(push,1) +#endif +#include <windows.h> +#if defined _MSC_VER +#pragma warning(pop) +#endif + +//------------------------------------------------------------------------ +// deklarations +//------------------------------------------------------------------------ + +int MultiByteToWideCharEx( UINT cp_src, + LPCSTR lpMultiByteString, + sal_uInt32 lenStr, + CStgTransferHelper& refDTransHelper, + BOOL bEnsureTrailingZero = TRUE ); + +int WideCharToMultiByteEx( UINT cp_dest, + LPCWSTR lpWideCharString, + sal_uInt32 lenStr, + CStgTransferHelper& refDTransHelper, + BOOL bEnsureTrailingZero = TRUE ); + +#endif diff --git a/dtrans/source/win32/dtobj/XNotifyingDataObject.cxx b/dtrans/source/win32/dtobj/XNotifyingDataObject.cxx new file mode 100644 index 000000000000..25e3fab3a702 --- /dev/null +++ b/dtrans/source/win32/dtobj/XNotifyingDataObject.cxx @@ -0,0 +1,163 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_dtrans.hxx" +#include <osl/diagnose.h> +#include "XNotifyingDataObject.hxx" +#include "..\clipb\WinClipbImpl.hxx" +#include "..\clipb\WinClipboard.hxx" +#include "..\..\inc\DtObjFactory.hxx" + +#ifdef __MINGW32__ +#define __uuidof(I) IID_##I +#endif + +using namespace com::sun::star::datatransfer; +using namespace com::sun::star::datatransfer::clipboard; +using com::sun::star::uno::RuntimeException; +using com::sun::star::uno::Reference; + + +CXNotifyingDataObject::CXNotifyingDataObject( + const IDataObjectPtr& aIDataObject, + const Reference< XTransferable >& aXTransferable, + const Reference< XClipboardOwner >& aXClipOwner, + CWinClipbImpl* theWinClipImpl ) : + m_nRefCnt( 0 ), + m_aIDataObject( aIDataObject ), + m_XTransferable( aXTransferable ), + m_XClipboardOwner( aXClipOwner ), + m_pWinClipImpl( theWinClipImpl ) +{ +} + +STDMETHODIMP CXNotifyingDataObject::QueryInterface( REFIID iid, LPVOID* ppvObject ) +{ + if ( NULL == ppvObject ) + return E_INVALIDARG; + + HRESULT hr = E_NOINTERFACE; + + *ppvObject = NULL; + if ( ( __uuidof( IUnknown ) == iid ) || + ( __uuidof( IDataObject ) == iid ) ) + { + *ppvObject = static_cast< IUnknown* >( this ); + ( (LPUNKNOWN)*ppvObject )->AddRef( ); + hr = S_OK; + } + + return hr; +} + +STDMETHODIMP_(ULONG) CXNotifyingDataObject::AddRef( ) +{ + return static_cast< ULONG >( InterlockedIncrement( &m_nRefCnt ) ); +} + +STDMETHODIMP_(ULONG) CXNotifyingDataObject::Release( ) +{ + ULONG nRefCnt = + static_cast< ULONG >( InterlockedDecrement( &m_nRefCnt ) ); + + if ( 0 == nRefCnt ) + { + if ( m_pWinClipImpl ) + m_pWinClipImpl->onReleaseDataObject( this ); + + delete this; + } + + return nRefCnt; +} + +STDMETHODIMP CXNotifyingDataObject::GetData( LPFORMATETC pFormatetc, LPSTGMEDIUM pmedium ) +{ + return m_aIDataObject->GetData(pFormatetc, pmedium); +} + +STDMETHODIMP CXNotifyingDataObject::EnumFormatEtc( + DWORD dwDirection, IEnumFORMATETC** ppenumFormatetc ) +{ + return m_aIDataObject->EnumFormatEtc(dwDirection, ppenumFormatetc); +} + +STDMETHODIMP CXNotifyingDataObject::QueryGetData( LPFORMATETC pFormatetc ) +{ + return m_aIDataObject->QueryGetData(pFormatetc); +} + +STDMETHODIMP CXNotifyingDataObject::GetDataHere( LPFORMATETC lpFetc, LPSTGMEDIUM lpStgMedium ) +{ + return m_aIDataObject->GetDataHere(lpFetc, lpStgMedium); +} + +STDMETHODIMP CXNotifyingDataObject::GetCanonicalFormatEtc( LPFORMATETC lpFetc, LPFORMATETC lpCanonicalFetc ) +{ + return m_aIDataObject->GetCanonicalFormatEtc(lpFetc, lpCanonicalFetc); +} + +STDMETHODIMP CXNotifyingDataObject::SetData( LPFORMATETC lpFetc, LPSTGMEDIUM lpStgMedium, BOOL bRelease ) +{ + return m_aIDataObject->SetData( lpFetc, lpStgMedium, bRelease ); +} + +STDMETHODIMP CXNotifyingDataObject::DAdvise( + LPFORMATETC lpFetc, DWORD advf, LPADVISESINK lpAdvSink, DWORD* pdwConnection ) +{ + return m_aIDataObject->DAdvise( lpFetc, advf, lpAdvSink, pdwConnection ); +} + +STDMETHODIMP CXNotifyingDataObject::DUnadvise( DWORD dwConnection ) +{ + return m_aIDataObject->DUnadvise( dwConnection ); +} + +STDMETHODIMP CXNotifyingDataObject::EnumDAdvise( LPENUMSTATDATA * ppenumAdvise ) +{ + return m_aIDataObject->EnumDAdvise( ppenumAdvise ); +} + +CXNotifyingDataObject::operator IDataObject*( ) +{ + return static_cast< IDataObject* >( this ); +} + +void SAL_CALL CXNotifyingDataObject::lostOwnership( ) +{ + try + { + if (m_XClipboardOwner.is()) + m_XClipboardOwner->lostOwnership( + static_cast<XClipboardEx*>(m_pWinClipImpl->m_pWinClipboard ), m_XTransferable); + } + catch(RuntimeException&) + { + OSL_ENSURE( sal_False, "RuntimeException caught" ); + } +} diff --git a/dtrans/source/win32/dtobj/XNotifyingDataObject.hxx b/dtrans/source/win32/dtobj/XNotifyingDataObject.hxx new file mode 100644 index 000000000000..394b835c3612 --- /dev/null +++ b/dtrans/source/win32/dtobj/XNotifyingDataObject.hxx @@ -0,0 +1,105 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + + +#ifndef _XNOTIFYINGDATAOBJECT_HXX_ +#define _XNOTIFYINGDATAOBJECT_HXX_ + + +//------------------------------------------------------------------------ +// includes +//------------------------------------------------------------------------ + +#include <com/sun/star/datatransfer/XTransferable.hpp> +#include <com/sun/star/datatransfer/clipboard/XClipboardOwner.hpp> + +#if defined _MSC_VER +#pragma warning(push,1) +#endif +#include <objidl.h> +#include <windows.h> +#if defined _MSC_VER +#pragma warning(pop) +#endif + +#include <systools/win32/comtools.hxx> + +/*-------------------------------------------------------------------------- + To implement the lostOwnership mechanism cleanly we need this wrapper + object +----------------------------------------------------------------------------*/ + +// forward +class CWinClipbImpl; + +class CXNotifyingDataObject : public IDataObject +{ +public: + CXNotifyingDataObject( + const IDataObjectPtr& aIDataObject, + const com::sun::star::uno::Reference< com::sun::star::datatransfer::XTransferable >& aXTransferable, + const com::sun::star::uno::Reference< com::sun::star::datatransfer::clipboard::XClipboardOwner >& aXClipOwner, + CWinClipbImpl* theWinClipImpl ); + + virtual ~CXNotifyingDataObject() {} + + //----------------------------------------------------------------- + // ole interface implementation + //----------------------------------------------------------------- + + //IUnknown interface methods + STDMETHODIMP QueryInterface(REFIID iid, LPVOID* ppvObject); + STDMETHODIMP_( ULONG ) AddRef( ); + STDMETHODIMP_( ULONG ) Release( ); + + // IDataObject interface methods + STDMETHODIMP GetData( LPFORMATETC pFormatetc, LPSTGMEDIUM pmedium ); + STDMETHODIMP GetDataHere( LPFORMATETC pFormatetc, LPSTGMEDIUM pmedium ); + STDMETHODIMP QueryGetData( LPFORMATETC pFormatetc ); + STDMETHODIMP GetCanonicalFormatEtc( LPFORMATETC pFormatectIn, LPFORMATETC pFormatetcOut ); + STDMETHODIMP SetData( LPFORMATETC pFormatetc, LPSTGMEDIUM pmedium, BOOL fRelease ); + STDMETHODIMP EnumFormatEtc( DWORD dwDirection, IEnumFORMATETC** ppenumFormatetc ); + STDMETHODIMP DAdvise( LPFORMATETC pFormatetc, DWORD advf, LPADVISESINK pAdvSink, DWORD* pdwConnection ); + STDMETHODIMP DUnadvise( DWORD dwConnection ); + STDMETHODIMP EnumDAdvise( LPENUMSTATDATA* ppenumAdvise ); + + operator IDataObject*( ); + +private: + void SAL_CALL lostOwnership( ); + +private: + sal_Int32 m_nRefCnt; + IDataObjectPtr m_aIDataObject; + const com::sun::star::uno::Reference< com::sun::star::datatransfer::XTransferable > m_XTransferable; + const com::sun::star::uno::Reference< com::sun::star::datatransfer::clipboard::XClipboardOwner > m_XClipboardOwner; + CWinClipbImpl* m_pWinClipImpl; + + friend class CWinClipbImpl; +}; + +#endif diff --git a/dtrans/source/win32/dtobj/XTDataObject.cxx b/dtrans/source/win32/dtobj/XTDataObject.cxx new file mode 100644 index 000000000000..e17a931d7380 --- /dev/null +++ b/dtrans/source/win32/dtobj/XTDataObject.cxx @@ -0,0 +1,848 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_dtrans.hxx" + +//------------------------------------------------------------------------ +// includes +//------------------------------------------------------------------------ +#include <osl/diagnose.h> + +#ifndef _TXDATAOBJECT_HXX_ +#include "XTDataObject.hxx" +#endif +#include <com/sun/star/datatransfer/dataflavor.hpp> +#include "..\misc\ImplHelper.hxx" +#include "DTransHelper.hxx" +#include "TxtCnvtHlp.hxx" +#include <com/sun/star/datatransfer/clipboard/XClipboardEx.hpp> +#include "FmtFilter.hxx" + +#if defined _MSC_VER +#pragma warning(push,1) +#pragma warning(disable:4917) +#endif +#include <windows.h> +#include <shlobj.h> +#if defined _MSC_VER +#pragma warning(pop) +#endif + +#ifdef __MINGW32__ +#define __uuidof(I) IID_##I +#endif + +//------------------------------------------------------------------------ +// namespace directives +//------------------------------------------------------------------------ + +using namespace com::sun::star::datatransfer; +using namespace com::sun::star::datatransfer::clipboard; +using namespace com::sun::star::uno; +using namespace com::sun::star::lang; +using namespace rtl; + +//------------------------------------------------------------------------ +// a helper class that will be thrown by the function validateFormatEtc +//------------------------------------------------------------------------ + +class CInvalidFormatEtcException +{ +public: + HRESULT m_hr; + CInvalidFormatEtcException( HRESULT hr ) : m_hr( hr ) {}; +}; + +//------------------------------------------------------------------------ +// ctor +//------------------------------------------------------------------------ + +CXTDataObject::CXTDataObject( const Reference< XMultiServiceFactory >& aServiceManager, + const Reference< XTransferable >& aXTransferable ) : + m_nRefCnt( 0 ), + m_SrvMgr( aServiceManager ), + m_XTransferable( aXTransferable ), + m_DataFormatTranslator( aServiceManager ), + m_bFormatEtcContainerInitialized( sal_False ), + m_FormatRegistrar( m_SrvMgr, m_DataFormatTranslator ) +{ +} + +//------------------------------------------------------------------------ +// IUnknown->QueryInterface +//------------------------------------------------------------------------ + +STDMETHODIMP CXTDataObject::QueryInterface( REFIID iid, LPVOID* ppvObject ) +{ + if ( NULL == ppvObject ) + return E_INVALIDARG; + + HRESULT hr = E_NOINTERFACE; + + *ppvObject = NULL; + if ( ( __uuidof( IUnknown ) == iid ) || + ( __uuidof( IDataObject ) == iid ) ) + { + *ppvObject = static_cast< IUnknown* >( this ); + ( (LPUNKNOWN)*ppvObject )->AddRef( ); + hr = S_OK; + } + + return hr; +} + +//------------------------------------------------------------------------ +// IUnknown->AddRef +//------------------------------------------------------------------------ + +STDMETHODIMP_(ULONG) CXTDataObject::AddRef( ) +{ + return static_cast< ULONG >( InterlockedIncrement( &m_nRefCnt ) ); +} + +//------------------------------------------------------------------------ +// IUnknown->Release +//------------------------------------------------------------------------ + +STDMETHODIMP_(ULONG) CXTDataObject::Release( ) +{ + ULONG nRefCnt = + static_cast< ULONG >( InterlockedDecrement( &m_nRefCnt ) ); + + if ( 0 == nRefCnt ) + delete this; + + return nRefCnt; +} + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +STDMETHODIMP CXTDataObject::GetData( LPFORMATETC pFormatetc, LPSTGMEDIUM pmedium ) +{ + if ( !(pFormatetc && pmedium) ) + return E_INVALIDARG; + + try + { + // prepare data transfer + invalidateStgMedium( *pmedium ); + validateFormatEtc( pFormatetc ); + + // handle locale request, because locale is a artificial format for us + if ( CF_LOCALE == pFormatetc->cfFormat ) + renderLocaleAndSetupStgMedium( *pFormatetc, *pmedium ); + else if ( CF_UNICODETEXT == pFormatetc->cfFormat ) + renderUnicodeAndSetupStgMedium( *pFormatetc, *pmedium ); + else + renderAnyDataAndSetupStgMedium( *pFormatetc, *pmedium ); + } + catch(UnsupportedFlavorException&) + { + HRESULT hr = DV_E_FORMATETC; + + if ( m_FormatRegistrar.isSynthesizeableFormat( *pFormatetc ) ) + hr = renderSynthesizedFormatAndSetupStgMedium( *pFormatetc, *pmedium ); + + return hr; + } + catch( CInvalidFormatEtcException& ex ) + { + return ex.m_hr; + } + catch( CStgTransferHelper::CStgTransferException& ex ) + { + return translateStgExceptionCode( ex.m_hr ); + } + catch(...) + { + return E_UNEXPECTED; + } + + return S_OK; +} + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +// inline +void SAL_CALL CXTDataObject::renderDataAndSetupStgMedium( + const sal_Int8* lpStorage, const FORMATETC& fetc, sal_uInt32 nInitStgSize, + sal_uInt32 nBytesToTransfer, STGMEDIUM& stgmedium ) +{ + OSL_PRECOND( !nInitStgSize || nInitStgSize && (nInitStgSize >= nBytesToTransfer), + "Memory size less than number of bytes to transfer" ); + + CStgTransferHelper stgTransfHelper( AUTO_INIT ); + + // setup storage size + if ( nInitStgSize > 0 ) + stgTransfHelper.init( nInitStgSize, GHND ); + +#if OSL_DEBUG_LEVEL > 0 + sal_uInt32 nBytesWritten = 0; + stgTransfHelper.write( lpStorage, nBytesToTransfer, &nBytesWritten ); + OSL_ASSERT( nBytesWritten == nBytesToTransfer ); +#else + stgTransfHelper.write( lpStorage, nBytesToTransfer ); +#endif + + setupStgMedium( fetc, stgTransfHelper, stgmedium ); +} + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +//inline +void SAL_CALL CXTDataObject::renderLocaleAndSetupStgMedium( + FORMATETC& fetc, STGMEDIUM& stgmedium ) +{ + if ( m_FormatRegistrar.hasSynthesizedLocale( ) ) + { + LCID lcid = m_FormatRegistrar.getSynthesizedLocale( ); + renderDataAndSetupStgMedium( + reinterpret_cast< sal_Int8* >( &lcid ), + fetc, + 0, + sizeof( LCID ), + stgmedium ); + } + else + throw CInvalidFormatEtcException( DV_E_FORMATETC ); +} + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +//inline +void SAL_CALL CXTDataObject::renderUnicodeAndSetupStgMedium( + FORMATETC& fetc, STGMEDIUM& stgmedium ) +{ + DataFlavor aFlavor = formatEtcToDataFlavor( fetc ); + + Any aAny = m_XTransferable->getTransferData( aFlavor ); + + // unfortunately not all transferables fulfill the + // spec. an do throw an UnsupportedFlavorException + // so we must check the any + if ( !aAny.hasValue( ) ) + { + OSL_ENSURE( sal_False, "XTransferable should throw an exception if ask for an unsupported flavor" ); + throw UnsupportedFlavorException( ); + } + + OUString aText; + aAny >>= aText; + + sal_uInt32 nBytesToTransfer = aText.getLength( ) * sizeof( sal_Unicode ); + + // to be sure there is an ending 0 + sal_uInt32 nRequiredMemSize = nBytesToTransfer + sizeof( sal_Unicode ); + + renderDataAndSetupStgMedium( + reinterpret_cast< const sal_Int8* >( aText.getStr( ) ), + fetc, + nRequiredMemSize, + nBytesToTransfer, + stgmedium ); +} + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +//inline +void SAL_CALL CXTDataObject::renderAnyDataAndSetupStgMedium( + FORMATETC& fetc, STGMEDIUM& stgmedium ) +{ + DataFlavor aFlavor = formatEtcToDataFlavor( fetc ); + + Any aAny = m_XTransferable->getTransferData( aFlavor ); + + // unfortunately not all transferables fulfill the + // spec. an do throw an UnsupportedFlavorException + // so we must check the any + if ( !aAny.hasValue( ) ) + { + OSL_ENSURE( sal_False, "XTransferable should throw an exception if ask for an unsupported flavor" ); + throw UnsupportedFlavorException( ); + } + + // unfortunately not all transferables fulfill the + // spec. an do throw an UnsupportedFlavorException + // so we must check the any + if ( !aAny.hasValue( ) ) + throw UnsupportedFlavorException( ); + + Sequence< sal_Int8 > clipDataStream; + aAny >>= clipDataStream; + + sal_uInt32 nRequiredMemSize = 0; + if ( m_DataFormatTranslator.isOemOrAnsiTextFormat( fetc.cfFormat ) ) + nRequiredMemSize = sizeof( sal_Int8 ) * clipDataStream.getLength( ) + 1; + + // prepare data for transmision + if ( CF_DIB == fetc.cfFormat ) + clipDataStream = OOBmpToWinDIB( clipDataStream ); + + if ( CF_METAFILEPICT == fetc.cfFormat ) + { + stgmedium.tymed = TYMED_MFPICT; + stgmedium.hMetaFilePict = OOMFPictToWinMFPict( clipDataStream ); + stgmedium.pUnkForRelease = NULL; + } + else if( CF_ENHMETAFILE == fetc.cfFormat ) + { + stgmedium.tymed = TYMED_ENHMF; + stgmedium.hMetaFilePict = OOMFPictToWinENHMFPict( clipDataStream ); + stgmedium.pUnkForRelease = NULL; + } + else + renderDataAndSetupStgMedium( + clipDataStream.getArray( ), + fetc, + nRequiredMemSize, + clipDataStream.getLength( ), + stgmedium ); +} + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +HRESULT SAL_CALL CXTDataObject::renderSynthesizedFormatAndSetupStgMedium( FORMATETC& fetc, STGMEDIUM& stgmedium ) +{ + HRESULT hr = S_OK; + + try + { + if ( CF_UNICODETEXT == fetc.cfFormat ) + // the transferable seems to have only text + renderSynthesizedUnicodeAndSetupStgMedium( fetc, stgmedium ); + else if ( m_DataFormatTranslator.isOemOrAnsiTextFormat( fetc.cfFormat ) ) + // the transferable seems to have only unicode text + renderSynthesizedTextAndSetupStgMedium( fetc, stgmedium ); + else + // the transferable seems to have only text/html + renderSynthesizedHtmlAndSetupStgMedium( fetc, stgmedium ); + } + catch(UnsupportedFlavorException&) + { + hr = DV_E_FORMATETC; + } + catch( CInvalidFormatEtcException& ) + { + OSL_ENSURE( sal_False, "Unexpected exception" ); + } + catch( CStgTransferHelper::CStgTransferException& ex ) + { + return translateStgExceptionCode( ex.m_hr ); + } + catch(...) + { + hr = E_UNEXPECTED; + } + + return hr; +} + +//------------------------------------------------------------------------ +// the transferable must have only text, so we will synthesize unicode text +//------------------------------------------------------------------------ + +void SAL_CALL CXTDataObject::renderSynthesizedUnicodeAndSetupStgMedium( FORMATETC& fetc, STGMEDIUM& stgmedium ) +{ + OSL_ASSERT( CF_UNICODETEXT == fetc.cfFormat ); + + Any aAny = m_XTransferable->getTransferData( m_FormatRegistrar.getRegisteredTextFlavor( ) ); + + // unfortunately not all transferables fulfill the + // spec. an do throw an UnsupportedFlavorException + // so we must check the any + if ( !aAny.hasValue( ) ) + { + OSL_ENSURE( sal_False, "XTransferable should throw an exception if ask for an unsupported flavor" ); + throw UnsupportedFlavorException( ); + } + + Sequence< sal_Int8 > aText; + aAny >>= aText; + + CStgTransferHelper stgTransfHelper; + + MultiByteToWideCharEx( + m_FormatRegistrar.getRegisteredTextCodePage( ), + reinterpret_cast< char* >( aText.getArray( ) ), + aText.getLength( ), + stgTransfHelper ); + + setupStgMedium( fetc, stgTransfHelper, stgmedium ); +} + +//------------------------------------------------------------------------ +// the transferable must have only unicode text so we will sythesize text +//------------------------------------------------------------------------ + +void SAL_CALL CXTDataObject::renderSynthesizedTextAndSetupStgMedium( FORMATETC& fetc, STGMEDIUM& stgmedium ) +{ + OSL_ASSERT( m_DataFormatTranslator.isOemOrAnsiTextFormat( fetc.cfFormat ) ); + + DataFlavor aFlavor = formatEtcToDataFlavor( + m_DataFormatTranslator.getFormatEtcForClipformat( CF_UNICODETEXT ) ); + + Any aAny = m_XTransferable->getTransferData( aFlavor ); + + // unfortunately not all transferables fulfill the + // spec. an do throw an UnsupportedFlavorException + // so we must check the any + if ( !aAny.hasValue( ) ) + { + OSL_ENSURE( sal_False, "XTransferable should throw an exception if ask for an unsupported flavor" ); + throw UnsupportedFlavorException( ); + } + + OUString aUnicodeText; + aAny >>= aUnicodeText; + + CStgTransferHelper stgTransfHelper; + + WideCharToMultiByteEx( + GetACP( ), + reinterpret_cast<LPCWSTR>( aUnicodeText.getStr( ) ), + aUnicodeText.getLength( ), + stgTransfHelper ); + + setupStgMedium( fetc, stgTransfHelper, stgmedium ); +} + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +void SAL_CALL CXTDataObject::renderSynthesizedHtmlAndSetupStgMedium( FORMATETC& fetc, STGMEDIUM& stgmedium ) +{ + OSL_ASSERT( m_DataFormatTranslator.isHTMLFormat( fetc.cfFormat ) ); + + DataFlavor aFlavor; + + // creating a DataFlavor on the fly + aFlavor.MimeType = OUString::createFromAscii( "text/html" ); + aFlavor.DataType = getCppuType( (Sequence< sal_Int8 >*)0 ); + + Any aAny = m_XTransferable->getTransferData( aFlavor ); + + // unfortunately not all transferables fulfill the + // spec. an do throw an UnsupportedFlavorException + // so we must check the any + if ( !aAny.hasValue( ) ) + { + OSL_ENSURE( sal_False, "XTransferable should throw an exception if ask for an unsupported flavor" ); + throw UnsupportedFlavorException( ); + } + + Sequence< sal_Int8 > aTextHtmlSequence; + aAny >>= aTextHtmlSequence; + + Sequence< sal_Int8 > aHTMLFormatSequence = TextHtmlToHTMLFormat( aTextHtmlSequence ); + + sal_uInt32 nBytesToTransfer = aHTMLFormatSequence.getLength( ); + + renderDataAndSetupStgMedium( + reinterpret_cast< const sal_Int8* >( aHTMLFormatSequence.getArray( ) ), + fetc, + 0, + nBytesToTransfer, + stgmedium ); +} + +//------------------------------------------------------------------------ +// IDataObject->EnumFormatEtc +//------------------------------------------------------------------------ + +STDMETHODIMP CXTDataObject::EnumFormatEtc( + DWORD dwDirection, IEnumFORMATETC** ppenumFormatetc ) +{ + if ( NULL == ppenumFormatetc ) + return E_INVALIDARG; + + if ( DATADIR_SET == dwDirection ) + return E_NOTIMPL; + + *ppenumFormatetc = NULL; + + InitializeFormatEtcContainer( ); + + HRESULT hr; + if ( DATADIR_GET == dwDirection ) + { + *ppenumFormatetc = new CEnumFormatEtc( this, m_FormatEtcContainer ); + if ( NULL != *ppenumFormatetc ) + static_cast< LPUNKNOWN >( *ppenumFormatetc )->AddRef( ); + + hr = ( NULL != *ppenumFormatetc ) ? S_OK : E_OUTOFMEMORY; + } + else + hr = E_INVALIDARG; + + return hr; +} + +//------------------------------------------------------------------------ +// IDataObject->QueryGetData +//------------------------------------------------------------------------ + +STDMETHODIMP CXTDataObject::QueryGetData( LPFORMATETC pFormatetc ) +{ + if ( (NULL == pFormatetc) || IsBadReadPtr( pFormatetc, sizeof( FORMATETC ) ) ) + return E_INVALIDARG; + + InitializeFormatEtcContainer( ); + + return m_FormatEtcContainer.hasFormatEtc( *pFormatetc ) ? S_OK : S_FALSE; +} + +//------------------------------------------------------------------------ +// IDataObject->GetDataHere +//------------------------------------------------------------------------ + +STDMETHODIMP CXTDataObject::GetDataHere( LPFORMATETC, LPSTGMEDIUM ) +{ + return E_NOTIMPL; +} + +//------------------------------------------------------------------------ +// IDataObject->GetCanonicalFormatEtc +//------------------------------------------------------------------------ + +STDMETHODIMP CXTDataObject::GetCanonicalFormatEtc( LPFORMATETC, LPFORMATETC ) +{ + return E_NOTIMPL; +} + +//------------------------------------------------------------------------ +// IDataObject->SetData +//------------------------------------------------------------------------ + +STDMETHODIMP CXTDataObject::SetData( LPFORMATETC, LPSTGMEDIUM, BOOL ) +{ + return E_NOTIMPL; +} + +//------------------------------------------------------------------------ +// IDataObject->DAdvise +//------------------------------------------------------------------------ + +STDMETHODIMP CXTDataObject::DAdvise( LPFORMATETC, DWORD, LPADVISESINK, DWORD * ) +{ + return E_NOTIMPL; +} + +//------------------------------------------------------------------------ +// IDataObject->DUnadvise +//------------------------------------------------------------------------ + +STDMETHODIMP CXTDataObject::DUnadvise( DWORD ) +{ + return E_NOTIMPL; +} + +//------------------------------------------------------------------------ +// IDataObject->EnumDAdvise +//------------------------------------------------------------------------ + +STDMETHODIMP CXTDataObject::EnumDAdvise( LPENUMSTATDATA * ) +{ + return E_NOTIMPL; +} + +//------------------------------------------------------------------------ +// for our convenience +//------------------------------------------------------------------------ + +CXTDataObject::operator IDataObject*( ) +{ + return static_cast< IDataObject* >( this ); +} + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +inline +DataFlavor SAL_CALL CXTDataObject::formatEtcToDataFlavor( const FORMATETC& aFormatEtc ) const +{ + DataFlavor aFlavor; + + if ( m_FormatRegistrar.hasSynthesizedLocale( ) ) + aFlavor = + m_DataFormatTranslator.getDataFlavorFromFormatEtc( aFormatEtc, m_FormatRegistrar.getSynthesizedLocale( ) ); + else + aFlavor = m_DataFormatTranslator.getDataFlavorFromFormatEtc( aFormatEtc ); + + if ( !aFlavor.MimeType.getLength( ) ) + throw UnsupportedFlavorException( ); + + return aFlavor; +} + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +inline +void CXTDataObject::validateFormatEtc( LPFORMATETC lpFormatEtc ) const +{ + OSL_ASSERT( lpFormatEtc ); + + if ( lpFormatEtc->lindex != -1 ) + throw CInvalidFormatEtcException( DV_E_LINDEX ); + + if ( !(lpFormatEtc->dwAspect & DVASPECT_CONTENT) && + !(lpFormatEtc->dwAspect & DVASPECT_SHORTNAME) ) + throw CInvalidFormatEtcException( DV_E_DVASPECT ); + + if ( !(lpFormatEtc->tymed & TYMED_HGLOBAL) && + !(lpFormatEtc->tymed & TYMED_ISTREAM) && + !(lpFormatEtc->tymed & TYMED_MFPICT) && + !(lpFormatEtc->tymed & TYMED_ENHMF) ) + throw CInvalidFormatEtcException( DV_E_TYMED ); + + if ( lpFormatEtc->cfFormat == CF_METAFILEPICT && + !(lpFormatEtc->tymed & TYMED_MFPICT) ) + throw CInvalidFormatEtcException( DV_E_TYMED ); + + if ( lpFormatEtc->cfFormat == CF_ENHMETAFILE && + !(lpFormatEtc->tymed & TYMED_ENHMF) ) + throw CInvalidFormatEtcException( DV_E_TYMED ); +} + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +//inline +void SAL_CALL CXTDataObject::setupStgMedium( const FORMATETC& fetc, + CStgTransferHelper& stgTransHlp, + STGMEDIUM& stgmedium ) +{ + stgmedium.pUnkForRelease = NULL; + + if ( fetc.cfFormat == CF_METAFILEPICT ) + { + stgmedium.tymed = TYMED_MFPICT; + stgmedium.hMetaFilePict = static_cast< HMETAFILEPICT >( stgTransHlp.getHGlobal( ) ); + } + else if ( fetc.cfFormat == CF_ENHMETAFILE ) + { + stgmedium.tymed = TYMED_ENHMF; + stgmedium.hEnhMetaFile = static_cast< HENHMETAFILE >( stgTransHlp.getHGlobal( ) ); + } + else if ( fetc.tymed & TYMED_HGLOBAL ) + { + stgmedium.tymed = TYMED_HGLOBAL; + stgmedium.hGlobal = stgTransHlp.getHGlobal( ); + } + else if ( fetc.tymed & TYMED_ISTREAM ) + { + stgmedium.tymed = TYMED_ISTREAM; + stgTransHlp.getIStream( &stgmedium.pstm ); + } + else + OSL_ASSERT( sal_False ); +} + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +inline +void SAL_CALL CXTDataObject::invalidateStgMedium( STGMEDIUM& stgmedium ) const +{ + stgmedium.tymed = TYMED_NULL; +} + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +inline +HRESULT SAL_CALL CXTDataObject::translateStgExceptionCode( HRESULT hr ) const +{ + HRESULT hrTransl; + + switch( hr ) + { + case STG_E_MEDIUMFULL: + hrTransl = hr; + break; + + default: + hrTransl = E_UNEXPECTED; + break; + } + + return hrTransl; +} + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +inline void SAL_CALL CXTDataObject::InitializeFormatEtcContainer( ) +{ + if ( !m_bFormatEtcContainerInitialized ) + { + m_FormatRegistrar.RegisterFormats( m_XTransferable, m_FormatEtcContainer ); + m_bFormatEtcContainerInitialized = sal_True; + } +} + +//============================================================================ +// CEnumFormatEtc +//============================================================================ + +//---------------------------------------------------------------------------- +// ctor +//---------------------------------------------------------------------------- + +CEnumFormatEtc::CEnumFormatEtc( LPUNKNOWN lpUnkOuter, const CFormatEtcContainer& aFormatEtcContainer ) : + m_nRefCnt( 0 ), + m_lpUnkOuter( lpUnkOuter ), + m_FormatEtcContainer( aFormatEtcContainer ) +{ + Reset( ); +} + +//---------------------------------------------------------------------------- +// IUnknown->QueryInterface +//---------------------------------------------------------------------------- + +STDMETHODIMP CEnumFormatEtc::QueryInterface( REFIID iid, LPVOID* ppvObject ) +{ + if ( NULL == ppvObject ) + return E_INVALIDARG; + + HRESULT hr = E_NOINTERFACE; + + *ppvObject = NULL; + + if ( ( __uuidof( IUnknown ) == iid ) || + ( __uuidof( IEnumFORMATETC ) == iid ) ) + { + *ppvObject = static_cast< IUnknown* >( this ); + static_cast< LPUNKNOWN >( *ppvObject )->AddRef( ); + hr = S_OK; + } + + return hr; +} + +//---------------------------------------------------------------------------- +// IUnknown->AddRef +//---------------------------------------------------------------------------- + +STDMETHODIMP_(ULONG) CEnumFormatEtc::AddRef( ) +{ + // keep the dataobject alive + m_lpUnkOuter->AddRef( ); + return InterlockedIncrement( &m_nRefCnt ); +} + +//---------------------------------------------------------------------------- +// IUnknown->Release +//---------------------------------------------------------------------------- + +STDMETHODIMP_(ULONG) CEnumFormatEtc::Release( ) +{ + // release the outer dataobject + m_lpUnkOuter->Release( ); + + ULONG nRefCnt = InterlockedDecrement( &m_nRefCnt ); + if ( 0 == nRefCnt ) + delete this; + + return nRefCnt; +} + +//---------------------------------------------------------------------------- +// IEnumFORMATETC->Next +//---------------------------------------------------------------------------- + +STDMETHODIMP CEnumFormatEtc::Next( ULONG nRequested, LPFORMATETC lpDest, ULONG* lpFetched ) +{ + if ( ( nRequested < 1 ) || + (( nRequested > 1 ) && ( NULL == lpFetched )) || + IsBadWritePtr( lpDest, sizeof( FORMATETC ) * nRequested ) ) + return E_INVALIDARG; + + sal_uInt32 nFetched = m_FormatEtcContainer.nextFormatEtc( lpDest, nRequested ); + + if ( NULL != lpFetched ) + *lpFetched = nFetched; + + return (nFetched == nRequested) ? S_OK : S_FALSE; +} + +//---------------------------------------------------------------------------- +// IEnumFORMATETC->Skip +//---------------------------------------------------------------------------- + +STDMETHODIMP CEnumFormatEtc::Skip( ULONG celt ) +{ + return m_FormatEtcContainer.skipFormatEtc( celt ) ? S_OK : S_FALSE; +} + +//---------------------------------------------------------------------------- +// IEnumFORMATETC->Reset +//---------------------------------------------------------------------------- + +STDMETHODIMP CEnumFormatEtc::Reset( ) +{ + m_FormatEtcContainer.beginEnumFormatEtc( ); + return S_OK; +} + +//---------------------------------------------------------------------------- +// IEnumFORMATETC->Clone +//---------------------------------------------------------------------------- + +STDMETHODIMP CEnumFormatEtc::Clone( IEnumFORMATETC** ppenum ) +{ + if ( NULL == ppenum ) + return E_INVALIDARG; + + *ppenum = new CEnumFormatEtc( m_lpUnkOuter, m_FormatEtcContainer ); + if ( NULL != ppenum ) + static_cast< LPUNKNOWN >( *ppenum )->AddRef( ); + + return ( NULL != *ppenum ) ? S_OK : E_OUTOFMEMORY; +} diff --git a/dtrans/source/win32/dtobj/XTDataObject.hxx b/dtrans/source/win32/dtobj/XTDataObject.hxx new file mode 100644 index 000000000000..b7b20af56ac7 --- /dev/null +++ b/dtrans/source/win32/dtobj/XTDataObject.hxx @@ -0,0 +1,177 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + + +#ifndef _XTDATAOBJECT_HXX_ +#define _XTDATAOBJECT_HXX_ + + +//------------------------------------------------------------------------ +// includes +//------------------------------------------------------------------------ + +#include <com/sun/star/datatransfer/XTransferable.hpp> +#include <com/sun/star/datatransfer/clipboard/XClipboardOwner.hpp> + +#ifndef _DATAFORMATTRANSLATOR_HXX_ +#include "DataFmtTransl.hxx" +#endif + +#ifndef _FETCLIST_HXX_ +#include "FEtcList.hxx" +#endif + +#if defined _MSC_VER +#pragma warning(push,1) +#endif +#include <windows.h> +#include <ole2.h> +#include <objidl.h> +#if defined _MSC_VER +#pragma warning(pop) +#endif + +/*-------------------------------------------------------------------------- + - the function principle of the windows clipboard: + a data provider offers all formats he can deliver on the clipboard + a clipboard client ask for the available formats on the clipboard + and decides if there is a format he can use + if there is one, he requests the data in this format + + - This class inherits from IDataObject an so can be placed on the + OleClipboard. The class wrapps a transferable object which is the + original DataSource + - DataFlavors offerd by this transferable will be translated into + appropriate clipboard formats + - if the transferable contains text data always text and unicodetext + will be offered or vice versa + - text data will be automaticaly converted between text und unicode text + - although the transferable may support text in different charsets + (codepages) only text in one codepage can be offered by the clipboard + +----------------------------------------------------------------------------*/ + +class CStgTransferHelper; + +class CXTDataObject : public IDataObject +{ +public: + CXTDataObject( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& aServiceManager, + const ::com::sun::star::uno::Reference< ::com::sun::star::datatransfer::XTransferable >& aXTransferable ); + virtual ~CXTDataObject() {} + + //----------------------------------------------------------------- + // ole interface implementation + //----------------------------------------------------------------- + + //IUnknown interface methods + STDMETHODIMP QueryInterface(REFIID iid, LPVOID* ppvObject); + STDMETHODIMP_( ULONG ) AddRef( ); + STDMETHODIMP_( ULONG ) Release( ); + + // IDataObject interface methods + STDMETHODIMP GetData( LPFORMATETC pFormatetc, LPSTGMEDIUM pmedium ); + STDMETHODIMP GetDataHere( LPFORMATETC pFormatetc, LPSTGMEDIUM pmedium ); + STDMETHODIMP QueryGetData( LPFORMATETC pFormatetc ); + STDMETHODIMP GetCanonicalFormatEtc( LPFORMATETC pFormatectIn, LPFORMATETC pFormatetcOut ); + STDMETHODIMP SetData( LPFORMATETC pFormatetc, LPSTGMEDIUM pmedium, BOOL fRelease ); + STDMETHODIMP EnumFormatEtc( DWORD dwDirection, IEnumFORMATETC** ppenumFormatetc ); + STDMETHODIMP DAdvise( LPFORMATETC pFormatetc, DWORD advf, LPADVISESINK pAdvSink, DWORD* pdwConnection ); + STDMETHODIMP DUnadvise( DWORD dwConnection ); + STDMETHODIMP EnumDAdvise( LPENUMSTATDATA* ppenumAdvise ); + + operator IDataObject*( ); + +private: + com::sun::star::datatransfer::DataFlavor SAL_CALL formatEtcToDataFlavor( const FORMATETC& aFormatEtc ) const; + + void SAL_CALL renderDataAndSetupStgMedium( const sal_Int8* lpStorage, + const FORMATETC& fetc, + sal_uInt32 nInitStgSize, + sal_uInt32 nBytesToTransfer, + STGMEDIUM& stgmedium ); + + void SAL_CALL renderLocaleAndSetupStgMedium( FORMATETC& fetc, STGMEDIUM& stgmedium ); + void SAL_CALL renderUnicodeAndSetupStgMedium( FORMATETC& fetc, STGMEDIUM& stgmedium ); + void SAL_CALL renderAnyDataAndSetupStgMedium( FORMATETC& fetc, STGMEDIUM& stgmedium ); + + HRESULT SAL_CALL renderSynthesizedFormatAndSetupStgMedium( FORMATETC& fetc, STGMEDIUM& stgmedium ); + void SAL_CALL renderSynthesizedUnicodeAndSetupStgMedium( FORMATETC& fetc, STGMEDIUM& stgmedium ); + void SAL_CALL renderSynthesizedTextAndSetupStgMedium( FORMATETC& fetc, STGMEDIUM& stgmedium ); + void SAL_CALL renderSynthesizedHtmlAndSetupStgMedium( FORMATETC& fetc, STGMEDIUM& stgmedium ); + + void SAL_CALL setupStgMedium( const FORMATETC& fetc, + CStgTransferHelper& stgTransHlp, + STGMEDIUM& stgmedium ); + + void validateFormatEtc( LPFORMATETC lpFormatEtc ) const; + void SAL_CALL invalidateStgMedium( STGMEDIUM& stgmedium ) const; + + HRESULT SAL_CALL translateStgExceptionCode( HRESULT hr ) const; + + inline void SAL_CALL InitializeFormatEtcContainer( ); + +private: + LONG m_nRefCnt; + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > m_SrvMgr; + ::com::sun::star::uno::Reference< ::com::sun::star::datatransfer::XTransferable > m_XTransferable; + CFormatEtcContainer m_FormatEtcContainer; + sal_Bool m_bFormatEtcContainerInitialized; + CDataFormatTranslator m_DataFormatTranslator; + CFormatRegistrar m_FormatRegistrar; +}; + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ + +class CEnumFormatEtc : public IEnumFORMATETC +{ +public: + CEnumFormatEtc( LPUNKNOWN lpUnkOuter, const CFormatEtcContainer& aFormatEtcContainer ); + virtual ~CEnumFormatEtc() {} + + // IUnknown + STDMETHODIMP QueryInterface( REFIID iid, LPVOID* ppvObject ); + STDMETHODIMP_( ULONG ) AddRef( ); + STDMETHODIMP_( ULONG ) Release( ); + + //IEnumFORMATETC + STDMETHODIMP Next( ULONG nRequested, LPFORMATETC lpDest, ULONG* lpFetched ); + STDMETHODIMP Skip( ULONG celt ); + STDMETHODIMP Reset( ); + STDMETHODIMP Clone( IEnumFORMATETC** ppenum ); + +private: + LONG m_nRefCnt; + LPUNKNOWN m_lpUnkOuter; + CFormatEtcContainer m_FormatEtcContainer; +}; + +typedef CEnumFormatEtc *PCEnumFormatEtc; + +#endif diff --git a/dtrans/source/win32/dtobj/makefile.mk b/dtrans/source/win32/dtobj/makefile.mk new file mode 100644 index 000000000000..5aea2b133dc1 --- /dev/null +++ b/dtrans/source/win32/dtobj/makefile.mk @@ -0,0 +1,76 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ=..$/..$/.. + +PRJNAME=dtrans +TARGET=dtobjfact +ENABLE_EXCEPTIONS=TRUE +LIBTARGET=NO + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk + +# ------------------------------------------------------------------ + +#-DUNICODE -D_UNICODE +.IF "$(COM)"!="GCC" +CFLAGS+=-GR -Ob0 +.ENDIF + +SLOFILES=$(SLO)$/DtObjFactory.obj\ + $(SLO)$/APNDataObject.obj\ + $(SLO)$/DOTransferable.obj\ + $(SLO)$/DTransHelper.obj\ + $(SLO)$/XTDataObject.obj\ + $(SLO)$/TxtCnvtHlp.obj\ + $(SLO)$/DataFmtTransl.obj\ + $(SLO)$/FmtFilter.obj\ + $(SLO)$/FetcList.obj\ + $(SLO)$/Fetc.obj\ + $(SLO)$/XNotifyingDataObject.obj + +LIB1TARGET=$(SLB)$/$(TARGET).lib +.IF "$(COM)"!="GCC" +LIB1OBJFILES=$(SLOFILES) +.ELSE +LIB1OBJFILES=$(SLO)$/DtObjFactory.obj\ + $(SLO)$/APNDataObject.obj\ + $(SLO)$/DOTransferable.obj\ + $(SLO)$/DTransHelper.obj\ + $(SLO)$/XTDataObject.obj\ + $(SLO)$/TxtCnvtHlp.obj\ + $(SLO)$/DataFmtTransl.obj\ + $(SLO)$/FmtFilter.obj\ + $(SLO)$/FetcList.obj\ + $(SLO)$/Fetc.obj +.ENDIF + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk |