diff options
author | Jens-Heiner Rechtien <hr@openoffice.org> | 2009-12-01 17:41:04 +0000 |
---|---|---|
committer | Jens-Heiner Rechtien <hr@openoffice.org> | 2009-12-01 17:41:04 +0000 |
commit | 25df57fb136eb88253e7b9abc680adab85497dba (patch) | |
tree | 8ba67f4e32903a1f4dffb3361fa875b00f076ecd /oox/source | |
parent | 2be6a1367647d57da39bac601b5bca7d4d85312a (diff) | |
parent | 60be2a0e7659ad752551d8fce0d72e04b28e7888 (diff) |
chartshapes: merge with DEV300 m55
Diffstat (limited to 'oox/source')
133 files changed, 7430 insertions, 3365 deletions
diff --git a/oox/source/core/binaryfilterbase.cxx b/oox/source/core/binaryfilterbase.cxx index 2e6251b61424..86e89318d476 100644 --- a/oox/source/core/binaryfilterbase.cxx +++ b/oox/source/core/binaryfilterbase.cxx @@ -42,8 +42,8 @@ namespace core { // ============================================================================ -BinaryFilterBase::BinaryFilterBase( const Reference< XMultiServiceFactory >& rxFactory ) : - FilterBase( rxFactory ) +BinaryFilterBase::BinaryFilterBase( const Reference< XMultiServiceFactory >& rxGlobalFactory ) : + FilterBase( rxGlobalFactory ) { } diff --git a/oox/source/core/contexthandler.cxx b/oox/source/core/contexthandler.cxx index d1f8050d7945..ea463f4fcc5f 100644 --- a/oox/source/core/contexthandler.cxx +++ b/oox/source/core/contexthandler.cxx @@ -74,9 +74,9 @@ const OUString& ContextHandler::getFragmentPath() const return mxBaseData->maFragmentPath; } -OUString ContextHandler::getFragmentPathFromTarget( const OUString& rTarget ) const +OUString ContextHandler::getFragmentPathFromRelation( const Relation& rRelation ) const { - return mxBaseData->mxRelations->getFragmentPathFromTarget( rTarget ); + return mxBaseData->mxRelations->getFragmentPathFromRelation( rRelation ); } OUString ContextHandler::getFragmentPathFromRelId( const OUString& rRelId ) const @@ -84,9 +84,9 @@ OUString ContextHandler::getFragmentPathFromRelId( const OUString& rRelId ) cons return mxBaseData->mxRelations->getFragmentPathFromRelId( rRelId ); } -OUString ContextHandler::getFragmentPathFromType( const OUString& rType ) const +OUString ContextHandler::getFragmentPathFromFirstType( const OUString& rType ) const { - return mxBaseData->mxRelations->getFragmentPathFromType( rType ); + return mxBaseData->mxRelations->getFragmentPathFromFirstType( rType ); } void ContextHandler::implSetLocator( const Reference< XLocator >& rxLocator ) diff --git a/oox/source/core/facreg.cxx b/oox/source/core/facreg.cxx index 17489e27e11e..5ffd585e47ff 100644 --- a/oox/source/core/facreg.cxx +++ b/oox/source/core/facreg.cxx @@ -66,6 +66,7 @@ namespace oox { namespace shape { SERVICE( ShapeContextHandler ); } namespace shape { SERVICE( FastTokenHandlerService ); } namespace docprop { SERVICE2( OOXMLDocPropImportImpl ); } + namespace xls { SERVICE2( OOXMLFormulaParser ); } } // @@ -108,6 +109,7 @@ OOX_DLLPUBLIC sal_Bool SAL_CALL component_writeInfo( void * , void * pRegistryKe WRITEINFO( ::oox::shape::ShapeContextHandler ); WRITEINFO( ::oox::shape::FastTokenHandlerService ); WRITEINFO( ::oox::docprop::OOXMLDocPropImportImpl ); + WRITEINFO( ::oox::xls::OOXMLFormulaParser ); } catch (registry::InvalidRegistryException &) { @@ -147,7 +149,6 @@ OOX_DLLPUBLIC void * SAL_CALL component_getFactory( const sal_Char * pImplName, const sal_Int32 nImplNameLen = strlen( pImplName ); - // impress oasis import SINGLEFACTORY( ::oox::core::FilterDetect ) else SINGLEFACTORY( oox::ppt::PowerPointImport ) else SINGLEFACTORY( ::oox::xls::BiffDetector ) @@ -156,6 +157,7 @@ OOX_DLLPUBLIC void * SAL_CALL component_getFactory( const sal_Char * pImplName, else SINGLEFACTORY( ::oox::shape::ShapeContextHandler) else SINGLEFACTORY( ::oox::shape::FastTokenHandlerService) else SINGLEFACTORY2( ::oox::docprop::OOXMLDocPropImportImpl ) + else SINGLEFACTORY2( ::oox::xls::OOXMLFormulaParser ) if( xFactory.is()) { diff --git a/oox/source/core/filterbase.cxx b/oox/source/core/filterbase.cxx index e3babeec61e4..23363db46ed5 100644 --- a/oox/source/core/filterbase.cxx +++ b/oox/source/core/filterbase.cxx @@ -29,11 +29,22 @@ ************************************************************************/ #include "oox/core/filterbase.hxx" +#include <set> +#include <com/sun/star/awt/XDevice.hpp> +#include <com/sun/star/frame/XFramesSupplier.hpp> #include <com/sun/star/frame/XModel.hpp> #include <com/sun/star/task/XStatusIndicator.hpp> #include <com/sun/star/task/XInteractionHandler.hpp> +#include <osl/mutex.hxx> +#include <rtl/instance.hxx> #include <rtl/uri.hxx> #include <comphelper/mediadescriptor.hxx> +#include "tokens.hxx" +#include "oox/helper/binaryinputstream.hxx" +#include "oox/helper/binaryoutputstream.hxx" +#include "oox/helper/graphichelper.hxx" +#include "oox/helper/modelobjecthelper.hxx" +#include "oox/ole/oleobjecthelper.hxx" using ::rtl::OUString; using ::com::sun::star::uno::Any; @@ -42,47 +53,174 @@ using ::com::sun::star::uno::Sequence; using ::com::sun::star::uno::Exception; using ::com::sun::star::uno::RuntimeException; using ::com::sun::star::uno::UNO_QUERY; +using ::com::sun::star::uno::UNO_QUERY_THROW; +using ::com::sun::star::uno::UNO_SET_THROW; using ::com::sun::star::lang::IllegalArgumentException; using ::com::sun::star::lang::XMultiServiceFactory; using ::com::sun::star::lang::XComponent; +using ::com::sun::star::beans::NamedValue; using ::com::sun::star::beans::PropertyValue; +using ::com::sun::star::awt::DeviceInfo; +using ::com::sun::star::awt::XDevice; +using ::com::sun::star::frame::XFrame; +using ::com::sun::star::frame::XFramesSupplier; using ::com::sun::star::frame::XModel; using ::com::sun::star::io::XInputStream; using ::com::sun::star::io::XOutputStream; using ::com::sun::star::io::XStream; using ::com::sun::star::task::XStatusIndicator; using ::com::sun::star::task::XInteractionHandler; +using ::com::sun::star::graphic::XGraphic; using ::comphelper::MediaDescriptor; +using ::oox::ole::OleObjectHelper; namespace oox { namespace core { // ============================================================================ +namespace { + +/** This guard prevents recursive loading/saving of the same document. */ +class DocumentOpenedGuard : public ::osl::Mutex +{ +public: + explicit DocumentOpenedGuard( const OUString& rUrl ); + ~DocumentOpenedGuard(); + + inline bool isValid() const { return maUrl.getLength() > 0; } + +private: + DocumentOpenedGuard( const DocumentOpenedGuard& ); + DocumentOpenedGuard& operator=( const DocumentOpenedGuard& ); + + typedef ::std::set< OUString > UrlSet; + struct UrlPool : public ::rtl::Static< UrlSet, UrlPool > {}; + + UrlSet& mrUrls; + OUString maUrl; +}; + +DocumentOpenedGuard::DocumentOpenedGuard( const OUString& rUrl ) : + mrUrls( UrlPool::get() ) +{ + ::osl::MutexGuard aGuard( *this ); + OSL_ENSURE( (rUrl.getLength() == 0) || (mrUrls.count( rUrl ) == 0), + "DocumentOpenedGuard::DocumentOpenedGuard - filter called recursively for this document" ); + if( (rUrl.getLength() > 0) && (mrUrls.count( rUrl ) == 0) ) + { + mrUrls.insert( rUrl ); + maUrl = rUrl; + } +} + +DocumentOpenedGuard::~DocumentOpenedGuard() +{ + ::osl::MutexGuard aGuard( *this ); + if( isValid() ) + mrUrls.erase( maUrl ); +} + +} // namespace + +// ============================================================================ + struct FilterBaseImpl { + typedef ::boost::shared_ptr< GraphicHelper > GraphicHelperRef; + typedef ::boost::shared_ptr< ModelObjectHelper > ModelObjHelperRef; + typedef ::boost::shared_ptr< OleObjectHelper > OleObjHelperRef; + typedef ::std::map< OUString, Reference< XGraphic > > EmbeddedGraphicMap; + typedef ::std::map< sal_Int32, sal_Int32 > SystemPalette; + typedef ::std::map< OUString, Any > ArgumentMap; + MediaDescriptor maDescriptor; + DeviceInfo maDeviceInfo; OUString maFileUrl; StorageRef mxStorage; - Sequence< Any > maArguments; - Reference< XMultiServiceFactory > mxFactory; + GraphicHelperRef mxGraphicHelper; /// Graphic and graphic object handling. + ModelObjHelperRef mxModelObjHelper; /// Tables to create new named drawing objects. + OleObjHelperRef mxOleObjHelper; /// OLE object handling. + EmbeddedGraphicMap maEmbeddedGraphics; /// Maps all imported embedded graphics by their path. + SystemPalette maSystemPalette; /// Maps system colors (XML tokens) to RGB color values. + + ArgumentMap maArguments; + Reference< XMultiServiceFactory > mxGlobalFactory; Reference< XModel > mxModel; + Reference< XMultiServiceFactory > mxModelFactory; Reference< XInputStream > mxInStream; - Reference< XStream > mxStream; + Reference< XStream > mxOutStream; Reference< XStatusIndicator > mxStatusIndicator; Reference< XInteractionHandler > mxInteractionHandler; - explicit FilterBaseImpl( const Reference< XMultiServiceFactory >& rxFactory ); + explicit FilterBaseImpl( const Reference< XMultiServiceFactory >& rxGlobalFactory ); + + void setDocumentModel( const Reference< XComponent >& rxComponent ); void setMediaDescriptor( const Sequence< PropertyValue >& rDescriptor ); + + bool hasDocumentModel() const; }; // ---------------------------------------------------------------------------- -FilterBaseImpl::FilterBaseImpl( const Reference< XMultiServiceFactory >& rxFactory ) : - mxFactory( rxFactory ) +FilterBaseImpl::FilterBaseImpl( const Reference< XMultiServiceFactory >& rxGlobalFactory ) : + mxGlobalFactory( rxGlobalFactory ) { - OSL_ENSURE( mxFactory.is(), "FilterBaseImpl::FilterBaseImpl - missing service factory" ); + OSL_ENSURE( mxGlobalFactory.is(), "FilterBaseImpl::FilterBaseImpl - missing service factory" ); + if( mxGlobalFactory.is() ) + { + // get the metric of the output device + try + { + Reference< XFramesSupplier > xFramesSupp( mxGlobalFactory->createInstance( CREATE_OUSTRING( "com.sun.star.frame.Desktop" ) ), UNO_QUERY_THROW ); + Reference< XFrame > xFrame( xFramesSupp->getActiveFrame(), UNO_SET_THROW ); + Reference< XDevice > xDevice( xFrame->getContainerWindow(), UNO_QUERY_THROW ); + maDeviceInfo = xDevice->getInfo(); + } + catch( Exception& ) + { + OSL_ENSURE( false, "FilterBaseImpl::FilterBaseImpl - cannot get output device info" ); + } + } + + //! TODO: get colors from system + maSystemPalette[ XML_3dDkShadow ] = 0x716F64; + maSystemPalette[ XML_3dLight ] = 0xF1EFE2; + maSystemPalette[ XML_activeBorder ] = 0xD4D0C8; + maSystemPalette[ XML_activeCaption ] = 0x0054E3; + maSystemPalette[ XML_appWorkspace ] = 0x808080; + maSystemPalette[ XML_background ] = 0x004E98; + maSystemPalette[ XML_btnFace ] = 0xECE9D8; + maSystemPalette[ XML_btnHighlight ] = 0xFFFFFF; + maSystemPalette[ XML_btnShadow ] = 0xACA899; + maSystemPalette[ XML_btnText ] = 0x000000; + maSystemPalette[ XML_captionText ] = 0xFFFFFF; + maSystemPalette[ XML_gradientActiveCaption ] = 0x3D95FF; + maSystemPalette[ XML_gradientInactiveCaption ] = 0xD8E4F8; + maSystemPalette[ XML_grayText ] = 0xACA899; + maSystemPalette[ XML_highlight ] = 0x316AC5; + maSystemPalette[ XML_highlightText ] = 0xFFFFFF; + maSystemPalette[ XML_hotLight ] = 0x000080; + maSystemPalette[ XML_inactiveBorder ] = 0xD4D0C8; + maSystemPalette[ XML_inactiveCaption ] = 0x7A96DF; + maSystemPalette[ XML_inactiveCaptionText ] = 0xD8E4F8; + maSystemPalette[ XML_infoBk ] = 0xFFFFE1; + maSystemPalette[ XML_infoText ] = 0x000000; + maSystemPalette[ XML_menu ] = 0xFFFFFF; + maSystemPalette[ XML_menuBar ] = 0xECE9D8; + maSystemPalette[ XML_menuHighlight ] = 0x316AC5; + maSystemPalette[ XML_menuText ] = 0x000000; + maSystemPalette[ XML_scrollBar ] = 0xD4D0C8; + maSystemPalette[ XML_window ] = 0xFFFFFF; + maSystemPalette[ XML_windowFrame ] = 0x000000; + maSystemPalette[ XML_windowText ] = 0x000000; +} + +void FilterBaseImpl::setDocumentModel( const Reference< XComponent >& rxComponent ) +{ + mxModel.set( rxComponent, UNO_QUERY ); + mxModelFactory.set( rxComponent, UNO_QUERY ); } void FilterBaseImpl::setMediaDescriptor( const Sequence< PropertyValue >& rDescriptor ) @@ -91,7 +229,7 @@ void FilterBaseImpl::setMediaDescriptor( const Sequence< PropertyValue >& rDescr maFileUrl = maDescriptor.getUnpackedValueOrDefault( MediaDescriptor::PROP_URL(), maFileUrl ); mxInStream = maDescriptor.getUnpackedValueOrDefault( MediaDescriptor::PROP_INPUTSTREAM(), mxInStream ); - mxStream = maDescriptor.getUnpackedValueOrDefault( MediaDescriptor::PROP_STREAMFOROUTPUT(), mxStream ); + mxOutStream = maDescriptor.getUnpackedValueOrDefault( MediaDescriptor::PROP_STREAMFOROUTPUT(), mxOutStream ); mxStatusIndicator = maDescriptor.getUnpackedValueOrDefault( MediaDescriptor::PROP_STATUSINDICATOR(), mxStatusIndicator ); mxInteractionHandler = maDescriptor.getUnpackedValueOrDefault( MediaDescriptor::PROP_INTERACTIONHANDLER(), mxInteractionHandler ); @@ -99,10 +237,15 @@ void FilterBaseImpl::setMediaDescriptor( const Sequence< PropertyValue >& rDescr maDescriptor.addInputStream(); } +bool FilterBaseImpl::hasDocumentModel() const +{ + return mxGlobalFactory.is() && mxModel.is() && mxModelFactory.is(); +} + // ============================================================================ -FilterBase::FilterBase( const Reference< XMultiServiceFactory >& rxFactory ) : - mxImpl( new FilterBaseImpl( rxFactory ) ) +FilterBase::FilterBase( const Reference< XMultiServiceFactory >& rxGlobalFactory ) : + mxImpl( new FilterBaseImpl( rxGlobalFactory ) ) { } @@ -117,19 +260,20 @@ bool FilterBase::isImportFilter() const bool FilterBase::isExportFilter() const { - return mxImpl->mxStream.is(); + return mxImpl->mxOutStream.is(); } // ---------------------------------------------------------------------------- -const Sequence< Any >& FilterBase::getArguments() const +Any FilterBase::getArgument( const OUString& rArgName ) const { - return mxImpl->maArguments; + FilterBaseImpl::ArgumentMap::const_iterator aIt = mxImpl->maArguments.find( rArgName ); + return (aIt == mxImpl->maArguments.end()) ? Any() : aIt->second; } const Reference< XMultiServiceFactory >& FilterBase::getGlobalFactory() const { - return mxImpl->mxFactory; + return mxImpl->mxGlobalFactory; } const Reference< XModel >& FilterBase::getModel() const @@ -137,6 +281,11 @@ const Reference< XModel >& FilterBase::getModel() const return mxImpl->mxModel; } +const Reference< XMultiServiceFactory >& FilterBase::getModelFactory() const +{ + return mxImpl->mxModelFactory; +} + const Reference< XStatusIndicator >& FilterBase::getStatusIndicator() const { return mxImpl->mxStatusIndicator; @@ -174,8 +323,11 @@ OUString FilterBase::getAbsoluteUrl( const OUString& rUrl ) const const sal_Int32 nFilePrefixLen = aFilePrefix.getLength(); const OUString aUncPrefix = CREATE_OUSTRING( "//" ); - /* (1) convert all backslashes to slashes. */ + /* (1) convert all backslashes to slashes, and check that passed URL is + not empty. */ OUString aUrl = rUrl.replace( '\\', '/' ); + if( aUrl.getLength() == 0 ) + return aUrl; /* (2) add 'file:///' to absolute Windows paths, e.g. convert 'C:/path/file' to 'file:///c:/path/file'. */ @@ -236,6 +388,100 @@ Reference< XOutputStream > FilterBase::openOutputStream( const OUString& rStream return mxImpl->mxStorage->openOutputStream( rStreamName ); } +void FilterBase::commitStorage() const +{ + mxImpl->mxStorage->commit(); +} + +// helpers -------------------------------------------------------------------- + +GraphicHelper& FilterBase::getGraphicHelper() const +{ + if( !mxImpl->mxGraphicHelper ) + mxImpl->mxGraphicHelper.reset( new GraphicHelper( mxImpl->mxGlobalFactory ) ); + return *mxImpl->mxGraphicHelper; +} + +ModelObjectHelper& FilterBase::getModelObjectHelper() const +{ + if( !mxImpl->mxModelObjHelper ) + mxImpl->mxModelObjHelper.reset( new ModelObjectHelper( mxImpl->mxModelFactory ) ); + return *mxImpl->mxModelObjHelper; +} + +OleObjectHelper& FilterBase::getOleObjectHelper() const +{ + if( !mxImpl->mxOleObjHelper ) + mxImpl->mxOleObjHelper.reset( new OleObjectHelper( mxImpl->mxModelFactory ) ); + return *mxImpl->mxOleObjHelper; +} + +const DeviceInfo& FilterBase::getDeviceInfo() const +{ + return mxImpl->maDeviceInfo; +} + +sal_Int32 FilterBase::convertScreenPixelX( double fPixelX ) const +{ + return (mxImpl->maDeviceInfo.PixelPerMeterX > 0) ? + static_cast< sal_Int32 >( (fPixelX * 100000.0) / mxImpl->maDeviceInfo.PixelPerMeterX ) : 0; +} + +sal_Int32 FilterBase::convertScreenPixelY( double fPixelY ) const +{ + return (mxImpl->maDeviceInfo.PixelPerMeterY > 0) ? + static_cast< sal_Int32 >( (fPixelY * 100000.0) / mxImpl->maDeviceInfo.PixelPerMeterY ) : 0; +} + +sal_Int32 FilterBase::getSystemColor( sal_Int32 nToken, sal_Int32 nDefaultRgb ) const +{ + FilterBaseImpl::SystemPalette::const_iterator aIt = mxImpl->maSystemPalette.find( nToken ); + OSL_ENSURE( aIt != mxImpl->maSystemPalette.end(), "FilterBase::getSystemColor - invalid token identifier" ); + return (aIt == mxImpl->maSystemPalette.end()) ? ((nDefaultRgb < 0) ? API_RGB_WHITE : nDefaultRgb) : aIt->second; +} + +bool FilterBase::importBinaryData( StreamDataSequence& orDataSeq, const OUString& rStreamName ) +{ + OSL_ENSURE( rStreamName.getLength() > 0, "FilterBase::importBinaryData - empty stream name" ); + if( rStreamName.getLength() == 0 ) + return false; + + // try to open the stream (this may fail - do not assert) + BinaryXInputStream aInStrm( openInputStream( rStreamName ), true ); + if( aInStrm.isEof() ) + return false; + + // copy the entire stream to the passed sequence + SequenceOutputStream aOutStrm( orDataSeq ); + aOutStrm.copyStream( aInStrm ); + return true; +} + +Reference< XGraphic > FilterBase::importEmbeddedGraphic( const OUString& rStreamName ) const +{ + Reference< XGraphic > xGraphic; + OSL_ENSURE( rStreamName.getLength() > 0, "FilterBase::importEmbeddedGraphic - empty stream name" ); + if( rStreamName.getLength() > 0 ) + { + FilterBaseImpl::EmbeddedGraphicMap::const_iterator aIt = mxImpl->maEmbeddedGraphics.find( rStreamName ); + if( aIt == mxImpl->maEmbeddedGraphics.end() ) + { + xGraphic = getGraphicHelper().importGraphic( openInputStream( rStreamName ) ); + if( xGraphic.is() ) + mxImpl->maEmbeddedGraphics[ rStreamName ] = xGraphic; + } + else + xGraphic = aIt->second; + } + return xGraphic; +} + +OUString FilterBase::importEmbeddedGraphicObject( const OUString& rStreamName ) const +{ + Reference< XGraphic > xGraphic = importEmbeddedGraphic( rStreamName ); + return xGraphic.is() ? getGraphicHelper().createGraphicObject( xGraphic ) : OUString(); +} + // com.sun.star.lang.XServiceInfo interface ----------------------------------- OUString SAL_CALL FilterBase::getImplementationName() throw( RuntimeException ) @@ -262,15 +508,26 @@ Sequence< OUString > SAL_CALL FilterBase::getSupportedServiceNames() throw( Runt void SAL_CALL FilterBase::initialize( const Sequence< Any >& rArgs ) throw( Exception, RuntimeException ) { - mxImpl->maArguments = rArgs; + if( rArgs.getLength() >= 2 ) + { + Sequence< NamedValue > aArgSeq; + if( (rArgs[ 1 ] >>= aArgSeq) && aArgSeq.hasElements() ) + { + const NamedValue* pArg = aArgSeq.getConstArray(); + const NamedValue* pEnd = pArg + aArgSeq.getLength(); + for( ; pArg < pEnd; ++pArg ) + if( pArg->Name.getLength() > 0 ) + mxImpl->maArguments[ pArg->Name ] = pArg->Value; + } + } } // com.sun.star.document.XImporter interface ---------------------------------- void SAL_CALL FilterBase::setTargetDocument( const Reference< XComponent >& rxDocument ) throw( IllegalArgumentException, RuntimeException ) { - mxImpl->mxModel.set( rxDocument, UNO_QUERY ); - if( !mxImpl->mxModel.is() ) + mxImpl->setDocumentModel( rxDocument ); + if( !mxImpl->hasDocumentModel() ) throw IllegalArgumentException(); } @@ -278,8 +535,8 @@ void SAL_CALL FilterBase::setTargetDocument( const Reference< XComponent >& rxDo void SAL_CALL FilterBase::setSourceDocument( const Reference< XComponent >& rxDocument ) throw( IllegalArgumentException, RuntimeException ) { - mxImpl->mxModel.set( rxDocument, UNO_QUERY ); - if( !mxImpl->mxModel.is() ) + mxImpl->setDocumentModel( rxDocument ); + if( !mxImpl->hasDocumentModel() ) throw IllegalArgumentException(); } @@ -288,18 +545,22 @@ void SAL_CALL FilterBase::setSourceDocument( const Reference< XComponent >& rxDo sal_Bool SAL_CALL FilterBase::filter( const Sequence< PropertyValue >& rDescriptor ) throw( RuntimeException ) { sal_Bool bRet = sal_False; - if( mxImpl->mxFactory.is() && mxImpl->mxModel.is() ) + if( mxImpl->hasDocumentModel() ) { mxImpl->setMediaDescriptor( rDescriptor ); - mxImpl->mxStorage = implCreateStorage( mxImpl->mxInStream, mxImpl->mxStream ); - if( mxImpl->mxStorage.get() ) + DocumentOpenedGuard aOpenedGuard( mxImpl->maFileUrl ); + if( aOpenedGuard.isValid() ) { - mxImpl->mxModel->lockControllers(); - if( mxImpl->mxInStream.is() ) - bRet = importDocument(); - else if( mxImpl->mxStream.is() ) - bRet = exportDocument(); - mxImpl->mxModel->unlockControllers(); + mxImpl->mxStorage = implCreateStorage( mxImpl->mxInStream, mxImpl->mxOutStream ); + if( mxImpl->mxStorage.get() ) + { + mxImpl->mxModel->lockControllers(); + if( mxImpl->mxInStream.is() ) + bRet = importDocument(); + else if( mxImpl->mxOutStream.is() ) + bRet = exportDocument(); + mxImpl->mxModel->unlockControllers(); + } } } return bRet; diff --git a/oox/source/core/fragmenthandler.cxx b/oox/source/core/fragmenthandler.cxx index 35a28585e095..6fc97bdfe372 100644 --- a/oox/source/core/fragmenthandler.cxx +++ b/oox/source/core/fragmenthandler.cxx @@ -34,6 +34,7 @@ using ::rtl::OUString; using ::com::sun::star::uno::Reference; using ::com::sun::star::uno::RuntimeException; +using ::com::sun::star::io::XInputStream; using ::com::sun::star::xml::sax::SAXException; using ::com::sun::star::xml::sax::XFastAttributeList; using ::com::sun::star::xml::sax::XFastContextHandler; @@ -122,6 +123,13 @@ void FragmentHandler::processingInstruction( const OUString&, const OUString& ) { } +// XML stream handling -------------------------------------------------------- + +Reference< XInputStream > FragmentHandler::openFragmentStream() const +{ + return getFilter().openInputStream( getFragmentPath() ); +} + // binary records ------------------------------------------------------------- const RecordInfo* FragmentHandler::getRecordInfos() const diff --git a/oox/source/core/makefile.mk b/oox/source/core/makefile.mk index 6bfbea7a6ff1..3443bd35c7f8 100644 --- a/oox/source/core/makefile.mk +++ b/oox/source/core/makefile.mk @@ -54,11 +54,9 @@ SLOFILES = \ $(SLO)$/filterdetect.obj \ $(SLO)$/fragmenthandler.obj \ $(SLO)$/fragmenthandler2.obj \ - $(SLO)$/modelobjectcontainer.obj \ $(SLO)$/recordparser.obj \ $(SLO)$/relations.obj \ $(SLO)$/relationshandler.obj \ - $(SLO)$/skipcontext.obj \ $(SLO)$/xmlfilterbase.obj # --- Targets ------------------------------------------------------- diff --git a/oox/source/core/relations.cxx b/oox/source/core/relations.cxx index 35b967a402c1..12f880f9f7f7 100644 --- a/oox/source/core/relations.cxx +++ b/oox/source/core/relations.cxx @@ -29,17 +29,36 @@ ************************************************************************/ #include "oox/core/relations.hxx" +#include <rtl/ustrbuf.hxx> #include "oox/helper/helper.hxx" using ::rtl::OUString; +using ::rtl::OUStringBuffer; namespace oox { namespace core { // ============================================================================ -Relations::Relations( const OUString& rBasePath ) : - maBasePath( rBasePath ) +namespace { + +OUString lclRemoveFileName( const OUString& rPath ) +{ + return rPath.copy( 0, ::std::max< sal_Int32 >( rPath.lastIndexOf( '/' ), 0 ) ); +} + +OUString lclAppendFileName( const OUString& rPath, const OUString& rFileName ) +{ + return (rPath.getLength() == 0) ? rFileName : + OUStringBuffer( rPath ).append( sal_Unicode( '/' ) ).append( rFileName ).makeStringAndClear(); +} + +} // namespace + +// ============================================================================ + +Relations::Relations( const OUString& rFragmentPath ) : + maFragmentPath( rFragmentPath ) { } @@ -49,7 +68,7 @@ const Relation* Relations::getRelationFromRelId( const OUString& rId ) const return (aIt == end()) ? 0 : &aIt->second; } -const Relation* Relations::getRelationFromType( const OUString& rType ) const +const Relation* Relations::getRelationFromFirstType( const OUString& rType ) const { for( const_iterator aIt = begin(), aEnd = end(); aIt != aEnd; ++aIt ) if( aIt->second.maType == rType ) @@ -59,77 +78,68 @@ const Relation* Relations::getRelationFromType( const OUString& rType ) const RelationsRef Relations::getRelationsFromType( const OUString& rType ) const { - RelationsRef xRelations( new Relations( maBasePath ) ); + RelationsRef xRelations( new Relations( maFragmentPath ) ); for( const_iterator aIt = begin(), aEnd = end(); aIt != aEnd; ++aIt ) if( aIt->second.maType == rType ) (*xRelations)[ aIt->first ] = aIt->second; return xRelations; } -OUString Relations::getTargetFromRelId( const OUString& rRelId ) const +OUString Relations::getExternalTargetFromRelId( const OUString& rRelId ) const { - if( const Relation* pRelation = getRelationFromRelId( rRelId ) ) - return pRelation->maTarget; - return OUString(); + const Relation* pRelation = getRelationFromRelId( rRelId ); + return (pRelation && pRelation->mbExternal) ? pRelation->maTarget : OUString(); } -OUString Relations::getTargetFromType( const OUString& rType ) const +OUString Relations::getExternalTargetFromFirstType( const OUString& rType ) const { - if( const Relation* pRelation = getRelationFromType( rType ) ) - return pRelation->maTarget; - return OUString(); + const Relation* pRelation = getRelationFromFirstType( rType ); + return (pRelation && pRelation->mbExternal) ? pRelation->maTarget : OUString(); } -OUString Relations::getFragmentPathFromTarget( const OUString& rTarget ) const +OUString Relations::getFragmentPathFromRelation( const Relation& rRelation ) const { - const sal_Unicode cDirSep = '/'; - // no target, no fragment path - if( rTarget.getLength() == 0 ) + if( rRelation.mbExternal || (rRelation.maTarget.getLength() == 0) ) return OUString(); - // absolute target, or empty fragment path -> return target - if( (rTarget[ 0 ] == cDirSep) || (maBasePath.getLength() == 0) ) - return rTarget; - - sal_Int32 nLastSepPos = maBasePath.lastIndexOf( cDirSep ); - OUString aPath = (nLastSepPos < 0) ? maBasePath : maBasePath.copy( 0, nLastSepPos ); + // absolute target: return it without leading slash (#i100978) + if( rRelation.maTarget[ 0 ] == '/' ) + return rRelation.maTarget.copy( 1 ); - const OUString sBack = CREATE_OUSTRING( "../" ); - - // First, count the number of "../"'s found in relative path string. - sal_Int32 nCount = 0, nPos = 0; - while ( true ) - { - nPos = rTarget.indexOf(sBack, nCount*3); - if ( nPos != nCount*3 ) - break; - ++nCount; - } + // empty fragment path: return target + if( maFragmentPath.getLength() == 0 ) + return rRelation.maTarget; - // Now, reduce the base path's directory level by the count. - for ( sal_Int32 i = 0; i < nCount; ++i ) + // resolve relative target path according to base path + OUString aPath = lclRemoveFileName( maFragmentPath ); + sal_Int32 nStartPos = 0; + while( nStartPos < rRelation.maTarget.getLength() ) { - sal_Int32 pos = aPath.lastIndexOf(cDirSep); - if ( pos < 0 ) - // This is unexpected. Bail out. - return rTarget; - aPath = aPath.copy( 0, pos ); + sal_Int32 nSepPos = rRelation.maTarget.indexOf( '/', nStartPos ); + if( nSepPos < 0 ) nSepPos = rRelation.maTarget.getLength(); + // append next directory name from aTarget to aPath, or remove last directory on '../' + if( (nStartPos + 2 == nSepPos) && (rRelation.maTarget[ nStartPos ] == '.') && (rRelation.maTarget[ nStartPos + 1 ] == '.') ) + aPath = lclRemoveFileName( aPath ); + else + aPath = lclAppendFileName( aPath, rRelation.maTarget.copy( nStartPos, nSepPos - nStartPos ) ); + // move nStartPos to next directory name + nStartPos = nSepPos + 1; } - aPath += OUString( cDirSep ); - aPath += rTarget.copy( nCount*3 ); return aPath; } OUString Relations::getFragmentPathFromRelId( const OUString& rRelId ) const { - return getFragmentPathFromTarget( getTargetFromRelId( rRelId ) ); + const Relation* pRelation = getRelationFromRelId( rRelId ); + return pRelation ? getFragmentPathFromRelation( *pRelation ) : OUString(); } -OUString Relations::getFragmentPathFromType( const OUString& rType ) const +OUString Relations::getFragmentPathFromFirstType( const OUString& rType ) const { - return getFragmentPathFromTarget( getTargetFromType( rType ) ); + const Relation* pRelation = getRelationFromFirstType( rType ); + return pRelation ? getFragmentPathFromRelation( *pRelation ) : OUString(); } // ============================================================================ diff --git a/oox/source/core/relationshandler.cxx b/oox/source/core/relationshandler.cxx index 5badd88a24b6..9ca0378cd95f 100644 --- a/oox/source/core/relationshandler.cxx +++ b/oox/source/core/relationshandler.cxx @@ -30,8 +30,9 @@ #include "oox/core/relationshandler.hxx" #include <rtl/ustrbuf.hxx> -#include "oox/core/namespaces.hxx" #include "tokens.hxx" +#include "oox/helper/attributelist.hxx" +#include "oox/core/namespaces.hxx" using ::rtl::OUString; using ::rtl::OUStringBuffer; @@ -45,7 +46,7 @@ namespace core { namespace { -/* Build path to relations file from passed path, e.g.: +/* Build path to relations file from passed fragment path, e.g.: 'path/path/file.xml' -> 'path/path/_rels/file.xml.rels' 'file.xml' -> '_rels/file.xml.rels' '' -> '_rels/.rels' @@ -65,26 +66,36 @@ OUString lclGetRelationsPath( const OUString& rFragmentPath ) // ============================================================================ -RelationsFragmentHandler::RelationsFragmentHandler( XmlFilterBase& rFilter, RelationsRef xRelations ) : - FragmentHandler( rFilter, lclGetRelationsPath( xRelations->getBasePath() ), xRelations ), +RelationsFragment::RelationsFragment( XmlFilterBase& rFilter, RelationsRef xRelations ) : + FragmentHandler( rFilter, lclGetRelationsPath( xRelations->getFragmentPath() ), xRelations ), mxRelations( xRelations ) { } -Reference< XFastContextHandler > RelationsFragmentHandler::createFastChildContext( +Reference< XFastContextHandler > RelationsFragment::createFastChildContext( sal_Int32 nElement, const Reference< XFastAttributeList >& rxAttribs ) throw (SAXException, RuntimeException) { Reference< XFastContextHandler > xRet; + AttributeList aAttribs( rxAttribs ); switch( nElement ) { case NMSP_PACKAGE_RELATIONSHIPS|XML_Relationship: { Relation aRelation; - aRelation.maId = rxAttribs->getOptionalValue( XML_Id ); - aRelation.maType = rxAttribs->getOptionalValue( XML_Type ); - aRelation.maTarget = rxAttribs->getOptionalValue( XML_Target ); + aRelation.maId = aAttribs.getString( XML_Id, OUString() ); + aRelation.maType = aAttribs.getString( XML_Type, OUString() ); + aRelation.maTarget = aAttribs.getString( XML_Target, OUString() ); if( (aRelation.maId.getLength() > 0) && (aRelation.maType.getLength() > 0) && (aRelation.maTarget.getLength() > 0) ) - (*mxRelations)[ aRelation.maId ] = aRelation; + { + sal_Int32 nTargetMode = aAttribs.getToken( XML_TargetMode, XML_Internal ); + OSL_ENSURE( (nTargetMode == XML_Internal) || (nTargetMode == XML_External), + "RelationsFragment::createFastChildContext - unexpected target mode, assuming external" ); + aRelation.mbExternal = nTargetMode != XML_Internal; + + OSL_ENSURE( mxRelations->count( aRelation.maId ) == 0, + "RelationsFragment::createFastChildContext - relation identifier exists already" ); + mxRelations->insert( Relations::value_type( aRelation.maId, aRelation ) ); + } } break; case NMSP_PACKAGE_RELATIONSHIPS|XML_Relationships: diff --git a/oox/source/core/xmlfilterbase.cxx b/oox/source/core/xmlfilterbase.cxx index 12cb8dbe134b..71a2ef874419 100644 --- a/oox/source/core/xmlfilterbase.cxx +++ b/oox/source/core/xmlfilterbase.cxx @@ -29,30 +29,25 @@ ************************************************************************/ #include "oox/core/xmlfilterbase.hxx" -#include <set> #include <stdio.h> #include <rtl/ustrbuf.hxx> -#include <com/sun/star/beans/XPropertySet.hpp> #include <com/sun/star/container/XNameContainer.hpp> -#include <com/sun/star/document/XDocumentSubStorageSupplier.hpp> -#include <com/sun/star/embed/ElementModes.hpp> -#include <com/sun/star/embed/XTransactedObject.hpp> #include <com/sun/star/embed/XRelationshipAccess.hpp> #include <com/sun/star/xml/sax/InputSource.hpp> #include <com/sun/star/xml/sax/XFastParser.hpp> #include <sax/fshelper.hxx> +#include "properties.hxx" #include "oox/helper/containerhelper.hxx" +#include "oox/helper/propertyset.hxx" #include "oox/helper/zipstorage.hxx" #include "oox/core/fasttokenhandler.hxx" #include "oox/core/fragmenthandler.hxx" -#include "oox/core/modelobjectcontainer.hxx" #include "oox/core/namespaces.hxx" #include "oox/core/recordparser.hxx" #include "oox/core/relationshandler.hxx" using ::rtl::OUString; using ::rtl::OUStringBuffer; -using ::com::sun::star::beans::XPropertySet; using ::com::sun::star::beans::StringPair; using ::com::sun::star::uno::Reference; using ::com::sun::star::uno::Sequence; @@ -60,16 +55,14 @@ using ::com::sun::star::uno::Exception; using ::com::sun::star::uno::RuntimeException; using ::com::sun::star::uno::UNO_QUERY; using ::com::sun::star::uno::UNO_QUERY_THROW; -using ::com::sun::star::uno::makeAny; +using ::com::sun::star::uno::UNO_SET_THROW; using ::com::sun::star::lang::XMultiServiceFactory; using ::com::sun::star::embed::XRelationshipAccess; using ::com::sun::star::embed::XStorage; -using ::com::sun::star::embed::XTransactedObject; using ::com::sun::star::io::XInputStream; using ::com::sun::star::io::XOutputStream; using ::com::sun::star::io::XStream; using ::com::sun::star::container::XNameContainer; -using ::com::sun::star::document::XDocumentSubStorageSupplier; using ::com::sun::star::xml::sax::XFastParser; using ::com::sun::star::xml::sax::XFastTokenHandler; using ::com::sun::star::xml::sax::XFastDocumentHandler; @@ -91,11 +84,7 @@ struct XmlFilterBaseImpl Reference< XFastTokenHandler > mxTokenHandler; RelationsMap maRelationsMap; - ::std::set< OUString > maPictureSet; /// Already copied picture stream names. - Reference< XStorage > mxPictureStorage; /// Target model picture storage. - ::boost::shared_ptr< ModelObjectContainer > - mxObjContainer; /// Tables to create new named drawing objects. - + TextFieldStack maTextFieldStack; explicit XmlFilterBaseImpl(); }; @@ -109,8 +98,8 @@ XmlFilterBaseImpl::XmlFilterBaseImpl() : // ============================================================================ -XmlFilterBase::XmlFilterBase( const Reference< XMultiServiceFactory >& rxFactory ) : - FilterBase( rxFactory ), +XmlFilterBase::XmlFilterBase( const Reference< XMultiServiceFactory >& rxGlobalFactory ) : + FilterBase( rxGlobalFactory ), mxImpl( new XmlFilterBaseImpl ), mnRelId( 1 ), mnMaxDocId( 0 ) @@ -123,9 +112,10 @@ XmlFilterBase::~XmlFilterBase() // ---------------------------------------------------------------------------- -OUString XmlFilterBase::getFragmentPathFromType( const OUString& rType ) +OUString XmlFilterBase::getFragmentPathFromFirstType( const OUString& rType ) { - return importRelations( OUString() )->getTargetFromType( rType ); + // importRelations() caches the relations map for subsequence calls + return importRelations( OUString() )->getFragmentPathFromFirstType( rType ); } bool XmlFilterBase::importFragment( const ::rtl::Reference< FragmentHandler >& rxHandler ) @@ -140,17 +130,15 @@ bool XmlFilterBase::importFragment( const ::rtl::Reference< FragmentHandler >& r if( aFragmentPath.getLength() == 0 ) return false; - // try to open the fragment stream (this may fail - do not assert) - Reference< XInputStream > xInStrm = openInputStream( aFragmentPath ); - if( !xInStrm.is() ) - return false; - // try to import binary streams (fragment extension must be '.bin') sal_Int32 nBinSuffixPos = aFragmentPath.getLength() - mxImpl->maBinSuffix.getLength(); if( (nBinSuffixPos >= 0) && aFragmentPath.match( mxImpl->maBinSuffix, nBinSuffixPos ) ) { try { + // try to open the fragment stream (this may fail - do not assert) + Reference< XInputStream > xInStrm( openInputStream( aFragmentPath ), UNO_SET_THROW ); + // create the record parser RecordParser aParser; aParser.setFragmentHandler( rxHandler ); @@ -176,6 +164,9 @@ bool XmlFilterBase::importFragment( const ::rtl::Reference< FragmentHandler >& r // try to import XML stream try { + // try to open the fragment stream (this may fail - do not assert) + Reference< XInputStream > xInStrm( rxHandler->openFragmentStream(), UNO_SET_THROW ); + // create the fast parser Reference< XFastParser > xParser( getGlobalFactory()->createInstance( CREATE_OUSTRING( "com.sun.star.xml.sax.FastParser" ) ), UNO_QUERY_THROW ); @@ -226,144 +217,90 @@ RelationsRef XmlFilterBase::importRelations( const OUString& rFragmentPath ) { // import and cache relations rxRelations.reset( new Relations( rFragmentPath ) ); - importFragment( new RelationsFragmentHandler( *this, rxRelations ) ); + importFragment( new RelationsFragment( *this, rxRelations ) ); } return rxRelations; } -OUString XmlFilterBase::copyPictureStream( const OUString& rPicturePath ) -{ - // split source path into source storage path and stream name - sal_Int32 nIndex = rPicturePath.lastIndexOf( sal_Unicode( '/' ) ); - OUString sPictureName; - OUString sSourceStorageName; - if( nIndex < 0 ) - { - // root stream - sPictureName = rPicturePath; - } - else - { - // sub stream - sPictureName = rPicturePath.copy( nIndex + 1 ); - sSourceStorageName = rPicturePath.copy( 0, nIndex ); - } - - // check if we already copied this one! - if( mxImpl->maPictureSet.find( rPicturePath ) == mxImpl->maPictureSet.end() ) try - { - // ok, not yet, copy stream to documents picture storage - - // first get the picture storage from our target model - if( !mxImpl->mxPictureStorage.is() ) - { - static const OUString sPictures = CREATE_OUSTRING( "Pictures" ); - Reference< XDocumentSubStorageSupplier > xDSSS( getModel(), UNO_QUERY_THROW ); - mxImpl->mxPictureStorage.set( xDSSS->getDocumentSubStorage( - sPictures, ::com::sun::star::embed::ElementModes::WRITE ), UNO_QUERY_THROW ); - } - - StorageRef xSourceStorage = openSubStorage( sSourceStorageName, false ); - if( xSourceStorage.get() ) - { - Reference< XStorage > xSourceXStorage = xSourceStorage->getXStorage(); - if( xSourceXStorage.is() ) - { - xSourceXStorage->copyElementTo( sPictureName, mxImpl->mxPictureStorage, sPictureName ); - Reference< XTransactedObject > xTO( mxImpl->mxPictureStorage, UNO_QUERY_THROW ); - xTO->commit(); - } - } - } - catch( Exception& ) - { - } - - static const OUString sUrlPrefix = CREATE_OUSTRING( "vnd.sun.star.Package:Pictures/" ); - return sUrlPrefix + sPictureName; -} - -ModelObjectContainer& XmlFilterBase::getModelObjectContainer() const +Reference< XOutputStream > XmlFilterBase::openFragmentStream( const OUString& rStreamName, const OUString& rMediaType ) { - if( !mxImpl->mxObjContainer ) - mxImpl->mxObjContainer.reset( new ModelObjectContainer( getModel() ) ); - return *mxImpl->mxObjContainer; + Reference< XOutputStream > xOutputStream = openOutputStream( rStreamName ); + PropertySet aPropSet( xOutputStream ); + aPropSet.setProperty( PROP_MediaType, rMediaType ); + return xOutputStream; } -StorageRef XmlFilterBase::implCreateStorage( - Reference< XInputStream >& rxInStream, Reference< XStream >& rxStream ) const +FSHelperPtr XmlFilterBase::openFragmentStreamWithSerializer( const OUString& rStreamName, const OUString& rMediaType ) { - StorageRef xStorage; - if( rxInStream.is() ) - xStorage.reset( new ZipStorage( getGlobalFactory(), rxInStream ) ); - else if( rxStream.is() ) - xStorage.reset( new ZipStorage( getGlobalFactory(), rxStream ) ); - - return xStorage; + return FSHelperPtr( new FastSerializerHelper( openFragmentStream( rStreamName, rMediaType ) ) ); } -Reference< XOutputStream > XmlFilterBase::openOutputStream( const OUString& rStreamName, const OUString& rMediaType ) +TextFieldStack& XmlFilterBase::getTextFieldStack() const { - Reference< XOutputStream > xOutputStream = FilterBase::openOutputStream( rStreamName ); - Reference< XPropertySet > xPropSet( xOutputStream, UNO_QUERY_THROW ); - - if( xPropSet.is() ) - xPropSet->setPropertyValue( CREATE_OUSTRING( "MediaType" ), - makeAny( rMediaType ) ); - - return xOutputStream; + return mxImpl->maTextFieldStack; } -FSHelperPtr XmlFilterBase::openOutputStreamWithSerializer( const OUString& rStreamName, const OUString& rMediaType ) -{ - return FSHelperPtr( new FastSerializerHelper ( openOutputStream( rStreamName, rMediaType ) ) ); -} +namespace { -static OUString addRelation_impl( const Reference< XRelationshipAccess > xRelations, sal_Int32 nId, const OUString& rType, const OUString& rTarget, const OUString& rTargetMode ) +OUString lclAddRelation( const Reference< XRelationshipAccess > xRelations, sal_Int32 nId, const OUString& rType, const OUString& rTarget, bool bExternal ) { OUString sId = OUStringBuffer().appendAscii( "rId" ).append( nId ).makeStringAndClear(); - Sequence< StringPair > aEntry( rTargetMode.getLength() > 0 ? 3 : 2 ); + Sequence< StringPair > aEntry( bExternal ? 3 : 2 ); aEntry[0].First = CREATE_OUSTRING( "Type" ); aEntry[0].Second = rType; aEntry[1].First = CREATE_OUSTRING( "Target" ); aEntry[1].Second = rTarget; - if( rTargetMode.getLength() > 0 ) + if( bExternal ) { aEntry[2].First = CREATE_OUSTRING( "TargetMode" ); - aEntry[2].Second = rTargetMode; + aEntry[2].Second = CREATE_OUSTRING( "External" ); } - xRelations->insertRelationshipByID( sId, aEntry, true ); + xRelations->insertRelationshipByID( sId, aEntry, sal_True ); return sId; } -OUString XmlFilterBase::addRelation( const OUString& rType, const OUString& rTarget, const OUString& rTargetMode ) +} // namespace + +OUString XmlFilterBase::addRelation( const OUString& rType, const OUString& rTarget, bool bExternal ) { Reference< XRelationshipAccess > xRelations( getStorage()->getXStorage(), UNO_QUERY ); if( xRelations.is() ) - return addRelation_impl( xRelations, mnRelId ++, rType, rTarget, rTargetMode ); + return lclAddRelation( xRelations, mnRelId ++, rType, rTarget, bExternal ); return OUString(); } -OUString XmlFilterBase::addRelation( const Reference< XOutputStream > xOutputStream, const OUString& rType, const OUString& rTarget, const OUString& rTargetMode ) +OUString XmlFilterBase::addRelation( const Reference< XOutputStream > xOutputStream, const OUString& rType, const OUString& rTarget, bool bExternal ) { sal_Int32 nId = 0; - Reference< XPropertySet > xPropertySet( xOutputStream, UNO_QUERY ); - if( xPropertySet.is() ) - xPropertySet->getPropertyValue( CREATE_OUSTRING( "RelId" ) ) >>= nId; + PropertySet aPropSet( xOutputStream ); + if( aPropSet.is() ) + aPropSet.getProperty( nId, PROP_RelId ); else - nId = mnRelId ++; + nId = mnRelId++; Reference< XRelationshipAccess > xRelations( xOutputStream, UNO_QUERY ); if( xRelations.is() ) - return addRelation_impl( xRelations, nId, rType, rTarget, rTargetMode ); + return lclAddRelation( xRelations, nId, rType, rTarget, bExternal ); return OUString(); } +StorageRef XmlFilterBase::implCreateStorage( + Reference< XInputStream >& rxInStream, Reference< XStream >& rxOutStream ) const +{ + StorageRef xStorage; + if( rxInStream.is() ) + xStorage.reset( new ZipStorage( getGlobalFactory(), rxInStream ) ); + else if( rxOutStream.is() ) + xStorage.reset( new ZipStorage( getGlobalFactory(), rxOutStream ) ); + + return xStorage; +} + // ============================================================================ } // namespace core diff --git a/oox/source/docprop/docprophandler.cxx b/oox/source/docprop/docprophandler.cxx index db11f3e4435b..185a061acea4 100644 --- a/oox/source/docprop/docprophandler.cxx +++ b/oox/source/docprop/docprophandler.cxx @@ -28,16 +28,17 @@ * ************************************************************************/ +#include "docprophandler.hxx" + #include <com/sun/star/beans/PropertyAttribute.hpp> #include <com/sun/star/beans/PropertyExistException.hpp> #include <com/sun/star/lang/Locale.hpp> #include <osl/time.h> -#include <tokens.hxx> -#include <oox/core/namespaces.hxx> - -#include "docprophandler.hxx" +#include "tokens.hxx" +#include "oox/helper/attributelist.hxx" +#include "oox/core/namespaces.hxx" using namespace ::com::sun::star; @@ -159,7 +160,7 @@ util::DateTime OOXMLDocPropHandler::GetDateTimeFromW3CDTF( const ::rtl::OUString } } - return util::DateTime( (sal_uInt16)( aOslDTime.NanoSeconds / 10e7 ), aOslDTime.Seconds, aOslDTime.Minutes, aOslDTime.Hours, aOslDTime.Day, aOslDTime.Month, aOslDTime.Year ); + return util::DateTime( (sal_uInt16)( aOslDTime.NanoSeconds / 1e7 ), aOslDTime.Seconds, aOslDTime.Minutes, aOslDTime.Hours, aOslDTime.Day, aOslDTime.Month, aOslDTime.Year ); } // ------------------------------------------------ @@ -271,59 +272,6 @@ void OOXMLDocPropHandler::UpdateDocStatistic( const ::rtl::OUString& aChars ) } // ------------------------------------------------ -sal_Bool OOXMLDocPropHandler::Is16Digit( sal_Unicode cSign ) -{ - return ( (cSign >= (sal_Unicode)'0' && cSign <= (sal_Unicode)'9') - || (cSign >= (sal_Unicode)'a' && cSign <= (sal_Unicode)'f') - || (cSign >= (sal_Unicode)'A' && cSign <= (sal_Unicode)'F') ); -} - -// ------------------------------------------------ -::rtl::OUString OOXMLDocPropHandler::Decode_xHHHH_( const ::rtl::OUString& aChars ) -{ - ::rtl::OUString aResult; - - ::rtl::OUString aPrefix( RTL_CONSTASCII_USTRINGPARAM( "_x" ) ); - sal_Int32 nStartIndex = 0; - - do - { - sal_Int32 nIndex = aChars.indexOf( aPrefix, nStartIndex ); - if ( nIndex > nStartIndex && nIndex < aChars.getLength() ) - { - aResult += aChars.copy( nStartIndex, nIndex - nStartIndex ); - if ( aChars.getLength() - nIndex >= 7 - && Is16Digit( aChars.getStr()[nIndex + 2] ) - && Is16Digit( aChars.getStr()[nIndex + 3] ) - && Is16Digit( aChars.getStr()[nIndex + 4] ) - && Is16Digit( aChars.getStr()[nIndex + 5] ) - && aChars.getStr()[nIndex + 6] == (sal_Unicode)'_' ) - { - aResult += ::rtl::OUString( (sal_Unicode)aChars.copy( nIndex + 2, 4 ).toInt32( 16 ) ); - nStartIndex = nIndex + 7; - } - else - { - aResult += aChars.copy( nIndex, 2 ); - nStartIndex = nIndex + 2; - } - } - else if ( nIndex == -1 ) - { - aResult += aChars.copy( nStartIndex ); - nStartIndex = -1; - } - else - { - OSL_ASSERT( "Unexpecte string behavior!" ); - nStartIndex = -1; - } - } - while( nStartIndex >= 0 && nStartIndex < aChars.getLength() ); - - return aResult; -} - // com.sun.star.xml.sax.XFastDocumentHandler // ------------------------------------------------ void SAL_CALL OOXMLDocPropHandler::startDocument() @@ -453,7 +401,7 @@ void SAL_CALL OOXMLDocPropHandler::characters( const ::rtl::OUString& aChars ) { try { - if ( m_nInBlock == 2 || m_nInBlock == 3 && m_nType ) + if ( (m_nInBlock == 2) || ((m_nInBlock == 3) && m_nType) ) { if ( m_nState == ( XML_coreProperties|NMSP_COREPR ) ) { @@ -671,7 +619,7 @@ void SAL_CALL OOXMLDocPropHandler::characters( const ::rtl::OUString& aChars ) case XML_bstr|NMSP_VT: case XML_lpstr|NMSP_VT: case XML_lpwstr|NMSP_VT: - AddCustomProperty( uno::makeAny( Decode_xHHHH_( aChars ) ) ); // the property has string type + AddCustomProperty( uno::makeAny( AttributeList::decodeXString( aChars ) ) ); // the property has string type break; case XML_date|NMSP_VT: diff --git a/oox/source/docprop/docprophandler.hxx b/oox/source/docprop/docprophandler.hxx index fc1d008e2c09..3ea2f99e0bd4 100644 --- a/oox/source/docprop/docprophandler.hxx +++ b/oox/source/docprop/docprophandler.hxx @@ -65,9 +65,6 @@ public: ::com::sun::star::uno::Sequence< ::rtl::OUString > GetKeywordsSet( const ::rtl::OUString& aChars ); ::com::sun::star::lang::Locale GetLanguage( const ::rtl::OUString& aChars ); void UpdateDocStatistic( const ::rtl::OUString& aChars ); - sal_Bool Is16Digit( sal_Unicode cSign ); - ::rtl::OUString Decode_xHHHH_( const ::rtl::OUString& aChars ); - // com.sun.star.xml.sax.XFastDocumentHandler diff --git a/oox/source/drawingml/chart/objectformatter.cxx b/oox/source/drawingml/chart/objectformatter.cxx index 36e245d6bb6b..6ddb72bd3040 100644 --- a/oox/source/drawingml/chart/objectformatter.cxx +++ b/oox/source/drawingml/chart/objectformatter.cxx @@ -34,7 +34,9 @@ #include <osl/thread.h> #include <com/sun/star/util/XNumberFormatsSupplier.hpp> #include <com/sun/star/util/XNumberFormatTypes.hpp> -#include "oox/core/modelobjectcontainer.hxx" +#include "properties.hxx" +#include "tokens.hxx" +#include "oox/helper/modelobjecthelper.hxx" #include "oox/core/xmlfilterbase.hxx" #include "oox/drawingml/fillproperties.hxx" #include "oox/drawingml/lineproperties.hxx" @@ -42,8 +44,6 @@ #include "oox/drawingml/textparagraph.hxx" #include "oox/drawingml/theme.hxx" #include "oox/drawingml/chart/chartspacemodel.hxx" -#include "properties.hxx" -#include "tokens.hxx" using ::rtl::OStringBuffer; using ::rtl::OUString; @@ -61,7 +61,6 @@ using ::com::sun::star::graphic::XGraphic; using ::com::sun::star::util::XNumberFormats; using ::com::sun::star::util::XNumberFormatsSupplier; using ::com::sun::star::util::XNumberFormatTypes; -using ::oox::core::ModelObjectContainer; using ::oox::core::XmlFilterBase; namespace oox { @@ -558,6 +557,13 @@ static const ObjectTypeFormatEntry spObjTypeFormatEntries[] = #undef TYPEFORMAT_FRAME #undef TYPEFORMAT_LINE +// ---------------------------------------------------------------------------- + +void lclConvertPictureOptions( FillProperties& orFillProps, const PictureOptionsModel& rPicOptions ) +{ + bool bStacked = (rPicOptions.mnPictureFormat == XML_stack) || (rPicOptions.mnPictureFormat == XML_stackScale); + orFillProps.maBlipProps.moBitmapMode = bStacked ? XML_tile : XML_stretch; +} // ---------------------------------------------------------------------------- @@ -565,8 +571,8 @@ const sal_Int32 spnCommonLineIds[ LineId_END ] = { PROP_LineStyle, PROP_LineWi const sal_Int32 spnLinearLineIds[ LineId_END ] = { PROP_LineStyle, PROP_LineWidth, PROP_Color, PROP_Transparency, PROP_LineDashName, PROP_INVALID, PROP_INVALID, PROP_INVALID, PROP_INVALID, PROP_INVALID, PROP_INVALID, PROP_INVALID }; const sal_Int32 spnFilledLineIds[ LineId_END ] = { PROP_BorderStyle, PROP_BorderWidth, PROP_BorderColor, PROP_BorderTransparency, PROP_BorderDashName, PROP_INVALID, PROP_INVALID, PROP_INVALID, PROP_INVALID, PROP_INVALID, PROP_INVALID, PROP_INVALID }; -const sal_Int32 spnCommonFillIds[ FillId_END ] = { PROP_FillStyle, PROP_FillColor, PROP_FillTransparence, PROP_FillGradientName, PROP_FillBitmapName, PROP_FillBitmapMode, PROP_INVALID, PROP_INVALID, PROP_INVALID, PROP_INVALID, PROP_INVALID, PROP_INVALID, PROP_INVALID, PROP_INVALID }; -const sal_Int32 spnFilledFillIds[ FillId_END ] = { PROP_FillStyle, PROP_Color, PROP_Transparency, PROP_GradientName, PROP_FillBitmapName, PROP_FillBitmapMode, PROP_INVALID, PROP_INVALID, PROP_INVALID, PROP_INVALID, PROP_INVALID, PROP_INVALID, PROP_INVALID, PROP_INVALID }; +const sal_Int32 spnCommonFillIds[ FillId_END ] = { PROP_FillStyle, PROP_FillColor, PROP_FillTransparence, PROP_FillGradientName, PROP_FillBitmapName, PROP_FillBitmapMode, PROP_FillBitmapSizeX, PROP_FillBitmapSizeY, PROP_FillBitmapPositionOffsetX, PROP_FillBitmapPositionOffsetY, PROP_FillBitmapRectanglePoint }; +const sal_Int32 spnFilledFillIds[ FillId_END ] = { PROP_FillStyle, PROP_Color, PROP_Transparency, PROP_GradientName, PROP_FillBitmapName, PROP_FillBitmapMode, PROP_FillBitmapSizeX, PROP_FillBitmapSizeY, PROP_FillBitmapPositionOffsetX, PROP_FillBitmapPositionOffsetY, PROP_FillBitmapRectanglePoint }; } // namespace @@ -637,6 +643,7 @@ public: void convertFormatting( PropertySet& rPropSet, const ModelRef< Shape >& rxShapeProp, + const PictureOptionsModel* pPicOptions, sal_Int32 nSeriesIdx ); private: @@ -699,6 +706,7 @@ public: void convertFrameFormatting( PropertySet& rPropSet, const ModelRef< Shape >& rxShapeProp, + const PictureOptionsModel* pPicOptions, sal_Int32 nSeriesIdx ); /** Sets text formatting properties to the passed property set. */ @@ -731,7 +739,7 @@ private: LineFormatter maLineFormatter; /// Converter for line formatting. FillFormatter maFillFormatter; /// Converter for fill formatting. EffectFormatter maEffectFormatter; /// Converter for effect formatting. - TextFormatter maTextFormatter; /// Converter for effect formatting. + TextFormatter maTextFormatter; /// Converter for text formatting. const ObjectTypeFormatEntry& mrEntry; /// Additional settings. }; @@ -743,7 +751,7 @@ struct ObjectFormatterData const XmlFilterBase& mrFilter; /// Base filter object. ObjectTypeFormatterMap maTypeFormatters; /// Formatters for all types of objects in a chart. - ModelObjectContainer maObjContainer; /// Container for named drawing formatting (dashes, gradients, bitmaps). + ModelObjectHelper maModelObjHelper; /// Helper for named drawing formatting (dashes, gradients, bitmaps). LinePropertyIds maCommonLineIds; /// Property identifiers for common border formatting. LinePropertyIds maLinearLineIds; /// Property identifiers for line formatting of linear series. LinePropertyIds maFilledLineIds; /// Property identifiers for line formatting of filled series. @@ -884,7 +892,7 @@ void LineFormatter::convertFormatting( PropertySet& rPropSet, const ModelRef< Sh aLineProps.assignUsed( *mxAutoLine ); if( rxShapeProp.is() ) aLineProps.assignUsed( rxShapeProp->getLineProperties() ); - aLineProps.pushToPropSet( rPropSet, mrLinePropIds, mrData.mrFilter, mrData.maObjContainer, getPhColor( nSeriesIdx ) ); + aLineProps.pushToPropSet( rPropSet, mrLinePropIds, mrData.mrFilter, mrData.maModelObjHelper, getPhColor( nSeriesIdx ) ); } // ============================================================================ @@ -903,14 +911,16 @@ FillFormatter::FillFormatter( ObjectFormatterData& rData, const AutoFormatEntry* } } -void FillFormatter::convertFormatting( PropertySet& rPropSet, const ModelRef< Shape >& rxShapeProp, sal_Int32 nSeriesIdx ) +void FillFormatter::convertFormatting( PropertySet& rPropSet, const ModelRef< Shape >& rxShapeProp, const PictureOptionsModel* pPicOptions, sal_Int32 nSeriesIdx ) { FillProperties aFillProps; if( mxAutoFill.get() ) aFillProps.assignUsed( *mxAutoFill ); if( rxShapeProp.is() ) aFillProps.assignUsed( rxShapeProp->getFillProperties() ); - aFillProps.pushToPropSet( rPropSet, mrFillPropIds, mrData.mrFilter, mrData.maObjContainer, 0, getPhColor( nSeriesIdx ) ); + if( pPicOptions ) + lclConvertPictureOptions( aFillProps, *pPicOptions ); + aFillProps.pushToPropSet( rPropSet, mrFillPropIds, mrData.mrFilter, mrData.maModelObjHelper, 0, getPhColor( nSeriesIdx ) ); } // ============================================================================ @@ -986,11 +996,11 @@ ObjectTypeFormatter::ObjectTypeFormatter( ObjectFormatterData& rData, const Obje { } -void ObjectTypeFormatter::convertFrameFormatting( PropertySet& rPropSet, const ModelRef< Shape >& rxShapeProp, sal_Int32 nSeriesIdx ) +void ObjectTypeFormatter::convertFrameFormatting( PropertySet& rPropSet, const ModelRef< Shape >& rxShapeProp, const PictureOptionsModel* pPicOptions, sal_Int32 nSeriesIdx ) { maLineFormatter.convertFormatting( rPropSet, rxShapeProp, nSeriesIdx ); if( mrEntry.mbIsFrame ) - maFillFormatter.convertFormatting( rPropSet, rxShapeProp, nSeriesIdx ); + maFillFormatter.convertFormatting( rPropSet, rxShapeProp, pPicOptions, nSeriesIdx ); maEffectFormatter.convertFormatting( rPropSet, rxShapeProp, nSeriesIdx ); } @@ -1001,7 +1011,7 @@ void ObjectTypeFormatter::convertTextFormatting( PropertySet& rPropSet, const Mo void ObjectTypeFormatter::convertFormatting( PropertySet& rPropSet, const ModelRef< Shape >& rxShapeProp, const ModelRef< TextBody >& rxTextProp ) { - convertFrameFormatting( rPropSet, rxShapeProp, -1 ); + convertFrameFormatting( rPropSet, rxShapeProp, 0, -1 ); convertTextFormatting( rPropSet, rxTextProp ); } @@ -1020,7 +1030,7 @@ void ObjectTypeFormatter::convertAutomaticLine( PropertySet& rPropSet, sal_Int32 void ObjectTypeFormatter::convertAutomaticFill( PropertySet& rPropSet, sal_Int32 nSeriesIdx ) { ModelRef< Shape > xShapeProp; - maFillFormatter.convertFormatting( rPropSet, xShapeProp, nSeriesIdx ); + maFillFormatter.convertFormatting( rPropSet, xShapeProp, 0, nSeriesIdx ); maEffectFormatter.convertFormatting( rPropSet, xShapeProp, nSeriesIdx ); } @@ -1028,12 +1038,12 @@ void ObjectTypeFormatter::convertAutomaticFill( PropertySet& rPropSet, sal_Int32 ObjectFormatterData::ObjectFormatterData( const XmlFilterBase& rFilter, const Reference< XChartDocument >& rxChartDoc, const ChartSpaceModel& rChartSpace ) : mrFilter( rFilter ), - maObjContainer( Reference< XModel >( rxChartDoc, UNO_QUERY ) ), + maModelObjHelper( Reference< XMultiServiceFactory >( rxChartDoc, UNO_QUERY ) ), maCommonLineIds( spnCommonLineIds, true, false ), maLinearLineIds( spnLinearLineIds, true, false ), maFilledLineIds( spnFilledLineIds, true, false ), - maCommonFillIds( spnCommonFillIds, true, true, false ), - maFilledFillIds( spnFilledFillIds, true, true, false ), + maCommonFillIds( spnCommonFillIds, true, true ), + maFilledFillIds( spnFilledFillIds, true, true ), maEnUsLocale( CREATE_OUSTRING( "en" ), CREATE_OUSTRING( "US" ), OUString() ), mnMaxSeriesIdx( -1 ) { @@ -1105,7 +1115,13 @@ sal_Int32 ObjectFormatter::getMaxSeriesIndex() const void ObjectFormatter::convertFrameFormatting( PropertySet& rPropSet, const ModelRef< Shape >& rxShapeProp, ObjectType eObjType, sal_Int32 nSeriesIdx ) { if( ObjectTypeFormatter* pFormat = mxData->getTypeFormatter( eObjType ) ) - pFormat->convertFrameFormatting( rPropSet, rxShapeProp, nSeriesIdx ); + pFormat->convertFrameFormatting( rPropSet, rxShapeProp, 0, nSeriesIdx ); +} + +void ObjectFormatter::convertFrameFormatting( PropertySet& rPropSet, const ModelRef< Shape >& rxShapeProp, const PictureOptionsModel& rPicOptions, ObjectType eObjType, sal_Int32 nSeriesIdx ) +{ + if( ObjectTypeFormatter* pFormat = mxData->getTypeFormatter( eObjType ) ) + pFormat->convertFrameFormatting( rPropSet, rxShapeProp, &rPicOptions, nSeriesIdx ); } void ObjectFormatter::convertTextFormatting( PropertySet& rPropSet, const ModelRef< TextBody >& rxTextProp, ObjectType eObjType ) diff --git a/oox/source/drawingml/chart/plotareacontext.cxx b/oox/source/drawingml/chart/plotareacontext.cxx index 789b341cccf0..954b7e1e448b 100644 --- a/oox/source/drawingml/chart/plotareacontext.cxx +++ b/oox/source/drawingml/chart/plotareacontext.cxx @@ -32,6 +32,7 @@ #include "oox/drawingml/shapepropertiescontext.hxx" #include "oox/drawingml/chart/axiscontext.hxx" #include "oox/drawingml/chart/plotareamodel.hxx" +#include "oox/drawingml/chart/seriescontext.hxx" #include "oox/drawingml/chart/titlecontext.hxx" #include "oox/drawingml/chart/typegroupcontext.hxx" @@ -107,6 +108,8 @@ ContextHandlerRef WallFloorContext::onCreateContext( sal_Int32 nElement, const A case C_TOKEN( sideWall ): switch( nElement ) { + case C_TOKEN( pictureOptions ): + return new PictureOptionsContext( *this, mrModel.mxPicOptions.create() ); case C_TOKEN( spPr ): return new ShapePropertiesContext( *this, mrModel.mxShapeProp.create() ); } diff --git a/oox/source/drawingml/chart/plotareaconverter.cxx b/oox/source/drawingml/chart/plotareaconverter.cxx index 3b29490853b7..b4345af3f088 100644 --- a/oox/source/drawingml/chart/plotareaconverter.cxx +++ b/oox/source/drawingml/chart/plotareaconverter.cxx @@ -299,7 +299,7 @@ void WallFloorConverter::convertFromModel( const Reference< XDiagram >& rxDiagra default: OSL_ENSURE( false, "WallFloorConverter::convertFromModel - invalid object type" ); } if( aPropSet.is() ) - getFormatter().convertFrameFormatting( aPropSet, mrModel.mxShapeProp, eObjType ); + getFormatter().convertFrameFormatting( aPropSet, mrModel.mxShapeProp, mrModel.mxPicOptions.getOrCreate(), eObjType ); } } diff --git a/oox/source/drawingml/chart/seriescontext.cxx b/oox/source/drawingml/chart/seriescontext.cxx index 6367247cf9c0..a52c5fb4182c 100644 --- a/oox/source/drawingml/chart/seriescontext.cxx +++ b/oox/source/drawingml/chart/seriescontext.cxx @@ -169,6 +169,43 @@ void DataLabelsContext::onEndElement( const OUString& rChars ) // ============================================================================ +PictureOptionsContext::PictureOptionsContext( ContextHandler2Helper& rParent, PictureOptionsModel& rModel ) : + ContextBase< PictureOptionsModel >( rParent, rModel ) +{ +} + +PictureOptionsContext::~PictureOptionsContext() +{ +} + +ContextHandlerRef PictureOptionsContext::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs ) +{ + if( isRootElement() ) switch( nElement ) + { + case C_TOKEN( applyToEnd ): + // default is 'false', not 'true' as specified + mrModel.mbApplyToEnd = rAttribs.getBool( XML_val, false ); + return 0; + case C_TOKEN( applyToFront ): + // default is 'false', not 'true' as specified + mrModel.mbApplyToFront = rAttribs.getBool( XML_val, false ); + return 0; + case C_TOKEN( applyToSides ): + // default is 'false', not 'true' as specified + mrModel.mbApplyToSides = rAttribs.getBool( XML_val, false ); + return 0; + case C_TOKEN( pictureFormat ): + mrModel.mnPictureFormat = rAttribs.getToken( XML_val, XML_stretch ); + return 0; + case C_TOKEN( pictureStackUnit ): + mrModel.mfStackUnit = rAttribs.getDouble( XML_val, 1.0 ); + return 0; + } + return 0; +} + +// ============================================================================ + ErrorBarContext::ErrorBarContext( ContextHandler2Helper& rParent, ErrorBarModel& rModel ) : ContextBase< ErrorBarModel >( rParent, rModel ) { @@ -333,6 +370,8 @@ ContextHandlerRef DataPointContext::onCreateContext( sal_Int32 nElement, const A return 0; case C_TOKEN( marker ): return this; + case C_TOKEN( pictureOptions ): + return new PictureOptionsContext( *this, mrModel.mxPicOptions.create() ); case C_TOKEN( spPr ): return new ShapePropertiesContext( *this, mrModel.mxShapeProp.create() ); } @@ -469,6 +508,8 @@ ContextHandlerRef BarSeriesContext::onCreateContext( sal_Int32 nElement, const A // default is 'false', not 'true' as specified mrModel.mbInvertNeg = rAttribs.getBool( XML_val, false ); return 0; + case C_TOKEN( pictureOptions ): + return new PictureOptionsContext( *this, mrModel.mxPicOptions.create() ); case C_TOKEN( shape ): // missing attribute does not change shape type to 'box' as specified mrModel.monShape = rAttribs.getToken( XML_val ); diff --git a/oox/source/drawingml/chart/seriesconverter.cxx b/oox/source/drawingml/chart/seriesconverter.cxx index 9806dde43437..1c9931ae6177 100644 --- a/oox/source/drawingml/chart/seriesconverter.cxx +++ b/oox/source/drawingml/chart/seriesconverter.cxx @@ -434,7 +434,12 @@ void DataPointConverter::convertFromModel( const Reference< XDataSeries >& rxDat // point formatting if( mrModel.mxShapeProp.is() ) - getFormatter().convertFrameFormatting( aPropSet, mrModel.mxShapeProp, rTypeGroup.getSeriesObjectType(), rSeries.mnIndex ); + { + if( rTypeGroup.getTypeInfo().mbPictureOptions ) + getFormatter().convertFrameFormatting( aPropSet, mrModel.mxShapeProp, mrModel.mxPicOptions.getOrCreate(), rTypeGroup.getSeriesObjectType(), rSeries.mnIndex ); + else + getFormatter().convertFrameFormatting( aPropSet, mrModel.mxShapeProp, rTypeGroup.getSeriesObjectType(), rSeries.mnIndex ); + } } catch( Exception& ) { @@ -492,6 +497,13 @@ Reference< XDataSeries > SeriesConverter::createDataSeries( const TypeGroupConve Reference< XLabeledDataSequence > xXValueSeq = createCategorySequence( CREATE_OUSTRING( "values-x" ) ); if( xXValueSeq.is() ) aLabeledSeqVec.push_back( xXValueSeq ); + // add size values of bubble charts + if( rTypeInfo.meTypeId == TYPEID_BUBBLE ) + { + Reference< XLabeledDataSequence > xSizeValueSeq = createLabeledDataSequence( SeriesModel::POINTS, CREATE_OUSTRING( "values-size" ), true ); + if( xSizeValueSeq.is() ) + aLabeledSeqVec.push_back( xSizeValueSeq ); + } } // attach labeled data sequences to series if( !aLabeledSeqVec.empty() ) @@ -526,7 +538,10 @@ Reference< XDataSeries > SeriesConverter::createDataSeries( const TypeGroupConve // series formatting ObjectFormatter& rFormatter = getFormatter(); ObjectType eObjType = rTypeGroup.getSeriesObjectType(); - rFormatter.convertFrameFormatting( aSeriesProp, mrModel.mxShapeProp, eObjType, mrModel.mnIndex ); + if( rTypeInfo.mbPictureOptions ) + rFormatter.convertFrameFormatting( aSeriesProp, mrModel.mxShapeProp, mrModel.mxPicOptions.getOrCreate(), eObjType, mrModel.mnIndex ); + else + rFormatter.convertFrameFormatting( aSeriesProp, mrModel.mxShapeProp, eObjType, mrModel.mnIndex ); // set the (unused) property default value used by the Chart2 templates (true for pie/doughnut charts) bool bIsPie = rTypeInfo.meTypeCategory == TYPECATEGORY_PIE; diff --git a/oox/source/drawingml/chart/seriesmodel.cxx b/oox/source/drawingml/chart/seriesmodel.cxx index ec263d2679cb..224587b49025 100644 --- a/oox/source/drawingml/chart/seriesmodel.cxx +++ b/oox/source/drawingml/chart/seriesmodel.cxx @@ -69,6 +69,21 @@ DataLabelsModel::~DataLabelsModel() // ============================================================================ +PictureOptionsModel::PictureOptionsModel() : + mfStackUnit( 1.0 ), + mnPictureFormat( XML_stretch ), + mbApplyToFront( false ), + mbApplyToSides( false ), + mbApplyToEnd( false ) +{ +} + +PictureOptionsModel::~PictureOptionsModel() +{ +} + +// ============================================================================ + ErrorBarModel::ErrorBarModel() : mfValue( 0.0 ), mnDirection( XML_y ), diff --git a/oox/source/drawingml/chart/typegroupconverter.cxx b/oox/source/drawingml/chart/typegroupconverter.cxx index 2b5d95d86e6a..20ef90834482 100644 --- a/oox/source/drawingml/chart/typegroupconverter.cxx +++ b/oox/source/drawingml/chart/typegroupconverter.cxx @@ -77,31 +77,31 @@ const sal_Char SERVICE_CHART2_LINE[] = "com.sun.star.chart2.LineChartType"; const sal_Char SERVICE_CHART2_NET[] = "com.sun.star.chart2.NetChartType"; const sal_Char SERVICE_CHART2_PIE[] = "com.sun.star.chart2.PieChartType"; const sal_Char SERVICE_CHART2_SCATTER[] = "com.sun.star.chart2.ScatterChartType"; -const sal_Char SERVICE_CHART2_BUBBLE[] = "com.sun.star.chart2.ScatterChartType"; // Todo +const sal_Char SERVICE_CHART2_BUBBLE[] = "com.sun.star.chart2.BubbleChartType"; const sal_Char SERVICE_CHART2_SURFACE[] = "com.sun.star.chart2.ColumnChartType"; // Todo namespace csscd = ::com::sun::star::chart::DataLabelPlacement; static const TypeGroupInfo spTypeInfos[] = { - // type-id type-category service varied-point-color default label pos comb2d supp3d polar area2d 1stvis xcateg swap stack revers betw - { TYPEID_BAR, TYPECATEGORY_BAR, SERVICE_CHART2_COLUMN, VARPOINTMODE_SINGLE, csscd::OUTSIDE, true, true, false, true, false, true, false, true, false, true }, - { TYPEID_HORBAR, TYPECATEGORY_BAR, SERVICE_CHART2_COLUMN, VARPOINTMODE_SINGLE, csscd::OUTSIDE, false, true, false, true, false, true, true, true, false, true }, - { TYPEID_LINE, TYPECATEGORY_LINE, SERVICE_CHART2_LINE, VARPOINTMODE_SINGLE, csscd::RIGHT, true, true, false, false, false, true, false, true, false, true }, - { TYPEID_AREA, TYPECATEGORY_LINE, SERVICE_CHART2_AREA, VARPOINTMODE_NONE, csscd::CENTER, true, true, false, true, false, true, false, true, true, false }, - { TYPEID_STOCK, TYPECATEGORY_LINE, SERVICE_CHART2_CANDLE, VARPOINTMODE_NONE, csscd::RIGHT, true, false, false, false, false, true, false, true, false, true }, - { TYPEID_RADARLINE, TYPECATEGORY_RADAR, SERVICE_CHART2_NET, VARPOINTMODE_SINGLE, csscd::TOP, false, false, true, false, false, true, false, false, false, false }, - { TYPEID_RADARAREA, TYPECATEGORY_RADAR, SERVICE_CHART2_NET, VARPOINTMODE_NONE, csscd::TOP, false, false, true, true, false, true, false, false, false, false }, - { TYPEID_PIE, TYPECATEGORY_PIE, SERVICE_CHART2_PIE, VARPOINTMODE_MULTI, csscd::AVOID_OVERLAP, false, true, true, true, true, true, false, false, false, false }, - { TYPEID_DOUGHNUT, TYPECATEGORY_PIE, SERVICE_CHART2_PIE, VARPOINTMODE_MULTI, csscd::AVOID_OVERLAP, false, true, true, true, false, true, false, false, false, false }, - { TYPEID_OFPIE, TYPECATEGORY_PIE, SERVICE_CHART2_PIE, VARPOINTMODE_MULTI, csscd::AVOID_OVERLAP, false, true, true, true, true, true, false, false, false, false }, - { TYPEID_SCATTER, TYPECATEGORY_SCATTER, SERVICE_CHART2_SCATTER, VARPOINTMODE_SINGLE, csscd::RIGHT, true, true, false, false, false, false, false, false, false, false }, - { TYPEID_BUBBLE, TYPECATEGORY_SCATTER, SERVICE_CHART2_BUBBLE, VARPOINTMODE_SINGLE, csscd::RIGHT, false, true, false, true, false, false, false, false, false, false }, - { TYPEID_SURFACE, TYPECATEGORY_SURFACE, SERVICE_CHART2_SURFACE, VARPOINTMODE_NONE, csscd::RIGHT, false, true, false, true, false, true, false, false, false, false }, + // type-id type-category service varied-point-color default label pos comb2d supp3d polar area2d 1stvis xcateg swap stack revers betw picopt + { TYPEID_BAR, TYPECATEGORY_BAR, SERVICE_CHART2_COLUMN, VARPOINTMODE_SINGLE, csscd::OUTSIDE, true, true, false, true, false, true, false, true, false, true, true }, + { TYPEID_HORBAR, TYPECATEGORY_BAR, SERVICE_CHART2_COLUMN, VARPOINTMODE_SINGLE, csscd::OUTSIDE, false, true, false, true, false, true, true, true, false, true, true }, + { TYPEID_LINE, TYPECATEGORY_LINE, SERVICE_CHART2_LINE, VARPOINTMODE_SINGLE, csscd::RIGHT, true, true, false, false, false, true, false, true, false, true, false }, + { TYPEID_AREA, TYPECATEGORY_LINE, SERVICE_CHART2_AREA, VARPOINTMODE_NONE, csscd::CENTER, true, true, false, true, false, true, false, true, true, false, false }, + { TYPEID_STOCK, TYPECATEGORY_LINE, SERVICE_CHART2_CANDLE, VARPOINTMODE_NONE, csscd::RIGHT, true, false, false, false, false, true, false, true, false, true, false }, + { TYPEID_RADARLINE, TYPECATEGORY_RADAR, SERVICE_CHART2_NET, VARPOINTMODE_SINGLE, csscd::TOP, false, false, true, false, false, true, false, false, false, false, false }, + { TYPEID_RADARAREA, TYPECATEGORY_RADAR, SERVICE_CHART2_NET, VARPOINTMODE_NONE, csscd::TOP, false, false, true, true, false, true, false, false, false, false, false }, + { TYPEID_PIE, TYPECATEGORY_PIE, SERVICE_CHART2_PIE, VARPOINTMODE_MULTI, csscd::AVOID_OVERLAP, false, true, true, true, true, true, false, false, false, false, false }, + { TYPEID_DOUGHNUT, TYPECATEGORY_PIE, SERVICE_CHART2_PIE, VARPOINTMODE_MULTI, csscd::AVOID_OVERLAP, false, true, true, true, false, true, false, false, false, false, false }, + { TYPEID_OFPIE, TYPECATEGORY_PIE, SERVICE_CHART2_PIE, VARPOINTMODE_MULTI, csscd::AVOID_OVERLAP, false, true, true, true, true, true, false, false, false, false, false }, + { TYPEID_SCATTER, TYPECATEGORY_SCATTER, SERVICE_CHART2_SCATTER, VARPOINTMODE_SINGLE, csscd::RIGHT, true, true, false, false, false, false, false, false, false, false, false }, + { TYPEID_BUBBLE, TYPECATEGORY_SCATTER, SERVICE_CHART2_BUBBLE, VARPOINTMODE_SINGLE, csscd::RIGHT, false, false, false, true, false, false, false, false, false, false, false }, + { TYPEID_SURFACE, TYPECATEGORY_SURFACE, SERVICE_CHART2_SURFACE, VARPOINTMODE_NONE, csscd::RIGHT, false, true, false, true, false, true, false, false, false, false, false } }; static const TypeGroupInfo saUnknownTypeInfo = - { TYPEID_UNKNOWN, TYPECATEGORY_BAR, SERVICE_CHART2_COLUMN, VARPOINTMODE_SINGLE, csscd::OUTSIDE, true, true, false, true, false, true, false, true, false, true }; + { TYPEID_UNKNOWN, TYPECATEGORY_BAR, SERVICE_CHART2_COLUMN, VARPOINTMODE_SINGLE, csscd::OUTSIDE, true, true, false, true, false, true, false, true, false, true, true }; const TypeGroupInfo& lclGetTypeInfoFromTypeId( TypeId eTypeId ) { @@ -188,11 +188,6 @@ TypeGroupConverter::TypeGroupConverter( const ConverterRoot& rParent, TypeGroupM if( mrModel.mnRadarStyle == XML_filled ) eTypeId = TYPEID_RADARAREA; break; - case TYPEID_BUBBLE: - // create a symbol-only scatter chart from bubble charts - for( TypeGroupModel::SeriesVector::iterator aIt = mrModel.maSeries.begin(), aEnd = mrModel.maSeries.end(); aIt != aEnd; ++aIt ) - (*aIt)->mxShapeProp.getOrCreate().getLineProperties().maLineFill.moFillType = XML_noFill; - break; case TYPEID_SURFACE: // create a deep 3D bar chart from surface charts mrModel.mnGrouping = XML_standard; @@ -202,16 +197,6 @@ TypeGroupConverter::TypeGroupConverter( const ConverterRoot& rParent, TypeGroupM // set the chart type info struct for the current chart type maTypeInfo = lclGetTypeInfoFromTypeId( eTypeId ); - - // change type info for some chart types - switch( eTypeId ) - { - case TYPEID_BUBBLE: - // bubble chart has fill properties, but we create a scatter chart - maTypeInfo.mbSeriesIsFrame2d = false; - break; - default:; - } } TypeGroupConverter::~TypeGroupConverter() diff --git a/oox/source/drawingml/clrschemecontext.cxx b/oox/source/drawingml/clrschemecontext.cxx index ce86b4a412a4..6eedb908c00e 100644 --- a/oox/source/drawingml/clrschemecontext.cxx +++ b/oox/source/drawingml/clrschemecontext.cxx @@ -29,7 +29,6 @@ ************************************************************************/ #include "oox/drawingml/clrschemecontext.hxx" -#include "oox/drawingml/colorchoicecontext.hxx" #include "oox/core/namespaces.hxx" #include "tokens.hxx" @@ -67,66 +66,44 @@ clrMapContext::clrMapContext( ContextHandler& rParent, setClrMap( xAttributes, rClrMap, XML_folHlink ); } -Reference< XFastContextHandler > clrMapContext::createFastChildContext( sal_Int32 /* aElementToken */, const Reference< XFastAttributeList >& /* xAttribs */ ) - throw (SAXException, RuntimeException) +clrSchemeColorContext::clrSchemeColorContext( ContextHandler& rParent, ClrScheme& rClrScheme, sal_Int32 nColorToken ) : + ColorContext( rParent, *this ), + mrClrScheme( rClrScheme ), + mnColorToken( nColorToken ) { - Reference< XFastContextHandler > xRet; - return xRet; } -clrSchemeContext::clrSchemeContext( ContextHandler& rParent, ClrScheme& rClrScheme ) -: ContextHandler( rParent ) -, mrClrScheme( rClrScheme ) +clrSchemeColorContext::~clrSchemeColorContext() { + mrClrScheme.setColor( mnColorToken, getColor( getFilter() ) ); } -void clrSchemeContext::startFastElement( sal_Int32 /* aElementToken */, const Reference< XFastAttributeList >& /* xAttribs */ ) throw (SAXException, RuntimeException) +clrSchemeContext::clrSchemeContext( ContextHandler& rParent, ClrScheme& rClrScheme ) : + ContextHandler( rParent ), + mrClrScheme( rClrScheme ) { } -void clrSchemeContext::endFastElement( sal_Int32 aElementToken ) throw (SAXException, RuntimeException) +Reference< XFastContextHandler > clrSchemeContext::createFastChildContext( + sal_Int32 nElement, const Reference< XFastAttributeList >& ) throw (SAXException, RuntimeException) { - switch( aElementToken ) + switch( nElement ) { - case NMSP_DRAWINGML|XML_dk1: - case NMSP_DRAWINGML|XML_lt1: - case NMSP_DRAWINGML|XML_dk2: - case NMSP_DRAWINGML|XML_lt2: - case NMSP_DRAWINGML|XML_accent1: - case NMSP_DRAWINGML|XML_accent2: - case NMSP_DRAWINGML|XML_accent3: - case NMSP_DRAWINGML|XML_accent4: - case NMSP_DRAWINGML|XML_accent5: - case NMSP_DRAWINGML|XML_accent6: - case NMSP_DRAWINGML|XML_hlink: - case NMSP_DRAWINGML|XML_folHlink: - { - mrClrScheme.setColor( aElementToken & 0xffff, maColor.getColor( getFilter() ) ); - break; - } + case A_TOKEN( dk1 ): + case A_TOKEN( lt1 ): + case A_TOKEN( dk2 ): + case A_TOKEN( lt2 ): + case A_TOKEN( accent1 ): + case A_TOKEN( accent2 ): + case A_TOKEN( accent3 ): + case A_TOKEN( accent4 ): + case A_TOKEN( accent5 ): + case A_TOKEN( accent6 ): + case A_TOKEN( hlink ): + case A_TOKEN( folHlink ): + return new clrSchemeColorContext( *this, mrClrScheme, getToken( nElement ) ); } -} - -Reference< XFastContextHandler > clrSchemeContext::createFastChildContext( sal_Int32 aElementToken, const Reference< XFastAttributeList >& /* xAttribs */ ) throw (SAXException, RuntimeException) -{ - Reference< XFastContextHandler > xRet; - switch( aElementToken ) - { - case NMSP_DRAWINGML|XML_scrgbClr: // CT_ScRgbColor - case NMSP_DRAWINGML|XML_srgbClr: // CT_SRgbColor - case NMSP_DRAWINGML|XML_hslClr: // CT_HslColor - case NMSP_DRAWINGML|XML_sysClr: // CT_SystemColor -// case NMSP_DRAWINGML|XML_schemeClr: // CT_SchemeColor - case NMSP_DRAWINGML|XML_prstClr: // CT_PresetColor - { - xRet.set( new colorChoiceContext( *this, maColor ) ); - break; - } - } - if( !xRet.is() ) - xRet.set( this ); - - return xRet; + return 0; } } } diff --git a/oox/source/drawingml/color.cxx b/oox/source/drawingml/color.cxx index b5b02cdc6b9d..c269379b5adc 100644 --- a/oox/source/drawingml/color.cxx +++ b/oox/source/drawingml/color.cxx @@ -51,70 +51,7 @@ const sal_Int32 MAX_DEGREE = 360 * PER_DEGREE; const double DEC_GAMMA = 2.3; const double INC_GAMMA = 1.0 / DEC_GAMMA; -inline void lclRgbToRgbComponents( sal_Int32& ornR, sal_Int32& ornG, sal_Int32& ornB, sal_Int32 nRGB ) -{ - ornR = (nRGB >> 16) & 0xFF; - ornG = (nRGB >> 8) & 0xFF; - ornB = nRGB & 0xFF; -} - -inline sal_Int32 lclRgbComponentsToRgb( sal_Int32 nR, sal_Int32 nG, sal_Int32 nB ) -{ - return static_cast< sal_Int32 >( (nR << 16) | (nG << 8) | nB ); -} - -inline sal_Int32 lclRgbCompToCrgbComp( sal_Int32 nRgbComp ) -{ - return static_cast< sal_Int32 >( nRgbComp * MAX_PERCENT / 255 ); -} - -inline sal_Int32 lclCrgbCompToRgbComp( sal_Int32 nCrgbComp ) -{ - return static_cast< sal_Int32 >( nCrgbComp * 255 / MAX_PERCENT ); -} - -inline sal_Int32 lclGamma( sal_Int32 nComp, double fGamma ) -{ - return static_cast< sal_Int32 >( pow( static_cast< double >( nComp ) / MAX_PERCENT, fGamma ) * MAX_PERCENT + 0.5 ); -} - -void lclSetValue( sal_Int32& ornValue, sal_Int32 nNew, sal_Int32 nMax = MAX_PERCENT ) -{ - OSL_ENSURE( (0 <= nNew) && (nNew <= nMax), "lclSetValue - invalid value" ); - if( (0 <= nNew) && (nNew <= nMax) ) - ornValue = nNew; -} - -void lclModValue( sal_Int32& ornValue, sal_Int32 nMod, sal_Int32 nMax = MAX_PERCENT ) -{ - OSL_ENSURE( (0 <= nMod), "lclModValue - invalid modificator" ); - ornValue = getLimitedValue< sal_Int32, double >( static_cast< double >( ornValue ) * nMod / MAX_PERCENT, 0, nMax ); -} - -void lclOffValue( sal_Int32& ornValue, sal_Int32 nOff, sal_Int32 nMax = MAX_PERCENT ) -{ - OSL_ENSURE( (-nMax <= nOff) && (nOff <= nMax), "lclOffValue - invalid offset" ); - ornValue = getLimitedValue< sal_Int32, sal_Int32 >( ornValue + nOff, 0, nMax ); -} - -} // namespace - -// ---------------------------------------------------------------------------- - -Color::Color() : - meMode( COLOR_UNUSED ), - mnC1( 0 ), - mnC2( 0 ), - mnC3( 0 ), - mnAlpha( MAX_PERCENT ) -{ -} - -Color::~Color() -{ -} - -sal_Int32 Color::getPresetColor( sal_Int32 nToken ) +sal_Int32 lclGetPresetColor( sal_Int32 nToken ) { switch( nToken ) { @@ -259,21 +196,71 @@ sal_Int32 Color::getPresetColor( sal_Int32 nToken ) case XML_yellow: return 0xFFFF00; case XML_yellowGreen: return 0x9ACD32; } - OSL_ENSURE( false, "Color::getPresetColor - invalid preset color token" ); - return 0; + OSL_ENSURE( false, "lclGetPresetColor - invalid preset color token" ); + return API_RGB_BLACK; } -sal_Int32 Color::getSystemColor( sal_Int32 nToken, sal_Int32 nDefault ) +inline void lclRgbToRgbComponents( sal_Int32& ornR, sal_Int32& ornG, sal_Int32& ornB, sal_Int32 nRgb ) +{ + ornR = (nRgb >> 16) & 0xFF; + ornG = (nRgb >> 8) & 0xFF; + ornB = nRgb & 0xFF; +} + +inline sal_Int32 lclRgbComponentsToRgb( sal_Int32 nR, sal_Int32 nG, sal_Int32 nB ) +{ + return static_cast< sal_Int32 >( (nR << 16) | (nG << 8) | nB ); +} + +inline sal_Int32 lclRgbCompToCrgbComp( sal_Int32 nRgbComp ) +{ + return static_cast< sal_Int32 >( nRgbComp * MAX_PERCENT / 255 ); +} + +inline sal_Int32 lclCrgbCompToRgbComp( sal_Int32 nCrgbComp ) +{ + return static_cast< sal_Int32 >( nCrgbComp * 255 / MAX_PERCENT ); +} + +inline sal_Int32 lclGamma( sal_Int32 nComp, double fGamma ) +{ + return static_cast< sal_Int32 >( pow( static_cast< double >( nComp ) / MAX_PERCENT, fGamma ) * MAX_PERCENT + 0.5 ); +} + +void lclSetValue( sal_Int32& ornValue, sal_Int32 nNew, sal_Int32 nMax = MAX_PERCENT ) +{ + OSL_ENSURE( (0 <= nNew) && (nNew <= nMax), "lclSetValue - invalid value" ); + if( (0 <= nNew) && (nNew <= nMax) ) + ornValue = nNew; +} + +void lclModValue( sal_Int32& ornValue, sal_Int32 nMod, sal_Int32 nMax = MAX_PERCENT ) +{ + OSL_ENSURE( (0 <= nMod), "lclModValue - invalid modificator" ); + ornValue = getLimitedValue< sal_Int32, double >( static_cast< double >( ornValue ) * nMod / MAX_PERCENT, 0, nMax ); +} + +void lclOffValue( sal_Int32& ornValue, sal_Int32 nOff, sal_Int32 nMax = MAX_PERCENT ) +{ + OSL_ENSURE( (-nMax <= nOff) && (nOff <= nMax), "lclOffValue - invalid offset" ); + ornValue = getLimitedValue< sal_Int32, sal_Int32 >( ornValue + nOff, 0, nMax ); +} + +} // namespace + +// ---------------------------------------------------------------------------- + +Color::Color() : + meMode( COLOR_UNUSED ), + mnC1( 0 ), + mnC2( 0 ), + mnC3( 0 ), + mnAlpha( MAX_PERCENT ) +{ +} + +Color::~Color() { - //! TODO: get colors from system - switch( nToken ) - { - case XML_window: if( nDefault < 0 ) nDefault = 0xFFFFFF; break; - case XML_windowText: if( nDefault < 0 ) nDefault = 0x000000; break; - //! TODO: more colors to follow... (chapter 5.1.12.58) - default: if( nDefault < 0 ) nDefault = 0x000000; - } - return nDefault; } void Color::setUnused() @@ -281,11 +268,11 @@ void Color::setUnused() meMode = COLOR_UNUSED; } -void Color::setSrgbClr( sal_Int32 nRGB ) +void Color::setSrgbClr( sal_Int32 nRgb ) { - OSL_ENSURE( (0 <= nRGB) && (nRGB <= 0xFFFFFF), "Color::setSrgbClr - invalid RGB value" ); + OSL_ENSURE( (0 <= nRgb) && (nRgb <= 0xFFFFFF), "Color::setSrgbClr - invalid RGB value" ); meMode = COLOR_RGB; - lclRgbToRgbComponents( mnC1, mnC2, mnC3, nRGB ); + lclRgbToRgbComponents( mnC1, mnC2, mnC3, nRgb ); } void Color::setScrgbClr( sal_Int32 nR, sal_Int32 nG, sal_Int32 nB ) @@ -312,19 +299,22 @@ void Color::setHslClr( sal_Int32 nHue, sal_Int32 nSat, sal_Int32 nLum ) void Color::setPrstClr( sal_Int32 nToken ) { - setSrgbClr( getPresetColor( nToken ) ); + setSrgbClr( lclGetPresetColor( nToken ) ); } void Color::setSchemeClr( sal_Int32 nToken ) { - meMode = COLOR_SCHEME; + OSL_ENSURE( nToken != XML_TOKEN_INVALID, "Color::setSchemeClr - invalid color token" ); + meMode = (nToken == XML_phClr) ? COLOR_PH : COLOR_SCHEME; mnC1 = nToken; } -void Color::setSysClr( sal_Int32 nToken, sal_Int32 nLastRGB ) +void Color::setSysClr( sal_Int32 nToken, sal_Int32 nLastRgb ) { - OSL_ENSURE( (-1 <= nLastRGB) && (nLastRGB <= 0xFFFFFF), "Color::setSysClr - invalid RGB value" ); - setSrgbClr( getSystemColor( nToken, nLastRGB ) ); + OSL_ENSURE( (-1 <= nLastRgb) && (nLastRgb <= 0xFFFFFF), "Color::setSysClr - invalid RGB value" ); + meMode = COLOR_SYSTEM; + mnC1 = nToken; + mnC2 = nLastRgb; } void Color::addTransformation( sal_Int32 nElement, sal_Int32 nValue ) @@ -364,6 +354,14 @@ void Color::clearTransparence() sal_Int32 Color::getColor( const ::oox::core::XmlFilterBase& rFilter, sal_Int32 nPhClr ) const { + /* Special handling for theme style list placeholder colors (state + COLOR_PH), Color::getColor() may be called with different placeholder + colors in the nPhClr parameter. Therefore, the resolved color will not + be stored in this object, thus the state COLOR_FINAL will not be + reached and the transformation container will not be cleared, but the + original COLOR_PH state will be restored instead. */ + bool bIsPh = false; + switch( meMode ) { case COLOR_UNUSED: return -1; @@ -375,7 +373,16 @@ sal_Int32 Color::getColor( const ::oox::core::XmlFilterBase& rFilter, sal_Int32 case COLOR_SCHEME: meMode = COLOR_RGB; - lclRgbToRgbComponents( mnC1, mnC2, mnC3, (mnC1 == XML_phClr) ? nPhClr : rFilter.getSchemeClr( mnC1 ) ); + lclRgbToRgbComponents( mnC1, mnC2, mnC3, rFilter.getSchemeClr( mnC1 ) ); + break; + case COLOR_PH: + meMode = COLOR_RGB; + lclRgbToRgbComponents( mnC1, mnC2, mnC3, nPhClr ); + bIsPh = true; + break; + case COLOR_SYSTEM: + meMode = COLOR_RGB; + lclRgbToRgbComponents( mnC1, mnC2, mnC3, rFilter.getSystemColor( mnC1, mnC2 ) ); break; } @@ -443,7 +450,7 @@ sal_Int32 Color::getColor( const ::oox::core::XmlFilterBase& rFilter, sal_Int32 mnC3 = static_cast< sal_Int32 >( MAX_PERCENT - (MAX_PERCENT - mnC3) * fFactor ); } break; - case NMSP_XLS | XML_tint: + case XLS_TOKEN( tint ): // Excel tint: move luminance relative to current value toHsl(); OSL_ENSURE( (-MAX_PERCENT <= aIt->mnValue) && (aIt->mnValue <= MAX_PERCENT), "Color::getColor - invalid tint value" ); @@ -496,10 +503,11 @@ sal_Int32 Color::getColor( const ::oox::core::XmlFilterBase& rFilter, sal_Int32 break; } } - maTransforms.clear(); toRgb(); - meMode = COLOR_FINAL; + meMode = bIsPh ? COLOR_PH : COLOR_FINAL; + if( meMode == COLOR_FINAL ) + maTransforms.clear(); return mnC1 = lclRgbComponentsToRgb( mnC1, mnC2, mnC3 ); } diff --git a/oox/source/drawingml/colorchoicecontext.cxx b/oox/source/drawingml/colorchoicecontext.cxx index 73cf1ae4f8cd..3dff6aac52a7 100644 --- a/oox/source/drawingml/colorchoicecontext.cxx +++ b/oox/source/drawingml/colorchoicecontext.cxx @@ -29,103 +29,136 @@ ************************************************************************/ #include "oox/drawingml/colorchoicecontext.hxx" -#include "oox/drawingml/clrscheme.hxx" -#include "oox/drawingml/drawingmltypes.hxx" -#include "oox/core/namespaces.hxx" #include "oox/helper/attributelist.hxx" -#include "tokens.hxx" +#include "oox/core/namespaces.hxx" +#include "oox/drawingml/color.hxx" -using namespace ::oox::core; -using namespace ::com::sun::star::uno; -using namespace ::com::sun::star::xml::sax; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::RuntimeException; +using ::com::sun::star::xml::sax::SAXException; +using ::com::sun::star::xml::sax::XFastAttributeList; +using ::com::sun::star::xml::sax::XFastContextHandler; +using ::oox::core::ContextHandler; -namespace oox { namespace drawingml { +namespace oox { +namespace drawingml { -colorChoiceContext::colorChoiceContext( ContextHandler& rParent, Color& rColor ) -: ContextHandler( rParent ) -, mrColor( rColor ) +// ============================================================================ + +ColorValueContext::ColorValueContext( ContextHandler& rParent, Color& rColor ) : + ContextHandler( rParent ), + mrColor( rColor ) { } -void colorChoiceContext::startFastElement( sal_Int32 aElementToken, const Reference< XFastAttributeList >& xAttribs ) +void ColorValueContext::startFastElement( sal_Int32 nElement, const Reference< XFastAttributeList >& rxAttribs ) throw (SAXException, RuntimeException) { - AttributeList aAttribs( xAttribs ); - - switch( aElementToken ) + AttributeList aAttribs( rxAttribs ); + switch( nElement ) { - case NMSP_DRAWINGML|XML_scrgbClr: // CT_ScRgbColor + case A_TOKEN( scrgbClr ): mrColor.setScrgbClr( aAttribs.getInteger( XML_r, 0 ), aAttribs.getInteger( XML_g, 0 ), aAttribs.getInteger( XML_b, 0 ) ); break; - case NMSP_DRAWINGML|XML_srgbClr: // CT_SRgbColor - mrColor.setSrgbClr( aAttribs.getHex( XML_val, 0 ) ); + case A_TOKEN( srgbClr ): + mrColor.setSrgbClr( aAttribs.getIntegerHex( XML_val, 0 ) ); break; - case NMSP_DRAWINGML|XML_hslClr: // CT_HslColor + case A_TOKEN( hslClr ): mrColor.setHslClr( aAttribs.getInteger( XML_hue, 0 ), aAttribs.getInteger( XML_sat, 0 ), aAttribs.getInteger( XML_lum, 0 ) ); break; - case NMSP_DRAWINGML|XML_sysClr: // CT_SystemColor - mrColor.setSysClr( aAttribs.getToken( XML_val, XML_TOKEN_INVALID ), aAttribs.getHex( XML_lastClr, -1 ) ); + case A_TOKEN( sysClr ): + mrColor.setSysClr( + aAttribs.getToken( XML_val, XML_TOKEN_INVALID ), + aAttribs.getIntegerHex( XML_lastClr, -1 ) ); break; - case NMSP_DRAWINGML|XML_schemeClr: // CT_SchemeColor + case A_TOKEN( schemeClr ): mrColor.setSchemeClr( aAttribs.getToken( XML_val, XML_TOKEN_INVALID ) ); break; - case NMSP_DRAWINGML|XML_prstClr: // CT_PresetColor + case A_TOKEN( prstClr ): mrColor.setPrstClr( aAttribs.getToken( XML_val, XML_TOKEN_INVALID ) ); break; } } -Reference< XFastContextHandler > colorChoiceContext::createFastChildContext( sal_Int32 aElementToken, const Reference< XFastAttributeList >& rxAttribs ) throw (SAXException, RuntimeException) +Reference< XFastContextHandler > ColorValueContext::createFastChildContext( + sal_Int32 nElement, const Reference< XFastAttributeList >& rxAttribs ) throw (SAXException, RuntimeException) { - // colorTransformGroup - switch( aElementToken ) + AttributeList aAttribs( rxAttribs ); + switch( nElement ) { - case NMSP_DRAWINGML|XML_alpha: - case NMSP_DRAWINGML|XML_alphaMod: - case NMSP_DRAWINGML|XML_alphaOff: - case NMSP_DRAWINGML|XML_blue: - case NMSP_DRAWINGML|XML_blueMod: - case NMSP_DRAWINGML|XML_blueOff: - case NMSP_DRAWINGML|XML_hue: - case NMSP_DRAWINGML|XML_hueMod: - case NMSP_DRAWINGML|XML_hueOff: - case NMSP_DRAWINGML|XML_lum: - case NMSP_DRAWINGML|XML_lumMod: - case NMSP_DRAWINGML|XML_lumOff: - case NMSP_DRAWINGML|XML_green: - case NMSP_DRAWINGML|XML_greenMod: - case NMSP_DRAWINGML|XML_greenOff: - case NMSP_DRAWINGML|XML_red: - case NMSP_DRAWINGML|XML_redMod: - case NMSP_DRAWINGML|XML_redOff: - case NMSP_DRAWINGML|XML_sat: - case NMSP_DRAWINGML|XML_satMod: - case NMSP_DRAWINGML|XML_satOff: - case NMSP_DRAWINGML|XML_shade: - case NMSP_DRAWINGML|XML_tint: - mrColor.addTransformation( aElementToken, rxAttribs->getOptionalValue( XML_val ).toInt32() ); + case A_TOKEN( alpha ): + case A_TOKEN( alphaMod ): + case A_TOKEN( alphaOff ): + case A_TOKEN( blue ): + case A_TOKEN( blueMod ): + case A_TOKEN( blueOff ): + case A_TOKEN( hue ): + case A_TOKEN( hueMod ): + case A_TOKEN( hueOff ): + case A_TOKEN( lum ): + case A_TOKEN( lumMod ): + case A_TOKEN( lumOff ): + case A_TOKEN( green ): + case A_TOKEN( greenMod ): + case A_TOKEN( greenOff ): + case A_TOKEN( red ): + case A_TOKEN( redMod ): + case A_TOKEN( redOff ): + case A_TOKEN( sat ): + case A_TOKEN( satMod ): + case A_TOKEN( satOff ): + case A_TOKEN( shade ): + case A_TOKEN( tint ): + mrColor.addTransformation( nElement, aAttribs.getInteger( XML_val, 0 ) ); break; - case NMSP_DRAWINGML|XML_comp: - case NMSP_DRAWINGML|XML_gamma: - case NMSP_DRAWINGML|XML_gray: - case NMSP_DRAWINGML|XML_inv: - case NMSP_DRAWINGML|XML_invGamma: - mrColor.addTransformation( aElementToken ); + case A_TOKEN( comp ): + case A_TOKEN( gamma ): + case A_TOKEN( gray ): + case A_TOKEN( inv ): + case A_TOKEN( invGamma ): + mrColor.addTransformation( nElement ); break; } - return this; + return 0; +} + +// ============================================================================ + +ColorContext::ColorContext( ContextHandler& rParent, Color& rColor ) : + ContextHandler( rParent ), + mrColor( rColor ) +{ +} + +Reference< XFastContextHandler > ColorContext::createFastChildContext( + sal_Int32 nElement, const Reference< XFastAttributeList >& ) throw (SAXException, RuntimeException) +{ + switch( nElement ) + { + case A_TOKEN( scrgbClr ): + case A_TOKEN( srgbClr ): + case A_TOKEN( hslClr ): + case A_TOKEN( sysClr ): + case A_TOKEN( schemeClr ): + case A_TOKEN( prstClr ): + return new ColorValueContext( *this, mrColor ); + } + return 0; } +// ============================================================================ + +} // namespace drawingml +} // namespace oox -} } diff --git a/oox/source/drawingml/diagram/datamodelcontext.cxx b/oox/source/drawingml/diagram/datamodelcontext.cxx index cb98991dec97..c4260b5eea9c 100644 --- a/oox/source/drawingml/diagram/datamodelcontext.cxx +++ b/oox/source/drawingml/diagram/datamodelcontext.cxx @@ -30,7 +30,6 @@ #include "oox/drawingml/diagram/datamodelcontext.hxx" #include "oox/helper/attributelist.hxx" -#include "oox/core/skipcontext.hxx" #include "oox/core/namespaces.hxx" #include "oox/drawingml/fillpropertiesgroupcontext.hxx" #include "oox/drawingml/shapepropertiescontext.hxx" @@ -78,8 +77,7 @@ public: switch( aElementToken ) { case NMSP_DIAGRAM|XML_extLst: - xRet.set( new SkipContext( *this ) ); - break; + return xRet; default: break; } @@ -167,8 +165,7 @@ public: switch( aElementToken ) { case NMSP_DIAGRAM|XML_extLst: - xRet.set( new SkipContext( *this ) ); - break; + return xRet; case NMSP_DIAGRAM|XML_prSet: // TODO // CT_ElemPropSet @@ -266,7 +263,7 @@ public: case NMSP_DRAWINGML|XML_pattFill: case NMSP_DRAWINGML|XML_solidFill: // EG_FillProperties - xRet.set( FillPropertiesGroupContext::StaticCreateContext( + xRet.set( FillPropertiesContext::createFillContext( *this, aElementToken, xAttribs, *mpDataModel->getFillProperties() ) ); break; case NMSP_DRAWINGML|XML_effectDag: @@ -327,11 +324,9 @@ DataModelContext::createFastChildContext( ::sal_Int32 aElement, case NMSP_DIAGRAM|XML_whole: // CT_WholeE2oFormatting // TODO - xRet.set( new SkipContext( *this ) ); - break; + return xRet; case NMSP_DIAGRAM|XML_extLst: - xRet.set( new SkipContext( *this ) ); - break; + return xRet; default: break; } diff --git a/oox/source/drawingml/diagram/diagramdefinitioncontext.cxx b/oox/source/drawingml/diagram/diagramdefinitioncontext.cxx index 697d0f96cc1c..b49a39aa889c 100644 --- a/oox/source/drawingml/diagram/diagramdefinitioncontext.cxx +++ b/oox/source/drawingml/diagram/diagramdefinitioncontext.cxx @@ -28,11 +28,10 @@ * ************************************************************************/ -#include "oox/core/skipcontext.hxx" +#include "diagramdefinitioncontext.hxx" #include "oox/core/namespaces.hxx" #include "oox/helper/helper.hxx" #include "layoutnodecontext.hxx" -#include "diagramdefinitioncontext.hxx" #include "oox/drawingml/diagram/datamodelcontext.hxx" using namespace ::oox::core; @@ -95,8 +94,7 @@ DiagramDefinitionContext::createFastChildContext( ::sal_Int32 aElement, break; case NMSP_DIAGRAM|XML_clrData: // TODO, does not matter for the UI. skip. - xRet.set( new SkipContext( *this ) ); - break; + return xRet; case NMSP_DIAGRAM|XML_sampData: mpLayout->getSampData().reset( new DiagramData ); xRet.set( new DataModelContext( *this, mpLayout->getSampData() ) ); diff --git a/oox/source/drawingml/diagram/layoutnodecontext.cxx b/oox/source/drawingml/diagram/layoutnodecontext.cxx index 1a65c779e036..71c6ab9dbafe 100644 --- a/oox/source/drawingml/diagram/layoutnodecontext.cxx +++ b/oox/source/drawingml/diagram/layoutnodecontext.cxx @@ -31,7 +31,6 @@ #include "layoutnodecontext.hxx" #include "oox/helper/attributelist.hxx" -#include "oox/core/skipcontext.hxx" #include "oox/core/namespaces.hxx" #include "oox/drawingml/diagram/diagram.hxx" #include "oox/drawingml/shapecontext.hxx" @@ -290,8 +289,7 @@ LayoutNodeContext::createFastChildContext( ::sal_Int32 aElement, break; } case NMSP_DIAGRAM|XML_extLst: - xRet.set( new SkipContext( *this ) ); - break; + return xRet; case NMSP_DIAGRAM|XML_alg: { // CT_Algorithm diff --git a/oox/source/drawingml/embeddedwavaudiofile.cxx b/oox/source/drawingml/embeddedwavaudiofile.cxx index 23700c3abd99..a4933cf9d5e2 100644 --- a/oox/source/drawingml/embeddedwavaudiofile.cxx +++ b/oox/source/drawingml/embeddedwavaudiofile.cxx @@ -50,7 +50,7 @@ namespace oox { namespace drawingml { AttributeList attribs(xAttribs); OUString sId = xAttribs->getOptionalValue( NMSP_RELATIONSHIPS|XML_embed ); - aAudio.msLink = rRelations.getTargetFromRelId( sId ); + aAudio.msEmbed = rRelations.getFragmentPathFromRelId( sId ); aAudio.mbBuiltIn = attribs.getBool( XML_builtIn, false ); aAudio.msName = xAttribs->getOptionalValue( XML_name ); } diff --git a/oox/source/drawingml/fillproperties.cxx b/oox/source/drawingml/fillproperties.cxx index 8db948576d56..46fe6ae5292c 100644 --- a/oox/source/drawingml/fillproperties.cxx +++ b/oox/source/drawingml/fillproperties.cxx @@ -30,22 +30,21 @@ #include "oox/drawingml/fillproperties.hxx" #include <com/sun/star/lang/XMultiServiceFactory.hpp> -#include <com/sun/star/frame/XFramesSupplier.hpp> #include <com/sun/star/beans/XPropertySet.hpp> #include <com/sun/star/awt/Gradient.hpp> #include <com/sun/star/awt/Size.hpp> -#include <com/sun/star/awt/XBitmap.hpp> -#include <com/sun/star/awt/XDevice.hpp> #include <com/sun/star/drawing/BitmapMode.hpp> +#include <com/sun/star/drawing/ColorMode.hpp> #include <com/sun/star/drawing/FillStyle.hpp> #include <com/sun/star/drawing/RectanglePoint.hpp> #include <com/sun/star/graphic/XGraphicTransformer.hpp> -#include "oox/core/modelobjectcontainer.hxx" -#include "oox/core/xmlfilterbase.hxx" -#include "oox/helper/propertymap.hxx" -#include "oox/helper/propertyset.hxx" #include "properties.hxx" #include "tokens.hxx" +#include "oox/helper/graphichelper.hxx" +#include "oox/helper/modelobjecthelper.hxx" +#include "oox/helper/propertymap.hxx" +#include "oox/helper/propertyset.hxx" +#include "oox/core/xmlfilterbase.hxx" using namespace ::com::sun::star; using namespace ::com::sun::star::drawing; @@ -56,7 +55,6 @@ using ::com::sun::star::uno::Reference; using ::com::sun::star::uno::Exception; using ::com::sun::star::uno::UNO_QUERY; using ::com::sun::star::uno::UNO_QUERY_THROW; -using ::oox::core::ModelObjectContainer; using ::oox::core::XmlFilterBase; namespace oox { @@ -72,33 +70,12 @@ static const sal_Int32 spnDefaultFillIds[ FillId_END ] = PROP_FillColor, PROP_FillTransparence, PROP_FillGradient, - PROP_FillBitmap, - PROP_FillBitmapMode, - PROP_FillBitmapTile, - PROP_FillBitmapStretch, - PROP_FillBitmapLogicalSize, - PROP_FillBitmapSizeX, - PROP_FillBitmapSizeY, - PROP_FillBitmapOffsetX, - PROP_FillBitmapOffsetY, - PROP_FillBitmapRectanglePoint -}; - -static const sal_Int32 spnDefaultPicIds[ FillId_END ] = -{ - PROP_FillStyle, - PROP_FillColor, - PROP_FillTransparence, - PROP_FillGradient, - PROP_Graphic, + PROP_FillBitmapURL, PROP_FillBitmapMode, - PROP_FillBitmapTile, - PROP_FillBitmapStretch, - PROP_FillBitmapLogicalSize, PROP_FillBitmapSizeX, PROP_FillBitmapSizeY, - PROP_FillBitmapOffsetX, - PROP_FillBitmapOffsetY, + PROP_FillBitmapPositionOffsetX, + PROP_FillBitmapPositionOffsetY, PROP_FillBitmapRectanglePoint }; @@ -129,27 +106,6 @@ RectanglePoint lclGetRectanglePoint( sal_Int32 nToken ) return RectanglePoint_LEFT_TOP; } -const awt::DeviceInfo& lclGetDeviceInfo( const XmlFilterBase& rFilter ) -{ - static awt::DeviceInfo aDeviceInfo; - if( aDeviceInfo.Width <= 0 ) - { - try - { - Reference< frame::XFramesSupplier > xDesktop( rFilter.getGlobalFactory()->createInstance( - CREATE_OUSTRING( "com.sun.star.frame.Desktop" ) ), UNO_QUERY_THROW ); - Reference< frame::XFrame > xFrame( xDesktop->getActiveFrame() ); - Reference< awt::XWindow > xWindow( xFrame->getContainerWindow() ); - Reference< awt::XDevice > xDevice( xWindow, UNO_QUERY_THROW ); - aDeviceInfo = xDevice->getInfo(); - } - catch( Exception& ) - { - } - } - return aDeviceInfo; -} - const awt::Size lclGetOriginalSize( const XmlFilterBase& rFilter, const Reference< XGraphic >& rxGraphic ) { awt::Size aSize100thMM( 0, 0 ); @@ -163,12 +119,9 @@ const awt::Size lclGetOriginalSize( const XmlFilterBase& rFilter, const Referenc awt::Size aSourceSizePixel( 0, 0 ); if( xGraphicPropertySet->getPropertyValue( CREATE_OUSTRING( "SizePixel" ) ) >>= aSourceSizePixel ) { - const awt::DeviceInfo& rDeviceInfo = lclGetDeviceInfo( rFilter ); - if( rDeviceInfo.PixelPerMeterX && rDeviceInfo.PixelPerMeterY ) - { - aSize100thMM.Width = static_cast< sal_Int32 >( ( aSourceSizePixel.Width * 100000.0 ) / rDeviceInfo.PixelPerMeterX ); - aSize100thMM.Height = static_cast< sal_Int32 >( ( aSourceSizePixel.Height * 100000.0 ) / rDeviceInfo.PixelPerMeterY ); - } + aSize100thMM = awt::Size( + rFilter.convertScreenPixelX( aSourceSizePixel.Width ), + rFilter.convertScreenPixelY( aSourceSizePixel.Height ) ); } } } @@ -179,71 +132,75 @@ const awt::Size lclGetOriginalSize( const XmlFilterBase& rFilter, const Referenc return aSize100thMM; } -Reference< XGraphic > lclTransformGraphic( const Reference< XGraphic >& rxGraphic, - const Color& rFromColor, const Color& rToColor, const XmlFilterBase& rFilter, sal_Int32 nPhClr ) -{ - if( rxGraphic.is() && rFromColor.isUsed() && rToColor.isUsed() ) try - { - sal_Int32 nFromColor = rFromColor.getColor( rFilter, nPhClr ); - sal_Int32 nToColor = rToColor.getColor( rFilter, nPhClr ); - if ( (nFromColor != nToColor) || rToColor.hasTransparence() ) - { - sal_Int16 nToTransparence = rToColor.getTransparence(); - sal_Int8 nToAlpha = static_cast< sal_Int8 >( (100 - nToTransparence) / 39.062 ); // ?!? correct ?!? - Reference< XGraphicTransformer > xTransformer( rxGraphic, UNO_QUERY_THROW ); - return xTransformer->colorChange( rxGraphic, nFromColor, 9, nToColor, nToAlpha ); - } - } - catch( Exception& ) - { - } - return rxGraphic; -} - } // namespace // ============================================================================ -FillPropertyIds::FillPropertyIds( const sal_Int32* pnPropertyIds, bool bNamedFillGradient, bool bNamedFillBitmap, bool bTransformGraphic ) : +FillPropertyIds::FillPropertyIds( const sal_Int32* pnPropertyIds, bool bNamedFillGradient, bool bNamedFillBitmap ) : mpnPropertyIds( pnPropertyIds ), mbNamedFillGradient( bNamedFillGradient ), - mbNamedFillBitmap( bNamedFillBitmap ), - mbTransformGraphic( bTransformGraphic ) + mbNamedFillBitmap( bNamedFillBitmap ) { OSL_ENSURE( mpnPropertyIds != 0, "FillPropertyIds::FillPropertyIds - missing property identifiers" ); } // ============================================================================ -FillPropertyIds FillProperties::DEFAULT_IDS( spnDefaultFillIds, false, false, false ); -FillPropertyIds FillProperties::DEFAULT_PICIDS( spnDefaultPicIds, false, false, true ); - -void FillProperties::assignUsed( const FillProperties& rSourceProps ) +void GradientFillProperties::assignUsed( const GradientFillProperties& rSourceProps ) { - moFillType.assignIfUsed( rSourceProps.moFillType ); - moRotateWithShape.assignIfUsed( rSourceProps.moRotateWithShape ); - - maFillColor.assignIfUsed( rSourceProps.maFillColor ); - if( !rSourceProps.maGradientStops.empty() ) maGradientStops = rSourceProps.maGradientStops; + moFillToRect.assignIfUsed( rSourceProps.moFillToRect ); + moTileRect.assignIfUsed( rSourceProps.moTileRect ); moGradientPath.assignIfUsed( rSourceProps.moGradientPath ); moShadeAngle.assignIfUsed( rSourceProps.moShadeAngle ); + moShadeFlip.assignIfUsed( rSourceProps.moShadeFlip ); moShadeScaled.assignIfUsed( rSourceProps.moShadeScaled ); - moFlipModeToken.assignIfUsed( rSourceProps.moFlipModeToken ); - moFillToRect.assignIfUsed( rSourceProps.moFillToRect ); - moTileRect.assignIfUsed( rSourceProps.moTileRect ); + moRotateWithShape.assignIfUsed( rSourceProps.moRotateWithShape ); +} + +// ============================================================================ + +void PatternFillProperties::assignUsed( const PatternFillProperties& rSourceProps ) +{ + maPattFgColor.assignIfUsed( rSourceProps.maPattFgColor ); + maPattBgColor.assignIfUsed( rSourceProps.maPattBgColor ); + moPattPreset.assignIfUsed( rSourceProps.moPattPreset ); +} +// ============================================================================ + +void BlipFillProperties::assignUsed( const BlipFillProperties& rSourceProps ) +{ if( rSourceProps.mxGraphic.is() ) mxGraphic = rSourceProps.mxGraphic; - maColorChangeFrom.assignIfUsed( rSourceProps.maColorChangeFrom ); - maColorChangeTo.assignIfUsed( rSourceProps.maColorChangeTo ); moBitmapMode.assignIfUsed( rSourceProps.moBitmapMode ); - moTileX.assignIfUsed( rSourceProps.moTileX ); - moTileY.assignIfUsed( rSourceProps.moTileY ); - moTileSX.assignIfUsed( rSourceProps.moTileSX ); - moTileSY.assignIfUsed( rSourceProps.moTileSY ); + moFillRect.assignIfUsed( rSourceProps.moFillRect ); + moTileOffsetX.assignIfUsed( rSourceProps.moTileOffsetX ); + moTileOffsetY.assignIfUsed( rSourceProps.moTileOffsetY ); + moTileScaleX.assignIfUsed( rSourceProps.moTileScaleX ); + moTileScaleY.assignIfUsed( rSourceProps.moTileScaleY ); moTileAlign.assignIfUsed( rSourceProps.moTileAlign ); + moTileFlip.assignIfUsed( rSourceProps.moTileFlip ); + moRotateWithShape.assignIfUsed( rSourceProps.moRotateWithShape ); + moColorEffect.assignIfUsed( rSourceProps.moColorEffect ); + moBrightness.assignIfUsed( rSourceProps.moBrightness ); + moContrast.assignIfUsed( rSourceProps.moContrast ); + maColorChangeFrom.assignIfUsed( rSourceProps.maColorChangeFrom ); + maColorChangeTo.assignIfUsed( rSourceProps.maColorChangeTo ); +} + +// ============================================================================ + +FillPropertyIds FillProperties::DEFAULT_IDS( spnDefaultFillIds, false, false ); + +void FillProperties::assignUsed( const FillProperties& rSourceProps ) +{ + moFillType.assignIfUsed( rSourceProps.moFillType ); + maFillColor.assignIfUsed( rSourceProps.maFillColor ); + maGradientProps.assignUsed( rSourceProps.maGradientProps ); + maPatternProps.assignUsed( rSourceProps.maPatternProps ); + maBlipProps.assignUsed( rSourceProps.maBlipProps ); } Color FillProperties::getBestSolidColor() const @@ -255,26 +212,22 @@ Color FillProperties::getBestSolidColor() const aSolidColor = maFillColor; break; case XML_gradFill: - if( !maGradientStops.empty() ) - aSolidColor = maGradientStops.begin()->second; + if( !maGradientProps.maGradientStops.empty() ) + aSolidColor = maGradientProps.maGradientStops.begin()->second; break; case XML_pattFill: - aSolidColor = maPattBgColor.isUsed() ? maPattBgColor : maPattFgColor; + aSolidColor = maPatternProps.maPattBgColor.isUsed() ? maPatternProps.maPattBgColor : maPatternProps.maPattFgColor; break; } return aSolidColor; } void FillProperties::pushToPropMap( PropertyMap& rPropMap, const FillPropertyIds& rPropIds, - const XmlFilterBase& rFilter, ModelObjectContainer& rObjContainer, + const XmlFilterBase& rFilter, ModelObjectHelper& rModelObjHelper, sal_Int32 nShapeRotation, sal_Int32 nPhClr ) const { if( moFillType.has() ) { - // "rotate with shape" not set, or set to false -> do not rotate - if ( !moRotateWithShape.get( false ) ) - nShapeRotation = 0; - FillStyle eFillStyle = FillStyle_NONE; switch( moFillType.get() ) { @@ -301,30 +254,34 @@ void FillProperties::pushToPropMap( PropertyMap& rPropMap, const FillPropertyIds aGradient.StartIntensity = 100; aGradient.EndIntensity = 100; - if( maGradientStops.size() > 1 ) + if( maGradientProps.maGradientStops.size() > 1 ) { - aGradient.StartColor = maGradientStops.begin()->second.getColor( rFilter, nPhClr ); - aGradient.EndColor = maGradientStops.rbegin()->second.getColor( rFilter, nPhClr ); + aGradient.StartColor = maGradientProps.maGradientStops.begin()->second.getColor( rFilter, nPhClr ); + aGradient.EndColor = maGradientProps.maGradientStops.rbegin()->second.getColor( rFilter, nPhClr ); } - if( moGradientPath.has() ) + // "rotate with shape" not set, or set to false -> do not rotate + if ( !maGradientProps.moRotateWithShape.get( false ) ) + nShapeRotation = 0; + + if( maGradientProps.moGradientPath.has() ) { - aGradient.Style = (moGradientPath.get() == XML_circle) ? awt::GradientStyle_ELLIPTICAL : awt::GradientStyle_RECT; + aGradient.Style = (maGradientProps.moGradientPath.get() == XML_circle) ? awt::GradientStyle_ELLIPTICAL : awt::GradientStyle_RECT; aGradient.Angle = static_cast< sal_Int16 >( (900 - (nShapeRotation / 6000)) % 3600 ); - aGradient.XOffset = moFillToRect.has() ? getLimitedValue< sal_Int16, sal_Int32 >( moFillToRect.get().X1 / 1000, 30, 70 ) : 50; - aGradient.YOffset = moFillToRect.has() ? getLimitedValue< sal_Int16, sal_Int32 >( moFillToRect.get().Y1 / 1000, 30, 70 ) : 50; + aGradient.XOffset = maGradientProps.moFillToRect.has() ? getLimitedValue< sal_Int16, sal_Int32 >( maGradientProps.moFillToRect.get().X1 / 1000, 30, 70 ) : 50; + aGradient.YOffset = maGradientProps.moFillToRect.has() ? getLimitedValue< sal_Int16, sal_Int32 >( maGradientProps.moFillToRect.get().Y1 / 1000, 30, 70 ) : 50; ::std::swap( aGradient.StartColor, aGradient.EndColor ); } else { aGradient.Style = awt::GradientStyle_LINEAR; - aGradient.Angle = static_cast< sal_Int16 >( (4500 - ((moShadeAngle.get( 0 ) - nShapeRotation) / 6000)) % 3600 ); + aGradient.Angle = static_cast< sal_Int16 >( (4500 - ((maGradientProps.moShadeAngle.get( 0 ) - nShapeRotation) / 6000)) % 3600 ); } // push gradient or named gradient to property map if( rPropIds.mbNamedFillGradient ) { - OUString aGradientName = rObjContainer.insertFillGradient( aGradient ); + OUString aGradientName = rModelObjHelper.insertFillGradient( aGradient ); if( aGradientName.getLength() > 0 ) { rPropMap.setProperty( rPropIds[ FillGradientId ], aGradientName ); @@ -341,30 +298,26 @@ void FillProperties::pushToPropMap( PropertyMap& rPropMap, const FillPropertyIds case XML_blipFill: // do not start complex graphic transformation if property is not supported... - if( mxGraphic.is() && rPropIds.has( FillBitmapId ) ) + if( maBlipProps.mxGraphic.is() && rPropIds.has( FillBitmapUrlId ) ) { // TODO: "rotate with shape" is not possible with our current core - // created transformed graphic - Reference< XGraphic > xGraphic = rPropIds.mbTransformGraphic ? - lclTransformGraphic( mxGraphic, maColorChangeFrom, maColorChangeTo, rFilter, nPhClr ) : - mxGraphic; - - if( xGraphic.is() ) + OUString aGraphicUrl = rFilter.getGraphicHelper().createGraphicObject( maBlipProps.mxGraphic ); + if( aGraphicUrl.getLength() > 0 ) { // push bitmap or named bitmap to property map if( rPropIds.mbNamedFillBitmap ) { - OUString aBitmapName = rObjContainer.insertFillBitmap( Reference< awt::XBitmap >( xGraphic, UNO_QUERY ) ); + OUString aBitmapName = rModelObjHelper.insertFillBitmap( aGraphicUrl ); if( aBitmapName.getLength() > 0 ) { - rPropMap.setProperty( rPropIds[ FillBitmapId ], aBitmapName ); + rPropMap.setProperty( rPropIds[ FillBitmapUrlId ], aBitmapName ); eFillStyle = FillStyle_BITMAP; } } else { - rPropMap.setProperty( rPropIds[ FillBitmapId ], xGraphic ); + rPropMap.setProperty( rPropIds[ FillBitmapUrlId ], aGraphicUrl ); eFillStyle = FillStyle_BITMAP; } } @@ -373,35 +326,33 @@ void FillProperties::pushToPropMap( PropertyMap& rPropMap, const FillPropertyIds if( eFillStyle == FillStyle_BITMAP ) { // bitmap mode (single, repeat, stretch) - BitmapMode eBitmapMode = lclGetBitmapMode( moBitmapMode.get( XML_TOKEN_INVALID ) ); + BitmapMode eBitmapMode = lclGetBitmapMode( maBlipProps.moBitmapMode.get( XML_TOKEN_INVALID ) ); rPropMap.setProperty( rPropIds[ FillBitmapModeId ], eBitmapMode ); - // anchor position inside bitmap - RectanglePoint eRectPoint = lclGetRectanglePoint( moTileAlign.get( XML_tl ) ); - rPropMap.setProperty( rPropIds[ FillBitmapRectanglePointId ], eRectPoint ); - // additional settings for repeated bitmap if( eBitmapMode == BitmapMode_REPEAT ) { - rPropMap.setProperty( rPropIds[ FillBitmapTileId ], true ); - rPropMap.setProperty( rPropIds[ FillBitmapStretchId ], true ); - rPropMap.setProperty( rPropIds[ FillBitmapLogicalSizeId ], true ); + // anchor position inside bitmap + RectanglePoint eRectPoint = lclGetRectanglePoint( maBlipProps.moTileAlign.get( XML_tl ) ); + rPropMap.setProperty( rPropIds[ FillBitmapRectanglePointId ], eRectPoint ); - // size of one bitmap tile - awt::Size aOriginalSize = lclGetOriginalSize( rFilter, mxGraphic ); + awt::Size aOriginalSize = lclGetOriginalSize( rFilter, maBlipProps.mxGraphic ); if( (aOriginalSize.Width > 0) && (aOriginalSize.Height > 0) ) { - sal_Int32 nFillBmpSizeX = static_cast< sal_Int32 >( (aOriginalSize.Width / 100000.0) * moTileSX.get( 100000 ) ); + // size of one bitmap tile (given as 1/1000 percent of bitmap size), convert to 1/100 mm + double fScaleX = maBlipProps.moTileScaleX.get( 100000 ) / 100000.0; + sal_Int32 nFillBmpSizeX = getLimitedValue< sal_Int32, double >( aOriginalSize.Width * fScaleX, 1, SAL_MAX_INT32 ); rPropMap.setProperty( rPropIds[ FillBitmapSizeXId ], nFillBmpSizeX ); - sal_Int32 nFillBmpSizeY = static_cast< sal_Int32 >( (aOriginalSize.Height / 100000.0) * moTileSY.get( 100000 ) ); + double fScaleY = maBlipProps.moTileScaleY.get( 100000 ) / 100000.0; + sal_Int32 nFillBmpSizeY = getLimitedValue< sal_Int32, double >( aOriginalSize.Height * fScaleY, 1, SAL_MAX_INT32 ); rPropMap.setProperty( rPropIds[ FillBitmapSizeYId ], nFillBmpSizeY ); - } - // offset of the first bitmap tile -// if( moTileX.has() ) -// rPropMap.setProperty( rPropIds[ FillBitmapOffsetXId ], static_cast< sal_Int16 >( moTileX.get() / 360 ) ); -// if( moTileY.has() ) -// rPropMap.setProperty( rPropIds[ FillBitmapOffsetYId ], static_cast< sal_Int16 >( moTileY.get() / 360 ) ); + // offset of the first bitmap tile (given as EMUs), convert to percent + sal_Int16 nTileOffsetX = getDoubleIntervalValue< sal_Int16 >( maBlipProps.moTileOffsetX.get( 0 ) / 3.6 / aOriginalSize.Width, 0, 100 ); + rPropMap.setProperty( rPropIds[ FillBitmapOffsetXId ], nTileOffsetX ); + sal_Int16 nTileOffsetY = getDoubleIntervalValue< sal_Int16 >( maBlipProps.moTileOffsetY.get( 0 ) / 3.6 / aOriginalSize.Height, 0, 100 ); + rPropMap.setProperty( rPropIds[ FillBitmapOffsetYId ], nTileOffsetY ); + } } } } @@ -433,11 +384,70 @@ void FillProperties::pushToPropMap( PropertyMap& rPropMap, const FillPropertyIds } void FillProperties::pushToPropSet( PropertySet& rPropSet, const FillPropertyIds& rPropIds, - const XmlFilterBase& rFilter, ModelObjectContainer& rObjContainer, + const XmlFilterBase& rFilter, ModelObjectHelper& rModelObjHelper, sal_Int32 nShapeRotation, sal_Int32 nPhClr ) const { PropertyMap aPropMap; - pushToPropMap( aPropMap, rPropIds, rFilter, rObjContainer, nShapeRotation, nPhClr ); + pushToPropMap( aPropMap, rPropIds, rFilter, rModelObjHelper, nShapeRotation, nPhClr ); + rPropSet.setProperties( aPropMap ); +} + +// ============================================================================ + +void GraphicProperties::assignUsed( const GraphicProperties& rSourceProps ) +{ + maBlipProps.assignUsed( rSourceProps.maBlipProps ); +} + +void GraphicProperties::pushToPropMap( PropertyMap& rPropMap, const XmlFilterBase& rFilter, sal_Int32 nPhClr ) const +{ + if( maBlipProps.mxGraphic.is() ) + { + // created transformed graphic + Reference< XGraphic > xGraphic = maBlipProps.mxGraphic; + if( maBlipProps.maColorChangeFrom.isUsed() && maBlipProps.maColorChangeTo.isUsed() ) + { + sal_Int32 nFromColor = maBlipProps.maColorChangeFrom.getColor( rFilter, nPhClr ); + sal_Int32 nToColor = maBlipProps.maColorChangeTo.getColor( rFilter, nPhClr ); + if ( (nFromColor != nToColor) || maBlipProps.maColorChangeTo.hasTransparence() ) try + { + sal_Int16 nToTransparence = maBlipProps.maColorChangeTo.getTransparence(); + sal_Int8 nToAlpha = static_cast< sal_Int8 >( (100 - nToTransparence) / 39.062 ); // ?!? correct ?!? + Reference< XGraphicTransformer > xTransformer( maBlipProps.mxGraphic, UNO_QUERY_THROW ); + xGraphic = xTransformer->colorChange( maBlipProps.mxGraphic, nFromColor, 9, nToColor, nToAlpha ); + } + catch( Exception& ) + { + } + } + + OUString aGraphicUrl = rFilter.getGraphicHelper().createGraphicObject( xGraphic ); + if( aGraphicUrl.getLength() > 0 ) + rPropMap[ PROP_GraphicURL ] <<= aGraphicUrl; + } + + // color effect + ColorMode eColorMode = ColorMode_STANDARD; + switch( maBlipProps.moColorEffect.get( XML_TOKEN_INVALID ) ) + { + case XML_biLevel: eColorMode = ColorMode_MONO; break; + case XML_grayscl: eColorMode = ColorMode_GREYS; break; + } + rPropMap[ PROP_GraphicColorMode ] <<= eColorMode; + + // brightness and contrast + sal_Int16 nBrightness = getLimitedValue< sal_Int16, sal_Int32 >( maBlipProps.moBrightness.get( 0 ) / 1000, -100, 100 ); + if( nBrightness != 0 ) + rPropMap[ PROP_AdjustLuminance ] <<= nBrightness; + sal_Int16 nContrast = getLimitedValue< sal_Int16, sal_Int32 >( maBlipProps.moContrast.get( 0 ) / 1000, -100, 100 ); + if( nContrast != 0 ) + rPropMap[ PROP_AdjustContrast ] <<= nContrast; +} + +void GraphicProperties::pushToPropSet( PropertySet& rPropSet, const XmlFilterBase& rFilter, sal_Int32 nPhClr ) const +{ + PropertyMap aPropMap; + pushToPropMap( aPropMap, rFilter, nPhClr ); rPropSet.setProperties( aPropMap ); } diff --git a/oox/source/drawingml/fillpropertiesgroupcontext.cxx b/oox/source/drawingml/fillpropertiesgroupcontext.cxx index 623762df7e4d..1e27dcd60bb7 100644 --- a/oox/source/drawingml/fillpropertiesgroupcontext.cxx +++ b/oox/source/drawingml/fillpropertiesgroupcontext.cxx @@ -29,447 +29,276 @@ ************************************************************************/ #include "oox/drawingml/fillpropertiesgroupcontext.hxx" -#include <com/sun/star/io/XInputStream.hpp> -#include <com/sun/star/graphic/XGraphicProvider.hpp> -#include <cppuhelper/exc_hlp.hxx> -#include <comphelper/anytostring.hxx> -#include "oox/drawingml/colorchoicecontext.hxx" -#include "oox/drawingml/drawingmltypes.hxx" -#include "oox/drawingml/fillproperties.hxx" +#include "oox/helper/attributelist.hxx" #include "oox/core/namespaces.hxx" #include "oox/core/xmlfilterbase.hxx" -#include "oox/helper/attributelist.hxx" +#include "oox/drawingml/drawingmltypes.hxx" +#include "oox/drawingml/fillproperties.hxx" using ::rtl::OUString; -using ::oox::core::ContextHandler; -using ::oox::core::XmlFilterBase; using namespace ::com::sun::star; using namespace ::com::sun::star::uno; using namespace ::com::sun::star::xml::sax; +using ::oox::core::ContextHandler; +using ::oox::core::XmlFilterBase; -namespace oox { namespace drawingml { +namespace oox { +namespace drawingml { -// --------------------------------------------------------------------- +// ============================================================================ -class NoFillContext : public FillPropertiesGroupContext +SolidFillContext::SolidFillContext( ContextHandler& rParent, + const Reference< XFastAttributeList >&, FillProperties& rFillProps ) : + ColorContext( rParent, rFillProps.maFillColor ) { -public: - NoFillContext( ContextHandler& rParent, FillProperties& rFillProperties ) throw(); -}; - -// --------------------------------------------------------------------- - -class SolidFillPropertiesContext : public FillPropertiesGroupContext -{ -public: - SolidFillPropertiesContext( ContextHandler& rParent, const Reference< XFastAttributeList >& xAttributes, FillProperties& rFillProperties ) throw(); - virtual Reference< XFastContextHandler > SAL_CALL createFastChildContext( sal_Int32 aElementToken, const Reference< XFastAttributeList >& xAttribs ) throw (SAXException, RuntimeException); -}; +} -// --------------------------------------------------------------------- +// ============================================================================ -class GradFillPropertiesContext : public FillPropertiesGroupContext +GradientFillContext::GradientFillContext( ContextHandler& rParent, + const Reference< XFastAttributeList >& rxAttribs, GradientFillProperties& rGradientProps ) : + ContextHandler( rParent ), + mrGradientProps( rGradientProps ) { -public: - GradFillPropertiesContext( ContextHandler& rParent, const Reference< XFastAttributeList >& xAttributes, FillProperties& rFillProperties ) throw(); - - virtual void SAL_CALL endFastElement( sal_Int32 aElementToken ) throw (SAXException, RuntimeException); - virtual Reference< XFastContextHandler > SAL_CALL createFastChildContext( sal_Int32 aElementToken, const Reference< XFastAttributeList >& xAttribs ) throw (SAXException, RuntimeException); -}; - -// --------------------------------------------------------------------- + AttributeList aAttribs( rxAttribs ); + mrGradientProps.moShadeFlip = aAttribs.getToken( XML_flip ); + mrGradientProps.moRotateWithShape = aAttribs.getBool( XML_rotWithShape ); +} -class PattFillPropertiesContext : public FillPropertiesGroupContext +Reference< XFastContextHandler > GradientFillContext::createFastChildContext( + sal_Int32 nElement, const Reference< XFastAttributeList >& rxAttribs ) throw (SAXException, RuntimeException) { -public: - PattFillPropertiesContext( ContextHandler& rParent, const Reference< XFastAttributeList >& xAttributes, FillProperties& rFillProperties ) throw(); - - virtual void SAL_CALL startFastElement( sal_Int32 aElementToken, const Reference< XFastAttributeList >& xAttribs ) throw (SAXException, RuntimeException); - virtual void SAL_CALL endFastElement( sal_Int32 aElementToken ) throw (SAXException, RuntimeException); - virtual Reference< XFastContextHandler > SAL_CALL createFastChildContext( sal_Int32 aElementToken, const Reference< XFastAttributeList >& xAttribs ) throw (SAXException, RuntimeException); -}; - -// --------------------------------------------------------------------- + AttributeList aAttribs( rxAttribs ); + switch( nElement ) + { + case A_TOKEN( gsLst ): + return this; // for gs elements -class GrpFillPropertiesContext : public FillPropertiesGroupContext -{ -public: - GrpFillPropertiesContext( ContextHandler& rParent, const Reference< ::XFastAttributeList >& xAttributes, FillProperties& rFillProperties ) throw(); + case A_TOKEN( gs ): + if( aAttribs.hasAttribute( XML_pos ) ) + { + double fPosition = getLimitedValue< double >( aAttribs.getDouble( XML_pos, 0.0 ) / 100000.0, 0.0, 1.0 ); + return new ColorContext( *this, mrGradientProps.maGradientStops[ fPosition ] ); + } + break; - virtual void SAL_CALL startFastElement( sal_Int32 aElementToken, const Reference< XFastAttributeList >& xAttribs ) throw (SAXException, RuntimeException); - virtual void SAL_CALL endFastElement( sal_Int32 aElementToken ) throw (SAXException, RuntimeException); - virtual Reference< XFastContextHandler > SAL_CALL createFastChildContext( sal_Int32 aElementToken, const Reference< XFastAttributeList >& xAttribs ) throw (SAXException, RuntimeException); -}; + case A_TOKEN( lin ): + mrGradientProps.moShadeAngle = aAttribs.getInteger( XML_ang ); + mrGradientProps.moShadeScaled = aAttribs.getBool( XML_scaled ); + break; -// --------------------------------------------------------------------- + case A_TOKEN( path ): + // always set a path type, this disables linear gradient in conversion + mrGradientProps.moGradientPath = aAttribs.getToken( XML_path, XML_rect ); + return this; // for fillToRect element -class clrChangeContext : public ContextHandler -{ -public: - clrChangeContext( ContextHandler& rParent, const Reference< XFastAttributeList >& xAttributes, - Color& rClrFrom, Color& rClrTo ) throw(); - ~clrChangeContext(); - virtual Reference< XFastContextHandler > SAL_CALL createFastChildContext( sal_Int32 aElementToken, const Reference< XFastAttributeList >& xAttribs ) throw (SAXException, RuntimeException); - -private: - Color& mrClrFrom; - Color& mrClrTo; - bool mbUseAlpha; -}; - -// --------------------------------------------------------------------- - -FillPropertiesContext::FillPropertiesContext( ContextHandler& rParent, FillProperties& rFillProperties ) throw() -: ContextHandler( rParent ) -, mrFillProperties( rFillProperties ) -{ -} + case A_TOKEN( fillToRect ): + mrGradientProps.moFillToRect = GetRelativeRect( rxAttribs ); + break; -Reference< XFastContextHandler > FillPropertiesContext::createFastChildContext( sal_Int32 aElementToken, const Reference< XFastAttributeList >& xAttribs ) - throw ( SAXException, RuntimeException ) -{ - return FillPropertiesGroupContext::StaticCreateContext( *this, aElementToken, xAttribs, mrFillProperties ); + case A_TOKEN( tileRect ): + mrGradientProps.moTileRect = GetRelativeRect( rxAttribs ); + break; + } + return 0; } -// --------------------------------------------------------------------- +// ============================================================================ -FillPropertiesGroupContext::FillPropertiesGroupContext( ContextHandler& rParent, FillProperties& rFillProperties, sal_Int32 nContext ) throw() -: ContextHandler( rParent ) -, mrFillProperties( rFillProperties ) +PatternFillContext::PatternFillContext( ContextHandler& rParent, + const Reference< XFastAttributeList >& rxAttribs, PatternFillProperties& rPatternProps ) : + ContextHandler( rParent ), + mrPatternProps( rPatternProps ) { - mrFillProperties.moFillType = nContext; + AttributeList aAttribs( rxAttribs ); + mrPatternProps.moPattPreset = aAttribs.getToken( XML_prst ); } -// --------------------------------------------------------------------- - -Reference< XFastContextHandler > FillPropertiesGroupContext::StaticCreateContext( ContextHandler& rParent, sal_Int32 aElementToken, - const Reference< XFastAttributeList >& xAttribs, FillProperties& rFillProperties ) - throw ( SAXException, RuntimeException ) +Reference< XFastContextHandler > PatternFillContext::createFastChildContext( + sal_Int32 nElement, const Reference< XFastAttributeList >& ) throw (SAXException, RuntimeException) { - Reference< XFastContextHandler > xRet; - - switch( aElementToken ) + switch( nElement ) { - case NMSP_DRAWINGML|XML_noFill: // CT_NoFillProperties - xRet.set( new NoFillContext( rParent, rFillProperties ) ); - break; - case NMSP_DRAWINGML|XML_solidFill: // CT_SolidFillProperties - xRet.set( new SolidFillPropertiesContext( rParent, xAttribs, rFillProperties ) ); - break; - case NMSP_DRAWINGML|XML_gradFill: // CT_GradientFillProperties - xRet.set( new GradFillPropertiesContext( rParent, xAttribs, rFillProperties ) ); - break; - case NMSP_DRAWINGML|XML_blipFill: // CT_BlipFillProperties - xRet.set( new BlipFillPropertiesContext( rParent, xAttribs, rFillProperties ) ); - break; - case NMSP_DRAWINGML|XML_pattFill: // CT_PatternFillProperties - xRet.set( new PattFillPropertiesContext( rParent, xAttribs, rFillProperties ) ); - break; - case NMSP_DRAWINGML|XML_grpFill: // CT_GroupFillProperties - xRet.set( new GrpFillPropertiesContext( rParent, xAttribs, rFillProperties ) ); - break; + case A_TOKEN( bgClr ): + return new ColorContext( *this, mrPatternProps.maPattBgColor ); + case A_TOKEN( fgClr ): + return new ColorContext( *this, mrPatternProps.maPattFgColor ); } - return xRet; + return 0; } -// --------------------------------------------------------------------- +// ============================================================================ +// ============================================================================ -NoFillContext::NoFillContext( ContextHandler& rParent, FillProperties& rFillProperties ) throw() -: FillPropertiesGroupContext( rParent, rFillProperties, XML_noFill ) +ColorChangeContext::ColorChangeContext( ContextHandler& rParent, + const Reference< XFastAttributeList >& rxAttribs, BlipFillProperties& rBlipProps ) : + ContextHandler( rParent ), + mrBlipProps( rBlipProps ) { + mrBlipProps.maColorChangeFrom.setUnused(); + mrBlipProps.maColorChangeTo.setUnused(); + AttributeList aAttribs( rxAttribs ); + mbUseAlpha = aAttribs.getBool( XML_useA, true ); } -// --------------------------------------------------------------------- - -SolidFillPropertiesContext::SolidFillPropertiesContext( ContextHandler& rParent, const Reference< XFastAttributeList >&, FillProperties& rFillProperties ) throw() -: FillPropertiesGroupContext( rParent, rFillProperties, XML_solidFill ) +ColorChangeContext::~ColorChangeContext() { + if( !mbUseAlpha ) + mrBlipProps.maColorChangeTo.clearTransparence(); } -Reference< XFastContextHandler > SolidFillPropertiesContext::createFastChildContext( sal_Int32 aElementToken, const Reference< XFastAttributeList >& ) throw (SAXException, RuntimeException) +Reference< XFastContextHandler > ColorChangeContext::createFastChildContext( + sal_Int32 nElement, const Reference< XFastAttributeList >& ) throw (SAXException, RuntimeException) { - Reference< XFastContextHandler > xRet; - switch( aElementToken ) + switch( nElement ) { - case NMSP_DRAWINGML|XML_scrgbClr: // CT_ScRgbColor - case NMSP_DRAWINGML|XML_srgbClr: // CT_SRgbColor - case NMSP_DRAWINGML|XML_hslClr: // CT_HslColor - case NMSP_DRAWINGML|XML_sysClr: // CT_SystemColor - case NMSP_DRAWINGML|XML_schemeClr: // CT_SchemeColor - case NMSP_DRAWINGML|XML_prstClr: // CT_PresetColor - xRet.set( new colorChoiceContext( *this, mrFillProperties.maFillColor ) ); - break; + case A_TOKEN( clrFrom ): + return new ColorContext( *this, mrBlipProps.maColorChangeFrom ); + case A_TOKEN( clrTo ): + return new ColorContext( *this, mrBlipProps.maColorChangeTo ); } - return xRet; + return 0; } -// --------------------------------------------------------------------- +// ============================================================================ -GradFillPropertiesContext::GradFillPropertiesContext( ContextHandler& rParent, const Reference< XFastAttributeList >& xAttribs, - FillProperties& rFillProperties ) throw() -: FillPropertiesGroupContext( rParent, rFillProperties, XML_gradFill ) -{ - AttributeList aAttribs( xAttribs ); - rFillProperties.moFlipModeToken = aAttribs.getToken( XML_flip ); - rFillProperties.moRotateWithShape = aAttribs.getBool( XML_rotWithShape ); -} - -void GradFillPropertiesContext::endFastElement( sal_Int32 ) throw (SAXException, RuntimeException) +BlipContext::BlipContext( ContextHandler& rParent, + const Reference< XFastAttributeList >& rxAttribs, BlipFillProperties& rBlipProps ) : + ContextHandler( rParent ), + mrBlipProps( rBlipProps ) { + AttributeList aAttribs( rxAttribs ); + if( aAttribs.hasAttribute( R_TOKEN( embed ) ) ) + { + // internal picture URL + OUString aFragmentPath = getFragmentPathFromRelId( aAttribs.getString( R_TOKEN( embed ), OUString() ) ); + if( aFragmentPath.getLength() > 0 ) + mrBlipProps.mxGraphic = getFilter().importEmbeddedGraphic( aFragmentPath ); + } + else if( aAttribs.hasAttribute( R_TOKEN( link ) ) ) + { + // external URL + OUString aRelId = aAttribs.getString( R_TOKEN( link ), OUString() ); + OUString aTargetLink = getFilter().getAbsoluteUrl( getRelations().getExternalTargetFromRelId( aRelId ) ); + // TODO: load external picture + } } -Reference< XFastContextHandler > GradFillPropertiesContext::createFastChildContext( sal_Int32 aElementToken, const Reference< XFastAttributeList >& xAttribs) throw (SAXException, RuntimeException) +Reference< XFastContextHandler > BlipContext::createFastChildContext( + sal_Int32 nElement, const Reference< XFastAttributeList >& rxAttribs ) throw (SAXException, RuntimeException) { - Reference< XFastContextHandler > xRet; - AttributeList aAttribs( xAttribs ); - switch( aElementToken ) + AttributeList aAttribs( rxAttribs ); + switch( nElement ) { - case NMSP_DRAWINGML|XML_gsLst: // CT_GradientStopList - { - xRet = this; - } - break; - case NMSP_DRAWINGML|XML_gs: - { - if( aAttribs.hasAttribute( XML_pos ) ) - { - double fPosition = GetPositiveFixedPercentage( xAttribs->getOptionalValue( XML_pos ) ); - xRet.set( new colorChoiceContext( *this, mrFillProperties.maGradientStops[ fPosition ] ) ); - } - } - break; - - // EG_ShadeProperties - case NMSP_DRAWINGML|XML_lin: // CT_LinearShadeProperties - mrFillProperties.moShadeAngle = aAttribs.getInteger( XML_ang ); - mrFillProperties.moShadeScaled = aAttribs.getBool( XML_scaled ); + case A_TOKEN( biLevel ): + case A_TOKEN( grayscl ): + mrBlipProps.moColorEffect = getToken( nElement ); break; - case NMSP_DRAWINGML|XML_path: // CT_PathShadeProperties - // always set a path type, this disables linear gradient in conversion - mrFillProperties.moGradientPath = aAttribs.getToken( XML_path, XML_rect ); - xRet = this; - break; - - case NMSP_DRAWINGML|XML_fillToRect: // CT_RelativeRect - mrFillProperties.moFillToRect = GetRelativeRect( xAttribs ); - break; + case A_TOKEN( clrChange ): + return new ColorChangeContext( *this, rxAttribs, mrBlipProps ); - case NMSP_DRAWINGML|XML_tileRect: // CT_RelativeRect - mrFillProperties.moTileRect = GetRelativeRect( xAttribs ); + case A_TOKEN( lum ): + mrBlipProps.moBrightness = aAttribs.getInteger( XML_bright ); + mrBlipProps.moContrast = aAttribs.getInteger( XML_contrast ); break; - - default:; } - return xRet; + return 0; } -// --------------------------------------------------------------------- -// CT_BlipFill -// --------------------------------------------------------------------- +// ============================================================================ -BlipFillPropertiesContext::BlipFillPropertiesContext( ContextHandler& rParent, const Reference< XFastAttributeList >& xAttribs, - FillProperties& rFillProperties ) - throw() -: FillPropertiesGroupContext( rParent, rFillProperties, XML_blipFill ) +BlipFillContext::BlipFillContext( ContextHandler& rParent, + const Reference< XFastAttributeList >& rxAttribs, BlipFillProperties& rBlipProps ) : + ContextHandler( rParent ), + mrBlipProps( rBlipProps ) { - /* todo - if( xAttribs->hasAttribute( XML_dpi ) ) - { - xsd:unsignedInt - DPI (dots per inch) used to calculate the size of the blip. If not present or zero, - the DPI in the blip is used. - - } - */ - AttributeList aAttribs( xAttribs ); - rFillProperties.moRotateWithShape = aAttribs.getBool( XML_rotWithShape ); + AttributeList aAttribs( rxAttribs ); + mrBlipProps.moRotateWithShape = aAttribs.getBool( XML_rotWithShape ); } -void BlipFillPropertiesContext::endFastElement( sal_Int32 ) throw (SAXException, RuntimeException) +Reference< XFastContextHandler > BlipFillContext::createFastChildContext( + sal_Int32 nElement, const Reference< XFastAttributeList >& rxAttribs ) throw (SAXException, RuntimeException) { - if( msEmbed.getLength() ) + AttributeList aAttribs( rxAttribs ); + switch( nElement ) { - const OUString aFragmentPath = getFragmentPathFromRelId( msEmbed ); - if( aFragmentPath.getLength() > 0 ) try - { - // get the input stream for the fill bitmap - XmlFilterBase& rFilter = getFilter(); - Reference< io::XInputStream > xInputStream( rFilter.openInputStream( aFragmentPath ), UNO_QUERY_THROW ); - - // load the fill bitmap into an XGraphic with the GraphicProvider - static const OUString sGraphicProvider = CREATE_OUSTRING( "com.sun.star.graphic.GraphicProvider" ); - Reference< graphic::XGraphicProvider > xGraphicProvider( rFilter.getGlobalFactory()->createInstance( sGraphicProvider ), UNO_QUERY_THROW ); - - static const OUString sInputStream = CREATE_OUSTRING( "InputStream" ); - beans::PropertyValues aMediaProperties(1); - aMediaProperties[0].Name = sInputStream; - aMediaProperties[0].Value <<= xInputStream; - - mrFillProperties.mxGraphic = xGraphicProvider->queryGraphic( aMediaProperties ); - } - catch( Exception& ) - { - OSL_ENSURE( false, - (rtl::OString("oox::drawingml::BlipFillPropertiesContext::EndElement(), " - "exception caught: ") + - rtl::OUStringToOString( - comphelper::anyToString( cppu::getCaughtException() ), - RTL_TEXTENCODING_UTF8 )).getStr() ); - - } - } -} + case A_TOKEN( blip ): + return new BlipContext( *this, rxAttribs, mrBlipProps ); -Reference< XFastContextHandler > BlipFillPropertiesContext::createFastChildContext( sal_Int32 aElementToken, const Reference< XFastAttributeList >& xAttribs ) throw (SAXException, RuntimeException) -{ - Reference< XFastContextHandler > xRet; - switch( aElementToken ) - { - case NMSP_DRAWINGML|XML_blip: // CT_Blip - msEmbed = xAttribs->getOptionalValue(NMSP_RELATIONSHIPS|XML_embed); // relationship identifer for embedded blobs - msLink = xAttribs->getOptionalValue(NMSP_RELATIONSHIPS|XML_link); // relationship identifer for linked blobs - break; - case NMSP_DRAWINGML|XML_alphaBiLevel: - case NMSP_DRAWINGML|XML_alphaCeiling: - case NMSP_DRAWINGML|XML_alphaFloor: - case NMSP_DRAWINGML|XML_alphaInv: - case NMSP_DRAWINGML|XML_alphaMod: - case NMSP_DRAWINGML|XML_alphaModFix: - case NMSP_DRAWINGML|XML_alphaRepl: - case NMSP_DRAWINGML|XML_biLevel: - case NMSP_DRAWINGML|XML_blur: - break; - case NMSP_DRAWINGML|XML_clrChange: - { - xRet = new clrChangeContext( *this, xAttribs, mrFillProperties.maColorChangeFrom, mrFillProperties.maColorChangeTo ); - } - break; - case NMSP_DRAWINGML|XML_clrRepl: - case NMSP_DRAWINGML|XML_duotone: - case NMSP_DRAWINGML|XML_extLst: - case NMSP_DRAWINGML|XML_fillOverlay: - case NMSP_DRAWINGML|XML_grayscl: - case NMSP_DRAWINGML|XML_hsl: - case NMSP_DRAWINGML|XML_lum: - case NMSP_DRAWINGML|XML_tint: + case A_TOKEN( srcRect ): + // TODO break; - case NMSP_DRAWINGML|XML_srcRect: // CT_RelativeRect -// todo maSrcRect = GetRelativeRect( xAttribs ); - break; - case NMSP_DRAWINGML|XML_tile: // CT_TileInfo - { - mrFillProperties.moBitmapMode = getToken( aElementToken ); - - AttributeList aAttribs( xAttribs ); - mrFillProperties.moFlipModeToken = aAttribs.getToken( XML_flip ); - mrFillProperties.moTileX = aAttribs.getInteger( XML_tx ); - mrFillProperties.moTileY = aAttribs.getInteger( XML_ty ); - mrFillProperties.moTileSX = aAttribs.getInteger( XML_sx ); - mrFillProperties.moTileSY = aAttribs.getInteger( XML_sy ); - mrFillProperties.moTileAlign = aAttribs.getToken( XML_algn ); - } + case A_TOKEN( tile ): + mrBlipProps.moBitmapMode = getToken( nElement ); + mrBlipProps.moTileOffsetX = aAttribs.getInteger( XML_tx ); + mrBlipProps.moTileOffsetY = aAttribs.getInteger( XML_ty ); + mrBlipProps.moTileScaleX = aAttribs.getInteger( XML_sx ); + mrBlipProps.moTileScaleY = aAttribs.getInteger( XML_sy ); + mrBlipProps.moTileAlign = aAttribs.getToken( XML_algn ); + mrBlipProps.moTileFlip = aAttribs.getToken( XML_flip ); break; - case NMSP_DRAWINGML|XML_stretch: // CT_StretchInfo - mrFillProperties.moBitmapMode = getToken( aElementToken ); + + case A_TOKEN( stretch ): + mrBlipProps.moBitmapMode = getToken( nElement ); + return this; // for fillRect element + + case A_TOKEN( fillRect ): + mrBlipProps.moFillRect = GetRelativeRect( rxAttribs ); break; - case NMSP_DRAWINGML|XML_fillRect: - // todo maFillRect = GetRelativeRect( xAttribs ); - break; } - if ( !xRet.is() ) - xRet.set( this ); - return xRet; + return 0; } -// --------------------------------------------------------------------- +// ============================================================================ +// ============================================================================ -PattFillPropertiesContext::PattFillPropertiesContext( ContextHandler& rParent, const Reference< XFastAttributeList >& rxAttribs, FillProperties& rFillProperties ) throw() -: FillPropertiesGroupContext( rParent, rFillProperties, XML_pattFill ) +FillPropertiesContext::FillPropertiesContext( ContextHandler& rParent, FillProperties& rFillProps ) : + ContextHandler( rParent ), + mrFillProps( rFillProps ) { - AttributeList aAttribs( rxAttribs ); - mrFillProperties.moPattPreset = aAttribs.getToken( XML_prst ); } -void PattFillPropertiesContext::startFastElement( sal_Int32, const Reference< XFastAttributeList >& ) throw (SAXException, RuntimeException) -{ -} - -void PattFillPropertiesContext::endFastElement( sal_Int32 ) throw (SAXException, RuntimeException) +Reference< XFastContextHandler > FillPropertiesContext::createFastChildContext( + sal_Int32 nElement, const Reference< XFastAttributeList >& rxAttribs ) + throw ( SAXException, RuntimeException ) { + return createFillContext( *this, nElement, rxAttribs, mrFillProps ); } -Reference< XFastContextHandler > PattFillPropertiesContext::createFastChildContext( sal_Int32 nElement, const Reference< XFastAttributeList >& ) throw (SAXException, RuntimeException) +/*static*/ Reference< XFastContextHandler > FillPropertiesContext::createFillContext( + ContextHandler& rParent, sal_Int32 nElement, + const Reference< XFastAttributeList >& rxAttribs, FillProperties& rFillProps ) { + rFillProps.moFillType = getToken( nElement ); switch( nElement ) { - case NMSP_DRAWINGML|XML_bgClr: - return new colorChoiceContext( *this, mrFillProperties.maPattBgColor ); - case NMSP_DRAWINGML|XML_fgClr: - return new colorChoiceContext( *this, mrFillProperties.maPattFgColor ); + case A_TOKEN( noFill ): return 0; + case A_TOKEN( solidFill ): return new SolidFillContext( rParent, rxAttribs, rFillProps ); + case A_TOKEN( gradFill ): return new GradientFillContext( rParent, rxAttribs, rFillProps.maGradientProps ); + case A_TOKEN( pattFill ): return new PatternFillContext( rParent, rxAttribs, rFillProps.maPatternProps ); + case A_TOKEN( blipFill ): return new BlipFillContext( rParent, rxAttribs, rFillProps.maBlipProps ); + case A_TOKEN( grpFill ): return 0; // TODO } return 0; } -// --------------------------------------------------------------------- +// ============================================================================ -GrpFillPropertiesContext::GrpFillPropertiesContext( ContextHandler& rParent, const Reference< XFastAttributeList >&, FillProperties& rFillProperties ) throw() -: FillPropertiesGroupContext( rParent, rFillProperties, XML_grpFill ) +SimpleFillPropertiesContext::SimpleFillPropertiesContext( ContextHandler& rParent, Color& rColor ) : + FillPropertiesContext( rParent, *this ), + mrColor( rColor ) { } -void GrpFillPropertiesContext::startFastElement( sal_Int32, const Reference< XFastAttributeList >& ) throw (SAXException, RuntimeException) +SimpleFillPropertiesContext::~SimpleFillPropertiesContext() { + mrColor = getBestSolidColor(); } -void GrpFillPropertiesContext::endFastElement( sal_Int32 ) throw (SAXException, RuntimeException) -{ -} - -Reference< XFastContextHandler > GrpFillPropertiesContext::createFastChildContext( sal_Int32, const Reference< XFastAttributeList >& ) - throw (SAXException, RuntimeException) -{ - return this; -} +// ============================================================================ +} // namespace drawingml +} // namespace oox -// --------------------------------------------------------------------- - -clrChangeContext::clrChangeContext( ContextHandler& rParent, const Reference< XFastAttributeList >& xAttributes, - Color& rClrFrom, Color& rClrTo ) throw() -: ContextHandler( rParent ) -, mrClrFrom( rClrFrom ) -, mrClrTo( rClrTo ) -{ - mrClrFrom.setUnused(); - mrClrTo.setUnused(); - AttributeList aAttribs( xAttributes ); - mbUseAlpha = aAttribs.getBool( XML_useA, true ); -} - -clrChangeContext::~clrChangeContext() -{ - if ( !mbUseAlpha ) - mrClrTo.clearTransparence(); -} - -Reference< XFastContextHandler > clrChangeContext::createFastChildContext( sal_Int32 aElementToken, const Reference< XFastAttributeList >& ) - throw (SAXException, RuntimeException) -{ - Reference< XFastContextHandler > xRet; - switch( aElementToken ) - { - case NMSP_DRAWINGML|XML_clrFrom: // CT_Color - xRet.set( new colorChoiceContext( *this, mrClrFrom ) ); - break; - case NMSP_DRAWINGML|XML_clrTo: // CT_Color - xRet.set( new colorChoiceContext( *this, mrClrTo ) ); - break; - default: - break; - } - return xRet; -} - -} } diff --git a/oox/source/drawingml/graphicshapecontext.cxx b/oox/source/drawingml/graphicshapecontext.cxx index 0a15f8a0ffc8..7d0207d3fb6a 100644 --- a/oox/source/drawingml/graphicshapecontext.cxx +++ b/oox/source/drawingml/graphicshapecontext.cxx @@ -28,28 +28,28 @@ * ************************************************************************/ +#include "oox/drawingml/graphicshapecontext.hxx" #include <osl/diagnose.h> +#include <com/sun/star/chart2/XChartDocument.hpp> #include "oox/drawingml/fillpropertiesgroupcontext.hxx" -#include "oox/drawingml/graphicshapecontext.hxx" #include "oox/drawingml/diagram/diagramfragmenthandler.hxx" #include "oox/drawingml/table/tablecontext.hxx" #include "oox/core/namespaces.hxx" #include "oox/core/xmlfilterbase.hxx" #include "oox/helper/attributelist.hxx" #include "oox/helper/propertyset.hxx" +#include "oox/vml/vmldrawing.hxx" +#include "oox/vml/vmlshape.hxx" +#include "oox/vml/vmlshapecontainer.hxx" +#include "oox/ole/oleobjecthelper.hxx" +#include "oox/drawingml/fillproperties.hxx" #include "oox/drawingml/transform2dcontext.hxx" #include "oox/drawingml/chart/chartconverter.hxx" #include "oox/drawingml/chart/chartspacefragment.hxx" #include "oox/drawingml/chart/chartspacemodel.hxx" #include "properties.hxx" #include "tokens.hxx" -#include <com/sun/star/container/XNameAccess.hpp> -#include <com/sun/star/io/XStream.hpp> -#include <com/sun/star/beans/XPropertySet.hpp> -#include <com/sun/star/document/XEmbeddedObjectResolver.hpp> -#include <com/sun/star/graphic/XGraphicProvider.hpp> -#include <com/sun/star/chart2/XChartDocument.hpp> using ::rtl::OUString; using namespace ::com::sun::star; @@ -57,14 +57,16 @@ using namespace ::com::sun::star::io; using namespace ::com::sun::star::uno; using namespace ::com::sun::star::lang; using namespace ::com::sun::star::beans; -using namespace ::oox::core; using namespace ::com::sun::star::xml::sax; +using namespace ::oox::core; +using ::oox::vml::OleObjectInfo; -namespace oox { namespace drawingml { - +namespace oox { +namespace drawingml { -// ==================================================================== +// ============================================================================ // CT_Picture + GraphicShapeContext::GraphicShapeContext( ContextHandler& rParent, ShapePtr pMasterShapePtr, ShapePtr pShapePtr ) : ShapeContext( rParent, pMasterShapePtr, pShapePtr ) { @@ -81,7 +83,7 @@ Reference< XFastContextHandler > GraphicShapeContext::createFastChildContext( sa xRet.set( new Transform2DContext( *this, xAttribs, *mpShapePtr ) ); break; case XML_blipFill: - xRet.set( new BlipFillPropertiesContext( *this, xAttribs, *mpShapePtr->getGraphicProperties() ) ); + xRet.set( new BlipFillContext( *this, xAttribs, mpShapePtr->getGraphicProperties().maBlipProps ) ); break; } @@ -104,11 +106,12 @@ Reference< XFastContextHandler > GraphicShapeContext::createFastChildContext( sa return xRet; } -// ==================================================================== +// ============================================================================ // CT_GraphicalObjectFrameContext -GraphicalObjectFrameContext::GraphicalObjectFrameContext( ContextHandler& rParent, ShapePtr pMasterShapePtr, ShapePtr pShapePtr, bool bEmbedShapesInChart ) -: ShapeContext( rParent, pMasterShapePtr, pShapePtr ) -, mbEmbedShapesInChart( bEmbedShapesInChart ) + +GraphicalObjectFrameContext::GraphicalObjectFrameContext( ContextHandler& rParent, ShapePtr pMasterShapePtr, ShapePtr pShapePtr, bool bEmbedShapesInChart ) : + ShapeContext( rParent, pMasterShapePtr, pShapePtr ), + mbEmbedShapesInChart( bEmbedShapesInChart ) { } @@ -132,7 +135,7 @@ Reference< XFastContextHandler > GraphicalObjectFrameContext::createFastChildCon { OUString sUri( xAttribs->getOptionalValue( XML_uri ) ); if ( sUri.equalsAscii( "http://schemas.openxmlformats.org/presentationml/2006/ole" ) ) - xRet.set( new PresentationOle2006Context( *this, mpShapePtr ) ); + xRet.set( new OleObjectGraphicDataContext( *this, mpShapePtr ) ); else if ( sUri.equalsAscii( "http://schemas.openxmlformats.org/drawingml/2006/diagram" ) ) xRet.set( new DiagramGraphicDataContext( *this, mpShapePtr ) ); else if ( sUri.equalsAscii( "http://schemas.openxmlformats.org/drawingml/2006/chart" ) ) @@ -153,111 +156,115 @@ Reference< XFastContextHandler > GraphicalObjectFrameContext::createFastChildCon return xRet; } -// ==================================================================== +// ============================================================================ -PresentationOle2006Context::PresentationOle2006Context( ContextHandler& rParent, ShapePtr pShapePtr ) -: ShapeContext( rParent, ShapePtr(), pShapePtr ) +class CreateOleObjectCallback : public CreateShapeCallback { -} +public: + explicit CreateOleObjectCallback( XmlFilterBase& rFilter, const ::boost::shared_ptr< OleObjectInfo >& rxOleObjectInfo ); + virtual OUString onCreateXShape( const OUString& rServiceName, const awt::Rectangle& rShapeRect ); + +private: + ::boost::shared_ptr< OleObjectInfo > mxOleObjectInfo; +}; -PresentationOle2006Context::~PresentationOle2006Context() +// ---------------------------------------------------------------------------- + +CreateOleObjectCallback::CreateOleObjectCallback( XmlFilterBase& rFilter, const ::boost::shared_ptr< OleObjectInfo >& rxOleObjectInfo ) : + CreateShapeCallback( rFilter ), + mxOleObjectInfo( rxOleObjectInfo ) { - static sal_Int32 nObjectCount = 100; +} - XmlFilterBase& rFilter = getFilter(); - const OUString aFragmentPath = getFragmentPathFromRelId( msId ); - if( aFragmentPath.getLength() > 0 ) try +OUString CreateOleObjectCallback::onCreateXShape( const OUString&, const awt::Rectangle& rShapeRect ) +{ + awt::Size aOleSize( rShapeRect.Width, rShapeRect.Height ); + bool bSuccess = mrFilter.getOleObjectHelper().importOleObject( maShapeProps, *mxOleObjectInfo, aOleSize ); + OUString aServiceName = bSuccess ? CREATE_OUSTRING( "com.sun.star.drawing.OLE2Shape" ) : CREATE_OUSTRING( "com.sun.star.drawing.GraphicObjectShape" ); + + // get the path to the representation graphic + OUString aGraphicPath; + if( mxOleObjectInfo->maShapeId.getLength() > 0 ) + if( ::oox::vml::Drawing* pVmlDrawing = mrFilter.getVmlDrawing() ) + if( const ::oox::vml::ShapeBase* pVmlShape = pVmlDrawing->getShapes().getShapeById( mxOleObjectInfo->maShapeId, true ) ) + aGraphicPath = pVmlShape->getGraphicPath(); + + // import and store the graphic + if( aGraphicPath.getLength() > 0 ) { - Reference< ::com::sun::star::io::XInputStream > xInputStream( rFilter.openInputStream( aFragmentPath ), UNO_QUERY_THROW ); + Reference< graphic::XGraphic > xGraphic = mrFilter.importEmbeddedGraphic( aGraphicPath ); + if( xGraphic.is() ) + maShapeProps[ PROP_Graphic ] <<= xGraphic; + } - Sequence< sal_Int8 > aData; - xInputStream->readBytes( aData, 0x7fffffff ); - uno::Reference< lang::XMultiServiceFactory > xMSF( rFilter.getModel(), UNO_QUERY_THROW ); - Reference< com::sun::star::document::XEmbeddedObjectResolver > xEmbeddedResolver( xMSF->createInstance( CREATE_OUSTRING( "com.sun.star.document.ImportEmbeddedObjectResolver" ) ), UNO_QUERY_THROW ); + return aServiceName; +} - Reference< com::sun::star::container::XNameAccess > xNA( xEmbeddedResolver, UNO_QUERY_THROW ); - OUString aURL = CREATE_OUSTRING( "Obj" ) + OUString::valueOf( nObjectCount++ ); - Reference < XOutputStream > xOLEStream; - if( (xNA->getByName( aURL ) >>= xOLEStream) && xOLEStream.is() ) - { - xOLEStream->writeBytes( aData ); - xOLEStream->closeOutput(); +// ============================================================================ - static const OUString sProtocol = CREATE_OUSTRING( "vnd.sun.star.EmbeddedObject:" ); - OUString aPersistName( xEmbeddedResolver->resolveEmbeddedObjectURL( aURL ) ); - aPersistName = aPersistName.copy( sProtocol.getLength() ); +OleObjectGraphicDataContext::OleObjectGraphicDataContext( ContextHandler& rParent, ShapePtr xShape ) : + ShapeContext( rParent, ShapePtr(), xShape ), + mxOleObjectInfo( new OleObjectInfo( true ) ) +{ + CreateShapeCallbackRef xCallback( new CreateOleObjectCallback( getFilter(), mxOleObjectInfo ) ); + xShape->setCreateShapeCallback( xCallback ); +} - mpShapePtr->getShapeProperties()[ PROP_PersistName ] <<= aPersistName; - } - Reference< XComponent > xComp( xEmbeddedResolver, UNO_QUERY_THROW ); - xComp->dispose(); - } - catch( Exception& ) - { - } +OleObjectGraphicDataContext::~OleObjectGraphicDataContext() +{ + /* Register the OLE shape at the VML drawing, this prevents that the + related VML shape converts the OLE object by itself. */ + if( mxOleObjectInfo->maShapeId.getLength() > 0 ) + if( ::oox::vml::Drawing* pVmlDrawing = getFilter().getVmlDrawing() ) + pVmlDrawing->registerOleObject( *mxOleObjectInfo ); +} + +Reference< XFastContextHandler > OleObjectGraphicDataContext::createFastChildContext( sal_Int32 nElement, const Reference< XFastAttributeList >& xAttribs ) throw (SAXException, RuntimeException) +{ + Reference< XFastContextHandler > xRet; + AttributeList aAttribs( xAttribs ); - // taking care of the representation graphic - if ( msSpid.getLength() ) + switch( nElement ) { - oox::vml::DrawingPtr pDrawingPtr = rFilter.getDrawings(); - if ( pDrawingPtr ) + case PPT_TOKEN( oleObj ): { - OUString aGraphicURL( pDrawingPtr->getGraphicUrlById( msSpid ) ); - if ( aGraphicURL.getLength() ) + mxOleObjectInfo->maShapeId = aAttribs.getXString( XML_spid, OUString() ); + const Relation* pRelation = getRelations().getRelationFromRelId( aAttribs.getString( R_TOKEN( id ), OUString() ) ); + OSL_ENSURE( pRelation, "OleObjectGraphicDataContext::createFastChildContext - missing relation for OLE object" ); + if( pRelation ) { - try + mxOleObjectInfo->mbLinked = pRelation->mbExternal; + if( pRelation->mbExternal ) { - Reference< io::XInputStream > xInputStream( rFilter.openInputStream( aGraphicURL ), UNO_QUERY_THROW ); - Reference< graphic::XGraphicProvider > xGraphicProvider( rFilter.getGlobalFactory()->createInstance( CREATE_OUSTRING( "com.sun.star.graphic.GraphicProvider" ) ), UNO_QUERY_THROW ); - Sequence< PropertyValue > aArgs( 1 ); - const OUString sInputStream = CREATE_OUSTRING( "InputStream" ); - aArgs[ 0 ].Name = sInputStream; - aArgs[ 0 ].Value <<= xInputStream; - Reference< graphic::XGraphic > xGraphic = xGraphicProvider->queryGraphic( aArgs ); - if ( xGraphic.is() ) - { - mpShapePtr->getShapeProperties()[ PROP_GraphicURL ] <<= OUString(); - mpShapePtr->getShapeProperties()[ PROP_Graphic ] <<= xGraphic; - } + mxOleObjectInfo->maTargetLink = getFilter().getAbsoluteUrl( pRelation->maTarget ); } - catch( Exception& ) + else { + OUString aFragmentPath = getFragmentPathFromRelation( *pRelation ); + if( aFragmentPath.getLength() > 0 ) + getFilter().importBinaryData( mxOleObjectInfo->maEmbeddedData, aFragmentPath ); } } + mxOleObjectInfo->maName = aAttribs.getXString( XML_name, OUString() ); + mxOleObjectInfo->maProgId = aAttribs.getXString( XML_progId, OUString() ); + mxOleObjectInfo->mbShowAsIcon = aAttribs.getBool( XML_showAsIcon, false ); + xRet.set( this ); } - } -} - -Reference< XFastContextHandler > PresentationOle2006Context::createFastChildContext( sal_Int32 aElementToken, const Reference< XFastAttributeList >& xAttribs ) throw (SAXException, RuntimeException) -{ - Reference< XFastContextHandler > xRet; + break; - switch( aElementToken &(~NMSP_MASK) ) - { - case XML_oleObj: - { - msSpid = xAttribs->getOptionalValue( XML_spid ); - msName = xAttribs->getOptionalValue( XML_name ); - msId = xAttribs->getOptionalValue( NMSP_RELATIONSHIPS|XML_id ); - mnWidth = GetCoordinate( xAttribs->getOptionalValue( XML_imgW ) ); - mnHeight = GetCoordinate( xAttribs->getOptionalValue( XML_imgH ) ); - msProgId = xAttribs->getOptionalValue( XML_progId ); - } + case PPT_TOKEN( embed ): + OSL_ENSURE( !mxOleObjectInfo->mbLinked, "OleObjectGraphicDataContext::createFastChildContext - unexpected child element" ); break; - case XML_embed: - { - mnFollowColorSchemeToken = xAttribs->getOptionalValueToken( XML_followColorScheme, XML_full ); - } - break; + case PPT_TOKEN( link ): + OSL_ENSURE( mxOleObjectInfo->mbLinked, "OleObjectGraphicDataContext::createFastChildContext - unexpected child element" ); + mxOleObjectInfo->mbAutoUpdate = aAttribs.getBool( XML_updateAutomatic, false ); + break; } - if( !xRet.is() ) - xRet.set( ShapeContext::createFastChildContext( aElementToken, xAttribs ) ); - return xRet; } -// ==================================================================== +// ============================================================================ DiagramGraphicDataContext::DiagramGraphicDataContext( ContextHandler& rParent, ShapePtr pShapePtr ) : ShapeContext( rParent, ShapePtr(), pShapePtr ) @@ -266,11 +273,8 @@ DiagramGraphicDataContext::DiagramGraphicDataContext( ContextHandler& rParent, S pShapePtr->setSubType( 0 ); } - - DiagramGraphicDataContext::~DiagramGraphicDataContext() { - } DiagramPtr DiagramGraphicDataContext::loadDiagram() @@ -344,32 +348,31 @@ Reference< XFastContextHandler > DiagramGraphicDataContext::createFastChildConte return xRet; } -// ==================================================================== +// ============================================================================ class CreateChartCallback : public CreateShapeCallback { public: explicit CreateChartCallback( XmlFilterBase& rFilter, const OUString& rFragmentPath, bool bEmbedShapes ); - virtual void onCreateXShape( const Reference< drawing::XShape >& rxShape, const Reference< drawing::XShapes >& rxShapes ); + virtual void onXShapeCreated( const Reference< drawing::XShape >& rxShape, const Reference< drawing::XShapes >& rxShapes ) const; private: - XmlFilterBase& mrFilter; OUString maFragmentPath; bool mbEmbedShapes; }; -// -------------------------------------------------------------------- +// ---------------------------------------------------------------------------- CreateChartCallback::CreateChartCallback( XmlFilterBase& rFilter, const OUString& rFragmentPath, bool bEmbedShapes ) : - mrFilter( rFilter ), + CreateShapeCallback( rFilter ), maFragmentPath( rFragmentPath ), mbEmbedShapes( bEmbedShapes ) { } -void CreateChartCallback::onCreateXShape( const Reference< drawing::XShape >& rxShape, const Reference< drawing::XShapes >& rxShapes ) +void CreateChartCallback::onXShapeCreated( const Reference< drawing::XShape >& rxShape, const Reference< drawing::XShapes >& rxShapes ) const { - OSL_ENSURE( maFragmentPath.getLength() > 0, "CreateChartCallback::onCreateXShape - missing chart fragment" ); + OSL_ENSURE( maFragmentPath.getLength() > 0, "CreateChartCallback::onXShapeCreated - missing chart fragment" ); if( maFragmentPath.getLength() > 0 ) try { // set the chart2 OLE class ID at the OLE shape @@ -396,28 +399,30 @@ void CreateChartCallback::onCreateXShape( const Reference< drawing::XShape >& rx } } -// ==================================================================== +// ============================================================================ -ChartGraphicDataContext::ChartGraphicDataContext( ContextHandler& rParent, ShapePtr pShapePtr, bool bEmbedShapes ) : - ShapeContext( rParent, ShapePtr(), pShapePtr ), +ChartGraphicDataContext::ChartGraphicDataContext( ContextHandler& rParent, const ShapePtr& rxShape, bool bEmbedShapes ) : + ShapeContext( rParent, ShapePtr(), rxShape ), mbEmbedShapes( bEmbedShapes ) { - pShapePtr->setServiceName( "com.sun.star.drawing.OLE2Shape" ); + rxShape->setServiceName( "com.sun.star.drawing.OLE2Shape" ); } Reference< XFastContextHandler > ChartGraphicDataContext::createFastChildContext( ::sal_Int32 nElement, const Reference< XFastAttributeList >& rxAttribs ) throw (SAXException, RuntimeException) { - if( nElement == (NMSP_CHART | XML_chart) ) + if( nElement == C_TOKEN( chart ) ) { AttributeList aAttribs( rxAttribs ); - OUString aFragmentPath = getFragmentPathFromRelId( aAttribs.getString( NMSP_RELATIONSHIPS | XML_id, OUString() ) ); + OUString aFragmentPath = getFragmentPathFromRelId( aAttribs.getString( R_TOKEN( id ), OUString() ) ); CreateShapeCallbackRef xCallback( new CreateChartCallback( getFilter(), aFragmentPath, mbEmbedShapes ) ); mpShapePtr->setCreateShapeCallback( xCallback ); } return 0; } -// ==================================================================== +// ============================================================================ + +} // namespace drawingml +} // namespace oox -} } diff --git a/oox/source/drawingml/hyperlinkcontext.cxx b/oox/source/drawingml/hyperlinkcontext.cxx index 8759f59eddcd..7335f2cc4dfd 100644 --- a/oox/source/drawingml/hyperlinkcontext.cxx +++ b/oox/source/drawingml/hyperlinkcontext.cxx @@ -37,7 +37,6 @@ #include "oox/helper/propertymap.hxx" #include "oox/core/relations.hxx" #include "oox/core/namespaces.hxx" -#include "oox/core/skipcontext.hxx" #include "oox/core/xmlfilterbase.hxx" #include "oox/drawingml/embeddedwavaudiofile.hxx" #include "properties.hxx" @@ -56,33 +55,106 @@ HyperLinkContext::HyperLinkContext( ContextHandler& rParent, : ContextHandler( rParent ) , maProperties(aProperties) { + OUString sURL, sHref; OUString aRelId = xAttributes->getOptionalValue( NMSP_RELATIONSHIPS|XML_id ); - OSL_TRACE("OOX: URI rId %s", ::rtl::OUStringToOString (aRelId, RTL_TEXTENCODING_UTF8).pData->buffer); - const OUString& sHref = getRelations().getTargetFromRelId( aRelId ); - if( sHref.getLength() > 0 ) + if ( aRelId.getLength() ) { - OSL_TRACE("OOX: URI href %s", ::rtl::OUStringToOString (sHref, RTL_TEXTENCODING_UTF8).pData->buffer); - maProperties[ PROP_URL ] <<= getFilter().getAbsoluteUrl( sHref ); - OUString sTooltip = xAttributes->getOptionalValue( NMSP_RELATIONSHIPS|XML_tooltip ); + OSL_TRACE("OOX: URI rId %s", ::rtl::OUStringToOString (aRelId, RTL_TEXTENCODING_UTF8).pData->buffer); + sHref = getRelations().getExternalTargetFromRelId( aRelId ); + if( sHref.getLength() > 0 ) + { + OSL_TRACE("OOX: URI href %s", ::rtl::OUStringToOString (sHref, RTL_TEXTENCODING_UTF8).pData->buffer); + sURL = getFilter().getAbsoluteUrl( sHref ); + } + } + OUString sTooltip = xAttributes->getOptionalValue( NMSP_RELATIONSHIPS|XML_tooltip ); + if ( sTooltip.getLength() ) maProperties[ PROP_Representation ] <<= sTooltip; + OUString sFrame = xAttributes->getOptionalValue( NMSP_RELATIONSHIPS|XML_tgtFrame ); + if( sFrame.getLength() ) + maProperties[ PROP_TargetFrame ] <<= sFrame; + OUString aAction = xAttributes->getOptionalValue( XML_action ); + if ( aAction.getLength() ) + { + // reserved values of the unrestricted string aAction: + // ppaction://customshow?id=SHOW_ID // custom presentation + // ppaction://hlinkfile // external file via r:id + // ppaction://hlinkpres?slideindex=SLIDE_NUM // external presentation via r:id + // ppaction://hlinkshowjump?jump=endshow + // ppaction://hlinkshowjump?jump=firstslide + // ppaction://hlinkshowjump?jump=lastslide + // ppaction://hlinkshowjump?jump=lastslideviewed + // ppaction://hlinkshowjump?jump=nextslide + // ppaction://hlinkshowjump?jump=previousslide + // ppaction://hlinksldjump + // ppaction://macro?name=MACRO_NAME + // ppaction://program - OUString sFrame = xAttributes->getOptionalValue( NMSP_RELATIONSHIPS|XML_tgtFrame ); - if( sFrame.getLength() ) - maProperties[ PROP_TargetFrame ] <<= sFrame; + const OUString sPPAction( CREATE_OUSTRING( "ppaction://" ) ); + if ( aAction.matchIgnoreAsciiCase( sPPAction, 0 ) ) + { + OUString aPPAct( aAction.copy( sPPAction.getLength() ) ); + sal_Int32 nIndex = aPPAct.indexOf( '?', 0 ); + OUString aPPAction( nIndex > 0 ? aPPAct.copy( 0, nIndex ) : aPPAct ); -// sValue = OUString( RTL_CONSTASCII_USTRINGPARAM( "" ) ); -// const rtl::OUString sUnvisitedCharStyleName( CREATE_OUSTRING( "UnvisitedCharStyleName" ) ); -// maProperties[ sUnvisitedCharStyleName ] <<= sValue; -// const rtl::OUString sVisitedCharStyleName( CREATE_OUSTRING( "VisitedCharStyleName" ) ); -// maProperties[ sVisitedCharStyleName ] <<= sValue; + const OUString sHlinkshowjump( CREATE_OUSTRING( "hlinkshowjump" ) ); + const OUString sHlinksldjump( CREATE_OUSTRING( "hlinksldjump" ) ); + if ( aPPAction.match( sHlinkshowjump ) ) + { + const OUString sJump( CREATE_OUSTRING( "jump=" ) ); + if ( aPPAct.match( sJump, nIndex + 1 ) ) + { + OUString aDestination( aPPAct.copy( nIndex + 1 + sJump.getLength() ) ); + sURL = sURL.concat( CREATE_OUSTRING( "#action?jump=" ) ); + sURL = sURL.concat( aDestination ); + } + } + else if ( aPPAction.match( sHlinksldjump ) ) + { + sURL = OUString(); + sal_Int32 nIndex2 = 0; + while ( nIndex2 < sHref.getLength() ) + { + sal_Unicode nChar = sHref[ nIndex2 ]; + if ( ( nChar >= '0' ) && ( nChar <= '9' ) ) + break; + nIndex2++; + } + if ( nIndex2 && ( nIndex2 != sHref.getLength() ) ) + { + sal_Int32 nLength = 1; + while( ( nIndex2 + nLength ) < sHref.getLength() ) + { + sal_Unicode nChar = sHref[ nIndex2 + nLength ]; + if ( ( nChar < '0' ) || ( nChar > '9' ) ) + break; + nLength++; + } + sal_Int32 nPageNumber = sHref.copy( nIndex2, nLength ).toInt32(); + if ( nPageNumber ) + { + const OUString sSlide( CREATE_OUSTRING( "slide" ) ); + const OUString sNotesSlide( CREATE_OUSTRING( "notesSlide" ) ); + const OUString aSlideType( sHref.copy( 0, nIndex2 ) ); + if ( aSlideType.match( sSlide ) ) + sURL = CREATE_OUSTRING( "#Slide " ).concat( rtl::OUString::valueOf( nPageNumber ) ); + else if ( aSlideType.match( sNotesSlide ) ) + sURL = CREATE_OUSTRING( "#Notes " ).concat( rtl::OUString::valueOf( nPageNumber ) ); +// else: todo for other types such as notesMaster or slideMaster as they can't be referenced easily + } + } + } + } } + if ( sURL.getLength() ) + maProperties[ PROP_URL ] <<= sURL; + // TODO unhandled // XML_invalidUrl // XML_history // XML_highlightClick // XML_endSnd - // XML_action } HyperLinkContext::~HyperLinkContext() @@ -96,8 +168,7 @@ Reference< XFastContextHandler > HyperLinkContext::createFastChildContext( switch( aElement ) { case NMSP_DRAWINGML|XML_extLst: - xRet.set( new SkipContext( *this ) ); - break; + return xRet; case NMSP_DRAWINGML|XML_snd: EmbeddedWAVAudioFile aAudio; getEmbeddedWAVAudioFile( getRelations(), xAttribs, aAudio ); diff --git a/oox/source/drawingml/lineproperties.cxx b/oox/source/drawingml/lineproperties.cxx index d072082b0045..7f31bc05cb7e 100644 --- a/oox/source/drawingml/lineproperties.cxx +++ b/oox/source/drawingml/lineproperties.cxx @@ -38,14 +38,14 @@ #include <com/sun/star/drawing/LineStyle.hpp> #include <com/sun/star/drawing/PointSequence.hpp> #include <com/sun/star/drawing/PolyPolygonBezierCoords.hpp> -#include "oox/drawingml/drawingmltypes.hxx" -#include "oox/core/modelobjectcontainer.hxx" -#include "oox/core/namespaces.hxx" -#include "oox/core/xmlfilterbase.hxx" -#include "oox/helper/propertymap.hxx" -#include "oox/helper/propertyset.hxx" #include "properties.hxx" #include "tokens.hxx" +#include "oox/helper/modelobjecthelper.hxx" +#include "oox/helper/propertymap.hxx" +#include "oox/helper/propertyset.hxx" +#include "oox/core/namespaces.hxx" +#include "oox/core/xmlfilterbase.hxx" +#include "oox/drawingml/drawingmltypes.hxx" using namespace ::com::sun::star::drawing; @@ -55,7 +55,6 @@ using ::com::sun::star::uno::Any; using ::com::sun::star::uno::Reference; using ::com::sun::star::awt::Point; using ::com::sun::star::container::XNameContainer; -using ::oox::core::ModelObjectContainer; using ::oox::core::XmlFilterBase; namespace oox { @@ -123,7 +122,7 @@ sal_Int32 lclGetArrowSize( sal_Int32 nToken ) // ---------------------------------------------------------------------------- void lclPushMarkerProperties( PropertyMap& rPropMap, const LineArrowProperties& rArrowProps, - const LinePropertyIds& rPropIds, ModelObjectContainer& rObjContainer, sal_Int32 nLineWidth, bool bLineEnd ) + const LinePropertyIds& rPropIds, ModelObjectHelper& rModelObjHelper, sal_Int32 nLineWidth, bool bLineEnd ) { PolyPolygonBezierCoords aMarker; OUString aMarkerName; @@ -182,7 +181,7 @@ void lclPushMarkerProperties( PropertyMap& rPropMap, const LineArrowProperties& nMarkerWidth = static_cast< sal_Int32 >( fArrowWidth * nApiLineWidth ); // test if the arrow already exists, do not create it again in this case - if( !rPropIds.mbNamedLineMarker || !rObjContainer.hasLineMarker( aMarkerName ) ) + if( !rPropIds.mbNamedLineMarker || !rModelObjHelper.hasLineMarker( aMarkerName ) ) { // pass X and Y as percentage to OOX_ARROW_POINT #define OOX_ARROW_POINT( x, y ) Point( static_cast< sal_Int32 >( fArrowWidth * x ), static_cast< sal_Int32 >( fArrowLength * y ) ) @@ -247,7 +246,7 @@ void lclPushMarkerProperties( PropertyMap& rPropMap, const LineArrowProperties& aMarker.Flags.realloc( 1 ); aMarker.Flags[ 0 ] = ContainerHelper::vectorToSequence( aFlags ); - if( rPropIds.mbNamedLineMarker && !rObjContainer.insertLineMarker( aMarkerName, aMarker ) ) + if( rPropIds.mbNamedLineMarker && !rModelObjHelper.insertLineMarker( aMarkerName, aMarker ) ) aMarkerName = OUString(); } else @@ -318,7 +317,7 @@ void LineProperties::assignUsed( const LineProperties& rSourceProps ) } void LineProperties::pushToPropMap( PropertyMap& rPropMap, const LinePropertyIds& rPropIds, - const XmlFilterBase& rFilter, ModelObjectContainer& rObjContainer, sal_Int32 nPhClr ) const + const XmlFilterBase& rFilter, ModelObjectHelper& rModelObjHelper, sal_Int32 nPhClr ) const { // line fill type must exist, otherwise ignore other properties if( maLineFill.moFillType.has() ) @@ -375,7 +374,7 @@ void LineProperties::pushToPropMap( PropertyMap& rPropMap, const LinePropertyIds if( rPropIds.mbNamedLineDash ) { - OUString aDashName = rObjContainer.insertLineDash( aLineDash ); + OUString aDashName = rModelObjHelper.insertLineDash( aLineDash ); if( aDashName.getLength() > 0 ) { rPropMap.setProperty( rPropIds[ LineDashId ], aDashName ); @@ -410,16 +409,16 @@ void LineProperties::pushToPropMap( PropertyMap& rPropMap, const LinePropertyIds } // line markers - lclPushMarkerProperties( rPropMap, maStartArrow, rPropIds, rObjContainer, moLineWidth.get( 0 ), false ); - lclPushMarkerProperties( rPropMap, maEndArrow, rPropIds, rObjContainer, moLineWidth.get( 0 ), true ); + lclPushMarkerProperties( rPropMap, maStartArrow, rPropIds, rModelObjHelper, moLineWidth.get( 0 ), false ); + lclPushMarkerProperties( rPropMap, maEndArrow, rPropIds, rModelObjHelper, moLineWidth.get( 0 ), true ); } } void LineProperties::pushToPropSet( PropertySet& rPropSet, const LinePropertyIds& rPropIds, - const XmlFilterBase& rFilter, ModelObjectContainer& rObjContainer, sal_Int32 nPhClr ) const + const XmlFilterBase& rFilter, ModelObjectHelper& rModelObjHelper, sal_Int32 nPhClr ) const { PropertyMap aPropMap; - pushToPropMap( aPropMap, rPropIds, rFilter, rObjContainer, nPhClr ); + pushToPropMap( aPropMap, rPropIds, rFilter, rModelObjHelper, nPhClr ); rPropSet.setProperties( aPropMap ); } diff --git a/oox/source/drawingml/linepropertiescontext.cxx b/oox/source/drawingml/linepropertiescontext.cxx index b7e9f88f9636..b98f30738ec0 100644 --- a/oox/source/drawingml/linepropertiescontext.cxx +++ b/oox/source/drawingml/linepropertiescontext.cxx @@ -67,31 +67,31 @@ Reference< XFastContextHandler > LinePropertiesContext::createFastChildContext( switch( nElement ) { // LineFillPropertiesGroup - case NMSP_DRAWINGML|XML_noFill: - case NMSP_DRAWINGML|XML_solidFill: - case NMSP_DRAWINGML|XML_gradFill: - case NMSP_DRAWINGML|XML_pattFill: - xRet = FillPropertiesGroupContext::StaticCreateContext( *this, nElement, xAttribs, mrLineProperties.maLineFill ); + case A_TOKEN( noFill ): + case A_TOKEN( solidFill ): + case A_TOKEN( gradFill ): + case A_TOKEN( pattFill ): + xRet = FillPropertiesContext::createFillContext( *this, nElement, xAttribs, mrLineProperties.maLineFill ); break; // LineDashPropertiesGroup - case NMSP_DRAWINGML|XML_prstDash: // CT_PresetLineDashProperties + case A_TOKEN( prstDash ): // CT_PresetLineDashProperties mrLineProperties.moPresetDash = aAttribs.getToken( XML_val ); break; - case NMSP_DRAWINGML|XML_custDash: // CT_DashStopList + case A_TOKEN( custDash ): // CT_DashStopList break; // LineJoinPropertiesGroup - case NMSP_DRAWINGML|XML_round: - case NMSP_DRAWINGML|XML_bevel: - case NMSP_DRAWINGML|XML_miter: + case A_TOKEN( round ): + case A_TOKEN( bevel ): + case A_TOKEN( miter ): mrLineProperties.moLineJoint = getToken( nElement ); break; - case NMSP_DRAWINGML|XML_headEnd: // CT_LineEndProperties - case NMSP_DRAWINGML|XML_tailEnd: // CT_LineEndProperties + case A_TOKEN( headEnd ): // CT_LineEndProperties + case A_TOKEN( tailEnd ): // CT_LineEndProperties { // ST_LineEndType - bool bTailEnd = nElement == (NMSP_DRAWINGML|XML_tailEnd); + bool bTailEnd = nElement == A_TOKEN( tailEnd ); LineArrowProperties& rArrowProps = bTailEnd ? mrLineProperties.maEndArrow : mrLineProperties.maStartArrow; rArrowProps.moArrowType = aAttribs.getToken( XML_type ); rArrowProps.moArrowWidth = aAttribs.getToken( XML_w ); diff --git a/oox/source/drawingml/makefile.mk b/oox/source/drawingml/makefile.mk index 84dc3f306bfd..329d748288b1 100644 --- a/oox/source/drawingml/makefile.mk +++ b/oox/source/drawingml/makefile.mk @@ -68,7 +68,6 @@ SLOFILES = \ $(SLO)$/shapepropertiescontext.obj\ $(SLO)$/shapestylecontext.obj\ $(SLO)$/spdefcontext.obj\ - $(SLO)$/stylematrixreferencecontext.obj\ $(SLO)$/textbody.obj\ $(SLO)$/textbodycontext.obj\ $(SLO)$/textbodypropertiescontext.obj\ diff --git a/oox/source/drawingml/shape.cxx b/oox/source/drawingml/shape.cxx index cbb84136fccc..f7cfed3270eb 100644 --- a/oox/source/drawingml/shape.cxx +++ b/oox/source/drawingml/shape.cxx @@ -65,16 +65,30 @@ namespace oox { namespace drawingml { // ============================================================================ +CreateShapeCallback::CreateShapeCallback( XmlFilterBase& rFilter ) : + mrFilter( rFilter ) +{ +} + CreateShapeCallback::~CreateShapeCallback() { } +OUString CreateShapeCallback::onCreateXShape( const OUString& rServiceName, const Rectangle& ) +{ + return rServiceName; +} + +void CreateShapeCallback::onXShapeCreated( const Reference< XShape >&, const Reference< XShapes >& ) const +{ +} + // ============================================================================ Shape::Shape( const sal_Char* pServiceName ) : mpLinePropertiesPtr( new LineProperties ) , mpFillPropertiesPtr( new FillProperties ) -, mpGraphicPropertiesPtr( new FillProperties ) +, mpGraphicPropertiesPtr( new GraphicProperties ) , mpCustomShapePropertiesPtr( new CustomShapeProperties ) , mpMasterTextListStyle( new TextListStyle ) , mnSubType( 0 ) @@ -134,7 +148,7 @@ void Shape::addShape( rtl::OUString sServiceName( msServiceName ); if( sServiceName.getLength() ) { - Reference< XShape > xShape( createAndInsert( rFilterBase, sServiceName, pTheme, rxShapes, pShapeRect ) ); + Reference< XShape > xShape( createAndInsert( rFilterBase, sServiceName, pTheme, rxShapes, pShapeRect, sal_False ) ); if( pShapeMap && msId.getLength() ) { @@ -233,12 +247,17 @@ Reference< XShape > Shape::createAndInsert( const rtl::OUString& rServiceName, const Theme* pTheme, const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShapes >& rxShapes, - const awt::Rectangle* pShapeRect ) + const awt::Rectangle* pShapeRect, + sal_Bool bClearText ) { - basegfx::B2DHomMatrix aTransformation; - awt::Size aSize( pShapeRect ? awt::Size( pShapeRect->Width, pShapeRect->Height ) : maSize ); awt::Point aPosition( pShapeRect ? awt::Point( pShapeRect->X, pShapeRect->Y ) : maPosition ); + + OUString aServiceName = rServiceName; + if( mxCreateCallback.get() ) + aServiceName = mxCreateCallback->onCreateXShape( aServiceName, awt::Rectangle( aPosition.X / 360, aPosition.Y / 360, aSize.Width / 360, aSize.Height / 360 ) ); + + basegfx::B2DHomMatrix aTransformation; if( aSize.Width != 1 || aSize.Height != 1) { // take care there are no zeros used by error @@ -279,7 +298,7 @@ Reference< XShape > Shape::createAndInsert( } // special for lineshape - if ( rServiceName == OUString::createFromAscii( "com.sun.star.drawing.LineShape" ) ) + if ( aServiceName == OUString::createFromAscii( "com.sun.star.drawing.LineShape" ) ) { ::basegfx::B2DPolygon aPoly; aPoly.insert( 0, ::basegfx::B2DPoint( 0, 0 ) ); @@ -300,7 +319,7 @@ Reference< XShape > Shape::createAndInsert( maShapeProperties[ PROP_PolyPolygon ] <<= aPolyPolySequence; } - else if ( rServiceName == OUString::createFromAscii( "com.sun.star.drawing.ConnectorShape" ) ) + else if ( aServiceName == OUString::createFromAscii( "com.sun.star.drawing.ConnectorShape" ) ) { ::basegfx::B2DPolygon aPoly; aPoly.insert( 0, ::basegfx::B2DPoint( 0, 0 ) ); @@ -336,7 +355,7 @@ Reference< XShape > Shape::createAndInsert( } Reference< lang::XMultiServiceFactory > xServiceFact( rFilterBase.getModel(), UNO_QUERY_THROW ); if ( !mxShape.is() ) - mxShape = Reference< drawing::XShape >( xServiceFact->createInstance( rServiceName ), UNO_QUERY_THROW ); + mxShape = Reference< drawing::XShape >( xServiceFact->createInstance( aServiceName ), UNO_QUERY_THROW ); Reference< XPropertySet > xSet( mxShape, UNO_QUERY ); if( mxShape.is() && xSet.is() ) @@ -349,6 +368,17 @@ Reference< XShape > Shape::createAndInsert( } rxShapes->add( mxShape ); + // sj: removing default text of placeholder objects such as SlideNumberShape or HeaderShape + if ( bClearText ) + { + uno::Reference< text::XText > xText( mxShape, uno::UNO_QUERY ); + if ( xText.is() ) + { + OUString aEmpty; + xText->setString( aEmpty ); + } + } + LineProperties aLineProperties; aLineProperties.maLineFill.moFillType = XML_noFill; sal_Int32 nLinePhClr = -1; @@ -383,6 +413,8 @@ Reference< XShape > Shape::createAndInsert( PropertyMap aShapeProperties; aShapeProperties.insert( getShapeProperties().begin(), getShapeProperties().end() ); + if( mxCreateCallback.get() ) + aShapeProperties.insert( mxCreateCallback->getShapeProperties().begin(), mxCreateCallback->getShapeProperties().end() ); // add properties from textbody to shape properties if( mpTextBody.get() ) @@ -390,12 +422,12 @@ Reference< XShape > Shape::createAndInsert( // applying properties PropertySet aPropSet( xSet ); - if ( rServiceName == OUString::createFromAscii( "com.sun.star.drawing.GraphicObjectShape" ) ) - mpGraphicPropertiesPtr->pushToPropSet( aPropSet, FillProperties::DEFAULT_PICIDS, rFilterBase, rFilterBase.getModelObjectContainer(), 0, -1 ); - if ( mpTablePropertiesPtr.get() && ( rServiceName == OUString::createFromAscii( "com.sun.star.drawing.TableShape" ) ) ) + if ( aServiceName == OUString::createFromAscii( "com.sun.star.drawing.GraphicObjectShape" ) ) + mpGraphicPropertiesPtr->pushToPropSet( aPropSet, rFilterBase, -1 ); + if ( mpTablePropertiesPtr.get() && ( aServiceName == OUString::createFromAscii( "com.sun.star.drawing.TableShape" ) ) ) mpTablePropertiesPtr->pushToPropSet( rFilterBase, xSet, mpMasterTextListStyle ); - aFillProperties.pushToPropSet( aPropSet, FillProperties::DEFAULT_IDS, rFilterBase, rFilterBase.getModelObjectContainer(), mnRotation, nFillPhClr ); - aLineProperties.pushToPropSet( aPropSet, LineProperties::DEFAULT_IDS, rFilterBase, rFilterBase.getModelObjectContainer(), nLinePhClr ); + aFillProperties.pushToPropSet( aPropSet, FillProperties::DEFAULT_IDS, rFilterBase, rFilterBase.getModelObjectHelper(), mnRotation, nFillPhClr ); + aLineProperties.pushToPropSet( aPropSet, LineProperties::DEFAULT_IDS, rFilterBase, rFilterBase.getModelObjectHelper(), nLinePhClr ); // applying autogrowheight property before setting shape size, because // the shape size might be changed if currently autogrowheight is true @@ -406,9 +438,11 @@ Reference< XShape > Shape::createAndInsert( if( /*const Any* pAutoGrowHeight =*/ aShapeProperties.getProperty( PROP_TextAutoGrowHeight ) ) xSet->setPropertyValue( rPropName, Any( false ) ); - aPropSet.setProperties( aShapeProperties ); + // do not set properties at a group shape (this causes assertions from svx) + if( aServiceName != OUString::createFromAscii( "com.sun.star.drawing.GroupShape" ) ) + aPropSet.setProperties( aShapeProperties ); - if( rServiceName == OUString::createFromAscii( "com.sun.star.drawing.CustomShape" ) ) + if( aServiceName == OUString::createFromAscii( "com.sun.star.drawing.CustomShape" ) ) mpCustomShapePropertiesPtr->pushToPropSet( rFilterBase, xSet, mxShape ); // in some cases, we don't have any text body. @@ -434,7 +468,7 @@ Reference< XShape > Shape::createAndInsert( // use a callback for further processing on the XShape (e.g. charts) if( mxShape.is() && mxCreateCallback.get() ) - mxCreateCallback->onCreateXShape( mxShape, rxShapes ); + mxCreateCallback->onXShapeCreated( mxShape, rxShapes ); return mxShape; } diff --git a/oox/source/drawingml/shapepropertiescontext.cxx b/oox/source/drawingml/shapepropertiescontext.cxx index 96ea1dc19f3d..bfef3bdcf922 100644 --- a/oox/source/drawingml/shapepropertiescontext.cxx +++ b/oox/source/drawingml/shapepropertiescontext.cxx @@ -116,7 +116,7 @@ Reference< XFastContextHandler > ShapePropertiesContext::createFastChildContext( // FillPropertiesGroupContext if( !xRet.is() ) - xRet.set( FillPropertiesGroupContext::StaticCreateContext( *this, aElementToken, xAttribs, mrShape.getFillProperties() ) ); + xRet.set( FillPropertiesContext::createFillContext( *this, aElementToken, xAttribs, mrShape.getFillProperties() ) ); return xRet; } diff --git a/oox/source/drawingml/shapestylecontext.cxx b/oox/source/drawingml/shapestylecontext.cxx index 6b5edc84dc97..8b82d2933dc2 100644 --- a/oox/source/drawingml/shapestylecontext.cxx +++ b/oox/source/drawingml/shapestylecontext.cxx @@ -33,7 +33,6 @@ #include "oox/helper/attributelist.hxx" #include "oox/core/namespaces.hxx" #include "oox/drawingml/colorchoicecontext.hxx" -#include "oox/drawingml/stylematrixreferencecontext.hxx" #include "tokens.hxx" using ::rtl::OUString; @@ -79,7 +78,7 @@ Reference< XFastContextHandler > ShapeStyleContext::createFastChildContext( sal_ sal_Int32 nToken = getToken( aElementToken ); ShapeStyleRef& rStyleRef = mrShape.getShapeStyleRefs()[ nToken ]; rStyleRef.mnThemedIdx = (nToken == XML_fontRef) ? aAttribs.getToken( XML_idx, XML_none ) : aAttribs.getInteger( XML_idx, 0 ); - xRet.set( new StyleMatrixReferenceContext( *this, rStyleRef.maPhClr ) ); + xRet.set( new ColorContext( *this, rStyleRef.maPhClr ) ); } break; } diff --git a/oox/source/drawingml/table/tablebackgroundstylecontext.cxx b/oox/source/drawingml/table/tablebackgroundstylecontext.cxx index 80832a80d6e0..48c07e348071 100644 --- a/oox/source/drawingml/table/tablebackgroundstylecontext.cxx +++ b/oox/source/drawingml/table/tablebackgroundstylecontext.cxx @@ -30,7 +30,6 @@ #include <osl/diagnose.h> -#include "oox/drawingml/stylematrixreferencecontext.hxx" #include "oox/drawingml/table/tablebackgroundstylecontext.hxx" #include "oox/drawingml/fillpropertiesgroupcontext.hxx" #include "oox/core/namespaces.hxx" @@ -66,16 +65,16 @@ TableBackgroundStyleContext::createFastChildContext( ::sal_Int32 aElementToken, // EG_ThemeableFillStyle (choice) case NMSP_DRAWINGML|XML_fill: // CT_FillProperties { - boost::shared_ptr< oox::drawingml::FillProperties >& rFillProperties( mrTableStyle.getBackgroundFillProperties() ); - rFillProperties = boost::shared_ptr< oox::drawingml::FillProperties > ( new oox::drawingml::FillProperties() ); - xRet.set( new oox::drawingml::FillPropertiesContext( *this, *rFillProperties.get() ) ); + boost::shared_ptr< FillProperties >& rxFillProperties = mrTableStyle.getBackgroundFillProperties(); + rxFillProperties.reset( new FillProperties ); + xRet.set( new FillPropertiesContext( *this, *rxFillProperties ) ); } break; case NMSP_DRAWINGML|XML_fillRef: // CT_StyleMatrixReference { ShapeStyleRef& rStyleRef = mrTableStyle.getBackgroundFillStyleRef(); rStyleRef.mnThemedIdx = aAttribs.getInteger( XML_idx, 0 ); - xRet.set( new StyleMatrixReferenceContext( *this, rStyleRef.maPhClr ) ); + xRet.set( new ColorContext( *this, rStyleRef.maPhClr ) ); } break; diff --git a/oox/source/drawingml/table/tablecell.cxx b/oox/source/drawingml/table/tablecell.cxx index d0b48048cbd8..58aaf9081385 100644 --- a/oox/source/drawingml/table/tablecell.cxx +++ b/oox/source/drawingml/table/tablecell.cxx @@ -364,7 +364,7 @@ void TableCell::pushToXCell( const ::oox::core::XmlFilterBase& rFilterBase, ::oo PropertySet aPropSet( xPropSet ); // TODO: phClr? aFillProperties.pushToPropSet( aPropSet, FillProperties::DEFAULT_IDS, - rFilterBase, rFilterBase.getModelObjectContainer(), 0, -1 ); + rFilterBase, rFilterBase.getModelObjectHelper(), 0, -1 ); } } } } diff --git a/oox/source/drawingml/table/tablecellcontext.cxx b/oox/source/drawingml/table/tablecellcontext.cxx index c61e9fce9f64..1ebb4294f330 100644 --- a/oox/source/drawingml/table/tablecellcontext.cxx +++ b/oox/source/drawingml/table/tablecellcontext.cxx @@ -115,7 +115,7 @@ TableCellContext::createFastChildContext( ::sal_Int32 aElementToken, const uno:: break; default: - xRet.set( oox::drawingml::FillPropertiesGroupContext::StaticCreateContext( *this, aElementToken, xAttribs, mrTableCell.maFillProperties ) ); + xRet.set( FillPropertiesContext::createFillContext( *this, aElementToken, xAttribs, mrTableCell.maFillProperties ) ); break; } diff --git a/oox/source/drawingml/table/tablestylecellstylecontext.cxx b/oox/source/drawingml/table/tablestylecellstylecontext.cxx index efd38d1f601e..fa550d9e66a4 100644 --- a/oox/source/drawingml/table/tablestylecellstylecontext.cxx +++ b/oox/source/drawingml/table/tablestylecellstylecontext.cxx @@ -33,7 +33,6 @@ #include "oox/drawingml/table/tablestylecellstylecontext.hxx" #include "oox/drawingml/fillpropertiesgroupcontext.hxx" #include "oox/drawingml/linepropertiescontext.hxx" -#include "oox/drawingml/stylematrixreferencecontext.hxx" #include "oox/core/namespaces.hxx" #include "oox/helper/attributelist.hxx" #include "tokens.hxx" @@ -95,7 +94,7 @@ TableStyleCellStyleContext::createFastChildContext( ::sal_Int32 aElementToken, c { ShapeStyleRef& rLineStyleRef = mrTableStylePart.getStyleRefs()[ mnLineType ]; rLineStyleRef.mnThemedIdx = aAttribs.getInteger( XML_idx, 0 ); - xRet.set( new StyleMatrixReferenceContext( *this, rLineStyleRef.maPhClr ) ); + xRet.set( new ColorContext( *this, rLineStyleRef.maPhClr ) ); } } break; @@ -103,16 +102,16 @@ TableStyleCellStyleContext::createFastChildContext( ::sal_Int32 aElementToken, c // EG_ThemeableFillStyle (choice) case NMSP_DRAWINGML|XML_fill: // CT_FillProperties { - oox::drawingml::FillPropertiesPtr& rFillProperties( mrTableStylePart.getFillProperties() ); - rFillProperties.reset( new oox::drawingml::FillProperties ); - xRet.set( new oox::drawingml::FillPropertiesContext( *this, *rFillProperties ) ); + FillPropertiesPtr& rxFillProperties = mrTableStylePart.getFillProperties(); + rxFillProperties.reset( new FillProperties ); + xRet.set( new FillPropertiesContext( *this, *rxFillProperties ) ); } break; case NMSP_DRAWINGML|XML_fillRef: // CT_StyleMatrixReference { ShapeStyleRef& rStyleRef = mrTableStylePart.getStyleRefs()[ XML_fillRef ]; rStyleRef.mnThemedIdx = aAttribs.getInteger( XML_idx, 0 ); - xRet.set( new StyleMatrixReferenceContext( *this, rStyleRef.maPhClr ) ); + xRet.set( new ColorContext( *this, rStyleRef.maPhClr ) ); } break; diff --git a/oox/source/drawingml/table/tablestyletextstylecontext.cxx b/oox/source/drawingml/table/tablestyletextstylecontext.cxx index c5caa0361fba..3e46882b459e 100644 --- a/oox/source/drawingml/table/tablestyletextstylecontext.cxx +++ b/oox/source/drawingml/table/tablestyletextstylecontext.cxx @@ -32,7 +32,6 @@ #include "oox/drawingml/table/tablestyletextstylecontext.hxx" #include "oox/drawingml/colorchoicecontext.hxx" -#include "oox/drawingml/stylematrixreferencecontext.hxx" #include "oox/core/namespaces.hxx" #include "oox/helper/attributelist.hxx" #include "tokens.hxx" @@ -97,7 +96,7 @@ TableStyleTextStyleContext::createFastChildContext( ::sal_Int32 aElementToken, c { ShapeStyleRef& rFontStyle = mrTableStylePart.getStyleRefs()[ XML_fontRef ]; rFontStyle.mnThemedIdx = aAttribs.getToken( XML_idx, XML_none ); - xRet.set( new StyleMatrixReferenceContext( *this, rFontStyle.maPhClr ) ); + xRet.set( new ColorContext( *this, rFontStyle.maPhClr ) ); } break; @@ -105,7 +104,7 @@ TableStyleTextStyleContext::createFastChildContext( ::sal_Int32 aElementToken, c break; } if( !xRet.is() ) - xRet.set( new colorChoiceContext( *this, mrTableStylePart.getTextColor() ) ); + xRet.set( new ColorValueContext( *this, mrTableStylePart.getTextColor() ) ); return xRet; } diff --git a/oox/source/drawingml/textcharacterpropertiescontext.cxx b/oox/source/drawingml/textcharacterpropertiescontext.cxx index efc8e8fa4192..07c16b02080f 100644 --- a/oox/source/drawingml/textcharacterpropertiescontext.cxx +++ b/oox/source/drawingml/textcharacterpropertiescontext.cxx @@ -116,7 +116,7 @@ Reference< XFastContextHandler > TextCharacterPropertiesContext::createFastChild // break; case NMSP_DRAWINGML|XML_solidFill: // EG_FillProperties - xRet.set( new colorChoiceContext( *this, mrTextCharacterProperties.maCharColor ) ); + xRet.set( new ColorContext( *this, mrTextCharacterProperties.maCharColor ) ); break; // EG_EffectProperties @@ -125,7 +125,7 @@ Reference< XFastContextHandler > TextCharacterPropertiesContext::createFastChild break; case NMSP_DRAWINGML|XML_highlight: // CT_Color - xRet.set( new colorChoiceContext( *this, mrTextCharacterProperties.maHighlightColor ) ); + xRet.set( new ColorContext( *this, mrTextCharacterProperties.maHighlightColor ) ); break; // EG_TextUnderlineLine @@ -142,7 +142,7 @@ Reference< XFastContextHandler > TextCharacterPropertiesContext::createFastChild mrTextCharacterProperties.moUnderlineFillFollowText = true; break; case NMSP_DRAWINGML|XML_uFill: // CT_TextUnderlineFillGroupWrapper->EG_FillProperties (not supported) - xRet.set( new colorChoiceContext( *this, mrTextCharacterProperties.maUnderlineColor ) ); + xRet.set( new SimpleFillPropertiesContext( *this, mrTextCharacterProperties.maUnderlineColor ) ); break; // CT_FontCollection diff --git a/oox/source/drawingml/textparagraphpropertiescontext.cxx b/oox/source/drawingml/textparagraphpropertiescontext.cxx index 2d689ac630f1..4c4f61e4a822 100644 --- a/oox/source/drawingml/textparagraphpropertiescontext.cxx +++ b/oox/source/drawingml/textparagraphpropertiescontext.cxx @@ -164,8 +164,8 @@ TextParagraphPropertiesContext::~TextParagraphPropertiesContext() rPropertyMap[ PROP_ParaTabStops ] <<= aSeq; } - if ( mpFillPropertiesPtr && mpFillPropertiesPtr->mxGraphic.is() ) - mrBulletList.setGraphic( mpFillPropertiesPtr->mxGraphic ); + if ( mxBlipProps.get() && mxBlipProps->mxGraphic.is() ) + mrBulletList.setGraphic( mxBlipProps->mxGraphic ); if( mrBulletList.is() ) rPropertyMap[ PROP_IsNumbering ] <<= sal_True; @@ -205,7 +205,7 @@ Reference< XFastContextHandler > TextParagraphPropertiesContext::createFastChild mrBulletList.mbBulletColorFollowText <<= sal_True; break; case NMSP_DRAWINGML|XML_buClr: // CT_Color - xRet.set( new colorChoiceContext( *this, *mrBulletList.maBulletColorPtr ) ); + xRet.set( new ColorContext( *this, *mrBulletList.maBulletColorPtr ) ); break; // EG_TextBulletSize @@ -266,8 +266,8 @@ Reference< XFastContextHandler > TextParagraphPropertiesContext::createFastChild break; case NMSP_DRAWINGML|XML_buBlip: // CT_TextBlipBullet { - mpFillPropertiesPtr.reset( new FillProperties ); - xRet.set( new BlipFillPropertiesContext( *this, rXAttributes, *mpFillPropertiesPtr ) ); + mxBlipProps.reset( new BlipFillProperties ); + xRet.set( new BlipFillContext( *this, rXAttributes, *mxBlipProps ) ); } break; diff --git a/oox/source/drawingml/textrun.cxx b/oox/source/drawingml/textrun.cxx index 2d8422b2f018..04dcb68c053f 100644 --- a/oox/source/drawingml/textrun.cxx +++ b/oox/source/drawingml/textrun.cxx @@ -91,12 +91,21 @@ void TextRun::insertAt( Reference< XTextField > xField( xFactory->createInstance( CREATE_OUSTRING( "com.sun.star.text.TextField.URL" ) ), UNO_QUERY ); if( xField.is() ) { + Reference< XTextCursor > xTextFieldCursor = xText->createTextCursor(); + xTextFieldCursor->gotoEnd( sal_False ); + PropertySet aFieldProps( xField ); aFieldProps.setProperties( maTextCharacterProperties.maHyperlinkPropertyMap ); aFieldProps.setProperty( PROP_Representation, getText() ); - Reference< XTextContent > xContent( xField, UNO_QUERY); xText->insertTextContent( xStart, xContent, sal_False ); + + xTextFieldCursor->gotoEnd( sal_True ); + oox::core::TextField aTextField; + aTextField.xText = xText; + aTextField.xTextCursor = xTextFieldCursor; + aTextField.xTextField = xField; + rFilterBase.getTextFieldStack().push_back( aTextField ); } else { diff --git a/oox/source/drawingml/themeelementscontext.cxx b/oox/source/drawingml/themeelementscontext.cxx index 16a1cb2d7483..1b5f72666933 100644 --- a/oox/source/drawingml/themeelementscontext.cxx +++ b/oox/source/drawingml/themeelementscontext.cxx @@ -77,7 +77,7 @@ Reference< XFastContextHandler > FillStyleListContext::createFastChildContext( s case NMSP_DRAWINGML|XML_pattFill: case NMSP_DRAWINGML|XML_grpFill: mrFillStyleList.push_back( FillPropertiesPtr( new FillProperties ) ); - return FillPropertiesGroupContext::StaticCreateContext( *this, nElement, xAttribs, *mrFillStyleList.back() ); + return FillPropertiesContext::createFillContext( *this, nElement, xAttribs, *mrFillStyleList.back() ); } return 0; } diff --git a/oox/source/dump/biffdumper.cxx b/oox/source/dump/biffdumper.cxx index 110f0f5aca56..95b7da811a74 100644 --- a/oox/source/dump/biffdumper.cxx +++ b/oox/source/dump/biffdumper.cxx @@ -351,7 +351,6 @@ bool BiffObjectBase::implStartRecord( BinaryInputStream&, sal_Int64& ornRecPos, } ornRecSize = mxBiffStrm->getLength(); - mxBiffStrm->enableNulChars( true ); return bValid; } @@ -429,7 +428,7 @@ OUString BiffObjectBase::dumpByteString( const String& rName, BiffStringFlags nF OSL_ENSURE( !getFlag( nFlags, static_cast< BiffStringFlags >( ~(BIFF_STR_8BITLENGTH | BIFF_STR_EXTRAFONTS) ) ), "BiffObjectBase::dumpByteString - unknown flag" ); bool b8BitLength = getFlag( nFlags, BIFF_STR_8BITLENGTH ); - OString aString = mxBiffStrm->readByteString( !b8BitLength ); + OString aString = mxBiffStrm->readByteString( !b8BitLength, true ); FontPortionModelList aPortions; if( getFlag( nFlags, BIFF_STR_EXTRAFONTS ) ) aPortions.importPortions( *mxBiffStrm, false ); @@ -486,7 +485,7 @@ OUString BiffObjectBase::dumpUniString( const String& rName, BiffStringFlags nFl sal_uInt32 nPhoneticSize = bPhonetic ? mxBiffStrm->readuInt32() : 0; // --- character array --- - OUString aString = mxBiffStrm->readUniStringChars( nChars, b16Bit ); + OUString aString = mxBiffStrm->readUniStringChars( nChars, b16Bit, true ); writeStringItem( rName( "text" ), aString ); // --- formatting --- @@ -2096,16 +2095,16 @@ void WorkbookStreamObject::implDumpRecordBody() sal_uInt8 nDescrLen = dumpDec< sal_uInt8 >( "description-text-len" ); sal_uInt8 nHelpLen = dumpDec< sal_uInt8 >( "help-text-len" ); sal_uInt8 nStatusLen = dumpDec< sal_uInt8 >( "statusbar-text-len" ); - writeStringItem( "name", bBiff8 ? rStrm.readUniString( nNameLen ) : rStrm.readCharArray( nNameLen, eTextEnc ) ); + writeStringItem( "name", bBiff8 ? rStrm.readUniStringBody( nNameLen, true ) : rStrm.readCharArrayUC( nNameLen, eTextEnc, true ) ); getFormulaDumper().dumpNameFormula( EMPTY_STRING, nFmlaSize ); - if( nMenuLen > 0 ) writeStringItem( "menu-text", bBiff8 ? rStrm.readUniString( nMenuLen ) : rStrm.readCharArray( nMenuLen, eTextEnc ) ); - if( nDescrLen > 0 ) writeStringItem( "description-text", bBiff8 ? rStrm.readUniString( nDescrLen ) : rStrm.readCharArray( nDescrLen, eTextEnc ) ); - if( nHelpLen > 0 ) writeStringItem( "help-text", bBiff8 ? rStrm.readUniString( nHelpLen ) : rStrm.readCharArray( nHelpLen, eTextEnc ) ); - if( nStatusLen > 0 ) writeStringItem( "statusbar-text", bBiff8 ? rStrm.readUniString( nStatusLen ) : rStrm.readCharArray( nStatusLen, eTextEnc ) ); + if( nMenuLen > 0 ) writeStringItem( "menu-text", bBiff8 ? rStrm.readUniStringBody( nMenuLen, true ) : rStrm.readCharArrayUC( nMenuLen, eTextEnc, true ) ); + if( nDescrLen > 0 ) writeStringItem( "description-text", bBiff8 ? rStrm.readUniStringBody( nDescrLen, true ) : rStrm.readCharArrayUC( nDescrLen, eTextEnc, true ) ); + if( nHelpLen > 0 ) writeStringItem( "help-text", bBiff8 ? rStrm.readUniStringBody( nHelpLen, true ) : rStrm.readCharArrayUC( nHelpLen, eTextEnc, true ) ); + if( nStatusLen > 0 ) writeStringItem( "statusbar-text", bBiff8 ? rStrm.readUniStringBody( nStatusLen, true ) : rStrm.readCharArrayUC( nStatusLen, eTextEnc, true ) ); } else { - writeStringItem( "name", rStrm.readCharArray( nNameLen, eTextEnc ) ); + writeStringItem( "name", rStrm.readCharArrayUC( nNameLen, eTextEnc, true ) ); getFormulaDumper().dumpNameFormula( EMPTY_STRING, nFmlaSize ); if( eBiff == BIFF2 ) getFormulaDumper().dumpFormulaSize(); } @@ -2177,7 +2176,7 @@ void WorkbookStreamObject::implDumpRecordBody() } else { - OStringBuffer aUrl( rStrm.readByteString( false ) ); + OStringBuffer aUrl( rStrm.readByteString( false, true ) ); if( (aUrl.getLength() > 0) && (aUrl[ 0 ] == '\x03') ) aUrl.append( static_cast< sal_Char >( rStrm.readuInt8() ) ); writeStringItem( "encoded-url", OStringToOUString( aUrl.makeStringAndClear(), getBiffData().getTextEncoding() ) ); @@ -2318,7 +2317,7 @@ void WorkbookStreamObject::implDumpRecordBody() else { sal_uInt16 nTextLen = ::std::min( dumpDec< sal_uInt16 >( "text-len" ), static_cast< sal_uInt16 >( rStrm.getRemaining() ) ); - writeStringItem( "note-text", rStrm.readCharArray( nTextLen, getBiffData().getTextEncoding() ) ); + writeStringItem( "note-text", rStrm.readCharArrayUC( nTextLen, getBiffData().getTextEncoding(), true ) ); } break; @@ -2546,6 +2545,35 @@ void WorkbookStreamObject::implDumpRecordBody() } break; + case BIFF_ID_SCENARIO: + { + sal_uInt16 nCellCount = dumpDec< sal_uInt16 >( "cell-count" ); + // two bytes instead of flag field + dumpBoolean( "locked" ); + dumpBoolean( "hidden" ); + sal_uInt16 nNameLen = dumpDec< sal_uInt8 >( "name-len" ); + sal_uInt16 nCommentLen = dumpDec< sal_uInt8 >( "comment-len" ); + sal_uInt16 nUserLen = dumpDec< sal_uInt8 >( "user-len" ); + writeStringItem( "name", rStrm.readUniStringBody( nNameLen, true ) ); + if( nUserLen > 0 ) dumpUniString( "user" ); // repeated string length + if( nCommentLen > 0 ) dumpUniString( "comment" ); // repeated string length + out().resetItemIndex(); + for( sal_uInt16 nCell = 0; !rStrm.isEof() && (nCell < nCellCount); ++nCell ) + dumpAddress( "#pos" ); + out().resetItemIndex(); + for( sal_uInt16 nCell = 0; !rStrm.isEof() && (nCell < nCellCount); ++nCell ) + dumpString( "#value" ); + dumpUnused( 2 * nCellCount ); + } + break; + + case BIFF_ID_SCENARIOS: + dumpDec< sal_uInt16 >( "count" ); + dumpDec< sal_uInt16 >( "selected" ); + dumpDec< sal_uInt16 >( "shown" ); + dumpRangeList( "result-cells" ); + break; + case BIFF_ID_SCL: { sal_uInt16 nNum = dumpDec< sal_uInt16 >( "numerator" ); @@ -2768,7 +2796,7 @@ OUString WorkbookStreamObject::dumpPivotString( const String& rName, sal_uInt16 { aString = (getBiff() == BIFF8) ? getBiffStream().readUniString( nStrLen ) : - getBiffStream().readCharArray( nStrLen, getBiffData().getTextEncoding() ); + getBiffStream().readCharArrayUC( nStrLen, getBiffData().getTextEncoding() ); writeStringItem( rName, aString ); } return aString; @@ -3484,7 +3512,7 @@ void WorkbookStreamObject::dumpObjRecString( const String& rName, sal_uInt16 nTe if( bRepeatLen ) dumpByteString( rName, BIFF_STR_8BITLENGTH ); else - writeStringItem( rName, getBiffStream().readCharArray( nTextLen, getBiffData().getTextEncoding() ) ); + writeStringItem( rName, getBiffStream().readCharArrayUC( nTextLen, getBiffData().getTextEncoding() ) ); dumpObjRecPadding(); } } diff --git a/oox/source/dump/biffdumper.ini b/oox/source/dump/biffdumper.ini index 2b4782c7197b..510e950ff652 100644 --- a/oox/source/dump/biffdumper.ini +++ b/oox/source/dump/biffdumper.ini @@ -305,7 +305,7 @@ multilist=RECORD-NAMES-BIFF5 0x0023=EXTERNALNAME 0x0031=FONT 0x0098=,,,FILTERMODE,,AUTOFILTERINFO,AUTOFILTER, - 0x00A8=,,,,,,SCENMAN,SCENARIO + 0x00A8=,,,,,,SCENARIOS,SCENARIO 0x00B0=PTDEFINITION,PTFIELD,PTFITEM,,PTROWCOLFIELDS,PTROWCOLITEMS,PTPAGEFIELDS, 0x00B8=DOCROUTE,RECIPNAME,,,SHAREDFMLA,MULTRK,MULTBLANK, 0x00C0=,MMS,ADDMENU,DELMENU,,PTDATAFIELD,PCDEFINITION,PCDFIELD @@ -1141,7 +1141,7 @@ shortlist=HIDEOBJ,0,show,placeholder,hide constlist=IMGDATA-FORMAT -1=none 2=wmf-pict - 9=bmp + 9=dib 14=native end diff --git a/oox/source/dump/dumperbase.cxx b/oox/source/dump/dumperbase.cxx index 75d817194458..fb9179d9fe54 100644 --- a/oox/source/dump/dumperbase.cxx +++ b/oox/source/dump/dumperbase.cxx @@ -3010,7 +3010,7 @@ void XmlStreamObject::implDumpLine( const OUString& rLine, sal_uInt32 ) /* check for start element at beginning of the line - pcEnd and thus (pcPos+1) are dereferenceable, because OUStringBuffer::getStr is null-terminated. */ - if( (*pcPos == '<') && (*(pcPos + 1) != '/') ) + if( (*pcPos == '<') && (pcPos[ 1 ] != '/') ) { const sal_Unicode* pcElementEnd = ::std::find( pcPos, pcEnd, '>' ); if( pcElementEnd == pcEnd ) @@ -3021,7 +3021,7 @@ void XmlStreamObject::implDumpLine( const OUString& rLine, sal_uInt32 ) } else { - bIsComplElement = (*(pcPos + 1) == '?') || (*(pcElementEnd - 1) == '/'); + bIsComplElement = (pcPos[ 1 ] == '?') || (pcPos[ 1 ] == '!') || (pcElementEnd[ -1 ] == '/'); bIsStartElement = !bIsComplElement; ++pcElementEnd; aOutLine.append( pcPos, static_cast< sal_Int32 >( pcElementEnd - pcPos ) ); @@ -3044,7 +3044,7 @@ void XmlStreamObject::implDumpLine( const OUString& rLine, sal_uInt32 ) } // check for stand-alone or following end element - if( !bIsComplElement && (pcPos < pcEnd) && (*(pcPos + 1) == '/') ) + if( !bIsComplElement && (pcPos < pcEnd) && (pcPos[ 1 ] == '/') ) { const sal_Unicode* pcElementEnd = ::std::find( pcPos, pcEnd, '>' ); if( pcElementEnd == pcEnd ) diff --git a/oox/source/dump/oledumper.cxx b/oox/source/dump/oledumper.cxx index a61cfc837ea6..65e04039d1fa 100644 --- a/oox/source/dump/oledumper.cxx +++ b/oox/source/dump/oledumper.cxx @@ -1201,6 +1201,8 @@ void OcxControlObject::implDump() OcxSpinButtonObject( *this ).dump(); else if( maProgId.equalsAscii( "Forms.TabStrip.1" ) ) OcxTabStripObject( *this ).dump(); + else if( maProgId.equalsAscii( "StdPic" ) ) + StdPicObject( *this ).dump(); } dumpRemainingTo( nEndPos ); } @@ -1213,6 +1215,18 @@ OcxGuidControlObject::OcxGuidControlObject( const InputObjectBase& rParent, sal_ InputObjectBase::construct( rParent ); } +OcxGuidControlObject::OcxGuidControlObject( const OutputObjectBase& rParent, const BinaryInputStreamRef& rxStrm ) +{ + mnLength = rxStrm.get() ? rxStrm->getLength() : -1; + InputObjectBase::construct( rParent, rxStrm ); +} + +OcxGuidControlObject::OcxGuidControlObject( const ObjectBase& rParent, const BinaryInputStreamRef& rxStrm, const OUString& rSysFileName ) +{ + mnLength = rxStrm.get() ? rxStrm->getLength() : -1; + InputObjectBase::construct( rParent, rxStrm, rSysFileName ); +} + void OcxGuidControlObject::implDump() { OUString aProgId = cfg().getStringOption( dumpGuid(), OUString() ); diff --git a/oox/source/dump/oledumper.ini b/oox/source/dump/oledumper.ini index 0032ba7a8d09..c398b0c01e51 100644 --- a/oox/source/dump/oledumper.ini +++ b/oox/source/dump/oledumper.ini @@ -193,7 +193,7 @@ shortlist=OCX-BORDERSTYLE,0,none,single shortlist=OCX-SPECIALEFFECT,0,flat,raised,sunken,etched,,,bump shortlist=OCX-ORIENTATION,-1,auto,vertical,horizontal shortlist=OCX-POS,0,top-left,top,top-right,left,center,right,bottom-left,bottom,bottom-right -shortlist=OCX-IMAGEALIGN,0,lop-left,top-right,center,bottom-left,bottom-right +shortlist=OCX-IMAGEALIGN,0,top-left,top-right,center,bottom-left,bottom-right shortlist=OCX-IMAGESIZEMODE,0,clip,stretch,,stretch-ratio # CFontNew ------------------------------------------------------------------- @@ -212,11 +212,13 @@ flagslist=OCX-CFONTNEW-PROPERTIES end flagslist=OCX-CFONTNEW-FLAGS - 0x0001=bold - 0x0002=italic - 0x0004=underline - 0x0008=strikeout - 0x2000=sunken + 0x00000001=bold + 0x00000002=italic + 0x00000004=underline + 0x00000008=strikeout + 0x00002000=sunken + 0x00002000=sunken + 0x40000000=auto-color end shortlist=OCX-CFONTNEW-ALIGNMENT,1,left,right,center diff --git a/oox/source/dump/pptxdumper.cxx b/oox/source/dump/pptxdumper.cxx index a59960d42103..d1694000f03b 100644 --- a/oox/source/dump/pptxdumper.cxx +++ b/oox/source/dump/pptxdumper.cxx @@ -29,7 +29,11 @@ ************************************************************************/ #include "oox/dump/pptxdumper.hxx" +#include "oox/helper/olestorage.hxx" #include "oox/helper/zipstorage.hxx" +#include "oox/dump/biffdumper.hxx" +#include "oox/dump/oledumper.hxx" +#include "oox/dump/xlsbdumper.hxx" #if OOX_INCLUDE_DUMPER @@ -50,15 +54,62 @@ RootStorageObject::RootStorageObject( const DumperBase& rParent ) StorageObjectBase::construct( rParent ); } -void RootStorageObject::implDumpStream( const BinaryInputStreamRef& rxStrm, const OUString& /*rStrgPath*/, const OUString& rStrmName, const OUString& rSysFileName ) +void RootStorageObject::implDumpStream( const BinaryInputStreamRef& rxStrm, const OUString& rStrgPath, const OUString& rStrmName, const OUString& rSysFileName ) { OUString aExt = InputOutputHelper::getFileNameExtension( rStrmName ); - if( aExt.equalsIgnoreAsciiCaseAscii( "xml" ) || + Reference< XInputStream > xInStrm = InputOutputHelper::getXInputStream( *rxStrm ); + if( aExt.equalsIgnoreAsciiCaseAscii( "pptx" ) || + aExt.equalsIgnoreAsciiCaseAscii( "potx" ) ) + { + Dumper( getFactory(), xInStrm, rSysFileName ).dump(); + } + else if( + aExt.equalsIgnoreAsciiCaseAscii( "xlsb" ) || + aExt.equalsIgnoreAsciiCaseAscii( "xlsm" ) || + aExt.equalsIgnoreAsciiCaseAscii( "xlsx" ) || + aExt.equalsIgnoreAsciiCaseAscii( "xltm" ) || + aExt.equalsIgnoreAsciiCaseAscii( "xltx" ) ) + { + ::oox::dump::xlsb::Dumper( getFactory(), xInStrm, rSysFileName ).dump(); + } + else if( + aExt.equalsIgnoreAsciiCaseAscii( "xla" ) || + aExt.equalsIgnoreAsciiCaseAscii( "xlc" ) || + aExt.equalsIgnoreAsciiCaseAscii( "xlm" ) || + aExt.equalsIgnoreAsciiCaseAscii( "xls" ) || + aExt.equalsIgnoreAsciiCaseAscii( "xlt" ) || + aExt.equalsIgnoreAsciiCaseAscii( "xlw" ) ) + { + ::oox::dump::biff::Dumper( getFactory(), xInStrm, rSysFileName ).dump(); + } + else if( + aExt.equalsIgnoreAsciiCaseAscii( "xml" ) || aExt.equalsIgnoreAsciiCaseAscii( "vml" ) || aExt.equalsIgnoreAsciiCaseAscii( "rels" ) ) { XmlStreamObject( *this, rxStrm, rSysFileName ).dump(); } + else if( aExt.equalsIgnoreAsciiCaseAscii( "bin" ) ) + { + if( rStrgPath.equalsAscii( "ppt" ) && rStrmName.equalsAscii( "vbaProject.bin" ) ) + { + StorageRef xStrg( new OleStorage( getFactory(), xInStrm, false ) ); + VbaProjectStorageObject( *this, xStrg, rSysFileName ).dump(); + } + else if( rStrgPath.equalsAscii( "ppt/embeddings" ) ) + { + StorageRef xStrg( new OleStorage( getFactory(), xInStrm, false ) ); + OleStorageObject( *this, xStrg, rSysFileName ).dump(); + } + else if( rStrgPath.equalsAscii( "ppt/activeX" ) ) + { + OcxGuidControlObject( *this, rxStrm, rSysFileName ).dump(); + } + else + { + BinaryStreamObject( *this, rxStrm, rSysFileName ).dump(); + } + } } // ============================================================================ diff --git a/oox/source/dump/xlsbdumper.cxx b/oox/source/dump/xlsbdumper.cxx index 52866cc7b7ca..819aff6bed92 100644 --- a/oox/source/dump/xlsbdumper.cxx +++ b/oox/source/dump/xlsbdumper.cxx @@ -32,6 +32,7 @@ #include <com/sun/star/io/XTextInputStream.hpp> #include "oox/dump/biffdumper.hxx" #include "oox/dump/oledumper.hxx" +#include "oox/dump/pptxdumper.hxx" #include "oox/helper/olestorage.hxx" #include "oox/helper/zipstorage.hxx" #include "oox/core/filterbase.hxx" @@ -1583,6 +1584,13 @@ void RecordStreamObject::implDumpRecordBody() dumpString( "display" ); break; + case OOBIN_ID_INPUTCELLS: + dumpAddress( "pos" ); + dumpUnused( 8 ); + dumpDec< sal_uInt16 >( "numfmt-id" ); + dumpString( "value" ); + break; + case OOBIN_ID_LEGACYDRAWING: dumpString( "rel-id" ); break; @@ -1986,6 +1994,22 @@ void RecordStreamObject::implDumpRecordBody() dumpDec< sal_Int32 >( "manual-count" ); break; + case OOBIN_ID_SCENARIO: + dumpDec< sal_uInt16 >( "cell-count" ); + // two longs instead of flag field + dumpDec< sal_Int32 >( "locked", "BOOLEAN" ); + dumpDec< sal_Int32 >( "hidden", "BOOLEAN" ); + dumpString( "name" ); + dumpString( "comment" ); + dumpString( "user" ); + break; + + case OOBIN_ID_SCENARIOS: + dumpDec< sal_uInt16 >( "selected" ); + dumpDec< sal_uInt16 >( "shown" ); + dumpRangeList( "result-cells" ); + break; + case OOBIN_ID_SELECTION: dumpDec< sal_Int32 >( "pane", "PANE-ID" ); dumpAddress( "active-cell" ); @@ -2180,6 +2204,12 @@ void RootStorageObject::implDumpStream( const BinaryInputStreamRef& rxStrm, cons ::oox::dump::biff::Dumper( getFactory(), xInStrm, rSysFileName ).dump(); } else if( + aExt.equalsIgnoreAsciiCaseAscii( "pptx" ) || + aExt.equalsIgnoreAsciiCaseAscii( "potx" ) ) + { + ::oox::dump::pptx::Dumper( getFactory(), xInStrm, rSysFileName ).dump(); + } + else if( aExt.equalsIgnoreAsciiCaseAscii( "xml" ) || aExt.equalsIgnoreAsciiCaseAscii( "vml" ) || aExt.equalsIgnoreAsciiCaseAscii( "rels" ) ) @@ -2211,6 +2241,10 @@ void RootStorageObject::implDumpStream( const BinaryInputStreamRef& rxStrm, cons { RecordStreamObject( *this, rxStrm, rSysFileName ).dump(); } + else if( rStrgPath.equalsAscii( "xl/activeX" ) ) + { + OcxGuidControlObject( *this, rxStrm, rSysFileName ).dump(); + } else { BinaryStreamObject( *this, rxStrm, rSysFileName ).dump(); diff --git a/oox/source/dump/xlsbdumper.ini b/oox/source/dump/xlsbdumper.ini index 593fcfb85a48..be6efd2c6af3 100644 --- a/oox/source/dump/xlsbdumper.ini +++ b/oox/source/dump/xlsbdumper.ini @@ -210,8 +210,8 @@ multilist=RECORD-NAMES 0x01D8=,COLORS,COLORS_END,RGBCOLOR,PAGEMARGINS,PRINTOPTIONS,PAGESETUP,HEADERFOOTER 0x01E0=HEADERFOOTER_END,,,,,SHEETFORMATPR,, 0x01E8=,,,,,,HYPERLINK, - - 0x01F8=,DXFS,DXFS_END,DXF,TABLESTYLES,TABLESTYLES_END,, + 0x01F0=,,,,SCENARIOS,SCENARIOS_END,SCENARIO,SCENARIO_END + 0x01F8=INPUTCELLS,DXFS,DXFS_END,DXF,TABLESTYLES,TABLESTYLES_END,, 0x0200=,TABLESTYLEINFO,VOLTYPES,VOLTYPES_END,VOLTYPE,VOLTYPE_END,VOLTYPEMAIN,VOLTYPEMAIN_END 0x0208=VOLTYPETP,VOLTYPETP_END,VOLTYPESTP,VOLTYPETR,,VOLTYPE_ERROR,, 0x0210=CALCCHAIN,CALCCHAIN_END,,,,,,SHEETPROTECTION diff --git a/oox/source/helper/attributelist.cxx b/oox/source/helper/attributelist.cxx index 708ecd82c533..61fb47aab9ca 100644 --- a/oox/source/helper/attributelist.cxx +++ b/oox/source/helper/attributelist.cxx @@ -30,8 +30,10 @@ #include "oox/helper/attributelist.hxx" #include <osl/diagnose.h> +#include <rtl/ustrbuf.hxx> using ::rtl::OUString; +using ::rtl::OUStringBuffer; using ::com::sun::star::uno::Reference; using ::com::sun::star::uno::Exception; using ::com::sun::star::util::DateTime; @@ -41,6 +43,40 @@ namespace oox { // ============================================================================ +namespace { + +const sal_Int32 XSTRING_ENCCHAR_LEN = 7; + +bool lclAddHexDigit( sal_Unicode& orcChar, sal_Unicode cDigit, int nBitShift ) +{ + if( ('0' <= cDigit) && (cDigit <= '9') ) { orcChar |= ((cDigit - '0') << nBitShift); return true; } + if( ('a' <= cDigit) && (cDigit <= 'f') ) { orcChar |= ((cDigit - 'a' + 10) << nBitShift); return true; } + if( ('A' <= cDigit) && (cDigit <= 'F') ) { orcChar |= ((cDigit - 'A' + 10) << nBitShift); return true; } + return false; +} + +sal_Unicode lclGetXChar( const sal_Unicode*& rpcStr, const sal_Unicode* pcEnd ) +{ + sal_Unicode cChar = 0; + if( (pcEnd - rpcStr >= XSTRING_ENCCHAR_LEN) && + (rpcStr[ 0 ] == '_') && + (rpcStr[ 1 ] == 'x') && + (rpcStr[ 6 ] == '_') && + lclAddHexDigit( cChar, rpcStr[ 2 ], 12 ) && + lclAddHexDigit( cChar, rpcStr[ 3 ], 8 ) && + lclAddHexDigit( cChar, rpcStr[ 4 ], 4 ) && + lclAddHexDigit( cChar, rpcStr[ 5 ], 0 ) ) + { + rpcStr += XSTRING_ENCCHAR_LEN; + return cChar; + } + return *rpcStr++; +} + +} // namespace + +// ============================================================================ + AttributeList::AttributeList( const Reference< XFastAttributeList >& rxAttribs ) : mxAttribs( rxAttribs ) { @@ -52,6 +88,56 @@ bool AttributeList::hasAttribute( sal_Int32 nElement ) const return mxAttribs->hasAttribute( nElement ); } +// static string conversion ----------------------------------------------- + +OUString AttributeList::decodeXString( const OUString& rValue ) +{ + // string shorter than one encoded character - no need to decode + if( rValue.getLength() < XSTRING_ENCCHAR_LEN ) + return rValue; + OUStringBuffer aBuffer; + const sal_Unicode* pcStr = rValue.getStr(); + const sal_Unicode* pcEnd = pcStr + rValue.getLength(); + while( pcStr < pcEnd ) + aBuffer.append( lclGetXChar( pcStr, pcEnd ) ); + return aBuffer.makeStringAndClear(); +} + +double AttributeList::decodeDouble( const OUString& rValue ) +{ + return rValue.toDouble(); +} + +sal_Int32 AttributeList::decodeInteger( const OUString& rValue ) +{ + return rValue.toInt32(); +} + +sal_uInt32 AttributeList::decodeUnsigned( const OUString& rValue ) +{ + return getLimitedValue< sal_uInt32, sal_Int64 >( rValue.toInt64(), 0, SAL_MAX_UINT32 ); +} + +sal_Int64 AttributeList::decodeHyper( const OUString& rValue ) +{ + return rValue.toInt64(); +} + +sal_Int32 AttributeList::decodeIntegerHex( const OUString& rValue ) +{ + return rValue.toInt32( 16 ); +} + +sal_uInt32 AttributeList::decodeUnsignedHex( const OUString& rValue ) +{ + return getLimitedValue< sal_uInt32, sal_Int64 >( rValue.toInt64( 16 ), 0, SAL_MAX_UINT32 ); +} + +sal_Int64 AttributeList::decodeHyperHex( const OUString& rValue ) +{ + return rValue.toInt64( 16 ); +} + // optional return values ----------------------------------------------------- OptValue< sal_Int32 > AttributeList::getToken( sal_Int32 nElement ) const @@ -65,49 +151,69 @@ OptValue< OUString > AttributeList::getString( sal_Int32 nElement ) const return OptValue< OUString >( mxAttribs->hasAttribute( nElement ), mxAttribs->getOptionalValue( nElement ) ); } +OptValue< OUString > AttributeList::getXString( sal_Int32 nElement ) const +{ + return OptValue< OUString >( mxAttribs->hasAttribute( nElement ), decodeXString( mxAttribs->getOptionalValue( nElement ) ) ); +} + OptValue< double > AttributeList::getDouble( sal_Int32 nElement ) const { OUString aValue = mxAttribs->getOptionalValue( nElement ); bool bValid = aValue.getLength() > 0; - return OptValue< double >( bValid, bValid ? aValue.toDouble() : 0.0 ); + return OptValue< double >( bValid, bValid ? decodeDouble( aValue ) : 0.0 ); } OptValue< sal_Int32 > AttributeList::getInteger( sal_Int32 nElement ) const { OUString aValue = mxAttribs->getOptionalValue( nElement ); bool bValid = aValue.getLength() > 0; - return OptValue< sal_Int32 >( bValid, bValid ? aValue.toInt32() : 0 ); + return OptValue< sal_Int32 >( bValid, bValid ? decodeInteger( aValue ) : 0 ); +} + +OptValue< sal_uInt32 > AttributeList::getUnsigned( sal_Int32 nElement ) const +{ + OUString aValue = mxAttribs->getOptionalValue( nElement ); + bool bValid = aValue.getLength() > 0; + return OptValue< sal_uInt32 >( bValid, decodeUnsigned( aValue ) ); +} + +OptValue< sal_Int64 > AttributeList::getHyper( sal_Int32 nElement ) const +{ + OUString aValue = mxAttribs->getOptionalValue( nElement ); + bool bValid = aValue.getLength() > 0; + return OptValue< sal_Int64 >( bValid, bValid ? decodeHyper( aValue ) : 0 ); } -OptValue< sal_uInt32 > AttributeList::getUnsignedInteger( sal_Int32 nElement ) const +OptValue< sal_Int32 > AttributeList::getIntegerHex( sal_Int32 nElement ) const { OUString aValue = mxAttribs->getOptionalValue( nElement ); bool bValid = aValue.getLength() > 0; - sal_Int64 nValue = bValid ? aValue.toInt64() : 0; - return OptValue< sal_uInt32 >( bValid, static_cast< sal_uInt32 >( ((nValue < 0) || (nValue > SAL_MAX_UINT32)) ? 0 : nValue ) ); + return OptValue< sal_Int32 >( bValid, bValid ? decodeIntegerHex( aValue ) : 0 ); } -OptValue< sal_Int64 > AttributeList::getInteger64( sal_Int32 nElement ) const +OptValue< sal_uInt32 > AttributeList::getUnsignedHex( sal_Int32 nElement ) const { OUString aValue = mxAttribs->getOptionalValue( nElement ); bool bValid = aValue.getLength() > 0; - return OptValue< sal_Int64 >( bValid, bValid ? aValue.toInt64() : 0 ); + return OptValue< sal_uInt32 >( bValid, bValid ? decodeUnsignedHex( aValue ) : 0 ); } -OptValue< sal_Int32 > AttributeList::getHex( sal_Int32 nElement ) const +OptValue< sal_Int64 > AttributeList::getHyperHex( sal_Int32 nElement ) const { OUString aValue = mxAttribs->getOptionalValue( nElement ); bool bValid = aValue.getLength() > 0; - return OptValue< sal_Int32 >( bValid, bValid ? aValue.toInt32( 16 ) : 0 ); + return OptValue< sal_Int64 >( bValid, bValid ? decodeHyperHex( aValue ) : 0 ); } OptValue< bool > AttributeList::getBool( sal_Int32 nElement ) const { - // boolean attributes may be "true", "false", "on", "off", "1", or "0" + // boolean attributes may be "t", "f", "true", "false", "on", "off", "1", or "0" switch( getToken( nElement, -1 ) ) { + case XML_t: return OptValue< bool >( true, true ); // used in VML case XML_true: return OptValue< bool >( true, true ); case XML_on: return OptValue< bool >( true, true ); + case XML_f: return OptValue< bool >( true, false ); // used in VML case XML_false: return OptValue< bool >( true, false ); case XML_off: return OptValue< bool >( true, false ); } @@ -152,6 +258,11 @@ OUString AttributeList::getString( sal_Int32 nElement, const OUString& rDefault return rDefault; } +OUString AttributeList::getXString( sal_Int32 nElement, const OUString& rDefault ) const +{ + return getXString( nElement ).get( rDefault ); +} + double AttributeList::getDouble( sal_Int32 nElement, double fDefault ) const { return getDouble( nElement ).get( fDefault ); @@ -162,19 +273,29 @@ sal_Int32 AttributeList::getInteger( sal_Int32 nElement, sal_Int32 nDefault ) co return getInteger( nElement ).get( nDefault ); } -sal_uInt32 AttributeList::getUnsignedInteger( sal_Int32 nElement, sal_uInt32 nDefault ) const +sal_uInt32 AttributeList::getUnsigned( sal_Int32 nElement, sal_uInt32 nDefault ) const +{ + return getUnsigned( nElement ).get( nDefault ); +} + +sal_Int64 AttributeList::getHyper( sal_Int32 nElement, sal_Int64 nDefault ) const +{ + return getHyper( nElement ).get( nDefault ); +} + +sal_Int32 AttributeList::getIntegerHex( sal_Int32 nElement, sal_Int32 nDefault ) const { - return getUnsignedInteger( nElement ).get( nDefault ); + return getIntegerHex( nElement ).get( nDefault ); } -sal_Int64 AttributeList::getInteger64( sal_Int32 nElement, sal_Int64 nDefault ) const +sal_uInt32 AttributeList::getUnsignedHex( sal_Int32 nElement, sal_uInt32 nDefault ) const { - return getInteger64( nElement ).get( nDefault ); + return getUnsignedHex( nElement ).get( nDefault ); } -sal_Int32 AttributeList::getHex( sal_Int32 nElement, sal_Int32 nDefault ) const +sal_Int64 AttributeList::getHyperHex( sal_Int32 nElement, sal_Int64 nDefault ) const { - return getHex( nElement ).get( nDefault ); + return getHyperHex( nElement ).get( nDefault ); } bool AttributeList::getBool( sal_Int32 nElement, bool bDefault ) const diff --git a/oox/source/helper/binaryinputstream.cxx b/oox/source/helper/binaryinputstream.cxx index 4675372b497b..5f7f0c29591e 100644 --- a/oox/source/helper/binaryinputstream.cxx +++ b/oox/source/helper/binaryinputstream.cxx @@ -29,9 +29,16 @@ ************************************************************************/ #include "oox/helper/binaryinputstream.hxx" -#include <osl/diagnose.h> #include <string.h> - +#include <vector> +#include <rtl/strbuf.hxx> +#include <rtl/ustrbuf.hxx> + +using ::rtl::OString; +using ::rtl::OStringBuffer; +using ::rtl::OStringToOUString; +using ::rtl::OUString; +using ::rtl::OUStringBuffer; using ::com::sun::star::uno::UNO_QUERY; using ::com::sun::star::uno::Reference; using ::com::sun::star::uno::Exception; @@ -44,6 +51,60 @@ const sal_Int32 INPUTSTREAM_BUFFERSIZE = 0x8000; // ============================================================================ +OString BinaryInputStream::readNulCharArray() +{ + OStringBuffer aBuffer; + for( sal_uInt8 nChar = readuInt8(); !mbEof && (nChar > 0); readValue( nChar ) ) + aBuffer.append( static_cast< sal_Char >( nChar ) ); + return aBuffer.makeStringAndClear(); +} + +OUString BinaryInputStream::readNulCharArrayUC( rtl_TextEncoding eTextEnc ) +{ + return OStringToOUString( readNulCharArray(), eTextEnc ); +} + +OUString BinaryInputStream::readNulUnicodeArray() +{ + OUStringBuffer aBuffer; + for( sal_uInt16 nChar = readuInt16(); !mbEof && (nChar > 0); readValue( nChar ) ) + aBuffer.append( static_cast< sal_Unicode >( nChar ) ); + return aBuffer.makeStringAndClear(); +} + +OString BinaryInputStream::readCharArray( sal_Int32 nChars, bool bAllowNulChars ) +{ + if( nChars <= 0 ) + return OString(); + + ::std::vector< sal_Char > aBuffer( static_cast< size_t >( nChars ) ); + size_t nCharsRead = static_cast< size_t >( readMemory( &aBuffer.front(), nChars ) ); + if( !bAllowNulChars ) + ::std::replace( aBuffer.begin(), aBuffer.begin() + nCharsRead, '\0', '?' ); + return OString( &aBuffer.front(), nCharsRead ); +} + +OUString BinaryInputStream::readCharArrayUC( sal_Int32 nChars, rtl_TextEncoding eTextEnc, bool bAllowNulChars ) +{ + return OStringToOUString( readCharArray( nChars, bAllowNulChars ), eTextEnc ); +} + +OUString BinaryInputStream::readUnicodeArray( sal_Int32 nChars, bool bAllowNulChars ) +{ + OUStringBuffer aBuffer; + if( nChars > 0 ) + { + aBuffer.ensureCapacity( nChars ); + sal_uInt16 nChar; + for( sal_uInt16 nCharIdx = 0; !mbEof && (nCharIdx < nChars); ++nCharIdx ) + { + readValue( nChar ); + aBuffer.append( static_cast< sal_Unicode >( (!bAllowNulChars && (nChar == 0)) ? '?' : nChar ) ); + } + } + return aBuffer.makeStringAndClear(); +} + void BinaryInputStream::readAtom( void* opMem, sal_uInt8 nSize ) { readMemory( opMem, nSize ); @@ -131,7 +192,7 @@ void BinaryXInputStream::close() // ============================================================================ -SequenceInputStream::SequenceInputStream( StreamDataSequence& rData ) : +SequenceInputStream::SequenceInputStream( const StreamDataSequence& rData ) : SequenceSeekableStream( rData ) { } diff --git a/oox/source/helper/binaryoutputstream.cxx b/oox/source/helper/binaryoutputstream.cxx index c61b005029ba..474b33965fb5 100644 --- a/oox/source/helper/binaryoutputstream.cxx +++ b/oox/source/helper/binaryoutputstream.cxx @@ -148,8 +148,8 @@ void SequenceOutputStream::writeMemory( const void* pMem, sal_Int32 nBytes ) if( nBytes > 0 ) { if( mrData.getLength() - mnPos < nBytes ) - mrData.realloc( mnPos + nBytes ); - memcpy( mrData.getArray() + mnPos, pMem, static_cast< size_t >( nBytes ) ); + const_cast< StreamDataSequence& >( mrData ).realloc( mnPos + nBytes ); + memcpy( const_cast< StreamDataSequence& >( mrData ).getArray() + mnPos, pMem, static_cast< size_t >( nBytes ) ); mnPos += nBytes; } } diff --git a/oox/source/helper/graphichelper.cxx b/oox/source/helper/graphichelper.cxx new file mode 100644 index 000000000000..6d8d5a678a18 --- /dev/null +++ b/oox/source/helper/graphichelper.cxx @@ -0,0 +1,123 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: graphichelper.cxx,v $ + * $Revision: 1.1 $ + * + * 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. + * + ************************************************************************/ + +#include "oox/helper/graphichelper.hxx" +#include <com/sun/star/graphic/GraphicObject.hpp> +#include <com/sun/star/graphic/XGraphicProvider.hpp> +#include <comphelper/componentcontext.hxx> +#include <comphelper/seqstream.hxx> + +using ::rtl::OUString; +using ::com::sun::star::uno::Exception; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Sequence; +using ::com::sun::star::uno::UNO_QUERY; +using ::com::sun::star::uno::UNO_SET_THROW; +using ::com::sun::star::beans::PropertyValue; +using ::com::sun::star::io::XInputStream; +using ::com::sun::star::lang::XMultiServiceFactory; +using ::com::sun::star::graphic::GraphicObject; +using ::com::sun::star::graphic::XGraphic; +using ::com::sun::star::graphic::XGraphicObject; +using ::com::sun::star::graphic::XGraphicProvider; + +namespace oox { + +// ============================================================================ + +GraphicHelper::GraphicHelper( const Reference< XMultiServiceFactory >& rxFactory ) : + mxGraphicProvider( rxFactory->createInstance( CREATE_OUSTRING( "com.sun.star.graphic.GraphicProvider" ) ), UNO_QUERY ), + maGraphicObjScheme( CREATE_OUSTRING( "vnd.sun.star.GraphicObject:" ) ) +{ + ::comphelper::ComponentContext aContext( rxFactory ); + mxCompContext = aContext.getUNOContext(); +} + +GraphicHelper::~GraphicHelper() +{ +} + +Reference< XGraphic > GraphicHelper::importGraphic( const Reference< XInputStream >& rxInStrm ) +{ + Reference< XGraphic > xGraphic; + if( rxInStrm.is() && mxGraphicProvider.is() ) try + { + Sequence< PropertyValue > aArgs( 1 ); + aArgs[ 0 ].Name = CREATE_OUSTRING( "InputStream" ); + aArgs[ 0 ].Value <<= rxInStrm; + xGraphic = mxGraphicProvider->queryGraphic( aArgs ); + } + catch( Exception& ) + { + } + return xGraphic; +} + +Reference< XGraphic > GraphicHelper::importGraphic( const StreamDataSequence& rGraphicData ) +{ + Reference< XGraphic > xGraphic; + if( rGraphicData.hasElements() ) + { + Reference< XInputStream > xInStrm( new ::comphelper::SequenceInputStream( rGraphicData ) ); + xGraphic = importGraphic( xInStrm ); + } + return xGraphic; +} + +OUString GraphicHelper::createGraphicObject( const Reference< XGraphic >& rxGraphic ) +{ + OUString aGraphicObjUrl; + if( mxCompContext.is() && rxGraphic.is() ) try + { + Reference< XGraphicObject > xGraphicObj( GraphicObject::create( mxCompContext ), UNO_SET_THROW ); + xGraphicObj->setGraphic( rxGraphic ); + maGraphicObjects.push_back( xGraphicObj ); + aGraphicObjUrl = maGraphicObjScheme + xGraphicObj->getUniqueID(); + } + catch( Exception& ) + { + } + return aGraphicObjUrl; +} + +OUString GraphicHelper::importGraphicObject( const Reference< XInputStream >& rxInStrm ) +{ + return createGraphicObject( importGraphic( rxInStrm ) ); +} + +OUString GraphicHelper::importGraphicObject( const StreamDataSequence& rGraphicData ) +{ + return createGraphicObject( importGraphic( rGraphicData ) ); +} + +// ============================================================================ + +} // namespace oox + diff --git a/oox/source/helper/makefile.mk b/oox/source/helper/makefile.mk index 7677a1fa3329..b172cad3d9d4 100644 --- a/oox/source/helper/makefile.mk +++ b/oox/source/helper/makefile.mk @@ -50,6 +50,8 @@ SLOFILES = \ $(SLO)$/binaryoutputstream.obj \ $(SLO)$/binarystreambase.obj \ $(SLO)$/containerhelper.obj \ + $(SLO)$/graphichelper.obj \ + $(SLO)$/modelobjecthelper.obj \ $(SLO)$/olestorage.obj \ $(SLO)$/progressbar.obj \ $(SLO)$/propertymap.obj \ diff --git a/oox/source/core/modelobjectcontainer.cxx b/oox/source/helper/modelobjecthelper.cxx index 1e2f78921216..e6e45492eb60 100644 --- a/oox/source/core/modelobjectcontainer.cxx +++ b/oox/source/helper/modelobjecthelper.cxx @@ -6,8 +6,8 @@ * * OpenOffice.org - a multi-platform office productivity suite * - * $RCSfile: modelobjectcontainer.cxx,v $ - * $Revision: 1.2 $ + * $RCSfile: modelobjecthelper.cxx,v $ + * $Revision: 1.1 $ * * This file is part of OpenOffice.org. * @@ -28,10 +28,9 @@ * ************************************************************************/ -#include "oox/core/modelobjectcontainer.hxx" +#include "oox/helper/modelobjecthelper.hxx" #include <com/sun/star/lang/XMultiServiceFactory.hpp> #include <com/sun/star/awt/Gradient.hpp> -#include <com/sun/star/awt/XBitmap.hpp> #include <com/sun/star/drawing/LineDash.hpp> #include <com/sun/star/drawing/PolyPolygonBezierCoords.hpp> #include "oox/helper/helper.hxx" @@ -39,62 +38,57 @@ using ::rtl::OUString; using ::com::sun::star::uno::Any; using ::com::sun::star::uno::Reference; -using ::com::sun::star::uno::UNO_QUERY; using ::com::sun::star::lang::XMultiServiceFactory; -using ::com::sun::star::frame::XModel; using ::com::sun::star::awt::Gradient; -using ::com::sun::star::awt::XBitmap; using ::com::sun::star::drawing::LineDash; using ::com::sun::star::drawing::PolyPolygonBezierCoords; namespace oox { -namespace core { // ============================================================================ -ModelObjectContainer::ModelObjectContainer( const Reference< XModel >& rxModel ) : - maMarkerContainer( Reference< XMultiServiceFactory >( rxModel, UNO_QUERY ), CREATE_OUSTRING( "com.sun.star.drawing.MarkerTable" ) ), - maDashContainer( Reference< XMultiServiceFactory >( rxModel, UNO_QUERY ), CREATE_OUSTRING( "com.sun.star.drawing.DashTable" ) ), - maGradientContainer( Reference< XMultiServiceFactory >( rxModel, UNO_QUERY ), CREATE_OUSTRING( "com.sun.star.drawing.GradientTable" ) ), - maBitmapContainer( Reference< XMultiServiceFactory >( rxModel, UNO_QUERY ), CREATE_OUSTRING( "com.sun.star.drawing.BitmapTable" ) ), +ModelObjectHelper::ModelObjectHelper( const Reference< XMultiServiceFactory >& rxFactory ) : + maMarkerContainer( rxFactory, CREATE_OUSTRING( "com.sun.star.drawing.MarkerTable" ) ), + maDashContainer( rxFactory, CREATE_OUSTRING( "com.sun.star.drawing.DashTable" ) ), + maGradientContainer( rxFactory, CREATE_OUSTRING( "com.sun.star.drawing.GradientTable" ) ), + maBitmapContainer( rxFactory, CREATE_OUSTRING( "com.sun.star.drawing.BitmapTable" ) ), maDashNameBase( CREATE_OUSTRING( "msLineDash " ) ), maGradientNameBase( CREATE_OUSTRING( "msFillGradient " ) ), maBitmapNameBase( CREATE_OUSTRING( "msFillBitmap " ) ) { } -bool ModelObjectContainer::hasLineMarker( const OUString& rMarkerName ) const +bool ModelObjectHelper::hasLineMarker( const OUString& rMarkerName ) const { return maMarkerContainer.hasObject( rMarkerName ); } -bool ModelObjectContainer::insertLineMarker( const OUString& rMarkerName, const PolyPolygonBezierCoords& rMarker ) +bool ModelObjectHelper::insertLineMarker( const OUString& rMarkerName, const PolyPolygonBezierCoords& rMarker ) { - OSL_ENSURE( rMarker.Coordinates.hasElements(), "ModelObjectContainer::insertLineMarker - line marker without coordinates" ); + OSL_ENSURE( rMarker.Coordinates.hasElements(), "ModelObjectHelper::insertLineMarker - line marker without coordinates" ); if( rMarker.Coordinates.hasElements() ) return maMarkerContainer.insertObject( rMarkerName, Any( rMarker ), false ).getLength() > 0; return false; } -OUString ModelObjectContainer::insertLineDash( const LineDash& rDash ) +OUString ModelObjectHelper::insertLineDash( const LineDash& rDash ) { return maDashContainer.insertObject( maDashNameBase, Any( rDash ), true ); } -OUString ModelObjectContainer::insertFillGradient( const Gradient& rGradient ) +OUString ModelObjectHelper::insertFillGradient( const Gradient& rGradient ) { return maGradientContainer.insertObject( maGradientNameBase, Any( rGradient ), true ); } -OUString ModelObjectContainer::insertFillBitmap( const Reference< XBitmap >& rxBitmap ) +OUString ModelObjectHelper::insertFillBitmap( const OUString& rGraphicUrl ) { - if( rxBitmap.is() ) - return maBitmapContainer.insertObject( maBitmapNameBase, Any( rxBitmap ), true ); + if( rGraphicUrl.getLength() > 0 ) + return maBitmapContainer.insertObject( maBitmapNameBase, Any( rGraphicUrl ), true ); return OUString(); } // ============================================================================ -} // namespace core } // namespace oox diff --git a/oox/source/helper/recordinputstream.cxx b/oox/source/helper/recordinputstream.cxx index 4b2ad21fc5c2..ee1138d3c751 100644 --- a/oox/source/helper/recordinputstream.cxx +++ b/oox/source/helper/recordinputstream.cxx @@ -38,7 +38,7 @@ namespace oox { // ============================================================================ -RecordInputStream::RecordInputStream( StreamDataSequence& rData ) : +RecordInputStream::RecordInputStream( const StreamDataSequence& rData ) : SequenceInputStream( rData ) { } diff --git a/oox/source/helper/storagebase.cxx b/oox/source/helper/storagebase.cxx index bb130f962f98..028daeb027fb 100644 --- a/oox/source/helper/storagebase.cxx +++ b/oox/source/helper/storagebase.cxx @@ -75,12 +75,12 @@ StorageBase::StorageBase( const Reference< XInputStream >& rxInStream, bool bBas OSL_ENSURE( mxInStream.is(), "StorageBase::StorageBase - missing base input stream" ); } -StorageBase::StorageBase( const Reference< XStream >& rxStream, bool bBaseStreamAccess ) : - mxStream( rxStream ), +StorageBase::StorageBase( const Reference< XStream >& rxOutStream, bool bBaseStreamAccess ) : + mxOutStream( rxOutStream ), mpParentStorage( 0 ), mbBaseStreamAccess( bBaseStreamAccess ) { - OSL_ENSURE( mxStream.is(), "StorageBase::StorageBase - missing base output stream" ); + OSL_ENSURE( mxOutStream.is(), "StorageBase::StorageBase - missing base output stream" ); } StorageBase::StorageBase( const StorageBase& rParentStorage, const OUString& rStorageName ) : @@ -183,7 +183,7 @@ Reference< XOutputStream > StorageBase::openOutputStream( const OUString& rStrea } else if( mbBaseStreamAccess ) { - xOutStream = mxStream->getOutputStream(); + xOutStream = mxOutStream->getOutputStream(); } return xOutStream; } diff --git a/oox/source/ole/axcontrol.cxx b/oox/source/ole/axcontrol.cxx new file mode 100644 index 000000000000..2495305d1c35 --- /dev/null +++ b/oox/source/ole/axcontrol.cxx @@ -0,0 +1,1027 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: axcontrol.cxx,v $ + * $Revision: 1.1 $ + * + * 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. + * + ************************************************************************/ + +#include "oox/ole/axcontrol.hxx" +#include <rtl/tencinfo.h> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/container/XIndexContainer.hpp> +#include <com/sun/star/awt/FontSlant.hpp> +#include <com/sun/star/awt/FontStrikeout.hpp> +#include <com/sun/star/awt/FontUnderline.hpp> +#include <com/sun/star/awt/FontWeight.hpp> +#include <com/sun/star/awt/ImagePosition.hpp> +#include <com/sun/star/awt/ImageScaleMode.hpp> +#include <com/sun/star/awt/ScrollBarOrientation.hpp> +#include <com/sun/star/awt/TextAlign.hpp> +#include <com/sun/star/awt/VisualEffect.hpp> +#include <com/sun/star/awt/XControlModel.hpp> +#include <com/sun/star/style/VerticalAlignment.hpp> +#include <com/sun/star/form/XFormComponent.hpp> +#include "properties.hxx" +#include "tokens.hxx" +#include "oox/helper/attributelist.hxx" +#include "oox/helper/binaryinputstream.hxx" +#include "oox/helper/graphichelper.hxx" +#include "oox/helper/propertymap.hxx" +#include "oox/helper/propertyset.hxx" +#include "oox/core/filterbase.hxx" +#include "oox/ole/axcontrolhelper.hxx" +#include "oox/ole/olehelper.hxx" + +using ::rtl::OUString; +using ::com::sun::star::uno::Any; +using ::com::sun::star::uno::Exception; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::UNO_QUERY_THROW; +using ::com::sun::star::container::XIndexContainer; +using ::com::sun::star::awt::XControlModel; +using ::com::sun::star::form::XFormComponent; +using ::oox::core::FilterBase; + +namespace oox { +namespace ole { + +// ============================================================================ + +namespace { + +const sal_uInt32 AX_FLAGS_ENABLED = 0x00000002; +const sal_uInt32 AX_FLAGS_LOCKED = 0x00000004; +const sal_uInt32 AX_FLAGS_OPAQUE = 0x00000008; +const sal_uInt32 AX_FLAGS_COLUMNHEADS = 0x00000400; +const sal_uInt32 AX_FLAGS_ENTIREROWS = 0x00000800; +const sal_uInt32 AX_FLAGS_EXISTINGENTRIES = 0x00001000; +const sal_uInt32 AX_FLAGS_CAPTIONLEFT = 0x00002000; +const sal_uInt32 AX_FLAGS_EDITABLE = 0x00004000; +const sal_uInt32 AX_FLAGS_IMEMODE_MASK = 0x00078000; +const sal_uInt32 AX_FLAGS_DRAGENABLED = 0x00080000; +const sal_uInt32 AX_FLAGS_ENTERASNEWLINE = 0x00100000; +const sal_uInt32 AX_FLAGS_KEEPSELECTION = 0x00200000; +const sal_uInt32 AX_FLAGS_TABASCHARACTER = 0x00400000; +const sal_uInt32 AX_FLAGS_WORDWRAP = 0x00800000; +const sal_uInt32 AX_FLAGS_BORDERSSUPPRESSED = 0x02000000; +const sal_uInt32 AX_FLAGS_SELECTLINE = 0x04000000; +const sal_uInt32 AX_FLAGS_SINGLECHARSELECT = 0x08000000; +const sal_uInt32 AX_FLAGS_AUTOSIZE = 0x10000000; +const sal_uInt32 AX_FLAGS_HIDESELECTION = 0x20000000; +const sal_uInt32 AX_FLAGS_MAXLENAUTOTAB = 0x40000000; +const sal_uInt32 AX_FLAGS_MULTILINE = 0x80000000; + +const sal_uInt32 AX_CMDBUTTON_DEFFLAGS = 0x0000001B; +const sal_uInt32 AX_LABEL_DEFFLAGS = 0x0080001B; +const sal_uInt32 AX_IMAGE_DEFFLAGS = 0x0000001B; +const sal_uInt32 AX_MORPHDATA_DEFFLAGS = 0x2C80081B; +const sal_uInt32 AX_SPINBUTTON_DEFFLAGS = 0x0000001B; +const sal_uInt32 AX_SCROLLBAR_DEFFLAGS = 0x0000001B; + +const sal_uInt32 AX_FONT_BOLD = 0x00000001; +const sal_uInt32 AX_FONT_ITALIC = 0x00000002; +const sal_uInt32 AX_FONT_UNDERLINE = 0x00000004; +const sal_uInt32 AX_FONT_STRIKEOUT = 0x00000008; +const sal_uInt32 AX_FONT_DISABLED = 0x00002000; +const sal_uInt32 AX_FONT_AUTOCOLOR = 0x40000000; + +const sal_Int32 AX_FONTALIGN_LEFT = 1; +const sal_Int32 AX_FONTALIGN_RIGHT = 2; +const sal_Int32 AX_FONTALIGN_CENTER = 3; + +const sal_Int32 AX_BORDERSTYLE_NONE = 0; +const sal_Int32 AX_BORDERSTYLE_SINGLE = 1; + +const sal_Int32 AX_SPECIALEFFECT_FLAT = 0; +const sal_Int32 AX_SPECIALEFFECT_RAISED = 1; +const sal_Int32 AX_SPECIALEFFECT_SUNKEN = 2; +const sal_Int32 AX_SPECIALEFFECT_ETCHED = 3; +const sal_Int32 AX_SPECIALEFFECT_BUMPED = 6; + +const sal_uInt16 AX_POS_TOPLEFT = 0; +const sal_uInt16 AX_POS_TOP = 1; +const sal_uInt16 AX_POS_TOPRIGHT = 2; +const sal_uInt16 AX_POS_LEFT = 3; +const sal_uInt16 AX_POS_CENTER = 4; +const sal_uInt16 AX_POS_RIGHT = 5; +const sal_uInt16 AX_POS_BOTTOMLEFT = 6; +const sal_uInt16 AX_POS_BOTTOM = 7; +const sal_uInt16 AX_POS_BOTTOMRIGHT = 8; + +#define AX_PICPOS( label, image ) ((AX_POS_##label << 16) | AX_POS_##image) +const sal_uInt32 AX_PICPOS_LEFTTOP = AX_PICPOS( TOPRIGHT, TOPLEFT ); +const sal_uInt32 AX_PICPOS_LEFTCENTER = AX_PICPOS( RIGHT, LEFT ); +const sal_uInt32 AX_PICPOS_LEFTBOTTOM = AX_PICPOS( BOTTOMRIGHT, BOTTOMLEFT ); +const sal_uInt32 AX_PICPOS_RIGHTTOP = AX_PICPOS( TOPLEFT, TOPRIGHT ); +const sal_uInt32 AX_PICPOS_RIGHTCENTER = AX_PICPOS( LEFT, RIGHT ); +const sal_uInt32 AX_PICPOS_RIGHTBOTTOM = AX_PICPOS( BOTTOMLEFT, BOTTOMRIGHT ); +const sal_uInt32 AX_PICPOS_ABOVELEFT = AX_PICPOS( BOTTOMLEFT, TOPLEFT ); +const sal_uInt32 AX_PICPOS_ABOVECENTER = AX_PICPOS( BOTTOM, TOP ); +const sal_uInt32 AX_PICPOS_ABOVERIGHT = AX_PICPOS( BOTTOMRIGHT, TOPRIGHT ); +const sal_uInt32 AX_PICPOS_BELOWLEFT = AX_PICPOS( TOPLEFT, BOTTOMLEFT ); +const sal_uInt32 AX_PICPOS_BELOWCENTER = AX_PICPOS( TOP, BOTTOM ); +const sal_uInt32 AX_PICPOS_BELOWRIGHT = AX_PICPOS( TOPRIGHT, BOTTOMRIGHT ); +const sal_uInt32 AX_PICPOS_CENTER = AX_PICPOS( CENTER, CENTER ); +#undef AX_PICPOS + +const sal_Int32 AX_PICSIZE_CLIP = 0; +const sal_Int32 AX_PICSIZE_STRETCH = 1; +const sal_Int32 AX_PICSIZE_ZOOM = 3; + +const sal_Int32 AX_PICALIGN_TOPLEFT = 0; +const sal_Int32 AX_PICALIGN_TOPRIGHT = 1; +const sal_Int32 AX_PICALIGN_CENTER = 2; +const sal_Int32 AX_PICALIGN_BOTTOMLEFT = 3; +const sal_Int32 AX_PICALIGN_BOTTOMRIGHT = 4; + +const sal_Int32 AX_DISPLAYSTYLE_TEXT = 1; +const sal_Int32 AX_DISPLAYSTYLE_LISTBOX = 2; +const sal_Int32 AX_DISPLAYSTYLE_COMBOBOX = 3; +const sal_Int32 AX_DISPLAYSTYLE_CHECKBOX = 4; +const sal_Int32 AX_DISPLAYSTYLE_OPTBUTTON = 5; +const sal_Int32 AX_DISPLAYSTYLE_TOGGLE = 6; +const sal_Int32 AX_DISPLAYSTYLE_DROPDOWN = 7; + +const sal_Int32 AX_SELCTION_SINGLE = 0; +const sal_Int32 AX_SELCTION_MULTI = 1; +const sal_Int32 AX_SELCTION_EXTENDED = 2; + +const sal_Int32 AX_SCROLLBAR_NONE = 0x00; +const sal_Int32 AX_SCROLLBAR_HORIZONTAL = 0x01; +const sal_Int32 AX_SCROLLBAR_VERTICAL = 0x02; + +const sal_Int32 AX_MATCHENTRY_FIRSTLETTER = 0; +const sal_Int32 AX_MATCHENTRY_COMPLETE = 1; +const sal_Int32 AX_MATCHENTRY_NONE = 2; + +const sal_Int32 AX_SHOWDROPBUTTON_NEVER = 0; +const sal_Int32 AX_SHOWDROPBUTTON_FOCUS = 1; +const sal_Int32 AX_SHOWDROPBUTTON_ALWAYS = 2; + +const sal_Int32 AX_ORIENTATION_AUTO = -1; +const sal_Int32 AX_ORIENTATION_VERTICAL = 0; +const sal_Int32 AX_ORIENTATION_HORIZONTAL = 1; + +const sal_Int32 AX_PROPTHUMB_ON = -1; +const sal_Int32 AX_PROPTHUMB_OFF = 0; + +// ---------------------------------------------------------------------------- + +const sal_Int16 API_BORDER_NONE = 0; +const sal_Int16 API_BORDER_SUNKEN = 1; +const sal_Int16 API_BORDER_FLAT = 2; + +const sal_Int16 API_STATE_UNCHECKED = 0; +const sal_Int16 API_STATE_CHECKED = 1; +const sal_Int16 API_STATE_DONTKNOW = 2; + +// ---------------------------------------------------------------------------- + +/** Specifies how a form control supports transparent background. */ +enum ApiTransparencyMode +{ + API_TRANSPARENCY_NOTSUPPORTED, /// Control does not support transparency. + API_TRANSPARENCY_VOID, /// Transparency is enabled by missing fill color. + API_TRANSPARENCY_PAINTTRANSPARENT /// Transparency is enabled by the 'PaintTransparent' property. +}; + +// ---------------------------------------------------------------------------- + +/** Converts the AX background formatting to UNO properties. */ +void lclConvertBackground( AxControlHelper& rHelper, PropertyMap& rPropMap, sal_uInt32 nBackColor, sal_uInt32 nFlags, ApiTransparencyMode eTranspMode ) +{ + bool bOpaque = getFlag( nFlags, AX_FLAGS_OPAQUE ); + switch( eTranspMode ) + { + case API_TRANSPARENCY_NOTSUPPORTED: + // fake transparency by using system window background if needed + rPropMap.setProperty( PROP_BackgroundColor, rHelper.convertColor( bOpaque ? nBackColor : AX_SYSCOLOR_WINDOWBACK ) ); + break; + case API_TRANSPARENCY_PAINTTRANSPARENT: + rPropMap.setProperty( PROP_PaintTransparent, !bOpaque ); + // run-through intended! + case API_TRANSPARENCY_VOID: + // keep transparency by leaving the (void) default property value + if( bOpaque ) + rPropMap.setProperty( PROP_BackgroundColor, rHelper.convertColor( nBackColor ) ); + break; + } +} + +// ---------------------------------------------------------------------------- + +/** Converts the AX border formatting to UNO properties. */ +void lclConvertBorder( AxControlHelper& rHelper, PropertyMap& rPropMap, sal_uInt32 nBorderColor, sal_Int32 nBorderStyle, sal_Int32 nSpecialEffect ) +{ + sal_Int16 nBorder = (nBorderStyle == AX_BORDERSTYLE_SINGLE) ? API_BORDER_FLAT : + ((nSpecialEffect == AX_SPECIALEFFECT_FLAT) ? API_BORDER_NONE : API_BORDER_SUNKEN); + rPropMap.setProperty( PROP_Border, nBorder ); + rPropMap.setProperty( PROP_BorderColor, rHelper.convertColor( nBorderColor ) ); +} + +// ---------------------------------------------------------------------------- + +/** Converts the AX special effect to UNO properties. */ +void lclConvertVisualEffect( AxControlHelper& /*rHelper*/, PropertyMap& rPropMap, sal_Int32 nSpecialEffect ) +{ + namespace AwtVisualEffect = ::com::sun::star::awt::VisualEffect; + sal_Int16 nVisualEffect = (nSpecialEffect == AX_SPECIALEFFECT_FLAT) ? AwtVisualEffect::FLAT : AwtVisualEffect::LOOK3D; + rPropMap.setProperty( PROP_VisualEffect, nVisualEffect ); +} + +// ---------------------------------------------------------------------------- + +/** Converts the AX picture to UNO properties. */ +void lclConvertPicture( AxControlHelper& rHelper, PropertyMap& rPropMap, const StreamDataSequence& rPicData ) +{ + if( rPicData.hasElements() ) + { + SequenceInputStream aInStrm( rPicData ); + StreamDataSequence aPictureData; + if( OleHelper::importStdPic( aPictureData, aInStrm, true ) ) + { + OUString aGraphicUrl = rHelper.getFilter().getGraphicHelper().importGraphicObject( aPictureData ); + if( aGraphicUrl.getLength() > 0 ) + rPropMap.setProperty( PROP_ImageURL, aGraphicUrl ); + } + } +} + +// ---------------------------------------------------------------------------- + +/** Converts the AX picture and position to UNO properties. */ +void lclConvertPicture( AxControlHelper& rHelper, PropertyMap& rPropMap, const StreamDataSequence& rPicData, sal_uInt32 nPicPos ) +{ + // the picture + lclConvertPicture( rHelper, rPropMap, rPicData ); + + // picture position + namespace AwtImagePos = ::com::sun::star::awt::ImagePosition; + sal_Int16 nImagePos = AwtImagePos::LeftCenter; + switch( nPicPos ) + { + case AX_PICPOS_LEFTTOP: nImagePos = AwtImagePos::LeftTop; break; + case AX_PICPOS_LEFTCENTER: nImagePos = AwtImagePos::LeftCenter; break; + case AX_PICPOS_LEFTBOTTOM: nImagePos = AwtImagePos::LeftBottom; break; + case AX_PICPOS_RIGHTTOP: nImagePos = AwtImagePos::RightTop; break; + case AX_PICPOS_RIGHTCENTER: nImagePos = AwtImagePos::RightCenter; break; + case AX_PICPOS_RIGHTBOTTOM: nImagePos = AwtImagePos::RightBottom; break; + case AX_PICPOS_ABOVELEFT: nImagePos = AwtImagePos::AboveLeft; break; + case AX_PICPOS_ABOVECENTER: nImagePos = AwtImagePos::AboveCenter; break; + case AX_PICPOS_ABOVERIGHT: nImagePos = AwtImagePos::AboveRight; break; + case AX_PICPOS_BELOWLEFT: nImagePos = AwtImagePos::BelowLeft; break; + case AX_PICPOS_BELOWCENTER: nImagePos = AwtImagePos::BelowCenter; break; + case AX_PICPOS_BELOWRIGHT: nImagePos = AwtImagePos::BelowRight; break; + case AX_PICPOS_CENTER: nImagePos = AwtImagePos::Centered; break; + default: OSL_ENSURE( false, "lclConvertPicture - unknown picture position" ); + } + rPropMap.setProperty( PROP_ImagePosition, nImagePos ); +} + +// ---------------------------------------------------------------------------- + +/** Converts the AX picture and position to UNO properties. */ +void lclConvertPicture( AxControlHelper& rHelper, PropertyMap& rPropMap, const StreamDataSequence& rPicData, sal_Int32 nPicSizeMode, sal_Int32 /*nPicAlign*/, bool /*bPicTiling*/ ) +{ + // the picture + lclConvertPicture( rHelper, rPropMap, rPicData ); + + // picture scale mode + namespace AwtScaleMode = ::com::sun::star::awt::ImageScaleMode; + sal_Int16 nScaleMode = AwtScaleMode::None; + switch( nPicSizeMode ) + { + case AX_PICSIZE_CLIP: nScaleMode = AwtScaleMode::None; break; + case AX_PICSIZE_STRETCH: nScaleMode = AwtScaleMode::Anisotropic; break; + case AX_PICSIZE_ZOOM: nScaleMode = AwtScaleMode::Isotropic; break; + default: OSL_ENSURE( false, "lclConvertPicture - unknown picture size mode" ); + } + rPropMap.setProperty( PROP_ScaleMode, nScaleMode ); +} + +// ---------------------------------------------------------------------------- + +/** Converts the AX value for checked/unchecked/dontknow to UNO properties. */ +void lclConvertState( AxControlHelper& /*rHelper*/, PropertyMap& rPropMap, const OUString& rValue, sal_Int32 nMultiSelect, bool bSupportsTriState ) +{ + // state + sal_Int16 nState = bSupportsTriState ? API_STATE_DONTKNOW : API_STATE_UNCHECKED; + if( rValue.getLength() == 1 ) switch( rValue[ 0 ] ) + { + case '0': nState = API_STATE_UNCHECKED; break; + case '1': nState = API_STATE_CHECKED; break; + // any other string (also empty) means 'dontknow' + } + rPropMap.setProperty( PROP_DefaultState, nState ); + + // tristate + if( bSupportsTriState ) + rPropMap.setProperty( PROP_TriState, nMultiSelect == AX_SELCTION_MULTI ); +} + +// ---------------------------------------------------------------------------- + +/** Converts the AX control orientation to UNO properties. */ +void lclConvertOrientation( AxControlHelper& /*rHelper*/, PropertyMap& rPropMap, sal_Int32 nOrientation, sal_Int32 nWidth, sal_Int32 nHeight ) +{ + namespace AwtScrollBarOrient = ::com::sun::star::awt::ScrollBarOrientation; + sal_Int32 nScrollOrient = AwtScrollBarOrient::HORIZONTAL; + switch( nOrientation ) + { + case AX_ORIENTATION_AUTO: if( nWidth <= nHeight) nScrollOrient = AwtScrollBarOrient::VERTICAL; break; + case AX_ORIENTATION_VERTICAL: nScrollOrient = AwtScrollBarOrient::VERTICAL; break; + case AX_ORIENTATION_HORIZONTAL: nScrollOrient = AwtScrollBarOrient::HORIZONTAL; break; + default: OSL_ENSURE( false, "lclConvertOrientation - unknown orientation" ); + } + rPropMap.setProperty( PROP_Orientation, nScrollOrient ); +} + +} // namespace + +// ============================================================================ + +AxControlModelBase::AxControlModelBase() : + mnWidth( 0 ), + mnHeight( 0 ) +{ +} + +AxControlModelBase::~AxControlModelBase() +{ +} + +void AxControlModelBase::importProperty( sal_Int32 nPropId, const OUString& rValue ) +{ + switch( nPropId ) + { + // size of the control shape: format is "width;height" + case XML_Size: + { + sal_Int32 nSepPos = rValue.indexOf( ';' ); + OSL_ENSURE( nSepPos >= 0, "AxControlModelBase::importProperty - missing separator in 'Size' property" ); + if( nSepPos >= 0 ) + { + mnWidth = rValue.copy( 0, nSepPos ).toInt32(); + mnHeight = rValue.copy( nSepPos + 1 ).toInt32(); + } + } + break; + } +} + +void AxControlModelBase::importPictureData( sal_Int32 /*nPropId*/, const StreamDataSequence& /*rDataSeq*/ ) +{ +} + +void AxControlModelBase::convertProperties( AxControlHelper& /*rHelper*/, PropertyMap& /*rPropMap*/ ) const +{ +} + +// ============================================================================ + +AxFontDataModel::AxFontDataModel() : + mnFontEffects( 0 ), + mnFontHeight( 160 ), + mnFontCharSet( 1 ), + mnHorAlign( AX_FONTALIGN_LEFT ) +{ +} + +void AxFontDataModel::importProperty( sal_Int32 nPropId, const OUString& rValue ) +{ + switch( nPropId ) + { + case XML_FontName: maFontName = rValue; break; + case XML_FontEffects: mnFontEffects = AttributeList::decodeUnsigned( rValue ); break; + case XML_FontHeight: mnFontHeight = AttributeList::decodeInteger( rValue ); break; + case XML_FontCharSet: mnFontCharSet = AttributeList::decodeInteger( rValue ); break; + case XML_ParagraphAlign: mnHorAlign = AttributeList::decodeInteger( rValue ); break; + default: AxControlModelBase::importProperty( nPropId, rValue ); + } +} + +void AxFontDataModel::convertProperties( AxControlHelper& rHelper, PropertyMap& rPropMap ) const +{ + namespace cssa = ::com::sun::star::awt; + + // font name + if( maFontName.getLength() > 0 ) + rPropMap.setProperty( PROP_FontName, maFontName ); + + // font effects + rPropMap.setProperty( PROP_FontWeight, getFlagValue( mnFontEffects, AX_FONT_BOLD, cssa::FontWeight::BOLD, cssa::FontWeight::NORMAL ) ); + rPropMap.setProperty( PROP_FontSlant, getFlagValue< sal_Int16 >( mnFontEffects, AX_FONT_ITALIC, cssa::FontSlant_ITALIC, cssa::FontSlant_NONE ) ); + rPropMap.setProperty( PROP_FontUnderline, getFlagValue( mnFontEffects, AX_FONT_UNDERLINE, cssa::FontUnderline::SINGLE, cssa::FontUnderline::NONE ) ); + rPropMap.setProperty( PROP_FontStrikeout, getFlagValue( mnFontEffects, AX_FONT_STRIKEOUT, cssa::FontStrikeout::SINGLE, cssa::FontStrikeout::NONE ) ); + + /* font height in points. MSO uses weird font sizes: + 1pt->30, 2pt->45, 3pt->60, 4pt->75, 5pt->105, 6pt->120, 7pt->135, + 8pt->165, 9pt->180, 10pt->195, 11pt->225, ... */ + sal_Int16 nHeight = getLimitedValue< sal_Int16, sal_Int32 >( (mnFontHeight + 10) / 20, 1, SAL_MAX_INT16 ); + rPropMap.setProperty( PROP_FontHeight, nHeight ); + + // font character set + rtl_TextEncoding eFontEnc = RTL_TEXTENCODING_DONTKNOW; + if( (0 <= mnFontCharSet) && (mnFontCharSet <= SAL_MAX_UINT8) ) + eFontEnc = rtl_getTextEncodingFromWindowsCharset( static_cast< sal_uInt8 >( mnFontCharSet ) ); + if( eFontEnc != RTL_TEXTENCODING_DONTKNOW ) + rPropMap.setProperty( PROP_FontCharset, static_cast< sal_Int16 >( eFontEnc ) ); + + // text alignment + sal_Int32 nAlign = cssa::TextAlign::LEFT; + switch( mnHorAlign ) + { + case AX_FONTALIGN_LEFT: nAlign = cssa::TextAlign::LEFT; break; + case AX_FONTALIGN_RIGHT: nAlign = cssa::TextAlign::RIGHT; break; + case AX_FONTALIGN_CENTER: nAlign = cssa::TextAlign::CENTER; break; + default: OSL_ENSURE( false, "AxFontDataModel::convertProperties - unknown text alignment" ); + } + // form controls expect short value + rPropMap.setProperty( PROP_Align, static_cast< sal_Int16 >( nAlign ) ); + + // process base class properties + AxControlModelBase::convertProperties( rHelper, rPropMap ); +} + +// ============================================================================ + +AxCommandButtonModel::AxCommandButtonModel() : + mnTextColor( AX_SYSCOLOR_BUTTONTEXT ), + mnBackColor( AX_SYSCOLOR_BUTTONFACE ), + mnFlags( AX_CMDBUTTON_DEFFLAGS ), + mnPicturePos( AX_PICPOS_ABOVECENTER ), + mbFocusOnClick( true ) +{ +} + +void AxCommandButtonModel::importProperty( sal_Int32 nPropId, const OUString& rValue ) +{ + switch( nPropId ) + { + case XML_Caption: maCaption = rValue; break; + case XML_ForeColor: mnTextColor = AttributeList::decodeUnsigned( rValue ); break; + case XML_BackColor: mnBackColor = AttributeList::decodeUnsigned( rValue ); break; + case XML_VariousPropertyBits: mnFlags = AttributeList::decodeUnsigned( rValue ); break; + case XML_PicturePosition: mnPicturePos = AttributeList::decodeUnsigned( rValue ); break; + case XML_TakeFocusOnClick: mbFocusOnClick = AttributeList::decodeInteger( rValue ) != 0; break; + default: AxFontDataModel::importProperty( nPropId, rValue ); + } +} + +void AxCommandButtonModel::importPictureData( sal_Int32 nPropId, const StreamDataSequence& rDataSeq ) +{ + switch( nPropId ) + { + case XML_Picture: maPictureData = rDataSeq; break; + default: AxFontDataModel::importPictureData( nPropId, rDataSeq ); + } +} + +OUString AxCommandButtonModel::getServiceName() const +{ + return CREATE_OUSTRING( "com.sun.star.form.component.CommandButton" ); +} + +void AxCommandButtonModel::convertProperties( AxControlHelper& rHelper, PropertyMap& rPropMap ) const +{ + rPropMap.setProperty( PROP_Label, maCaption ); + rPropMap.setProperty( PROP_TextColor, rHelper.convertColor( mnTextColor ) ); + rPropMap.setProperty( PROP_Enabled, getFlag( mnFlags, AX_FLAGS_ENABLED ) ); + rPropMap.setProperty( PROP_MultiLine, getFlag( mnFlags, AX_FLAGS_WORDWRAP ) ); + rPropMap.setProperty( PROP_FocusOnClick, mbFocusOnClick ); + rPropMap.setProperty( PROP_VerticalAlign, ::com::sun::star::style::VerticalAlignment_MIDDLE ); + lclConvertBackground( rHelper, rPropMap, mnBackColor, mnFlags, API_TRANSPARENCY_NOTSUPPORTED ); + lclConvertPicture( rHelper, rPropMap, maPictureData, mnPicturePos ); + AxFontDataModel::convertProperties( rHelper, rPropMap ); +} + +// ============================================================================ + +AxLabelModel::AxLabelModel() : + mnTextColor( AX_SYSCOLOR_BUTTONTEXT ), + mnBackColor( AX_SYSCOLOR_BUTTONFACE ), + mnFlags( AX_LABEL_DEFFLAGS ), + mnBorderColor( AX_SYSCOLOR_WINDOWFRAME ), + mnBorderStyle( AX_BORDERSTYLE_NONE ), + mnSpecialEffect( AX_SPECIALEFFECT_FLAT ) +{ +} + +void AxLabelModel::importProperty( sal_Int32 nPropId, const OUString& rValue ) +{ + switch( nPropId ) + { + case XML_Caption: maCaption = rValue; break; + case XML_ForeColor: mnTextColor = AttributeList::decodeUnsigned( rValue ); break; + case XML_BackColor: mnBackColor = AttributeList::decodeUnsigned( rValue ); break; + case XML_VariousPropertyBits: mnFlags = AttributeList::decodeUnsigned( rValue ); break; + case XML_BorderColor: mnBorderColor = AttributeList::decodeUnsigned( rValue ); break; + case XML_BorderStyle: mnBorderStyle = AttributeList::decodeInteger( rValue ); break; + case XML_SpecialEffect: mnSpecialEffect = AttributeList::decodeInteger( rValue ); break; + default: AxFontDataModel::importProperty( nPropId, rValue ); + } +} + +OUString AxLabelModel::getServiceName() const +{ + return CREATE_OUSTRING( "com.sun.star.form.component.FixedText" ); +} + +void AxLabelModel::convertProperties( AxControlHelper& rHelper, PropertyMap& rPropMap ) const +{ + rPropMap.setProperty( PROP_Label, maCaption ); + rPropMap.setProperty( PROP_TextColor, rHelper.convertColor( mnTextColor ) ); + rPropMap.setProperty( PROP_Enabled, getFlag( mnFlags, AX_FLAGS_ENABLED ) ); + rPropMap.setProperty( PROP_MultiLine, getFlag( mnFlags, AX_FLAGS_WORDWRAP ) ); + rPropMap.setProperty( PROP_VerticalAlign, ::com::sun::star::style::VerticalAlignment_TOP ); + lclConvertBackground( rHelper, rPropMap, mnBackColor, mnFlags, API_TRANSPARENCY_VOID ); + lclConvertBorder( rHelper, rPropMap, mnBorderColor, mnBorderStyle, mnSpecialEffect ); + AxFontDataModel::convertProperties( rHelper, rPropMap ); +} + +// ============================================================================ + +AxImageModel::AxImageModel() : + mnBackColor( AX_SYSCOLOR_BUTTONFACE ), + mnFlags( AX_IMAGE_DEFFLAGS ), + mnBorderColor( AX_SYSCOLOR_WINDOWFRAME ), + mnBorderStyle( AX_BORDERSTYLE_SINGLE ), + mnSpecialEffect( AX_SPECIALEFFECT_FLAT ), + mnPicSizeMode( AX_PICSIZE_CLIP ), + mnPicAlign( AX_PICALIGN_CENTER ), + mbPicTiling( false ) +{ +} + +void AxImageModel::importProperty( sal_Int32 nPropId, const OUString& rValue ) +{ + switch( nPropId ) + { + case XML_BackColor: mnBackColor = AttributeList::decodeUnsigned( rValue ); break; + case XML_VariousPropertyBits: mnFlags = AttributeList::decodeUnsigned( rValue ); break; + case XML_BorderColor: mnBorderColor = AttributeList::decodeUnsigned( rValue ); break; + case XML_BorderStyle: mnBorderStyle = AttributeList::decodeInteger( rValue ); break; + case XML_SpecialEffect: mnSpecialEffect = AttributeList::decodeInteger( rValue ); break; + case XML_SizeMode: mnPicSizeMode = AttributeList::decodeInteger( rValue ); break; + case XML_PictureAlignment: mnPicAlign = AttributeList::decodeInteger( rValue ); break; + case XML_PictureTiling: mbPicTiling = AttributeList::decodeInteger( rValue ) != 0; break; + default: AxControlModelBase::importProperty( nPropId, rValue ); + } +} + +void AxImageModel::importPictureData( sal_Int32 nPropId, const StreamDataSequence& rDataSeq ) +{ + switch( nPropId ) + { + case XML_Picture: maPictureData = rDataSeq; break; + default: AxControlModelBase::importPictureData( nPropId, rDataSeq ); + } +} + +OUString AxImageModel::getServiceName() const +{ + return CREATE_OUSTRING( "com.sun.star.form.component.DatabaseImageControl" ); +} + +void AxImageModel::convertProperties( AxControlHelper& rHelper, PropertyMap& rPropMap ) const +{ + rPropMap.setProperty( PROP_Enabled, getFlag( mnFlags, AX_FLAGS_ENABLED ) ); + lclConvertBackground( rHelper, rPropMap, mnBackColor, mnFlags, API_TRANSPARENCY_VOID ); + lclConvertBorder( rHelper, rPropMap, mnBorderColor, mnBorderStyle, mnSpecialEffect ); + lclConvertPicture( rHelper, rPropMap, maPictureData, mnPicSizeMode, mnPicAlign, mbPicTiling ); + AxControlModelBase::convertProperties( rHelper, rPropMap ); +} + +// ============================================================================ + +AxMorphDataModel::AxMorphDataModel() : + mnTextColor( AX_SYSCOLOR_WINDOWTEXT ), + mnBackColor( AX_SYSCOLOR_WINDOWBACK ), + mnFlags( AX_MORPHDATA_DEFFLAGS ), + mnPicturePos( AX_PICPOS_ABOVECENTER ), + mnBorderColor( AX_SYSCOLOR_WINDOWFRAME ), + mnBorderStyle( AX_BORDERSTYLE_NONE ), + mnSpecialEffect( AX_SPECIALEFFECT_SUNKEN ), + mnDisplayStyle( AX_DISPLAYSTYLE_TEXT ), + mnMultiSelect( AX_SELCTION_SINGLE ), + mnScrollBars( AX_SCROLLBAR_NONE ), + mnMatchEntry( AX_MATCHENTRY_NONE ), + mnShowDropButton( AX_SHOWDROPBUTTON_NEVER ), + mnMaxLength( 0 ), + mnPasswordChar( 0 ), + mnListRows( 8 ) +{ +} + +void AxMorphDataModel::importProperty( sal_Int32 nPropId, const OUString& rValue ) +{ + switch( nPropId ) + { + case XML_Caption: maCaption = rValue; break; + case XML_Value: maValue = rValue; break; + case XML_GroupName: maGroupName = rValue; break; + case XML_ForeColor: mnTextColor = AttributeList::decodeUnsigned( rValue ); break; + case XML_BackColor: mnBackColor = AttributeList::decodeUnsigned( rValue ); break; + case XML_VariousPropertyBits: mnFlags = AttributeList::decodeUnsigned( rValue ); break; + case XML_PicturePosition: mnPicturePos = AttributeList::decodeUnsigned( rValue ); break; + case XML_BorderColor: mnBorderColor = AttributeList::decodeUnsigned( rValue ); break; + case XML_BorderStyle: mnBorderStyle = AttributeList::decodeInteger( rValue ); break; + case XML_SpecialEffect: mnSpecialEffect = AttributeList::decodeInteger( rValue ); break; + case XML_DisplayStyle: mnDisplayStyle = AttributeList::decodeInteger( rValue ); break; + case XML_MultiSelect: mnMultiSelect = AttributeList::decodeInteger( rValue ); break; + case XML_ScrollBars: mnScrollBars = AttributeList::decodeInteger( rValue ); break; + case XML_MatchEntry: mnMatchEntry = AttributeList::decodeInteger( rValue ); break; + case XML_ShowDropButtonWhen: mnShowDropButton = AttributeList::decodeInteger( rValue ); break; + case XML_MaxLength: mnMaxLength = AttributeList::decodeInteger( rValue ); break; + case XML_PasswordChar: mnPasswordChar = AttributeList::decodeInteger( rValue ); break; + case XML_ListRows: mnListRows = AttributeList::decodeInteger( rValue ); break; + default: AxFontDataModel::importProperty( nPropId, rValue ); + } +} + +void AxMorphDataModel::importPictureData( sal_Int32 nPropId, const StreamDataSequence& rDataSeq ) +{ + switch( nPropId ) + { + case XML_Picture: maPictureData = rDataSeq; break; + default: AxFontDataModel::importPictureData( nPropId, rDataSeq ); + } +} + +void AxMorphDataModel::convertProperties( AxControlHelper& rHelper, PropertyMap& rPropMap ) const +{ + rPropMap.setProperty( PROP_TextColor, rHelper.convertColor( mnTextColor ) ); + rPropMap.setProperty( PROP_Enabled, getFlag( mnFlags, AX_FLAGS_ENABLED ) ); + AxFontDataModel::convertProperties( rHelper, rPropMap ); +} + +// ============================================================================ + +AxToggleButtonModel::AxToggleButtonModel() +{ +} + +OUString AxToggleButtonModel::getServiceName() const +{ + OSL_ENSURE( mnDisplayStyle == AX_DISPLAYSTYLE_TOGGLE, "AxToggleButtonModel::getServiceName - invalid control type" ); + return CREATE_OUSTRING( "com.sun.star.form.component.CommandButton" ); +} + +void AxToggleButtonModel::convertProperties( AxControlHelper& rHelper, PropertyMap& rPropMap ) const +{ + rPropMap.setProperty( PROP_Label, maCaption ); + rPropMap.setProperty( PROP_MultiLine, getFlag( mnFlags, AX_FLAGS_WORDWRAP ) ); + rPropMap.setProperty( PROP_VerticalAlign, ::com::sun::star::style::VerticalAlignment_MIDDLE ); + rPropMap.setProperty( PROP_Toggle, true ); + lclConvertBackground( rHelper, rPropMap, mnBackColor, mnFlags, API_TRANSPARENCY_NOTSUPPORTED ); + lclConvertPicture( rHelper, rPropMap, maPictureData, mnPicturePos ); + AxMorphDataModel::convertProperties( rHelper, rPropMap ); +} + +// ============================================================================ + +AxCheckBoxModel::AxCheckBoxModel() +{ +} + +OUString AxCheckBoxModel::getServiceName() const +{ + OSL_ENSURE( mnDisplayStyle == AX_DISPLAYSTYLE_CHECKBOX, "AxCheckBoxModel::getServiceName - invalid control type" ); + return CREATE_OUSTRING( "com.sun.star.form.component.CheckBox" ); +} + +void AxCheckBoxModel::convertProperties( AxControlHelper& rHelper, PropertyMap& rPropMap ) const +{ + rPropMap.setProperty( PROP_Label, maCaption ); + rPropMap.setProperty( PROP_MultiLine, getFlag( mnFlags, AX_FLAGS_WORDWRAP ) ); + rPropMap.setProperty( PROP_VerticalAlign, ::com::sun::star::style::VerticalAlignment_MIDDLE ); + lclConvertBackground( rHelper, rPropMap, mnBackColor, mnFlags, API_TRANSPARENCY_VOID ); + lclConvertVisualEffect( rHelper, rPropMap, mnSpecialEffect ); + lclConvertPicture( rHelper, rPropMap, maPictureData, mnPicturePos ); + lclConvertState( rHelper, rPropMap, maValue, mnMultiSelect, true ); + AxMorphDataModel::convertProperties( rHelper, rPropMap ); +} + +// ============================================================================ + +AxOptionButtonModel::AxOptionButtonModel() +{ +} + +OUString AxOptionButtonModel::getServiceName() const +{ + OSL_ENSURE( mnDisplayStyle == AX_DISPLAYSTYLE_OPTBUTTON, "AxOptionButtonModel::getServiceName - invalid control type" ); + return CREATE_OUSTRING( "com.sun.star.form.component.RadioButton" ); +} + +void AxOptionButtonModel::convertProperties( AxControlHelper& rHelper, PropertyMap& rPropMap ) const +{ + rPropMap.setProperty( PROP_Label, maCaption ); + rPropMap.setProperty( PROP_MultiLine, getFlag( mnFlags, AX_FLAGS_WORDWRAP ) ); + rPropMap.setProperty( PROP_VerticalAlign, ::com::sun::star::style::VerticalAlignment_MIDDLE ); + lclConvertBackground( rHelper, rPropMap, mnBackColor, mnFlags, API_TRANSPARENCY_VOID ); + lclConvertVisualEffect( rHelper, rPropMap, mnSpecialEffect ); + lclConvertPicture( rHelper, rPropMap, maPictureData, mnPicturePos ); + lclConvertState( rHelper, rPropMap, maValue, mnMultiSelect, false ); + AxMorphDataModel::convertProperties( rHelper, rPropMap ); +} + +// ============================================================================ + +AxTextBoxModel::AxTextBoxModel() +{ +} + +OUString AxTextBoxModel::getServiceName() const +{ + OSL_ENSURE( mnDisplayStyle == AX_DISPLAYSTYLE_TEXT, "AxTextBoxModel::getServiceName - invalid control type" ); + return CREATE_OUSTRING( "com.sun.star.form.component.TextField" ); +} + +void AxTextBoxModel::convertProperties( AxControlHelper& rHelper, PropertyMap& rPropMap ) const +{ + rPropMap.setProperty( PROP_MultiLine, getFlag( mnFlags, AX_FLAGS_MULTILINE ) ); + rPropMap.setProperty( PROP_HideInactiveSelection, getFlag( mnFlags, AX_FLAGS_HIDESELECTION ) ); + rPropMap.setProperty( PROP_DefaultText, maValue ); + rPropMap.setProperty( PROP_MaxTextLen, getLimitedValue< sal_Int16, sal_Int32 >( mnMaxLength, 0, SAL_MAX_INT16 ) ); + if( (0 < mnPasswordChar) && (mnPasswordChar <= SAL_MAX_INT16) ) + rPropMap.setProperty( PROP_EchoChar, static_cast< sal_Int16 >( mnPasswordChar ) ); + rPropMap.setProperty( PROP_HScroll, getFlag( mnScrollBars, AX_SCROLLBAR_HORIZONTAL ) ); + rPropMap.setProperty( PROP_VScroll, getFlag( mnScrollBars, AX_SCROLLBAR_VERTICAL ) ); + lclConvertBackground( rHelper, rPropMap, mnBackColor, mnFlags, API_TRANSPARENCY_VOID ); + lclConvertBorder( rHelper, rPropMap, mnBorderColor, mnBorderStyle, mnSpecialEffect ); + AxMorphDataModel::convertProperties( rHelper, rPropMap ); +} + +// ============================================================================ + +AxListBoxModel::AxListBoxModel() +{ +} + +OUString AxListBoxModel::getServiceName() const +{ + OSL_ENSURE( mnDisplayStyle == AX_DISPLAYSTYLE_LISTBOX, "AxListBoxModel::getServiceName - invalid control type" ); + return CREATE_OUSTRING( "com.sun.star.form.component.ListBox" ); +} + +void AxListBoxModel::convertProperties( AxControlHelper& rHelper, PropertyMap& rPropMap ) const +{ + bool bMultiSelect = (mnMultiSelect == AX_SELCTION_MULTI) || (mnMultiSelect == AX_SELCTION_EXTENDED); + rPropMap.setProperty( PROP_MultiSelection, bMultiSelect ); + rPropMap.setProperty( PROP_Dropdown, false ); + lclConvertBackground( rHelper, rPropMap, mnBackColor, mnFlags, API_TRANSPARENCY_VOID ); + lclConvertBorder( rHelper, rPropMap, mnBorderColor, mnBorderStyle, mnSpecialEffect ); + AxMorphDataModel::convertProperties( rHelper, rPropMap ); +} + +// ============================================================================ + +AxComboBoxModel::AxComboBoxModel() +{ +} + +OUString AxComboBoxModel::getServiceName() const +{ + OSL_ENSURE( (mnDisplayStyle == AX_DISPLAYSTYLE_COMBOBOX) || (mnDisplayStyle == AX_DISPLAYSTYLE_DROPDOWN), "AxComboBoxModel::getServiceName - invalid control type" ); + return (mnDisplayStyle == AX_DISPLAYSTYLE_DROPDOWN) ? CREATE_OUSTRING( "com.sun.star.form.component.ListBox" ) : CREATE_OUSTRING( "com.sun.star.form.component.ComboBox" ); +} + +void AxComboBoxModel::convertProperties( AxControlHelper& rHelper, PropertyMap& rPropMap ) const +{ + if( mnDisplayStyle != AX_DISPLAYSTYLE_DROPDOWN ) + { + rPropMap.setProperty( PROP_HideInactiveSelection, getFlag( mnFlags, AX_FLAGS_HIDESELECTION ) ); + rPropMap.setProperty( PROP_DefaultText, maValue ); + rPropMap.setProperty( PROP_MaxTextLen, getLimitedValue< sal_Int16, sal_Int32 >( mnMaxLength, 0, SAL_MAX_INT16 ) ); + bool bAutoComplete = (mnMatchEntry == AX_MATCHENTRY_FIRSTLETTER) || (mnMatchEntry == AX_MATCHENTRY_COMPLETE); + rPropMap.setProperty( PROP_Autocomplete, bAutoComplete ); + } + bool bShowDropdown = (mnShowDropButton == AX_SHOWDROPBUTTON_FOCUS) || (mnShowDropButton == AX_SHOWDROPBUTTON_ALWAYS); + rPropMap.setProperty( PROP_Dropdown, bShowDropdown ); + rPropMap.setProperty( PROP_LineCount, getLimitedValue< sal_Int16, sal_Int32 >( mnListRows, 1, SAL_MAX_INT16 ) ); + lclConvertBackground( rHelper, rPropMap, mnBackColor, mnFlags, API_TRANSPARENCY_VOID ); + lclConvertBorder( rHelper, rPropMap, mnBorderColor, mnBorderStyle, mnSpecialEffect ); + AxMorphDataModel::convertProperties( rHelper, rPropMap ); +} + +// ============================================================================ + +AxSpinButtonModel::AxSpinButtonModel() : + mnArrowColor( AX_SYSCOLOR_BUTTONTEXT ), + mnBackColor( AX_SYSCOLOR_BUTTONFACE ), + mnFlags( AX_SPINBUTTON_DEFFLAGS ), + mnOrientation( AX_ORIENTATION_AUTO ), + mnMin( 0 ), + mnMax( 100 ), + mnPosition( 0 ), + mnSmallChange( 1 ), + mnDelay( 50 ) +{ +} + +OUString AxSpinButtonModel::getServiceName() const +{ + return CREATE_OUSTRING( "com.sun.star.form.component.SpinButton" ); +} + +void AxSpinButtonModel::importProperty( sal_Int32 nPropId, const OUString& rValue ) +{ + switch( nPropId ) + { + case XML_ForeColor: mnArrowColor = AttributeList::decodeUnsigned( rValue ); break; + case XML_BackColor: mnBackColor = AttributeList::decodeUnsigned( rValue ); break; + case XML_VariousPropertyBits: mnFlags = AttributeList::decodeUnsigned( rValue ); break; + case XML_Orientation: mnOrientation = AttributeList::decodeInteger( rValue ); break; + case XML_Min: mnMin = AttributeList::decodeInteger( rValue ); break; + case XML_Max: mnMax = AttributeList::decodeInteger( rValue ); break; + case XML_Position: mnPosition = AttributeList::decodeInteger( rValue ); break; + case XML_SmallChange: mnSmallChange = AttributeList::decodeInteger( rValue ); break; + case XML_Delay: mnDelay = AttributeList::decodeInteger( rValue ); break; + default: AxControlModelBase::importProperty( nPropId, rValue ); + } +} + +void AxSpinButtonModel::convertProperties( AxControlHelper& rHelper, PropertyMap& rPropMap ) const +{ + sal_Int32 nMin = ::std::min( mnMin, mnMax ); + sal_Int32 nMax = ::std::max( mnMin, mnMax ); + rPropMap.setProperty( PROP_SymbolColor, rHelper.convertColor( mnArrowColor ) ); + rPropMap.setProperty( PROP_Enabled, getFlag( mnFlags, AX_FLAGS_ENABLED ) ); + rPropMap.setProperty( PROP_SpinValueMin, nMin ); + rPropMap.setProperty( PROP_SpinValueMax, nMax ); + rPropMap.setProperty( PROP_SpinIncrement, mnSmallChange ); + rPropMap.setProperty( PROP_DefaultSpinValue, mnPosition ); + rPropMap.setProperty( PROP_Repeat, true ); + rPropMap.setProperty( PROP_RepeatDelay, mnDelay ); + rPropMap.setProperty( PROP_Border, API_BORDER_NONE ); + lclConvertBackground( rHelper, rPropMap, mnBackColor, mnFlags, API_TRANSPARENCY_NOTSUPPORTED ); + lclConvertOrientation( rHelper, rPropMap, mnOrientation, mnWidth, mnHeight ); + AxControlModelBase::convertProperties( rHelper, rPropMap ); +} + +// ============================================================================ + +AxScrollBarModel::AxScrollBarModel() : + mnArrowColor( AX_SYSCOLOR_BUTTONTEXT ), + mnBackColor( AX_SYSCOLOR_BUTTONFACE ), + mnFlags( AX_SCROLLBAR_DEFFLAGS ), + mnOrientation( AX_ORIENTATION_AUTO ), + mnPropThumb( AX_PROPTHUMB_ON ), + mnMin( 0 ), + mnMax( 32767 ), + mnPosition( 0 ), + mnSmallChange( 1 ), + mnLargeChange( 1 ), + mnDelay( 50 ) +{ +} + +OUString AxScrollBarModel::getServiceName() const +{ + return CREATE_OUSTRING( "com.sun.star.form.component.ScrollBar" ); +} + +void AxScrollBarModel::importProperty( sal_Int32 nPropId, const OUString& rValue ) +{ + switch( nPropId ) + { + case XML_ForeColor: mnArrowColor = AttributeList::decodeUnsigned( rValue ); break; + case XML_BackColor: mnBackColor = AttributeList::decodeUnsigned( rValue ); break; + case XML_VariousPropertyBits: mnFlags = AttributeList::decodeUnsigned( rValue ); break; + case XML_Orientation: mnOrientation = AttributeList::decodeInteger( rValue ); break; + case XML_ProportionalThumb: mnPropThumb = AttributeList::decodeInteger( rValue ); break; + case XML_Min: mnMin = AttributeList::decodeInteger( rValue ); break; + case XML_Max: mnMax = AttributeList::decodeInteger( rValue ); break; + case XML_Position: mnPosition = AttributeList::decodeInteger( rValue ); break; + case XML_SmallChange: mnSmallChange = AttributeList::decodeInteger( rValue ); break; + case XML_LargeChange: mnLargeChange = AttributeList::decodeInteger( rValue ); break; + case XML_Delay: mnDelay = AttributeList::decodeInteger( rValue ); break; + default: AxControlModelBase::importProperty( nPropId, rValue ); + } +} + +void AxScrollBarModel::convertProperties( AxControlHelper& rHelper, PropertyMap& rPropMap ) const +{ + sal_Int32 nMin = ::std::min( mnMin, mnMax ); + sal_Int32 nMax = ::std::max( mnMin, mnMax ); + rPropMap.setProperty( PROP_SymbolColor, rHelper.convertColor( mnArrowColor ) ); + rPropMap.setProperty( PROP_Enabled, getFlag( mnFlags, AX_FLAGS_ENABLED ) ); + rPropMap.setProperty( PROP_ScrollValueMin, nMin ); + rPropMap.setProperty( PROP_ScrollValueMax, nMax ); + rPropMap.setProperty( PROP_LineIncrement, mnSmallChange ); + rPropMap.setProperty( PROP_BlockIncrement, mnLargeChange ); + rPropMap.setProperty( PROP_DefaultScrollValue, mnPosition ); + rPropMap.setProperty( PROP_RepeatDelay, mnDelay ); + rPropMap.setProperty( PROP_Border, API_BORDER_NONE ); + if( (mnPropThumb == AX_PROPTHUMB_ON) && (nMin < nMax) && (mnLargeChange > 0) ) + { + double fInterval = nMax - nMin; // prevent integer overflow (fInterval+mnLargeChange may become 0 when int is used) + sal_Int32 nThumbLen = getLimitedValue< sal_Int32, double >( (fInterval * mnLargeChange) / (fInterval + mnLargeChange), 1, SAL_MAX_INT32 ); + rPropMap.setProperty( PROP_VisibleSize, nThumbLen ); + } + lclConvertBackground( rHelper, rPropMap, mnBackColor, mnFlags, API_TRANSPARENCY_NOTSUPPORTED ); + lclConvertOrientation( rHelper, rPropMap, mnOrientation, mnWidth, mnHeight ); + AxControlModelBase::convertProperties( rHelper, rPropMap ); +} + +// ============================================================================ + +AxControl::AxControl( const OUString& rName ) : + maName( rName ) +{ +} + +AxControl::~AxControl() +{ +} + +AxControlModelBase* AxControl::createModel( const OUString& rClassId ) +{ + // TODO: move into a factory + if( rClassId.equalsIgnoreAsciiCaseAscii( "{D7053240-CE69-11CD-A777-00DD01143C57}" ) ) // Forms.CommandButton.1 + mxModel.reset( new AxCommandButtonModel ); + else if( rClassId.equalsIgnoreAsciiCaseAscii( "{978C9E23-D4B0-11CE-BF2D-00AA003F40D0}" ) ) // Forms.Label.1 + mxModel.reset( new AxLabelModel ); + else if( rClassId.equalsIgnoreAsciiCaseAscii( "{4C599241-6926-101B-9992-00000B65C6F9}" ) ) // Forms.Image.1 + mxModel.reset( new AxImageModel ); + else if( rClassId.equalsIgnoreAsciiCaseAscii( "{8BD21D60-EC42-11CE-9E0D-00AA006002F3}" ) ) // Forms.ToggleButton.1 + mxModel.reset( new AxToggleButtonModel ); + else if( rClassId.equalsIgnoreAsciiCaseAscii( "{8BD21D40-EC42-11CE-9E0D-00AA006002F3}" ) ) // Forms.CheckBox.1 + mxModel.reset( new AxCheckBoxModel ); + else if( rClassId.equalsIgnoreAsciiCaseAscii( "{8BD21D50-EC42-11CE-9E0D-00AA006002F3}" ) ) // Forms.OptionButton.1 + mxModel.reset( new AxOptionButtonModel ); + else if( rClassId.equalsIgnoreAsciiCaseAscii( "{8BD21D10-EC42-11CE-9E0D-00AA006002F3}" ) ) // Forms.TextBox.1 + mxModel.reset( new AxTextBoxModel ); + else if( rClassId.equalsIgnoreAsciiCaseAscii( "{8BD21D20-EC42-11CE-9E0D-00AA006002F3}" ) ) // Forms.ListBox.1 + mxModel.reset( new AxListBoxModel ); + else if( rClassId.equalsIgnoreAsciiCaseAscii( "{8BD21D30-EC42-11CE-9E0D-00AA006002F3}" ) ) // Forms.ComboBox.1 + mxModel.reset( new AxComboBoxModel ); + else if( rClassId.equalsIgnoreAsciiCaseAscii( "{79176FB0-B7F2-11CE-97EF-00AA006D2776}" ) ) // Forms.SpinButton.1 + mxModel.reset( new AxSpinButtonModel ); + else if( rClassId.equalsIgnoreAsciiCaseAscii( "{DFD181E0-5E2F-11CE-A449-00AA004A803D}" ) ) // Forms.ScrollBar.1 + mxModel.reset( new AxScrollBarModel ); + else + mxModel.reset(); + + return mxModel.get(); +} + +Reference< XControlModel > AxControl::convertAndInsert( AxControlHelper& rHelper ) const +{ + Reference< XControlModel > xCtrlModel; + if( mxModel.get() ) try + { + Reference< XIndexContainer > xFormIC( rHelper.getControlForm(), UNO_QUERY_THROW ); + + // document model creates the form control model + xCtrlModel.set( rHelper.getFilter().getModelFactory()->createInstance( mxModel->getServiceName() ), UNO_QUERY_THROW ); + Reference< XFormComponent > xFormComp( xCtrlModel, UNO_QUERY_THROW ); + + // insert control model into the passed form + sal_Int32 nNewIndex = xFormIC->getCount(); + xFormIC->insertByIndex( nNewIndex, Any( xFormComp ) ); + + // convert all control properties + PropertyMap aPropMap; + aPropMap.setProperty( PROP_Name, maName ); + mxModel->convertProperties( rHelper, aPropMap ); + + PropertySet aPropSet( xCtrlModel ); + aPropSet.setProperties( aPropMap ); + } + catch( Exception& ) + { + xCtrlModel.clear(); // on error: forget the created form control model + } + return xCtrlModel; +} + +// ============================================================================ + +} // namespace ole +} // namespace oox + diff --git a/oox/source/ole/axcontrolfragment.cxx b/oox/source/ole/axcontrolfragment.cxx new file mode 100644 index 000000000000..ff1b1e1c8117 --- /dev/null +++ b/oox/source/ole/axcontrolfragment.cxx @@ -0,0 +1,118 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: axcontrolfragment.cxx,v $ + * $Revision: 1.1 $ + * + * 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. + * + ************************************************************************/ + +#include "oox/ole/axcontrolfragment.hxx" +#include "oox/helper/binaryinputstream.hxx" +#include "oox/helper/binaryoutputstream.hxx" +#include "oox/core/xmlfilterbase.hxx" +#include "oox/ole/axcontrol.hxx" + +using ::rtl::OUString; +using ::oox::core::ContextHandler2; +using ::oox::core::ContextHandlerRef; +using ::oox::core::FragmentHandler2; +using ::oox::core::XmlFilterBase; + +namespace oox { +namespace ole { + +// ============================================================================ + +AxControlPropertyContext::AxControlPropertyContext( FragmentHandler2& rFragment, AxControlModelBase& rModel ) : + ContextHandler2( rFragment ), + mrModel( rModel ), + mnPropId( XML_TOKEN_INVALID ) +{ +} + +ContextHandlerRef AxControlPropertyContext::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs ) +{ + switch( getCurrentElement() ) + { + case AX_TOKEN( ocx ): + if( nElement == AX_TOKEN( ocxPr ) ) + { + mnPropId = rAttribs.getToken( AX_TOKEN( name ), XML_TOKEN_INVALID ); + switch( mnPropId ) + { + case XML_TOKEN_INVALID: + return 0; + case XML_Picture: + case XML_MouseIcon: + return this; // import picture path from ax:picture child element + default: + mrModel.importProperty( mnPropId, rAttribs.getString( AX_TOKEN( value ), OUString() ) ); + } + } + break; + + case AX_TOKEN( ocxPr ): + if( nElement == AX_TOKEN( picture ) ) + { + OUString aPicturePath = getFragmentPathFromRelId( rAttribs.getString( R_TOKEN( id ), OUString() ) ); + if( aPicturePath.getLength() > 0 ) + { + StreamDataSequence aPictureData; + if( getFilter().importBinaryData( aPictureData, aPicturePath ) ) + mrModel.importPictureData( mnPropId, aPictureData ); + } + } + break; + } + return 0; +} + +// ============================================================================ + +AxControlFragment::AxControlFragment( XmlFilterBase& rFilter, const OUString& rFragmentPath, AxControl& rControl ) : + FragmentHandler2( rFilter, rFragmentPath, true ), + mrControl( rControl ) +{ +} + +ContextHandlerRef AxControlFragment::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs ) +{ + if( isRootElement() && (nElement == AX_TOKEN( ocx )) ) + { + if( rAttribs.getToken( AX_TOKEN( persistence ), XML_TOKEN_INVALID ) == XML_persistPropertyBag ) + { + OUString aClassId = rAttribs.getString( AX_TOKEN( classid ), OUString() ); + if( AxControlModelBase* pModel = mrControl.createModel( aClassId ) ) + return new AxControlPropertyContext( *this, *pModel ); + } + } + return 0; +} + +// ============================================================================ + +} // namespace ole +} // namespace oox + diff --git a/oox/source/ole/axcontrolhelper.cxx b/oox/source/ole/axcontrolhelper.cxx new file mode 100644 index 000000000000..a1bd9bfd9ac7 --- /dev/null +++ b/oox/source/ole/axcontrolhelper.cxx @@ -0,0 +1,182 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: axcontrolhelper.cxx,v $ + * $Revision: 1.1 $ + * + * 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. + * + ************************************************************************/ + +#include "oox/ole/axcontrolhelper.hxx" +#include <com/sun/star/container/XNameContainer.hpp> +#include <com/sun/star/form/XForm.hpp> +#include <com/sun/star/form/XFormsSupplier.hpp> +#include "tokens.hxx" +#include "oox/helper/containerhelper.hxx" +#include "oox/core/filterbase.hxx" +#include "oox/drawingml/color.hxx" + +using ::rtl::OUString; +using ::com::sun::star::uno::Any; +using ::com::sun::star::uno::Exception; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::UNO_QUERY_THROW; +using ::com::sun::star::uno::UNO_SET_THROW; +using ::com::sun::star::container::XNameContainer; +using ::com::sun::star::graphic::XGraphic; +using ::com::sun::star::drawing::XDrawPage; +using ::com::sun::star::form::XForm; +using ::com::sun::star::form::XFormsSupplier; +using ::oox::core::FilterBase; + +namespace oox { +namespace ole { + +// ============================================================================ + +namespace { + +const sal_uInt32 AX_COLORTYPE_MASK = 0xFF000000; +const sal_uInt32 AX_COLORTYPE_CLIENT = 0x00000000; +const sal_uInt32 AX_COLORTYPE_PALETTE = 0x01000000; +const sal_uInt32 AX_COLORTYPE_BGR = 0x02000000; +const sal_uInt32 AX_COLORTYPE_SYSCOLOR = 0x80000000; + +const sal_uInt32 AX_PALETTECOLOR_MASK = 0x0000FFFF; +const sal_uInt32 AX_BGRCOLOR_MASK = 0x00FFFFFF; +const sal_uInt32 AX_SYSTEMCOLOR_MASK = 0x0000FFFF; + +// ---------------------------------------------------------------------------- + +/** Returns the UNO RGB color from the passed encoded OLE BGR color. */ +inline sal_Int32 lclDecodeBgrColor( sal_uInt32 nAxColor ) +{ + return static_cast< sal_Int32 >( ((nAxColor & 0x0000FF) << 16) | (nAxColor & 0x00FF00) | ((nAxColor & 0xFF0000) >> 16) ); +} + +} // namespace + +// ============================================================================ + +AxControlHelper::AxControlHelper( const FilterBase& rFilter, AxDefaultColorMode eColorMode ) : + mrFilter( rFilter ), + meColorMode( eColorMode ), + mbHasFormQuerried( false ) +{ +} + +AxControlHelper::~AxControlHelper() +{ +} + +Reference< XForm > AxControlHelper::getControlForm() const +{ + if( !mbHasFormQuerried ) + mxForm = createControlForm(); // virtual call + mbHasFormQuerried = true; + return mxForm; +} + +sal_Int32 AxControlHelper::convertColor( sal_uInt32 nAxColor ) const +{ + static const sal_Int32 spnSystemColors[] = + { + XML_scrollBar, XML_background, XML_activeCaption, XML_inactiveCaption, + XML_menu, XML_window, XML_windowFrame, XML_menuText, + XML_windowText, XML_captionText, XML_activeBorder, XML_inactiveBorder, + XML_appWorkspace, XML_highlight, XML_highlightText, XML_btnFace, + XML_btnShadow, XML_grayText, XML_btnText, XML_inactiveCaptionText, + XML_btnHighlight, XML_3dDkShadow, XML_3dLight, XML_infoText, + XML_infoBk + }; + + switch( nAxColor & AX_COLORTYPE_MASK ) + { + case AX_COLORTYPE_CLIENT: + switch( meColorMode ) + { + case AX_DEFAULTCOLORMODE_BGR: return lclDecodeBgrColor( nAxColor ); + case AX_DEFAULTCOLORMODE_PALETTE: return getPaletteColor( static_cast< sal_uInt16 >( nAxColor & AX_PALETTECOLOR_MASK ) ); + } + break; + + case AX_COLORTYPE_PALETTE: + return getPaletteColor( static_cast< sal_uInt16 >( nAxColor & AX_PALETTECOLOR_MASK ) ); + + case AX_COLORTYPE_BGR: + return lclDecodeBgrColor( nAxColor ); + + case AX_COLORTYPE_SYSCOLOR: + return mrFilter.getSystemColor( STATIC_ARRAY_SELECT( spnSystemColors, nAxColor & AX_SYSTEMCOLOR_MASK, XML_TOKEN_INVALID ), API_RGB_WHITE ); + } + OSL_ENSURE( false, "AxControlHelper::convertColor - unknown color type" ); + return 0; +} + +sal_Int32 AxControlHelper::getPaletteColor( sal_uInt16 /*nPaletteIdx*/ ) const +{ + OSL_ENSURE( false, "AxControlHelper::getPaletteColor - palette colors not implemented" ); + return 0; +} + +// ============================================================================ + +AxEmbeddedControlHelper::AxEmbeddedControlHelper( const FilterBase& rFilter, + const Reference< XDrawPage >& rxDrawPage, AxDefaultColorMode eColorMode ) : + AxControlHelper( rFilter, eColorMode ), + mxDrawPage( rxDrawPage ) +{ +} + +Reference< XForm > AxEmbeddedControlHelper::createControlForm() const +{ + Reference< XForm > xForm; + try + { + Reference< XFormsSupplier > xFormsSupplier( mxDrawPage, UNO_QUERY_THROW ); + Reference< XNameContainer > xFormsNC( xFormsSupplier->getForms(), UNO_SET_THROW ); + OUString aFormName = CREATE_OUSTRING( "Standard" ); + if( xFormsNC->hasByName( aFormName ) ) + { + xFormsNC->getByName( aFormName ) >>= xForm; + } + else + { + Reference< XForm > xNewForm( getFilter().getModelFactory()->createInstance( CREATE_OUSTRING( "com.sun.star.form.component.Form" ) ), UNO_QUERY_THROW ); + xFormsNC->insertByName( aFormName, Any( xNewForm ) ); + // return the form if insertion did not fail + xForm = xNewForm; + } + } + catch( Exception& ) + { + } + return xForm; +} + +// ============================================================================ + +} // namespace ole +} // namespace oox + diff --git a/oox/source/ole/makefile.mk b/oox/source/ole/makefile.mk index 14575fd6450f..6d466e1f39ab 100644 --- a/oox/source/ole/makefile.mk +++ b/oox/source/ole/makefile.mk @@ -45,6 +45,11 @@ ENABLE_EXCEPTIONS=TRUE # --- Files -------------------------------------------------------- SLOFILES = \ + $(SLO)$/axcontrol.obj \ + $(SLO)$/axcontrolfragment.obj \ + $(SLO)$/axcontrolhelper.obj \ + $(SLO)$/olehelper.obj \ + $(SLO)$/oleobjecthelper.obj \ $(SLO)$/vbainputstream.obj # --- Targets ------------------------------------------------------- diff --git a/oox/source/ole/olehelper.cxx b/oox/source/ole/olehelper.cxx new file mode 100644 index 000000000000..c0eb37003d9a --- /dev/null +++ b/oox/source/ole/olehelper.cxx @@ -0,0 +1,214 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: olehelper.cxx,v $ + * $Revision: 1.1 $ + * + * 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. + * + ************************************************************************/ + +#include "oox/ole/olehelper.hxx" +#include <rtl/ustrbuf.hxx> +#include "oox/helper/binaryinputstream.hxx" + +using ::rtl::OUString; +using ::rtl::OUStringBuffer; + +namespace oox { +namespace ole { + +// ============================================================================ + +namespace { + +const sal_Char* const OLE_GUID_STDPIC = "{0BE35204-8F91-11CE-9DE3-00AA004BB851}"; +const sal_Char* const OLE_GUID_STDHLINK = "{79EAC9D0-BAF9-11CE-8C82-00AA004BA90B}"; +const sal_Char* const OLE_GUID_URLMONIKER = "{79EAC9E0-BAF9-11CE-8C82-00AA004BA90B}"; +const sal_Char* const OLE_GUID_FILEMONIKER = "{00000303-0000-0000-C000-000000000046}"; + +const sal_uInt32 OLE_STDPIC_ID = 0x0000746C; + +const sal_uInt32 OLE_STDHLINK_VERSION = 2; +const sal_uInt32 OLE_STDHLINK_HASTARGET = 0x00000001; /// Has hyperlink moniker. +const sal_uInt32 OLE_STDHLINK_ABSOLUTE = 0x00000002; /// Absolute path. +const sal_uInt32 OLE_STDHLINK_HASLOCATION = 0x00000008; /// Has target location. +const sal_uInt32 OLE_STDHLINK_HASDISPLAY = 0x00000010; /// Has display string. +const sal_uInt32 OLE_STDHLINK_HASGUID = 0x00000020; /// Has identification GUID. +const sal_uInt32 OLE_STDHLINK_HASTIME = 0x00000040; /// Has creation time. +const sal_uInt32 OLE_STDHLINK_HASFRAME = 0x00000080; /// Has frame. +const sal_uInt32 OLE_STDHLINK_ASSTRING = 0x00000100; /// Hyperlink as simple string. + +// ---------------------------------------------------------------------------- + +template< typename Type > +void lclAppendHex( OUStringBuffer& orBuffer, Type nValue ) +{ + const sal_Int32 nWidth = 2 * sizeof( Type ); + static const sal_Unicode spcHexChars[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; + orBuffer.setLength( orBuffer.getLength() + nWidth ); + for( sal_Int32 nCharIdx = orBuffer.getLength() - 1, nCharEnd = nCharIdx - nWidth; nCharIdx > nCharEnd; --nCharIdx, nValue >>= 4 ) + orBuffer.setCharAt( nCharIdx, spcHexChars[ nValue & 0xF ] ); +} + +OUString lclReadStdHlinkString( BinaryInputStream& rInStrm, rtl_TextEncoding eTextEnc, bool bUnicode ) +{ + OUString aRet; + sal_Int32 nChars = rInStrm.readInt32(); + if( nChars > 0 ) + { + sal_Int32 nReadChars = getLimitedValue< sal_Int32, sal_Int32 >( nChars, 0, SAL_MAX_UINT16 ); + aRet = bUnicode ? rInStrm.readUnicodeArray( nReadChars, true ) : rInStrm.readCharArrayUC( nReadChars, eTextEnc, true ); + // strings are NUL terminated, remove trailing NUL and possible other garbage + sal_Int32 nNulPos = aRet.indexOf( '\0' ); + if( nNulPos >= 0 ) + aRet = aRet.copy( 0, nNulPos ); + // skip remaining chars + rInStrm.skip( (bUnicode ? 2 : 1) * (nChars - nReadChars) ); + } + return aRet; +} + +} // namespace + +// ============================================================================ + +/*static*/ OUString OleHelper::importGuid( BinaryInputStream& rInStrm ) +{ + OUStringBuffer aBuffer; + aBuffer.append( sal_Unicode( '{' ) ); + lclAppendHex( aBuffer, rInStrm.readuInt32() ); + aBuffer.append( sal_Unicode( '-' ) ); + lclAppendHex( aBuffer, rInStrm.readuInt16() ); + aBuffer.append( sal_Unicode( '-' ) ); + lclAppendHex( aBuffer, rInStrm.readuInt16() ); + aBuffer.append( sal_Unicode( '-' ) ); + lclAppendHex( aBuffer, rInStrm.readuInt8() ); + lclAppendHex( aBuffer, rInStrm.readuInt8() ); + aBuffer.append( sal_Unicode( '-' ) ); + for( int nIndex = 0; nIndex < 6; ++nIndex ) + lclAppendHex( aBuffer, rInStrm.readuInt8() ); + aBuffer.append( sal_Unicode( '}' ) ); + return aBuffer.makeStringAndClear(); +} + +/*static*/ bool OleHelper::importStdPic( StreamDataSequence& orGraphicData, BinaryInputStream& rInStrm, bool bWithGuid ) +{ + if( bWithGuid ) + { + bool bIsStdPic = importGuid( rInStrm ).equalsAscii( OLE_GUID_STDPIC ); + OSL_ENSURE( bIsStdPic, "OleHelper::importStdPic - unexpected header GUID, expected StdPic" ); + if( !bIsStdPic ) + return false; + } + + sal_uInt32 nStdPicId; + sal_Int32 nBytes; + rInStrm >> nStdPicId >> nBytes; + OSL_ENSURE( nStdPicId == OLE_STDPIC_ID, "OleHelper::importStdPic - unexpected header version" ); + return !rInStrm.isEof() && (nStdPicId == OLE_STDPIC_ID) && (nBytes > 0) && (rInStrm.readData( orGraphicData, nBytes ) == nBytes); +} + +/*static*/ bool OleHelper::importStdHlink( StdHlinkInfo& orHlinkInfo, BinaryInputStream& rInStrm, rtl_TextEncoding eTextEnc, bool bWithGuid ) +{ + if( bWithGuid ) + { + bool bIsStdHlink = importGuid( rInStrm ).equalsAscii( OLE_GUID_STDHLINK ); + OSL_ENSURE( bIsStdHlink, "OleHelper::importStdHlink - unexpected header GUID, expected StdHlink" ); + if( !bIsStdHlink ) + return false; + } + + sal_uInt32 nVersion, nFlags; + rInStrm >> nVersion >> nFlags; + OSL_ENSURE( nVersion == OLE_STDHLINK_VERSION, "OleHelper::importStdHlink - unexpected header version" ); + if( rInStrm.isEof() || (nVersion != OLE_STDHLINK_VERSION) ) + return false; + + // display string + if( getFlag( nFlags, OLE_STDHLINK_HASDISPLAY ) ) + orHlinkInfo.maDisplay = lclReadStdHlinkString( rInStrm, eTextEnc, true ); + // frame string + if( getFlag( nFlags, OLE_STDHLINK_HASFRAME ) ) + orHlinkInfo.maFrame = lclReadStdHlinkString( rInStrm, eTextEnc, true ); + + // target + if( getFlag( nFlags, OLE_STDHLINK_HASTARGET ) ) + { + if( getFlag( nFlags, OLE_STDHLINK_ASSTRING ) ) + { + OSL_ENSURE( getFlag( nFlags, OLE_STDHLINK_ABSOLUTE ), "OleHelper::importStdHlink - link not absolute" ); + orHlinkInfo.maTarget = lclReadStdHlinkString( rInStrm, eTextEnc, true ); + } + else // hyperlink moniker + { + OUString aGuid = importGuid( rInStrm ); + if( aGuid.equalsAscii( OLE_GUID_FILEMONIKER ) ) + { + // file name, maybe relative and with directory up-count + sal_Int16 nUpLevels; + rInStrm >> nUpLevels; + OSL_ENSURE( (nUpLevels == 0) || !getFlag( nFlags, OLE_STDHLINK_ABSOLUTE ), "OleHelper::importStdHlink - absolute filename with upcount" ); + orHlinkInfo.maTarget = lclReadStdHlinkString( rInStrm, eTextEnc, false ); + rInStrm.skip( 24 ); + sal_Int32 nBytes = rInStrm.readInt32(); + if( nBytes > 0 ) + { + sal_Int64 nEndPos = rInStrm.tell() + ::std::max< sal_Int32 >( nBytes, 0 ); + sal_uInt16 nChars = getLimitedValue< sal_uInt16, sal_Int32 >( rInStrm.readInt32() / 2, 0, SAL_MAX_UINT16 ); + rInStrm.skip( 2 ); // key value + orHlinkInfo.maTarget = rInStrm.readUnicodeArray( nChars ); // NOT null terminated + rInStrm.seek( nEndPos ); + } + if( !getFlag( nFlags, OLE_STDHLINK_ABSOLUTE ) ) + for( sal_Int16 nLevel = 0; nLevel < nUpLevels; ++nLevel ) + orHlinkInfo.maTarget = CREATE_OUSTRING( "../" ) + orHlinkInfo.maTarget; + } + else if( aGuid.equalsAscii( OLE_GUID_URLMONIKER ) ) + { + // URL, maybe relative and with leading '../' + sal_Int32 nBytes = rInStrm.readInt32(); + sal_Int64 nEndPos = rInStrm.tell() + ::std::max< sal_Int32 >( nBytes, 0 ); + orHlinkInfo.maTarget = rInStrm.readNulUnicodeArray(); + rInStrm.seek( nEndPos ); + } + else + { + OSL_ENSURE( false, "OleHelper::importStdHlink - unsupported hyperlink moniker" ); + return false; + } + } + } + + // target location + if( getFlag( nFlags, OLE_STDHLINK_HASLOCATION ) ) + orHlinkInfo.maLocation = lclReadStdHlinkString( rInStrm, eTextEnc, true ); + + return true; +} + +// ============================================================================ + +} // namespace ole +} // namespace oox + diff --git a/oox/source/ole/oleobjecthelper.cxx b/oox/source/ole/oleobjecthelper.cxx new file mode 100644 index 000000000000..c261c1ee46f1 --- /dev/null +++ b/oox/source/ole/oleobjecthelper.cxx @@ -0,0 +1,144 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: olehelper.cxx,v $ + * $Revision: 1.1 $ + * + * 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. + * + ************************************************************************/ + +#include "oox/ole/oleobjecthelper.hxx" +#include <com/sun/star/lang/XComponent.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/container/XNameAccess.hpp> +#include <com/sun/star/io/XOutputStream.hpp> +#include <com/sun/star/awt/Rectangle.hpp> +#include <com/sun/star/awt/Size.hpp> +#include <com/sun/star/document/XEmbeddedObjectResolver.hpp> +#include <com/sun/star/embed/Aspects.hpp> +#include "properties.hxx" +#include "oox/helper/propertymap.hxx" + +using ::rtl::OUString; +using ::com::sun::star::uno::Exception; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::UNO_QUERY; +using ::com::sun::star::uno::UNO_QUERY_THROW; +using ::com::sun::star::container::XNameAccess; +using ::com::sun::star::lang::XComponent; +using ::com::sun::star::lang::XMultiServiceFactory; +using ::com::sun::star::io::XOutputStream; +using ::com::sun::star::awt::Rectangle; +using ::com::sun::star::awt::Size; + +namespace oox { +namespace ole { + +// ============================================================================ + +OleObjectInfo::OleObjectInfo() : + mbLinked( false ), + mbShowAsIcon( false ), + mbAutoUpdate( false ) +{ +} + +// ============================================================================ + +OleObjectHelper::OleObjectHelper( const Reference< XMultiServiceFactory >& rxFactory ) : + maEmbeddedObjScheme( CREATE_OUSTRING( "vnd.sun.star.EmbeddedObject:" ) ), + mnObjectId( 100 ) +{ + if( rxFactory.is() ) + mxResolver.set( rxFactory->createInstance( CREATE_OUSTRING( "com.sun.star.document.ImportEmbeddedObjectResolver" ) ), UNO_QUERY ); +} + +OleObjectHelper::~OleObjectHelper() +{ + try + { + Reference< XComponent > xResolverComp( mxResolver, UNO_QUERY_THROW ); + xResolverComp->dispose(); + } + catch( Exception& ) + { + } +} + +bool OleObjectHelper::importOleObject( PropertyMap& rPropMap, const OleObjectInfo& rOleObject, const Size& rObjSize ) +{ + bool bRet = false; + + if( rOleObject.mbLinked ) + { + // linked OLE object - set target URL + if( rOleObject.maTargetLink.getLength() > 0 ) + { + rPropMap[ PROP_LinkURL ] <<= rOleObject.maTargetLink; + bRet = true; + } + } + else + { + // embedded OLE object - import the embedded data + if( rOleObject.maEmbeddedData.hasElements() && mxResolver.is() ) try + { + OUString aObjectId = CREATE_OUSTRING( "Obj" ) + OUString::valueOf( mnObjectId++ ); + + Reference< XNameAccess > xResolverNA( mxResolver, UNO_QUERY_THROW ); + Reference< XOutputStream > xOutStrm( xResolverNA->getByName( aObjectId ), UNO_QUERY_THROW ); + xOutStrm->writeBytes( rOleObject.maEmbeddedData ); + xOutStrm->closeOutput(); + + OUString aUrl = mxResolver->resolveEmbeddedObjectURL( aObjectId ); + OSL_ENSURE( aUrl.match( maEmbeddedObjScheme ), "OleObjectHelper::importOleObject - unexpected URL scheme" ); + OUString aPersistName = aUrl.copy( maEmbeddedObjScheme.getLength() ); + if( aPersistName.getLength() > 0 ) + { + rPropMap[ PROP_PersistName ] <<= aPersistName; + bRet = true; + } + } + catch( Exception& ) + { + } + } + + if( bRet ) + { + // aspect mode + using namespace ::com::sun::star::embed::Aspects; + sal_Int64 nAspect = rOleObject.mbShowAsIcon ? MSOLE_ICON : MSOLE_CONTENT; + rPropMap[ PROP_Aspect ] <<= nAspect; + // visual area + rPropMap[ PROP_VisualArea ] <<= Rectangle( 0, 0, rObjSize.Width, rObjSize.Height ); + } + return bRet; +} + +// ============================================================================ + +} // namespace ole +} // namespace oox + diff --git a/oox/source/ppt/animvariantcontext.cxx b/oox/source/ppt/animvariantcontext.cxx index e5f7f387b3cb..e8f60d9df234 100644 --- a/oox/source/ppt/animvariantcontext.cxx +++ b/oox/source/ppt/animvariantcontext.cxx @@ -89,7 +89,7 @@ namespace oox { namespace ppt { break; } case NMSP_PPT|XML_clrVal: - xRet.set( new ::oox::drawingml::colorChoiceContext( *this, maColor ) ); + xRet.set( new ::oox::drawingml::ColorContext( *this, maColor ) ); // we'll defer setting the Any until the end. break; case NMSP_PPT|XML_fltVal: diff --git a/oox/source/ppt/backgroundproperties.cxx b/oox/source/ppt/backgroundproperties.cxx index c17870f14edd..14ca161c8337 100644 --- a/oox/source/ppt/backgroundproperties.cxx +++ b/oox/source/ppt/backgroundproperties.cxx @@ -60,7 +60,7 @@ Reference< XFastContextHandler > BackgroundPropertiesContext::createFastChildCon // FillPropertiesGroupContext if( !xRet.is() ) - xRet = ::oox::drawingml::FillPropertiesGroupContext::StaticCreateContext( *this, aElementToken, xAttribs, mrFillProperties ); + xRet = ::oox::drawingml::FillPropertiesContext::createFillContext( *this, aElementToken, xAttribs, mrFillProperties ); return xRet; } diff --git a/oox/source/ppt/commontimenodecontext.cxx b/oox/source/ppt/commontimenodecontext.cxx index 291727a5e1aa..b24cb1a6ba54 100644 --- a/oox/source/ppt/commontimenodecontext.cxx +++ b/oox/source/ppt/commontimenodecontext.cxx @@ -458,12 +458,12 @@ static OUString getConvertedSubType( sal_Int16 nPresetClass, sal_Int32 nPresetId } if( attribs.hasAttribute( XML_grpId ) ) { - attribs.getUnsignedInteger( XML_grpId, 0 ); + attribs.getUnsigned( XML_grpId, 0 ); } // ST_TLTimeNodeID if( attribs.hasAttribute( XML_id ) ) { - sal_uInt32 nId = attribs.getUnsignedInteger( XML_id, 0 ); + sal_uInt32 nId = attribs.getUnsigned( XML_id, 0 ); pNode->setId( nId ); } // ST_TLTimeNodeMasterRelation @@ -687,7 +687,7 @@ static OUString getConvertedSubType( sal_Int16 nPresetClass, sal_Int32 nPresetId if( mbIterate ) { AttributeList attribs( xAttribs ); - double fTime = attribs.getUnsignedInteger( XML_val, 0 ); + double fTime = attribs.getUnsigned( XML_val, 0 ); // time in ms. property is in % TODO mpNode->getNodeProperties()[ NP_ITERATEINTERVAL ] <<= fTime; } @@ -696,7 +696,7 @@ static OUString getConvertedSubType( sal_Int16 nPresetClass, sal_Int32 nPresetId if( mbIterate ) { AttributeList attribs( xAttribs ); - double fPercent = (double)attribs.getUnsignedInteger( XML_val, 0 ) / 100000.0; + double fPercent = (double)attribs.getUnsigned( XML_val, 0 ) / 100000.0; mpNode->getNodeProperties()[ NP_ITERATEINTERVAL ] <<= fPercent; } break; diff --git a/oox/source/ppt/conditioncontext.cxx b/oox/source/ppt/conditioncontext.cxx index 29f7e5ae1550..8c49785486e5 100644 --- a/oox/source/ppt/conditioncontext.cxx +++ b/oox/source/ppt/conditioncontext.cxx @@ -154,7 +154,7 @@ namespace oox { namespace ppt { { maCond.mnType = aElementToken; AttributeList attribs( xAttribs ); - sal_uInt32 nId = attribs.getUnsignedInteger( XML_val, 0 ); + sal_uInt32 nId = attribs.getUnsigned( XML_val, 0 ); maCond.maValue = makeAny( nId ); break; } diff --git a/oox/source/drawingml/stylematrixreferencecontext.cxx b/oox/source/ppt/headerfootercontext.cxx index 22557bd03d67..9214e2d3b4ba 100644 --- a/oox/source/drawingml/stylematrixreferencecontext.cxx +++ b/oox/source/ppt/headerfootercontext.cxx @@ -6,9 +6,8 @@ * * OpenOffice.org - a multi-platform office productivity suite * - * $RCSfile: stylematrixreferencecontext.cxx,v $ - * - * $Revision: 1.3 $ + * $RCSfile:$ + * $Revision:$ * * This file is part of OpenOffice.org. * @@ -29,27 +28,42 @@ * ************************************************************************/ -#include "oox/drawingml/stylematrixreferencecontext.hxx" -#include "oox/drawingml/colorchoicecontext.hxx" +#include "headerfootercontext.hxx" #include "oox/core/namespaces.hxx" +#include "oox/helper/attributelist.hxx" #include "tokens.hxx" -using ::rtl::OUString; using namespace ::oox::core; using namespace ::com::sun::star::uno; using namespace ::com::sun::star::xml::sax; -namespace oox { namespace drawingml { +namespace oox { namespace ppt { -StyleMatrixReferenceContext::StyleMatrixReferenceContext( ContextHandler& rParent, Color& rColor ) -: ContextHandler( rParent ) -, mrColor( rColor ) -{ -} + HeaderFooterContext::HeaderFooterContext( ContextHandler& rParent, + const Reference< XFastAttributeList >& xAttribs, HeaderFooter& rHeaderFooter ) + : ContextHandler( rParent ) + { + AttributeList aAttribs( xAttribs ); + if ( xAttribs->hasAttribute( XML_sldNum ) ) + { + rHeaderFooter.mbSlideNumber = aAttribs.getBool( XML_sldNum, sal_True ); + } + if ( xAttribs->hasAttribute( XML_hdr ) ) + { + rHeaderFooter.mbHeader = aAttribs.getBool( XML_hdr, sal_True ); + } + if ( xAttribs->hasAttribute( XML_ftr ) ) + { + rHeaderFooter.mbFooter = aAttribs.getBool( XML_ftr, sal_True ); + } + if ( xAttribs->hasAttribute( XML_dt ) ) + { + rHeaderFooter.mbDateTime = aAttribs.getBool( XML_dt, sal_True ); + } + } -Reference< XFastContextHandler > StyleMatrixReferenceContext::createFastChildContext( sal_Int32 /* aElementToken */, const Reference< XFastAttributeList >& /* rxAttributes */ ) throw (SAXException, RuntimeException) -{ - return new colorChoiceContext( *this, mrColor ); -} + HeaderFooterContext::~HeaderFooterContext( ) + { + } } } diff --git a/oox/source/core/skipcontext.cxx b/oox/source/ppt/headerfootercontext.hxx index c20ba15b7c8a..3bf07315c62e 100644 --- a/oox/source/core/skipcontext.cxx +++ b/oox/source/ppt/headerfootercontext.hxx @@ -6,8 +6,8 @@ * * OpenOffice.org - a multi-platform office productivity suite * - * $RCSfile: skipcontext.cxx,v $ - * $Revision: 1.4 $ + * $RCSfile:$ + * $Revision:$ * * This file is part of OpenOffice.org. * @@ -28,17 +28,26 @@ * ************************************************************************/ -#include "oox/core/skipcontext.hxx" -namespace oox { -namespace core { -SkipContext::SkipContext( ContextHandler& rParent ) - : ContextHandler( rParent ) -{ - OSL_TRACE( "OOX: Skipping Context" ); -} +#ifndef OOX_PPT_HEADERFOOTERCONTEXT +#define OOX_PPT_HEADERFOOTERCONTEXT -} // namespace core -} // namespace oox +#include "oox/ppt/headerfooter.hxx" +#include "oox/core/contexthandler.hxx" +namespace oox { namespace ppt { + + /** CT_HeaderFooter */ + class HeaderFooterContext : public ::oox::core::ContextHandler + { + public: + HeaderFooterContext( ::oox::core::ContextHandler& rParent, + const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastAttributeList >& xAttribs, HeaderFooter& rHeaderFooter ); + + ~HeaderFooterContext( ); + }; + +} } + +#endif diff --git a/oox/source/ppt/layoutfragmenthandler.cxx b/oox/source/ppt/layoutfragmenthandler.cxx index 06db75f82724..98ff039a9099 100644 --- a/oox/source/ppt/layoutfragmenthandler.cxx +++ b/oox/source/ppt/layoutfragmenthandler.cxx @@ -34,6 +34,7 @@ #include <com/sun/star/beans/XMultiPropertySet.hpp> #include <com/sun/star/container/XNamed.hpp> +#include "headerfootercontext.hxx" #include "oox/ppt/layoutfragmenthandler.hxx" #include "oox/drawingml/shapegroupcontext.hxx" #include "oox/core/namespaces.hxx" @@ -72,6 +73,9 @@ Reference< XFastContextHandler > LayoutFragmentHandler::createFastChildContext( case NMSP_PPT|XML_sldLayout: // CT_SlideLayout mpSlidePersistPtr->setLayoutValueToken( xAttribs->getOptionalValueToken( XML_type, 0 ) ); // CT_SlideLayoutType break; + case NMSP_PPT|XML_hf: // CT_HeaderFooter + xRet.set( new HeaderFooterContext( *this, xAttribs, mpSlidePersistPtr->getHeaderFooter() ) ); + break; default: xRet.set( SlideFragmentHandler::createFastChildContext( aElementToken, xAttribs ) ); } diff --git a/oox/source/ppt/makefile.mk b/oox/source/ppt/makefile.mk index df1826b9add2..fd2946d54826 100644 --- a/oox/source/ppt/makefile.mk +++ b/oox/source/ppt/makefile.mk @@ -54,6 +54,7 @@ SLOFILES = \ $(SLO)$/commontimenodecontext.obj \ $(SLO)$/conditioncontext.obj \ $(SLO)$/customshowlistcontext.obj \ + $(SLO)$/headerfootercontext.obj \ $(SLO)$/layoutfragmenthandler.obj\ $(SLO)$/pptfilterhelpers.obj\ $(SLO)$/pptimport.obj\ diff --git a/oox/source/ppt/pptimport.cxx b/oox/source/ppt/pptimport.cxx index 27074a436b49..f772a9236785 100644 --- a/oox/source/ppt/pptimport.cxx +++ b/oox/source/ppt/pptimport.cxx @@ -75,9 +75,9 @@ bool PowerPointImport::importDocument() throw() file:///<path-to-oox-module>/source/dump/pptxdumper.ini. */ OOX_DUMP_FILE( ::oox::dump::pptx::Dumper ); - OUString aFragmentPath = getFragmentPathFromType( CREATE_OFFICEDOC_RELATIONSTYPE( "officeDocument" ) ); + OUString aFragmentPath = getFragmentPathFromFirstType( CREATE_OFFICEDOC_RELATIONSTYPE( "officeDocument" ) ); FragmentHandlerRef xPresentationFragmentHandler( new PresentationFragmentHandler( *this, aFragmentPath ) ); - maTableStyleListPath = xPresentationFragmentHandler->getFragmentPathFromType( CREATE_OFFICEDOC_RELATIONSTYPE( "tableStyles" ) ); + maTableStyleListPath = xPresentationFragmentHandler->getFragmentPathFromFirstType( CREATE_OFFICEDOC_RELATIONSTYPE( "tableStyles" ) ); return importFragment( xPresentationFragmentHandler ); @@ -132,12 +132,9 @@ sal_Int32 PowerPointImport::getSchemeClr( sal_Int32 nColorSchemeToken ) const return nColor; } -const oox::vml::DrawingPtr PowerPointImport::getDrawings() +::oox::vml::Drawing* PowerPointImport::getVmlDrawing() { - oox::vml::DrawingPtr xRet; - if ( mpActualSlidePersist ) - xRet = mpActualSlidePersist->getDrawing(); - return xRet; + return mpActualSlidePersist ? mpActualSlidePersist->getDrawing() : 0; } const oox::drawingml::table::TableStyleListPtr PowerPointImport::getTableStyles() diff --git a/oox/source/ppt/pptshape.cxx b/oox/source/ppt/pptshape.cxx index e4b144e6e55d..a5a17468a5af 100644 --- a/oox/source/ppt/pptshape.cxx +++ b/oox/source/ppt/pptshape.cxx @@ -82,6 +82,7 @@ void PPTShape::addShape( { oox::drawingml::TextListStylePtr aMasterTextListStyle; Reference< lang::XMultiServiceFactory > xServiceFact( rFilterBase.getModel(), UNO_QUERY_THROW ); + sal_Bool bClearText = sal_False; if ( sServiceName != OUString::createFromAscii( "com.sun.star.drawing.GraphicObjectShape" ) ) { @@ -122,24 +123,28 @@ void PPTShape::addShape( { const rtl::OUString sDateTimeShapeService( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.presentation.DateTimeShape" ) ); sServiceName = sDateTimeShapeService; + bClearText = sal_True; } break; case XML_hdr : { const rtl::OUString sHeaderShapeService( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.presentation.HeaderShape" ) ); sServiceName = sHeaderShapeService; + bClearText = sal_True; } break; case XML_ftr : { const rtl::OUString sFooterShapeService( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.presentation.FooterShape" ) ); sServiceName = sFooterShapeService; + bClearText = sal_True; } break; case XML_sldNum : { const rtl::OUString sSlideNumberShapeService( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.presentation.SlideNumberShape" ) ); sServiceName = sSlideNumberShapeService; + bClearText = sal_True; } break; case XML_sldImg : @@ -157,8 +162,24 @@ void PPTShape::addShape( aMasterTextListStyle = rSlidePersist.getMasterPersist().get() ? rSlidePersist.getMasterPersist()->getOtherTextStyle() : rSlidePersist.getOtherTextStyle(); setMasterTextListStyle( aMasterTextListStyle ); - Reference< XShape > xShape( createAndInsert( rFilterBase, sServiceName, pTheme, rxShapes, pShapeRect ) ); - + Reference< XShape > xShape( createAndInsert( rFilterBase, sServiceName, pTheme, rxShapes, pShapeRect, bClearText ) ); + if ( !rSlidePersist.isMasterPage() && rSlidePersist.getPage().is() && ( (sal_Int32)mnSubType == XML_title ) ) + { + try + { + rtl::OUString aTitleText; + Reference< XTextRange > xText( xShape, UNO_QUERY_THROW ); + aTitleText = xText->getString(); + if ( aTitleText.getLength() && ( aTitleText.getLength() < 64 ) ) // just a magic value, but we don't want to set slide names which are too long + { + Reference< container::XNamed > xName( rSlidePersist.getPage(), UNO_QUERY_THROW ); + xName->setName( aTitleText ); + } + } + catch( uno::Exception& ) + { + } + } if( pShapeMap && msId.getLength() ) { (*pShapeMap)[ msId ] = shared_from_this(); diff --git a/oox/source/ppt/pptshapecontext.cxx b/oox/source/ppt/pptshapecontext.cxx index 2a94ff0dbb63..0b481f8c91cf 100644 --- a/oox/source/ppt/pptshapecontext.cxx +++ b/oox/source/ppt/pptshapecontext.cxx @@ -46,6 +46,7 @@ #include "oox/drawingml/customshapegeometry.hxx" #include "oox/drawingml/textbodycontext.hxx" #include "tokens.hxx" +#include "properties.hxx" using rtl::OUString; using namespace oox::core; @@ -189,6 +190,7 @@ Reference< XFastContextHandler > PPTShapeContext::createFastChildContext( sal_In case NMSP_PPT|XML_txBody: { oox::drawingml::TextBodyPtr xTextBody( new oox::drawingml::TextBody ); + xTextBody->getTextProperties().maPropertyMap[ PROP_FontIndependentLineSpacing ] <<= static_cast< sal_Bool >( sal_True ); mpShapePtr->setTextBody( xTextBody ); xRet = new oox::drawingml::TextBodyContext( *this, *xTextBody ); break; diff --git a/oox/source/ppt/presentationfragmenthandler.cxx b/oox/source/ppt/presentationfragmenthandler.cxx index 09b089075173..2cd4fb4d2e5b 100644 --- a/oox/source/ppt/presentationfragmenthandler.cxx +++ b/oox/source/ppt/presentationfragmenthandler.cxx @@ -68,6 +68,14 @@ PresentationFragmentHandler::PresentationFragmentHandler( XmlFilterBase& rFilter : FragmentHandler( rFilter, rFragmentPath ) , mpTextListStyle( new TextListStyle ) { + TextParagraphPropertiesVector& rParagraphDefaulsVector( mpTextListStyle->getListStyle() ); + TextParagraphPropertiesVector::iterator aParagraphDefaultIter( rParagraphDefaulsVector.begin() ); + while( aParagraphDefaultIter != rParagraphDefaulsVector.end() ) + { + // ppt is having zero bottom margin per default, whereas OOo is 0,5cm, + // so this attribute needs to be set always + (*aParagraphDefaultIter++)->getParaBottomMargin() = TextSpacing( 0 ); + } } PresentationFragmentHandler::~PresentationFragmentHandler() throw() @@ -78,6 +86,66 @@ void PresentationFragmentHandler::startDocument() throw (SAXException, RuntimeEx { } +void ResolveTextFields( XmlFilterBase& rFilter ) +{ + const oox::core::TextFieldStack& rTextFields = rFilter.getTextFieldStack(); + if ( rTextFields.size() ) + { + Reference< frame::XModel > xModel( rFilter.getModel() ); + oox::core::TextFieldStack::const_iterator aIter( rTextFields.begin() ); + while( aIter != rTextFields.end() ) + { + const OUString sURL = CREATE_OUSTRING( "URL" ); + Reference< drawing::XDrawPagesSupplier > xDPS( xModel, uno::UNO_QUERY_THROW ); + Reference< drawing::XDrawPages > xDrawPages( xDPS->getDrawPages(), uno::UNO_QUERY_THROW ); + + const oox::core::TextField& rTextField( *aIter++ ); + Reference< XPropertySet > xPropSet( rTextField.xTextField, UNO_QUERY ); + Reference< XPropertySetInfo > xPropSetInfo( xPropSet->getPropertySetInfo() ); + if ( xPropSetInfo->hasPropertyByName( sURL ) ) + { + rtl::OUString aURL; + if ( xPropSet->getPropertyValue( sURL ) >>= aURL ) + { + const OUString sSlide = CREATE_OUSTRING( "#Slide " ); + const OUString sNotes = CREATE_OUSTRING( "#Notes " ); + sal_Bool bNotes = sal_False; + sal_Int32 nPageNumber = 0; + if ( aURL.match( sSlide ) ) + nPageNumber = aURL.copy( sSlide.getLength() ).toInt32(); + else if ( aURL.match( sNotes ) ) + { + nPageNumber = aURL.copy( sNotes.getLength() ).toInt32(); + bNotes = sal_True; + } + if ( nPageNumber ) + { + try + { + Reference< XDrawPage > xDrawPage; + xDrawPages->getByIndex( nPageNumber - 1 ) >>= xDrawPage; + if ( bNotes ) + { + Reference< ::com::sun::star::presentation::XPresentationPage > xPresentationPage( xDrawPage, UNO_QUERY_THROW ); + xDrawPage = xPresentationPage->getNotesPage(); + } + Reference< container::XNamed > xNamed( xDrawPage, UNO_QUERY_THROW ); + aURL = CREATE_OUSTRING( "#" ).concat( xNamed->getName() ); + xPropSet->setPropertyValue( sURL, Any( aURL ) ); + Reference< text::XTextContent > xContent( rTextField.xTextField, UNO_QUERY); + Reference< text::XTextRange > xTextRange( rTextField.xTextCursor, UNO_QUERY ); + rTextField.xText->insertTextContent( xTextRange, xContent, sal_True ); + } + catch( uno::Exception& ) + { + } + } + } + } + } + } +} + void PresentationFragmentHandler::endDocument() throw (SAXException, RuntimeException) { // todo: localized progress bar text @@ -111,18 +179,18 @@ void PresentationFragmentHandler::endDocument() throw (SAXException, RuntimeExce if( aSlideFragmentPath.getLength() > 0 ) { SlidePersistPtr pMasterPersistPtr; - SlidePersistPtr pSlidePersistPtr( new SlidePersist( sal_False, sal_False, xSlide, + SlidePersistPtr pSlidePersistPtr( new SlidePersist( rFilter, sal_False, sal_False, xSlide, ShapePtr( new PPTShape( Slide, "com.sun.star.drawing.GroupShape" ) ), mpTextListStyle ) ); FragmentHandlerRef xSlideFragmentHandler( new SlideFragmentHandler( rFilter, aSlideFragmentPath, pSlidePersistPtr, Slide ) ); // importing the corresponding masterpage/layout - OUString aLayoutFragmentPath = xSlideFragmentHandler->getFragmentPathFromType( CREATE_OFFICEDOC_RELATIONSTYPE( "slideLayout" ) ); + OUString aLayoutFragmentPath = xSlideFragmentHandler->getFragmentPathFromFirstType( CREATE_OFFICEDOC_RELATIONSTYPE( "slideLayout" ) ); if ( aLayoutFragmentPath.getLength() > 0 ) { // importing layout RelationsRef xLayoutRelations = rFilter.importRelations( aLayoutFragmentPath ); - OUString aMasterFragmentPath = xLayoutRelations->getFragmentPathFromType( CREATE_OFFICEDOC_RELATIONSTYPE( "slideMaster" ) ); + OUString aMasterFragmentPath = xLayoutRelations->getFragmentPathFromFirstType( CREATE_OFFICEDOC_RELATIONSTYPE( "slideMaster" ) ); if( aMasterFragmentPath.getLength() ) { // check if the corresponding masterpage+layout has already been imported @@ -148,7 +216,7 @@ void PresentationFragmentHandler::endDocument() throw (SAXException, RuntimeExce else xMasterPage = xMasterPages->insertNewByIndex( xMasterPages->getCount() ); - pMasterPersistPtr = SlidePersistPtr( new SlidePersist( sal_True, sal_False, xMasterPage, + pMasterPersistPtr = SlidePersistPtr( new SlidePersist( rFilter, sal_True, sal_False, xMasterPage, ShapePtr( new PPTShape( Master, "com.sun.star.drawing.GroupShape" ) ), mpTextListStyle ) ); pMasterPersistPtr->setLayoutPath( aLayoutFragmentPath ); rFilter.getMasterPages().push_back( pMasterPersistPtr ); @@ -156,7 +224,7 @@ void PresentationFragmentHandler::endDocument() throw (SAXException, RuntimeExce FragmentHandlerRef xMasterFragmentHandler( new SlideFragmentHandler( rFilter, aMasterFragmentPath, pMasterPersistPtr, Master ) ); // set the correct theme - OUString aThemeFragmentPath = xMasterFragmentHandler->getFragmentPathFromType( CREATE_OFFICEDOC_RELATIONSTYPE( "theme" ) ); + OUString aThemeFragmentPath = xMasterFragmentHandler->getFragmentPathFromFirstType( CREATE_OFFICEDOC_RELATIONSTYPE( "theme" ) ); if( aThemeFragmentPath.getLength() > 0 ) { std::map< OUString, oox::drawingml::ThemePtr >& rThemes( rFilter.getThemes() ); @@ -194,7 +262,7 @@ void PresentationFragmentHandler::endDocument() throw (SAXException, RuntimeExce pSlidePersistPtr->createXShapes( rFilter ); // now importing the notes page - OUString aNotesFragmentPath = xSlideFragmentHandler->getFragmentPathFromType( CREATE_OFFICEDOC_RELATIONSTYPE( "notesSlide" ) ); + OUString aNotesFragmentPath = xSlideFragmentHandler->getFragmentPathFromFirstType( CREATE_OFFICEDOC_RELATIONSTYPE( "notesSlide" ) ); if( aNotesFragmentPath.getLength() > 0 ) { Reference< XPresentationPage > xPresentationPage( xSlide, UNO_QUERY ); @@ -203,7 +271,7 @@ void PresentationFragmentHandler::endDocument() throw (SAXException, RuntimeExce Reference< XDrawPage > xNotesPage( xPresentationPage->getNotesPage() ); if ( xNotesPage.is() ) { - SlidePersistPtr pNotesPersistPtr( new SlidePersist( sal_False, sal_True, xNotesPage, + SlidePersistPtr pNotesPersistPtr( new SlidePersist( rFilter, sal_False, sal_True, xNotesPage, ShapePtr( new PPTShape( Slide, "com.sun.star.drawing.GroupShape" ) ), mpTextListStyle ) ); FragmentHandlerRef xNotesFragmentHandler( new SlideFragmentHandler( getFilter(), aNotesFragmentPath, pNotesPersistPtr, Slide ) ); rFilter.getNotesPages().push_back( pNotesPersistPtr ); @@ -216,6 +284,7 @@ void PresentationFragmentHandler::endDocument() throw (SAXException, RuntimeExce } } } + ResolveTextFields( rFilter ); } catch( uno::Exception& ) { @@ -297,6 +366,26 @@ bool PresentationFragmentHandler::importSlide( const FragmentHandlerRef& rxSlide awt::Size& rPageSize( pSlidePersistPtr->isNotesPage() ? maNotesSize : maSlideSize ); xPropertySet->setPropertyValue( sWidth, Any( rPageSize.Width ) ); xPropertySet->setPropertyValue( sHeight, Any( rPageSize.Height ) ); + + oox::ppt::HeaderFooter aHeaderFooter( pSlidePersistPtr->getHeaderFooter() ); + if ( !pSlidePersistPtr->isMasterPage() ) + aHeaderFooter.mbSlideNumber = aHeaderFooter.mbHeader = aHeaderFooter.mbFooter = aHeaderFooter.mbDateTime = sal_False; + try + { + static const OUString sIsHeaderVisible = CREATE_OUSTRING( "IsHeaderVisible" ); + static const OUString sIsFooterVisible = CREATE_OUSTRING( "IsFooterVisible" ); + static const OUString sIsDateTimeVisible = CREATE_OUSTRING( "IsDateTimeVisible" ); + static const OUString sIsPageNumberVisible = CREATE_OUSTRING( "IsPageNumberVisible" ); + + if ( pSlidePersistPtr->isNotesPage() ) + xPropertySet->setPropertyValue( sIsHeaderVisible, Any( aHeaderFooter.mbHeader ) ); + xPropertySet->setPropertyValue( sIsFooterVisible, Any( aHeaderFooter.mbFooter ) ); + xPropertySet->setPropertyValue( sIsDateTimeVisible, Any( aHeaderFooter.mbDateTime ) ); + xPropertySet->setPropertyValue( sIsPageNumberVisible, Any( aHeaderFooter.mbSlideNumber ) ); + } + catch( uno::Exception& ) + { + } } pSlidePersistPtr->setPath( rxSlideFragmentHandler->getFragmentPath() ); return getFilter().importFragment( rxSlideFragmentHandler ); diff --git a/oox/source/ppt/slidefragmenthandler.cxx b/oox/source/ppt/slidefragmenthandler.cxx index f07a8a265a2d..4127eb32a218 100644 --- a/oox/source/ppt/slidefragmenthandler.cxx +++ b/oox/source/ppt/slidefragmenthandler.cxx @@ -38,6 +38,7 @@ #include "oox/helper/propertyset.hxx" #include "oox/core/namespaces.hxx" #include "oox/core/xmlfilterbase.hxx" +#include "headerfootercontext.hxx" #include "oox/ppt/backgroundproperties.hxx" #include "oox/ppt/slidefragmenthandler.hxx" #include "oox/ppt/slidetimingcontext.hxx" @@ -45,6 +46,8 @@ #include "oox/ppt/slidemastertextstylescontext.hxx" #include "oox/ppt/pptshapegroupcontext.hxx" #include "oox/ppt/pptshape.hxx" +#include "oox/vml/vmldrawing.hxx" +#include "oox/vml/vmldrawingfragment.hxx" #include "oox/drawingml/clrschemecontext.hxx" @@ -64,21 +67,22 @@ SlideFragmentHandler::SlideFragmentHandler( XmlFilterBase& rFilter, const OUStri , mpSlidePersistPtr( pPersistPtr ) , meShapeLocation( eShapeLocation ) { - OUString aVMLDrawingFragmentPath = getFragmentPathFromType( CREATE_OFFICEDOC_RELATIONSTYPE( "vmlDrawing" ) ); + OUString aVMLDrawingFragmentPath = getFragmentPathFromFirstType( CREATE_OFFICEDOC_RELATIONSTYPE( "vmlDrawing" ) ); if( aVMLDrawingFragmentPath.getLength() > 0 ) - { - getFilter().importFragment( new oox::vml::DrawingFragmentHandler( - getFilter(), aVMLDrawingFragmentPath, pPersistPtr->getDrawing()->getShapes(), pPersistPtr->getDrawing()->getShapeTypes() ) ); - } + getFilter().importFragment( new oox::vml::DrawingFragment( + getFilter(), aVMLDrawingFragmentPath, *pPersistPtr->getDrawing() ) ); } SlideFragmentHandler::~SlideFragmentHandler() throw() { + // convert and insert all VML shapes (mostly form controls) + mpSlidePersistPtr->getDrawing()->convertAndInsert(); } Reference< XFastContextHandler > SlideFragmentHandler::createFastChildContext( sal_Int32 aElementToken, const Reference< XFastAttributeList >& xAttribs ) throw (SAXException, RuntimeException) { Reference< XFastContextHandler > xRet; + AttributeList aAttribs( xAttribs ); switch( aElementToken ) { @@ -100,12 +104,28 @@ Reference< XFastContextHandler > SlideFragmentHandler::createFastChildContext( s } break; + case NMSP_PPT|XML_controls: + xRet = getFastContextHandler(); + break; + case NMSP_PPT|XML_control: + { + ::oox::vml::ControlInfo aInfo; + aInfo.setShapeId( aAttribs.getInteger( XML_spid, 0 ) ); + aInfo.maFragmentPath = getFragmentPathFromRelId( aAttribs.getString( R_TOKEN( id ), OUString() ) ); + aInfo.maName = aAttribs.getXString( XML_name, OUString() ); + mpSlidePersistPtr->getDrawing()->registerControl( aInfo ); + } + return xRet; + case NMSP_PPT|XML_timing: // CT_SlideTiming xRet.set( new SlideTimingContext( *this, mpSlidePersistPtr->getTimeNodeList() ) ); break; case NMSP_PPT|XML_transition: // CT_SlideTransition xRet.set( new SlideTransitionContext( *this, xAttribs, maSlideProperties ) ); break; + case NMSP_PPT|XML_hf: + xRet.set( new HeaderFooterContext( *this, xAttribs, mpSlidePersistPtr->getHeaderFooter() ) ); + break; // BackgroundGroup case NMSP_PPT|XML_bgPr: // CT_BackgroundProperties diff --git a/oox/source/ppt/slidepersist.cxx b/oox/source/ppt/slidepersist.cxx index 0f083c52a209..47e5f8c84c5e 100644 --- a/oox/source/ppt/slidepersist.cxx +++ b/oox/source/ppt/slidepersist.cxx @@ -33,6 +33,7 @@ #include "oox/ppt/pptshape.hxx" #include "oox/ppt/slidepersist.hxx" #include "oox/drawingml/fillproperties.hxx" +#include "oox/vml/vmldrawing.hxx" #include "oox/core/namespaces.hxx" #include "oox/core/xmlfilterbase.hxx" #include "tokens.hxx" @@ -52,10 +53,10 @@ using namespace ::com::sun::star::animations; namespace oox { namespace ppt { -SlidePersist::SlidePersist( sal_Bool bMaster, sal_Bool bNotes, +SlidePersist::SlidePersist( XmlFilterBase& rFilter, sal_Bool bMaster, sal_Bool bNotes, const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XDrawPage >& rxPage, oox::drawingml::ShapePtr pShapesPtr, const drawingml::TextListStylePtr & pDefaultTextStyle ) -: mpDrawingPtr( new oox::vml::Drawing ) +: mpDrawingPtr( new oox::vml::Drawing( rFilter, rxPage, oox::vml::VMLDRAWING_POWERPOINT ) ) , mxPage( rxPage ) , maShapesPtr( pShapesPtr ) , mnLayoutValueToken( 0 ) @@ -181,7 +182,7 @@ void SlidePersist::createBackground( const XmlFilterBase& rFilterBase ) PropertySet aPropSet( xPropertySet ); mpBackgroundPropertiesPtr->pushToPropSet( aPropSet, ::oox::drawingml::FillProperties::DEFAULT_IDS, - rFilterBase, rFilterBase.getModelObjectContainer(), 0, -1 ); + rFilterBase, rFilterBase.getModelObjectHelper(), 0, -1 ); xPagePropSet->setPropertyValue( sBackground, Any( xPropertySet ) ); } catch( Exception ) diff --git a/oox/source/ppt/slidetimingcontext.cxx b/oox/source/ppt/slidetimingcontext.cxx index 96e6069373e7..7fc20d0066e2 100644 --- a/oox/source/ppt/slidetimingcontext.cxx +++ b/oox/source/ppt/slidetimingcontext.cxx @@ -38,7 +38,6 @@ #include "oox/drawingml/shapegroupcontext.hxx" #include "oox/helper/attributelist.hxx" #include "oox/core/namespaces.hxx" -#include "oox/core/skipcontext.hxx" #include "oox/ppt/timenodelistcontext.hxx" #include "buildlistcontext.hxx" #include "tokens.hxx" @@ -80,8 +79,7 @@ Reference< XFastContextHandler > SlideTimingContext::createFastChildContext( sal xRet.set( new BuildListContext( *this, xAttribs, maTimeNodeList ) ); break; case NMSP_PPT|XML_extLst: - xRet.set( new SkipContext( *this ) ); - break; + return xRet; case NMSP_PPT|XML_tnLst: // timing nodes { diff --git a/oox/source/ppt/slidetransitioncontext.cxx b/oox/source/ppt/slidetransitioncontext.cxx index 80b5cdd6b706..3d22ad670af2 100644 --- a/oox/source/ppt/slidetransitioncontext.cxx +++ b/oox/source/ppt/slidetransitioncontext.cxx @@ -42,7 +42,6 @@ #include "oox/drawingml/shapegroupcontext.hxx" #include "oox/helper/attributelist.hxx" #include "oox/core/namespaces.hxx" -#include "oox/core/skipcontext.hxx" #include "tokens.hxx" @@ -154,7 +153,7 @@ Reference< XFastContextHandler > SlideTransitionContext::createFastChildContext( { mbHasTransition = true; AttributeList attribs(xAttribs); - maTransition.setOoxTransitionType( aElementToken, attribs.getUnsignedInteger( XML_spokes, 4 ), 0 ); + maTransition.setOoxTransitionType( aElementToken, attribs.getUnsigned( XML_spokes, 4 ), 0 ); // unsignedInt } break; @@ -179,8 +178,7 @@ Reference< XFastContextHandler > SlideTransitionContext::createFastChildContext( xRet.set( new SoundActionContext ( *this, maSlideProperties ) ); break; case NMSP_PPT|XML_extLst: // CT_OfficeArtExtensionList - xRet.set( new SkipContext( *this ) ); - break; + return xRet; default: break; } diff --git a/oox/source/ppt/soundactioncontext.cxx b/oox/source/ppt/soundactioncontext.cxx index 24a675b072d4..0df2ed896685 100644 --- a/oox/source/ppt/soundactioncontext.cxx +++ b/oox/source/ppt/soundactioncontext.cxx @@ -115,7 +115,7 @@ namespace oox { namespace ppt { drawingml::EmbeddedWAVAudioFile aAudio; drawingml::getEmbeddedWAVAudioFile( getRelations(), xAttribs, aAudio); - msSndName = ( aAudio.mbBuiltIn ? aAudio.msName : aAudio.msLink ); + msSndName = ( aAudio.mbBuiltIn ? aAudio.msName : aAudio.msEmbed ); } break; case NMSP_PPT|XML_endSnd: diff --git a/oox/source/ppt/timenodelistcontext.cxx b/oox/source/ppt/timenodelistcontext.cxx index 7199afac01f4..70da57a52bd4 100644 --- a/oox/source/ppt/timenodelistcontext.cxx +++ b/oox/source/ppt/timenodelistcontext.cxx @@ -565,11 +565,11 @@ namespace oox { namespace ppt { break; case NMSP_PPT|XML_to: // CT_Color - xRet.set( new colorChoiceContext( *this, maToClr ) ); + xRet.set( new ColorContext( *this, maToClr ) ); break; case NMSP_PPT|XML_from: // CT_Color - xRet.set( new colorChoiceContext( *this, maFromClr ) ); + xRet.set( new ColorContext( *this, maFromClr ) ); break; default: diff --git a/oox/source/ppt/timetargetelementcontext.cxx b/oox/source/ppt/timetargetelementcontext.cxx index a3e41657af85..59a544df951e 100644 --- a/oox/source/ppt/timetargetelementcontext.cxx +++ b/oox/source/ppt/timetargetelementcontext.cxx @@ -152,7 +152,7 @@ namespace oox { namespace ppt { drawingml::EmbeddedWAVAudioFile aAudio; drawingml::getEmbeddedWAVAudioFile( getRelations(), xAttribs, aAudio); - OUString sSndName = ( aAudio.mbBuiltIn ? aAudio.msName : aAudio.msLink ); + OUString sSndName = ( aAudio.mbBuiltIn ? aAudio.msName : aAudio.msEmbed ); mpTarget->msValue = sSndName; break; } diff --git a/oox/source/shape/ShapeContextHandler.cxx b/oox/source/shape/ShapeContextHandler.cxx index 6d1da1e74da3..80caad025630 100644 --- a/oox/source/shape/ShapeContextHandler.cxx +++ b/oox/source/shape/ShapeContextHandler.cxx @@ -29,7 +29,9 @@ ************************************************************************/ #include "ShapeContextHandler.hxx" -#include "oox/vml/drawingfragmenthandler.hxx" +#include "oox/vml/vmldrawingfragment.hxx" +#include "oox/vml/vmlshape.hxx" +#include "oox/vml/vmlshapecontainer.hxx" namespace oox { namespace shape { @@ -90,11 +92,11 @@ ShapeContextHandler::getDrawingShapeContext() { if (!mxDrawingFragmentHandler.is()) { - mpDrawing.reset( new oox::vml::Drawing() ); + mpDrawing.reset( new oox::vml::Drawing( *mxFilterBase, mxDrawPage, oox::vml::VMLDRAWING_WORD ) ); mxDrawingFragmentHandler.set - (dynamic_cast<ContextHandler *> - (new oox::vml::DrawingFragmentHandler - ( *mxFilterBase, msRelationFragmentPath, mpDrawing->getShapes(), mpDrawing->getShapeTypes() ))); + (dynamic_cast<ContextHandler *> + (new oox::vml::DrawingFragment + ( *mxFilterBase, msRelationFragmentPath, *mpDrawing ))); } return mxDrawingFragmentHandler; @@ -217,21 +219,19 @@ uno::Reference< drawing::XShape > SAL_CALL ShapeContextHandler::getShape() throw (uno::RuntimeException) { uno::Reference< drawing::XShape > xResult; + uno::Reference< drawing::XShapes > xShapes( mxDrawPage, uno::UNO_QUERY ); - if (mxFilterBase.is() && mxShapes.is()) + if (mxFilterBase.is() && xShapes.is()) { if (mpDrawing.get() != NULL) { - std::vector< oox::vml::ShapePtr >& rShapes = mpDrawing->getShapes(); - if ( rShapes.size() ) - { - rShapes[ 0 ]->addShape( *mxFilterBase, *mpDrawing, mxShapes, NULL ); - xResult.set(rShapes[ 0 ]->getXShape()); - } + mpDrawing->finalizeFragmentImport(); + if( const ::oox::vml::ShapeBase* pShape = mpDrawing->getShapes().getFirstShape() ) + xResult = pShape->convertAndInsert( xShapes ); } else if (mpShape.get() != NULL) { - mpShape->addShape(*mxFilterBase, mpThemePtr.get(), mxShapes); + mpShape->addShape(*mxFilterBase, mpThemePtr.get(), xShapes); xResult.set(mpShape->getXShape()); } } @@ -239,17 +239,17 @@ ShapeContextHandler::getShape() throw (uno::RuntimeException) return xResult; } -css::uno::Reference< css::drawing::XShapes > SAL_CALL -ShapeContextHandler::getShapes() throw (css::uno::RuntimeException) +css::uno::Reference< css::drawing::XDrawPage > SAL_CALL +ShapeContextHandler::getDrawPage() throw (css::uno::RuntimeException) { - return mxShapes; + return mxDrawPage; } -void SAL_CALL ShapeContextHandler::setShapes -(const css::uno::Reference< css::drawing::XShapes > & the_value) +void SAL_CALL ShapeContextHandler::setDrawPage +(const css::uno::Reference< css::drawing::XDrawPage > & the_value) throw (css::uno::RuntimeException) { - mxShapes = the_value; + mxDrawPage = the_value; } css::uno::Reference< css::frame::XModel > SAL_CALL diff --git a/oox/source/shape/ShapeContextHandler.hxx b/oox/source/shape/ShapeContextHandler.hxx index 171640838502..47b2cf1951de 100644 --- a/oox/source/shape/ShapeContextHandler.hxx +++ b/oox/source/shape/ShapeContextHandler.hxx @@ -40,7 +40,6 @@ #include "oox/drawingml/theme.hxx" #include "oox/core/fragmenthandler.hxx" #include "oox/core/xmlfilterbase.hxx" -#include "oox/vml/drawingfragmenthandler.hxx" #include "ShapeFilterBase.hxx" namespace css = ::com::sun::star; @@ -134,11 +133,11 @@ public: virtual css::uno::Reference< css::drawing::XShape > SAL_CALL getShape() throw (css::uno::RuntimeException); - virtual css::uno::Reference< css::drawing::XShapes > SAL_CALL getShapes() + virtual css::uno::Reference< css::drawing::XDrawPage > SAL_CALL getDrawPage() throw (css::uno::RuntimeException); - virtual void SAL_CALL setShapes - (const css::uno::Reference< css::drawing::XShapes > & the_value) + virtual void SAL_CALL setDrawPage + (const css::uno::Reference< css::drawing::XDrawPage > & the_value) throw (css::uno::RuntimeException); virtual css::uno::Reference< css::frame::XModel > SAL_CALL getModel() @@ -172,7 +171,7 @@ private: css::uno::Reference< css::uno::XComponentContext > m_xContext; drawingml::ShapePtr mpShape; - vml::DrawingPtr mpDrawing; + ::boost::shared_ptr< vml::Drawing > mpDrawing; typedef boost::shared_ptr<drawingml::GraphicShapeContext> GraphicShapeContextPtr; @@ -181,7 +180,7 @@ private: core::XmlFilterRef mxFilterBase; drawingml::ThemePtr mpThemePtr; - css::uno::Reference<css::drawing::XShapes> mxShapes; + css::uno::Reference<css::drawing::XDrawPage> mxDrawPage; css::uno::Reference<css::io::XInputStream> mxInputStream; ::rtl::OUString msRelationFragmentPath; diff --git a/oox/source/shape/ShapeFilterBase.cxx b/oox/source/shape/ShapeFilterBase.cxx index c43eaddf363d..0933af28ffd5 100644 --- a/oox/source/shape/ShapeFilterBase.cxx +++ b/oox/source/shape/ShapeFilterBase.cxx @@ -58,9 +58,9 @@ sal_Int32 ShapeFilterBase::getSchemeClr(sal_Int32 /*nColorSchemeToken*/ ) const return 0; } -const vml::DrawingPtr ShapeFilterBase::getDrawings() +::oox::vml::Drawing* ShapeFilterBase::getVmlDrawing() { - return vml::DrawingPtr(); + return 0; } const ::oox::drawingml::table::TableStyleListPtr ShapeFilterBase::getTableStyles() diff --git a/oox/source/shape/ShapeFilterBase.hxx b/oox/source/shape/ShapeFilterBase.hxx index 0657aea11c2e..d90904ed22cc 100644 --- a/oox/source/shape/ShapeFilterBase.hxx +++ b/oox/source/shape/ShapeFilterBase.hxx @@ -33,7 +33,7 @@ #include <boost/shared_ptr.hpp> #include <rtl/ref.hxx> -#include "oox/vml/drawing.hxx" +#include "oox/vml/vmldrawing.hxx" #include "oox/drawingml/table/tablestylelist.hxx" #include "oox/core/xmlfilterbase.hxx" @@ -58,8 +58,8 @@ public: /** Has to be implemented by each filter to resolve scheme colors. */ virtual sal_Int32 getSchemeClr( sal_Int32 nColorSchemeToken ) const; - /** Has to be implemented by each filter to return drawings collection. */ - virtual const ::oox::vml::DrawingPtr getDrawings(); + /** Has to be implemented by each filter to return the collection of VML shapes. */ + virtual ::oox::vml::Drawing* getVmlDrawing(); /** Has to be implemented by each filter to return TableStyles. */ virtual const ::oox::drawingml::table::TableStyleListPtr getTableStyles(); diff --git a/oox/source/token/makefile.mk b/oox/source/token/makefile.mk index c7846d5c4cf2..3cce788d2508 100644 --- a/oox/source/token/makefile.mk +++ b/oox/source/token/makefile.mk @@ -58,7 +58,7 @@ $(MISC)$/do_tokens $(do_phony) : tokens.txt gentoken.pl $(MISC)$/tokens.gperf $( $(PERL) gentoken.pl tokens.txt $(INCCOM)$/tokens.hxx $(INCCOM)$/tokenwords.inc $(MISC)$/tokens.gperf && $(TOUCH) $@ $(INCCOM)$/tokens.inc : $(MISC)$/tokens.gperf $(MISC)$/do_tokens - gperf --compare-strncmp $(MISC)$/tokens.gperf | $(SED) -e "s/(char\*)0/(char\*)0, 0/g" | $(GREP) -v "^#line" >$(INCCOM)$/tokens.inc + $(AUGMENT_LIBRARY_PATH) gperf --compare-strncmp $(MISC)$/tokens.gperf | $(SED) -e "s/(char\*)0/(char\*)0, 0/g" | $(GREP) -v "^#line" >$(INCCOM)$/tokens.inc $(SLO)$/tokenmap.obj : $(INCCOM)$/tokens.inc $(INCCOM)$/tokenwords.inc $(INCCOM)$/tokens.hxx $(MISC)$/do_tokens diff --git a/oox/source/token/properties.txt b/oox/source/token/properties.txt index 7d86333ef784..958a9ac24e77 100644 --- a/oox/source/token/properties.txt +++ b/oox/source/token/properties.txt @@ -1,14 +1,23 @@ AbsoluteName +Action ActiveSplitRange ActiveTable Adjust +AdjustContrast +AdjustLuminance +Align ArrangeOrder +Aspect AttachedAxisIndex AutoFilter AutoShowInfo +Autocomplete BackGraphicLocation BackGraphicURL +BackgroundColor BlackDay +BlockIncrement +Border BorderColor BorderDashName BorderStyle @@ -70,6 +79,9 @@ CompileEnglish ConditionalFormat ConnectBars ContainsHeader +CopyBack +CopyFormulas +CopyStyles CrossoverPosition CrossoverValue CursorPositionX @@ -85,10 +97,17 @@ D3DScenePerspective D3DSceneShadeMode DDELinks DatabaseRanges +DefaultScrollValue +DefaultSpinValue +DefaultState +DefaultText DiagonalBLTR DiagonalTLBR DisplayLabels DrillDownOnDoubleClick +Dropdown +EchoChar +Enabled EndPosition ErrorAlertStyle ErrorBarStyle @@ -99,17 +118,14 @@ ErrorTitle ExternalDocLinks ExternalLinks FileFormat -FillBitmap -FillBitmapLogicalSize FillBitmapMode FillBitmapName -FillBitmapOffsetX -FillBitmapOffsetY +FillBitmapPositionOffsetX +FillBitmapPositionOffsetY FillBitmapRectanglePoint FillBitmapSizeX FillBitmapSizeY -FillBitmapStretch -FillBitmapTile +FillBitmapURL FillColor FillGradient FillGradientName @@ -117,6 +133,15 @@ FillStyle FillTransparence FirstLineOffset FirstPageNumber +FocusOnClick +FontCharset +FontHeight +FontIndependentLineSpacing +FontName +FontSlant +FontStrikeout +FontUnderline +FontWeight FooterBodyDistance FooterHeight FooterIsDynamicHeight @@ -128,10 +153,12 @@ GapwidthSequence Geometry3D GradientName Graphic +GraphicColorMode GraphicSize GraphicURL GridColor GroupInfo +HScroll HasAutoShowInfo HasColumnRowHeaders HasHorizontalScrollBar @@ -146,15 +173,19 @@ HeaderIsDynamicHeight HeaderIsOn HeaderIsShared Height +HideInactiveSelection HoriJustify HorizontalSplitMode HorizontalSplitPositionTwips IgnoreBlankCells IgnoreCase IgnoreLeadingSpaces +ImagePosition +ImageURL IncludeHiddenCells InputMessage InputTitle +IsActive IsAdjustHeightEnabled IsCellBackgroundTransparent IsChangeReadOnlyEnabled @@ -185,11 +216,13 @@ LeftMargin LeftPageFooterContent LeftPageHeaderContent LineColor +LineCount LineDash LineDashName LineEndCenter LineEndName LineEndWidth +LineIncrement LineJoint LineStartCenter LineStartName @@ -197,13 +230,19 @@ LineStartWidth LineStyle LineTransparence LineWidth +LinkURL LookUpLabels MajorTickmarks MarkPosition MaxFieldCount +MaxTextLen +MediaType MinorTickmarks MissingValueTreatment Model +MultiLine +MultiSelection +Name NamedRanges NegativeError NullDate @@ -219,6 +258,7 @@ OverlapSequence PageScale PageStyle PageViewZoomValue +PaintTransparent ParaAdjust ParaBottomMargin ParaFirstLineIndent @@ -242,14 +282,19 @@ PositionTop PositiveError Prefix PrintAnnotations +PrintBorder PrintDownFirst PrintGrid PrintHeaders +Printable +Protected Reference ReferenceDevice -ReferencePosition RegularExpressions +RelId RelativeHorizontalTabbarWidth +Repeat +RepeatDelay Representation RightAngledAxes RightBorder @@ -263,11 +308,15 @@ RotationHorizontal RotationVertical RowGrand RowLabelRanges +ScaleMode ScaleToPages ScaleToPagesX ScaleToPagesY +ScrollValueMax +ScrollValueMin SelectedPage Show +ShowBorder ShowCharts ShowCorrelationCoefficient ShowDetail @@ -293,6 +342,9 @@ SortInfo Sound SoundOn Speed +SpinIncrement +SpinValueMax +SpinValueMin StackCharacters StackingDirection StartPosition @@ -302,6 +354,7 @@ Subtotals Suffix SwapXAndYAxis Symbol +SymbolColor TableBorder TableLayout TableSelected @@ -309,6 +362,7 @@ Tables TargetFrame TextAutoGrowHeight TextBreak +TextColor TextLeftDistance TextLowerDistance TextOverlap @@ -317,6 +371,7 @@ TextRotation TextUpperDistance TextWordWrap TextWritingMode +Toggle TokenIndex TopBorder TopMargin @@ -326,16 +381,22 @@ TransitionFadeColor TransitionSubtype TransitionType Transparency +TriState Type URL UseRegularExpressions UseRings UseSelectedPage +VScroll Validation VaryColorsByPoint VertJustify +VerticalAlign VerticalSplitMode VerticalSplitPositionTwips +VisibleSize +VisualArea +VisualEffect Weight WhiteDay Width diff --git a/oox/source/token/tokens.txt b/oox/source/token/tokens.txt index 96f14da3f37c..8c345fc23352 100644 --- a/oox/source/token/tokens.txt +++ b/oox/source/token/tokens.txt @@ -51,17 +51,21 @@ B4ISO B4JIS B5ISO B5JIS +BackColor Bitmap Book BookAuthor BookSection BookTitle +BorderColor +BorderStyle BroadcastTitle Broadcaster Button CF Camera Cancel +Caption Case CaseNumber ChapterNumber @@ -100,17 +104,20 @@ Day DayAccessed Default DefaultSize +Delay Department Dialog DigSig Director Disabled Dismiss +DisplayStyle Distributor DocSecurity DocumentFromInternetSite DrawAspect Drop +DropButtonStyle DropLines DropStyle Dx @@ -124,6 +131,7 @@ ElectronicSource Embed EnhancedMetaFile Extension +External False FieldCodes FileBinding @@ -137,10 +145,18 @@ FmlaMacro FmlaPict FmlaRange FmlaTxbx +FontCharSet +FontEffects +FontHeight +FontName +FontPitchAndFamily +FontWeight +ForeColor Format Formula GBox Group +GroupName Guid HLinks HTMLInset @@ -159,6 +175,7 @@ Icon Id Inc Institution +Internal InternetSite InternetSiteTitle Interview @@ -172,6 +189,7 @@ JustLastX LCID LCT Label +LargeChange Last LineA Lines @@ -180,6 +198,8 @@ LinkType LinksUpToDate List ListItem +ListRows +ListStyle LockText Locked LockedField @@ -202,17 +222,22 @@ Manager Map MapInfo MapOCX +MatchEntry Max +MaxLength Medium Middle Min Misc Month MonthAccessed +MouseIcon +MousePointer MoveWithCells Movie MultiLine MultiSel +MultiSelect NA NCName NMTOKEN @@ -221,6 +246,7 @@ NOTATION Name NameList Namespace +NextEnabled NoThreeD NoThreeD2 Note @@ -232,11 +258,14 @@ OLEUPDATE_ONCALL ObjectID ObjectType OnCall +Orientation Override Page Pages +ParagraphAlign Paragraphs PartName +PasswordChar Patent PatentNumber Performance @@ -248,14 +277,20 @@ PictOld PictPrint PictScreen Picture +PictureAlignment +PicturePosition +PictureTiling +Position PresentationFormat PreserveFormat PreserveSortAFLayout +PrevEnabled PrintObject ProducerName ProductionCompany ProgID Properties +ProportionalThumb PublicationTitle Publisher Q1 @@ -288,6 +323,7 @@ ScriptLanguage ScriptLocation ScriptText Scroll +ScrollBars SecretEdit Sel SelType @@ -297,21 +333,27 @@ Shape ShapeID SharedDoc ShortTitle +ShowDropButtonWhen ShowImportExportValidationErrors SignatureTime +Size +SizeMode SizeWithCells Slides +SmallChange SoundRecording Source SourceId SourceType Sources +SpecialEffect Spin StandardNumber StateProvince Station StyleName Tag +TakeFocusOnClick Target TargetMode Template @@ -335,6 +377,7 @@ VTEdit Val ValidIds Value +VariousPropertyBits Version Visible Volume @@ -1097,6 +1140,7 @@ citation class classic classicalWave +classid clean clear clearAll @@ -2911,6 +2955,7 @@ lgDash lgDashDot lgDashDotDot lgGrid +license lid light1 light2 @@ -3484,6 +3529,8 @@ oblob obscured oc octagon +ocx +ocxPr odbc odcFile oddFooter @@ -3726,6 +3773,11 @@ percentile period permEnd permStart +persistPropertyBag +persistStorage +persistStream +persistStreamInit +persistence personal personalCompose personalReply diff --git a/oox/source/vml/makefile.mk b/oox/source/vml/makefile.mk index 6d5c719ac0c3..305353eb8f02 100644 --- a/oox/source/vml/makefile.mk +++ b/oox/source/vml/makefile.mk @@ -1,7 +1,7 @@ #************************************************************************* # # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# +# # Copyright 2008 by Sun Microsystems, Inc. # # OpenOffice.org - a multi-platform office productivity suite @@ -45,9 +45,12 @@ ENABLE_EXCEPTIONS=TRUE # --- Files -------------------------------------------------------- SLOFILES = \ - $(SLO)$/vmlshape.obj\ - $(SLO)$/vmldrawing.obj\ - $(SLO)$/vmldrawingfragmenthandler.obj + $(SLO)$/vmldrawing.obj \ + $(SLO)$/vmldrawingfragment.obj \ + $(SLO)$/vmlinputstream.obj \ + $(SLO)$/vmlshape.obj \ + $(SLO)$/vmlshapecontainer.obj \ + $(SLO)$/vmlshapecontext.obj # --- Targets ------------------------------------------------------- diff --git a/oox/source/vml/vmldrawing.cxx b/oox/source/vml/vmldrawing.cxx index 9fc0c2efd88a..42529ea4a351 100644 --- a/oox/source/vml/vmldrawing.cxx +++ b/oox/source/vml/vmldrawing.cxx @@ -28,67 +28,141 @@ * ************************************************************************/ -#include "oox/vml/drawing.hxx" -#include "oox/core/namespaces.hxx" +#include "oox/vml/vmldrawing.hxx" +#include <com/sun/star/drawing/XShapes.hpp> #include "tokens.hxx" +#include "oox/core/xmlfilterbase.hxx" +#include "oox/ole/axcontrolhelper.hxx" +#include "oox/vml/vmlshape.hxx" +#include "oox/vml/vmlshapecontainer.hxx" -namespace oox { namespace vml { +using ::rtl::OUString; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::UNO_QUERY; +using ::com::sun::star::awt::Rectangle; +using ::com::sun::star::awt::XControlModel; +using ::com::sun::star::drawing::XDrawPage; +using ::com::sun::star::drawing::XShapes; +using ::oox::core::XmlFilterBase; -Drawing::Drawing() +namespace oox { +namespace vml { + +// ============================================================================ + +namespace { + +/** Returns the textual representation of a numeric VML shape identifier. */ +OUString lclGetShapeId( sal_Int32 nShapeId ) +{ + // identifier consists of a literal NUL character, a lowercase 's', and the id + return CREATE_OUSTRING( "\0s" ) + OUString::valueOf( nShapeId ); +} + +} // namespace + +// ============================================================================ + +OleObjectInfo::OleObjectInfo( bool bDmlShape ) : + mbAutoLoad( false ), + mbDmlShape( bDmlShape ) +{ +} + +void OleObjectInfo::setShapeId( sal_Int32 nShapeId ) { + maShapeId = lclGetShapeId( nShapeId ); } + +// ============================================================================ + +ControlInfo::ControlInfo() +{ +} + +void ControlInfo::setShapeId( sal_Int32 nShapeId ) +{ + maShapeId = lclGetShapeId( nShapeId ); +} + +// ============================================================================ + +Drawing::Drawing( XmlFilterBase& rFilter, const Reference< XDrawPage >& rxDrawPage, DrawingType eType ) : + mrFilter( rFilter ), + mxDrawPage( rxDrawPage ), + mxShapes( new ShapeContainer( *this ) ), + meType( eType ) +{ + OSL_ENSURE( mxDrawPage.is(), "Drawing::Drawing - missing UNO draw page" ); +} + Drawing::~Drawing() { } -ShapePtr Drawing::createShapeById( const rtl::OUString sId ) const +::oox::ole::AxControlHelper& Drawing::getControlHelper() const { - ShapePtr pRet, pRef; - std::vector< ShapePtr >::const_iterator aIter( maShapes.begin() ); - while( aIter != maShapes.end() ) - { - if ( (*aIter)->msId == sId ) - { - pRef = (*aIter); - break; - } - aIter++; - } - if ( pRef ) + // create the helper object on demand + if( !mxCtrlHelper.get() ) { - pRet = ShapePtr( new Shape( pRef->msServiceName ) ); - if ( pRef->msType.getLength() ) - { - std::vector< ShapePtr >::const_iterator aShapeTypeIter( maShapeTypes.begin() ); - while( aShapeTypeIter != maShapeTypes.end() ) - { - if ( (*aShapeTypeIter)->msType == pRef->msType ) - { - pRet->applyAttributes( *(*aShapeTypeIter).get() ); - break; - } - aShapeTypeIter++; - } - } - pRet->applyAttributes( *pRef.get() ); + mxCtrlHelper.reset( createControlHelper() ); + OSL_ENSURE( mxCtrlHelper.get(), "Drawing::getControlHelper - cannot create form controls helper" ); } - return pRet; + return *mxCtrlHelper; } -rtl::OUString Drawing::getGraphicUrlById( const rtl::OUString sId ) const +void Drawing::registerOleObject( const OleObjectInfo& rOleObject ) { - rtl::OUString sGraphicURL; - std::vector< ShapePtr >::const_iterator aIter( maShapes.begin() ); - while( aIter != maShapes.end() ) - { - if ( (*aIter)->msId == sId ) - { - sGraphicURL = (*aIter)->msGraphicURL; - break; - } - aIter++; - } - return sGraphicURL; + OSL_ENSURE( rOleObject.maShapeId.getLength() > 0, "Drawing::registerOleObject - missing OLE object shape id" ); + OSL_ENSURE( maOleObjects.count( rOleObject.maShapeId ) == 0, "Drawing::registerOleObject - OLE object already registered" ); + maOleObjects.insert( OleObjectInfoMap::value_type( rOleObject.maShapeId, rOleObject ) ); } -} } +void Drawing::registerControl( const ControlInfo& rControl ) +{ + OSL_ENSURE( rControl.maShapeId.getLength() > 0, "Drawing::registerControl - missing form control shape id" ); + OSL_ENSURE( rControl.maName.getLength() > 0, "Drawing::registerControl - missing form control name" ); + OSL_ENSURE( maControls.count( rControl.maShapeId ) == 0, "Drawing::registerControl - form control already registered" ); + maControls.insert( ControlInfoMap::value_type( rControl.maShapeId, rControl ) ); +} + +void Drawing::finalizeFragmentImport() +{ + mxShapes->finalizeFragmentImport(); +} + +void Drawing::convertAndInsert() const +{ + Reference< XShapes > xShapes( mxDrawPage, UNO_QUERY ); + mxShapes->convertAndInsert( xShapes ); +} + +const OleObjectInfo* Drawing::getOleObjectInfo( const OUString& rShapeId ) const +{ + return ContainerHelper::getMapElement( maOleObjects, rShapeId ); +} + +const ControlInfo* Drawing::getControlInfo( const OUString& rShapeId ) const +{ + return ContainerHelper::getMapElement( maControls, rShapeId ); +} + +bool Drawing::convertShapeClientAnchor( Rectangle& /*orShapeRect*/, const OUString& /*rShapeAnchor*/ ) const +{ + return false; +} + +void Drawing::convertControlClientData( const Reference< XControlModel >& /*rxCtrlModel*/, const ShapeClientData& /*rClientData*/ ) const +{ +} + +::oox::ole::AxControlHelper* Drawing::createControlHelper() const +{ + return new ::oox::ole::AxEmbeddedControlHelper( mrFilter, mxDrawPage ); +} + +// ============================================================================ + +} // namespace vml +} // namespave oox + diff --git a/oox/source/vml/vmldrawingfragment.cxx b/oox/source/vml/vmldrawingfragment.cxx new file mode 100644 index 000000000000..b622df39941c --- /dev/null +++ b/oox/source/vml/vmldrawingfragment.cxx @@ -0,0 +1,95 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: vmldrawingfragmenthandler.cxx,v $ + * $Revision: 1.6 $ + * + * 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. + * + ************************************************************************/ + +#include "oox/vml/vmldrawingfragment.hxx" +#include "oox/vml/vmldrawing.hxx" +#include "oox/vml/vmlinputstream.hxx" +#include "oox/vml/vmlshapecontext.hxx" + +using ::rtl::OUString; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::io::XInputStream; +using ::oox::core::ContextHandlerRef; +using ::oox::core::FragmentHandler2; +using ::oox::core::XmlFilterBase; + +namespace oox { +namespace vml { + +// ============================================================================ + +DrawingFragment::DrawingFragment( XmlFilterBase& rFilter, const OUString& rFragmentPath, Drawing& rDrawing ) : + FragmentHandler2( rFilter, rFragmentPath ), + mrDrawing( rDrawing ) +{ +} + +Reference< XInputStream > DrawingFragment::openFragmentStream() const +{ + return new InputStream( FragmentHandler2::openFragmentStream() ); +} + +ContextHandlerRef DrawingFragment::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs ) +{ + switch( mrDrawing.getType() ) + { + // DOCX filter handles plain shape elements with this fragment handler + case VMLDRAWING_WORD: + if( isRootElement() ) + return ShapeContextBase::createContext( *this, nElement, rAttribs, mrDrawing.getShapes() ); + break; + + // XLSX and PPTX filters load the entire VML fragment + case VMLDRAWING_EXCEL: + case VMLDRAWING_POWERPOINT: + switch( getCurrentElement() ) + { + case XML_ROOT_CONTEXT: + if( nElement == XML_xml ) return this; + break; + case XML_xml: + return ShapeContextBase::createContext( *this, nElement, rAttribs, mrDrawing.getShapes() ); + } + break; + } + return 0; +} + +void DrawingFragment::finalizeImport() +{ + // resolve shape template references for all shapes + mrDrawing.finalizeFragmentImport(); +} + +// ============================================================================ + +} // namespace vml +} // namespace oox + diff --git a/oox/source/vml/vmldrawingfragmenthandler.cxx b/oox/source/vml/vmldrawingfragmenthandler.cxx deleted file mode 100644 index 28e0eebb5e1c..000000000000 --- a/oox/source/vml/vmldrawingfragmenthandler.cxx +++ /dev/null @@ -1,519 +0,0 @@ -/************************************************************************* - * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * Copyright 2008 by Sun Microsystems, Inc. - * - * OpenOffice.org - a multi-platform office productivity suite - * - * $RCSfile: vmldrawingfragmenthandler.cxx,v $ - * $Revision: 1.6 $ - * - * 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. - * - ************************************************************************/ - -#include "oox/vml/drawingfragmenthandler.hxx" - -#include "comphelper/anytostring.hxx" -#include "cppuhelper/exc_hlp.hxx" -#include "oox/helper/attributelist.hxx" -#include "oox/core/contexthandler.hxx" -#include <com/sun/star/beans/XMultiPropertySet.hpp> -#include <com/sun/star/container/XNamed.hpp> -#include <com/sun/star/drawing/PointSequence.hpp> -#include <com/sun/star/drawing/PointSequenceSequence.hpp> -#include "oox/core/namespaces.hxx" -#include "tokens.hxx" - -using ::rtl::OUString; -using namespace ::com::sun::star; -using namespace ::oox::core; -using namespace ::com::sun::star::uno; -using namespace ::com::sun::star::xml::sax; -using namespace ::com::sun::star::container; - -namespace oox { namespace vml { - -static sal_Int32 getMeasure( const rtl::OUString& rVal ) -{ - double fVal = rVal.toDouble(); - const sal_Int32 nLen = rVal.getLength(); - if ( nLen >= 2 ) - { - switch( static_cast< sal_Int8 >( rVal[ nLen - 1 ] ) ) - { - case 'n' : fVal *= 2540; break; - case 'm' : rVal[ nLen - 2 ] == 'm' ? fVal *= 100.0 : fVal *= 1000.0; break; - case 't' : fVal *= 2540.0 / 72.0; break; - case 'c' : fVal *= ( 2540.0 / 72.0 ) * 12.0; break; - } - } - return static_cast< sal_Int32 >( fVal ); -} - -// AG_CoreAttributes -static void ApplyCoreAttributes( const Reference< XFastAttributeList >& xAttribs, Shape& rShape ) -{ - // AG_Id - rShape.msId = xAttribs->getOptionalValue( XML_id ); - - // AG_Style - if ( xAttribs->hasAttribute( XML_style ) ) - { - rtl::OUString sStyle( xAttribs->getOptionalValue( XML_style ) ); - sal_Int32 nIndex = 0; - do - { - OUString aStyleToken( sStyle.getToken( 0, ';', nIndex ) ); - if ( aStyleToken.getLength() ) - { - sal_Int32 nIndex2 = 0; - OUString aName( aStyleToken.getToken( 0, ':', nIndex2 ) ); - OUString aVal ( aStyleToken.getToken( 0, ':', nIndex2 ) ); - if ( aName.getLength() && aVal.getLength() ) - { - static const ::rtl::OUString sPosition( RTL_CONSTASCII_USTRINGPARAM( "position" ) ); - static const ::rtl::OUString sLeft( RTL_CONSTASCII_USTRINGPARAM( "left" ) ); - static const ::rtl::OUString sTop( RTL_CONSTASCII_USTRINGPARAM( "top" ) ); - static const ::rtl::OUString sWidth( RTL_CONSTASCII_USTRINGPARAM( "width" ) ); - static const ::rtl::OUString sHeight( RTL_CONSTASCII_USTRINGPARAM( "height" ) ); - static const ::rtl::OUString sMarginLeft( RTL_CONSTASCII_USTRINGPARAM( "margin-left" ) ); - static const ::rtl::OUString sMarginTop( RTL_CONSTASCII_USTRINGPARAM( "margin-top" ) ); - if ( aName == sPosition ) - rShape.msPosition = aVal; - else if ( aName == sLeft ) - rShape.maPosition.X = getMeasure( aVal ); - else if ( aName == sTop ) - rShape.maPosition.Y = getMeasure( aVal ); - else if ( aName == sWidth ) - rShape.maSize.Width = getMeasure( aVal ); - else if ( aName == sHeight ) - rShape.maSize.Height = getMeasure( aVal ); - else if ( aName == sMarginLeft ) - rShape.maPosition.X = getMeasure( aVal ); - else if ( aName == sMarginTop ) - rShape.maPosition.Y = getMeasure( aVal ); - } - } - } - while ( nIndex >= 0 ); - } - - // href - // target - // class - // title - // alt - - // coordsize - rtl::OUString aCoordSize( xAttribs->getOptionalValue( XML_coordsize ) ); - if ( aCoordSize.getLength() ) - { - sal_Int32 nIndex = 0; - rtl::OUString aCoordWidth ( aCoordSize.getToken( 0, ',', nIndex ) ); - rtl::OUString aCoordHeight( aCoordSize.getToken( 0, ',', nIndex ) ); - if ( aCoordWidth.getLength() ) - rShape.mnCoordWidth = aCoordWidth.toInt32(); - if ( aCoordHeight.getLength() ) - rShape.mnCoordHeight = aCoordHeight.toInt32(); - } - - // coordorigin - // wrapcoords - // print -} - -// AG_ShapeAttributes -static void ApplyShapeAttributes( const Reference< XFastAttributeList >& xAttribs, Shape& rShape ) -{ - AttributeList aAttributeList( xAttribs ); - rShape.mnStroked = xAttribs->getOptionalValueToken( XML_stroked, 0 ); - if ( xAttribs->hasAttribute( XML_filled ) ) - rShape.moFilled = ::boost::optional< sal_Bool >( aAttributeList.getBool( XML_filled, sal_False ) ); - if ( xAttribs->hasAttribute( XML_fillcolor ) ) - rShape.moFillColor = ::boost::optional< rtl::OUString >( xAttribs->getOptionalValue( XML_fillcolor ) ); -} - -//-------------------------------------------------------------------------------------------------------------- -// EG_ShapeElements -class BasicShapeContext : public ContextHandler -{ -public: - BasicShapeContext( ContextHandler& rParent, - sal_Int32 aElement, const Reference< XFastAttributeList >& xAttribs, Shape& rShape ); - virtual Reference< XFastContextHandler > SAL_CALL createFastChildContext( sal_Int32 Element, - const Reference< XFastAttributeList >& Attribs ) throw (::com::sun::star::xml::sax::SAXException, RuntimeException); -private: - Shape& mrShape; -}; - -BasicShapeContext::BasicShapeContext( ContextHandler& rParent, - sal_Int32 /* aElement */, const Reference< XFastAttributeList >& xAttribs, Shape& rShape ) -: ContextHandler( rParent ) -, mrShape( rShape ) -{ - mrShape.msType = xAttribs->getOptionalValue( XML_type ); - mrShape.msShapeType = xAttribs->getOptionalValue( NMSP_OFFICE|XML_spt ); -} -Reference< XFastContextHandler > BasicShapeContext::createFastChildContext( sal_Int32 aElementToken, const Reference< XFastAttributeList >& xAttribs ) - throw (SAXException, RuntimeException) -{ - Reference< XFastContextHandler > xRet; - switch( aElementToken ) - { - case NMSP_VML|XML_imagedata: - { - OUString aRelId( xAttribs->getOptionalValue( NMSP_OFFICE|XML_relid ) ); - mrShape.msGraphicURL = getFragmentPathFromRelId( aRelId ); - mrShape.msImageTitle = xAttribs->getOptionalValue( NMSP_OFFICE|XML_title ); - } - break; - default: - break; - } - if( !xRet.is() ) - xRet.set( this ); - return xRet; -} - -//-------------------------------------------------------------------------------------------------------------- -// CT_Shapetype -class ShapeTypeContext : public BasicShapeContext -{ -public: - ShapeTypeContext( ContextHandler& rParent, - sal_Int32 aElement, const Reference< XFastAttributeList >& xAttribs, Shape& rShape ); - virtual Reference< XFastContextHandler > SAL_CALL createFastChildContext( sal_Int32 Element, - const Reference< XFastAttributeList >& Attribs ) throw (SAXException, RuntimeException); -}; - -ShapeTypeContext::ShapeTypeContext( ContextHandler& rParent, - sal_Int32 aElement, const Reference< XFastAttributeList >& xAttribs, Shape& rShape ) -: BasicShapeContext( rParent, aElement, xAttribs, rShape ) -{ -} - -Reference< XFastContextHandler > ShapeTypeContext::createFastChildContext( sal_Int32 aElementToken, const Reference< XFastAttributeList >& xAttribs ) - throw (SAXException, RuntimeException) -{ - Reference< XFastContextHandler > xRet; -// switch( aElementToken ) -// { -// default: - xRet = BasicShapeContext::createFastChildContext( aElementToken, xAttribs ); -// break; -// } - if( !xRet.is() ) - xRet.set( this ); - return xRet; -} -//-------------------------------------------------------------------------------------------------------------- -// CT_PolyLine -class PolyLineContext : public BasicShapeContext -{ -public: - PolyLineContext( ContextHandler& rParent, - sal_Int32 aElement, const Reference< XFastAttributeList >& xAttribs, Shape& rShape ); - virtual Reference< XFastContextHandler > SAL_CALL createFastChildContext( sal_Int32 Element, - const Reference< XFastAttributeList >& Attribs ) throw (SAXException, RuntimeException); -}; - -PolyLineContext::PolyLineContext( ContextHandler& rParent, - sal_Int32 aElement, const Reference< XFastAttributeList >& xAttribs, Shape& rShape ) -: BasicShapeContext( rParent, aElement, xAttribs, rShape ) -{ - ApplyShapeAttributes( xAttribs, rShape ); - ApplyCoreAttributes( xAttribs, rShape ); - - rtl::OUString aPoints( xAttribs->getOptionalValue( XML_points ) ); - if ( aPoints.getLength() ) - { - std::vector< awt::Point > vPoints; - sal_Int32 nIndex = 0; - do - { - OUString aX( aPoints.getToken( 0, ',', nIndex ) ); - OUString aY( aPoints.getToken( 0, ',', nIndex ) ); - awt::Point aPt( getMeasure( aX ), getMeasure( aY ) ); - vPoints.push_back( aPt ); - } - while ( nIndex >= 0 ); - - drawing::PointSequenceSequence aPointSeq( 1 ); - aPointSeq[ 0 ] = drawing::PointSequence( &vPoints.front(), vPoints.size() ); - static const ::rtl::OUString sPolyPolygon( RTL_CONSTASCII_USTRINGPARAM( "PolyPolygon" ) ); - rShape.maPath.Name = sPolyPolygon; - rShape.maPath.Value <<= aPointSeq; - -/* not sure if the following is needed - - // calculating the bounding box - sal_Int32 nGlobalLeft = SAL_MAX_INT32; - sal_Int32 nGlobalRight = SAL_MIN_INT32; - sal_Int32 nGlobalTop = SAL_MAX_INT32; - sal_Int32 nGlobalBottom= SAL_MIN_INT32; - std::vector< awt::Point >::const_iterator aIter( vPoints.begin() ); - while( aIter != vPoints.end() ) - { - sal_Int32 x = (*aIter).X; - sal_Int32 y = (*aIter).Y; - if ( nGlobalLeft > x ) - nGlobalLeft = x; - if ( nGlobalRight < x ) - nGlobalRight = x; - if ( nGlobalTop > y ) - nGlobalTop = y; - if ( nGlobalBottom < y ) - nGlobalBottom = y; - aIter++; - } - rShape.maPosition.X = nGlobalLeft; - rShape.maPosition.Y = nGlobalTop; - rShape.maSize.Width = nGlobalRight - nGlobalLeft; - rShape.maSize.Height = nGlobalBottom - nGlobalTop; -*/ - } -} - -Reference< XFastContextHandler > PolyLineContext::createFastChildContext( sal_Int32 aElementToken, const Reference< XFastAttributeList >& xAttribs ) - throw (SAXException, RuntimeException) -{ - Reference< XFastContextHandler > xRet; -// switch( aElementToken ) -// { -// default: - xRet = BasicShapeContext::createFastChildContext( aElementToken, xAttribs ); -// break; -// } - if( !xRet.is() ) - xRet.set( this ); - return xRet; -} - -//-------------------------------------------------------------------------------------------------------------- -// CT_Shape -class ShapeContext : public BasicShapeContext -{ -public: - ShapeContext( ContextHandler& rParent, - sal_Int32 aElement, const Reference< XFastAttributeList >& xAttribs, Shape& rShape ); - virtual Reference< XFastContextHandler > SAL_CALL createFastChildContext( sal_Int32 Element, - const Reference< XFastAttributeList >& Attribs ) throw (SAXException, RuntimeException); -}; - -ShapeContext::ShapeContext( ContextHandler& rParent, - sal_Int32 aElement, const Reference< XFastAttributeList >& xAttribs, Shape& rShape ) -: BasicShapeContext( rParent, aElement, xAttribs, rShape ) -{ - ApplyShapeAttributes( xAttribs, rShape ); - ApplyCoreAttributes( xAttribs, rShape ); -// rShape.msPath = xAttribs->getOptionalValue( XML_path ); -} - -Reference< XFastContextHandler > ShapeContext::createFastChildContext( sal_Int32 aElementToken, const Reference< XFastAttributeList >& xAttribs ) - throw (SAXException, RuntimeException) -{ - Reference< XFastContextHandler > xRet; -// switch( aElementToken ) -// { -// default: - xRet = BasicShapeContext::createFastChildContext( aElementToken, xAttribs ); -// break; -// } - if( !xRet.is() ) - xRet.set( this ); - return xRet; -} - -//-------------------------------------------------------------------------------------------------------------- - -class GroupShapeContext : public BasicShapeContext -{ -public: - GroupShapeContext( ContextHandler& rParent, sal_Int32 aElement, const Reference< XFastAttributeList >& xAttribs, - Shape& rShape, std::vector< ShapePtr >& rShapeTypes ); - virtual Reference< XFastContextHandler > SAL_CALL createFastChildContext( sal_Int32 Element, - const Reference< XFastAttributeList >& Attribs ) throw (::com::sun::star::xml::sax::SAXException, RuntimeException); -private: - Shape& mrShape; - std::vector< ShapePtr >& mrShapeTypes; -}; - -GroupShapeContext::GroupShapeContext( ContextHandler& rParent, - sal_Int32 aElement, const Reference< XFastAttributeList >& xAttribs, - Shape& rShape, std::vector< ShapePtr >& rShapeTypes ) -: BasicShapeContext( rParent, aElement, xAttribs, rShape ) -, mrShape( rShape ) -, mrShapeTypes( rShapeTypes ) -{ - AttributeList aAttributeList( xAttribs ); - if ( xAttribs->hasAttribute( XML_filled ) ) - rShape.moFilled = ::boost::optional< sal_Bool >( aAttributeList.getBool( XML_filled, sal_False ) ); - if ( xAttribs->hasAttribute( XML_fillcolor ) ) - rShape.moFillColor = ::boost::optional< rtl::OUString >( xAttribs->getOptionalValue( XML_fillcolor ) ); - ApplyCoreAttributes( xAttribs, rShape ); -} -Reference< XFastContextHandler > GroupShapeContext::createFastChildContext( sal_Int32 aElementToken, const Reference< XFastAttributeList >& xAttribs ) - throw (SAXException, RuntimeException) -{ - return DrawingFragmentHandler::StaticCreateContext( *this, aElementToken, xAttribs, mrShape.getChilds(), mrShapeTypes ); -} - -//-------------------------------------------------------------------------------------------------------------- - -DrawingFragmentHandler::DrawingFragmentHandler( XmlFilterBase& rFilter, const OUString& rFragmentPath, - std::vector< ShapePtr >& rShapes, std::vector< ShapePtr >& rShapeTypes ) - throw() -: FragmentHandler( rFilter, rFragmentPath ) -, mrShapes( rShapes ) -, mrShapeTypes( rShapeTypes ) -, maFragmentPath( rFragmentPath ) -{ -} -DrawingFragmentHandler::~DrawingFragmentHandler() - throw() -{ -} - -::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastContextHandler > DrawingFragmentHandler::StaticCreateContext( oox::core::ContextHandler& rParent, - sal_Int32 aElementToken, const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastAttributeList >& xAttribs, - std::vector< ShapePtr >& rShapes, std::vector< ShapePtr >& rShapeTypes ) - throw (::com::sun::star::xml::sax::SAXException, ::com::sun::star::uno::RuntimeException ) -{ - static const ::rtl::OUString sCustomShape( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.drawing.CustomShape" ) ); - - Reference< XFastContextHandler > xRet; - switch( aElementToken ) - { - case NMSP_VML|XML_group : - { - static const ::rtl::OUString sGroupShape( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.drawing.GroupShape" ) ); - ShapePtr pShapePtr( new Shape( sGroupShape ) ); - xRet = new GroupShapeContext( rParent, aElementToken, xAttribs, *pShapePtr.get(), rShapeTypes ); - rShapes.push_back( pShapePtr ); - } - break; - case NMSP_VML|XML_shapetype : - { - ShapePtr pShapePtr( new Shape( OUString() ) ); - xRet = new ShapeTypeContext( rParent, aElementToken, xAttribs, *pShapePtr.get() ); - rShapeTypes.push_back( pShapePtr ); - } - break; - case NMSP_VML|XML_shape: - { - ShapePtr pShapePtr( new Shape( sCustomShape ) ); - xRet = new ShapeContext( rParent, aElementToken, xAttribs, *pShapePtr.get() ); - rShapes.push_back( pShapePtr ); - } - break; - case NMSP_VML|XML_oval: - { - static const ::rtl::OUString sEllipseShape( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.drawing.EllipseShape" ) ); - ShapePtr pShapePtr( new Shape( sEllipseShape ) ); - xRet = new ShapeContext( rParent, aElementToken, xAttribs, *pShapePtr.get() ); - rShapes.push_back( pShapePtr ); - } - break; - case NMSP_VML|XML_polyline: - { - static const ::rtl::OUString sPolyLineShape( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.drawing.PolyLineShape" ) ); - ShapePtr pShapePtr( new Shape( sPolyLineShape ) ); - xRet = new PolyLineContext( rParent, aElementToken, xAttribs, *pShapePtr.get() ); - rShapes.push_back( pShapePtr ); - } - break; - case NMSP_VML|XML_rect: - { - static const ::rtl::OUString sRectangleShape( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.drawing.RectangleShape" ) ); - ShapePtr pShapePtr( new Shape( sRectangleShape ) ); - xRet = new ShapeContext( rParent, aElementToken, xAttribs, *pShapePtr.get() ); - rShapes.push_back( pShapePtr ); - } - break; - case NMSP_VML|XML_roundrect: - { - static const ::rtl::OUString sRectangleShape( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.drawing.RectangleShape" ) ); - ShapePtr pShapePtr( new Shape( sRectangleShape ) ); - xRet = new ShapeContext( rParent, aElementToken, xAttribs, *pShapePtr.get() ); - rShapes.push_back( pShapePtr ); - } - break; - - // TODO: - case NMSP_VML|XML_arc: - { - ShapePtr pShapePtr( new Shape( sCustomShape ) ); - xRet = new ShapeContext( rParent, aElementToken, xAttribs, *pShapePtr.get() ); - rShapes.push_back( pShapePtr ); - } - break; - case NMSP_VML|XML_curve: - { - ShapePtr pShapePtr( new Shape( sCustomShape ) ); - xRet = new ShapeContext( rParent, aElementToken, xAttribs, *pShapePtr.get() ); - rShapes.push_back( pShapePtr ); - } - break; - case NMSP_VML|XML_line: - { - ShapePtr pShapePtr( new Shape( sCustomShape ) ); - xRet = new ShapeContext( rParent, aElementToken, xAttribs, *pShapePtr.get() ); - rShapes.push_back( pShapePtr ); - } - break; - case NMSP_OFFICE|XML_diagram: - { - ShapePtr pShapePtr( new Shape( sCustomShape ) ); - xRet = new ShapeContext( rParent, aElementToken, xAttribs, *pShapePtr.get() ); - rShapes.push_back( pShapePtr ); - } - break; - case NMSP_VML|XML_image: - { - ShapePtr pShapePtr( new Shape( sCustomShape ) ); - xRet = new ShapeContext( rParent, aElementToken, xAttribs, *pShapePtr.get() ); - rShapes.push_back( pShapePtr ); - } - break; - } - return xRet; -} - - -// CT_GROUP -Reference< XFastContextHandler > DrawingFragmentHandler::createFastChildContext( sal_Int32 aElementToken, const Reference< XFastAttributeList >& xAttribs ) - throw (SAXException, RuntimeException) -{ - return aElementToken == XML_xml - ? getFastContextHandler() - : StaticCreateContext( *this, aElementToken, xAttribs, mrShapes, mrShapeTypes ); -} - -void SAL_CALL DrawingFragmentHandler::endDocument() - throw (SAXException, RuntimeException) -{ -} - -//-------------------------------------------------------------------------------------------------------------- - - - -} } - diff --git a/oox/source/vml/vmlinputstream.cxx b/oox/source/vml/vmlinputstream.cxx new file mode 100644 index 000000000000..56964ad4ab19 --- /dev/null +++ b/oox/source/vml/vmlinputstream.cxx @@ -0,0 +1,94 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: vmldrawing.cxx,v $ + * $Revision: 1.5 $ + * + * 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. + * + ************************************************************************/ + +#include "oox/vml/vmlinputstream.hxx" +#include <algorithm> +#include <string.h> + +using ::com::sun::star::uno::Exception; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::io::XInputStream; + +namespace oox { +namespace vml { + +// ============================================================================ + +StreamDataContainer::StreamDataContainer( const Reference< XInputStream >& rxInStrm ) +{ + if( rxInStrm.is() ) try + { + // read all bytes we can read + rxInStrm->readBytes( maDataSeq, SAL_MAX_INT32 ); + } + catch( Exception& ) + { + } + + // parse the data and eat all parser instructions that make expat sad + if( maDataSeq.hasElements() ) + { + sal_Char* pcBeg = reinterpret_cast< sal_Char* >( maDataSeq.getArray() ); + sal_Char* pcEnd = pcBeg + maDataSeq.getLength(); + sal_Char* pcCurr = pcBeg; + while( pcCurr < pcEnd ) + { + pcCurr = ::std::find( pcCurr, pcEnd, '<' ); + sal_Char* pcClose = ::std::find( pcCurr, pcEnd, '>' ); + if( (pcCurr < pcEnd) && (pcClose < pcEnd) && (pcClose - pcCurr >= 5) && (pcCurr[ 1 ] == '!') && (pcCurr[ 2 ] == '[') && (pcClose[ -1 ] == ']') ) + { + ++pcClose; + memmove( pcCurr, pcClose, pcEnd - pcClose ); + pcEnd -= (pcClose - pcCurr); + } + else + pcCurr = pcClose; + } + maDataSeq.realloc( static_cast< sal_Int32 >( pcEnd - pcBeg ) ); + } +} + +// ============================================================================ + +InputStream::InputStream( const Reference< XInputStream >& rxInStrm ) : + StreamDataContainer( rxInStrm ), + ::comphelper::SequenceInputStream( maDataSeq ) +{ +} + +InputStream::~InputStream() +{ +} + +// ============================================================================ + +} // namespace vml +} // namespave oox + diff --git a/oox/source/vml/vmlshape.cxx b/oox/source/vml/vmlshape.cxx index 106eb394651f..e583248adcfa 100644 --- a/oox/source/vml/vmlshape.cxx +++ b/oox/source/vml/vmlshape.cxx @@ -28,206 +28,534 @@ * ************************************************************************/ -#include <rtl/ustring.hxx> -#include "oox/vml/shape.hxx" -#include "oox/core/xmlfilterbase.hxx" -#include <com/sun/star/drawing/XEnhancedCustomShapeDefaulter.hpp> +#include "oox/vml/vmlshape.hxx" +#include <rtl/math.hxx> #include <com/sun/star/lang/XMultiServiceFactory.hpp> -#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/beans/PropertyValues.hpp> +#include <com/sun/star/awt/XControlModel.hpp> #include <com/sun/star/drawing/FillStyle.hpp> +#include <com/sun/star/drawing/PointSequenceSequence.hpp> +#include <com/sun/star/drawing/XControlShape.hpp> +#include <com/sun/star/drawing/XEnhancedCustomShapeDefaulter.hpp> +#include <com/sun/star/drawing/XShapes.hpp> +#include <com/sun/star/graphic/XGraphic.hpp> +#include "properties.hxx" +#include "oox/helper/propertymap.hxx" +#include "oox/helper/propertyset.hxx" +#include "oox/core/xmlfilterbase.hxx" +#include "oox/ole/axcontrol.hxx" +#include "oox/ole/axcontrolfragment.hxx" +#include "oox/ole/oleobjecthelper.hxx" +#include "oox/vml/vmldrawing.hxx" +#include "oox/vml/vmlshapecontainer.hxx" + +using ::rtl::OUString; +using ::com::sun::star::uno::Exception; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::UNO_QUERY; +using ::com::sun::star::uno::UNO_QUERY_THROW; +using ::com::sun::star::uno::UNO_SET_THROW; +using ::com::sun::star::lang::XMultiServiceFactory; +using ::com::sun::star::awt::Point; +using ::com::sun::star::awt::Rectangle; +using ::com::sun::star::awt::Size; +using ::com::sun::star::awt::XControlModel; +using ::com::sun::star::graphic::XGraphic; +using ::com::sun::star::drawing::PointSequenceSequence; +using ::com::sun::star::drawing::XControlShape; +using ::com::sun::star::drawing::XEnhancedCustomShapeDefaulter; +using ::com::sun::star::drawing::XShape; +using ::com::sun::star::drawing::XShapes; +using ::oox::core::XmlFilterBase; + +namespace oox { +namespace vml { -using namespace com::sun::star; +// ============================================================================ -namespace oox { namespace vml { +namespace { -Shape::Shape( const rtl::OUString& rServiceName ) -: msServiceName( rServiceName ) -, mnCoordWidth( 0 ) -, mnCoordHeight( 0 ) -, mnStroked( 0 ) +sal_Int32 lclGetMeasure( const XmlFilterBase& /*rFilter*/, const OUString& rValue, sal_Int32 nRefValue ) { + // default for missing values is 0 + if( rValue.getLength() == 0 ) + return 0; + + // TODO: according to spec, value may contain "auto" + if( rValue.equalsAscii( "auto" ) ) + return nRefValue; + + // extract the double value and find start position of unit characters + rtl_math_ConversionStatus eConvStatus = rtl_math_ConversionStatus_Ok; + sal_Int32 nEndPos = 0; + double fValue = ::rtl::math::stringToDouble( rValue, '.', '\0', &eConvStatus, &nEndPos ); + if( (eConvStatus != rtl_math_ConversionStatus_Ok) || (fValue == 0.0) ) + return 0; + + // process trailing unit, convert to 1/100 mm + static const OUString saPx = CREATE_OUSTRING( "px" ); + OUString aUnit = ((0 < nEndPos) && (nEndPos < rValue.getLength())) ? rValue.copy( nEndPos ) : saPx; + if( aUnit.getLength() == 2 ) + { + sal_Unicode cChar1 = aUnit[ 0 ]; + sal_Unicode cChar2 = aUnit[ 1 ]; + if( (cChar1 == 'i') && (cChar2 == 'n') ) // 1 inch = 2540 1/100mm + fValue *= 2540.0; + else if( (cChar1 == 'c') && (cChar2 == 'm') ) // 1 cm = 1000 1/100mm + fValue *= 1000.0; + else if( (cChar1 == 'm') && (cChar2 == 'm') ) // 1 mm = 100 1/100mm + fValue *= 100.0; + else if( (cChar1 == 'p') && (cChar2 == 't') ) // 1 point = 1/72 inch + fValue *= 2540.0 / 72.0; + else if( (cChar1 == 'p') && (cChar2 == 'c') ) // 1 pica = 1/6 inch + fValue *= 2540.0 / 6.0; + else if( (cChar1 == 'e') && (cChar2 == 'm') ) // relative to refvalue + fValue *= nRefValue; + else if( (cChar1 == 'p') && (cChar2 == 'x') ) // 1 pixel, dependent on output device + fValue *= 1.0; + } + else if( (aUnit.getLength() == 1) && (aUnit[ 0 ] == '%') ) + { + fValue *= nRefValue / 100.0; + } + else + { + OSL_ENSURE( false, "lclGetMeasure - unknown measure unit" ); + fValue = nRefValue; + } + return static_cast< sal_Int32 >( fValue + 0.5 ); } -Shape::~Shape() + +Point lclGetAbsPoint( const Point& rRelPoint, const Rectangle& rShapeRect, const Rectangle& rCoordSys ) { + double fWidthRatio = static_cast< double >( rShapeRect.Width ) / rCoordSys.Width; + double fHeightRatio = static_cast< double >( rShapeRect.Height ) / rCoordSys.Height; + Point aAbsPoint; + aAbsPoint.X = static_cast< sal_Int32 >( rShapeRect.X + fWidthRatio * (rRelPoint.X - rCoordSys.X) + 0.5 ); + aAbsPoint.Y = static_cast< sal_Int32 >( rShapeRect.Y + fHeightRatio * (rRelPoint.Y - rCoordSys.Y) + 0.5 ); + return aAbsPoint; } -void Shape::applyAttributes( const vml::Shape& rSource ) +Rectangle lclGetAbsRect( const Rectangle& rRelRect, const Rectangle& rShapeRect, const Rectangle& rCoordSys ) { - if ( rSource.msId.getLength() ) - msId = rSource.msId; - if ( rSource.msType.getLength() ) - msType = rSource.msType; - if ( rSource.msShapeType.getLength() ) - msShapeType = rSource.msShapeType; - if ( rSource.mnCoordWidth ) - mnCoordWidth = rSource.mnCoordWidth; - if ( rSource.mnCoordHeight ) - mnCoordHeight = rSource.mnCoordHeight; - if ( rSource.mnStroked ) - mnStroked = rSource.mnStroked; - if ( rSource.moFilled ) - moFilled = rSource.moFilled; - if ( rSource.moFillColor ) - moFillColor = rSource.moFillColor; - if ( rSource.maPath.Name.getLength() ) - maPath = rSource.maPath; - if ( rSource.msPosition.getLength() ) - msPosition = rSource.msPosition; - maPosition = rSource.maPosition; - maSize = rSource.maSize; + double fWidthRatio = static_cast< double >( rShapeRect.Width ) / rCoordSys.Width; + double fHeightRatio = static_cast< double >( rShapeRect.Height ) / rCoordSys.Height; + Rectangle aAbsRect; + aAbsRect.X = static_cast< sal_Int32 >( rShapeRect.X + fWidthRatio * (rRelRect.X - rCoordSys.X) + 0.5 ); + aAbsRect.Y = static_cast< sal_Int32 >( rShapeRect.Y + fHeightRatio * (rRelRect.Y - rCoordSys.Y) + 0.5 ); + aAbsRect.Width = static_cast< sal_Int32 >( fWidthRatio * rRelRect.Width + 0.5 ); + aAbsRect.Height = static_cast< sal_Int32 >( fHeightRatio * rRelRect.Height + 0.5 ); + return aAbsRect; } -::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape > Shape::createAndInsert( - const ::oox::core::XmlFilterBase& rFilterBase, const ::oox::vml::Shape& rShape, - const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShapes >& rxShapes, - const awt::Rectangle* pShapeRect ) +Reference< XShape > lclCreateXShape( const XmlFilterBase& rFilter, const OUString& rService ) { - uno::Reference< drawing::XShape > xShape; - if ( rShape.msServiceName ) + OSL_ENSURE( rService.getLength() > 0, "lclCreateXShape - missing UNO shape service name" ); + Reference< XShape > xShape; + try { - try - { - uno::Reference< lang::XMultiServiceFactory > xServiceFact( rFilterBase.getModel(), uno::UNO_QUERY_THROW ); - xShape.set( xServiceFact->createInstance( rShape.msServiceName ), uno::UNO_QUERY_THROW ); - rxShapes->add( xShape ); - awt::Point aPosition; - awt::Size aSize; - if ( pShapeRect ) - { - aPosition.X = pShapeRect->X; - aPosition.Y = pShapeRect->Y; - aSize.Width = pShapeRect->Width; - aSize.Height = pShapeRect->Height; - } - else - { - aPosition = maPosition; - aSize = maSize; - } - xShape->setPosition( aPosition ); - xShape->setSize( aSize ); - uno::Reference< beans::XPropertySet > xPropSet( xShape, uno::UNO_QUERY ); - try - { - if ( maPath.Name.getLength() ) - xPropSet->setPropertyValue( maPath.Name, maPath.Value ); + Reference< XMultiServiceFactory > xFactory( rFilter.getModel(), UNO_QUERY_THROW ); + xShape.set( xFactory->createInstance( rService ), UNO_QUERY_THROW ); + } + catch( Exception& ) + { + } + OSL_ENSURE( xShape.is(), "lclCreateXShape - cannot instanciate shape object" ); + return xShape; +} - ::rtl::OUString sFillStyle( rtl::OUString::createFromAscii( "FillStyle" ) ); - if ( moFilled ) - xPropSet->setPropertyValue( sFillStyle, uno::Any( *moFilled ? drawing::FillStyle_SOLID : drawing::FillStyle_NONE ) ); - } - catch ( uno::Exception& ) - { - } - ::rtl::OUString rServiceName( rtl::OUString::createFromAscii( "com.sun.star.drawing.CustomShape" ) ); - if ( rShape.msShapeType.getLength() && ( msServiceName == rServiceName ) ) - { - uno::Reference< drawing::XEnhancedCustomShapeDefaulter > xDefaulter( xShape, uno::UNO_QUERY ); - if( xDefaulter.is() ) - xDefaulter->createCustomShapeDefaults( rShape.msShapeType ); - } - mxShape = xShape; - } - catch( uno::Exception& ) - { - } +void lclInsertXShape( const Reference< XShapes >& rxShapes, const Reference< XShape >& rxShape, const Rectangle& rShapeRect ) +{ + OSL_ENSURE( rxShapes.is(), "lclInsertXShape - missing XShapes container" ); + OSL_ENSURE( rxShape.is(), "lclInsertXShape - missing XShape" ); + if( rxShapes.is() && rxShape.is() ) try + { + // insert shape into passed shape collection (maybe drawpage or group shape) + rxShapes->add( rxShape ); + // set position/size + rxShape->setPosition( Point( rShapeRect.X, rShapeRect.Y ) ); + rxShape->setSize( Size( rShapeRect.Width, rShapeRect.Height ) ); + } + catch( Exception& ) + { + } +} + +Reference< XShape > lclCreateAndInsertXShape( const XmlFilterBase& rFilter, + const Reference< XShapes >& rxShapes, const OUString& rService, const Rectangle& rShapeRect ) +{ + Reference< XShape > xShape = lclCreateXShape( rFilter, rService ); + lclInsertXShape( rxShapes, xShape, rShapeRect ); + return xShape; +} + +} // namespace + +// ============================================================================ + +ShapeTypeModel::ShapeTypeModel() +{ +} + +void ShapeTypeModel::assignUsed( const ShapeTypeModel& rSource ) +{ + monShapeType.assignIfUsed( rSource.monShapeType ); + monCoordLeft.assignIfUsed( rSource.monCoordLeft ); + monCoordTop.assignIfUsed( rSource.monCoordTop ); + monCoordWidth.assignIfUsed( rSource.monCoordWidth ); + monCoordHeight.assignIfUsed( rSource.monCoordHeight ); + /* The style properties position, left, top, width, height, margin-left, + margin-top are not derived from shape template to shape. */ + mobStroked.assignIfUsed( rSource.mobStroked ); + moStrokeColor.assignIfUsed( rSource.moStrokeColor ); + mobFilled.assignIfUsed( rSource.mobFilled ); + moFillColor.assignIfUsed( rSource.moFillColor ); + moGraphicPath.assignIfUsed( rSource.moGraphicPath ); + moGraphicTitle.assignIfUsed( rSource.moGraphicTitle ); +} + +// ---------------------------------------------------------------------------- + +ShapeType::ShapeType( const Drawing& rDrawing ) : + mrDrawing( rDrawing ) +{ +} + +ShapeType::~ShapeType() +{ +} + +OUString ShapeType::getGraphicPath() const +{ + return maTypeModel.moGraphicPath.get( OUString() ); +} + +Rectangle ShapeType::getCoordSystem() const +{ + return Rectangle( + maTypeModel.monCoordLeft.get( 0 ), + maTypeModel.monCoordTop.get( 0 ), + maTypeModel.monCoordWidth.get( 1000 ), + maTypeModel.monCoordHeight.get( 1000 ) ); +} + +Rectangle ShapeType::getRectangle( const ShapeParentAnchor* pParentAnchor ) const +{ + return pParentAnchor ? + lclGetAbsRect( getRelRectangle(), pParentAnchor->maShapeRect, pParentAnchor->maCoordSys ) : + getAbsRectangle(); +} + +Rectangle ShapeType::getAbsRectangle() const +{ + const XmlFilterBase& rFilter = mrDrawing.getFilter(); + return Rectangle( + lclGetMeasure( rFilter, maTypeModel.maLeft, 0 ) + lclGetMeasure( rFilter, maTypeModel.maMarginLeft, 0 ), + lclGetMeasure( rFilter, maTypeModel.maTop, 0 ) + lclGetMeasure( rFilter, maTypeModel.maMarginTop, 0 ), + lclGetMeasure( rFilter, maTypeModel.maWidth, 0 ), + lclGetMeasure( rFilter, maTypeModel.maHeight, 0 ) ); +} + +Rectangle ShapeType::getRelRectangle() const +{ + return Rectangle( + maTypeModel.maLeft.toInt32(), + maTypeModel.maTop.toInt32(), + maTypeModel.maWidth.toInt32(), + maTypeModel.maHeight.toInt32() ); +} + +// ============================================================================ + +ShapeClientData::ShapeClientData() : + mnObjType( XML_TOKEN_INVALID ), + mbPrintObject( true ) +{ +} + +// ---------------------------------------------------------------------------- + +ShapeModel::ShapeModel() +{ +} + +ShapeClientData& ShapeModel::createClientData() +{ + mxClientData.reset( new ShapeClientData ); + return *mxClientData; +} + +// ---------------------------------------------------------------------------- + +ShapeBase::ShapeBase( const Drawing& rDrawing ) : + ShapeType( rDrawing ) +{ +} + +void ShapeBase::finalizeFragmentImport() +{ + // resolve shape template reference + if( (maShapeModel.maType.getLength() > 1) && (maShapeModel.maType[ 0 ] == '#') ) + if( const ShapeType* pShapeType = mrDrawing.getShapes().getShapeTypeById( maShapeModel.maType.copy( 1 ), true ) ) + maTypeModel.assignUsed( pShapeType->getTypeModel() ); +} + +const ShapeType* ShapeBase::getChildTypeById( const OUString& ) const +{ + return 0; +} + +const ShapeBase* ShapeBase::getChildById( const OUString& ) const +{ + return 0; +} + +Reference< XShape > ShapeBase::convertAndInsert( const Reference< XShapes >& rxShapes, const ShapeParentAnchor* pParentAnchor ) const +{ + Reference< XShape > xShape; + /* Calculate shape rectangle. Applications may do something special + according to some imported shape client data (e.g. Excel cell anchor). */ + Rectangle aShapeRect; + if( !maShapeModel.mxClientData.get() || !mrDrawing.convertShapeClientAnchor( aShapeRect, maShapeModel.mxClientData->maAnchor ) ) + aShapeRect = getRectangle( pParentAnchor ); + // convert the shape, if the calculated rectangle is not empty + if( (aShapeRect.Width > 0) || (aShapeRect.Height > 0) && rxShapes.is() ) + xShape = implConvertAndInsert( rxShapes, aShapeRect ); + return xShape; +} + +// protected ------------------------------------------------------------------ + +void ShapeBase::convertShapeProperties( const Reference< XShape >& rxShape ) const +{ + // shape properties + PropertySet aPropSet( rxShape ); + + // fill style + bool bFilled = maTypeModel.mobFilled.get( true ); + aPropSet.setProperty( PROP_FillStyle, bFilled ? ::com::sun::star::drawing::FillStyle_SOLID : ::com::sun::star::drawing::FillStyle_NONE ); +} + +// ============================================================================ + +SimpleShape::SimpleShape( const Drawing& rDrawing, const OUString& rService ) : + ShapeBase( rDrawing ), + maService( rService ) +{ +} + +Reference< XShape > SimpleShape::implConvertAndInsert( const Reference< XShapes >& rxShapes, const Rectangle& rShapeRect ) const +{ + Reference< XShape > xShape = lclCreateAndInsertXShape( mrDrawing.getFilter(), rxShapes, maService, rShapeRect ); + convertShapeProperties( xShape ); + return xShape; +} + +// ============================================================================ + +RectangleShape::RectangleShape( const Drawing& rDrawing ) : + SimpleShape( rDrawing, CREATE_OUSTRING( "com.sun.star.drawing.RectangleShape" ) ) +{ +} + +// ============================================================================ + +EllipseShape::EllipseShape( const Drawing& rDrawing ) : + SimpleShape( rDrawing, CREATE_OUSTRING( "com.sun.star.drawing.EllipseShape" ) ) +{ +} + +// ============================================================================ + +PolyLineShape::PolyLineShape( const Drawing& rDrawing ) : + SimpleShape( rDrawing, CREATE_OUSTRING( "com.sun.star.drawing.PolyLineShape" ) ) +{ +} + +Reference< XShape > PolyLineShape::implConvertAndInsert( const Reference< XShapes >& rxShapes, const Rectangle& rShapeRect ) const +{ + Reference< XShape > xShape = SimpleShape::implConvertAndInsert( rxShapes, rShapeRect ); + // polygon path + Rectangle aCoordSys = getCoordSystem(); + if( !maShapeModel.maPoints.empty() && (aCoordSys.Width > 0) && (aCoordSys.Height > 0) ) + { + ::std::vector< Point > aAbsPoints; + for( ShapeModel::PointVector::const_iterator aIt = maShapeModel.maPoints.begin(), aEnd = maShapeModel.maPoints.end(); aIt != aEnd; ++aIt ) + aAbsPoints.push_back( lclGetAbsPoint( *aIt, rShapeRect, aCoordSys ) ); + PointSequenceSequence aPointSeq( 1 ); + aPointSeq[ 0 ] = ContainerHelper::vectorToSequence( aAbsPoints ); + PropertySet aPropSet( xShape ); + aPropSet.setProperty( PROP_PolyPolygon, aPointSeq ); } return xShape; } -void Shape::addChilds( const ::oox::core::XmlFilterBase& rFilterBase, const ::oox::vml::Drawing& rDrawing, - const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShapes >& rxShapes, - const awt::Rectangle& rClientRect ) +// ============================================================================ + +CustomShape::CustomShape( const Drawing& rDrawing ) : + SimpleShape( rDrawing, CREATE_OUSTRING( "com.sun.star.drawing.CustomShape" ) ) { - sal_Int32 nGlobalLeft = SAL_MAX_INT32; - sal_Int32 nGlobalRight = SAL_MIN_INT32; - sal_Int32 nGlobalTop = SAL_MAX_INT32; - sal_Int32 nGlobalBottom= SAL_MIN_INT32; - std::vector< ShapePtr >::iterator aIter( maChilds.begin() ); - while( aIter != maChilds.end() ) +} + +Reference< XShape > CustomShape::implConvertAndInsert( const Reference< XShapes >& rxShapes, const Rectangle& rShapeRect ) const +{ + // try to create a custom shape + Reference< XShape > xShape = SimpleShape::implConvertAndInsert( rxShapes, rShapeRect ); + if( xShape.is() ) try { - sal_Int32 l = (*aIter)->maPosition.X; - sal_Int32 t = (*aIter)->maPosition.Y; - sal_Int32 r = l + (*aIter)->maSize.Width; - sal_Int32 b = t + (*aIter)->maSize.Height; - if ( nGlobalLeft > l ) - nGlobalLeft = l; - if ( nGlobalRight < r ) - nGlobalRight = r; - if ( nGlobalTop > t ) - nGlobalTop = t; - if ( nGlobalBottom < b ) - nGlobalBottom = b; - aIter++; + // create the custom shape geometry + Reference< XEnhancedCustomShapeDefaulter > xDefaulter( xShape, UNO_QUERY_THROW ); + xDefaulter->createCustomShapeDefaults( OUString::valueOf( maTypeModel.monShapeType.get( 0 ) ) ); + // convert common properties + convertShapeProperties( xShape ); } - aIter = maChilds.begin(); - while( aIter != maChilds.end() ) + catch( Exception& ) { - awt::Rectangle aShapeRect; - awt::Rectangle* pShapeRect = 0; - if ( ( nGlobalLeft != SAL_MAX_INT32 ) && ( nGlobalRight != SAL_MIN_INT32 ) && ( nGlobalTop != SAL_MAX_INT32 ) && ( nGlobalBottom != SAL_MIN_INT32 ) ) - { - sal_Int32 nGlobalWidth = nGlobalRight - nGlobalLeft; - sal_Int32 nGlobalHeight = nGlobalBottom - nGlobalTop; - if ( nGlobalWidth && nGlobalHeight ) - { - double fWidth = (*aIter)->maSize.Width; - double fHeight= (*aIter)->maSize.Height; - double fXScale = (double)rClientRect.Width / (double)nGlobalWidth; - double fYScale = (double)rClientRect.Height / (double)nGlobalHeight; - aShapeRect.X = static_cast< sal_Int32 >( ( ( (*aIter)->maPosition.X - nGlobalLeft ) * fXScale ) + rClientRect.X ); - aShapeRect.Y = static_cast< sal_Int32 >( ( ( (*aIter)->maPosition.Y - nGlobalTop ) * fYScale ) + rClientRect.Y ); - fWidth *= fXScale; - fHeight *= fYScale; - aShapeRect.Width = static_cast< sal_Int32 >( fWidth ); - aShapeRect.Height = static_cast< sal_Int32 >( fHeight ); - pShapeRect = &aShapeRect; - } - } - (*aIter++)->addShape( rFilterBase, rDrawing, rxShapes, pShapeRect ); } + return xShape; +} + +// ============================================================================ + +ComplexShape::ComplexShape( const Drawing& rDrawing ) : + CustomShape( rDrawing ) +{ } -void Shape::addShape( const ::oox::core::XmlFilterBase& rFilterBase, const ::oox::vml::Drawing& rDrawing, - const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShapes >& rxShapes, - const awt::Rectangle* pShapeRect ) +Reference< XShape > ComplexShape::implConvertAndInsert( const Reference< XShapes >& rxShapes, const Rectangle& rShapeRect ) const { - oox::vml::Shape aShape( msServiceName ); - if ( msType.getLength() ) + XmlFilterBase& rFilter = mrDrawing.getFilter(); + OUString aGraphicPath = getGraphicPath(); + + // try to find registered OLE object info + if( const OleObjectInfo* pOleObjectInfo = mrDrawing.getOleObjectInfo( maTypeModel.maShapeId ) ) { - std::vector< ShapePtr >& rShapeTypes = const_cast< ::oox::vml::Drawing& >( rDrawing ).getShapeTypes(); - std::vector< ShapePtr >::const_iterator aShapeTypeIter( rShapeTypes.begin() ); - while( aShapeTypeIter != rShapeTypes.end() ) + // if OLE object is embedded into a DrawingML shape (PPTX), do not create it here + if( pOleObjectInfo->mbDmlShape ) + return Reference< XShape >(); + + PropertyMap aOleProps; + Size aOleSize( rShapeRect.Width, rShapeRect.Height ); + if( rFilter.getOleObjectHelper().importOleObject( aOleProps, *pOleObjectInfo, aOleSize ) ) { - if ( (*aShapeTypeIter)->msType == aShape.msType ) + Reference< XShape > xShape = lclCreateAndInsertXShape( rFilter, rxShapes, CREATE_OUSTRING( "com.sun.star.drawing.OLE2Shape" ), rShapeRect ); + if( xShape.is() ) { - aShape.applyAttributes( *(*aShapeTypeIter).get() ); - break; + // set the replacement graphic + if( aGraphicPath.getLength() > 0 ) + { + Reference< XGraphic > xGraphic = rFilter.importEmbeddedGraphic( aGraphicPath ); + if( xGraphic.is() ) + aOleProps[ PROP_Graphic ] <<= xGraphic; + } + + PropertySet aPropSet( xShape ); + aPropSet.setProperties( aOleProps ); + + return xShape; } - aShapeTypeIter++; } } - aShape.applyAttributes( *this ); - // creating XShape - uno::Reference< drawing::XShape > xShape( createAndInsert( rFilterBase, aShape, rxShapes, pShapeRect ) ); + // try to find registered form control info + const ControlInfo* pControlInfo = mrDrawing.getControlInfo( maTypeModel.maShapeId ); + if( pControlInfo && (pControlInfo->maFragmentPath.getLength() > 0) && (maTypeModel.maName.getLength() > 0) ) + { + OSL_ENSURE( maTypeModel.maName == pControlInfo->maName, "ComplexShape::implConvertAndInsert - control name mismatch" ); + ::oox::ole::AxControl aControl( maTypeModel.maName ); + // load the control properties from fragment + if( rFilter.importFragment( new ::oox::ole::AxControlFragment( rFilter, pControlInfo->maFragmentPath, aControl ) ) ) try + { + // create control model and insert it into the form of the draw page + Reference< XControlModel > xCtrlModel( aControl.convertAndInsert( mrDrawing.getControlHelper() ), UNO_SET_THROW ); + if( maShapeModel.mxClientData.get() ) + mrDrawing.convertControlClientData( xCtrlModel, *maShapeModel.mxClientData ); - // creating GroupShape if possible - uno::Reference< drawing::XShapes > xShapes( xShape, uno::UNO_QUERY ); - if ( xShapes.is() ) + // create the control shape, set control model at the shape + Reference< XShape > xShape = lclCreateAndInsertXShape( + rFilter, rxShapes, CREATE_OUSTRING( "com.sun.star.drawing.ControlShape" ), rShapeRect ); + Reference< XControlShape > xCtrlShape( xShape, UNO_QUERY ); // do not throw, but always return the shape + if( xCtrlShape.is() ) + xCtrlShape->setControl( xCtrlModel ); + return xShape; + } + catch( Exception& ) + { + } + // on error, proceed and try to create picture from replacement image + } + + // try to create a picture object + if( aGraphicPath.getLength() > 0 ) { - awt::Rectangle aChildRect; - if ( pShapeRect ) - aChildRect = *pShapeRect; - else + Reference< XShape > xShape = lclCreateAndInsertXShape( rFilter, rxShapes, CREATE_OUSTRING( "com.sun.star.drawing.GraphicObjectShape" ), rShapeRect ); + if( xShape.is() ) { - aChildRect.X = maPosition.X; - aChildRect.Y = maPosition.Y; - aChildRect.Width = maSize.Width; - aChildRect.Height = maSize.Height; + OUString aGraphicUrl = rFilter.importEmbeddedGraphicObject( aGraphicPath ); + if( aGraphicUrl.getLength() > 0 ) + { + PropertySet aPropSet( xShape ); + aPropSet.setProperty( PROP_GraphicURL, aGraphicUrl ); + } } - addChilds( rFilterBase, rDrawing, xShapes, aChildRect ); + return xShape; + } + + // default: try to create a custom shape + return CustomShape::implConvertAndInsert( rxShapes, rShapeRect ); +} + +// ============================================================================ + +GroupShape::GroupShape( const Drawing& rDrawing ) : + ShapeBase( rDrawing ), + mxChildren( new ShapeContainer( rDrawing ) ) +{ +} + +GroupShape::~GroupShape() +{ +} + +void GroupShape::finalizeFragmentImport() +{ + // basic shape processing + ShapeBase::finalizeFragmentImport(); + // finalize all child shapes + mxChildren->finalizeFragmentImport(); +} + +const ShapeType* GroupShape::getChildTypeById( const OUString& rShapeId ) const +{ + return mxChildren->getShapeTypeById( rShapeId, true ); +} + +const ShapeBase* GroupShape::getChildById( const OUString& rShapeId ) const +{ + return mxChildren->getShapeById( rShapeId, true ); +} + +Reference< XShape > GroupShape::implConvertAndInsert( const Reference< XShapes >& rxShapes, const Rectangle& rShapeRect ) const +{ + Reference< XShape > xShape; + // check that this shape contains children and a valid coordinate system + ShapeParentAnchor aParentAnchor; + aParentAnchor.maShapeRect = rShapeRect; + aParentAnchor.maCoordSys = getCoordSystem(); + if( !mxChildren->empty() && (aParentAnchor.maCoordSys.Width > 0) && (aParentAnchor.maCoordSys.Height > 0) ) try + { + xShape = lclCreateAndInsertXShape( mrDrawing.getFilter(), rxShapes, CREATE_OUSTRING( "com.sun.star.drawing.GroupShape" ), rShapeRect ); + Reference< XShapes > xShapes( xShape, UNO_QUERY_THROW ); + mxChildren->convertAndInsert( xShapes, &aParentAnchor ); } + catch( Exception& ) + { + } + return xShape; } -} } +// ============================================================================ + +} // namespace vml +} // namespace oox + diff --git a/oox/source/vml/vmlshapecontainer.cxx b/oox/source/vml/vmlshapecontainer.cxx new file mode 100644 index 000000000000..3b9346f3096a --- /dev/null +++ b/oox/source/vml/vmlshapecontainer.cxx @@ -0,0 +1,137 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: vmlshapecontainer.cxx,v $ + * $Revision: 1.1 $ + * + * 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. + * + ************************************************************************/ + +#include "oox/vml/vmlshapecontainer.hxx" +#include "oox/vml/vmldrawing.hxx" +#include "oox/vml/vmlshape.hxx" + +using ::rtl::OUString; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::awt::Rectangle; +using ::com::sun::star::drawing::XShapes; +using ::oox::core::XmlFilterBase; + +namespace oox { +namespace vml { + +// ============================================================================ + +namespace { + +template< typename ShapeType > +void lclMapShapesById( RefMap< OUString, ShapeType >& orMap, const RefVector< ShapeType >& rVector ) +{ + for( typename RefVector< ShapeType >::const_iterator aIt = rVector.begin(), aEnd = rVector.end(); aIt != aEnd; ++aIt ) + { + const OUString& rShapeId = (*aIt)->getShapeId(); + OSL_ENSURE( rShapeId.getLength() > 0, "lclMapShapesById - missing shape identifier" ); + if( rShapeId.getLength() > 0 ) + { + OSL_ENSURE( orMap.find( rShapeId ) == orMap.end(), "lclMapShapesById - shape identifier already used" ); + orMap[ rShapeId ] = *aIt; + } + } +} + +} // namespace + +// ============================================================================ + +ShapeContainer::ShapeContainer( const Drawing& rDrawing ) : + mrDrawing( rDrawing ) +{ +} + +ShapeContainer::~ShapeContainer() +{ +} + +ShapeType& ShapeContainer::createShapeType() +{ + ::boost::shared_ptr< ShapeType > xShape( new ShapeType( mrDrawing ) ); + maTypes.push_back( xShape ); + return *xShape; +} + +void ShapeContainer::finalizeFragmentImport() +{ + // map all shape templates by shape identifier + lclMapShapesById( maTypesById, maTypes ); + // map all shapes by shape identifier + lclMapShapesById( maShapesById, maShapes ); + /* process all shapes (map all children templates/shapes in group shapes, + resolve template references in all shapes) */ + maShapes.forEachMem( &ShapeBase::finalizeFragmentImport ); +} + +const ShapeType* ShapeContainer::getShapeTypeById( const OUString& rShapeId, bool bDeep ) const +{ + // search in own shape template list + if( const ShapeType* pType = maTypesById.get( rShapeId ).get() ) + return pType; + // search deep in child shapes + if( bDeep ) + for( ShapeVector::const_iterator aVIt = maShapes.begin(), aVEnd = maShapes.end(); aVIt != aVEnd; ++aVIt ) + if( const ShapeType* pType = (*aVIt)->getChildTypeById( rShapeId ) ) + return pType; + return 0; +} + +const ShapeBase* ShapeContainer::getShapeById( const OUString& rShapeId, bool bDeep ) const +{ + // search in own shape list + if( const ShapeBase* pShape = maShapesById.get( rShapeId ).get() ) + return pShape; + // search deep in child shapes + if( bDeep ) + for( ShapeVector::const_iterator aVIt = maShapes.begin(), aVEnd = maShapes.end(); aVIt != aVEnd; ++aVIt ) + if( const ShapeBase* pShape = (*aVIt)->getChildById( rShapeId ) ) + return pShape; + return 0; +} + +const ShapeBase* ShapeContainer::getFirstShape() const +{ + OSL_ENSURE( mrDrawing.getType() == VMLDRAWING_WORD, "ShapeContainer::getFirstShape - illegal call, Word filter only" ); + OSL_ENSURE( maShapes.size() == 1, "ShapeContainer::getFirstShape - single shape expected" ); + return maShapes.get( 0 ).get(); +} + +void ShapeContainer::convertAndInsert( const Reference< XShapes >& rxShapes, const ShapeParentAnchor* pParentAnchor ) const +{ + for( ShapeVector::const_iterator aIt = maShapes.begin(), aEnd = maShapes.end(); aIt != aEnd; ++aIt ) + (*aIt)->convertAndInsert( rxShapes, pParentAnchor ); +} + +// ============================================================================ + +} // namespace vml +} // namespace oox + diff --git a/oox/source/vml/vmlshapecontext.cxx b/oox/source/vml/vmlshapecontext.cxx new file mode 100644 index 000000000000..dcf842a67a8f --- /dev/null +++ b/oox/source/vml/vmlshapecontext.cxx @@ -0,0 +1,267 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: vmldrawingfragmenthandler.cxx,v $ + * $Revision: 1.6 $ + * + * 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. + * + ************************************************************************/ + +#include "oox/vml/vmlshapecontext.hxx" +#include "oox/vml/vmlshape.hxx" +#include "oox/vml/vmlshapecontainer.hxx" + +using ::rtl::OUString; +using ::com::sun::star::awt::Point; +using ::oox::core::ContextHandler2; +using ::oox::core::ContextHandler2Helper; +using ::oox::core::ContextHandlerRef; + +namespace oox { +namespace vml { + +// ============================================================================ + +namespace { + +bool lclSeparateValue( OUString& orName, OUString& orValue, const OUString& rAttrib, sal_Unicode cSep = ':' ) +{ + sal_Int32 nSepPos = rAttrib.indexOf( cSep ); + if( nSepPos <= 0 ) return false; + orName = rAttrib.copy( 0, nSepPos ).trim(); + orValue = rAttrib.copy( nSepPos + 1 ).trim(); + return (orName.getLength() > 0) && (orValue.getLength() > 0); +} + +/** Returns the boolean value from the passed string (supported: f, t, False, True). + @param bDefaultForEmpty Default value for the empty string. + */ +bool lclDecodeBool( const OUString& rValue, bool bDefaultForEmpty ) +{ + if( rValue.getLength() == 0 ) return bDefaultForEmpty; + // anything else than 't' or 'True' is considered to be false, as specified + return ((rValue.getLength() == 1) && (rValue[ 0 ] == 't')) || (rValue == CREATE_OUSTRING( "True" )); +} + +} // namespace + +// ============================================================================ + +ShapeClientDataContext::ShapeClientDataContext( ContextHandler2Helper& rParent, + const AttributeList& rAttribs, ShapeClientData& rClientData ) : + ContextHandler2( rParent ), + mrClientData( rClientData ) +{ + mrClientData.mnObjType = rAttribs.getToken( XML_ObjectType, XML_TOKEN_INVALID ); +} + +ContextHandlerRef ShapeClientDataContext::onCreateContext( sal_Int32 /*nElement*/, const AttributeList& /*rAttribs*/ ) +{ + return isRootElement() ? this : 0; +} + +void ShapeClientDataContext::onEndElement( const OUString& rChars ) +{ + switch( getCurrentElement() ) + { + case VMLX_TOKEN( Anchor ): mrClientData.maAnchor = rChars; break; + case VMLX_TOKEN( FmlaLink ): mrClientData.maLinkedCell = rChars; break; + case VMLX_TOKEN( FmlaPict ): mrClientData.maPictureLink = rChars; break; + case VMLX_TOKEN( FmlaRange ): mrClientData.maSourceRange = rChars; break; + case VMLX_TOKEN( PrintObject ): mrClientData.mbPrintObject = lclDecodeBool( rChars, true ); break; + } +} + +// ============================================================================ + +ShapeContextBase::ShapeContextBase( ContextHandler2Helper& rParent ) : + ContextHandler2( rParent ) +{ +} + +/*static*/ ContextHandlerRef ShapeContextBase::createContext( ContextHandler2Helper& rParent, + sal_Int32 nElement, const AttributeList& rAttribs, ShapeContainer& rShapes ) +{ + switch( nElement ) + { + case VML_TOKEN( shapetype ): + return new ShapeTypeContext( rParent, rAttribs, rShapes.createShapeType() ); + case VML_TOKEN( group ): + return new GroupShapeContext( rParent, rAttribs, rShapes.createShape< GroupShape >() ); + case VML_TOKEN( shape ): + return new ShapeContext( rParent, rAttribs, rShapes.createShape< ComplexShape >() ); + case VML_TOKEN( rect ): + case VML_TOKEN( roundrect ): + return new ShapeContext( rParent, rAttribs, rShapes.createShape< RectangleShape >() ); + case VML_TOKEN( oval ): + return new ShapeContext( rParent, rAttribs, rShapes.createShape< EllipseShape >() ); + case VML_TOKEN( polyline ): + return new ShapeContext( rParent, rAttribs, rShapes.createShape< PolyLineShape >() ); + + // TODO: + case VML_TOKEN( arc ): + case VML_TOKEN( curve ): + case VML_TOKEN( line ): + case VML_TOKEN( diagram ): + case VML_TOKEN( image ): + return new ShapeContext( rParent, rAttribs, rShapes.createShape< ComplexShape >() ); + } + return false; +} + +// ============================================================================ + +ShapeTypeContext::ShapeTypeContext( ContextHandler2Helper& rParent, const AttributeList& rAttribs, ShapeType& rShapeType ) : + ShapeContextBase( rParent ), + mrTypeModel( rShapeType.getTypeModel() ) +{ + // shape identifier and shape name + bool bHasOspid = rAttribs.hasAttribute( O_TOKEN( spid ) ); + mrTypeModel.maShapeId = rAttribs.getXString( bHasOspid ? O_TOKEN( spid ) : XML_id, OUString() ); + OSL_ENSURE( mrTypeModel.maShapeId.getLength() > 0, "ShapeTypeContext::ShapeTypeContext - missing shape identifier" ); + // if the o:spid attribute exists, the id attribute contains the user-defined shape name + if( bHasOspid ) + mrTypeModel.maName = rAttribs.getXString( XML_id, OUString() ); + // builtin shape type identifier + mrTypeModel.monShapeType = rAttribs.getInteger( O_TOKEN( spt ) ); + // coordinate system position/size + setCoordOrigin( rAttribs.getString( XML_coordorigin, OUString() ) ); + setCoordSize( rAttribs.getString( XML_coordsize, OUString() ) ); + // CSS style + setStyle( rAttribs.getString( XML_style, OUString() ) ); + // border line + mrTypeModel.mobStroked = rAttribs.getBool( XML_stroked ); + mrTypeModel.moStrokeColor = rAttribs.getString( XML_strokecolor ); + // shape fill + mrTypeModel.mobFilled = rAttribs.getBool( XML_filled ); + mrTypeModel.moFillColor = rAttribs.getString( XML_fillcolor ); +} + +ContextHandlerRef ShapeTypeContext::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs ) +{ + if( isRootElement() ) switch( nElement ) + { + case VML_TOKEN( imagedata ): + OptValue< OUString > oGraphicRelId = rAttribs.getString( O_TOKEN( relid ) ); + if( oGraphicRelId.has() ) + mrTypeModel.moGraphicPath = getFragmentPathFromRelId( oGraphicRelId.get() ); + mrTypeModel.moGraphicTitle = rAttribs.getString( O_TOKEN( title ) ); + break; + } + return 0; +} + +void ShapeTypeContext::setCoordOrigin( const OUString& rCoordOrigin ) +{ + OUString aCoordL, aCoordT; + if( lclSeparateValue( aCoordL, aCoordT, rCoordOrigin, ',' ) ) + { + mrTypeModel.monCoordLeft = aCoordL.toInt32(); + mrTypeModel.monCoordTop = aCoordT.toInt32(); + } +} + +void ShapeTypeContext::setCoordSize( const OUString& rCoordSize ) +{ + OUString aCoordW, aCoordH; + if( lclSeparateValue( aCoordW, aCoordH, rCoordSize, ',' ) ) + { + mrTypeModel.monCoordWidth = aCoordW.toInt32(); + mrTypeModel.monCoordHeight = aCoordH.toInt32(); + } +} + +void ShapeTypeContext::setStyle( const OUString& rStyle ) +{ + sal_Int32 nIndex = 0; + while( nIndex >= 0 ) + { + OUString aName, aValue; + if( lclSeparateValue( aName, aValue, rStyle.getToken( 0, ';', nIndex ) ) ) + { + if( aName.equalsAscii( "position" ) ) mrTypeModel.maPosition = aValue; + else if( aName.equalsAscii( "left" ) ) mrTypeModel.maLeft = aValue; + else if( aName.equalsAscii( "top" ) ) mrTypeModel.maTop = aValue; + else if( aName.equalsAscii( "width" ) ) mrTypeModel.maWidth = aValue; + else if( aName.equalsAscii( "height" ) ) mrTypeModel.maHeight = aValue; + else if( aName.equalsAscii( "margin-left" ) ) mrTypeModel.maMarginLeft = aValue; + else if( aName.equalsAscii( "margin-top" ) ) mrTypeModel.maMarginTop = aValue; + } + } +} + +// ============================================================================ + +ShapeContext::ShapeContext( ContextHandler2Helper& rParent, const AttributeList& rAttribs, ShapeBase& rShape ) : + ShapeTypeContext( rParent, rAttribs, rShape ), + mrShapeModel( rShape.getShapeModel() ) +{ + // collect shape specific attributes + mrShapeModel.maType = rAttribs.getXString( XML_type, OUString() ); + // polyline path + setPoints( rAttribs.getString( XML_points, OUString() ) ); +} + +ContextHandlerRef ShapeContext::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs ) +{ + // Excel specific shape client data + if( isRootElement() && (nElement == VMLX_TOKEN( ClientData )) ) + return new ShapeClientDataContext( *this, rAttribs, mrShapeModel.createClientData() ); + // handle remaining stuff in base class + return ShapeTypeContext::onCreateContext( nElement, rAttribs ); +} + +void ShapeContext::setPoints( const OUString& rPoints ) +{ + mrShapeModel.maPoints.clear(); + sal_Int32 nIndex = 0; + while( nIndex >= 0 ) + { + sal_Int32 nX = rPoints.getToken( 0, ',', nIndex ).toInt32(); + sal_Int32 nY = rPoints.getToken( 0, ',', nIndex ).toInt32(); + mrShapeModel.maPoints.push_back( Point( nX, nY ) ); + } +} + +// ============================================================================ + +GroupShapeContext::GroupShapeContext( ContextHandler2Helper& rParent, const AttributeList& rAttribs, GroupShape& rShape ) : + ShapeContext( rParent, rAttribs, rShape ), + mrShapes( rShape.getChildren() ) +{ +} + +ContextHandlerRef GroupShapeContext::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs ) +{ + // try to create a context of an embedded shape + ContextHandlerRef xContext = ShapeContextBase::createContext( *this, nElement, rAttribs, mrShapes ); + // handle remaining stuff of this shape in base class + return xContext.get() ? xContext : ShapeContext::onCreateContext( nElement, rAttribs ); +} + +// ============================================================================ + +} // namespace vml +} // namespace oox + diff --git a/oox/source/xls/addressconverter.cxx b/oox/source/xls/addressconverter.cxx index a5e2b7c7b64d..06bce7716967 100644 --- a/oox/source/xls/addressconverter.cxx +++ b/oox/source/xls/addressconverter.cxx @@ -590,7 +590,7 @@ bool AddressConverter::checkCellAddress( const CellAddress& rAddress, bool bTrac checkRow( rAddress.Row, bTrackOverflow ); } -bool AddressConverter::convertToCellAddressUnckecked( CellAddress& orAddress, +bool AddressConverter::convertToCellAddressUnchecked( CellAddress& orAddress, const OUString& rString, sal_Int16 nSheet ) { orAddress.Sheet = nSheet; @@ -601,7 +601,7 @@ bool AddressConverter::convertToCellAddress( CellAddress& orAddress, const OUString& rString, sal_Int16 nSheet, bool bTrackOverflow ) { return - convertToCellAddressUnckecked( orAddress, rString, nSheet ) && + convertToCellAddressUnchecked( orAddress, rString, nSheet ) && checkCellAddress( orAddress, bTrackOverflow ); } @@ -618,7 +618,7 @@ CellAddress AddressConverter::createValidCellAddress( return aAddress; } -void AddressConverter::convertToCellAddressUnckecked( CellAddress& orAddress, +void AddressConverter::convertToCellAddressUnchecked( CellAddress& orAddress, const BinAddress& rBinAddress, sal_Int16 nSheet ) { orAddress.Sheet = nSheet; @@ -629,7 +629,7 @@ void AddressConverter::convertToCellAddressUnckecked( CellAddress& orAddress, bool AddressConverter::convertToCellAddress( CellAddress& orAddress, const BinAddress& rBinAddress, sal_Int16 nSheet, bool bTrackOverflow ) { - convertToCellAddressUnckecked( orAddress, rBinAddress, nSheet ); + convertToCellAddressUnchecked( orAddress, rBinAddress, nSheet ); return checkCellAddress( orAddress, bTrackOverflow ); } diff --git a/oox/source/xls/autofiltercontext.cxx b/oox/source/xls/autofiltercontext.cxx index 42a373b3d440..4ea712c32d59 100644 --- a/oox/source/xls/autofiltercontext.cxx +++ b/oox/source/xls/autofiltercontext.cxx @@ -38,7 +38,6 @@ #include <com/sun/star/sheet/XSheetFilterDescriptor.hpp> #include <com/sun/star/sheet/FilterOperator.hpp> #include <com/sun/star/sheet/FilterConnection.hpp> -#include <com/sun/star/lang/XMultiServiceFactory.hpp> #include <com/sun/star/i18n/XLocaleData.hpp> #include "properties.hxx" #include "oox/helper/attributelist.hxx" @@ -719,7 +718,7 @@ void OoxAutoFilterContext::importCustomFilter( const AttributeList& rAttribs ) case XML_equal: case XML_notEqual: { - Reference< XLocaleData > xLocale( getBaseFilter().getGlobalFactory()->createInstance( + Reference< XLocaleData > xLocale( getGlobalFactory()->createInstance( CREATE_OUSTRING("com.sun.star.i18n.LocaleData") ), UNO_QUERY ); if ( !xLocale.is() ) diff --git a/oox/source/xls/biffhelper.cxx b/oox/source/xls/biffhelper.cxx index 6a12bf48d5a4..a12909ed9ef0 100644 --- a/oox/source/xls/biffhelper.cxx +++ b/oox/source/xls/biffhelper.cxx @@ -41,56 +41,6 @@ using ::rtl::OUStringBuffer; namespace oox { namespace xls { -// GUID ======================================================================= - -BiffGuid::BiffGuid() -{ - ::std::fill_n( mpnData, sizeof( mpnData ), 0 ); -} - -BiffGuid::BiffGuid( - sal_uInt32 nData1, sal_uInt16 nData2, sal_uInt16 nData3, - sal_uInt8 nData41, sal_uInt8 nData42, sal_uInt8 nData43, sal_uInt8 nData44, - sal_uInt8 nData45, sal_uInt8 nData46, sal_uInt8 nData47, sal_uInt8 nData48 ) -{ - // convert to little endian -> makes streaming easy - ByteOrderConverter::writeLittleEndian( mpnData, nData1 ); - ByteOrderConverter::writeLittleEndian( mpnData + 4, nData2 ); - ByteOrderConverter::writeLittleEndian( mpnData + 6, nData3 ); - mpnData[ 8 ] = nData41; - mpnData[ 9 ] = nData42; - mpnData[ 10 ] = nData43; - mpnData[ 11 ] = nData44; - mpnData[ 12 ] = nData45; - mpnData[ 13 ] = nData46; - mpnData[ 14 ] = nData47; - mpnData[ 15 ] = nData48; -} - -bool operator==( const BiffGuid& rGuid1, const BiffGuid& rGuid2 ) -{ - return ::std::equal( rGuid1.mpnData, STATIC_ARRAY_END( rGuid1.mpnData ), rGuid2.mpnData ); -} - -bool operator<( const BiffGuid& rGuid1, const BiffGuid& rGuid2 ) -{ - return ::std::lexicographical_compare( - rGuid1.mpnData, STATIC_ARRAY_END( rGuid1.mpnData ), - rGuid2.mpnData, STATIC_ARRAY_END( rGuid2.mpnData ) ); -} - -BiffInputStream& operator>>( BiffInputStream& rStrm, BiffGuid& rGuid ) -{ - rStrm.readMemory( rGuid.mpnData, 16 ); // mpnData always in little endian - return rStrm; -} - -BiffOutputStream& operator<<( BiffOutputStream& rStrm, const BiffGuid& rGuid ) -{ - rStrm.writeBlock( rGuid.mpnData, 16 ); // mpnData already in little endian - return rStrm; -} - // ============================================================================ namespace { @@ -99,6 +49,14 @@ const sal_Int32 BIFF_RK_100FLAG = 0x00000001; const sal_Int32 BIFF_RK_INTFLAG = 0x00000002; const sal_Int32 BIFF_RK_VALUEMASK = 0xFFFFFFFC; +const sal_Int32 BITMAPFILEHEADER_SIZE = 14; +const sal_Int32 BITMAPCOREHEADER_SIZE = 12; +const sal_Int32 BITMAPINFOHEADER_SIZE = 40; + +const sal_uInt16 BIFF_IMGDATA_WMF = 2; +const sal_uInt16 BIFF_IMGDATA_DIB = 9; +const sal_uInt16 BIFF_IMGDATA_NATIVE = 14; + // ---------------------------------------------------------------------------- static const struct CodePageEntry @@ -162,43 +120,7 @@ struct CodePageEntry_TEPred rtl_TextEncoding meTextEnc; }; -} // namespace - -// ============================================================================ - -const BiffGuid BiffHelper::maGuidStdHlink( - 0x79EAC9D0, 0xBAF9, 0x11CE, 0x8C, 0x82, 0x00, 0xAA, 0x00, 0x4B, 0xA9, 0x0B ); - -const BiffGuid BiffHelper::maGuidUrlMoniker( - 0x79EAC9E0, 0xBAF9, 0x11CE, 0x8C, 0x82, 0x00, 0xAA, 0x00, 0x4B, 0xA9, 0x0B ); - -const BiffGuid BiffHelper::maGuidFileMoniker( - 0x00000303, 0x0000, 0x0000, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46 ); - -// conversion ----------------------------------------------------------------- - -double BiffHelper::calcDoubleFromRk( sal_Int32 nRkValue ) -{ - double fValue = 0.0; - if( getFlag( nRkValue, BIFF_RK_INTFLAG ) ) - { - sal_Int32 nTemp = nRkValue >> 2; - setFlag< sal_Int32 >( nTemp, 0xE0000000, nRkValue < 0 ); - fValue = nTemp; - } - else - { - sal_math_Double* pDouble = reinterpret_cast< sal_math_Double* >( &fValue ); - pDouble->w32_parts.msw = static_cast< sal_uInt32 >( nRkValue & BIFF_RK_VALUEMASK ); - } - - if( getFlag( nRkValue, BIFF_RK_100FLAG ) ) - fValue /= 100.0; - - return fValue; -} - -namespace { +// ---------------------------------------------------------------------------- bool lclCalcRkFromDouble( sal_Int32& ornRkValue, double fValue ) { @@ -224,9 +146,112 @@ bool lclCalcRkFromDouble( sal_Int32& ornRkValue, double fValue ) return false; } +// ---------------------------------------------------------------------------- + +void lclImportImgDataDib( StreamDataSequence& orDataSeq, BiffInputStream& rStrm, sal_Int32 nBytes, BiffType eBiff ) +{ + /* The IMGDATA record for bitmap format contains a Windows DIB (a bitmap + file without the 'BITMAPFILEHEADER' header structure). Usually, the DIB + header consists of 12 bytes (called 'OS/2 V1 header' or + 'BITMAPCOREHEADER', see http://en.wikipedia.org/wiki/BMP_file_format) + followed by the remaining pixel data, but the 'Windows V3' or + 'BITMAPINFOHEADER' is also supported here. This function creates a + complete 'BMP file' that can be read by the OOo graphic provider used + to import graphic objects. For that, the BITMAPFILEHEADER has to be + inserted before the DIB data, and it has to contain the correct offset + to the pixel data. Currently, in real life there are only 24-bit and + 32-bit DIBs (without color palette) in use. This code relies on this + fact and calculates the offset to the pixel data according to the size + of the DIB header. + Remaining tasks are (if really used somewhere): + - Support of DIBs with color palette, + - Support of 'Windows V4' and 'Windows V5' DIB header. */ + + // read and check validity of DIB header + sal_Int64 nInStrmPos = rStrm.tell(); + sal_Int32 nDibHdrSize = rStrm.readInt32(); + sal_uInt16 nPlanes = 0, nDepth = 0; + switch( nDibHdrSize ) + { + case BITMAPCOREHEADER_SIZE: + rStrm.skip( 4 ); // width/height as 16-bit integer + rStrm >> nPlanes >> nDepth; + break; + case BITMAPINFOHEADER_SIZE: + rStrm.skip( 8 ); // width/height as 32-bit integer + rStrm >> nPlanes >> nDepth; + break; + } + rStrm.seek( nInStrmPos ); + + if( (nPlanes == 1) && ((nDepth == 24) || (nDepth == 32)) ) + { + // allocate enough space for the BITMAPFILEHEADER and the DIB data + orDataSeq.realloc( BITMAPFILEHEADER_SIZE + nBytes ); + SequenceOutputStream aOutStrm( orDataSeq ); + + // write the BITMAPFILEHEADER of a regular BMP file + sal_Int32 nBmpSize = BITMAPFILEHEADER_SIZE + nBytes; + sal_Int32 nOffset = BITMAPFILEHEADER_SIZE + nDibHdrSize; + aOutStrm << sal_uInt16( 0x4D42 ) << nBmpSize << sal_Int32( 0 ) << nOffset; + + // copy the DIB header + aOutStrm.copyStream( rStrm, nDibHdrSize ); + nBytes -= nDibHdrSize; + + /* Excel 3.x and Excel 4.x seem to write broken or out-dated DIB data. + Usually they write a BITMAPCOREHEADER containing width, height, + planes as usual. The pixel depth field is set to 32 bit (though + this is not allowed according to documentation). Between that + header and the actual pixel data, 3 unused bytes are inserted. This + does even confuse Excel 5.x and later, which cannot read the image + data correctly. */ + if( (eBiff <= BIFF4) && (nDibHdrSize == BITMAPCOREHEADER_SIZE) && (nDepth == 32) ) + { + // skip the dummy bytes in input stream + rStrm.skip( 3 ); + nBytes -= 3; + // correct the total BMP file size in output stream + sal_Int64 nOutStrmPos = aOutStrm.tell(); + aOutStrm.seek( 2 ); + aOutStrm << sal_Int32( nBmpSize - 3 ); + aOutStrm.seek( nOutStrmPos ); + } + + // copy remaining pixel data top output stream + aOutStrm.copyStream( rStrm, nBytes ); + } + rStrm.seek( nInStrmPos + nBytes ); +} + } // namespace -bool BiffHelper::calcRkFromDouble( sal_Int32& ornRkValue, double fValue ) +// ============================================================================ + +// conversion ----------------------------------------------------------------- + +/*static*/ double BiffHelper::calcDoubleFromRk( sal_Int32 nRkValue ) +{ + double fValue = 0.0; + if( getFlag( nRkValue, BIFF_RK_INTFLAG ) ) + { + sal_Int32 nTemp = nRkValue >> 2; + setFlag< sal_Int32 >( nTemp, 0xE0000000, nRkValue < 0 ); + fValue = nTemp; + } + else + { + sal_math_Double* pDouble = reinterpret_cast< sal_math_Double* >( &fValue ); + pDouble->w32_parts.msw = static_cast< sal_uInt32 >( nRkValue & BIFF_RK_VALUEMASK ); + } + + if( getFlag( nRkValue, BIFF_RK_100FLAG ) ) + fValue /= 100.0; + + return fValue; +} + +/*static*/ bool BiffHelper::calcRkFromDouble( sal_Int32& ornRkValue, double fValue ) { if( lclCalcRkFromDouble( ornRkValue, fValue ) ) return true; @@ -240,7 +265,7 @@ bool BiffHelper::calcRkFromDouble( sal_Int32& ornRkValue, double fValue ) return false; } -double BiffHelper::calcDoubleFromError( sal_uInt8 nErrorCode ) +/*static*/ double BiffHelper::calcDoubleFromError( sal_uInt8 nErrorCode ) { sal_uInt16 nApiError = 0x7FFF; switch( nErrorCode ) @@ -260,7 +285,7 @@ double BiffHelper::calcDoubleFromError( sal_uInt8 nErrorCode ) return fValue; } -rtl_TextEncoding BiffHelper::calcTextEncodingFromCodePage( sal_uInt16 nCodePage ) +/*static*/ rtl_TextEncoding BiffHelper::calcTextEncodingFromCodePage( sal_uInt16 nCodePage ) { const CodePageEntry* pEntry = ::std::find_if( spCodePages, STATIC_ARRAY_END( spCodePages ), CodePageEntry_CPPred( nCodePage ) ); if( pEntry == STATIC_ARRAY_END( spCodePages ) ) @@ -271,7 +296,7 @@ rtl_TextEncoding BiffHelper::calcTextEncodingFromCodePage( sal_uInt16 nCodePage return pEntry->meTextEnc; } -sal_uInt16 BiffHelper::calcCodePageFromTextEncoding( rtl_TextEncoding eTextEnc ) +/*static*/ sal_uInt16 BiffHelper::calcCodePageFromTextEncoding( rtl_TextEncoding eTextEnc ) { const CodePageEntry* pEntry = ::std::find_if( spCodePages, STATIC_ARRAY_END( spCodePages ), CodePageEntry_TEPred( eTextEnc ) ); if( pEntry == STATIC_ARRAY_END( spCodePages ) ) @@ -282,6 +307,25 @@ sal_uInt16 BiffHelper::calcCodePageFromTextEncoding( rtl_TextEncoding eTextEnc ) return pEntry->mnCodePage; } +/*static*/ void BiffHelper::importImgData( StreamDataSequence& orDataSeq, BiffInputStream& rStrm, BiffType eBiff ) +{ + sal_uInt16 nFormat, nEnv; + sal_Int32 nBytes; + rStrm >> nFormat >> nEnv >> nBytes; + OSL_ENSURE( (nFormat == BIFF_IMGDATA_WMF) || (nFormat == BIFF_IMGDATA_DIB) || (nFormat == BIFF_IMGDATA_NATIVE), "BiffHelper::importImgData - unknown format" ); + OSL_ENSURE( nBytes > 0, "BiffHelper::importImgData - invalid data size" ); + if( (0 < nBytes) && (nBytes <= rStrm.getRemaining()) ) + { + switch( nFormat ) + { + case BIFF_IMGDATA_WMF: /* TODO */ break; + case BIFF_IMGDATA_DIB: lclImportImgDataDib( orDataSeq, rStrm, nBytes, eBiff ); break; + case BIFF_IMGDATA_NATIVE: /* TODO */ break; + default: OSL_ENSURE( false, "BiffHelper::importImgData - unknown image format" ); + } + } +} + // ============================================================================ } // namespace xls diff --git a/oox/source/xls/biffinputstream.cxx b/oox/source/xls/biffinputstream.cxx index d19b62de27a6..681b751279fc 100644 --- a/oox/source/xls/biffinputstream.cxx +++ b/oox/source/xls/biffinputstream.cxx @@ -176,8 +176,7 @@ BiffInputStream::BiffInputStream( BinaryInputStream& rInStream, bool bContLookup mnCurrRecSize( 0 ), mnComplRecSize( 0 ), mbHasComplRec( false ), - mbCont( bContLookup ), - mbNulChars( false ) + mbCont( bContLookup ) { mbEof = true; // EOF will be true if stream is not inside a record } @@ -361,32 +360,15 @@ void BiffInputStream::skip( sal_Int32 nBytes ) // byte strings --------------------------------------------------------------- -OString BiffInputStream::readCharArray( sal_uInt16 nChars ) +OString BiffInputStream::readByteString( bool b16BitLen, bool bAllowNulChars ) { - if( nChars == 0 ) - return OString(); - - ::std::vector< sal_Char > aBuffer( static_cast< size_t >( nChars ) ); - size_t nCharsRead = static_cast< size_t >( readMemory( &aBuffer.front(), nChars ) ); - if( !mbNulChars ) - ::std::replace( aBuffer.begin(), aBuffer.begin() + nCharsRead, '\0', '?' ); - return OString( &aBuffer.front(), nCharsRead ); + sal_Int32 nStrLen = b16BitLen ? readuInt16() : readuInt8(); + return readCharArray( nStrLen, bAllowNulChars ); } -OUString BiffInputStream::readCharArray( sal_uInt16 nChars, rtl_TextEncoding eTextEnc ) +OUString BiffInputStream::readByteStringUC( bool b16BitLen, rtl_TextEncoding eTextEnc, bool bAllowNulChars ) { - return OStringToOUString( readCharArray( nChars ), eTextEnc ); -} - -OString BiffInputStream::readByteString( bool b16BitLen ) -{ - sal_uInt16 nStrLen = b16BitLen ? readuInt16() : readuInt8(); - return readCharArray( nStrLen ); -} - -OUString BiffInputStream::readByteString( bool b16BitLen, rtl_TextEncoding eTextEnc ) -{ - return OStringToOUString( readByteString( b16BitLen ), eTextEnc ); + return OStringToOUString( readByteString( b16BitLen, bAllowNulChars ), eTextEnc ); } void BiffInputStream::skipByteString( bool b16BitLen ) @@ -396,22 +378,7 @@ void BiffInputStream::skipByteString( bool b16BitLen ) // Unicode strings ------------------------------------------------------------ -OUString BiffInputStream::readNulUnicodeArray() -{ - OUStringBuffer aBuffer; - for( sal_uInt16 nChar = readuInt16(); !mbEof && (nChar > 0); readValue( nChar ) ) - aBuffer.append( static_cast< sal_Unicode >( nChar ) ); - return aBuffer.makeStringAndClear(); -} - -OUString BiffInputStream::readUnicodeArray( sal_uInt16 nChars ) -{ - OUStringBuffer aBuffer; - appendUnicodeArray( aBuffer, nChars, true ); - return aBuffer.makeStringAndClear(); -} - -OUString BiffInputStream::readUniStringChars( sal_uInt16 nChars, bool b16Bit ) +OUString BiffInputStream::readUniStringChars( sal_uInt16 nChars, bool b16BitChars, bool bAllowNulChars ) { OUStringBuffer aBuffer; aBuffer.ensureCapacity( nChars ); @@ -422,7 +389,7 @@ OUString BiffInputStream::readUniStringChars( sal_uInt16 nChars, bool b16Bit ) while( !mbEof && (nCharsLeft > 0) ) { sal_uInt16 nPortionCount = 0; - if( b16Bit ) + if( b16BitChars ) { nPortionCount = ::std::min< sal_uInt16 >( nCharsLeft, maRecBuffer.getRecLeft() / 2 ); OSL_ENSURE( (nPortionCount <= nCharsLeft) || ((maRecBuffer.getRecLeft() & 1) == 0), @@ -434,39 +401,39 @@ OUString BiffInputStream::readUniStringChars( sal_uInt16 nChars, bool b16Bit ) } // read the character array - appendUnicodeArray( aBuffer, nPortionCount, b16Bit ); + appendUnicodeArray( aBuffer, nPortionCount, b16BitChars, bAllowNulChars ); // prepare for next CONTINUE record nCharsLeft = nCharsLeft - nPortionCount; if( nCharsLeft > 0 ) - jumpToNextStringContinue( b16Bit ); + jumpToNextStringContinue( b16BitChars ); } return aBuffer.makeStringAndClear(); } -OUString BiffInputStream::readUniString( sal_uInt16 nChars ) +OUString BiffInputStream::readUniStringBody( sal_uInt16 nChars, bool bAllowNulChars ) { - bool b16Bit; + bool b16BitChars; sal_Int32 nAddSize; - readUniStringHeader( b16Bit, nAddSize ); - OUString aString = readUniStringChars( nChars, b16Bit ); + readUniStringHeader( b16BitChars, nAddSize ); + OUString aString = readUniStringChars( nChars, b16BitChars, bAllowNulChars ); skip( nAddSize ); return aString; } -OUString BiffInputStream::readUniString() +OUString BiffInputStream::readUniString( bool bAllowNulChars ) { - return readUniString( readuInt16() ); + return readUniStringBody( readuInt16(), bAllowNulChars ); } -void BiffInputStream::skipUniStringChars( sal_uInt16 nChars, bool b16Bit ) +void BiffInputStream::skipUniStringChars( sal_uInt16 nChars, bool b16BitChars ) { sal_uInt16 nCharsLeft = nChars; while( !mbEof && (nCharsLeft > 0) ) { sal_uInt16 nPortionCount; - if( b16Bit ) + if( b16BitChars ) { nPortionCount = ::std::min< sal_uInt16 >( nCharsLeft, maRecBuffer.getRecLeft() / 2 ); OSL_ENSURE( (nPortionCount <= nCharsLeft) || ((maRecBuffer.getRecLeft() & 1) == 0), @@ -482,22 +449,22 @@ void BiffInputStream::skipUniStringChars( sal_uInt16 nChars, bool b16Bit ) // prepare for next CONTINUE record nCharsLeft = nCharsLeft - nPortionCount; if( nCharsLeft > 0 ) - jumpToNextStringContinue( b16Bit ); + jumpToNextStringContinue( b16BitChars ); } } -void BiffInputStream::skipUniString( sal_uInt16 nChars ) +void BiffInputStream::skipUniStringBody( sal_uInt16 nChars ) { - bool b16Bit; + bool b16BitChars; sal_Int32 nAddSize; - readUniStringHeader( b16Bit, nAddSize ); - skipUniStringChars( nChars, b16Bit ); + readUniStringHeader( b16BitChars, nAddSize ); + skipUniStringChars( nChars, b16BitChars ); skip( nAddSize ); } void BiffInputStream::skipUniString() { - skipUniString( readuInt16() ); + skipUniStringBody( readuInt16() ); } // private -------------------------------------------------------------------- @@ -517,7 +484,6 @@ void BiffInputStream::setupRecord() mnAltContId = BIFF_ID_UNKNOWN; mnCurrRecSize = mnComplRecSize = maRecBuffer.getRecSize(); mbHasComplRec = !mbCont; - mbNulChars = false; mbEof = !isInRecord(); // enable decoder in new record enableDecoder( true ); @@ -561,7 +527,7 @@ bool BiffInputStream::jumpToNextContinue() return !mbEof; } -bool BiffInputStream::jumpToNextStringContinue( bool& rb16Bit ) +bool BiffInputStream::jumpToNextStringContinue( bool& rb16BitChars ) { OSL_ENSURE( maRecBuffer.getRecLeft() == 0, "BiffInputStream::jumpToNextStringContinue - unexpected garbage" ); @@ -582,7 +548,7 @@ bool BiffInputStream::jumpToNextStringContinue( bool& rb16Bit ) // trying to read the flags invalidates stream, if no CONTINUE record has been found sal_uInt8 nFlags; readValue( nFlags ); - rb16Bit = getFlag( nFlags, BIFF_STRF_16BIT ); + rb16BitChars = getFlag( nFlags, BIFF_STRF_16BIT ); return !mbEof; } @@ -611,22 +577,22 @@ sal_uInt16 BiffInputStream::getMaxRawReadSize( sal_Int32 nBytes ) const return getLimitedValue< sal_uInt16, sal_Int32 >( nBytes, 0, maRecBuffer.getRecLeft() ); } -void BiffInputStream::appendUnicodeArray( OUStringBuffer& orBuffer, sal_uInt16 nChars, bool b16Bit ) +void BiffInputStream::appendUnicodeArray( OUStringBuffer& orBuffer, sal_uInt16 nChars, bool b16BitChars, bool bAllowNulChars ) { orBuffer.ensureCapacity( orBuffer.getLength() + nChars ); sal_uInt16 nChar; for( sal_uInt16 nCharIdx = 0; !mbEof && (nCharIdx < nChars); ++nCharIdx ) { - if( b16Bit ) readValue( nChar ); else nChar = readuInt8(); - orBuffer.append( static_cast< sal_Unicode >( (!mbNulChars && (nChar == 0)) ? '?' : nChar ) ); + if( b16BitChars ) readValue( nChar ); else nChar = readuInt8(); + orBuffer.append( static_cast< sal_Unicode >( (!bAllowNulChars && (nChar == 0)) ? '?' : nChar ) ); } } -void BiffInputStream::readUniStringHeader( bool& orb16Bit, sal_Int32& ornAddSize ) +void BiffInputStream::readUniStringHeader( bool& orb16BitChars, sal_Int32& ornAddSize ) { sal_uInt8 nFlags = readuInt8(); OSL_ENSURE( !getFlag( nFlags, BIFF_STRF_UNKNOWN ), "BiffInputStream::readUniStringHeader - unknown flags" ); - orb16Bit = getFlag( nFlags, BIFF_STRF_16BIT ); + orb16BitChars = getFlag( nFlags, BIFF_STRF_16BIT ); sal_uInt16 nFontCount = getFlag( nFlags, BIFF_STRF_RICH ) ? readuInt16() : 0; sal_Int32 nPhoneticSize = getFlag( nFlags, BIFF_STRF_PHONETIC ) ? readInt32() : 0; ornAddSize = 4 * nFontCount + ::std::max< sal_Int32 >( 0, nPhoneticSize ); diff --git a/oox/source/xls/condformatbuffer.cxx b/oox/source/xls/condformatbuffer.cxx index 99ac65bc1bcc..a546cb37d282 100644 --- a/oox/source/xls/condformatbuffer.cxx +++ b/oox/source/xls/condformatbuffer.cxx @@ -452,17 +452,19 @@ void CondFormatRule::finalizeImport( const Reference< XSheetConditionalEntries > /* Replacement formula for unsupported rule types (text comparison rules, time period rules, cell type rules). The replacement formulas below may contain several placeholders: - - '#B' will be replaced by the current relative base address (may - occur several times). - - '#R' will be replaced by the entire range list of the conditional + - '#B' will be replaced by the current relative base address (may occur + several times). + - '#R' will be replaced by the entire range list of the conditional formatting (absolute addresses). - - '#T' will be replaced by the quoted comparison text. - - '#L' will be replaced by the length of the comparison text (from + - '#T' will be replaced by the quoted comparison text. + - '#L' will be replaced by the length of the comparison text (from the 'text' attribute) used in text comparison rules. - - '#K' will be replaced by the rank (from the 'rank' attribute) used - in top-10 rules. - - '#M' will be replaced by the top/bottom flag (from the 'bottom' + - '#K' will be replaced by the rank (from the 'rank' attribute) used in + top-10 rules. + - '#M' will be replaced by the top/bottom flag (from the 'bottom' attribute) used in the RANK function in top-10 rules. + - '#C' will be replaced by one of the comparison operators <, >, <=, or + >=, according to the 'aboveAverage' and 'equalAverage' flags. */ OUString aReplaceFormula; @@ -548,18 +550,13 @@ void CondFormatRule::finalizeImport( const Reference< XSheetConditionalEntries > break; case XML_aboveAverage: if( maModel.mnStdDev == 0 ) - { - if( maModel.mbAboveAverage ) - aReplaceFormula = maModel.mbEqualAverage ? CREATE_OUSTRING( "#B>=AVERAGE(#R)" ) : CREATE_OUSTRING( "#B>AVERAGE(#R)" ); - else - aReplaceFormula = maModel.mbEqualAverage ? CREATE_OUSTRING( "#B<=AVERAGE(#R)" ) : CREATE_OUSTRING( "#B<AVERAGE(#R)" ); - } + aReplaceFormula = CREATE_OUSTRING( "#B#CAVERAGE(#R)" ); break; } if( aReplaceFormula.getLength() > 0 ) { - OUString aAddress, aRanges, aText; + OUString aAddress, aRanges, aText, aComp; sal_Int32 nStrPos = aReplaceFormula.getLength(); while( (nStrPos = aReplaceFormula.lastIndexOf( '#', nStrPos )) >= 0 ) { @@ -593,6 +590,13 @@ void CondFormatRule::finalizeImport( const Reference< XSheetConditionalEntries > aReplaceFormula = aReplaceFormula.replaceAt( nStrPos, 2, OUString::valueOf( static_cast< sal_Int32 >( maModel.mbBottom ? 1 : 0 ) ) ); break; + case 'C': // average comparison operator + if( aComp.getLength() == 0 ) + aComp = maModel.mbAboveAverage ? + (maModel.mbEqualAverage ? CREATE_OUSTRING( ">=" ) : CREATE_OUSTRING( ">" )) : + (maModel.mbEqualAverage ? CREATE_OUSTRING( "<=" ) : CREATE_OUSTRING( "<" )); + aReplaceFormula = aReplaceFormula.replaceAt( nStrPos, 2, aComp ); + break; default: OSL_ENSURE( false, "CondFormatRule::finalizeImport - unknown placeholder" ); } @@ -702,7 +706,7 @@ void CondFormat::finalizeImport() if( xEntries.is() ) { // maRules is sorted by rule priority - maRules.forEachMem( &CondFormatRule::finalizeImport, xEntries ); + maRules.forEachMem( &CondFormatRule::finalizeImport, ::boost::cref( xEntries ) ); aPropSet.setProperty( PROP_ConditionalFormat, xEntries ); } } diff --git a/oox/source/xls/defnamesbuffer.cxx b/oox/source/xls/defnamesbuffer.cxx index 0d03c93d21a6..786d0cd41334 100644 --- a/oox/source/xls/defnamesbuffer.cxx +++ b/oox/source/xls/defnamesbuffer.cxx @@ -301,7 +301,7 @@ DefinedName::DefinedName( const WorkbookHelper& rHelper, sal_Int32 nLocalSheet ) void DefinedName::importDefinedName( const AttributeList& rAttribs ) { - maModel.maName = rAttribs.getString( XML_name, OUString() ); + maModel.maName = rAttribs.getXString( XML_name, OUString() ); maModel.mnSheet = rAttribs.getInteger( XML_localSheetId, -1 ); maModel.mnFuncGroupId = rAttribs.getInteger( XML_functionGroupId, -1 ); maModel.mbMacro = rAttribs.getBool( XML_xlm, false ); @@ -359,7 +359,6 @@ void DefinedName::importDefinedName( BiffInputStream& rStrm ) sal_Int16 nTabId = BIFF_DEFNAME_GLOBAL; sal_uInt8 nNameLen = 0, nShortCut = 0; - rStrm.enableNulChars( true ); switch( eBiff ) { case BIFF2: @@ -370,27 +369,26 @@ void DefinedName::importDefinedName( BiffInputStream& rStrm ) rStrm >> nShortCut >> nNameLen; mnFmlaSize = rStrm.readuInt8(); setFlag( nFlags, BIFF_DEFNAME_FUNC, getFlag( nFlagsBiff2, BIFF2_DEFNAME_FUNC ) ); - maModel.maName = rStrm.readCharArray( nNameLen, getTextEncoding() ); + maModel.maName = rStrm.readCharArrayUC( nNameLen, getTextEncoding(), true ); } break; case BIFF3: case BIFF4: rStrm >> nFlags >> nShortCut >> nNameLen >> mnFmlaSize; - maModel.maName = rStrm.readCharArray( nNameLen, getTextEncoding() ); + maModel.maName = rStrm.readCharArrayUC( nNameLen, getTextEncoding(), true ); break; case BIFF5: rStrm >> nFlags >> nShortCut >> nNameLen >> mnFmlaSize >> nRefId >> nTabId; rStrm.skip( 4 ); - maModel.maName = rStrm.readCharArray( nNameLen, getTextEncoding() ); + maModel.maName = rStrm.readCharArrayUC( nNameLen, getTextEncoding(), true ); break; case BIFF8: rStrm >> nFlags >> nShortCut >> nNameLen >> mnFmlaSize >> nRefId >> nTabId; rStrm.skip( 4 ); - maModel.maName = rStrm.readUniString( nNameLen ); + maModel.maName = rStrm.readUniStringBody( nNameLen, true ); break; case BIFF_UNKNOWN: break; } - rStrm.enableNulChars( false ); // macro function/command, hidden flag maModel.mnFuncGroupId = extractValue< sal_Int32 >( nFlags, 6, 6 ); @@ -510,7 +508,7 @@ void DefinedName::convertFormula() { Reference< XPrintAreas > xPrintAreas( getSheetFromDoc( maModel.mnSheet ), UNO_QUERY ); ApiCellRangeList aPrintRanges; - getFormulaParser().extractCellRangeList( aPrintRanges, xTokens->getTokens(), maModel.mnSheet ); + getFormulaParser().extractCellRangeList( aPrintRanges, xTokens->getTokens(), false, maModel.mnSheet ); if( xPrintAreas.is() && !aPrintRanges.empty() ) xPrintAreas->setPrintAreas( ContainerHelper::vectorToSequence( aPrintRanges ) ); } @@ -519,7 +517,7 @@ void DefinedName::convertFormula() { Reference< XPrintAreas > xPrintAreas( getSheetFromDoc( maModel.mnSheet ), UNO_QUERY ); ApiCellRangeList aTitleRanges; - getFormulaParser().extractCellRangeList( aTitleRanges, xTokens->getTokens(), maModel.mnSheet ); + getFormulaParser().extractCellRangeList( aTitleRanges, xTokens->getTokens(), false, maModel.mnSheet ); if( xPrintAreas.is() && !aTitleRanges.empty() ) { bool bHasRowTitles = false; @@ -561,7 +559,7 @@ bool DefinedName::getAbsoluteRange( CellRangeAddress& orRange ) const /* ScNamedRangeObj::XCellRangeReferrer::getReferredCells is buggy with relative references, so we extract an absolute reference by hand. */ Reference< XFormulaTokens > xTokens( mxNamedRange, UNO_QUERY ); - return xTokens.is() && getFormulaParser().extractAbsoluteRange( orRange, xTokens->getTokens() ); + return xTokens.is() && getFormulaParser().extractCellRange( orRange, xTokens->getTokens(), false ); } void DefinedName::implImportOoxFormula( FormulaContext& rContext ) diff --git a/oox/source/xls/drawingfragment.cxx b/oox/source/xls/drawingfragment.cxx index 9de5d6f29033..14973af544df 100644 --- a/oox/source/xls/drawingfragment.cxx +++ b/oox/source/xls/drawingfragment.cxx @@ -30,23 +30,41 @@ #include "oox/xls/drawingfragment.hxx" #include <com/sun/star/awt/Point.hpp> -#include <com/sun/star/drawing/XDrawPageSupplier.hpp> +#include <com/sun/star/beans/NamedValue.hpp> +#include <com/sun/star/form/binding/XBindableValue.hpp> +#include <com/sun/star/form/binding/XListEntrySink.hpp> +#include <com/sun/star/form/binding/XListEntrySource.hpp> +#include <com/sun/star/form/binding/XValueBinding.hpp> +#include "properties.hxx" #include "oox/helper/attributelist.hxx" +#include "oox/helper/propertyset.hxx" #include "oox/drawingml/connectorshapecontext.hxx" #include "oox/drawingml/graphicshapecontext.hxx" #include "oox/drawingml/shapecontext.hxx" #include "oox/drawingml/shapegroupcontext.hxx" +#include "oox/vml/vmlshape.hxx" +#include "oox/xls/formulaparser.hxx" #include "oox/xls/themebuffer.hxx" #include "oox/xls/unitconverter.hxx" using ::rtl::OUString; +using ::com::sun::star::uno::Any; +using ::com::sun::star::uno::Exception; using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Sequence; using ::com::sun::star::uno::UNO_QUERY; +using ::com::sun::star::uno::UNO_QUERY_THROW; +using ::com::sun::star::beans::NamedValue; using ::com::sun::star::awt::Point; -using ::com::sun::star::awt::Size; using ::com::sun::star::awt::Rectangle; -using ::com::sun::star::drawing::XDrawPageSupplier; +using ::com::sun::star::awt::Size; +using ::com::sun::star::awt::XControlModel; +using ::com::sun::star::form::binding::XBindableValue; +using ::com::sun::star::form::binding::XListEntrySink; +using ::com::sun::star::form::binding::XListEntrySource; +using ::com::sun::star::form::binding::XValueBinding; using ::com::sun::star::table::CellAddress; +using ::com::sun::star::table::CellRangeAddress; using ::oox::core::ContextHandlerRef; using ::oox::drawingml::ConnectorShapeContext; using ::oox::drawingml::GraphicalObjectFrameContext; @@ -55,12 +73,26 @@ using ::oox::drawingml::Shape; using ::oox::drawingml::ShapePtr; using ::oox::drawingml::ShapeContext; using ::oox::drawingml::ShapeGroupContext; +// no using's for ::oox::vml, that may clash with ::oox::drawingml types namespace oox { namespace xls { // ============================================================================ +namespace { + +/** Converts the passed 64-bit integer value from the passed unit to EMUs. */ +sal_Int64 lclCalcEmu( const UnitConverter& rUnitConv, sal_Int64 nValue, Unit eFromUnit ) +{ + return (eFromUnit == UNIT_EMU) ? nValue : + static_cast< sal_Int64 >( rUnitConv.scaleValue( static_cast< double >( nValue ), eFromUnit, UNIT_EMU ) + 0.5 ); +} + +} // namespace + +// ============================================================================ + AnchorCellModel::AnchorCellModel() : mnCol( -1 ), mnRow( -1 ), @@ -108,15 +140,15 @@ void ShapeAnchor::importAnchor( sal_Int32 nElement, const AttributeList& rAttrib void ShapeAnchor::importPos( const AttributeList& rAttribs ) { OSL_ENSURE( meType == ANCHOR_ABSOLUTE, "ShapeAnchor::importPos - unexpected 'xdr:pos' element" ); - maPos.X = rAttribs.getInteger64( XML_x, 0 ); - maPos.Y = rAttribs.getInteger64( XML_y, 0 ); + maPos.X = rAttribs.getHyper( XML_x, 0 ); + maPos.Y = rAttribs.getHyper( XML_y, 0 ); } void ShapeAnchor::importExt( const AttributeList& rAttribs ) { OSL_ENSURE( (meType == ANCHOR_ABSOLUTE) || (meType == ANCHOR_ONECELL), "ShapeAnchor::importExt - unexpected 'xdr:ext' element" ); - maSize.Width = rAttribs.getInteger64( XML_cx, 0 ); - maSize.Height = rAttribs.getInteger64( XML_cy, 0 ); + maSize.Width = rAttribs.getHyper( XML_cx, 0 ); + maSize.Height = rAttribs.getHyper( XML_cy, 0 ); } void ShapeAnchor::importClientData( const AttributeList& rAttribs ) @@ -151,6 +183,29 @@ void ShapeAnchor::setCellPos( sal_Int32 nElement, sal_Int32 nParentContext, cons } } +void ShapeAnchor::importVmlAnchor( const OUString& rAnchor ) +{ + meType = ANCHOR_VML; + + ::std::vector< OUString > aTokens; + sal_Int32 nIndex = 0; + while( nIndex >= 0 ) + aTokens.push_back( rAnchor.getToken( 0, ',', nIndex ).trim() ); + + OSL_ENSURE( aTokens.size() >= 8, "ShapeAnchor::importVmlAnchor - missing anchor tokens" ); + if( aTokens.size() >= 8 ) + { + maFrom.mnCol = aTokens[ 0 ].toInt32(); + maFrom.mnColOffset = aTokens[ 1 ].toInt32(); + maFrom.mnRow = aTokens[ 2 ].toInt32(); + maFrom.mnRowOffset = aTokens[ 3 ].toInt32(); + maTo.mnCol = aTokens[ 4 ].toInt32(); + maTo.mnColOffset = aTokens[ 5 ].toInt32(); + maTo.mnRow = aTokens[ 6 ].toInt32(); + maTo.mnRowOffset = aTokens[ 7 ].toInt32(); + } +} + bool ShapeAnchor::isValidAnchor() const { bool bValid = false; @@ -167,6 +222,7 @@ bool ShapeAnchor::isValidAnchor() const bValid = maFrom.isValid() && maSize.isValid() && (maSize.Width > 0) && (maSize.Height > 0); break; case ANCHOR_TWOCELL: + case ANCHOR_VML: OSL_ENSURE( maFrom.isValid(), "ShapeAnchor::isValidAnchor - invalid from position" ); OSL_ENSURE( maTo.isValid(), "ShapeAnchor::isValidAnchor - invalid to position" ); bValid = maFrom.isValid() && maTo.isValid() && @@ -180,12 +236,13 @@ bool ShapeAnchor::isValidAnchor() const return bValid; } -#if 0 // unused code Rectangle ShapeAnchor::calcApiLocation( const Size& rApiSheetSize, const AnchorSizeModel& rEmuSheetSize ) const { AddressConverter& rAddrConv = getAddressConverter(); UnitConverter& rUnitConv = getUnitConverter(); Rectangle aApiLoc( -1, -1, -1, -1 ); + Unit eUnitX = (meType == ANCHOR_VML) ? UNIT_SCREENX : UNIT_EMU; + Unit eUnitY = (meType == ANCHOR_VML) ? UNIT_SCREENY : UNIT_EMU; // calculate shape position switch( meType ) @@ -200,12 +257,13 @@ Rectangle ShapeAnchor::calcApiLocation( const Size& rApiSheetSize, const AnchorS break; case ANCHOR_ONECELL: case ANCHOR_TWOCELL: + case ANCHOR_VML: OSL_ENSURE( maFrom.isValid(), "ShapeAnchor::calcApiLocation - invalid position" ); if( maFrom.isValid() && rAddrConv.checkCol( maFrom.mnCol, true ) && rAddrConv.checkRow( maFrom.mnRow, true ) ) { Point aPoint = getCellPosition( maFrom.mnCol, maFrom.mnRow ); - aApiLoc.X = aPoint.X + rUnitConv.scaleToMm100( static_cast< double >( maFrom.mnColOffset ), UNIT_EMU ); - aApiLoc.Y = aPoint.Y + rUnitConv.scaleToMm100( static_cast< double >( maFrom.mnRowOffset ), UNIT_EMU ); + aApiLoc.X = aPoint.X + rUnitConv.scaleToMm100( static_cast< double >( maFrom.mnColOffset ), eUnitX ); + aApiLoc.Y = aPoint.Y + rUnitConv.scaleToMm100( static_cast< double >( maFrom.mnRowOffset ), eUnitY ); } break; case ANCHOR_INVALID: @@ -230,6 +288,7 @@ Rectangle ShapeAnchor::calcApiLocation( const Size& rApiSheetSize, const AnchorS } break; case ANCHOR_TWOCELL: + case ANCHOR_VML: OSL_ENSURE( maTo.isValid(), "ShapeAnchor::calcApiLocation - invalid position" ); if( maTo.isValid() ) { @@ -241,14 +300,14 @@ Rectangle ShapeAnchor::calcApiLocation( const Size& rApiSheetSize, const AnchorS aApiLoc.Width = rApiSheetSize.Width - aApiLoc.X; if( aToCell.Column == maTo.mnCol ) { - aPoint.X += rUnitConv.scaleToMm100( static_cast< double >( maTo.mnColOffset ), UNIT_EMU ); + aPoint.X += rUnitConv.scaleToMm100( static_cast< double >( maTo.mnColOffset ), eUnitX ); aApiLoc.Width = ::std::min< sal_Int32 >( aPoint.X - aApiLoc.X + 1, aApiLoc.Width ); } // height aApiLoc.Height = rApiSheetSize.Height - aApiLoc.Y; if( aToCell.Row == maTo.mnRow ) { - aPoint.Y += rUnitConv.scaleToMm100( static_cast< double >( maTo.mnRowOffset ), UNIT_EMU ); + aPoint.Y += rUnitConv.scaleToMm100( static_cast< double >( maTo.mnRowOffset ), eUnitY ); aApiLoc.Height = ::std::min< sal_Int32 >( aPoint.Y - aApiLoc.Y + 1, aApiLoc.Height ); } } @@ -259,7 +318,6 @@ Rectangle ShapeAnchor::calcApiLocation( const Size& rApiSheetSize, const AnchorS return aApiLoc; } -#endif Rectangle ShapeAnchor::calcEmuLocation( const AnchorSizeModel& rEmuSheetSize ) const { @@ -270,6 +328,8 @@ Rectangle ShapeAnchor::calcEmuLocation( const AnchorSizeModel& rEmuSheetSize ) c getLimitedValue< sal_Int32, sal_Int64 >( rEmuSheetSize.Width, 0, SAL_MAX_INT32 ), getLimitedValue< sal_Int32, sal_Int64 >( rEmuSheetSize.Height, 0, SAL_MAX_INT32 ) ); Rectangle aLoc( -1, -1, -1, -1 ); + Unit eUnitX = (meType == ANCHOR_VML) ? UNIT_SCREENX : UNIT_EMU; + Unit eUnitY = (meType == ANCHOR_VML) ? UNIT_SCREENY : UNIT_EMU; // calculate shape position switch( meType ) @@ -284,12 +344,13 @@ Rectangle ShapeAnchor::calcEmuLocation( const AnchorSizeModel& rEmuSheetSize ) c break; case ANCHOR_ONECELL: case ANCHOR_TWOCELL: + case ANCHOR_VML: OSL_ENSURE( maFrom.isValid(), "ShapeAnchor::calcEmuLocation - invalid position" ); if( maFrom.isValid() && rAddrConv.checkCol( maFrom.mnCol, true ) && rAddrConv.checkRow( maFrom.mnRow, true ) ) { Point aPoint = getCellPosition( maFrom.mnCol, maFrom.mnRow ); - sal_Int64 nX = static_cast< sal_Int64 >( rUnitConv.scaleFromMm100( aPoint.X, UNIT_EMU ) ) + maFrom.mnColOffset; - sal_Int64 nY = static_cast< sal_Int64 >( rUnitConv.scaleFromMm100( aPoint.Y, UNIT_EMU ) ) + maFrom.mnRowOffset; + sal_Int64 nX = static_cast< sal_Int64 >( rUnitConv.scaleFromMm100( aPoint.X, UNIT_EMU ) ) + lclCalcEmu( rUnitConv, maFrom.mnColOffset, eUnitX ); + sal_Int64 nY = static_cast< sal_Int64 >( rUnitConv.scaleFromMm100( aPoint.Y, UNIT_EMU ) ) + lclCalcEmu( rUnitConv, maFrom.mnRowOffset, eUnitY ); if( (nX < aSheetSize.Width) && (nY < aSheetSize.Height) ) { aLoc.X = static_cast< sal_Int32 >( nX ); @@ -315,6 +376,7 @@ Rectangle ShapeAnchor::calcEmuLocation( const AnchorSizeModel& rEmuSheetSize ) c } break; case ANCHOR_TWOCELL: + case ANCHOR_VML: OSL_ENSURE( maTo.isValid(), "ShapeAnchor::calcEmuLocation - invalid position" ); if( maTo.isValid() ) { @@ -328,14 +390,14 @@ Rectangle ShapeAnchor::calcEmuLocation( const AnchorSizeModel& rEmuSheetSize ) c aLoc.Width = aSheetSize.Width - aLoc.X; if( aToCell.Column == maTo.mnCol ) { - nX += maTo.mnColOffset; + nX += lclCalcEmu( rUnitConv, maTo.mnColOffset, eUnitX ); aLoc.Width = static_cast< sal_Int32 >( ::std::min< sal_Int64 >( nX - aLoc.X + 1, aLoc.Width ) ); } // height aLoc.Height = aSheetSize.Height - aLoc.Y; if( aToCell.Row == maTo.mnRow ) { - nY += maTo.mnRowOffset; + nY += lclCalcEmu( rUnitConv, maTo.mnRowOffset, eUnitY ); aLoc.Height = static_cast< sal_Int32 >( ::std::min< sal_Int64 >( nY - aLoc.Y + 1, aLoc.Height ) ); } } @@ -357,13 +419,10 @@ Rectangle ShapeAnchor::calcEmuLocation( const AnchorSizeModel& rEmuSheetSize ) c // ============================================================================ OoxDrawingFragment::OoxDrawingFragment( const WorksheetHelper& rHelper, const OUString& rFragmentPath ) : - OoxWorksheetFragmentBase( rHelper, rFragmentPath ) + OoxWorksheetFragmentBase( rHelper, rFragmentPath ), + mxDrawPage( rHelper.getDrawPage(), UNO_QUERY ) { - Reference< XDrawPageSupplier > xDrawPageSupp( getSheet(), UNO_QUERY ); - if( xDrawPageSupp.is() ) - mxDrawPage.set( xDrawPageSupp->getDrawPage(), UNO_QUERY ); OSL_ENSURE( mxDrawPage.is(), "OoxDrawingFragment::OoxDrawingFragment - missing drawing page" ); - maApiSheetSize = getDrawPageSize(); maEmuSheetSize.Width = static_cast< sal_Int64 >( getUnitConverter().scaleFromMm100( maApiSheetSize.Width, UNIT_EMU ) ); maEmuSheetSize.Height = static_cast< sal_Int64 >( getUnitConverter().scaleFromMm100( maApiSheetSize.Height, UNIT_EMU ) ); @@ -462,6 +521,110 @@ void OoxDrawingFragment::onEndElement( const OUString& rChars ) // ============================================================================ +VmlDrawing::VmlDrawing( const WorksheetHelper& rHelper ) : + ::oox::vml::Drawing( rHelper.getOoxFilter(), rHelper.getDrawPage(), ::oox::vml::VMLDRAWING_EXCEL ), + WorksheetHelper( rHelper ) +{ +} + +bool VmlDrawing::convertShapeClientAnchor( Rectangle& orShapeRect, const OUString& rShapeAnchor ) const +{ + if( rShapeAnchor.getLength() == 0 ) + return false; + ShapeAnchor aAnchor( *this ); + aAnchor.importVmlAnchor( rShapeAnchor ); + orShapeRect = aAnchor.calcApiLocation( getDrawPageSize(), AnchorSizeModel() ); + return (orShapeRect.Width >= 0) && (orShapeRect.Height >= 0); +} + +void VmlDrawing::convertControlClientData( const Reference< XControlModel >& rxCtrlModel, + const ::oox::vml::ShapeClientData& rClientData ) const +{ + if( rxCtrlModel.is() ) + { + PropertySet aPropSet( rxCtrlModel ); + + // printable + aPropSet.setProperty( PROP_Printable, rClientData.mbPrintObject ); + + // linked cell + if( rClientData.maLinkedCell.getLength() > 0 ) try + { + Reference< XBindableValue > xBindable( rxCtrlModel, UNO_QUERY_THROW ); + + // convert formula string to cell address + FormulaParser& rParser = getFormulaParser(); + TokensFormulaContext aContext( true, false ); + aContext.setBaseAddress( CellAddress( getSheetIndex(), 0, 0 ) ); + rParser.importFormula( aContext, rClientData.maLinkedCell ); + CellAddress aAddress; + if( rParser.extractCellAddress( aAddress, aContext.getTokens(), true ) ) + { + // create argument sequence for createInstanceWithArguments() + NamedValue aValue; + aValue.Name = CREATE_OUSTRING( "BoundCell" ); + aValue.Value <<= aAddress; + Sequence< Any > aArgs( 1 ); + aArgs[ 0 ] <<= aValue; + + // create the CellValueBinding instance and set at the control model + Reference< XValueBinding > xBinding( getDocumentFactory()->createInstanceWithArguments( + CREATE_OUSTRING( "com.sun.star.table.CellValueBinding" ), aArgs ), UNO_QUERY_THROW ); + xBindable->setValueBinding( xBinding ); + } + } + catch( Exception& ) + { + } + + // source range + if( rClientData.maSourceRange.getLength() > 0 ) try + { + Reference< XListEntrySink > xEntrySink( rxCtrlModel, UNO_QUERY_THROW ); + + // convert formula string to cell range + FormulaParser& rParser = getFormulaParser(); + TokensFormulaContext aContext( true, false ); + aContext.setBaseAddress( CellAddress( getSheetIndex(), 0, 0 ) ); + rParser.importFormula( aContext, rClientData.maSourceRange ); + CellRangeAddress aRange; + if( rParser.extractCellRange( aRange, aContext.getTokens(), true ) ) + { + // create argument sequence for createInstanceWithArguments() + NamedValue aValue; + aValue.Name = CREATE_OUSTRING( "CellRange" ); + aValue.Value <<= aRange; + Sequence< Any > aArgs( 1 ); + aArgs[ 0 ] <<= aValue; + + // create the EntrySource instance and set at the control model + Reference< XListEntrySource > xEntrySource( getDocumentFactory()->createInstanceWithArguments( + CREATE_OUSTRING( "com.sun.star.table.CellRangeListSource" ), aArgs ), UNO_QUERY_THROW ); + xEntrySink->setListEntrySource( xEntrySource ); + } + } + catch( Exception& ) + { + } + } +} + +// ============================================================================ + +OoxVmlDrawingFragment::OoxVmlDrawingFragment( const WorksheetHelper& rHelper, const OUString& rFragmentPath ) : + ::oox::vml::DrawingFragment( rHelper.getOoxFilter(), rFragmentPath, rHelper.getVmlDrawing() ), + WorksheetHelper( rHelper ) +{ +} + +void OoxVmlDrawingFragment::finalizeImport() +{ + ::oox::vml::DrawingFragment::finalizeImport(); + getVmlDrawing().convertAndInsert(); +} + +// ============================================================================ + } // namespace xls } // namespace oox diff --git a/oox/source/xls/excelchartconverter.cxx b/oox/source/xls/excelchartconverter.cxx index cf9f98681be4..52e327699f0d 100644 --- a/oox/source/xls/excelchartconverter.cxx +++ b/oox/source/xls/excelchartconverter.cxx @@ -95,7 +95,7 @@ Reference< XDataSequence > ExcelChartConverter::createDataSequence( // create a range list from the token sequence ApiCellRangeList aRanges; - rParser.extractCellRangeList( aRanges, aContext.getTokens() ); + rParser.extractCellRangeList( aRanges, aContext.getTokens(), false ); aRangeRep = rParser.generateApiRangeListString( aRanges ); } else if( !rDataSeq.maData.empty() ) diff --git a/oox/source/xls/excelfilter.cxx b/oox/source/xls/excelfilter.cxx index 4f3fce123387..f460f3e8fdcb 100644 --- a/oox/source/xls/excelfilter.cxx +++ b/oox/source/xls/excelfilter.cxx @@ -51,7 +51,6 @@ using ::oox::core::FragmentHandlerRef; using ::oox::core::Relation; using ::oox::core::Relations; using ::oox::core::XmlFilterBase; -using ::oox::vml::DrawingPtr; using ::oox::drawingml::table::TableStyleListPtr; namespace oox { @@ -72,15 +71,15 @@ Sequence< OUString > SAL_CALL ExcelFilter_getSupportedServiceNames() throw() } Reference< XInterface > SAL_CALL ExcelFilter_createInstance( - const Reference< XMultiServiceFactory >& rxFactory ) throw( Exception ) + const Reference< XMultiServiceFactory >& rxGlobalFactory ) throw( Exception ) { - return static_cast< ::cppu::OWeakObject* >( new ExcelFilter( rxFactory ) ); + return static_cast< ::cppu::OWeakObject* >( new ExcelFilter( rxGlobalFactory ) ); } // ---------------------------------------------------------------------------- -ExcelFilter::ExcelFilter( const Reference< XMultiServiceFactory >& rxFactory ) : - XmlFilterBase( rxFactory ), +ExcelFilter::ExcelFilter( const Reference< XMultiServiceFactory >& rxGlobalFactory ) : + XmlFilterBase( rxGlobalFactory ), mpHelper( 0 ) { } @@ -97,7 +96,7 @@ bool ExcelFilter::importDocument() throw() OOX_DUMP_FILE( ::oox::dump::xlsb::Dumper ); bool bRet = false; - OUString aWorkbookPath = getFragmentPathFromType( CREATE_OFFICEDOC_RELATIONSTYPE( "officeDocument" ) ); + OUString aWorkbookPath = getFragmentPathFromFirstType( CREATE_OFFICEDOC_RELATIONSTYPE( "officeDocument" ) ); if( aWorkbookPath.getLength() > 0 ) { WorkbookHelperRoot aHelper( *this ); @@ -127,9 +126,9 @@ sal_Int32 ExcelFilter::getSchemeClr( sal_Int32 nColorSchemeToken ) const return mpHelper->getTheme().getColorByToken( nColorSchemeToken ); } -const DrawingPtr ExcelFilter::getDrawings() +::oox::vml::Drawing* ExcelFilter::getVmlDrawing() { - return DrawingPtr(); + return 0; } const TableStyleListPtr ExcelFilter::getTableStyles() @@ -163,15 +162,15 @@ Sequence< OUString > SAL_CALL ExcelBiffFilter_getSupportedServiceNames() throw() } Reference< XInterface > SAL_CALL ExcelBiffFilter_createInstance( - const Reference< XMultiServiceFactory >& rxFactory ) throw( Exception ) + const Reference< XMultiServiceFactory >& rxGlobalFactory ) throw( Exception ) { - return static_cast< ::cppu::OWeakObject* >( new ExcelBiffFilter( rxFactory ) ); + return static_cast< ::cppu::OWeakObject* >( new ExcelBiffFilter( rxGlobalFactory ) ); } // ---------------------------------------------------------------------------- -ExcelBiffFilter::ExcelBiffFilter( const Reference< XMultiServiceFactory >& rxFactory ) : - BinaryFilterBase( rxFactory ) +ExcelBiffFilter::ExcelBiffFilter( const Reference< XMultiServiceFactory >& rxGlobalFactory ) : + BinaryFilterBase( rxGlobalFactory ) { } @@ -186,12 +185,12 @@ bool ExcelBiffFilter::importDocument() throw() file:///<path-to-oox-module>/source/dump/biffdumper.ini. */ OOX_DUMP_FILE( ::oox::dump::biff::Dumper ); - /* A boolean argument passed through XInitialisation decides whether to - use the BIFF file dumper implemented in this filter only, or to really - import/export the document. */ - const Sequence< Any >& rArgs = getArguments(); - bool bDumperOnly = false; - if( (rArgs.getLength() >= 2) && (rArgs[ 1 ] >>= bDumperOnly) && bDumperOnly ) + /* The boolean argument "UseBiffFilter" passed through XInitialisation + decides whether to use the BIFF file dumper implemented in this filter + only (false or missing), or to import/export the document (true). */ + Any aUseBiffFilter = getArgument( CREATE_OUSTRING( "UseBiffFilter" ) ); + bool bUseBiffFilter = false; + if( !(aUseBiffFilter >>= bUseBiffFilter) || !bUseBiffFilter ) return true; bool bRet = false; diff --git a/oox/source/xls/externallinkbuffer.cxx b/oox/source/xls/externallinkbuffer.cxx index d46adb8f0c45..564775228d2a 100644 --- a/oox/source/xls/externallinkbuffer.cxx +++ b/oox/source/xls/externallinkbuffer.cxx @@ -115,7 +115,7 @@ ExternalName::ExternalName( const ExternalLink& rParentLink, sal_Int32 nLocalShe void ExternalName::importDefinedName( const AttributeList& rAttribs ) { - maModel.maName = rAttribs.getString( XML_name, OUString() ); + maModel.maName = rAttribs.getXString( XML_name, OUString() ); OSL_ENSURE( maModel.maName.getLength() > 0, "ExternalName::importDefinedName - empty name" ); // zero-based index into sheet list of externalBook maModel.mnSheet = rAttribs.getInteger( XML_sheetId, -1 ); @@ -123,7 +123,7 @@ void ExternalName::importDefinedName( const AttributeList& rAttribs ) void ExternalName::importDdeItem( const AttributeList& rAttribs ) { - maModel.maName = rAttribs.getString( XML_name, OUString() ); + maModel.maName = rAttribs.getXString( XML_name, OUString() ); OSL_ENSURE( maModel.maName.getLength() > 0, "ExternalName::importDdeItem - empty name" ); maExtNameModel.mbOleObj = false; maExtNameModel.mbStdDocName = rAttribs.getBool( XML_ole, false ); @@ -138,7 +138,7 @@ void ExternalName::importValues( const AttributeList& rAttribs ) void ExternalName::importOleItem( const AttributeList& rAttribs ) { - maModel.maName = rAttribs.getString( XML_name, OUString() ); + maModel.maName = rAttribs.getXString( XML_name, OUString() ); OSL_ENSURE( maModel.maName.getLength() > 0, "ExternalName::importOleItem - empty name" ); maExtNameModel.mbOleObj = true; maExtNameModel.mbNotify = rAttribs.getBool( XML_advise, false ); @@ -235,8 +235,8 @@ void ExternalName::importExternalName( BiffInputStream& rStrm ) } maModel.maName = (getBiff() == BIFF8) ? - rStrm.readUniString( rStrm.readuInt8() ) : - rStrm.readByteString( false, getTextEncoding() ); + rStrm.readUniStringBody( rStrm.readuInt8() ) : + rStrm.readByteStringUC( false, getTextEncoding() ); OSL_ENSURE( maModel.maName.getLength() > 0, "ExternalName::importExternalName - empty name" ); switch( mrParentLink.getLinkType() ) @@ -277,7 +277,7 @@ void ExternalName::importExternalName( BiffInputStream& rStrm ) appendResultValue( rStrm.readDouble() ); break; case BIFF_DATATYPE_STRING: - appendResultValue( bBiff8 ? rStrm.readUniString() : rStrm.readByteString( false, getTextEncoding() ) ); + appendResultValue( bBiff8 ? rStrm.readUniString() : rStrm.readByteStringUC( false, getTextEncoding() ) ); break; case BIFF_DATATYPE_BOOL: appendResultValue< double >( (rStrm.readuInt8() == 0) ? 0.0 : 1.0 ); @@ -453,7 +453,7 @@ void ExternalLink::importExternalBook( const Relations& rRelations, const Attrib void ExternalLink::importSheetName( const AttributeList& rAttribs ) { - insertExternalSheet( rAttribs.getString( XML_val, OUString() ) ); + insertExternalSheet( rAttribs.getXString( XML_val, OUString() ) ); } void ExternalLink::importDefinedName( const AttributeList& rAttribs ) @@ -463,8 +463,8 @@ void ExternalLink::importDefinedName( const AttributeList& rAttribs ) void ExternalLink::importDdeLink( const AttributeList& rAttribs ) { - OUString aDdeService = rAttribs.getString( XML_ddeService, OUString() ); - OUString aDdeTopic = rAttribs.getString( XML_ddeTopic, OUString() ); + OUString aDdeService = rAttribs.getXString( XML_ddeService, OUString() ); + OUString aDdeTopic = rAttribs.getXString( XML_ddeTopic, OUString() ); setDdeOleTargetUrl( aDdeService, aDdeTopic, LINKTYPE_DDE ); } @@ -477,8 +477,8 @@ ExternalNameRef ExternalLink::importDdeItem( const AttributeList& rAttribs ) void ExternalLink::importOleLink( const Relations& rRelations, const AttributeList& rAttribs ) { - OUString aProgId = rAttribs.getString( XML_progId, OUString() ); - OUString aTargetUrl = rRelations.getTargetFromRelId( rAttribs.getString( R_TOKEN( id ), OUString() ) ); + OUString aProgId = rAttribs.getXString( XML_progId, OUString() ); + OUString aTargetUrl = rRelations.getExternalTargetFromRelId( rAttribs.getString( R_TOKEN( id ), OUString() ) ); setDdeOleTargetUrl( aProgId, aTargetUrl, LINKTYPE_OLE ); } @@ -525,7 +525,7 @@ void ExternalLink::importExternalBook( const Relations& rRelations, RecordInputS break; case OOBIN_EXTERNALBOOK_OLE: { - OUString aTargetUrl = rRelations.getTargetFromRelId( rStrm.readString() ); + OUString aTargetUrl = rRelations.getExternalTargetFromRelId( rStrm.readString() ); OUString aProgId = rStrm.readString(); setDdeOleTargetUrl( aProgId, aTargetUrl, LINKTYPE_OLE ); } @@ -554,9 +554,7 @@ ExternalNameRef ExternalLink::importExternalName( RecordInputStream& rStrm ) void ExternalLink::importExternSheet( BiffInputStream& rStrm ) { - rStrm.enableNulChars( true ); - OStringBuffer aTargetBuffer( rStrm.readByteString( false ) ); - rStrm.enableNulChars( false ); + OStringBuffer aTargetBuffer( rStrm.readByteString( false, true ) ); // references to own sheets have wrong string length field (off by 1) if( (aTargetBuffer.getLength() > 0) && (aTargetBuffer[ 0 ] == 3) ) aTargetBuffer.append( static_cast< sal_Char >( rStrm.readuInt8() ) ); @@ -592,9 +590,7 @@ void ExternalLink::importExternalBook( BiffInputStream& rStrm ) else if( rStrm.getRemaining() >= 3 ) { // NUL characters may occur - rStrm.enableNulChars( true ); - aTarget = rStrm.readUniString(); - rStrm.enableNulChars( false ); + aTarget = rStrm.readUniString( true ); } // parse the encoded URL @@ -754,15 +750,14 @@ void ExternalLink::setExternalTargetUrl( const OUString& rTargetUrl, const OUStr meLinkType = LINKTYPE_UNKNOWN; if( rTargetType == OOX_TARGETTYPE_EXTLINK ) { - maTargetUrl = getBaseFilter().getAbsoluteUrl( rTargetUrl ); + maTargetUrl = getBaseFilter().getAbsoluteUrl( rTargetUrl ); if( maTargetUrl.getLength() > 0 ) meLinkType = LINKTYPE_EXTERNAL; } else if( rTargetType == OOX_TARGETTYPE_LIBRARY ) { meLinkType = LINKTYPE_LIBRARY; - if( rTargetUrl.equalsIgnoreAsciiCaseAscii( "EUROTOOL.XLA" ) || rTargetUrl.equalsIgnoreAsciiCaseAscii( "EUROTOOL.XLAM" ) ) - meFuncLibType = FUNCLIB_EUROTOOL; + meFuncLibType = getFormulaParser().getFuncLibTypeFromLibraryName( rTargetUrl ); } OSL_ENSURE( meLinkType != LINKTYPE_UNKNOWN, "ExternalLink::setExternalTargetUrl - empty target URL or unknown target type" ); diff --git a/oox/source/xls/externallinkfragment.cxx b/oox/source/xls/externallinkfragment.cxx index d985ad5ecf8e..0245c44eb13c 100644 --- a/oox/source/xls/externallinkfragment.cxx +++ b/oox/source/xls/externallinkfragment.cxx @@ -507,7 +507,7 @@ void BiffExternalLinkFragment::importCrn() break; case BIFF_DATATYPE_STRING: { - OUString aText = (getBiff() == BIFF8) ? mrStrm.readUniString() : mrStrm.readByteString( false, getTextEncoding() ); + OUString aText = (getBiff() == BIFF8) ? mrStrm.readUniString() : mrStrm.readByteStringUC( false, getTextEncoding() ); setCellValue( aBinAddr, Any( aText ) ); } break; diff --git a/oox/source/xls/formulabase.cxx b/oox/source/xls/formulabase.cxx index 2c5fed66ce30..7ba8af38324b 100644 --- a/oox/source/xls/formulabase.cxx +++ b/oox/source/xls/formulabase.cxx @@ -34,6 +34,7 @@ #include <rtl/ustrbuf.hxx> #include <com/sun/star/lang/XMultiServiceFactory.hpp> #include <com/sun/star/table/XCellRange.hpp> +#include <com/sun/star/sheet/AddressConvention.hpp> #include <com/sun/star/sheet/ReferenceFlags.hpp> #include <com/sun/star/sheet/SingleReference.hpp> #include <com/sun/star/sheet/ComplexReference.hpp> @@ -41,9 +42,9 @@ #include <com/sun/star/sheet/FormulaMapGroup.hpp> #include <com/sun/star/sheet/FormulaMapGroupSpecialOffset.hpp> #include <com/sun/star/sheet/XFormulaOpCodeMapper.hpp> +#include <com/sun/star/sheet/XFormulaParser.hpp> #include <com/sun/star/sheet/XFormulaTokens.hpp> #include "properties.hxx" -#include "oox/helper/propertyset.hxx" #include "oox/helper/recordinputstream.hxx" #include "oox/core/filterbase.hxx" #include "oox/xls/biffinputstream.hxx" @@ -54,12 +55,13 @@ using ::rtl::OUString; using ::rtl::OUStringBuffer; using ::rtl::OStringToOUString; using ::rtl::OUStringToOString; +using ::com::sun::star::lang::XMultiServiceFactory; using ::com::sun::star::uno::Any; using ::com::sun::star::uno::Reference; using ::com::sun::star::uno::Sequence; using ::com::sun::star::uno::Exception; +using ::com::sun::star::uno::UNO_QUERY; using ::com::sun::star::uno::UNO_QUERY_THROW; -using ::com::sun::star::lang::XMultiServiceFactory; using ::com::sun::star::table::CellAddress; using ::com::sun::star::table::CellRangeAddress; using ::com::sun::star::table::XCellRange; @@ -70,7 +72,6 @@ using ::com::sun::star::sheet::FormulaOpCodeMapEntry; using ::com::sun::star::sheet::XSpreadsheetDocument; using ::com::sun::star::sheet::XFormulaOpCodeMapper; using ::com::sun::star::sheet::XFormulaTokens; -using namespace ::com::sun::star::sheet::ReferenceFlags; namespace oox { namespace xls { @@ -296,9 +297,9 @@ static const FunctionData saFuncTableBiff2[] = { "SIN", "SIN", 15, 15, 1, 1, V, { V }, 0 }, { "COS", "COS", 16, 16, 1, 1, V, { V }, 0 }, { "TAN", "TAN", 17, 17, 1, 1, V, { V }, 0 }, - { "COT", "TAN", 17, 17, 1, 1, V, { V }, FUNCFLAG_EXPORTONLY }, + { "COT", 0, 17, 17, 1, 1, V, { V }, FUNCFLAG_EXPORTONLY }, { "ATAN", "ATAN", 18, 18, 1, 1, V, { V }, 0 }, - { "ACOT", "ATAN", 18, 18, 1, 1, V, { V }, FUNCFLAG_EXPORTONLY }, + { "ACOT", 0, 18, 18, 1, 1, V, { V }, FUNCFLAG_EXPORTONLY }, { "PI", "PI", 19, 19, 0, 0, V, {}, 0 }, { "SQRT", "SQRT", 20, 20, 1, 1, V, { V }, 0 }, { "EXP", "EXP", 21, 21, 1, 1, V, { V }, 0 }, @@ -459,11 +460,11 @@ static const FunctionData saFuncTableBiff3[] = { "SINH", "SINH", 229, 229, 1, 1, V, { V }, 0 }, { "COSH", "COSH", 230, 230, 1, 1, V, { V }, 0 }, { "TANH", "TANH", 231, 231, 1, 1, V, { V }, 0 }, - { "COTH", "TANH", 231, 231, 1, 1, V, { V }, FUNCFLAG_EXPORTONLY }, + { "COTH", 0, 231, 231, 1, 1, V, { V }, FUNCFLAG_EXPORTONLY }, { "ASINH", "ASINH", 232, 232, 1, 1, V, { V }, 0 }, { "ACOSH", "ACOSH", 233, 233, 1, 1, V, { V }, 0 }, { "ATANH", "ATANH", 234, 234, 1, 1, V, { V }, 0 }, - { "ACOTH", "ATANH", 234, 234, 1, 1, V, { V }, FUNCFLAG_EXPORTONLY }, + { "ACOTH", 0, 234, 234, 1, 1, V, { V }, FUNCFLAG_EXPORTONLY }, { "DGET", "DGET", 235, 235, 3, 3, V, { R }, 0 }, { "INFO", "INFO", 244, 244, 1, 1, V, { V }, FUNCFLAG_VOLATILE } }; @@ -792,15 +793,35 @@ FuncInfoParamClassIterator& FuncInfoParamClassIterator::operator++() // function provider ========================================================== -FunctionProvider::FunctionProvider( FilterType eFilter, BiffType eBiff, bool bImportFilter ) : - mxFuncs( new FuncVector ), - mxOdfFuncs( new FuncNameMap ), - mxOoxFuncs( new FuncNameMap ), - mxOobFuncs( new FuncIdMap ), - mxBiffFuncs( new FuncIdMap ), - mxMacroFuncs( new FuncNameMap ) -{ - OSL_ENSURE( bImportFilter, "FunctionProvider::FunctionProvider - need special handling for macro call functions" ); +struct FunctionProviderImpl +{ + typedef RefMap< OUString, FunctionInfo > FuncNameMap; + typedef RefMap< sal_uInt16, FunctionInfo > FuncIdMap; + + FunctionInfoVector maFuncs; /// All function infos in one list. + FuncNameMap maOdfFuncs; /// Maps ODF function names to function data. + FuncNameMap maOoxFuncs; /// Maps OOXML function names to function data. + FuncIdMap maOobFuncs; /// Maps OOBIN function indexes to function data. + FuncIdMap maBiffFuncs; /// Maps BIFF function indexes to function data. + FuncNameMap maMacroFuncs; /// Maps macro function names to function data. + + explicit FunctionProviderImpl( FilterType eFilter, BiffType eBiff, bool bImportFilter ); + +private: + /** Creates and inserts a function info struct from the passed function data. */ + void initFunc( const FunctionData& rFuncData, sal_uInt8 nMaxParam ); + + /** Initializes the members from the passed function data list. */ + void initFuncs( + const FunctionData* pBeg, const FunctionData* pEnd, + sal_uInt8 nMaxParam, bool bImportFilter ); +}; + +// ---------------------------------------------------------------------------- + +FunctionProviderImpl::FunctionProviderImpl( FilterType eFilter, BiffType eBiff, bool bImportFilter ) +{ + OSL_ENSURE( bImportFilter, "FunctionProviderImpl::FunctionProviderImpl - need special handling for macro call functions" ); sal_uInt8 nMaxParam = 0; switch( eFilter ) { @@ -812,10 +833,10 @@ FunctionProvider::FunctionProvider( FilterType eFilter, BiffType eBiff, bool bIm nMaxParam = BIFF_MAX_PARAMCOUNT; break; case FILTER_UNKNOWN: - OSL_ENSURE( false, "FunctionProvider::FunctionProvider - invalid filter type" ); + OSL_ENSURE( false, "FunctionProviderImpl::FunctionProviderImpl - invalid filter type" ); break; } - OSL_ENSURE( eBiff != BIFF_UNKNOWN, "FunctionProvider::FunctionProvider - invalid BIFF type" ); + OSL_ENSURE( eBiff != BIFF_UNKNOWN, "FunctionProviderImpl::FunctionProviderImpl - invalid BIFF type" ); /* Add functions supported in the current BIFF version only. Function tables from later BIFF versions may overwrite single functions from @@ -834,38 +855,7 @@ FunctionProvider::FunctionProvider( FilterType eFilter, BiffType eBiff, bool bIm initFuncs( saFuncTableOox, STATIC_ARRAY_END( saFuncTableOox ), nMaxParam, bImportFilter ); } -FunctionProvider::~FunctionProvider() -{ -} - -const FunctionInfo* FunctionProvider::getFuncInfoFromOdfFuncName( const OUString& rFuncName ) const -{ - return mxOdfFuncs->get( rFuncName ).get(); -} - -const FunctionInfo* FunctionProvider::getFuncInfoFromOoxFuncName( const OUString& rFuncName ) const -{ - return mxOoxFuncs->get( rFuncName ).get(); -} - -const FunctionInfo* FunctionProvider::getFuncInfoFromOobFuncId( sal_uInt16 nFuncId ) const -{ - return mxOobFuncs->get( nFuncId ).get(); -} - -const FunctionInfo* FunctionProvider::getFuncInfoFromBiffFuncId( sal_uInt16 nFuncId ) const -{ - return mxBiffFuncs->get( nFuncId ).get(); -} - -const FunctionInfo* FunctionProvider::getFuncInfoFromMacroName( const OUString& rFuncName ) const -{ - return mxMacroFuncs->get( rFuncName ).get(); -} - -// private -------------------------------------------------------------------- - -void FunctionProvider::initFunc( const FunctionData& rFuncData, sal_uInt8 nMaxParam ) +void FunctionProviderImpl::initFunc( const FunctionData& rFuncData, sal_uInt8 nMaxParam ) { // create a function info object FunctionInfoRef xFuncInfo( new FunctionInfo ); @@ -897,39 +887,122 @@ void FunctionProvider::initFunc( const FunctionData& rFuncData, sal_uInt8 nMaxPa setFlag( xFuncInfo->mnBiffFuncId, BIFF_TOK_FUNCVAR_CMD, bMacroCmd ); // insert the function info into the member maps - mxFuncs->push_back( xFuncInfo ); + maFuncs.push_back( xFuncInfo ); if( xFuncInfo->maOdfFuncName.getLength() > 0 ) - (*mxOdfFuncs)[ xFuncInfo->maOdfFuncName ] = xFuncInfo; + maOdfFuncs[ xFuncInfo->maOdfFuncName ] = xFuncInfo; if( xFuncInfo->maOoxFuncName.getLength() > 0 ) - (*mxOoxFuncs)[ xFuncInfo->maOoxFuncName ] = xFuncInfo; + maOoxFuncs[ xFuncInfo->maOoxFuncName ] = xFuncInfo; if( xFuncInfo->mnOobFuncId != NOID ) - (*mxOobFuncs)[ xFuncInfo->mnOobFuncId ] = xFuncInfo; + maOobFuncs[ xFuncInfo->mnOobFuncId ] = xFuncInfo; if( xFuncInfo->mnBiffFuncId != NOID ) - (*mxBiffFuncs)[ xFuncInfo->mnBiffFuncId ] = xFuncInfo; + maBiffFuncs[ xFuncInfo->mnBiffFuncId ] = xFuncInfo; if( xFuncInfo->maBiffMacroName.getLength() > 0 ) - (*mxMacroFuncs)[ xFuncInfo->maBiffMacroName ] = xFuncInfo; + maMacroFuncs[ xFuncInfo->maBiffMacroName ] = xFuncInfo; } -void FunctionProvider::initFuncs( const FunctionData* pBeg, const FunctionData* pEnd, sal_uInt8 nMaxParam, bool bImportFilter ) +void FunctionProviderImpl::initFuncs( const FunctionData* pBeg, const FunctionData* pEnd, sal_uInt8 nMaxParam, bool bImportFilter ) { for( const FunctionData* pIt = pBeg; pIt != pEnd; ++pIt ) if( pIt->isSupported( bImportFilter ) ) initFunc( *pIt, nMaxParam ); } +// ---------------------------------------------------------------------------- + +FunctionProvider::FunctionProvider( FilterType eFilter, BiffType eBiff, bool bImportFilter ) : + mxFuncImpl( new FunctionProviderImpl( eFilter, eBiff, bImportFilter ) ) +{ +} + +FunctionProvider::~FunctionProvider() +{ +} + +const FunctionInfo* FunctionProvider::getFuncInfoFromOdfFuncName( const OUString& rFuncName ) const +{ + return mxFuncImpl->maOdfFuncs.get( rFuncName ).get(); +} + +const FunctionInfo* FunctionProvider::getFuncInfoFromOoxFuncName( const OUString& rFuncName ) const +{ + return mxFuncImpl->maOoxFuncs.get( rFuncName ).get(); +} + +const FunctionInfo* FunctionProvider::getFuncInfoFromOobFuncId( sal_uInt16 nFuncId ) const +{ + return mxFuncImpl->maOobFuncs.get( nFuncId ).get(); +} + +const FunctionInfo* FunctionProvider::getFuncInfoFromBiffFuncId( sal_uInt16 nFuncId ) const +{ + return mxFuncImpl->maBiffFuncs.get( nFuncId ).get(); +} + +const FunctionInfo* FunctionProvider::getFuncInfoFromMacroName( const OUString& rFuncName ) const +{ + return mxFuncImpl->maMacroFuncs.get( rFuncName ).get(); +} + +FunctionLibraryType FunctionProvider::getFuncLibTypeFromLibraryName( const OUString& rLibraryName ) const +{ +#define OOX_XLS_IS_LIBNAME( libname, basename ) (libname.equalsIgnoreAsciiCaseAscii( basename ".XLA" ) || libname.equalsIgnoreAsciiCaseAscii( basename ".XLAM" )) + + // the EUROTOOL add-in containing the EUROCONVERT function + if( OOX_XLS_IS_LIBNAME( rLibraryName, "EUROTOOL" ) ) + return FUNCLIB_EUROTOOL; + +#undef OOX_XLS_IS_LIBNAME + + // default: unknown library + return FUNCLIB_UNKNOWN; +} + +const FunctionInfoVector& FunctionProvider::getFuncs() const +{ + return mxFuncImpl->maFuncs; +} + // op-code and function provider ============================================== -OpCodeProvider::OpCodeProvider( const WorkbookHelper& rHelper ) : - FunctionProvider( rHelper.getFilterType(), rHelper.getBiff(), rHelper.getBaseFilter().isImportFilter() ), - WorkbookHelper( rHelper ), - mxOpCodeFuncs( new OpCodeFuncMap ), - mxExtProgFuncs( new FuncNameMap ), - mxParserMap( new OpCodeEntryVector ) +struct OpCodeProviderImpl : public ApiOpCodes { - try + typedef RefMap< sal_Int32, FunctionInfo > OpCodeFuncMap; + typedef RefMap< OUString, FunctionInfo > FuncNameMap; + typedef ::std::vector< FormulaOpCodeMapEntry > OpCodeEntryVector; + + OpCodeFuncMap maOpCodeFuncs; /// Maps API function op-codes to function data. + FuncNameMap maExtProgFuncs; /// Maps programmatical API function names to function data. + OpCodeEntryVector maParserMap; /// OOXML token mapping for formula parser service. + + explicit OpCodeProviderImpl( + const FunctionInfoVector& rFuncInfos, + const Reference< XMultiServiceFactory >& rxFactory ); + +private: + typedef ::std::map< OUString, ApiToken > ApiTokenMap; + typedef Sequence< FormulaOpCodeMapEntry > OpCodeEntrySequence; + + static bool fillEntrySeq( OpCodeEntrySequence& orEntrySeq, const Reference< XFormulaOpCodeMapper >& rxMapper, sal_Int32 nMapGroup ); + static bool fillTokenMap( ApiTokenMap& orTokenMap, OpCodeEntrySequence& orEntrySeq, const Reference< XFormulaOpCodeMapper >& rxMapper, sal_Int32 nMapGroup ); + bool fillFuncTokenMaps( ApiTokenMap& orIntFuncTokenMap, ApiTokenMap& orExtFuncTokenMap, OpCodeEntrySequence& orEntrySeq, const Reference< XFormulaOpCodeMapper >& rxMapper ) const; + + static bool initOpCode( sal_Int32& ornOpCode, const OpCodeEntrySequence& rEntrySeq, sal_Int32 nSpecialId ); + bool initOpCode( sal_Int32& ornOpCode, const ApiTokenMap& rTokenMap, const OUString& rOdfName, const OUString& rOoxName ); + bool initOpCode( sal_Int32& ornOpCode, const ApiTokenMap& rTokenMap, const sal_Char* pcOdfName, const sal_Char* pcOoxName ); + bool initOpCode( sal_Int32& ornOpCode, const ApiTokenMap& rTokenMap, sal_Unicode cOdfName, sal_Unicode cOoxName ); + + bool initFuncOpCode( FunctionInfo& orFuncInfo, const ApiTokenMap& rFuncTokenMap ); + bool initFuncOpCodes( const ApiTokenMap& rIntFuncTokenMap, const ApiTokenMap& rExtFuncTokenMap, const FunctionInfoVector& rFuncInfos ); +}; + +// ---------------------------------------------------------------------------- + +OpCodeProviderImpl::OpCodeProviderImpl( const FunctionInfoVector& rFuncInfos, + const Reference< XMultiServiceFactory >& rxFactory ) +{ + if( rxFactory.is() ) try { - Reference< XMultiServiceFactory > xFactory( getDocument(), UNO_QUERY_THROW ); - Reference< XFormulaOpCodeMapper > xMapper( xFactory->createInstance( + Reference< XFormulaOpCodeMapper > xMapper( rxFactory->createInstance( CREATE_OUSTRING( "com.sun.star.sheet.FormulaOpCodeMapper" ) ), UNO_QUERY_THROW ); // op-codes provided as attributes @@ -988,61 +1061,22 @@ OpCodeProvider::OpCodeProvider( const WorkbookHelper& rHelper ) : initOpCode( OPCODE_RANGE, aTokenMap, ':', ':' ) && // functions fillFuncTokenMaps( aTokenMap, aExtFuncTokenMap, aEntrySeq, xMapper ) && - initFuncOpCodes( aTokenMap, aExtFuncTokenMap ) && + initFuncOpCodes( aTokenMap, aExtFuncTokenMap, rFuncInfos ) && initOpCode( OPCODE_DDE, aTokenMap, "DDE", 0 ); - OSL_ENSURE( bIsValid, "OpCodeProvider::OpCodeProvider - opcodes not initialized" ); + OSL_ENSURE( bIsValid, "OpCodeProviderImpl::OpCodeProviderImpl - opcodes not initialized" ); (void)bIsValid; // OPCODE_PLUS_SIGN and OPCODE_ADD should be equal, otherwise "+" has to be passed above - OSL_ENSURE( OPCODE_PLUS_SIGN == OPCODE_ADD, "OpCodeProvider::OpCodeProvider - need opcode mapping for OPCODE_PLUS_SIGN" ); + OSL_ENSURE( OPCODE_PLUS_SIGN == OPCODE_ADD, "OpCodeProviderImpl::OpCodeProviderImpl - need opcode mapping for OPCODE_PLUS_SIGN" ); } catch( Exception& ) { - OSL_ENSURE( false, "OpCodeProvider::OpCodeProvider - cannot receive formula opcode mapper" ); - } -} - -OpCodeProvider::~OpCodeProvider() -{ -} - -const FunctionInfo* OpCodeProvider::getFuncInfoFromApiToken( const ApiToken& rToken ) const -{ - const FunctionInfo* pFuncInfo = 0; - if( (rToken.OpCode == OPCODE_EXTERNAL) && rToken.Data.hasValue() ) - { - OUString aProgFuncName; - if( rToken.Data >>= aProgFuncName ) - pFuncInfo = mxExtProgFuncs->get( aProgFuncName ).get(); - } - else if( (rToken.OpCode == OPCODE_MACRO) && rToken.Data.hasValue() ) - { - OUString aMacroName; - if( rToken.Data >>= aMacroName ) - pFuncInfo = getFuncInfoFromMacroName( aMacroName ); + OSL_ENSURE( false, "OpCodeProviderImpl::OpCodeProviderImpl - cannot receive formula opcode mapper" ); } - else if( (rToken.OpCode == OPCODE_BAD) && rToken.Data.hasValue() ) - { - OUString aOoxFuncName; - if( rToken.Data >>= aOoxFuncName ) - pFuncInfo = getFuncInfoFromOoxFuncName( aOoxFuncName ); - } - else - { - pFuncInfo = mxOpCodeFuncs->get( rToken.OpCode ).get(); - } - return pFuncInfo; -} - -Sequence< FormulaOpCodeMapEntry > OpCodeProvider::getOoxParserMap() const -{ - return ContainerHelper::vectorToSequence( *mxParserMap ); } -// private -------------------------------------------------------------------- - -bool OpCodeProvider::fillEntrySeq( OpCodeEntrySequence& orEntrySeq, +bool OpCodeProviderImpl::fillEntrySeq( OpCodeEntrySequence& orEntrySeq, const Reference< XFormulaOpCodeMapper >& rxMapper, sal_Int32 nMapGroup ) { try @@ -1056,7 +1090,7 @@ bool OpCodeProvider::fillEntrySeq( OpCodeEntrySequence& orEntrySeq, return false; } -bool OpCodeProvider::fillTokenMap( ApiTokenMap& orTokenMap, OpCodeEntrySequence& orEntrySeq, +bool OpCodeProviderImpl::fillTokenMap( ApiTokenMap& orTokenMap, OpCodeEntrySequence& orEntrySeq, const Reference< XFormulaOpCodeMapper >& rxMapper, sal_Int32 nMapGroup ) { orTokenMap.clear(); @@ -1070,7 +1104,7 @@ bool OpCodeProvider::fillTokenMap( ApiTokenMap& orTokenMap, OpCodeEntrySequence& return orEntrySeq.hasElements(); } -bool OpCodeProvider::fillFuncTokenMaps( ApiTokenMap& orIntFuncTokenMap, ApiTokenMap& orExtFuncTokenMap, OpCodeEntrySequence& orEntrySeq, const Reference< XFormulaOpCodeMapper >& rxMapper ) const +bool OpCodeProviderImpl::fillFuncTokenMaps( ApiTokenMap& orIntFuncTokenMap, ApiTokenMap& orExtFuncTokenMap, OpCodeEntrySequence& orEntrySeq, const Reference< XFormulaOpCodeMapper >& rxMapper ) const { orIntFuncTokenMap.clear(); orExtFuncTokenMap.clear(); @@ -1084,7 +1118,7 @@ bool OpCodeProvider::fillFuncTokenMaps( ApiTokenMap& orIntFuncTokenMap, ApiToken return orEntrySeq.hasElements(); } -bool OpCodeProvider::initOpCode( sal_Int32& ornOpCode, const OpCodeEntrySequence& rEntrySeq, sal_Int32 nSpecialId ) +bool OpCodeProviderImpl::initOpCode( sal_Int32& ornOpCode, const OpCodeEntrySequence& rEntrySeq, sal_Int32 nSpecialId ) { if( (0 <= nSpecialId) && (nSpecialId < rEntrySeq.getLength()) ) { @@ -1092,12 +1126,12 @@ bool OpCodeProvider::initOpCode( sal_Int32& ornOpCode, const OpCodeEntrySequence return true; } OSL_ENSURE( false, - OStringBuffer( "OpCodeProvider::initOpCode - opcode for special offset " ). + OStringBuffer( "OpCodeProviderImpl::initOpCode - opcode for special offset " ). append( nSpecialId ).append( " not found" ).getStr() ); return false; } -bool OpCodeProvider::initOpCode( sal_Int32& ornOpCode, const ApiTokenMap& rTokenMap, const OUString& rOdfName, const OUString& rOoxName ) +bool OpCodeProviderImpl::initOpCode( sal_Int32& ornOpCode, const ApiTokenMap& rTokenMap, const OUString& rOdfName, const OUString& rOoxName ) { ApiTokenMap::const_iterator aIt = rTokenMap.find( rOdfName ); if( aIt != rTokenMap.end() ) @@ -1108,32 +1142,32 @@ bool OpCodeProvider::initOpCode( sal_Int32& ornOpCode, const ApiTokenMap& rToken FormulaOpCodeMapEntry aEntry; aEntry.Name = rOoxName; aEntry.Token.OpCode = ornOpCode; - mxParserMap->push_back( aEntry ); + maParserMap.push_back( aEntry ); } return true; } OSL_ENSURE( false, - OStringBuffer( "OpCodeProvider::initOpCode - opcode for \"" ). + OStringBuffer( "OpCodeProviderImpl::initOpCode - opcode for \"" ). append( OUStringToOString( rOdfName, RTL_TEXTENCODING_ASCII_US ) ). append( "\" not found" ).getStr() ); return false; } -bool OpCodeProvider::initOpCode( sal_Int32& ornOpCode, const ApiTokenMap& rTokenMap, const sal_Char* pcOdfName, const sal_Char* pcOoxName ) +bool OpCodeProviderImpl::initOpCode( sal_Int32& ornOpCode, const ApiTokenMap& rTokenMap, const sal_Char* pcOdfName, const sal_Char* pcOoxName ) { OUString aOoxName; if( pcOoxName ) aOoxName = OUString::createFromAscii( pcOoxName ); return initOpCode( ornOpCode, rTokenMap, OUString::createFromAscii( pcOdfName ), aOoxName ); } -bool OpCodeProvider::initOpCode( sal_Int32& ornOpCode, const ApiTokenMap& rTokenMap, sal_Unicode cOdfName, sal_Unicode cOoxName ) +bool OpCodeProviderImpl::initOpCode( sal_Int32& ornOpCode, const ApiTokenMap& rTokenMap, sal_Unicode cOdfName, sal_Unicode cOoxName ) { OUString aOoxName; if( cOoxName ) aOoxName = OUString( cOoxName ); return initOpCode( ornOpCode, rTokenMap, OUString( cOdfName ), aOoxName ); } -bool OpCodeProvider::initFuncOpCode( FunctionInfo& orFuncInfo, const ApiTokenMap& rFuncTokenMap ) +bool OpCodeProviderImpl::initFuncOpCode( FunctionInfo& orFuncInfo, const ApiTokenMap& rFuncTokenMap ) { bool bIsValid = false; if( orFuncInfo.maOdfFuncName.getLength() > 0 ) @@ -1145,10 +1179,9 @@ bool OpCodeProvider::initFuncOpCode( FunctionInfo& orFuncInfo, const ApiTokenMap bIsValid = (orFuncInfo.mnApiOpCode >= 0) && (orFuncInfo.mnApiOpCode != OPCODE_UNKNOWN) && - (orFuncInfo.mnApiOpCode != OPCODE_NONAME) && - (orFuncInfo.maOoxFuncName.getLength() > 0); + (orFuncInfo.mnApiOpCode != OPCODE_NONAME); OSL_ENSURE( bIsValid, - OStringBuffer( "OpCodeProvider::initFuncOpCode - no valid opcode or missing OOX function name for ODF function \"" ). + OStringBuffer( "OpCodeProviderImpl::initFuncOpCode - no valid opcode for ODF function \"" ). append( OUStringToOString( orFuncInfo.maOdfFuncName, RTL_TEXTENCODING_ASCII_US ) ). append( '"' ).getStr() ); @@ -1156,18 +1189,19 @@ bool OpCodeProvider::initFuncOpCode( FunctionInfo& orFuncInfo, const ApiTokenMap { bIsValid = (aIt->second.Data >>= orFuncInfo.maExtProgName) && (orFuncInfo.maExtProgName.getLength() > 0); OSL_ENSURE( bIsValid, - OStringBuffer( "OpCodeProvider::initFuncOpCode - no programmatical name for external function \"" ). + OStringBuffer( "OpCodeProviderImpl::initFuncOpCode - no programmatical name for external function \"" ). append( OUStringToOString( orFuncInfo.maOdfFuncName, RTL_TEXTENCODING_ASCII_US ) ). append( '"' ).getStr() ); } - if( bIsValid ) + // add to parser map, if OOX function name exists + if( bIsValid && (orFuncInfo.maOoxFuncName.getLength() > 0) ) { // create the parser map entry FormulaOpCodeMapEntry aEntry; aEntry.Name = orFuncInfo.maOoxFuncName; aEntry.Token = aIt->second; - mxParserMap->push_back( aEntry ); + maParserMap.push_back( aEntry ); } } } @@ -1187,10 +1221,10 @@ bool OpCodeProvider::initFuncOpCode( FunctionInfo& orFuncInfo, const ApiTokenMap return bIsValid; } -bool OpCodeProvider::initFuncOpCodes( const ApiTokenMap& rIntFuncTokenMap, const ApiTokenMap& rExtFuncTokenMap ) +bool OpCodeProviderImpl::initFuncOpCodes( const ApiTokenMap& rIntFuncTokenMap, const ApiTokenMap& rExtFuncTokenMap, const FunctionInfoVector& rFuncInfos ) { bool bIsValid = true; - for( FuncVector::const_iterator aIt = getFuncs().begin(), aEnd = getFuncs().end(); aIt != aEnd; ++aIt ) + for( FunctionInfoVector::const_iterator aIt = rFuncInfos.begin(), aEnd = rFuncInfos.end(); aIt != aEnd; ++aIt ) { FunctionInfoRef xFuncInfo = *aIt; // set API opcode from ODF function name @@ -1199,20 +1233,92 @@ bool OpCodeProvider::initFuncOpCodes( const ApiTokenMap& rIntFuncTokenMap, const if( xFuncInfo->mnApiOpCode != OPCODE_NONAME ) { if( (xFuncInfo->mnApiOpCode == OPCODE_EXTERNAL) && (xFuncInfo->maExtProgName.getLength() > 0) ) - (*mxExtProgFuncs)[ xFuncInfo->maExtProgName ] = xFuncInfo; + maExtProgFuncs[ xFuncInfo->maExtProgName ] = xFuncInfo; else - (*mxOpCodeFuncs)[ xFuncInfo->mnApiOpCode ] = xFuncInfo; + maOpCodeFuncs[ xFuncInfo->mnApiOpCode ] = xFuncInfo; } } return bIsValid; } +// ---------------------------------------------------------------------------- + +OpCodeProvider::OpCodeProvider( const Reference< XMultiServiceFactory >& rxFactory, + FilterType eFilter, BiffType eBiff, bool bImportFilter ) : + FunctionProvider( eFilter, eBiff, bImportFilter ), + mxOpCodeImpl( new OpCodeProviderImpl( getFuncs(), rxFactory ) ) +{ +} + +OpCodeProvider::~OpCodeProvider() +{ +} + +const ApiOpCodes& OpCodeProvider::getOpCodes() const +{ + return *mxOpCodeImpl; +} + +const FunctionInfo* OpCodeProvider::getFuncInfoFromApiToken( const ApiToken& rToken ) const +{ + const FunctionInfo* pFuncInfo = 0; + if( (rToken.OpCode == mxOpCodeImpl->OPCODE_EXTERNAL) && rToken.Data.has< OUString >() ) + pFuncInfo = mxOpCodeImpl->maExtProgFuncs.get( rToken.Data.get< OUString >() ).get(); + else if( (rToken.OpCode == mxOpCodeImpl->OPCODE_MACRO) && rToken.Data.has< OUString >() ) + pFuncInfo = getFuncInfoFromMacroName( rToken.Data.get< OUString >() ); + else if( (rToken.OpCode == mxOpCodeImpl->OPCODE_BAD) && rToken.Data.has< OUString >() ) + pFuncInfo = getFuncInfoFromOoxFuncName( rToken.Data.get< OUString >() ); + else + pFuncInfo = mxOpCodeImpl->maOpCodeFuncs.get( rToken.OpCode ).get(); + return pFuncInfo; +} + +Sequence< FormulaOpCodeMapEntry > OpCodeProvider::getOoxParserMap() const +{ + return ContainerHelper::vectorToSequence( mxOpCodeImpl->maParserMap ); +} + +// API formula parser wrapper ================================================= + +ApiParserWrapper::ApiParserWrapper( + const Reference< XMultiServiceFactory >& rxFactory, const OpCodeProvider& rOpCodeProv ) : + OpCodeProvider( rOpCodeProv ) +{ + if( rxFactory.is() ) try + { + mxParser.set( rxFactory->createInstance( CREATE_OUSTRING( "com.sun.star.sheet.FormulaParser" ) ), UNO_QUERY_THROW ); + } + catch( Exception& ) + { + } + OSL_ENSURE( mxParser.is(), "ApiParserWrapper::ApiParserWrapper - cannot create API formula parser object" ); + maParserProps.set( mxParser ); + maParserProps.setProperty( PROP_CompileEnglish, true ); + maParserProps.setProperty( PROP_FormulaConvention, ::com::sun::star::sheet::AddressConvention::XL_OOX ); + maParserProps.setProperty( PROP_IgnoreLeadingSpaces, false ); + maParserProps.setProperty( PROP_OpCodeMap, getOoxParserMap() ); +} + +ApiTokenSequence ApiParserWrapper::parseFormula( const OUString& rFormula, const CellAddress& rRefPos ) +{ + ApiTokenSequence aTokenSeq; + if( mxParser.is() ) try + { + aTokenSeq = mxParser->parseFormula( rFormula, rRefPos ); + } + catch( Exception& ) + { + } + return aTokenSeq; +} + // formula contexts =========================================================== -FormulaContext::FormulaContext( bool bRelativeAsOffset, bool b2dRefsAs3dRefs ) : +FormulaContext::FormulaContext( bool bRelativeAsOffset, bool b2dRefsAs3dRefs, bool bAllowNulChars ) : maBaseAddress( 0, 0, 0 ), mbRelativeAsOffset( bRelativeAsOffset ), - mb2dRefsAs3dRefs( b2dRefsAs3dRefs ) + mb2dRefsAs3dRefs( b2dRefsAs3dRefs ), + mbAllowNulChars( bAllowNulChars ) { } @@ -1226,8 +1332,8 @@ void FormulaContext::setSharedFormula( const CellAddress& ) // ---------------------------------------------------------------------------- -TokensFormulaContext::TokensFormulaContext( bool bRelativeAsOffset, bool b2dRefsAs3dRefs ) : - FormulaContext( bRelativeAsOffset, b2dRefsAs3dRefs ) +TokensFormulaContext::TokensFormulaContext( bool bRelativeAsOffset, bool b2dRefsAs3dRefs, bool bAllowNulChars ) : + FormulaContext( bRelativeAsOffset, b2dRefsAs3dRefs, bAllowNulChars ) { } @@ -1239,8 +1345,8 @@ void TokensFormulaContext::setTokens( const ApiTokenSequence& rTokens ) // ---------------------------------------------------------------------------- SimpleFormulaContext::SimpleFormulaContext( const Reference< XFormulaTokens >& rxTokens, - bool bRelativeAsOffset, bool b2dRefsAs3dRefs ) : - FormulaContext( bRelativeAsOffset, b2dRefsAs3dRefs ), + bool bRelativeAsOffset, bool b2dRefsAs3dRefs, bool bAllowNulChars ) : + FormulaContext( bRelativeAsOffset, b2dRefsAs3dRefs, bAllowNulChars ), mxTokens( rxTokens ) { OSL_ENSURE( mxTokens.is(), "SimpleFormulaContext::SimpleFormulaContext - missing XFormulaTokens interface" ); @@ -1251,43 +1357,46 @@ void SimpleFormulaContext::setTokens( const ApiTokenSequence& rTokens ) mxTokens->setTokens( rTokens ); } -// formula parser/formula compiler base class ================================= +// formula parser/printer base class for filters ============================== namespace { -const sal_Int32 nForbiddenFlags = COLUMN_DELETED | ROW_DELETED | SHEET_DELETED | COLUMN_RELATIVE | ROW_RELATIVE | SHEET_RELATIVE | RELATIVE_NAME; - -bool lclConvertToCellAddress( CellAddress& orAddress, const SingleReference& rSingleRef, sal_Int32 nFilterBySheet ) +bool lclConvertToCellAddress( CellAddress& orAddress, const SingleReference& rSingleRef, sal_Int32 nForbiddenFlags, sal_Int32 nFilterBySheet ) { orAddress = CellAddress( static_cast< sal_Int16 >( rSingleRef.Sheet ), rSingleRef.Column, rSingleRef.Row ); return - ((nFilterBySheet < 0) || (nFilterBySheet == rSingleRef.Sheet)) && - !getFlag( rSingleRef.Flags, nForbiddenFlags ); + !getFlag( rSingleRef.Flags, nForbiddenFlags ) && + ((nFilterBySheet < 0) || (nFilterBySheet == rSingleRef.Sheet)); } -bool lclConvertToCellRange( CellRangeAddress& orRange, const ComplexReference& rComplexRef, sal_Int32 nFilterBySheet ) +bool lclConvertToCellRange( CellRangeAddress& orRange, const ComplexReference& rComplexRef, sal_Int32 nForbiddenFlags, sal_Int32 nFilterBySheet ) { orRange = CellRangeAddress( static_cast< sal_Int16 >( rComplexRef.Reference1.Sheet ), rComplexRef.Reference1.Column, rComplexRef.Reference1.Row, rComplexRef.Reference2.Column, rComplexRef.Reference2.Row ); return - (rComplexRef.Reference1.Sheet == rComplexRef.Reference2.Sheet) && - ((nFilterBySheet < 0) || (nFilterBySheet == rComplexRef.Reference1.Sheet)) && !getFlag( rComplexRef.Reference1.Flags, nForbiddenFlags ) && - !getFlag( rComplexRef.Reference2.Flags, nForbiddenFlags ); + !getFlag( rComplexRef.Reference2.Flags, nForbiddenFlags ) && + (rComplexRef.Reference1.Sheet == rComplexRef.Reference2.Sheet) && + ((nFilterBySheet < 0) || (nFilterBySheet == rComplexRef.Reference1.Sheet)); } enum TokenToRangeListState { STATE_REF, STATE_SEP, STATE_OPEN, STATE_CLOSE, STATE_ERROR }; -TokenToRangeListState lclProcessRef( ApiCellRangeList& orRanges, const Any& rData, sal_Int32 nFilterBySheet ) +TokenToRangeListState lclProcessRef( ApiCellRangeList& orRanges, const Any& rData, bool bAllowRelative, sal_Int32 nFilterBySheet ) { + using namespace ::com::sun::star::sheet::ReferenceFlags; + const sal_Int32 FORBIDDEN_FLAGS_DEL = COLUMN_DELETED | ROW_DELETED | SHEET_DELETED; + const sal_Int32 FORBIDDEN_FLAGS_REL = FORBIDDEN_FLAGS_DEL | COLUMN_RELATIVE | ROW_RELATIVE | SHEET_RELATIVE | RELATIVE_NAME; + + sal_Int32 nForbiddenFlags = bAllowRelative ? FORBIDDEN_FLAGS_DEL : FORBIDDEN_FLAGS_REL; SingleReference aSingleRef; if( rData >>= aSingleRef ) { CellAddress aAddress; // ignore invalid addresses (with #REF! errors), but do not stop parsing - if( lclConvertToCellAddress( aAddress, aSingleRef, nFilterBySheet ) ) + if( lclConvertToCellAddress( aAddress, aSingleRef, nForbiddenFlags, nFilterBySheet ) ) orRanges.push_back( CellRangeAddress( aAddress.Sheet, aAddress.Column, aAddress.Row, aAddress.Column, aAddress.Row ) ); return STATE_REF; } @@ -1296,7 +1405,7 @@ TokenToRangeListState lclProcessRef( ApiCellRangeList& orRanges, const Any& rDat { CellRangeAddress aRange; // ignore invalid ranges (with #REF! errors), but do not stop parsing - if( lclConvertToCellRange( aRange, aComplexRef, nFilterBySheet ) ) + if( lclConvertToCellRange( aRange, aComplexRef, nForbiddenFlags, nFilterBySheet ) ) orRanges.push_back( aRange ); return STATE_REF; } @@ -1320,7 +1429,9 @@ TokenToRangeListState lclProcessClose( sal_Int32& ornParenLevel ) // ---------------------------------------------------------------------------- FormulaProcessorBase::FormulaProcessorBase( const WorkbookHelper& rHelper ) : - OpCodeProvider( rHelper ) + OpCodeProvider( rHelper.getDocumentFactory(), rHelper.getFilterType(), rHelper.getBiff(), rHelper.getBaseFilter().isImportFilter() ), + ApiOpCodes( getOpCodes() ), + WorkbookHelper( rHelper ) { } @@ -1379,14 +1490,8 @@ OUString FormulaProcessorBase::generateRangeList2dString( const ApiCellRangeList OUString FormulaProcessorBase::generateApiAddressString( const CellAddress& rAddress ) const { OUString aCellName; - try - { - PropertySet aCellProp( getCellFromDoc( rAddress ) ); - aCellProp.getProperty( aCellName, PROP_AbsoluteName ); - } - catch( Exception& ) - { - } + PropertySet aCellProp( getCellFromDoc( rAddress ) ); + aCellProp.getProperty( aCellName, PROP_AbsoluteName ); OSL_ENSURE( aCellName.getLength() > 0, "FormulaProcessorBase::generateApiAddressString - cannot create cell address string" ); return aCellName; } @@ -1394,14 +1499,8 @@ OUString FormulaProcessorBase::generateApiAddressString( const CellAddress& rAdd OUString FormulaProcessorBase::generateApiRangeString( const CellRangeAddress& rRange ) const { OUString aRangeName; - try - { - PropertySet aRangeProp( getCellRangeFromDoc( rRange ) ); - aRangeProp.getProperty( aRangeName, PROP_AbsoluteName ); - } - catch( Exception& ) - { - } + PropertySet aRangeProp( getCellRangeFromDoc( rRange ) ); + aRangeProp.getProperty( aRangeName, PROP_AbsoluteName ); OSL_ENSURE( aRangeName.getLength() > 0, "FormulaProcessorBase::generateApiRangeString - cannot create cell range string" ); return aRangeName; } @@ -1472,10 +1571,25 @@ Any FormulaProcessorBase::extractReference( const ApiTokenSequence& rTokens ) co return Any(); } -bool FormulaProcessorBase::extractAbsoluteRange( CellRangeAddress& orRange, const ApiTokenSequence& rTokens ) const +bool FormulaProcessorBase::extractCellAddress( CellAddress& orAddress, + const ApiTokenSequence& rTokens, bool bAllowRelative ) const +{ + CellRangeAddress aRange; + if( extractCellRange( aRange, rTokens, bAllowRelative ) && (aRange.StartColumn == aRange.EndColumn) && (aRange.StartRow == aRange.EndRow) ) + { + orAddress.Sheet = aRange.Sheet; + orAddress.Column = aRange.StartColumn; + orAddress.Row = aRange.StartRow; + return true; + } + return false; +} + +bool FormulaProcessorBase::extractCellRange( CellRangeAddress& orRange, + const ApiTokenSequence& rTokens, bool bAllowRelative ) const { ApiCellRangeList aRanges; - lclProcessRef( aRanges, extractReference( rTokens ), -1 ); + lclProcessRef( aRanges, extractReference( rTokens ), bAllowRelative, -1 ); if( !aRanges.empty() ) { orRange = aRanges.front(); @@ -1485,7 +1599,7 @@ bool FormulaProcessorBase::extractAbsoluteRange( CellRangeAddress& orRange, cons } void FormulaProcessorBase::extractCellRangeList( ApiCellRangeList& orRanges, - const ApiTokenSequence& rTokens, sal_Int32 nFilterBySheet ) const + const ApiTokenSequence& rTokens, bool bAllowRelative, sal_Int32 nFilterBySheet ) const { orRanges.clear(); TokenToRangeListState eState = STATE_OPEN; @@ -1501,14 +1615,14 @@ void FormulaProcessorBase::extractCellRangeList( ApiCellRangeList& orRanges, else eState = STATE_ERROR; break; case STATE_SEP: - if( nOpCode == OPCODE_PUSH ) eState = lclProcessRef( orRanges, aIt->Data, nFilterBySheet ); + if( nOpCode == OPCODE_PUSH ) eState = lclProcessRef( orRanges, aIt->Data, bAllowRelative, nFilterBySheet ); else if( nOpCode == OPCODE_LIST ) eState = STATE_SEP; else if( nOpCode == OPCODE_OPEN ) eState = lclProcessOpen( nParenLevel ); else if( nOpCode == OPCODE_CLOSE ) eState = lclProcessClose( nParenLevel ); else eState = STATE_ERROR; break; case STATE_OPEN: - if( nOpCode == OPCODE_PUSH ) eState = lclProcessRef( orRanges, aIt->Data, nFilterBySheet ); + if( nOpCode == OPCODE_PUSH ) eState = lclProcessRef( orRanges, aIt->Data, bAllowRelative, nFilterBySheet ); else if( nOpCode == OPCODE_LIST ) eState = STATE_SEP; else if( nOpCode == OPCODE_OPEN ) eState = lclProcessOpen( nParenLevel ); else if( nOpCode == OPCODE_CLOSE ) eState = lclProcessClose( nParenLevel ); diff --git a/oox/source/xls/formulaparser.cxx b/oox/source/xls/formulaparser.cxx index 7657dff34449..d2818ff9cb1a 100644 --- a/oox/source/xls/formulaparser.cxx +++ b/oox/source/xls/formulaparser.cxx @@ -30,17 +30,14 @@ #include "oox/xls/formulaparser.hxx" #include <com/sun/star/lang/XMultiServiceFactory.hpp> -#include <com/sun/star/sheet/AddressConvention.hpp> #include <com/sun/star/sheet/ComplexReference.hpp> #include <com/sun/star/sheet/ExternalReference.hpp> #include <com/sun/star/sheet/FormulaToken.hpp> #include <com/sun/star/sheet/ReferenceFlags.hpp> #include <com/sun/star/sheet/SingleReference.hpp> -#include <com/sun/star/sheet/XFormulaParser.hpp> #include "properties.hxx" -#include "oox/helper/containerhelper.hxx" -#include "oox/helper/propertyset.hxx" #include "oox/helper/recordinputstream.hxx" +#include "oox/core/filterbase.hxx" #include "oox/xls/addressconverter.hxx" #include "oox/xls/biffinputstream.hxx" #include "oox/xls/defnamesbuffer.hxx" @@ -55,7 +52,6 @@ using ::com::sun::star::uno::Sequence; using ::com::sun::star::uno::Exception; using ::com::sun::star::uno::UNO_QUERY; using ::com::sun::star::uno::UNO_QUERY_THROW; -using ::com::sun::star::lang::XMultiServiceFactory; using ::com::sun::star::table::CellAddress; using ::com::sun::star::table::CellRangeAddress; using ::com::sun::star::sheet::ComplexReference; @@ -67,12 +63,362 @@ using namespace ::com::sun::star::sheet::ReferenceFlags; namespace oox { namespace xls { +// ============================================================================ + +namespace { + +sal_uInt16 lclReadFmlaSize( BiffInputStream& rStrm, BiffType eBiff, const sal_uInt16* pnFmlaSize ) +{ + return pnFmlaSize ? *pnFmlaSize : ((eBiff == BIFF2) ? rStrm.readuInt8() : rStrm.readuInt16()); +} + +} // namespace + +// formula finalizer ========================================================== + +FormulaFinalizer::FormulaFinalizer( const OpCodeProvider& rOpCodeProv ) : + OpCodeProvider( rOpCodeProv ), + ApiOpCodes( getOpCodes() ) +{ + maTokens.reserve( 0x2000 ); +} + +ApiTokenSequence FormulaFinalizer::finalizeTokenArray( const ApiTokenSequence& rTokens ) +{ + maTokens.clear(); + if( rTokens.hasElements() ) + { + const ApiToken* pToken = rTokens.getConstArray(); + processTokens( pToken, pToken + rTokens.getLength() ); + } + return ContainerHelper::vectorToSequence( maTokens ); +} + +const FunctionInfo* FormulaFinalizer::resolveBadFuncName( const OUString& ) const +{ + return 0; +} + +OUString FormulaFinalizer::resolveDefinedName( sal_Int32 ) const +{ + return OUString(); +} + +const FunctionInfo* FormulaFinalizer::getFunctionInfo( ApiToken& orFuncToken ) +{ + // first, try to find a regular function info from token op-code + if( const FunctionInfo* pRegFuncInfo = getFuncInfoFromApiToken( orFuncToken ) ) + return pRegFuncInfo; + + // try to recognize a function from an external library + if( (orFuncToken.OpCode == OPCODE_BAD) && orFuncToken.Data.has< OUString >() ) + { + // virtual call to resolveBadFuncName() + if( const FunctionInfo* pLibFuncInfo = resolveBadFuncName( orFuncToken.Data.get< OUString >() ) ) + { + // write function op-code to the OPCODE_BAD token + orFuncToken.OpCode = pLibFuncInfo->mnApiOpCode; + // if it is an external function, insert programmatic function name + if( (orFuncToken.OpCode == OPCODE_EXTERNAL) && (pLibFuncInfo->maExtProgName.getLength() > 0) ) + orFuncToken.Data <<= pLibFuncInfo->maExtProgName; + else + orFuncToken.Data.clear(); // clear string from OPCODE_BAD + return pLibFuncInfo; + } + } + + // no success - return null + return 0; + +} + +const FunctionInfo* FormulaFinalizer::getExternCallInfo( ApiToken& orFuncToken, const ApiToken& rECToken ) +{ + // try to resolve the passed token to a supported sheet function + if( const FunctionInfo* pFuncInfo = getFuncInfoFromApiToken( rECToken ) ) + { + orFuncToken.OpCode = pFuncInfo->mnApiOpCode; + // programmatic add-in function name + if( (pFuncInfo->mnApiOpCode == OPCODE_EXTERNAL) && (pFuncInfo->maExtProgName.getLength() > 0) ) + orFuncToken.Data <<= pFuncInfo->maExtProgName; + // name of unsupported function, convert to OPCODE_BAD to preserve the name + else if( (pFuncInfo->mnApiOpCode == OPCODE_BAD) && (pFuncInfo->maOoxFuncName.getLength() > 0) ) + orFuncToken.Data <<= pFuncInfo->maOoxFuncName; + return pFuncInfo; + } + + // macro call or unknown function name, move data to function token + if( (rECToken.OpCode == OPCODE_MACRO) || (rECToken.OpCode == OPCODE_BAD) ) + orFuncToken = rECToken; + + // defined name used as function call, convert to OPCODE_BAD to preserve the name + if( (rECToken.OpCode == OPCODE_NAME) && rECToken.Data.has< sal_Int32 >() ) + { + OUString aDefName = resolveDefinedName( rECToken.Data.get< sal_Int32 >() ); + if( aDefName.getLength() > 0 ) + { + orFuncToken.OpCode = OPCODE_BAD; + orFuncToken.Data <<= aDefName; + } + } + + return 0; +} + +void FormulaFinalizer::processTokens( const ApiToken* pToken, const ApiToken* pTokenEnd ) +{ + while( pToken < pTokenEnd ) + { + // push the current token into the vector + bool bValid = appendFinalToken( *pToken ); + // try to process a function + if( const FunctionInfo* pFuncInfo = bValid ? getFunctionInfo( maTokens.back() ) : 0 ) + pToken = processParameters( *pFuncInfo, pToken + 1, pTokenEnd ); + // otherwise, go to next token + else + ++pToken; + } +} + +const ApiToken* FormulaFinalizer::processParameters( + const FunctionInfo& rFuncInfo, const ApiToken* pToken, const ApiToken* pTokenEnd ) +{ + // remember position of the token containing the function op-code + size_t nFuncNameIdx = maTokens.size() - 1; + + // process a function, if an OPCODE_OPEN token is following + OSL_ENSURE( (pToken < pTokenEnd) && (pToken->OpCode == OPCODE_OPEN), "FormulaFinalizer::processParameters - OPCODE_OPEN expected" ); + if( (pToken < pTokenEnd) && (pToken->OpCode == OPCODE_OPEN) ) + { + // append the OPCODE_OPEN token to the vector + maTokens.append( OPCODE_OPEN ); + + // store positions of OPCODE_OPEN, parameter separators, and OPCODE_CLOSE + ParameterPosVector aParams; + pToken = findParameters( aParams, pToken, pTokenEnd ); + OSL_ENSURE( aParams.size() >= 2, "FormulaFinalizer::processParameters - missing tokens" ); + size_t nParamCount = aParams.size() - 1; + + if( (nParamCount == 1) && isEmptyParameter( aParams[ 0 ] + 1, aParams[ 1 ] ) ) + { + /* Empty pair of parentheses -> function call without parameters, + process parameter, there might be spaces between parentheses. */ + processTokens( aParams[ 0 ] + 1, aParams[ 1 ] ); + } + else + { + const FunctionInfo* pRealFuncInfo = &rFuncInfo; + ParameterPosVector::const_iterator aPosIt = aParams.begin(); + + /* Preprocess EXTERN.CALL functions. The actual function name is + contained as reference to a defined name in the first (hidden) + parameter. */ + if( rFuncInfo.mnBiffFuncId == BIFF_FUNC_EXTERNCALL ) + { + ApiToken& rFuncToken = maTokens[ nFuncNameIdx ]; + rFuncToken.OpCode = OPCODE_NONAME; + + // try to initialize function token from first parameter + if( const ApiToken* pECToken = getSingleToken( *aPosIt + 1, *(aPosIt + 1) ) ) + if( const FunctionInfo* pECFuncInfo = getExternCallInfo( rFuncToken, *pECToken ) ) + pRealFuncInfo = pECFuncInfo; + + /* On success (something has been inserted into rFuncToken), + skip the first parameter. */ + if( rFuncToken.OpCode != OPCODE_NONAME ) + { + --nParamCount; + ++aPosIt; + } + } + + // process all parameters + FuncInfoParamClassIterator aClassIt( *pRealFuncInfo ); + size_t nLastValidSize = maTokens.size(); + size_t nLastValidCount = 0; + for( size_t nParam = 0; nParam < nParamCount; ++nParam, ++aPosIt, ++aClassIt ) + { + // add embedded Calc-only parameters + if( aClassIt.isCalcOnlyParam() ) + { + appendCalcOnlyParameter( *pRealFuncInfo, nParam ); + while( aClassIt.isCalcOnlyParam() ) ++aClassIt; + } + + const ApiToken* pParamBegin = *aPosIt + 1; + const ApiToken* pParamEnd = *(aPosIt + 1); + bool bIsEmpty = isEmptyParameter( pParamBegin, pParamEnd ); + + if( !aClassIt.isExcelOnlyParam() ) + { + // replace empty second and third parameter in IF function with zeros + if( (pRealFuncInfo->mnOobFuncId == OOBIN_FUNC_IF) && ((nParam == 1) || (nParam == 2)) && bIsEmpty ) + { + maTokens.append< double >( OPCODE_PUSH, 0.0 ); + bIsEmpty = false; + } + else + { + // process all tokens of the parameter + processTokens( pParamBegin, pParamEnd ); + } + // append parameter separator token + maTokens.append( OPCODE_SEP ); + } + + /* #84453# Update size of new token sequence with valid parameters + to be able to remove trailing optional empty parameters. */ + if( !bIsEmpty || (nParam < pRealFuncInfo->mnMinParamCount) ) + { + nLastValidSize = maTokens.size(); + nLastValidCount = nParam + 1; + } + } + + // #84453# remove trailing optional empty parameters + maTokens.resize( nLastValidSize ); + + // add trailing Calc-only parameters + if( aClassIt.isCalcOnlyParam() ) + appendCalcOnlyParameter( *pRealFuncInfo, nLastValidCount ); + + // add optional parameters that are required in Calc + appendRequiredParameters( *pRealFuncInfo, nLastValidCount ); + + // remove last parameter separator token + if( maTokens.back().OpCode == OPCODE_SEP ) + maTokens.pop_back(); + } + + /* Append the OPCODE_CLOSE token to the vector, but only if there is + no OPCODE_BAD token at the end, this token already contains the + trailing closing parentheses. */ + if( (pTokenEnd - 1)->OpCode != OPCODE_BAD ) + maTokens.append( OPCODE_CLOSE ); + } + + /* Replace OPCODE_EXTERNAL with OPCODE_NONAME to get #NAME! error in cell, + if no matching add-in function was found. */ + ApiToken& rFuncNameToken = maTokens[ nFuncNameIdx ]; + if( (rFuncNameToken.OpCode == OPCODE_EXTERNAL) && !rFuncNameToken.Data.hasValue() ) + rFuncNameToken.OpCode = OPCODE_NONAME; + + return pToken; +} + +bool FormulaFinalizer::isEmptyParameter( const ApiToken* pToken, const ApiToken* pTokenEnd ) const +{ + while( (pToken < pTokenEnd) && (pToken->OpCode == OPCODE_SPACES) ) ++pToken; + if( (pToken < pTokenEnd) && (pToken->OpCode == OPCODE_MISSING) ) ++pToken; + while( (pToken < pTokenEnd) && (pToken->OpCode == OPCODE_SPACES) ) ++pToken; + return pToken == pTokenEnd; +} + +const ApiToken* FormulaFinalizer::getSingleToken( const ApiToken* pToken, const ApiToken* pTokenEnd ) const +{ + const ApiToken* pSingleToken = 0; + // skip leading whitespace tokens + while( (pToken < pTokenEnd) && (pToken->OpCode == OPCODE_SPACES) ) ++pToken; + // remember first non-whitespace token + if( pToken < pTokenEnd ) pSingleToken = pToken++; + // skip trailing whitespace tokens + while( (pToken < pTokenEnd) && (pToken->OpCode == OPCODE_SPACES) ) ++pToken; + // return null, if other non-whitespace tokens follow + return (pToken == pTokenEnd) ? pSingleToken : 0; +} + +const ApiToken* FormulaFinalizer::skipParentheses( const ApiToken* pToken, const ApiToken* pTokenEnd ) const +{ + // skip tokens between OPCODE_OPEN and OPCODE_CLOSE + OSL_ENSURE( (pToken < pTokenEnd) && (pToken->OpCode == OPCODE_OPEN), "skipParentheses - OPCODE_OPEN expected" ); + ++pToken; + while( (pToken < pTokenEnd) && (pToken->OpCode != OPCODE_CLOSE) ) + { + if( pToken->OpCode == OPCODE_OPEN ) + pToken = skipParentheses( pToken, pTokenEnd ); + else + ++pToken; + } + // skip the OPCODE_CLOSE token + OSL_ENSURE( ((pToken < pTokenEnd) && (pToken->OpCode == OPCODE_CLOSE)) || ((pTokenEnd - 1)->OpCode == OPCODE_BAD), "skipParentheses - OPCODE_CLOSE expected" ); + return (pToken < pTokenEnd) ? (pToken + 1) : pTokenEnd; +} + +const ApiToken* FormulaFinalizer::findParameters( ParameterPosVector& rParams, + const ApiToken* pToken, const ApiToken* pTokenEnd ) const +{ + // push position of OPCODE_OPEN + OSL_ENSURE( (pToken < pTokenEnd) && (pToken->OpCode == OPCODE_OPEN), "FormulaFinalizer::findParameters - OPCODE_OPEN expected" ); + rParams.push_back( pToken++ ); + + // find positions of parameter separators + while( (pToken < pTokenEnd) && (pToken->OpCode != OPCODE_CLOSE) ) + { + if( pToken->OpCode == OPCODE_OPEN ) + pToken = skipParentheses( pToken, pTokenEnd ); + else if( pToken->OpCode == OPCODE_SEP ) + rParams.push_back( pToken++ ); + else + ++pToken; + } + + // push position of OPCODE_CLOSE + OSL_ENSURE( ((pToken < pTokenEnd) && (pToken->OpCode == OPCODE_CLOSE)) || ((pTokenEnd - 1)->OpCode == OPCODE_BAD), "FormulaFinalizer::findParameters - OPCODE_CLOSE expected" ); + rParams.push_back( pToken ); + return (pToken < pTokenEnd) ? (pToken + 1) : pTokenEnd; +} + +void FormulaFinalizer::appendCalcOnlyParameter( const FunctionInfo& rFuncInfo, size_t nParam ) +{ + (void)nParam; // prevent 'unused' warning + switch( rFuncInfo.mnOobFuncId ) + { + case OOBIN_FUNC_FLOOR: + case OOBIN_FUNC_CEILING: + OSL_ENSURE( nParam == 2, "FormulaFinalizer::appendCalcOnlyParameter - unexpected parameter index" ); + maTokens.append< double >( OPCODE_PUSH, 1.0 ); + maTokens.append( OPCODE_SEP ); + break; + } +} + +void FormulaFinalizer::appendRequiredParameters( const FunctionInfo& rFuncInfo, size_t nParamCount ) +{ + switch( rFuncInfo.mnOobFuncId ) + { + case OOBIN_FUNC_WEEKNUM: + if( nParamCount == 1 ) + { + maTokens.append< double >( OPCODE_PUSH, 1.0 ); + maTokens.append( OPCODE_SEP ); + } + break; + } +} + +bool FormulaFinalizer::appendFinalToken( const ApiToken& rToken ) +{ + // replace OPCODE_MACRO without macro name with #NAME? error code + bool bValid = (rToken.OpCode != OPCODE_MACRO) || rToken.Data.hasValue(); + if( bValid ) + { + maTokens.push_back( rToken ); + } + else + { + maTokens.append( OPCODE_ARRAY_OPEN ); + maTokens.append( OPCODE_PUSH, BiffHelper::calcDoubleFromError( BIFF_ERR_NAME ) ); + maTokens.append( OPCODE_ARRAY_CLOSE ); + } + return bValid; +} + // parser implementation base ================================================= -class FormulaParserImpl : public OpCodeProvider +class FormulaParserImpl : public FormulaFinalizer, public WorkbookHelper { public: - explicit FormulaParserImpl( const OpCodeProvider& rOpCodeProv ); + explicit FormulaParserImpl( const FormulaParser& rParent ); /** Converts an XML formula string. */ virtual void importOoxFormula( @@ -95,6 +441,9 @@ public: FormulaContext& rContext, const ApiTokenSequence& rTokens ); + /** Tries to resolve the passed ref-id to an OLE target URL. */ + OUString resolveOleTarget( sal_Int32 nRefId ) const; + protected: typedef ::std::pair< sal_Int32, bool > WhiteSpace; typedef ::std::vector< WhiteSpace > WhiteSpaceVec; @@ -194,23 +543,11 @@ private: void convertReference3d( SingleReference& orApiRef, sal_Int32 nSheet, bool bSameSheet, const BinSingleRef2d& rRef, bool bDeleted, bool bRelativeAsOffset ) const; void convertReference3d( ComplexReference& orApiRef, const LinkSheetRange& rSheetRange, const BinSingleRef2d& rRef1, const BinSingleRef2d& rRef2, bool bDeleted, bool bRelativeAsOffset ) const; +private: // finalize token sequence ------------------------------------------------ - typedef ::std::vector< const ApiToken* > ParameterPosVector; - - void processTokens( const ApiToken* pToken, const ApiToken* pTokenEnd ); - const ApiToken* processParameters( const FunctionInfo& rFuncInfo, const ApiToken* pToken, const ApiToken* pTokenEnd ); - - const FunctionInfo* getFuncInfoFromLibFuncName( const ApiToken& rToken ) const; - bool isEmptyParameter( const ApiToken* pToken, const ApiToken* pTokenEnd ) const; - const ApiToken* getExternCallToken( const ApiToken* pToken, const ApiToken* pTokenEnd ) const; - const FunctionInfo* convertExternCallParam( ApiToken& orFuncToken, const ApiToken& rECToken ) const; - const ApiToken* skipParentheses( const ApiToken* pToken, const ApiToken* pTokenEnd ) const; - const ApiToken* findParameters( ParameterPosVector& rParams, const ApiToken* pToken, const ApiToken* pTokenEnd ) const; - void appendCalcOnlyParameter( const FunctionInfo& rFuncInfo, size_t nParam ); - void appendRequiredParameters( const FunctionInfo& rFuncInfo, size_t nParamCount ); - - void appendFinalToken( const ApiToken& rToken ); + virtual const FunctionInfo* resolveBadFuncName( const OUString& rTokenData ) const; + virtual ::rtl::OUString resolveDefinedName( sal_Int32 nTokenIndex ) const; protected: const sal_Int32 mnMaxApiCol; /// Maximum column index in own document. @@ -232,12 +569,13 @@ private: // ---------------------------------------------------------------------------- -FormulaParserImpl::FormulaParserImpl( const OpCodeProvider& rOpCodeProv ) : - OpCodeProvider( rOpCodeProv ), - mnMaxApiCol( rOpCodeProv.getAddressConverter().getMaxApiAddress().Column ), - mnMaxApiRow( rOpCodeProv.getAddressConverter().getMaxApiAddress().Row ), - mnMaxXlsCol( rOpCodeProv.getAddressConverter().getMaxXlsAddress().Column ), - mnMaxXlsRow( rOpCodeProv.getAddressConverter().getMaxXlsAddress().Row ), +FormulaParserImpl::FormulaParserImpl( const FormulaParser& rParent ) : + FormulaFinalizer( rParent ), + WorkbookHelper( rParent ), + mnMaxApiCol( rParent.getAddressConverter().getMaxApiAddress().Column ), + mnMaxApiRow( rParent.getAddressConverter().getMaxApiAddress().Row ), + mnMaxXlsCol( rParent.getAddressConverter().getMaxXlsAddress().Column ), + mnMaxXlsRow( rParent.getAddressConverter().getMaxXlsAddress().Row ), mpContext( 0 ) { // reserve enough space to make resize(), push_back() etc. cheap @@ -270,6 +608,15 @@ void FormulaParserImpl::setFormula( FormulaContext& rContext, const ApiTokenSequ finalizeImport( rTokens ); } +OUString FormulaParserImpl::resolveOleTarget( sal_Int32 nRefId ) const +{ + const ExternalLink* pExtLink = getExternalLinks().getExternalLink( nRefId ).get(); + OSL_ENSURE( pExtLink && (pExtLink->getLinkType() == LINKTYPE_OLE), "FormulaParserImpl::resolveOleTarget - missing or wrong link" ); + if( pExtLink && (pExtLink->getLinkType() == LINKTYPE_OLE) ) + return getBaseFilter().getAbsoluteUrl( pExtLink->getTargetUrl() ); + return OUString(); +} + void FormulaParserImpl::initializeImport( FormulaContext& rContext ) { maTokenStorage.clear(); @@ -280,11 +627,9 @@ void FormulaParserImpl::initializeImport( FormulaContext& rContext ) void FormulaParserImpl::finalizeImport( const ApiTokenSequence& rTokens ) { - maTokenStorage.clear(); - const ApiToken* pToken = rTokens.getConstArray(); - processTokens( pToken, pToken + rTokens.getLength() ); - if( !maTokenStorage.empty() ) - mpContext->setTokens( ContainerHelper::vectorToSequence( maTokenStorage ) ); + ApiTokenSequence aFinalTokens = finalizeTokenArray( rTokens ); + if( aFinalTokens.hasElements() ) + mpContext->setTokens( aFinalTokens ); } void FormulaParserImpl::finalizeImport() @@ -862,342 +1207,34 @@ void FormulaParserImpl::convertReference3d( ComplexReference& orApiRef, const Li // finalize token sequence ---------------------------------------------------- -void FormulaParserImpl::processTokens( const ApiToken* pToken, const ApiToken* pTokenEnd ) +const FunctionInfo* FormulaParserImpl::resolveBadFuncName( const OUString& rTokenData ) const { - while( pToken < pTokenEnd ) + /* Try to parse calls to library functions. The format of such a function + call is "[n]!funcname", n>0 being the link identifier of the function + library spreadsheet file. */ + sal_Int32 nBracketOpen = rTokenData.indexOf( '[' ); + sal_Int32 nBracketClose = rTokenData.indexOf( ']' ); + sal_Int32 nExclamation = rTokenData.indexOf( '!' ); + if( (0 == nBracketOpen) && (nBracketOpen + 1 < nBracketClose) && (nBracketClose + 1 == nExclamation) && (nExclamation + 1 < rTokenData.getLength()) ) { - // push the current token into the vector - appendFinalToken( *pToken ); - const FunctionInfo* pFuncInfo; - // try to process a function - if( (pFuncInfo = getFuncInfoFromApiToken( *pToken )) != 0 ) + sal_Int32 nRefId = rTokenData.copy( nBracketOpen + 1, nBracketClose - nBracketOpen - 1 ).toInt32(); + const ExternalLink* pExtLink = getExternalLinks().getExternalLink( nRefId ).get(); + if( pExtLink && (pExtLink->getLinkType() == LINKTYPE_LIBRARY) ) { - pToken = processParameters( *pFuncInfo, pToken + 1, pTokenEnd ); - } - // try to process a function from an external library - else if( (pFuncInfo = getFuncInfoFromLibFuncName( *pToken )) != 0 ) - { - ApiToken& rFuncToken = maTokenStorage.back(); - rFuncToken.OpCode = pFuncInfo->mnApiOpCode; - if( (rFuncToken.OpCode == OPCODE_EXTERNAL) && (pFuncInfo->maExtProgName.getLength() > 0) ) - rFuncToken.Data <<= pFuncInfo->maExtProgName; - else - rFuncToken.Data.clear(); // clear string from OPCODE_BAD - pToken = processParameters( *pFuncInfo, pToken + 1, pTokenEnd ); - } - // otherwise, go to next token - else - { - ++pToken; - } - } -} - -namespace { - -bool lclTokenHasChar( const ApiToken& rToken, sal_Int32 nOpCode, sal_Unicode cChar ) -{ - return (rToken.OpCode == nOpCode) && rToken.Data.has< OUString >() && (rToken.Data.get< OUString >() == OUString( cChar )); -} - -bool lclTokenHasDouble( const ApiToken& rToken, sal_Int32 nOpCode ) -{ - return (rToken.OpCode == nOpCode) && rToken.Data.has< double >(); -} - -} // namespace - -const ApiToken* FormulaParserImpl::processParameters( - const FunctionInfo& rFuncInfo, const ApiToken* pToken, const ApiToken* pTokenEnd ) -{ - /* OOXML import of library functions pushes the external reference "[n]!" - as BAD/PUSH/BAD/BAD tokens in front of the function name. Try to find - and remove them here. TODO: This will change with CWS mooxlsc, there, - the reference ID and function name are passed together in a BAD token, - see getFuncInfoFromLibFuncName(). */ - if( (rFuncInfo.meFuncLibType != FUNCLIB_UNKNOWN) && (maTokenStorage.size() >= 5) ) - { - sal_Size nSize = maTokenStorage.size(); - if( lclTokenHasChar( maTokenStorage[ nSize - 5 ], OPCODE_BAD, '[' ) && - lclTokenHasDouble( maTokenStorage[ nSize - 4 ], OPCODE_PUSH ) && - lclTokenHasChar( maTokenStorage[ nSize - 3 ], OPCODE_BAD, ']' ) && - lclTokenHasChar( maTokenStorage[ nSize - 2 ], OPCODE_BAD, '!' ) ) - { - maTokenStorage.erase( maTokenStorage.end() - 5, maTokenStorage.end() - 1 ); - } - } - - // remember position of the token containing the function op-code - size_t nFuncNameIdx = maTokenStorage.size() - 1; - - // process a function, if an OPCODE_OPEN token is following - OSL_ENSURE( (pToken < pTokenEnd) && (pToken->OpCode == OPCODE_OPEN), "FormulaParserImpl::processParameters - OPCODE_OPEN expected" ); - if( (pToken < pTokenEnd) && (pToken->OpCode == OPCODE_OPEN) ) - { - // append the OPCODE_OPEN token to the vector - maTokenStorage.append( OPCODE_OPEN ); - - // store positions of OPCODE_OPEN, parameter separators, and OPCODE_CLOSE - ParameterPosVector aParams; - pToken = findParameters( aParams, pToken, pTokenEnd ); - OSL_ENSURE( aParams.size() >= 2, "FormulaParserImpl::processParameters - missing tokens" ); - size_t nParamCount = aParams.size() - 1; - - if( (nParamCount == 1) && isEmptyParameter( aParams[ 0 ] + 1, aParams[ 1 ] ) ) - { - /* Empty pair of parentheses -> function call without parameters, - process parameter, there might be spaces between parentheses. */ - processTokens( aParams[ 0 ] + 1, aParams[ 1 ] ); - } - else - { - const FunctionInfo* pRealFuncInfo = &rFuncInfo; - ParameterPosVector::const_iterator aPosIt = aParams.begin(); - - // preprocess add-ins, first parameter is reference to function name - if( rFuncInfo.mnBiffFuncId == BIFF_FUNC_EXTERNCALL ) - { - maTokenStorage[ nFuncNameIdx ].OpCode = OPCODE_NONAME; - // try to initialize function token from first parameter - if( const ApiToken* pECToken = getExternCallToken( *aPosIt + 1, *(aPosIt + 1) ) ) - if( const FunctionInfo* pECFuncInfo = convertExternCallParam( maTokenStorage[ nFuncNameIdx ], *pECToken ) ) - pRealFuncInfo = pECFuncInfo; - // on success, ignore first parameter - if( maTokenStorage[ nFuncNameIdx ].OpCode != OPCODE_NONAME ) - { - --nParamCount; - ++aPosIt; - } - } - - // process all parameters - FuncInfoParamClassIterator aClassIt( *pRealFuncInfo ); - size_t nLastValidSize = maTokenStorage.size(); - size_t nLastValidCount = 0; - for( size_t nParam = 0; nParam < nParamCount; ++nParam, ++aPosIt, ++aClassIt ) - { - // add embedded Calc-only parameters - if( aClassIt.isCalcOnlyParam() ) - { - appendCalcOnlyParameter( *pRealFuncInfo, nParam ); - while( aClassIt.isCalcOnlyParam() ) ++aClassIt; - } - - const ApiToken* pParamBegin = *aPosIt + 1; - const ApiToken* pParamEnd = *(aPosIt + 1); - bool bIsEmpty = isEmptyParameter( pParamBegin, pParamEnd ); - - if( !aClassIt.isExcelOnlyParam() ) - { - // replace empty second and third parameter in IF function with zeros - if( (pRealFuncInfo->mnOobFuncId == OOBIN_FUNC_IF) && ((nParam == 1) || (nParam == 2)) && bIsEmpty ) - { - maTokenStorage.append< double >( OPCODE_PUSH, 0.0 ); - bIsEmpty = false; - } - else - { - // process all tokens of the parameter - processTokens( pParamBegin, pParamEnd ); - } - // append parameter separator token - maTokenStorage.append( OPCODE_SEP ); - } - - /* #84453# Update size of new token sequence with valid parameters - to be able to remove trailing optional empty parameters. */ - if( !bIsEmpty || (nParam < pRealFuncInfo->mnMinParamCount) ) - { - nLastValidSize = maTokenStorage.size(); - nLastValidCount = nParam + 1; - } - } - - // #84453# remove trailing optional empty parameters - maTokenStorage.resize( nLastValidSize ); - - // add trailing Calc-only parameters - if( aClassIt.isCalcOnlyParam() ) - appendCalcOnlyParameter( *pRealFuncInfo, nLastValidCount ); - - // add optional parameters that are required in Calc - appendRequiredParameters( *pRealFuncInfo, nLastValidCount ); - - // remove last parameter separator token - if( maTokenStorage.back().OpCode == OPCODE_SEP ) - maTokenStorage.pop_back(); - } - - /* Append the OPCODE_CLOSE token to the vector, but only if there is - no OPCODE_BAD token at the end, this token already contains the - trailing closing parentheses. */ - if( (pTokenEnd - 1)->OpCode != OPCODE_BAD ) - maTokenStorage.append( OPCODE_CLOSE ); - } - - /* Replace OPCODE_EXTERNAL with OPCODE_NONAME to get #NAME! error in cell, - if no matching add-in function was found. */ - ApiToken& rFuncNameToken = maTokenStorage[ nFuncNameIdx ]; - if( (rFuncNameToken.OpCode == OPCODE_EXTERNAL) && !rFuncNameToken.Data.hasValue() ) - rFuncNameToken.OpCode = OPCODE_NONAME; - - return pToken; -} - -const FunctionInfo* FormulaParserImpl::getFuncInfoFromLibFuncName( const ApiToken& rToken ) const -{ - // try to parse calls to library functions - if( (rToken.OpCode == OPCODE_BAD) && rToken.Data.has< OUString >() ) - { - // format of the function call is "[n]!funcname", n being the link to the library - OUString aString = rToken.Data.get< OUString >(); - sal_Int32 nBracketOpen = aString.indexOf( '[' ); - sal_Int32 nBracketClose = aString.indexOf( ']' ); - sal_Int32 nExclamation = aString.indexOf( '!' ); - if( (0 == nBracketOpen) && (nBracketOpen + 1 < nBracketClose) && (nBracketClose + 1 == nExclamation) && (nExclamation + 1 < aString.getLength()) ) - { - sal_Int32 nRefId = aString.copy( nBracketOpen + 1, nBracketClose - nBracketOpen - 1 ).toInt32(); - const ExternalLink* pExtLink = getExternalLinks().getExternalLink( nRefId ).get(); - if( pExtLink && (pExtLink->getLinkType() == LINKTYPE_LIBRARY) ) - if( const FunctionInfo* pFuncInfo = getFuncInfoFromOoxFuncName( aString.copy( nExclamation + 1 ).toAsciiUpperCase() ) ) - if( (pFuncInfo->meFuncLibType != FUNCLIB_UNKNOWN) && (pFuncInfo->meFuncLibType == pExtLink->getFuncLibraryType()) ) - return pFuncInfo; + OUString aFuncName = rTokenData.copy( nExclamation + 1 ).toAsciiUpperCase(); + if( const FunctionInfo* pFuncInfo = getFuncInfoFromOoxFuncName( aFuncName ) ) + if( (pFuncInfo->meFuncLibType != FUNCLIB_UNKNOWN) && (pFuncInfo->meFuncLibType == pExtLink->getFuncLibraryType()) ) + return pFuncInfo; } } return 0; } -bool FormulaParserImpl::isEmptyParameter( const ApiToken* pToken, const ApiToken* pTokenEnd ) const +OUString FormulaParserImpl::resolveDefinedName( sal_Int32 nTokenIndex ) const { - while( (pToken < pTokenEnd) && (pToken->OpCode == OPCODE_SPACES) ) ++pToken; - if( (pToken < pTokenEnd) && (pToken->OpCode == OPCODE_MISSING) ) ++pToken; - while( (pToken < pTokenEnd) && (pToken->OpCode == OPCODE_SPACES) ) ++pToken; - return pToken == pTokenEnd; -} - -const ApiToken* FormulaParserImpl::getExternCallToken( const ApiToken* pToken, const ApiToken* pTokenEnd ) const -{ - const ApiToken* pECToken = 0; - while( (pToken < pTokenEnd) && (pToken->OpCode == OPCODE_SPACES) ) ++pToken; - if( pToken < pTokenEnd ) pECToken = pToken++; - while( (pToken < pTokenEnd) && (pToken->OpCode == OPCODE_SPACES) ) ++pToken; - return (pToken == pTokenEnd) ? pECToken : 0; -} - -const FunctionInfo* FormulaParserImpl::convertExternCallParam( ApiToken& orFuncToken, const ApiToken& rECToken ) const -{ - if( const FunctionInfo* pFuncInfo = getFuncInfoFromApiToken( rECToken ) ) - { - orFuncToken.OpCode = pFuncInfo->mnApiOpCode; - // programmatic add-in function name - if( (pFuncInfo->mnApiOpCode == OPCODE_EXTERNAL) && (pFuncInfo->maExtProgName.getLength() > 0) ) - orFuncToken.Data <<= pFuncInfo->maExtProgName; - // name of unsupported function, convert to OPCODE_BAD to preserve the name - else if( (pFuncInfo->mnApiOpCode == OPCODE_BAD) && (pFuncInfo->maOoxFuncName.getLength() > 0) ) - orFuncToken.Data <<= pFuncInfo->maOoxFuncName; - return pFuncInfo; - } - - if( (rECToken.OpCode == OPCODE_MACRO) || (rECToken.OpCode == OPCODE_BAD) ) - { - // macro call or unknown function name, move data to function token - orFuncToken = rECToken; - } - else if( rECToken.OpCode == OPCODE_NAME ) - { - // defined name used as function call, convert to OPCODE_BAD to preserve the name - sal_Int32 nTokenIndex = 0; - if( rECToken.Data >>= nTokenIndex ) - { - if( const DefinedName* pDefName = getDefinedNames().getByTokenIndex( nTokenIndex ).get() ) - { - orFuncToken.OpCode = OPCODE_BAD; - orFuncToken.Data <<= pDefName->getCalcName(); - } - } - } - return 0; -} - -const ApiToken* FormulaParserImpl::skipParentheses( const ApiToken* pToken, const ApiToken* pTokenEnd ) const -{ - // skip tokens between OPCODE_OPEN and OPCODE_CLOSE - OSL_ENSURE( (pToken < pTokenEnd) && (pToken->OpCode == OPCODE_OPEN), "skipParentheses - OPCODE_OPEN expected" ); - ++pToken; - while( (pToken < pTokenEnd) && (pToken->OpCode != OPCODE_CLOSE) ) - { - if( pToken->OpCode == OPCODE_OPEN ) - pToken = skipParentheses( pToken, pTokenEnd ); - else - ++pToken; - } - // skip the OPCODE_CLOSE token - OSL_ENSURE( ((pToken < pTokenEnd) && (pToken->OpCode == OPCODE_CLOSE)) || ((pTokenEnd - 1)->OpCode == OPCODE_BAD), "skipParentheses - OPCODE_CLOSE expected" ); - return (pToken < pTokenEnd) ? (pToken + 1) : pTokenEnd; -} - -const ApiToken* FormulaParserImpl::findParameters( ParameterPosVector& rParams, - const ApiToken* pToken, const ApiToken* pTokenEnd ) const -{ - // push position of OPCODE_OPEN - OSL_ENSURE( (pToken < pTokenEnd) && (pToken->OpCode == OPCODE_OPEN), "FormulaParserImpl::findParameters - OPCODE_OPEN expected" ); - rParams.push_back( pToken++ ); - - // find positions of parameter separators - while( (pToken < pTokenEnd) && (pToken->OpCode != OPCODE_CLOSE) ) - { - if( pToken->OpCode == OPCODE_OPEN ) - pToken = skipParentheses( pToken, pTokenEnd ); - else if( pToken->OpCode == OPCODE_SEP ) - rParams.push_back( pToken++ ); - else - ++pToken; - } - - // push position of OPCODE_CLOSE - OSL_ENSURE( ((pToken < pTokenEnd) && (pToken->OpCode == OPCODE_CLOSE)) || ((pTokenEnd - 1)->OpCode == OPCODE_BAD), "FormulaParserImpl::findParameters - OPCODE_CLOSE expected" ); - rParams.push_back( pToken ); - return (pToken < pTokenEnd) ? (pToken + 1) : pTokenEnd; -} - -void FormulaParserImpl::appendCalcOnlyParameter( const FunctionInfo& rFuncInfo, size_t nParam ) -{ - (void)nParam; // prevent 'unused' warning - switch( rFuncInfo.mnOobFuncId ) - { - case OOBIN_FUNC_FLOOR: - case OOBIN_FUNC_CEILING: - OSL_ENSURE( nParam == 2, "FormulaParserImpl::appendCalcOnlyParameter - unexpected parameter index" ); - maTokenStorage.append< double >( OPCODE_PUSH, 1.0 ); - maTokenStorage.append( OPCODE_SEP ); - break; - } -} - -void FormulaParserImpl::appendRequiredParameters( const FunctionInfo& rFuncInfo, size_t nParamCount ) -{ - switch( rFuncInfo.mnOobFuncId ) - { - case OOBIN_FUNC_WEEKNUM: - if( nParamCount == 1 ) - { - maTokenStorage.append< double >( OPCODE_PUSH, 1.0 ); - maTokenStorage.append( OPCODE_SEP ); - } - break; - } -} - -void FormulaParserImpl::appendFinalToken( const ApiToken& rToken ) -{ - if( (rToken.OpCode == OPCODE_MACRO) && !rToken.Data.hasValue() ) - { - maTokenStorage.append( OPCODE_ARRAY_OPEN ); - maTokenStorage.append( OPCODE_PUSH, BiffHelper::calcDoubleFromError( BIFF_ERR_NAME ) ); - maTokenStorage.append( OPCODE_ARRAY_CLOSE ); - } - else - maTokenStorage.push_back( rToken ); + if( const DefinedName* pDefName = getDefinedNames().getByTokenIndex( nTokenIndex ).get() ) + return pDefName->getCalcName(); + return OUString(); } // OOX parser implementation ================================================== @@ -1205,7 +1242,7 @@ void FormulaParserImpl::appendFinalToken( const ApiToken& rToken ) class OoxFormulaParserImpl : public FormulaParserImpl { public: - explicit OoxFormulaParserImpl( const OpCodeProvider& rOpCodeProv ); + explicit OoxFormulaParserImpl( const FormulaParser& rParent ); virtual void importOoxFormula( FormulaContext& rContext, @@ -1247,49 +1284,30 @@ private: bool pushOobFunction( sal_uInt16 nFuncId, sal_uInt8 nParamCount ); private: - Reference< XFormulaParser > mxParser; - PropertySet maParserProps; + ApiParserWrapper maApiParser; /// Wrapper for the API formula parser object. sal_Int64 mnAddDataPos; /// Current stream position for additional data (tExp, tArray, tMemArea). bool mbNeedExtRefs; /// True = parser needs initialization of external reference info. }; // ---------------------------------------------------------------------------- -OoxFormulaParserImpl::OoxFormulaParserImpl( const OpCodeProvider& rOpCodeProv ) : - FormulaParserImpl( rOpCodeProv ), +OoxFormulaParserImpl::OoxFormulaParserImpl( const FormulaParser& rParent ) : + FormulaParserImpl( rParent ), + maApiParser( rParent.getDocumentFactory(), rParent ), mnAddDataPos( 0 ), mbNeedExtRefs( true ) { - try - { - Reference< XMultiServiceFactory > xFactory( getDocument(), UNO_QUERY_THROW ); - mxParser.set( xFactory->createInstance( CREATE_OUSTRING( "com.sun.star.sheet.FormulaParser" ) ), UNO_QUERY_THROW ); - } - catch( Exception& ) - { - } - OSL_ENSURE( mxParser.is(), "OoxFormulaParserImpl::OoxFormulaParserImpl - cannot create formula parser" ); - maParserProps.set( mxParser ); - maParserProps.setProperty( PROP_CompileEnglish, true ); - maParserProps.setProperty( PROP_FormulaConvention, ::com::sun::star::sheet::AddressConvention::XL_OOX ); - maParserProps.setProperty( PROP_IgnoreLeadingSpaces, false ); - maParserProps.setProperty( PROP_OpCodeMap, getOoxParserMap() ); } -void OoxFormulaParserImpl::importOoxFormula( - FormulaContext& rContext, const OUString& rFormulaString ) +void OoxFormulaParserImpl::importOoxFormula( FormulaContext& rContext, const OUString& rFormulaString ) { - if( mxParser.is() ) + if( mbNeedExtRefs ) { - if( mbNeedExtRefs ) - { - maParserProps.setProperty( PROP_ExternalLinks, getExternalLinks().getLinkInfos() ); - mbNeedExtRefs = false; - } - maParserProps.setProperty( PROP_ReferencePosition, rContext.getBaseAddress() ); - initializeImport( rContext ); - finalizeImport( mxParser->parseFormula( rFormulaString ) ); + maApiParser.getParserProperties().setProperty( PROP_ExternalLinks, getExternalLinks().getLinkInfos() ); + mbNeedExtRefs = false; } + initializeImport( rContext ); + finalizeImport( maApiParser.parseFormula( rFormulaString, rContext.getBaseAddress() ) ); } void OoxFormulaParserImpl::importOobFormula( FormulaContext& rContext, RecordInputStream& rStrm ) @@ -1826,7 +1844,7 @@ bool lclIsValidNlrRange( const BiffNlr& rNlr, const BinRange& rRange, bool bRow class BiffFormulaParserImpl : public FormulaParserImpl { public: - explicit BiffFormulaParserImpl( const OpCodeProvider& rOpCodeProv ); + explicit BiffFormulaParserImpl( const FormulaParser& rParent ); virtual void importBiffFormula( FormulaContext& rContext, @@ -1927,8 +1945,8 @@ private: // ---------------------------------------------------------------------------- -BiffFormulaParserImpl::BiffFormulaParserImpl( const OpCodeProvider& rOpCodeProv ) : - FormulaParserImpl( rOpCodeProv ), +BiffFormulaParserImpl::BiffFormulaParserImpl( const FormulaParser& rParent ) : + FormulaParserImpl( rParent ), mnAddDataPos( 0 ), mnCurrRefId( 0 ) { @@ -2054,7 +2072,7 @@ void BiffFormulaParserImpl::importBiffFormula( FormulaContext& rContext, initializeImport( rContext ); mnCurrRefId = 0; - sal_uInt16 nFmlaSize = pnFmlaSize ? *pnFmlaSize : ((getBiff() == BIFF2) ? rStrm.readuInt8() : rStrm.readuInt16()); + sal_uInt16 nFmlaSize = lclReadFmlaSize( rStrm, getBiff(), pnFmlaSize ); sal_Int64 nEndPos = mnAddDataPos = rStrm.tell() + nFmlaSize; bool bRelativeAsOffset = getFormulaContext().isRelativeAsOffset(); @@ -2066,73 +2084,77 @@ void BiffFormulaParserImpl::importBiffFormula( FormulaContext& rContext, sal_uInt8 nTokenClass = nTokenId & BIFF_TOKCLASS_MASK; sal_uInt8 nBaseId = nTokenId & BIFF_TOKID_MASK; - if( nTokenClass == BIFF_TOKCLASS_NONE ) + bOk = !getFlag( nTokenId, BIFF_TOKFLAG_INVALID ); + if( bOk ) { - // base tokens - switch( nBaseId ) + if( nTokenClass == BIFF_TOKCLASS_NONE ) { - case BIFF_TOKID_EXP: bOk = (this->*mpImportExpToken)( rStrm ); break; - case BIFF_TOKID_TBL: bOk = false; /* multiple op. will be set externally */ break; - case BIFF_TOKID_ADD: bOk = pushBinaryOperator( OPCODE_ADD ); break; - case BIFF_TOKID_SUB: bOk = pushBinaryOperator( OPCODE_SUB ); break; - case BIFF_TOKID_MUL: bOk = pushBinaryOperator( OPCODE_MULT ); break; - case BIFF_TOKID_DIV: bOk = pushBinaryOperator( OPCODE_DIV ); break; - case BIFF_TOKID_POWER: bOk = pushBinaryOperator( OPCODE_POWER ); break; - case BIFF_TOKID_CONCAT: bOk = pushBinaryOperator( OPCODE_CONCAT ); break; - case BIFF_TOKID_LT: bOk = pushBinaryOperator( OPCODE_LESS ); break; - case BIFF_TOKID_LE: bOk = pushBinaryOperator( OPCODE_LESS_EQUAL ); break; - case BIFF_TOKID_EQ: bOk = pushBinaryOperator( OPCODE_EQUAL ); break; - case BIFF_TOKID_GE: bOk = pushBinaryOperator( OPCODE_GREATER_EQUAL ); break; - case BIFF_TOKID_GT: bOk = pushBinaryOperator( OPCODE_GREATER ); break; - case BIFF_TOKID_NE: bOk = pushBinaryOperator( OPCODE_NOT_EQUAL ); break; - case BIFF_TOKID_ISECT: bOk = pushBinaryOperator( OPCODE_INTERSECT ); break; - case BIFF_TOKID_LIST: bOk = pushBinaryOperator( OPCODE_LIST ); break; - case BIFF_TOKID_RANGE: bOk = pushBinaryOperator( OPCODE_RANGE ); break; - case BIFF_TOKID_UPLUS: bOk = pushUnaryPreOperator( OPCODE_PLUS_SIGN ); break; - case BIFF_TOKID_UMINUS: bOk = pushUnaryPreOperator( OPCODE_MINUS_SIGN ); break; - case BIFF_TOKID_PERCENT: bOk = pushUnaryPostOperator( OPCODE_PERCENT ); break; - case BIFF_TOKID_PAREN: bOk = pushParenthesesOperator(); break; - case BIFF_TOKID_MISSARG: bOk = pushOperand( OPCODE_MISSING ); break; - case BIFF_TOKID_STR: bOk = (this->*mpImportStrToken)( rStrm ); break; - case BIFF_TOKID_NLR: bOk = (this->*mpImportNlrToken)( rStrm ); break; - case BIFF_TOKID_ATTR: bOk = importAttrToken( rStrm ); break; - case BIFF_TOKID_SHEET: bOk = (this->*mpImportSheetToken)( rStrm ); break; - case BIFF_TOKID_ENDSHEET: bOk = (this->*mpImportEndSheetToken)( rStrm ); break; - case BIFF_TOKID_ERR: bOk = pushBiffErrorOperand( rStrm.readuInt8() ); break; - case BIFF_TOKID_BOOL: bOk = pushBiffBoolOperand( rStrm.readuInt8() ); break; - case BIFF_TOKID_INT: bOk = pushValueOperand< double >( rStrm.readuInt16() ); break; - case BIFF_TOKID_NUM: bOk = pushValueOperand( rStrm.readDouble() ); break; - default: bOk = false; + // base tokens + switch( nBaseId ) + { + case BIFF_TOKID_EXP: bOk = (this->*mpImportExpToken)( rStrm ); break; + case BIFF_TOKID_TBL: bOk = false; /* multiple op. will be set externally */ break; + case BIFF_TOKID_ADD: bOk = pushBinaryOperator( OPCODE_ADD ); break; + case BIFF_TOKID_SUB: bOk = pushBinaryOperator( OPCODE_SUB ); break; + case BIFF_TOKID_MUL: bOk = pushBinaryOperator( OPCODE_MULT ); break; + case BIFF_TOKID_DIV: bOk = pushBinaryOperator( OPCODE_DIV ); break; + case BIFF_TOKID_POWER: bOk = pushBinaryOperator( OPCODE_POWER ); break; + case BIFF_TOKID_CONCAT: bOk = pushBinaryOperator( OPCODE_CONCAT ); break; + case BIFF_TOKID_LT: bOk = pushBinaryOperator( OPCODE_LESS ); break; + case BIFF_TOKID_LE: bOk = pushBinaryOperator( OPCODE_LESS_EQUAL ); break; + case BIFF_TOKID_EQ: bOk = pushBinaryOperator( OPCODE_EQUAL ); break; + case BIFF_TOKID_GE: bOk = pushBinaryOperator( OPCODE_GREATER_EQUAL ); break; + case BIFF_TOKID_GT: bOk = pushBinaryOperator( OPCODE_GREATER ); break; + case BIFF_TOKID_NE: bOk = pushBinaryOperator( OPCODE_NOT_EQUAL ); break; + case BIFF_TOKID_ISECT: bOk = pushBinaryOperator( OPCODE_INTERSECT ); break; + case BIFF_TOKID_LIST: bOk = pushBinaryOperator( OPCODE_LIST ); break; + case BIFF_TOKID_RANGE: bOk = pushBinaryOperator( OPCODE_RANGE ); break; + case BIFF_TOKID_UPLUS: bOk = pushUnaryPreOperator( OPCODE_PLUS_SIGN ); break; + case BIFF_TOKID_UMINUS: bOk = pushUnaryPreOperator( OPCODE_MINUS_SIGN ); break; + case BIFF_TOKID_PERCENT: bOk = pushUnaryPostOperator( OPCODE_PERCENT ); break; + case BIFF_TOKID_PAREN: bOk = pushParenthesesOperator(); break; + case BIFF_TOKID_MISSARG: bOk = pushOperand( OPCODE_MISSING ); break; + case BIFF_TOKID_STR: bOk = (this->*mpImportStrToken)( rStrm ); break; + case BIFF_TOKID_NLR: bOk = (this->*mpImportNlrToken)( rStrm ); break; + case BIFF_TOKID_ATTR: bOk = importAttrToken( rStrm ); break; + case BIFF_TOKID_SHEET: bOk = (this->*mpImportSheetToken)( rStrm ); break; + case BIFF_TOKID_ENDSHEET: bOk = (this->*mpImportEndSheetToken)( rStrm ); break; + case BIFF_TOKID_ERR: bOk = pushBiffErrorOperand( rStrm.readuInt8() ); break; + case BIFF_TOKID_BOOL: bOk = pushBiffBoolOperand( rStrm.readuInt8() ); break; + case BIFF_TOKID_INT: bOk = pushValueOperand< double >( rStrm.readuInt16() ); break; + case BIFF_TOKID_NUM: bOk = pushValueOperand( rStrm.readDouble() ); break; + default: bOk = false; + } } - } - else - { - // classified tokens - switch( nBaseId ) + else { - case BIFF_TOKID_ARRAY: bOk = importArrayToken( rStrm ); break; - case BIFF_TOKID_FUNC: bOk = (this->*mpImportFuncToken)( rStrm ); break; - case BIFF_TOKID_FUNCVAR: bOk = (this->*mpImportFuncVarToken)( rStrm ); break; - case BIFF_TOKID_NAME: bOk = importNameToken( rStrm ); break; - case BIFF_TOKID_REF: bOk = (this->*mpImportRefToken)( rStrm, false, false ); break; - case BIFF_TOKID_AREA: bOk = (this->*mpImportAreaToken)( rStrm, false, false ); break; - case BIFF_TOKID_MEMAREA: bOk = importMemAreaToken( rStrm, true ); break; - case BIFF_TOKID_MEMERR: bOk = importMemAreaToken( rStrm, false ); break; - case BIFF_TOKID_MEMNOMEM: bOk = importMemAreaToken( rStrm, false ); break; - case BIFF_TOKID_MEMFUNC: bOk = importMemFuncToken( rStrm ); break; - case BIFF_TOKID_REFERR: bOk = (this->*mpImportRefToken)( rStrm, true, false ); break; - case BIFF_TOKID_AREAERR: bOk = (this->*mpImportAreaToken)( rStrm, true, false ); break; - case BIFF_TOKID_REFN: bOk = (this->*mpImportRefToken)( rStrm, false, true ); break; - case BIFF_TOKID_AREAN: bOk = (this->*mpImportAreaToken)( rStrm, false, true ); break; - case BIFF_TOKID_MEMAREAN: bOk = importMemFuncToken( rStrm ); break; - case BIFF_TOKID_MEMNOMEMN: bOk = importMemFuncToken( rStrm ); break; - case BIFF_TOKID_FUNCCE: bOk = (this->*mpImportFuncCEToken)( rStrm ); break; - case BIFF_TOKID_NAMEX: bOk = (this->*mpImportNameXToken)( rStrm ); break; - case BIFF_TOKID_REF3D: bOk = (this->*mpImportRef3dToken)( rStrm, false, bRelativeAsOffset ); break; - case BIFF_TOKID_AREA3D: bOk = (this->*mpImportArea3dToken)( rStrm, false, bRelativeAsOffset ); break; - case BIFF_TOKID_REFERR3D: bOk = (this->*mpImportRef3dToken)( rStrm, true, bRelativeAsOffset ); break; - case BIFF_TOKID_AREAERR3D: bOk = (this->*mpImportArea3dToken)( rStrm, true, bRelativeAsOffset ); break; - default: bOk = false; + // classified tokens + switch( nBaseId ) + { + case BIFF_TOKID_ARRAY: bOk = importArrayToken( rStrm ); break; + case BIFF_TOKID_FUNC: bOk = (this->*mpImportFuncToken)( rStrm ); break; + case BIFF_TOKID_FUNCVAR: bOk = (this->*mpImportFuncVarToken)( rStrm ); break; + case BIFF_TOKID_NAME: bOk = importNameToken( rStrm ); break; + case BIFF_TOKID_REF: bOk = (this->*mpImportRefToken)( rStrm, false, false ); break; + case BIFF_TOKID_AREA: bOk = (this->*mpImportAreaToken)( rStrm, false, false ); break; + case BIFF_TOKID_MEMAREA: bOk = importMemAreaToken( rStrm, true ); break; + case BIFF_TOKID_MEMERR: bOk = importMemAreaToken( rStrm, false ); break; + case BIFF_TOKID_MEMNOMEM: bOk = importMemAreaToken( rStrm, false ); break; + case BIFF_TOKID_MEMFUNC: bOk = importMemFuncToken( rStrm ); break; + case BIFF_TOKID_REFERR: bOk = (this->*mpImportRefToken)( rStrm, true, false ); break; + case BIFF_TOKID_AREAERR: bOk = (this->*mpImportAreaToken)( rStrm, true, false ); break; + case BIFF_TOKID_REFN: bOk = (this->*mpImportRefToken)( rStrm, false, true ); break; + case BIFF_TOKID_AREAN: bOk = (this->*mpImportAreaToken)( rStrm, false, true ); break; + case BIFF_TOKID_MEMAREAN: bOk = importMemFuncToken( rStrm ); break; + case BIFF_TOKID_MEMNOMEMN: bOk = importMemFuncToken( rStrm ); break; + case BIFF_TOKID_FUNCCE: bOk = (this->*mpImportFuncCEToken)( rStrm ); break; + case BIFF_TOKID_NAMEX: bOk = (this->*mpImportNameXToken)( rStrm ); break; + case BIFF_TOKID_REF3D: bOk = (this->*mpImportRef3dToken)( rStrm, false, bRelativeAsOffset ); break; + case BIFF_TOKID_AREA3D: bOk = (this->*mpImportArea3dToken)( rStrm, false, bRelativeAsOffset ); break; + case BIFF_TOKID_REFERR3D: bOk = (this->*mpImportRef3dToken)( rStrm, true, bRelativeAsOffset ); break; + case BIFF_TOKID_AREAERR3D: bOk = (this->*mpImportArea3dToken)( rStrm, true, bRelativeAsOffset ); break; + default: bOk = false; + } } } } @@ -2161,13 +2183,13 @@ bool BiffFormulaParserImpl::importRefTokenNotAvailable( BiffInputStream&, bool, bool BiffFormulaParserImpl::importStrToken2( BiffInputStream& rStrm ) { - return pushValueOperand( rStrm.readByteString( false, getTextEncoding() ) ); + return pushValueOperand( rStrm.readByteStringUC( false, getTextEncoding(), getFormulaContext().isNulCharsAllowed() ) ); } bool BiffFormulaParserImpl::importStrToken8( BiffInputStream& rStrm ) { // read flags field for empty strings also - return pushValueOperand( rStrm.readUniString( rStrm.readuInt8() ) ); + return pushValueOperand( rStrm.readUniStringBody( rStrm.readuInt8(), getFormulaContext().isNulCharsAllowed() ) ); } bool BiffFormulaParserImpl::importAttrToken( BiffInputStream& rStrm ) @@ -2296,6 +2318,7 @@ bool BiffFormulaParserImpl::importArrayToken( BiffInputStream& rStrm ) size_t nOpSize = popOperandSize(); size_t nOldArraySize = getFormulaSize(); bool bBiff8 = getBiff() == BIFF8; + bool bNulChars = getFormulaContext().isNulCharsAllowed(); // read array size swapStreamPosition( rStrm ); @@ -2324,8 +2347,8 @@ bool BiffFormulaParserImpl::importArrayToken( BiffInputStream& rStrm ) break; case BIFF_DATATYPE_STRING: appendRawToken( OPCODE_PUSH ) <<= bBiff8 ? - rStrm.readUniString() : - rStrm.readByteString( false, getTextEncoding() ); + rStrm.readUniString( bNulChars ) : + rStrm.readByteStringUC( false, getTextEncoding(), bNulChars ); break; case BIFF_DATATYPE_BOOL: appendRawToken( OPCODE_PUSH ) <<= static_cast< double >( (rStrm.readuInt8() == BIFF_TOK_BOOL_FALSE) ? 0.0 : 1.0 ); @@ -2787,6 +2810,54 @@ void FormulaParser::convertNumberToHyperlink( FormulaContext& rContext, const OU } } +OUString FormulaParser::importOleTargetLink( const OUString& rFormulaString ) +{ + // obviously, this would overburden our formula parser, so we parse it manually + OUString aTargetLink; + sal_Int32 nFmlaLen = rFormulaString.getLength(); + if( (nFmlaLen >= 8) && (rFormulaString[ 0 ] == '[') ) + { + // passed string is trimmed already + sal_Int32 nBracketClose = rFormulaString.indexOf( ']' ); + sal_Int32 nExclamation = rFormulaString.indexOf( '!' ); + if( (nBracketClose >= 2) && + (nBracketClose + 1 == nExclamation) && + (rFormulaString[ nExclamation + 1 ] == '\'') && + (rFormulaString[ nFmlaLen - 1 ] == '\'') ) + { + sal_Int32 nRefId = rFormulaString.copy( 1, nBracketClose - 1 ).toInt32(); + aTargetLink = mxImpl->resolveOleTarget( nRefId ); + } + } + return aTargetLink; +} + +OUString FormulaParser::importOleTargetLink( RecordInputStream& rStrm ) +{ + OUString aTargetLink; + sal_Int32 nFmlaSize = rStrm.readInt32(); + sal_Int64 nFmlaEndPos = rStrm.tell() + ::std::max< sal_Int32 >( nFmlaSize, 0 ); + if( (nFmlaSize == 7) && (rStrm.getRemaining() >= 7) ) + { + sal_uInt8 nToken; + sal_Int16 nRefId; + sal_Int32 nNameId; + rStrm >> nToken >> nRefId >> nNameId; + if( nToken == (BIFF_TOKCLASS_VAL|BIFF_TOKID_NAMEX) ) + aTargetLink = mxImpl->resolveOleTarget( nRefId ); + } + rStrm.seek( nFmlaEndPos ); + return aTargetLink; +} + +OUString FormulaParser::importOleTargetLink( BiffInputStream& rStrm, const sal_uInt16* pnFmlaSize ) const +{ + OUString aTargetLink; + sal_uInt16 nFmlaSize = lclReadFmlaSize( rStrm, getBiff(), pnFmlaSize ); + rStrm.skip( nFmlaSize ); + return aTargetLink; +} + // ============================================================================ } // namespace xls diff --git a/oox/source/xls/makefile.mk b/oox/source/xls/makefile.mk index a8771bfca85a..42a92edfe863 100644 --- a/oox/source/xls/makefile.mk +++ b/oox/source/xls/makefile.mk @@ -68,6 +68,7 @@ SLOFILES = \ $(SLO)$/formulabase.obj \ $(SLO)$/formulaparser.obj \ $(SLO)$/numberformatsbuffer.obj \ + $(SLO)$/ooxformulaparser.obj \ $(SLO)$/pagesettings.obj \ $(SLO)$/pivotcachebuffer.obj \ $(SLO)$/pivotcachefragment.obj \ @@ -76,6 +77,8 @@ SLOFILES = \ $(SLO)$/querytablefragment.obj \ $(SLO)$/richstring.obj \ $(SLO)$/richstringcontext.obj \ + $(SLO)$/scenariobuffer.obj \ + $(SLO)$/scenariocontext.obj \ $(SLO)$/sharedformulabuffer.obj \ $(SLO)$/sharedstringsbuffer.obj \ $(SLO)$/sharedstringsfragment.obj \ diff --git a/oox/source/xls/numberformatsbuffer.cxx b/oox/source/xls/numberformatsbuffer.cxx index 76fb57ed2302..aafc600c9030 100644 --- a/oox/source/xls/numberformatsbuffer.cxx +++ b/oox/source/xls/numberformatsbuffer.cxx @@ -1890,8 +1890,8 @@ public: { rNumFmt.finalizeImport( mxNumFmts, maEnUsLocale ); } private: - ::com::sun::star::uno::Reference< ::com::sun::star::util::XNumberFormats > mxNumFmts; - ::com::sun::star::lang::Locale maEnUsLocale; + Reference< XNumberFormats > mxNumFmts; + Locale maEnUsLocale; }; NumberFormatFinalizer::NumberFormatFinalizer( const WorkbookHelper& rHelper ) : @@ -1959,7 +1959,7 @@ NumberFormatsBuffer::NumberFormatsBuffer( const WorkbookHelper& rHelper ) : // get the current locale try { - Reference< XMultiServiceFactory > xConfigProv( getBaseFilter().getGlobalFactory()->createInstance( + Reference< XMultiServiceFactory > xConfigProv( getGlobalFactory()->createInstance( CREATE_OUSTRING( "com.sun.star.configuration.ConfigurationProvider" ) ), UNO_QUERY_THROW ); // try user-defined locale setting @@ -2002,7 +2002,7 @@ NumberFormatRef NumberFormatsBuffer::createNumFmt( sal_Int32 nNumFmtId, const OU NumberFormatRef NumberFormatsBuffer::importNumFmt( const AttributeList& rAttribs ) { sal_Int32 nNumFmtId = rAttribs.getInteger( XML_numFmtId, -1 ); - OUString aFmtCode = rAttribs.getString( XML_formatCode, OUString() ); + OUString aFmtCode = rAttribs.getXString( XML_formatCode, OUString() ); return createNumFmt( nNumFmtId, aFmtCode ); } @@ -2020,15 +2020,15 @@ void NumberFormatsBuffer::importFormat( BiffInputStream& rStrm ) { case BIFF2: case BIFF3: - aFmtCode = rStrm.readByteString( false, getTextEncoding() ); + aFmtCode = rStrm.readByteStringUC( false, getTextEncoding() ); break; case BIFF4: rStrm.skip( 2 ); // in BIFF4 the index field exists, but is undefined - aFmtCode = rStrm.readByteString( false, getTextEncoding() ); + aFmtCode = rStrm.readByteStringUC( false, getTextEncoding() ); break; case BIFF5: mnNextBiffIndex = rStrm.readuInt16(); - aFmtCode = rStrm.readByteString( false, getTextEncoding() ); + aFmtCode = rStrm.readByteStringUC( false, getTextEncoding() ); break; case BIFF8: mnNextBiffIndex = rStrm.readuInt16(); diff --git a/oox/source/xls/ooxformulaparser.cxx b/oox/source/xls/ooxformulaparser.cxx new file mode 100644 index 000000000000..62e8189bdd00 --- /dev/null +++ b/oox/source/xls/ooxformulaparser.cxx @@ -0,0 +1,228 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: ooxformulaparser.cxx,v $ + * $Revision: 1.1 $ + * + * 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. + * + ************************************************************************/ + +#include "oox/xls/ooxformulaparser.hxx" +#include <com/sun/star/uno/XComponentContext.hpp> +#include "oox/xls/formulaparser.hxx" + +using ::rtl::OUString; +using ::com::sun::star::uno::Any; +using ::com::sun::star::uno::Exception; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::RuntimeException; +using ::com::sun::star::uno::Sequence; +using ::com::sun::star::uno::UNO_QUERY_THROW; +using ::com::sun::star::uno::XComponentContext; +using ::com::sun::star::uno::XInterface; +using ::com::sun::star::lang::XMultiServiceFactory; +using ::com::sun::star::table::CellAddress; +using ::com::sun::star::sheet::FormulaToken; + +namespace oox { +namespace xls { + +// ============================================================================ + +class OOXMLFormulaParserImpl : private FormulaFinalizer +{ +public: + explicit OOXMLFormulaParserImpl( const Reference< XMultiServiceFactory >& rxFactory ); + + Sequence< FormulaToken > parseFormula( const OUString& rFormula, const CellAddress& rReferencePos ); + +protected: + virtual const FunctionInfo* resolveBadFuncName( const OUString& rTokenData ) const; + +private: + ApiParserWrapper maApiParser; +}; + +// ---------------------------------------------------------------------------- + +OOXMLFormulaParserImpl::OOXMLFormulaParserImpl( const Reference< XMultiServiceFactory >& rxFactory ) : + FormulaFinalizer( OpCodeProvider( rxFactory, FILTER_OOX, BIFF_UNKNOWN, true ) ), + maApiParser( rxFactory, *this ) +{ +} + +Sequence< FormulaToken > OOXMLFormulaParserImpl::parseFormula( const OUString& rFormula, const CellAddress& rReferencePos ) +{ + return finalizeTokenArray( maApiParser.parseFormula( rFormula, rReferencePos ) ); +} + +const FunctionInfo* OOXMLFormulaParserImpl::resolveBadFuncName( const OUString& rTokenData ) const +{ + /* Try to parse calls to library functions. The format of such a function + call is assumed to be + "'<path-to-office-install>\Library\<libname>'!<funcname>". */ + + // the string has to start with an apostroph (followed by the library URL) + if( (rTokenData.getLength() >= 6) && (rTokenData[ 0 ] == '\'') ) + { + // library URL and function name are separated by an exclamation mark + sal_Int32 nExclamPos = rTokenData.lastIndexOf( '!' ); + if( (1 < nExclamPos) && (nExclamPos + 1 < rTokenData.getLength()) && (rTokenData[ nExclamPos - 1 ] == '\'') ) + { + // find the last backslash that separates library path and name + sal_Int32 nFileSep = rTokenData.lastIndexOf( '\\', nExclamPos - 2 ); + if( nFileSep > 1 ) + { + // find preceding backslash that separates the last directory name + sal_Int32 nDirSep = rTokenData.lastIndexOf( '\\', nFileSep - 1 ); + // function library is located in a directory called 'library' + if( (nDirSep > 0) && rTokenData.matchIgnoreAsciiCaseAsciiL( RTL_CONSTASCII_STRINGPARAM( "\\LIBRARY\\" ), nDirSep ) ) + { + // try to find a function info for the function name + OUString aFuncName = rTokenData.copy( nExclamPos + 1 ).toAsciiUpperCase(); + const FunctionInfo* pFuncInfo = getFuncInfoFromOoxFuncName( aFuncName ); + if( pFuncInfo && (pFuncInfo->meFuncLibType != FUNCLIB_UNKNOWN) ) + { + // check that the name of the library matches + OUString aLibName = rTokenData.copy( nFileSep + 1, nExclamPos - nFileSep - 2 ); + if( pFuncInfo->meFuncLibType == getFuncLibTypeFromLibraryName( aLibName ) ) + return pFuncInfo; + } + } + } + } + } + return 0; +} + +// ============================================================================ + +class OOXMLFormulaPrinterImpl : public OpCodeProvider +{ +public: + explicit OOXMLFormulaPrinterImpl( const Reference< XMultiServiceFactory >& rxFactory ); + +private: + ApiParserWrapper maApiParser; +}; + +// ---------------------------------------------------------------------------- + +OOXMLFormulaPrinterImpl::OOXMLFormulaPrinterImpl( const Reference< XMultiServiceFactory >& rxFactory ) : + OpCodeProvider( rxFactory, FILTER_OOX, BIFF_UNKNOWN, false ), + maApiParser( rxFactory, *this ) +{ +} + +// ============================================================================ + +Sequence< OUString > OOXMLFormulaParser_getSupportedServiceNames() +{ + Sequence< OUString > aServiceNames( 1 ); + aServiceNames[ 0 ] = CREATE_OUSTRING( "com.sun.star.sheet.FilterFormulaParser" ); + return aServiceNames; +} + +OUString OOXMLFormulaParser_getImplementationName() +{ + return CREATE_OUSTRING( "com.sun.star.comp.oox.OOXMLFormulaParser" ); +} + +Reference< XInterface > SAL_CALL OOXMLFormulaParser_createInstance( const Reference< XComponentContext >& ) throw( Exception ) +{ + return static_cast< ::cppu::OWeakObject* >( new OOXMLFormulaParser ); +} + +// ============================================================================ + +OOXMLFormulaParser::OOXMLFormulaParser() +{ +} + +OOXMLFormulaParser::~OOXMLFormulaParser() +{ +} + +// com.sun.star.lang.XServiceInfo interface ----------------------------------- + +OUString SAL_CALL OOXMLFormulaParser::getImplementationName() throw( RuntimeException ) +{ + return OOXMLFormulaParser_getImplementationName(); +} + +sal_Bool SAL_CALL OOXMLFormulaParser::supportsService( const OUString& rService ) throw( RuntimeException ) +{ + const Sequence< OUString > aServices( OOXMLFormulaParser_getSupportedServiceNames() ); + const OUString* pArray = aServices.getConstArray(); + const OUString* pArrayEnd = pArray + aServices.getLength(); + return ::std::find( pArray, pArrayEnd, rService ) != pArrayEnd; +} + +Sequence< OUString > SAL_CALL OOXMLFormulaParser::getSupportedServiceNames() throw( RuntimeException ) +{ + return OOXMLFormulaParser_getSupportedServiceNames(); +} + +// com.sun.star.lang.XInitialization interface -------------------------------- + +void SAL_CALL OOXMLFormulaParser::initialize( const Sequence< Any >& rArgs ) throw( Exception, RuntimeException ) +{ + OSL_ENSURE( rArgs.hasElements(), "OOXMLFormulaParser::initialize - missing arguments" ); + if( !rArgs.hasElements() ) + throw RuntimeException(); + mxComponent.set( rArgs[ 0 ], UNO_QUERY_THROW ); +} + +// com.sun.star.sheet.XFilterFormulaParser interface -------------------------- + +OUString SAL_CALL OOXMLFormulaParser::getSupportedNamespace() throw( RuntimeException ) +{ + return CREATE_OUSTRING( "http://schemas.microsoft.com/office/excel/formula" ); +} + +// com.sun.star.sheet.XFormulaParser interface -------------------------------- + +Sequence< FormulaToken > SAL_CALL OOXMLFormulaParser::parseFormula( + const OUString& rFormula, const CellAddress& rReferencePos ) throw( RuntimeException ) +{ + if( !mxParserImpl ) + { + Reference< XMultiServiceFactory > xFactory( mxComponent, UNO_QUERY_THROW ); + mxParserImpl.reset( new OOXMLFormulaParserImpl( xFactory ) ); + } + return mxParserImpl->parseFormula( rFormula, rReferencePos ); +} + +OUString SAL_CALL OOXMLFormulaParser::printFormula( + const Sequence< FormulaToken >& /*rTokens*/, const CellAddress& /*rReferencePos*/ ) throw( RuntimeException ) +{ + // not implemented + throw RuntimeException(); +} + +// ============================================================================ + +} // namespace xls +} // namespace oox + diff --git a/oox/source/xls/pagesettings.cxx b/oox/source/xls/pagesettings.cxx index c7dd02797147..956dec51f27e 100644 --- a/oox/source/xls/pagesettings.cxx +++ b/oox/source/xls/pagesettings.cxx @@ -43,6 +43,7 @@ #include <com/sun/star/text/XTextCursor.hpp> #include "properties.hxx" #include "oox/helper/attributelist.hxx" +#include "oox/helper/graphichelper.hxx" #include "oox/helper/propertymap.hxx" #include "oox/helper/propertyset.hxx" #include "oox/helper/recordinputstream.hxx" @@ -244,7 +245,7 @@ void PageSettings::importHeaderFooterCharacters( const OUString& rChars, sal_Int void PageSettings::importPicture( const Relations& rRelations, const AttributeList& rAttribs ) { - maModel.maPicturePath = rRelations.getFragmentPathFromRelId( rAttribs.getString( R_TOKEN( id ), OUString() ) ); + importPictureData( rRelations, rAttribs.getString( R_TOKEN( id ), OUString() ) ); } void PageSettings::importPageMargins( RecordInputStream& rStrm ) @@ -312,7 +313,7 @@ void PageSettings::importHeaderFooter( RecordInputStream& rStrm ) void PageSettings::importPicture( const Relations& rRelations, RecordInputStream& rStrm ) { - maModel.maPicturePath = rRelations.getFragmentPathFromRelId( rStrm.readString() ); + importPictureData( rRelations, rStrm.readString() ); } void PageSettings::importLeftMargin( BiffInputStream& rStrm ) @@ -395,7 +396,7 @@ void PageSettings::importPrintGridLines( BiffInputStream& rStrm ) void PageSettings::importHeader( BiffInputStream& rStrm ) { if( rStrm.getRemaining() > 0 ) - maModel.maOddHeader = (getBiff() == BIFF8) ? rStrm.readUniString() : rStrm.readByteString( false, getTextEncoding() ); + maModel.maOddHeader = (getBiff() == BIFF8) ? rStrm.readUniString() : rStrm.readByteStringUC( false, getTextEncoding() ); else maModel.maOddHeader = OUString(); } @@ -403,13 +404,16 @@ void PageSettings::importHeader( BiffInputStream& rStrm ) void PageSettings::importFooter( BiffInputStream& rStrm ) { if( rStrm.getRemaining() > 0 ) - maModel.maOddFooter = (getBiff() == BIFF8) ? rStrm.readUniString() : rStrm.readByteString( false, getTextEncoding() ); + maModel.maOddFooter = (getBiff() == BIFF8) ? rStrm.readUniString() : rStrm.readByteStringUC( false, getTextEncoding() ); else maModel.maOddFooter = OUString(); } -void PageSettings::importPicture( BiffInputStream& /*rStrm*/ ) +void PageSettings::importPicture( BiffInputStream& rStrm ) { + StreamDataSequence aPictureData; + BiffHelper::importImgData( aPictureData, rStrm, getBiff() ); + maModel.maGraphicUrl = getBaseFilter().getGraphicHelper().importGraphicObject( aPictureData ); } void PageSettings::setFitToPagesMode( bool bFitToPages ) @@ -435,6 +439,13 @@ void PageSettings::finalizeImport() aSheetProps.setProperty( PROP_PageStyle, aStyleName ); } +void PageSettings::importPictureData( const Relations& rRelations, const OUString& rRelId ) +{ + OUString aPicturePath = rRelations.getFragmentPathFromRelId( rRelId ); + if( aPicturePath.getLength() > 0 ) + maModel.maGraphicUrl = getBaseFilter().importEmbeddedGraphicObject( aPicturePath ); +} + // ============================================================================ // ============================================================================ @@ -1173,20 +1184,14 @@ void PageSettingsConverter::writePageSettingsProperties( aPropMap[ PROP_FooterIsDynamicHeight ] <<= maFooterData.mbDynamicHeight; aPropMap[ PROP_FooterHeight ] <<= maFooterData.mnHeight; aPropMap[ PROP_FooterBodyDistance ] <<= maFooterData.mnBodyDist; - rPropSet.setProperties( aPropMap ); - // background image - OSL_ENSURE( (getFilterType() == FILTER_OOX) || (rModel.maPicturePath.getLength() == 0), - "PageSettingsConverter::writePageSettingsProperties - unexpected background picture" ); - if( (getFilterType() == FILTER_OOX) && (rModel.maPicturePath.getLength() > 0) ) + if( rModel.maGraphicUrl.getLength() > 0 ) { - OUString aPictureUrl = getOoxFilter().copyPictureStream( rModel.maPicturePath ); - if( aPictureUrl.getLength() > 0 ) - { - rPropSet.setProperty( PROP_BackGraphicURL, aPictureUrl ); - rPropSet.setProperty( PROP_BackGraphicLocation, ::com::sun::star::style::GraphicLocation_TILED ); - } + aPropMap[ PROP_BackGraphicURL ] <<= rModel.maGraphicUrl; + aPropMap[ PROP_BackGraphicLocation ] <<= ::com::sun::star::style::GraphicLocation_TILED; } + + rPropSet.setProperties( aPropMap ); } void PageSettingsConverter::convertHeaderFooterData( diff --git a/oox/source/xls/pivotcachebuffer.cxx b/oox/source/xls/pivotcachebuffer.cxx index 2639126bb4af..33465d81d466 100644 --- a/oox/source/xls/pivotcachebuffer.cxx +++ b/oox/source/xls/pivotcachebuffer.cxx @@ -185,7 +185,7 @@ PivotCacheItem::PivotCacheItem() : void PivotCacheItem::readString( const AttributeList& rAttribs ) { - maValue <<= rAttribs.getString( XML_v, OUString() ); + maValue <<= rAttribs.getXString( XML_v, OUString() ); mnType = XML_s; } @@ -209,7 +209,7 @@ void PivotCacheItem::readBool( const AttributeList& rAttribs ) void PivotCacheItem::readError( const AttributeList& rAttribs, const UnitConverter& rUnitConverter ) { - maValue <<= static_cast< sal_Int32 >( rUnitConverter.calcBiffErrorCode( rAttribs.getString( XML_v, OUString() ) ) ); + maValue <<= static_cast< sal_Int32 >( rUnitConverter.calcBiffErrorCode( rAttribs.getXString( XML_v, OUString() ) ) ); mnType = XML_e; } @@ -265,7 +265,7 @@ void PivotCacheItem::readIndex( RecordInputStream& rStrm ) void PivotCacheItem::readString( BiffInputStream& rStrm, const WorkbookHelper& rHelper ) { - maValue <<= (rHelper.getBiff() == BIFF8) ? rStrm.readUniString() : rStrm.readByteString( true, rHelper.getTextEncoding() ); + maValue <<= (rHelper.getBiff() == BIFF8) ? rStrm.readUniString() : rStrm.readByteStringUC( true, rHelper.getTextEncoding() ); mnType = XML_s; } @@ -499,10 +499,10 @@ PivotCacheField::PivotCacheField( const WorkbookHelper& rHelper, bool bIsDatabas void PivotCacheField::importCacheField( const AttributeList& rAttribs ) { - maFieldModel.maName = rAttribs.getString( XML_name, OUString() ); - maFieldModel.maCaption = rAttribs.getString( XML_caption, OUString() ); - maFieldModel.maPropertyName = rAttribs.getString( XML_propertyName, OUString() ); - maFieldModel.maFormula = rAttribs.getString( XML_formula, OUString() ); + maFieldModel.maName = rAttribs.getXString( XML_name, OUString() ); + maFieldModel.maCaption = rAttribs.getXString( XML_caption, OUString() ); + maFieldModel.maPropertyName = rAttribs.getXString( XML_propertyName, OUString() ); + maFieldModel.maFormula = rAttribs.getXString( XML_formula, OUString() ); maFieldModel.mnNumFmtId = rAttribs.getInteger( XML_numFmtId, 0 ); maFieldModel.mnSqlType = rAttribs.getInteger( XML_sqlType, 0 ); maFieldModel.mnHierarchy = rAttribs.getInteger( XML_hierarchy, 0 ); @@ -650,7 +650,7 @@ void PivotCacheField::importPCDField( BiffInputStream& rStrm ) maFieldGroupModel.mnBaseField = rStrm.readuInt16(); rStrm.skip( 2 ); // number of unique items (either shared or group) rStrm >> nGroupItems >> nBaseItems >> nSharedItems; - maFieldModel.maName = (getBiff() == BIFF8) ? rStrm.readUniString() : rStrm.readByteString( true, getTextEncoding() ); + maFieldModel.maName = (getBiff() == BIFF8) ? rStrm.readUniString() : rStrm.readByteStringUC( true, getTextEncoding() ); maFieldModel.mbServerField = getFlag( nFlags, BIFF_PCDFIELD_SERVERFIELD ); maFieldModel.mbUniqueList = !getFlag( nFlags, BIFF_PCDFIELD_NOUNIQUEITEMS ); @@ -1057,7 +1057,7 @@ PivotCache::PivotCache( const WorkbookHelper& rHelper ) : void PivotCache::importPivotCacheDefinition( const AttributeList& rAttribs ) { maDefModel.maRelId = rAttribs.getString( R_TOKEN( id ), OUString() ); - maDefModel.maRefreshedBy = rAttribs.getString( XML_refreshedBy, OUString() ); + maDefModel.maRefreshedBy = rAttribs.getXString( XML_refreshedBy, OUString() ); maDefModel.mfRefreshedDate = rAttribs.getDouble( XML_refreshedDate, 0.0 ); maDefModel.mnRecords = rAttribs.getInteger( XML_recordCount, 0 ); maDefModel.mnMissItemsLimit = rAttribs.getInteger( XML_missingItemsLimit, 0 ); @@ -1082,11 +1082,11 @@ void PivotCache::importCacheSource( const AttributeList& rAttribs ) void PivotCache::importWorksheetSource( const AttributeList& rAttribs, const Relations& rRelations ) { maSheetSrcModel.maRelId = rAttribs.getString( R_TOKEN( id ), OUString() ); - maSheetSrcModel.maSheet = rAttribs.getString( XML_sheet, OUString() ); - maSheetSrcModel.maDefName = rAttribs.getString( XML_name, OUString() ); + maSheetSrcModel.maSheet = rAttribs.getXString( XML_sheet, OUString() ); + maSheetSrcModel.maDefName = rAttribs.getXString( XML_name, OUString() ); // resolve URL of external document - maTargetUrl = rRelations.getTargetFromRelId( maSheetSrcModel.maRelId ); + maTargetUrl = rRelations.getExternalTargetFromRelId( maSheetSrcModel.maRelId ); // store range address unchecked with sheet index 0, will be resolved/checked later getAddressConverter().convertToCellRangeUnchecked( maSheetSrcModel.maRange, rAttribs.getString( XML_ref, OUString() ), 0 ); } @@ -1146,7 +1146,7 @@ void PivotCache::importPCDSheetSource( RecordInputStream& rStrm, const Relations } // resolve URL of external document - maTargetUrl = rRelations.getTargetFromRelId( maSheetSrcModel.maRelId ); + maTargetUrl = rRelations.getExternalTargetFromRelId( maSheetSrcModel.maRelId ); } void PivotCache::importPCDSource( BiffInputStream& rStrm ) @@ -1192,7 +1192,7 @@ void PivotCache::importPCDefinition( BiffInputStream& rStrm ) if( nUserNameLen != BIFF_PC_NOSTRING ) maDefModel.maRefreshedBy = (getBiff() == BIFF8) ? rStrm.readUniString( nUserNameLen ) : - rStrm.readCharArray( nUserNameLen, getTextEncoding() ); + rStrm.readCharArrayUC( nUserNameLen, getTextEncoding() ); maDefModel.mbInvalid = getFlag( nFlags, BIFF_PCDEFINITION_INVALID ); maDefModel.mbSaveData = getFlag( nFlags, BIFF_PCDEFINITION_SAVEDATA ); @@ -1330,7 +1330,7 @@ void PivotCache::importDConRef( BiffInputStream& rStrm ) void PivotCache::importDConName( BiffInputStream& rStrm ) { - maSheetSrcModel.maDefName = (getBiff() == BIFF8) ? rStrm.readUniString() : rStrm.readByteString( false, getTextEncoding() ); + maSheetSrcModel.maDefName = (getBiff() == BIFF8) ? rStrm.readUniString() : rStrm.readByteStringUC( false, getTextEncoding() ); OSL_ENSURE( maSheetSrcModel.maDefName.getLength() > 0, "PivotCache::importDConName - missing defined name" ); importDConUrl( rStrm ); } @@ -1356,7 +1356,7 @@ void PivotCache::importDConUrl( BiffInputStream& rStrm ) } else { - aEncodedUrl = rStrm.readByteString( false, getTextEncoding() ); + aEncodedUrl = rStrm.readByteStringUC( false, getTextEncoding() ); } if( aEncodedUrl.getLength() > 0 ) diff --git a/oox/source/xls/pivottablebuffer.cxx b/oox/source/xls/pivottablebuffer.cxx index a49a5cda70ae..73404d29612f 100644 --- a/oox/source/xls/pivottablebuffer.cxx +++ b/oox/source/xls/pivottablebuffer.cxx @@ -221,7 +221,7 @@ OUString lclReadPivotString( const WorkbookHelper& rHelper, BiffInputStream& rSt { if( nLen == BIFF_PT_NOSTRING ) return OUString(); - return (rHelper.getBiff() == BIFF8) ? rStrm.readUniString( nLen ) : rStrm.readCharArray( nLen, rHelper.getTextEncoding() ); + return (rHelper.getBiff() == BIFF8) ? rStrm.readUniString( nLen ) : rStrm.readCharArrayUC( nLen, rHelper.getTextEncoding() ); } } // namespace @@ -381,7 +381,7 @@ void PivotTableField::importItem( const AttributeList& rAttribs ) void PivotTableField::importReference( const AttributeList& rAttribs ) { // field index is stored as unsigned integer - maModel.mnSortRefField = static_cast< sal_Int32 >( rAttribs.getUnsignedInteger( XML_field, SAL_MAX_UINT32 ) ); + maModel.mnSortRefField = static_cast< sal_Int32 >( rAttribs.getUnsigned( XML_field, SAL_MAX_UINT32 ) ); } void PivotTableField::importReferenceItem( const AttributeList& rAttribs ) @@ -891,10 +891,10 @@ PivotTableFilter::PivotTableFilter( const PivotTable& rPivotTable ) : void PivotTableFilter::importFilter( const AttributeList& rAttribs ) { - maModel.maName = rAttribs.getString( XML_name, OUString() ); - maModel.maDescription = rAttribs.getString( XML_description, OUString() ); - maModel.maStrValue1 = rAttribs.getString( XML_stringValue1, OUString() ); - maModel.maStrValue2 = rAttribs.getString( XML_stringValue2, OUString() ); + maModel.maName = rAttribs.getXString( XML_name, OUString() ); + maModel.maDescription = rAttribs.getXString( XML_description, OUString() ); + maModel.maStrValue1 = rAttribs.getXString( XML_stringValue1, OUString() ); + maModel.maStrValue2 = rAttribs.getXString( XML_stringValue2, OUString() ); maModel.mnField = rAttribs.getInteger( XML_fld, -1 ); maModel.mnMemPropField = rAttribs.getInteger( XML_mpFld, -1 ); maModel.mnType = rAttribs.getToken( XML_type, XML_TOKEN_INVALID ); @@ -1040,17 +1040,17 @@ PivotTable::PivotTable( const WorkbookHelper& rHelper ) : void PivotTable::importPivotTableDefinition( const AttributeList& rAttribs ) { - maDefModel.maName = rAttribs.getString( XML_name, OUString() ); - maDefModel.maDataCaption = rAttribs.getString( XML_dataCaption , OUString() ); - maDefModel.maGrandTotalCaption = rAttribs.getString( XML_grandTotalCaption, OUString() ); - maDefModel.maRowHeaderCaption = rAttribs.getString( XML_rowHeaderCaption, OUString() ); - maDefModel.maColHeaderCaption = rAttribs.getString( XML_colHeaderCaption, OUString() ); - maDefModel.maErrorCaption = rAttribs.getString( XML_errorCaption, OUString() ); - maDefModel.maMissingCaption = rAttribs.getString( XML_missingCaption, OUString() ); - maDefModel.maPageStyle = rAttribs.getString( XML_pageStyle, OUString() ); - maDefModel.maPivotTableStyle = rAttribs.getString( XML_pivotTableStyle, OUString() ); - maDefModel.maVacatedStyle = rAttribs.getString( XML_vacatedStyle, OUString() ); - maDefModel.maTag = rAttribs.getString( XML_tag, OUString() ); + maDefModel.maName = rAttribs.getXString( XML_name, OUString() ); + maDefModel.maDataCaption = rAttribs.getXString( XML_dataCaption , OUString() ); + maDefModel.maGrandTotalCaption = rAttribs.getXString( XML_grandTotalCaption, OUString() ); + maDefModel.maRowHeaderCaption = rAttribs.getXString( XML_rowHeaderCaption, OUString() ); + maDefModel.maColHeaderCaption = rAttribs.getXString( XML_colHeaderCaption, OUString() ); + maDefModel.maErrorCaption = rAttribs.getXString( XML_errorCaption, OUString() ); + maDefModel.maMissingCaption = rAttribs.getXString( XML_missingCaption, OUString() ); + maDefModel.maPageStyle = rAttribs.getXString( XML_pageStyle, OUString() ); + maDefModel.maPivotTableStyle = rAttribs.getXString( XML_pivotTableStyle, OUString() ); + maDefModel.maVacatedStyle = rAttribs.getXString( XML_vacatedStyle, OUString() ); + maDefModel.maTag = rAttribs.getXString( XML_tag, OUString() ); maDefModel.mnCacheId = rAttribs.getInteger( XML_cacheId, -1 ); maDefModel.mnDataPosition = rAttribs.getInteger( XML_dataPosition, 0 ); maDefModel.mnPageWrap = rAttribs.getInteger( XML_pageWrap, 0 ); @@ -1104,7 +1104,7 @@ void PivotTable::importColField( const AttributeList& rAttribs ) void PivotTable::importPageField( const AttributeList& rAttribs ) { PTPageFieldModel aModel; - aModel.maName = rAttribs.getString( XML_name, OUString() ); + aModel.maName = rAttribs.getXString( XML_name, OUString() ); aModel.mnField = rAttribs.getInteger( XML_fld, -1 ); // specification is wrong, XML_item is not the cache item, but the field item aModel.mnItem = rAttribs.getInteger( XML_item, OOBIN_PTPAGEFIELD_MULTIITEMS ); @@ -1114,7 +1114,7 @@ void PivotTable::importPageField( const AttributeList& rAttribs ) void PivotTable::importDataField( const AttributeList& rAttribs ) { PTDataFieldModel aModel; - aModel.maName = rAttribs.getString( XML_name, OUString() ); + aModel.maName = rAttribs.getXString( XML_name, OUString() ); aModel.mnField = rAttribs.getInteger( XML_fld, -1 ); aModel.mnSubtotal = rAttribs.getToken( XML_subtotal, XML_sum ); aModel.mnShowDataAs = rAttribs.getToken( XML_showDataAs, XML_normal ); @@ -1378,7 +1378,7 @@ void PivotTable::finalizeImport() aDescProp.setProperty( PROP_DrillDownOnDoubleClick, maDefModel.mbEnableDrill ); // finalize all fields, this finds field names and creates grouping fields - maFields.forEachMem( &PivotTableField::finalizeImport, mxDPDescriptor ); + maFields.forEachMem( &PivotTableField::finalizeImport, ::boost::cref( mxDPDescriptor ) ); // all row fields for( IndexVector::iterator aIt = maRowFields.begin(), aEnd = maRowFields.end(); aIt != aEnd; ++aIt ) @@ -1434,7 +1434,7 @@ void PivotTable::finalizeImport() void PivotTable::finalizeDateGroupingImport( const Reference< XDataPilotField >& rxBaseDPField, sal_Int32 nBaseFieldIdx ) { // process all fields, there is no chaining information in the cache fields - maFields.forEachMem( &PivotTableField::finalizeDateGroupingImport, rxBaseDPField, nBaseFieldIdx ); + maFields.forEachMem( &PivotTableField::finalizeDateGroupingImport, ::boost::cref( rxBaseDPField ), nBaseFieldIdx ); } void PivotTable::finalizeParentGroupingImport( const Reference< XDataPilotField >& rxBaseDPField, diff --git a/oox/source/xls/scenariobuffer.cxx b/oox/source/xls/scenariobuffer.cxx new file mode 100644 index 000000000000..2d11f55d538a --- /dev/null +++ b/oox/source/xls/scenariobuffer.cxx @@ -0,0 +1,309 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: scenariobuffer.cxx,v $ + * $Revision: 1.1 $ + * + * 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. + * + ************************************************************************/ + +#include "oox/xls/scenariobuffer.hxx" +#include <com/sun/star/container/XIndexAccess.hpp> +#include <com/sun/star/sheet/XScenario.hpp> +#include <com/sun/star/sheet/XScenarios.hpp> +#include <com/sun/star/sheet/XScenariosSupplier.hpp> +#include <com/sun/star/sheet/XSpreadsheet.hpp> +#include <com/sun/star/sheet/XSpreadsheetDocument.hpp> +#include "properties.hxx" +#include "oox/helper/attributelist.hxx" +#include "oox/helper/propertyset.hxx" +#include "oox/helper/recordinputstream.hxx" +#include "oox/xls/addressconverter.hxx" +#include "oox/xls/biffinputstream.hxx" + +using ::rtl::OUString; +using ::com::sun::star::uno::Exception; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::UNO_QUERY_THROW; +using ::com::sun::star::uno::UNO_SET_THROW; +using ::com::sun::star::container::XIndexAccess; +using ::com::sun::star::container::XNameAccess; +using ::com::sun::star::table::CellAddress; +using ::com::sun::star::table::CellRangeAddress; +using ::com::sun::star::table::XCell; +using ::com::sun::star::sheet::XScenario; +using ::com::sun::star::sheet::XScenarios; +using ::com::sun::star::sheet::XScenariosSupplier; +using ::com::sun::star::sheet::XSpreadsheet; + +namespace oox { +namespace xls { + +// ============================================================================ + +namespace { + +const sal_Int32 BIFF_SCENARIO_DELETED = 0x4000; + +} // namespace + +// ============================================================================ + +ScenarioCellModel::ScenarioCellModel() : + mnNumFmtId( 0 ), + mbDeleted( false ) +{ +} + +// ---------------------------------------------------------------------------- + +ScenarioModel::ScenarioModel() : + mbLocked( false ), + mbHidden( false ) +{ +} + +// ---------------------------------------------------------------------------- + +Scenario::Scenario( const WorkbookHelper& rHelper, sal_Int16 nSheet ) : + WorkbookHelper( rHelper ), + mnSheet( nSheet ) +{ +} + +void Scenario::importScenario( const AttributeList& rAttribs ) +{ + maModel.maName = rAttribs.getXString( XML_name, OUString() ); + maModel.maComment = rAttribs.getXString( XML_comment, OUString() ); + maModel.maUser = rAttribs.getXString( XML_user, OUString() ); + maModel.mbLocked = rAttribs.getBool( XML_locked, false ); + maModel.mbHidden = rAttribs.getBool( XML_hidden, false ); +} + +void Scenario::importInputCells( const AttributeList& rAttribs ) +{ + ScenarioCellModel aModel; + getAddressConverter().convertToCellAddressUnchecked( aModel.maPos, rAttribs.getString( XML_r, OUString() ), mnSheet ); + aModel.maValue = rAttribs.getXString( XML_val, OUString() ); + aModel.mnNumFmtId = rAttribs.getInteger( XML_numFmtId, 0 ); + aModel.mbDeleted = rAttribs.getBool( XML_deleted, false ); + maCells.push_back( aModel ); +} + +void Scenario::importScenario( RecordInputStream& rStrm ) +{ + rStrm.skip( 2 ); // cell count + // two longs instead of flag field + maModel.mbLocked = rStrm.readInt32() != 0; + maModel.mbHidden = rStrm.readInt32() != 0; + rStrm >> maModel.maName >> maModel.maComment >> maModel.maUser; +} + +void Scenario::importInputCells( RecordInputStream& rStrm ) +{ + // TODO: where is the deleted flag? + ScenarioCellModel aModel; + BinAddress aPos; + rStrm >> aPos; + rStrm.skip( 8 ); + aModel.mnNumFmtId = rStrm.readuInt16(); + rStrm >> aModel.maValue; + getAddressConverter().convertToCellAddressUnchecked( aModel.maPos, aPos, mnSheet ); + maCells.push_back( aModel ); +} + +void Scenario::importScenario( BiffInputStream& rStrm ) +{ + sal_uInt16 nCellCount; + sal_uInt8 nNameLen, nCommentLen, nUserLen; + rStrm >> nCellCount; + // two bytes instead of flag field + maModel.mbLocked = rStrm.readuInt8() != 0; + maModel.mbHidden = rStrm.readuInt8() != 0; + rStrm >> nNameLen >> nCommentLen >> nUserLen; + maModel.maName = rStrm.readUniStringBody( nNameLen ); + // user name: before comment (in difference to leading length field), repeated length + if( nUserLen > 0 ) + maModel.maUser = rStrm.readUniString(); + // comment: repeated length + if( nCommentLen > 0 ) + maModel.maComment = rStrm.readUniString(); + + // list of cell addresses + for( sal_uInt16 nCell = 0; !rStrm.isEof() && (nCell < nCellCount); ++nCell ) + { + ScenarioCellModel aModel; + BinAddress aPos; + rStrm >> aPos; + // deleted flag is encoded in column index + aModel.mbDeleted = getFlag( aPos.mnCol, BIFF_SCENARIO_DELETED ); + setFlag( aPos.mnCol, BIFF_SCENARIO_DELETED, false ); + getAddressConverter().convertToCellAddressUnchecked( aModel.maPos, aPos, mnSheet ); + maCells.push_back( aModel ); + } + + // list of cell values + for( ScenarioCellVector::iterator aIt = maCells.begin(), aEnd = maCells.end(); !rStrm.isEof() && (aIt != aEnd); ++aIt ) + aIt->maValue = rStrm.readUniString(); +} + +void Scenario::finalizeImport() +{ + AddressConverter& rAddrConv = getAddressConverter(); + ::std::vector< CellRangeAddress > aRanges; + for( ScenarioCellVector::iterator aIt = maCells.begin(), aEnd = maCells.end(); aIt != aEnd; ++aIt ) + if( !aIt->mbDeleted && rAddrConv.checkCellAddress( aIt->maPos, true ) ) + aRanges.push_back( CellRangeAddress( aIt->maPos.Sheet, aIt->maPos.Column, aIt->maPos.Row, aIt->maPos.Column, aIt->maPos.Row ) ); + + if( !aRanges.empty() && (maModel.maName.getLength() > 0) ) try + { + /* Find an unused name for the scenario (Calc stores scenario data in + hidden sheets named after the scenario following the base sheet). */ + Reference< XNameAccess > xSheetsNA( getDocument()->getSheets(), UNO_QUERY_THROW ); + OUString aScenName = ContainerHelper::getUnusedName( xSheetsNA, maModel.maName, '_' ); + + // create the new scenario sheet + Reference< XScenariosSupplier > xScenariosSupp( getSheetFromDoc( mnSheet ), UNO_QUERY_THROW ); + Reference< XScenarios > xScenarios( xScenariosSupp->getScenarios(), UNO_SET_THROW ); + xScenarios->addNewByName( aScenName, ContainerHelper::vectorToSequence( aRanges ), maModel.maComment ); + + // write scenario cell values + Reference< XSpreadsheet > xSheet( getSheetFromDoc( aScenName ), UNO_SET_THROW ); + for( ScenarioCellVector::iterator aIt = maCells.begin(), aEnd = maCells.end(); aIt != aEnd; ++aIt ) + { + if( !aIt->mbDeleted ) try + { + // use XCell::setFormula to auto-detect values and strings + Reference< XCell > xCell( xSheet->getCellByPosition( aIt->maPos.Column, aIt->maPos.Row ), UNO_SET_THROW ); + xCell->setFormula( aIt->maValue ); + } + catch( Exception& ) + { + } + } + + // scenario properties + PropertySet aPropSet( xScenarios->getByName( aScenName ) ); + aPropSet.setProperty( PROP_IsActive, false ); + aPropSet.setProperty( PROP_CopyBack, false ); + aPropSet.setProperty( PROP_CopyStyles, false ); + aPropSet.setProperty( PROP_CopyFormulas, false ); + aPropSet.setProperty( PROP_Protected, maModel.mbLocked ); + // #112621# do not show/print scenario border + aPropSet.setProperty( PROP_ShowBorder, false ); + aPropSet.setProperty( PROP_PrintBorder, false ); + } + catch( Exception& ) + { + } +} + +// ============================================================================ + +SheetScenariosModel::SheetScenariosModel() : + mnCurrent( 0 ), + mnShown( 0 ) +{ +} + +// ---------------------------------------------------------------------------- + +SheetScenarios::SheetScenarios( const WorkbookHelper& rHelper, sal_Int16 nSheet ) : + WorkbookHelper( rHelper ), + mnSheet( nSheet ) +{ +} + +void SheetScenarios::importScenarios( const AttributeList& rAttribs ) +{ + maModel.mnCurrent = rAttribs.getInteger( XML_current, 0 ); + maModel.mnShown = rAttribs.getInteger( XML_show, 0 ); +} + +void SheetScenarios::importScenarios( RecordInputStream& rStrm ) +{ + maModel.mnCurrent = rStrm.readuInt16(); + maModel.mnShown = rStrm.readuInt16(); +} + +void SheetScenarios::importScenarios( BiffInputStream& rStrm ) +{ + rStrm.skip( 2 ); // scenario count + maModel.mnCurrent = rStrm.readuInt16(); + maModel.mnShown = rStrm.readuInt16(); + + // read following SCENARIO records + while( (rStrm.getNextRecId() == BIFF_ID_SCENARIO) && rStrm.startNextRecord() ) + createScenario().importScenario( rStrm ); +} + +Scenario& SheetScenarios::createScenario() +{ + ScenarioVector::value_type xScenario( new Scenario( *this, mnSheet ) ); + maScenarios.push_back( xScenario ); + return *xScenario; +} + +void SheetScenarios::finalizeImport() +{ + maScenarios.forEachMem( &Scenario::finalizeImport ); + + // activate a scenario + try + { + Reference< XScenariosSupplier > xScenariosSupp( getSheetFromDoc( mnSheet ), UNO_QUERY_THROW ); + Reference< XIndexAccess > xScenariosIA( xScenariosSupp->getScenarios(), UNO_QUERY_THROW ); + Reference< XScenario > xScenario( xScenariosIA->getByIndex( maModel.mnShown ), UNO_QUERY_THROW ); + xScenario->apply(); + } + catch( Exception& ) + { + } +} + +// ============================================================================ + +ScenarioBuffer::ScenarioBuffer( const WorkbookHelper& rHelper ) : + WorkbookHelper( rHelper ) +{ +} + +SheetScenarios& ScenarioBuffer::createSheetScenarios( sal_Int16 nSheet ) +{ + SheetScenariosMap::mapped_type& rxSheetScens = maSheetScenarios[ nSheet ]; + if( !rxSheetScens ) + rxSheetScens.reset( new SheetScenarios( *this, nSheet ) ); + return *rxSheetScens; +} + +void ScenarioBuffer::finalizeImport() +{ + maSheetScenarios.forEachMem( &SheetScenarios::finalizeImport ); +} + +// ============================================================================ + +} // namespace xls +} // namespace oox + diff --git a/oox/source/xls/scenariocontext.cxx b/oox/source/xls/scenariocontext.cxx new file mode 100644 index 000000000000..3943bd5b257f --- /dev/null +++ b/oox/source/xls/scenariocontext.cxx @@ -0,0 +1,127 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: tablefragment.cxx,v $ + * $Revision: 1.4 $ + * + * 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. + * + ************************************************************************/ + +#include "oox/xls/scenariocontext.hxx" +#include "oox/xls/scenariobuffer.hxx" + +using ::oox::core::ContextHandlerRef; + +namespace oox { +namespace xls { + +// ============================================================================ + +OoxScenarioContext::OoxScenarioContext( OoxWorksheetContextBase& rParent, SheetScenarios& rSheetScenarios ) : + OoxWorksheetContextBase( rParent ), + mrScenario( rSheetScenarios.createScenario() ) +{ +} + +ContextHandlerRef OoxScenarioContext::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs ) +{ + switch( getCurrentElement() ) + { + case XLS_TOKEN( scenario ): + if( nElement == XLS_TOKEN( inputCells ) ) mrScenario.importInputCells( rAttribs ); + break; + } + return 0; +} + +void OoxScenarioContext::onStartElement( const AttributeList& rAttribs ) +{ + if( isRootElement() ) + mrScenario.importScenario( rAttribs ); +} + +ContextHandlerRef OoxScenarioContext::onCreateRecordContext( sal_Int32 nRecId, RecordInputStream& rStrm ) +{ + switch( getCurrentElement() ) + { + case OOBIN_ID_SCENARIO: + if( nRecId == OOBIN_ID_INPUTCELLS ) mrScenario.importInputCells( rStrm ); + break; + } + return 0; +} + +void OoxScenarioContext::onStartRecord( RecordInputStream& rStrm ) +{ + if( isRootElement() ) + mrScenario.importScenario( rStrm ); +} + +// ============================================================================ + +OoxScenariosContext::OoxScenariosContext( OoxWorksheetFragmentBase& rFragment ) : + OoxWorksheetContextBase( rFragment ), + mrSheetScenarios( getScenarios().createSheetScenarios( getSheetIndex() ) ) +{ +} + +ContextHandlerRef OoxScenariosContext::onCreateContext( sal_Int32 nElement, const AttributeList& ) +{ + switch( getCurrentElement() ) + { + case XLS_TOKEN( scenarios ): + if( nElement == XLS_TOKEN( scenario ) ) return new OoxScenarioContext( *this, mrSheetScenarios ); + break; + } + return 0; +} + +void OoxScenariosContext::onStartElement( const AttributeList& rAttribs ) +{ + if( isRootElement() ) + mrSheetScenarios.importScenarios( rAttribs ); +} + +ContextHandlerRef OoxScenariosContext::onCreateRecordContext( sal_Int32 nRecId, RecordInputStream& ) +{ + switch( getCurrentElement() ) + { + case OOBIN_ID_SCENARIOS: + if( nRecId == OOBIN_ID_SCENARIO ) return new OoxScenarioContext( *this, mrSheetScenarios ); + break; + } + return 0; +} + +void OoxScenariosContext::onStartRecord( RecordInputStream& rStrm ) +{ + if( isRootElement() ) + mrSheetScenarios.importScenarios( rStrm ); +} + +// ============================================================================ + +} // namespace xls +} // namespace oox + diff --git a/oox/source/xls/stylesbuffer.cxx b/oox/source/xls/stylesbuffer.cxx index f6a10f51b265..64d660f5c559 100644 --- a/oox/source/xls/stylesbuffer.cxx +++ b/oox/source/xls/stylesbuffer.cxx @@ -339,7 +339,7 @@ void Color::importColor( const AttributeList& rAttribs ) if( rAttribs.getBool( XML_auto, false ) ) setAuto(); else if( rAttribs.hasAttribute( XML_rgb ) ) - setRgb( rAttribs.getHex( XML_rgb, API_RGB_TRANSPARENT ), rAttribs.getDouble( XML_tint, 0.0 ) ); + setRgb( rAttribs.getIntegerHex( XML_rgb, API_RGB_TRANSPARENT ), rAttribs.getDouble( XML_tint, 0.0 ) ); else if( rAttribs.hasAttribute( XML_theme ) ) setTheme( rAttribs.getInteger( XML_theme, -1 ), rAttribs.getDouble( XML_tint, 0.0 ) ); else if( rAttribs.hasAttribute( XML_indexed ) ) @@ -505,9 +505,7 @@ static const sal_Int32 spnDefColors8[] = // ---------------------------------------------------------------------------- ColorPalette::ColorPalette( const WorkbookHelper& rHelper ) : - WorkbookHelper( rHelper ), - mnWindowColor( ::oox::drawingml::Color::getSystemColor( XML_window ) ), - mnWinTextColor( ::oox::drawingml::Color::getSystemColor( XML_windowText ) ) + WorkbookHelper( rHelper ) { // default colors switch( getFilterType() ) @@ -534,7 +532,7 @@ ColorPalette::ColorPalette( const WorkbookHelper& rHelper ) : void ColorPalette::importPaletteColor( const AttributeList& rAttribs ) { - appendColor( rAttribs.getHex( XML_rgb, API_RGB_TRANSPARENT ) ); + appendColor( rAttribs.getIntegerHex( XML_rgb, API_RGB_TRANSPARENT ) ); } void ColorPalette::importPaletteColor( RecordInputStream& rStrm ) @@ -571,17 +569,16 @@ sal_Int32 ColorPalette::getColor( sal_Int32 nPaletteIdx ) const { case OOX_COLOR_WINDOWTEXT3: case OOX_COLOR_WINDOWTEXT: - case OOX_COLOR_CHWINDOWTEXT: nColor = mnWinTextColor; break; + case OOX_COLOR_CHWINDOWTEXT: nColor = getBaseFilter().getSystemColor( XML_windowText ); break; case OOX_COLOR_WINDOWBACK3: case OOX_COLOR_WINDOWBACK: - case OOX_COLOR_CHWINDOWBACK: nColor = mnWindowColor; break; -// case OOX_COLOR_BUTTONBACK: -// case OOX_COLOR_CHBORDERAUTO: -// case OOX_COLOR_NOTEBACK: - case OOX_COLOR_NOTETEXT: nColor = mnWinTextColor; break; // !TODO - case OOX_COLOR_FONTAUTO: nColor = API_RGB_TRANSPARENT; break; - default: - OSL_ENSURE( false, "ColorPalette::getColor - unknown color index" ); + case OOX_COLOR_CHWINDOWBACK: nColor = getBaseFilter().getSystemColor( XML_window ); break; + case OOX_COLOR_BUTTONBACK: nColor = getBaseFilter().getSystemColor( XML_btnFace ); break; + case OOX_COLOR_CHBORDERAUTO: nColor = 0x000000; /* really always black? */ break; + case OOX_COLOR_NOTEBACK: nColor = getBaseFilter().getSystemColor( XML_infoBk ); break; + case OOX_COLOR_NOTETEXT: nColor = getBaseFilter().getSystemColor( XML_infoText ); break; + case OOX_COLOR_FONTAUTO: nColor = API_RGB_TRANSPARENT; break; + default: OSL_ENSURE( false, "ColorPalette::getColor - unknown color index" ); } return nColor; } @@ -748,7 +745,7 @@ void Font::importAttribs( sal_Int32 nElement, const AttributeList& rAttribs ) case XLS_TOKEN( rFont ): // when in <rPr> element if( rAttribs.hasAttribute( XML_val ) ) { - maModel.maName = rAttribs.getString( XML_val, OUString() ); + maModel.maName = rAttribs.getXString( XML_val, OUString() ); maUsedFlags.mbNameUsed = true; } break; @@ -949,7 +946,7 @@ void Font::importCfRule( BiffInputStream& rStrm ) OSL_ENSURE( rStrm.getRemaining() >= 118, "Font::importCfRule - missing record data" ); sal_Int64 nRecPos = rStrm.tell(); - maModel.maName = rStrm.readUniString( rStrm.readuInt8() ); + maModel.maName = rStrm.readUniStringBody( rStrm.readuInt8() ); maUsedFlags.mbNameUsed = maModel.maName.getLength() > 0; OSL_ENSURE( !rStrm.isEof() && (rStrm.tell() <= nRecPos + 64), "Font::importCfRule - font name too long" ); rStrm.seek( nRecPos + 64 ); @@ -1219,12 +1216,12 @@ void Font::importFontData5( BiffInputStream& rStrm ) void Font::importFontName2( BiffInputStream& rStrm ) { - maModel.maName = rStrm.readByteString( false, getTextEncoding() ); + maModel.maName = rStrm.readByteStringUC( false, getTextEncoding() ); } void Font::importFontName8( BiffInputStream& rStrm ) { - maModel.maName = rStrm.readUniString( rStrm.readuInt8() ); + maModel.maName = rStrm.readUniStringBody( rStrm.readuInt8() ); } // ============================================================================ @@ -2102,12 +2099,12 @@ void Fill::finalizeImport() if( !rModel.mbPattColorUsed ) rModel.maPatternColor.setAuto(); sal_Int32 nPattColor = rModel.maPatternColor.getColor( - *this, ::oox::drawingml::Color::getSystemColor( XML_windowText ) ); + *this, getBaseFilter().getSystemColor( XML_windowText ) ); if( !rModel.mbFillColorUsed ) rModel.maFillColor.setAuto(); sal_Int32 nFillColor = rModel.maFillColor.getColor( - *this, ::oox::drawingml::Color::getSystemColor( XML_window ) ); + *this, getBaseFilter().getSystemColor( XML_window ) ); maApiData.mnColor = lclGetMixedColor( nPattColor, nFillColor, nAlpha ); maApiData.mbTransparent = false; @@ -2813,7 +2810,7 @@ CellStyle::CellStyle( const WorkbookHelper& rHelper ) : void CellStyle::importCellStyle( const AttributeList& rAttribs ) { - maModel.maName = rAttribs.getString( XML_name, OUString() ); + maModel.maName = rAttribs.getXString( XML_name, OUString() ); maModel.mnXfId = rAttribs.getInteger( XML_xfId, -1 ); maModel.mnBuiltinId = rAttribs.getInteger( XML_builtinId, -1 ); maModel.mnLevel = rAttribs.getInteger( XML_iLevel, 0 ); @@ -2848,7 +2845,7 @@ void CellStyle::importStyle( BiffInputStream& rStrm ) else { maModel.maName = (getBiff() == BIFF8) ? - rStrm.readUniString() : rStrm.readByteString( false, getTextEncoding() ); + rStrm.readUniString() : rStrm.readByteStringUC( false, getTextEncoding() ); } } diff --git a/oox/source/xls/tablebuffer.cxx b/oox/source/xls/tablebuffer.cxx index 7943ad75ce8d..f38e3c7d41fe 100644 --- a/oox/source/xls/tablebuffer.cxx +++ b/oox/source/xls/tablebuffer.cxx @@ -70,8 +70,8 @@ Table::Table( const WorkbookHelper& rHelper ) : void Table::importTable( const AttributeList& rAttribs, sal_Int16 nSheet ) { getAddressConverter().convertToCellRangeUnchecked( maModel.maRange, rAttribs.getString( XML_ref, OUString() ), nSheet ); - maModel.maProgName = rAttribs.getString( XML_name, OUString() ); - maModel.maDisplayName = rAttribs.getString( XML_displayName, OUString() ); + maModel.maProgName = rAttribs.getXString( XML_name, OUString() ); + maModel.maDisplayName = rAttribs.getXString( XML_displayName, OUString() ); maModel.mnId = rAttribs.getInteger( XML_id, -1 ); maModel.mnType = rAttribs.getToken( XML_tableType, XML_worksheet ); maModel.mnHeaderRows = rAttribs.getInteger( XML_headerRowCount, 1 ); diff --git a/oox/source/xls/themebuffer.cxx b/oox/source/xls/themebuffer.cxx index d06757ee1e7e..b2baefccd5a5 100644 --- a/oox/source/xls/themebuffer.cxx +++ b/oox/source/xls/themebuffer.cxx @@ -32,7 +32,6 @@ #include "oox/xls/stylesbuffer.hxx" using ::oox::drawingml::ClrScheme; -using ::oox::drawingml::Color; namespace oox { namespace xls { diff --git a/oox/source/xls/unitconverter.cxx b/oox/source/xls/unitconverter.cxx index 8ee2606a30e9..ad95f48876ec 100644 --- a/oox/source/xls/unitconverter.cxx +++ b/oox/source/xls/unitconverter.cxx @@ -36,6 +36,7 @@ #include <com/sun/star/awt/XFont.hpp> #include <com/sun/star/util/Date.hpp> #include <com/sun/star/util/DateTime.hpp> +#include "oox/core/filterbase.hxx" #include "oox/xls/stylesbuffer.hxx" using ::rtl::OUString; @@ -110,14 +111,17 @@ UnitConverter::UnitConverter( const WorkbookHelper& rHelper ) : mnNullDate( lclGetDays( Date( 30, 12, 1899 ) ) ) { // initialize constant and default coefficients - maCoeffs[ UNIT_INCH ] = MM100_PER_INCH; - maCoeffs[ UNIT_POINT ] = MM100_PER_POINT; - maCoeffs[ UNIT_TWIP ] = MM100_PER_TWIP; - maCoeffs[ UNIT_EMU ] = MM100_PER_EMU; - maCoeffs[ UNIT_PIXELX ] = 12.5; // default: 1 px = 0.125 mm - maCoeffs[ UNIT_PIXELY ] = 12.5; // default: 1 px = 0.125 mm - maCoeffs[ UNIT_DIGIT ] = 200.0; // default: 1 digit = 2 mm - maCoeffs[ UNIT_SPACE ] = 100.0; // default 1 space = 1 mm + const DeviceInfo& rDeviceInfo = getBaseFilter().getDeviceInfo(); + maCoeffs[ UNIT_INCH ] = MM100_PER_INCH; + maCoeffs[ UNIT_POINT ] = MM100_PER_POINT; + maCoeffs[ UNIT_TWIP ] = MM100_PER_TWIP; + maCoeffs[ UNIT_EMU ] = MM100_PER_EMU; + maCoeffs[ UNIT_SCREENX ] = (rDeviceInfo.PixelPerMeterX > 0) ? (100000.0 / rDeviceInfo.PixelPerMeterX) : 50.0; + maCoeffs[ UNIT_SCREENY ] = (rDeviceInfo.PixelPerMeterY > 0) ? (100000.0 / rDeviceInfo.PixelPerMeterY) : 50.0; + maCoeffs[ UNIT_REFDEVX ] = 12.5; // default: 1 px = 0.125 mm + maCoeffs[ UNIT_REFDEVY ] = 12.5; // default: 1 px = 0.125 mm + maCoeffs[ UNIT_DIGIT ] = 200.0; // default: 1 digit = 2 mm + maCoeffs[ UNIT_SPACE ] = 100.0; // default 1 space = 1 mm // error code maps addErrorCode( BIFF_ERR_NULL, CREATE_OUSTRING( "#NULL!" ) ); @@ -134,28 +138,28 @@ void UnitConverter::finalizeImport() Reference< XDevice > xDevice = getReferenceDevice(); if( xDevice.is() ) { - // get pixel metric first, needed to get character widths below + // get reference device metric first, needed to get character widths below DeviceInfo aInfo = xDevice->getInfo(); - maCoeffs[ UNIT_PIXELX ] = 100000.0 / aInfo.PixelPerMeterX; - maCoeffs[ UNIT_PIXELY ] = 100000.0 / aInfo.PixelPerMeterY; + maCoeffs[ UNIT_REFDEVX ] = 100000.0 / aInfo.PixelPerMeterX; + maCoeffs[ UNIT_REFDEVY ] = 100000.0 / aInfo.PixelPerMeterY; // get character widths from default font if( const Font* pDefFont = getStyles().getDefaultFont().get() ) { // XDevice expects pixels in font descriptor, but font contains twips FontDescriptor aDesc = pDefFont->getFontDescriptor(); - aDesc.Height = static_cast< sal_Int16 >( scaleValue( aDesc.Height, UNIT_TWIP, UNIT_PIXELX ) + 0.5 ); + aDesc.Height = static_cast< sal_Int16 >( scaleValue( aDesc.Height, UNIT_TWIP, UNIT_REFDEVX ) + 0.5 ); Reference< XFont > xFont = xDevice->getFont( aDesc ); if( xFont.is() ) { // get maximum width of all digits sal_Int32 nDigitWidth = 0; for( sal_Unicode cChar = '0'; cChar <= '9'; ++cChar ) - nDigitWidth = ::std::max( nDigitWidth, scaleToMm100( xFont->getCharWidth( cChar ), UNIT_PIXELX ) ); + nDigitWidth = ::std::max( nDigitWidth, scaleToMm100( xFont->getCharWidth( cChar ), UNIT_REFDEVX ) ); if( nDigitWidth > 0 ) maCoeffs[ UNIT_DIGIT ] = nDigitWidth; // get width of space character - sal_Int32 nSpaceWidth = scaleToMm100( xFont->getCharWidth( ' ' ), UNIT_PIXELX ); + sal_Int32 nSpaceWidth = scaleToMm100( xFont->getCharWidth( ' ' ), UNIT_REFDEVX ); if( nSpaceWidth > 0 ) maCoeffs[ UNIT_SPACE ] = nSpaceWidth; } @@ -173,7 +177,7 @@ void UnitConverter::finalizeNullDate( const Date& rNullDate ) double UnitConverter::scaleValue( double fValue, Unit eFromUnit, Unit eToUnit ) const { - return fValue * getCoefficient( eFromUnit ) / getCoefficient( eToUnit ); + return (eFromUnit == eToUnit) ? fValue : (fValue * getCoefficient( eFromUnit ) / getCoefficient( eToUnit )); } sal_Int32 UnitConverter::scaleToMm100( double fValue, Unit eUnit ) const diff --git a/oox/source/xls/viewsettings.cxx b/oox/source/xls/viewsettings.cxx index 83d34949fe01..caeacaf6d45d 100644 --- a/oox/source/xls/viewsettings.cxx +++ b/oox/source/xls/viewsettings.cxx @@ -710,7 +710,7 @@ void ViewSettings::finalizeImport() sal_Int16 nShowMode = getWorkbookSettings().getApiShowObjectMode(); // view settings for all sheets - Reference< XNameContainer > xSheetsNC = ContainerHelper::createNameContainer( getBaseFilter().getGlobalFactory() ); + Reference< XNameContainer > xSheetsNC = ContainerHelper::createNameContainer( getGlobalFactory() ); if( !xSheetsNC.is() ) return; for( SheetPropertiesMap::const_iterator aIt = maSheetProps.begin(), aEnd = maSheetProps.end(); aIt != aEnd; ++aIt ) ContainerHelper::insertByName( xSheetsNC, rWorksheets.getCalcSheetName( aIt->first ), aIt->second ); @@ -722,7 +722,7 @@ void ViewSettings::finalizeImport() if( !rxActiveSheetView ) rxActiveSheetView.reset( new SheetViewModel ); - Reference< XIndexContainer > xContainer = ContainerHelper::createIndexContainer( getBaseFilter().getGlobalFactory() ); + Reference< XIndexContainer > xContainer = ContainerHelper::createIndexContainer( getGlobalFactory() ); if( xContainer.is() ) try { PropertyMap aPropMap; diff --git a/oox/source/xls/webquerybuffer.cxx b/oox/source/xls/webquerybuffer.cxx index e63bc72a6665..e2c2329889b2 100644 --- a/oox/source/xls/webquerybuffer.cxx +++ b/oox/source/xls/webquerybuffer.cxx @@ -103,7 +103,7 @@ void WebQueryBuffer::importConnection( const AttributeList& rAttribs ) return; } - sal_uInt32 nId = rAttribs.getUnsignedInteger( XML_id, 0 ); + sal_uInt32 nId = rAttribs.getUnsigned( XML_id, 0 ); if ( maConnections.size() < (nId + 1) ) maConnections.resize(nId + 1); diff --git a/oox/source/xls/workbookfragment.cxx b/oox/source/xls/workbookfragment.cxx index 15b6e8a3e41e..d5904877b7ee 100644 --- a/oox/source/xls/workbookfragment.cxx +++ b/oox/source/xls/workbookfragment.cxx @@ -204,25 +204,25 @@ void OoxWorkbookFragment::finalizeImport() ISegmentProgressBarRef xGlobalSegment = getProgressBar().createSegment( PROGRESS_LENGTH_GLOBALS ); // read the theme substream - OUString aThemeFragmentPath = getFragmentPathFromType( CREATE_OFFICEDOC_RELATIONSTYPE( "theme" ) ); + OUString aThemeFragmentPath = getFragmentPathFromFirstType( CREATE_OFFICEDOC_RELATIONSTYPE( "theme" ) ); if( aThemeFragmentPath.getLength() > 0 ) importOoxFragment( new ThemeFragmentHandler( getFilter(), aThemeFragmentPath, getTheme() ) ); xGlobalSegment->setPosition( 0.25 ); // read the styles substream (requires finalized theme buffer) - OUString aStylesFragmentPath = getFragmentPathFromType( CREATE_OFFICEDOC_RELATIONSTYPE( "styles" ) ); + OUString aStylesFragmentPath = getFragmentPathFromFirstType( CREATE_OFFICEDOC_RELATIONSTYPE( "styles" ) ); if( aStylesFragmentPath.getLength() > 0 ) importOoxFragment( new OoxStylesFragment( *this, aStylesFragmentPath ) ); xGlobalSegment->setPosition( 0.5 ); // read the shared string table substream (requires finalized styles buffer) - OUString aSstFragmentPath = getFragmentPathFromType( CREATE_OFFICEDOC_RELATIONSTYPE( "sharedStrings" ) ); + OUString aSstFragmentPath = getFragmentPathFromFirstType( CREATE_OFFICEDOC_RELATIONSTYPE( "sharedStrings" ) ); if( aSstFragmentPath.getLength() > 0 ) importOoxFragment( new OoxSharedStringsFragment( *this, aSstFragmentPath ) ); xGlobalSegment->setPosition( 0.75 ); // read the connections substream - OUString aConnFragmentPath = getFragmentPathFromType( CREATE_OFFICEDOC_RELATIONSTYPE( "connections" ) ); + OUString aConnFragmentPath = getFragmentPathFromFirstType( CREATE_OFFICEDOC_RELATIONSTYPE( "connections" ) ); if( aConnFragmentPath.getLength() > 0 ) importOoxFragment( new OoxConnectionsFragment( *this, aConnFragmentPath ) ); xGlobalSegment->setPosition( 1.0 ); @@ -240,7 +240,7 @@ void OoxWorkbookFragment::finalizeImport() if( const Relation* pRelation = getRelations().getRelationFromRelId( rWorksheets.getSheetRelId( nSheet ) ) ) { // get fragment path of the sheet - OUString aFragmentPath = getFragmentPathFromTarget( pRelation->maTarget ); + OUString aFragmentPath = getFragmentPathFromRelation( *pRelation ); OSL_ENSURE( aFragmentPath.getLength() > 0, "OoxWorkbookFragment::finalizeImport - cannot access sheet fragment" ); if( aFragmentPath.getLength() > 0 ) { @@ -443,7 +443,7 @@ bool BiffWorkbookFragment::importWorkspaceFragment() /* Read current sheet name (sheet substreams may not be in the same order as SHEET records are). */ mrStrm.skip( 4 ); - OUString aSheetName = mrStrm.readByteString( false, getTextEncoding() ); + OUString aSheetName = mrStrm.readByteStringUC( false, getTextEncoding() ); sal_Int32 nCurrSheet = rWorksheets.getCalcSheetIndex( aSheetName ); // load the sheet fragment records BiffFragmentType eSheetFragment = startFragment( getBiff() ); diff --git a/oox/source/xls/workbookhelper.cxx b/oox/source/xls/workbookhelper.cxx index 8d4e02a837b7..5f2fcced80cb 100644 --- a/oox/source/xls/workbookhelper.cxx +++ b/oox/source/xls/workbookhelper.cxx @@ -51,6 +51,7 @@ #include "oox/core/xmlfilterbase.hxx" #include "oox/drawingml/theme.hxx" #include "oox/xls/addressconverter.hxx" +#include "oox/xls/biffinputstream.hxx" #include "oox/xls/biffcodec.hxx" #include "oox/xls/defnamesbuffer.hxx" #include "oox/xls/excelchartconverter.hxx" @@ -59,6 +60,7 @@ #include "oox/xls/pagesettings.hxx" #include "oox/xls/pivotcachebuffer.hxx" #include "oox/xls/pivottablebuffer.hxx" +#include "oox/xls/scenariobuffer.hxx" #include "oox/xls/sharedstringsbuffer.hxx" #include "oox/xls/stylesbuffer.hxx" #include "oox/xls/tablebuffer.hxx" @@ -319,6 +321,8 @@ public: inline DefinedNamesBuffer& getDefinedNames() const { return *mxDefNames; } /** Returns the tables collection (equivalent to Calc's database ranges). */ inline TableBuffer& getTables() const { return *mxTables; } + /** Returns the scenarios collection. */ + inline ScenarioBuffer& getScenarios() const { return *mxScenarios; } /** Returns the web queries. */ inline WebQueryBuffer& getWebQueries() const { return *mxWebQueries; } /** Returns the collection of pivot caches. */ @@ -382,6 +386,7 @@ private: typedef ::std::auto_ptr< ExternalLinkBuffer > ExtLinkBfrPtr; typedef ::std::auto_ptr< DefinedNamesBuffer > DefNamesBfrPtr; typedef ::std::auto_ptr< TableBuffer > TableBfrPtr; + typedef ::std::auto_ptr< ScenarioBuffer > ScenarioBfrPtr; typedef ::std::auto_ptr< WebQueryBuffer > WebQueryBfrPtr; typedef ::std::auto_ptr< PivotCacheBuffer > PivotCacheBfrPtr; typedef ::std::auto_ptr< PivotTableBuffer > PivotTableBfrPtr; @@ -413,6 +418,7 @@ private: ExtLinkBfrPtr mxExtLinks; /// All external links. DefNamesBfrPtr mxDefNames; /// All defined names. TableBfrPtr mxTables; /// All tables (database ranges). + ScenarioBfrPtr mxScenarios; /// All scenarios. WebQueryBfrPtr mxWebQueries; /// Web queries buffer. PivotCacheBfrPtr mxPivotCaches; /// All pivot caches in the document. PivotTableBfrPtr mxPivotTables; /// All pivot tables in the document. @@ -561,8 +567,7 @@ Reference< XStyle > WorkbookData::createStyleObject( OUString& orStyleName, bool try { Reference< XNameContainer > xStylesNC( getStyleFamily( bPageStyle ), UNO_SET_THROW ); - Reference< XMultiServiceFactory > xFactory( mxDoc, UNO_QUERY_THROW ); - xStyle.set( xFactory->createInstance( bPageStyle ? maPageStyleServ : maCellStyleServ ), UNO_QUERY_THROW ); + xStyle.set( mrBaseFilter.getModelFactory()->createInstance( bPageStyle ? maPageStyleServ : maCellStyleServ ), UNO_QUERY_THROW ); orStyleName = ContainerHelper::insertByUnusedName( xStylesNC, orStyleName, ' ', Any( xStyle ), bRenameOldExisting ); } catch( Exception& ) @@ -655,6 +660,7 @@ void WorkbookData::initialize( bool bWorkbookFile ) mxExtLinks.reset( new ExternalLinkBuffer( *this ) ); mxDefNames.reset( new DefinedNamesBuffer( *this ) ); mxTables.reset( new TableBuffer( *this ) ); + mxScenarios.reset( new ScenarioBuffer( *this ) ); mxWebQueries.reset( new WebQueryBuffer( *this ) ); mxPivotCaches.reset( new PivotCacheBuffer( *this ) ); mxPivotTables.reset( new PivotTableBuffer( *this ) ); @@ -752,6 +758,11 @@ FilterBase& WorkbookHelper::getBaseFilter() const return mrBookData.getBaseFilter(); } +Reference< XMultiServiceFactory > WorkbookHelper::getGlobalFactory() const +{ + return mrBookData.getBaseFilter().getGlobalFactory(); +} + FilterType WorkbookHelper::getFilterType() const { return mrBookData.getFilterType(); @@ -787,8 +798,13 @@ void WorkbookHelper::finalizeWorkbookImport() data pilots expect existing source data on creation. */ mrBookData.getPivotTables().finalizeImport(); + /* Insert scenarios after all sheet processing is done, because new hidden + sheets are created for scenarios which would confuse code that relies + on certain sheet indexes. Must be done after pivot tables too. */ + mrBookData.getScenarios().finalizeImport(); + /* Set 'Default' page style to automatic page numbering (default is manual - number 1). Otherwise hidden tables (e.g. for scenarios) which have + number 1). Otherwise hidden sheets (e.g. for scenarios) which have 'Default' page style will break automatic page numbering for following sheets. Automatic numbering is set by passing the value 0. */ PropertySet aDefPageStyle( getStyleObject( CREATE_OUSTRING( "Default" ), true ) ); @@ -802,6 +818,11 @@ Reference< XSpreadsheetDocument > WorkbookHelper::getDocument() const return mrBookData.getDocument(); } +Reference< XMultiServiceFactory > WorkbookHelper::getDocumentFactory() const +{ + return mrBookData.getBaseFilter().getModelFactory(); +} + Reference< XDevice > WorkbookHelper::getReferenceDevice() const { return mrBookData.getReferenceDevice(); @@ -841,6 +862,20 @@ Reference< XSpreadsheet > WorkbookHelper::getSheetFromDoc( sal_Int32 nSheet ) co return xSheet; } +Reference< XSpreadsheet > WorkbookHelper::getSheetFromDoc( const OUString& rSheet ) const +{ + Reference< XSpreadsheet > xSheet; + try + { + Reference< XNameAccess > xSheetsNA( getDocument()->getSheets(), UNO_QUERY_THROW ); + xSheet.set( xSheetsNA->getByName( rSheet ), UNO_QUERY ); + } + catch( Exception& ) + { + } + return xSheet; +} + Reference< XCell > WorkbookHelper::getCellFromDoc( const CellAddress& rAddress ) const { Reference< XCell > xCell; @@ -936,6 +971,11 @@ TableBuffer& WorkbookHelper::getTables() const return mrBookData.getTables(); } +ScenarioBuffer& WorkbookHelper::getScenarios() const +{ + return mrBookData.getScenarios(); +} + WebQueryBuffer& WorkbookHelper::getWebQueries() const { return mrBookData.getWebQueries(); diff --git a/oox/source/xls/worksheetbuffer.cxx b/oox/source/xls/worksheetbuffer.cxx index da011649acb9..64e8acbb6c9c 100644 --- a/oox/source/xls/worksheetbuffer.cxx +++ b/oox/source/xls/worksheetbuffer.cxx @@ -101,7 +101,7 @@ void WorksheetBuffer::importSheet( const AttributeList& rAttribs ) { SheetInfoModel aModel; aModel.maRelId = rAttribs.getString( R_TOKEN( id ), OUString() ); - aModel.maName = rAttribs.getString( XML_name, OUString() ); + aModel.maName = rAttribs.getXString( XML_name, OUString() ); aModel.mnSheetId = rAttribs.getInteger( XML_sheetId, -1 ); aModel.mnState = rAttribs.getToken( XML_state, XML_visible ); insertSheet( aModel ); @@ -128,8 +128,8 @@ void WorksheetBuffer::importSheet( BiffInputStream& rStrm ) SheetInfoModel aModel; aModel.maName = (getBiff() == BIFF8) ? - rStrm.readUniString( rStrm.readuInt8() ) : - rStrm.readByteString( false, getTextEncoding() ); + rStrm.readUniStringBody( rStrm.readuInt8() ) : + rStrm.readByteStringUC( false, getTextEncoding() ); static const sal_Int32 spnStates[] = { XML_visible, XML_hidden, XML_veryHidden }; aModel.mnState = STATIC_ARRAY_SELECT( spnStates, nState, XML_visible ); insertSheet( aModel ); diff --git a/oox/source/xls/worksheetfragment.cxx b/oox/source/xls/worksheetfragment.cxx index 337223aecd59..4b754114b031 100644 --- a/oox/source/xls/worksheetfragment.cxx +++ b/oox/source/xls/worksheetfragment.cxx @@ -31,17 +31,21 @@ #include "oox/xls/worksheetfragment.hxx" #include "oox/helper/attributelist.hxx" #include "oox/helper/recordinputstream.hxx" +#include "oox/core/filterbase.hxx" #include "oox/core/relations.hxx" #include "oox/xls/addressconverter.hxx" #include "oox/xls/autofiltercontext.hxx" #include "oox/xls/biffinputstream.hxx" #include "oox/xls/commentsfragment.hxx" #include "oox/xls/condformatcontext.hxx" +#include "oox/xls/drawingfragment.hxx" #include "oox/xls/externallinkbuffer.hxx" #include "oox/xls/pagesettings.hxx" #include "oox/xls/pivottablebuffer.hxx" #include "oox/xls/pivottablefragment.hxx" #include "oox/xls/querytablefragment.hxx" +#include "oox/xls/scenariobuffer.hxx" +#include "oox/xls/scenariocontext.hxx" #include "oox/xls/sheetdatacontext.hxx" #include "oox/xls/tablefragment.hxx" #include "oox/xls/viewsettings.hxx" @@ -84,21 +88,12 @@ const sal_uInt32 BIFF_DATAVAL_NODROPDOWN = 0x00000200; const sal_uInt32 BIFF_DATAVAL_SHOWINPUT = 0x00040000; const sal_uInt32 BIFF_DATAVAL_SHOWERROR = 0x00080000; -const sal_uInt32 OLE_HYPERLINK_HASTARGET = 0x00000001; /// Has hyperlink moniker. -const sal_uInt32 OLE_HYPERLINK_ABSOLUTE = 0x00000002; /// Absolute path. -const sal_uInt32 OLE_HYPERLINK_HASLOCATION = 0x00000008; /// Has target location. -const sal_uInt32 OLE_HYPERLINK_HASDISPLAY = 0x00000010; /// Has display string. -const sal_uInt32 OLE_HYPERLINK_HASGUID = 0x00000020; /// Has identification GUID. -const sal_uInt32 OLE_HYPERLINK_HASTIME = 0x00000040; /// Has creation time. -const sal_uInt32 OLE_HYPERLINK_HASFRAME = 0x00000080; /// Has frame. -const sal_uInt32 OLE_HYPERLINK_ASSTRING = 0x00000100; /// Hyperlink as simple string. - const sal_Int32 OOBIN_OLEOBJECT_CONTENT = 1; const sal_Int32 OOBIN_OLEOBJECT_ICON = 4; const sal_Int32 OOBIN_OLEOBJECT_ALWAYS = 1; const sal_Int32 OOBIN_OLEOBJECT_ONCALL = 3; -const sal_uInt16 OOBIN_OLEOBJECT_AUTOLOAD = 0x0001; -const sal_uInt16 OOBIN_OLEOBJECT_LINKED = 0x0002; +const sal_uInt16 OOBIN_OLEOBJECT_LINKED = 0x0001; +const sal_uInt16 OOBIN_OLEOBJECT_AUTOLOAD = 0x0002; } // namespace @@ -178,10 +173,10 @@ void OoxDataValidationsContext::importDataValidation( const AttributeList& rAttr { mxValModel.reset( new ValidationModel ); getAddressConverter().convertToCellRangeList( mxValModel->maRanges, rAttribs.getString( XML_sqref, OUString() ), getSheetIndex(), true ); - mxValModel->maInputTitle = rAttribs.getString( XML_promptTitle, OUString() ); - mxValModel->maInputMessage = rAttribs.getString( XML_prompt, OUString() ); - mxValModel->maErrorTitle = rAttribs.getString( XML_errorTitle, OUString() ); - mxValModel->maErrorMessage = rAttribs.getString( XML_error, OUString() ); + mxValModel->maInputTitle = rAttribs.getXString( XML_promptTitle, OUString() ); + mxValModel->maInputMessage = rAttribs.getXString( XML_prompt, OUString() ); + mxValModel->maErrorTitle = rAttribs.getXString( XML_errorTitle, OUString() ); + mxValModel->maErrorMessage = rAttribs.getXString( XML_error, OUString() ); mxValModel->mnType = rAttribs.getToken( XML_type, XML_none ); mxValModel->mnOperator = rAttribs.getToken( XML_operator, XML_between ); mxValModel->mnErrorStyle = rAttribs.getToken( XML_errorStyle, XML_stop ); @@ -239,10 +234,10 @@ OoxWorksheetFragment::OoxWorksheetFragment( const WorkbookHelper& rHelper, // import data tables related to this worksheet RelationsRef xTableRels = getRelations().getRelationsFromType( CREATE_OFFICEDOC_RELATIONSTYPE( "table" ) ); for( Relations::const_iterator aIt = xTableRels->begin(), aEnd = xTableRels->end(); aIt != aEnd; ++aIt ) - importOoxFragment( new OoxTableFragment( *this, getFragmentPathFromTarget( aIt->second.maTarget ) ) ); + importOoxFragment( new OoxTableFragment( *this, getFragmentPathFromRelation( aIt->second ) ) ); // import comments related to this worksheet - ::rtl::OUString aCommentsFragmentPath = getFragmentPathFromType( CREATE_OFFICEDOC_RELATIONSTYPE( "comments" ) ); + OUString aCommentsFragmentPath = getFragmentPathFromFirstType( CREATE_OFFICEDOC_RELATIONSTYPE( "comments" ) ); if( aCommentsFragmentPath.getLength() > 0 ) importOoxFragment( new OoxCommentsFragment( *this, aCommentsFragmentPath ) ); } @@ -294,6 +289,8 @@ ContextHandlerRef OoxWorksheetFragment::onCreateContext( sal_Int32 nElement, con case XLS_TOKEN( picture ): getPageSettings().importPicture( getRelations(), rAttribs ); break; case XLS_TOKEN( drawing ): importDrawing( rAttribs ); break; case XLS_TOKEN( legacyDrawing ): importLegacyDrawing( rAttribs ); break; + case XLS_TOKEN( scenarios ): + return new OoxScenariosContext( *this ); } break; @@ -409,6 +406,8 @@ ContextHandlerRef OoxWorksheetFragment::onCreateRecordContext( sal_Int32 nRecId, case OOBIN_ID_PHONETICPR: getWorksheetSettings().importPhoneticPr( rStrm ); break; case OOBIN_ID_DRAWING: importDrawing( rStrm ); break; case OOBIN_ID_LEGACYDRAWING: importLegacyDrawing( rStrm ); break; + case OOBIN_ID_SCENARIOS: + return new OoxScenariosContext( *this ); } break; @@ -470,6 +469,8 @@ const RecordInfo* OoxWorksheetFragment::getRecordInfos() const { OOBIN_ID_OLEOBJECTS, OOBIN_ID_OLEOBJECTS + 2 }, { OOBIN_ID_ROW, -1 }, { OOBIN_ID_ROWBREAKS, OOBIN_ID_ROWBREAKS + 1 }, + { OOBIN_ID_SCENARIO, OOBIN_ID_SCENARIO + 1 }, + { OOBIN_ID_SCENARIOS, OOBIN_ID_SCENARIOS + 1 }, { OOBIN_ID_SHEETDATA, OOBIN_ID_SHEETDATA + 1 }, { OOBIN_ID_SHEETVIEW, OOBIN_ID_SHEETVIEW + 1 }, { OOBIN_ID_SHEETVIEWS, OOBIN_ID_SHEETVIEWS + 1 }, @@ -488,12 +489,12 @@ void OoxWorksheetFragment::initializeImport() // import query table fragments related to this worksheet RelationsRef xQueryRels = getRelations().getRelationsFromType( CREATE_OFFICEDOC_RELATIONSTYPE( "queryTable" ) ); for( Relations::const_iterator aIt = xQueryRels->begin(), aEnd = xQueryRels->end(); aIt != aEnd; ++aIt ) - importOoxFragment( new OoxQueryTableFragment( *this, getFragmentPathFromTarget( aIt->second.maTarget ) ) ); + importOoxFragment( new OoxQueryTableFragment( *this, getFragmentPathFromRelation( aIt->second ) ) ); // import pivot table fragments related to this worksheet RelationsRef xPivotRels = getRelations().getRelationsFromType( CREATE_OFFICEDOC_RELATIONSTYPE( "pivotTable" ) ); for( Relations::const_iterator aIt = xPivotRels->begin(), aEnd = xPivotRels->end(); aIt != aEnd; ++aIt ) - importOoxFragment( new OoxPivotTableFragment( *this, getFragmentPathFromTarget( aIt->second.maTarget ) ) ); + importOoxFragment( new OoxPivotTableFragment( *this, getFragmentPathFromRelation( aIt->second ) ) ); } void OoxWorksheetFragment::finalizeImport() @@ -558,10 +559,10 @@ void OoxWorksheetFragment::importHyperlink( const AttributeList& rAttribs ) HyperlinkModel aModel; if( getAddressConverter().convertToCellRange( aModel.maRange, rAttribs.getString( XML_ref, OUString() ), getSheetIndex(), true, true ) ) { - aModel.maTarget = getRelations().getTargetFromRelId( rAttribs.getString( R_TOKEN( id ), OUString() ) ); - aModel.maLocation = rAttribs.getString( XML_location, OUString() ); - aModel.maDisplay = rAttribs.getString( XML_display, OUString() ); - aModel.maTooltip = rAttribs.getString( XML_tooltip, OUString() ); + aModel.maTarget = getRelations().getExternalTargetFromRelId( rAttribs.getString( R_TOKEN( id ), OUString() ) ); + aModel.maLocation = rAttribs.getXString( XML_location, OUString() ); + aModel.maDisplay = rAttribs.getXString( XML_display, OUString() ); + aModel.maTooltip = rAttribs.getXString( XML_tooltip, OUString() ); setHyperlink( aModel ); } } @@ -588,28 +589,29 @@ void OoxWorksheetFragment::importLegacyDrawing( const AttributeList& rAttribs ) void OoxWorksheetFragment::importOleObject( const AttributeList& rAttribs ) { - OleObjectModel aModel; - aModel.maProgId = rAttribs.getString( XML_progId, OUString() ); + ::oox::vml::OleObjectInfo aInfo; + aInfo.setShapeId( rAttribs.getInteger( XML_shapeId, 0 ) ); OSL_ENSURE( rAttribs.hasAttribute( XML_link ) != rAttribs.hasAttribute( R_TOKEN( id ) ), - "OoxWorksheetFragment::importOleObject - either linked or embedded" ); - if( rAttribs.hasAttribute( XML_link ) ) - (void)0; - if( rAttribs.hasAttribute( R_TOKEN( id ) ) ) - aModel.maStoragePath = getFragmentPathFromRelId( rAttribs.getString( R_TOKEN( id ), OUString() ) ); - aModel.mnAspect = rAttribs.getToken( XML_dvAspect, XML_DVASPECT_CONTENT ); - aModel.mnUpdateMode = rAttribs.getToken( XML_oleUpdate, XML_OLEUPDATE_ALWAYS ); - aModel.mnShapeId = rAttribs.getInteger( XML_shapeId, 0 ); - aModel.mbAutoLoad = rAttribs.getBool( XML_autoLoad, false ); - setOleObject( aModel ); + "OoxWorksheetFragment::importOleObject - OLE object must be either linked or embedded" ); + aInfo.mbLinked = rAttribs.hasAttribute( XML_link ); + if( aInfo.mbLinked ) + aInfo.maTargetLink = getFormulaParser().importOleTargetLink( rAttribs.getString( XML_link, OUString() ) ); + else if( rAttribs.hasAttribute( R_TOKEN( id ) ) ) + importEmbeddedOleData( aInfo.maEmbeddedData, rAttribs.getString( R_TOKEN( id ), OUString() ) ); + aInfo.maProgId = rAttribs.getString( XML_progId, OUString() ); + aInfo.mbShowAsIcon = rAttribs.getToken( XML_dvAspect, XML_DVASPECT_CONTENT ) == XML_DVASPECT_ICON; + aInfo.mbAutoUpdate = rAttribs.getToken( XML_oleUpdate, XML_OLEUPDATE_ONCALL ) == XML_OLEUPDATE_ALWAYS; + aInfo.mbAutoLoad = rAttribs.getBool( XML_autoLoad, false ); + getVmlDrawing().registerOleObject( aInfo ); } void OoxWorksheetFragment::importControl( const AttributeList& rAttribs ) { - FormControlModel aModel; - aModel.maStoragePath = getFragmentPathFromRelId( rAttribs.getString( R_TOKEN( id ), OUString() ) ); - aModel.maName = rAttribs.getString( XML_name, OUString() ); - aModel.mnShapeId = rAttribs.getInteger( XML_shapeId, 0 ); - setFormControl( aModel ); + ::oox::vml::ControlInfo aInfo; + aInfo.setShapeId( rAttribs.getInteger( XML_shapeId, 0 ) ); + aInfo.maFragmentPath = getFragmentPathFromRelId( rAttribs.getString( R_TOKEN( id ), OUString() ) ); + aInfo.maName = rAttribs.getString( XML_name, OUString() ); + getVmlDrawing().registerControl( aInfo ); } void OoxWorksheetFragment::importDimension( RecordInputStream& rStrm ) @@ -678,7 +680,7 @@ void OoxWorksheetFragment::importHyperlink( RecordInputStream& rStrm ) HyperlinkModel aModel; if( getAddressConverter().convertToCellRange( aModel.maRange, aBinRange, getSheetIndex(), true, true ) ) { - aModel.maTarget = getRelations().getTargetFromRelId( rStrm.readString() ); + aModel.maTarget = getRelations().getExternalTargetFromRelId( rStrm.readString() ); rStrm >> aModel.maLocation >> aModel.maTooltip >> aModel.maDisplay; setHyperlink( aModel ); } @@ -705,27 +707,36 @@ void OoxWorksheetFragment::importLegacyDrawing( RecordInputStream& rStrm ) void OoxWorksheetFragment::importOleObject( RecordInputStream& rStrm ) { - OleObjectModel aModel; - sal_Int32 nAspect, nUpdateMode; + ::oox::vml::OleObjectInfo aInfo; + sal_Int32 nAspect, nUpdateMode, nShapeId; sal_uInt16 nFlags; - rStrm >> nAspect >> nUpdateMode >> aModel.mnShapeId >> nFlags >> aModel.maProgId; - if( getFlag( nFlags, OOBIN_OLEOBJECT_LINKED ) ) - (void)0; + rStrm >> nAspect >> nUpdateMode >> nShapeId >> nFlags >> aInfo.maProgId; + aInfo.mbLinked = getFlag( nFlags, OOBIN_OLEOBJECT_LINKED ); + if( aInfo.mbLinked ) + aInfo.maTargetLink = getFormulaParser().importOleTargetLink( rStrm ); else - aModel.maStoragePath = getFragmentPathFromRelId( rStrm.readString() ); - aModel.mnAspect = (nAspect == OOBIN_OLEOBJECT_ICON) ? XML_DVASPECT_ICON : XML_DVASPECT_CONTENT; - aModel.mnUpdateMode = (nUpdateMode == OOBIN_OLEOBJECT_ONCALL) ? XML_OLEUPDATE_ONCALL : XML_OLEUPDATE_ALWAYS; - aModel.mbAutoLoad = getFlag( nFlags, OOBIN_OLEOBJECT_AUTOLOAD ); - setOleObject( aModel ); + importEmbeddedOleData( aInfo.maEmbeddedData, rStrm.readString() ); + aInfo.setShapeId( nShapeId ); + aInfo.mbShowAsIcon = nAspect == OOBIN_OLEOBJECT_ICON; + aInfo.mbAutoUpdate = nUpdateMode == OOBIN_OLEOBJECT_ALWAYS; + aInfo.mbAutoLoad = getFlag( nFlags, OOBIN_OLEOBJECT_AUTOLOAD ); + getVmlDrawing().registerOleObject( aInfo ); } void OoxWorksheetFragment::importControl( RecordInputStream& rStrm ) { - FormControlModel aModel; - rStrm >> aModel.mnShapeId; - aModel.maStoragePath = getFragmentPathFromRelId( rStrm.readString() ); - rStrm >> aModel.maName; - setFormControl( aModel ); + ::oox::vml::ControlInfo aInfo; + aInfo.setShapeId( rStrm.readInt32() ); + aInfo.maFragmentPath = getFragmentPathFromRelId( rStrm.readString() ); + rStrm >> aInfo.maName; + getVmlDrawing().registerControl( aInfo ); +} + +void OoxWorksheetFragment::importEmbeddedOleData( StreamDataSequence& orEmbeddedData, const OUString& rRelId ) +{ + OUString aFragmentPath = getFragmentPathFromRelId( rRelId ); + if( aFragmentPath.getLength() > 0 ) + getBaseFilter().importBinaryData( orEmbeddedData, aFragmentPath ); } // ============================================================================ @@ -874,6 +885,7 @@ bool BiffWorksheetFragment::importFragment() case BIFF_ID_PICTURE: rPageSett.importPicture( mrStrm ); break; case BIFF_ID_PTDEFINITION: importPTDefinition(); break; case BIFF_ID_SAVERECALC: rWorkbookSett.importSaveRecalc( mrStrm ); break; + case BIFF_ID_SCENARIOS: importScenarios(); break; case BIFF_ID_SCENPROTECT: rWorksheetSett.importScenProtect( mrStrm ); break; case BIFF_ID_SCL: rSheetViewSett.importScl( mrStrm ); break; case BIFF_ID_SHEETPR: rWorksheetSett.importSheetPr( mrStrm ); break; @@ -986,9 +998,7 @@ namespace { OUString lclReadDataValMessage( BiffInputStream& rStrm ) { // empty strings are single NUL characters (string length is 1) - rStrm.enableNulChars( true ); - OUString aMessage = rStrm.readUniString(); - rStrm.enableNulChars( false ); + OUString aMessage = rStrm.readUniString( true ); if( (aMessage.getLength() == 1) && (aMessage[ 0 ] == 0) ) aMessage = OUString(); return aMessage; @@ -998,11 +1008,9 @@ ApiTokenSequence lclReadDataValFormula( BiffInputStream& rStrm, FormulaParser& r { sal_uInt16 nFmlaSize = rStrm.readuInt16(); rStrm.skip( 2 ); - TokensFormulaContext aContext( true, false ); // enable NUL characters, string list is single tStr token with NUL separators - rStrm.enableNulChars( true ); + TokensFormulaContext aContext( true, false, true ); rParser.importFormula( aContext, rStrm, &nFmlaSize ); - rStrm.enableNulChars( false ); return aContext.getTokens(); } @@ -1059,30 +1067,6 @@ void BiffWorksheetFragment::importDimension() setDimension( aRange ); } -OUString BiffWorksheetFragment::readHyperlinkString( rtl_TextEncoding eTextEnc, bool bUnicode ) -{ - OUString aRet; - sal_Int32 nChars = mrStrm.readInt32(); - if( nChars > 0 ) - { - sal_uInt16 nReadChars = getLimitedValue< sal_uInt16, sal_Int32 >( nChars, 0, SAL_MAX_UINT16 ); - // strings are NUL terminated - mrStrm.enableNulChars( true ); - aRet = bUnicode ? - mrStrm.readUnicodeArray( nReadChars ) : - mrStrm.readCharArray( nReadChars, eTextEnc ); - mrStrm.enableNulChars( false ); - // remove trailing NUL and possible other garbage - sal_Int32 nNulPos = aRet.indexOf( '\0' ); - if( nNulPos >= 0 ) - aRet = aRet.copy( 0, nNulPos ); - // skip remaining chars - sal_uInt32 nSkip = static_cast< sal_uInt32 >( nChars - nReadChars ); - mrStrm.skip( (bUnicode ? 2 : 1) * nSkip ); - } - return aRet; -} - void BiffWorksheetFragment::importHyperlink() { HyperlinkModel aModel; @@ -1096,75 +1080,11 @@ void BiffWorksheetFragment::importHyperlink() if( !getAddressConverter().convertToCellRange( aModel.maRange, aBiffRange, getSheetIndex(), true, true ) ) return; - BiffGuid aGuid; - sal_uInt32 nVersion, nFlags; - mrStrm >> aGuid >> nVersion >> nFlags; - - OSL_ENSURE( aGuid == BiffHelper::maGuidStdHlink, "BiffWorksheetFragment::importHyperlink - unexpected header GUID" ); - OSL_ENSURE( nVersion == 2, "BiffWorksheetFragment::importHyperlink - unexpected header version" ); - if( !(aGuid == BiffHelper::maGuidStdHlink) || (nVersion != 2) ) + // try to read the StdHlink data + if( !::oox::ole::OleHelper::importStdHlink( aModel, mrStrm, getTextEncoding(), true ) ) return; - // display string - if( getFlag( nFlags, OLE_HYPERLINK_HASDISPLAY ) ) - aModel.maDisplay = readHyperlinkString( getTextEncoding(), true ); - // frame string - if( getFlag( nFlags, OLE_HYPERLINK_HASFRAME ) ) - aModel.maFrame = readHyperlinkString( getTextEncoding(), true ); - - // target - if( getFlag( nFlags, OLE_HYPERLINK_HASTARGET ) ) - { - if( getFlag( nFlags, OLE_HYPERLINK_ASSTRING ) ) - { - OSL_ENSURE( getFlag( nFlags, OLE_HYPERLINK_ABSOLUTE ), "BiffWorksheetFragment::importHyperlink - link not absolute" ); - aModel.maTarget = readHyperlinkString( getTextEncoding(), true ); - } - else // hyperlink moniker - { - mrStrm >> aGuid; - if( aGuid == BiffHelper::maGuidFileMoniker ) - { - // file name, maybe relative and with directory up-count - sal_Int16 nUpLevels; - mrStrm >> nUpLevels; - OSL_ENSURE( (nUpLevels == 0) || !getFlag( nFlags, OLE_HYPERLINK_ABSOLUTE ), "BiffWorksheetFragment::importHyperlink - absolute filename with upcount" ); - aModel.maTarget = readHyperlinkString( getTextEncoding(), false ); - mrStrm.skip( 24 ); - sal_Int32 nBytes = mrStrm.readInt32(); - if( nBytes > 0 ) - { - sal_Int64 nEndPos = mrStrm.tell() + ::std::max< sal_Int32 >( nBytes, 0 ); - sal_uInt16 nChars = getLimitedValue< sal_uInt16, sal_Int32 >( mrStrm.readInt32() / 2, 0, SAL_MAX_UINT16 ); - mrStrm.skip( 2 ); // key value - aModel.maTarget = mrStrm.readUnicodeArray( nChars ); // NOT null terminated - mrStrm.seek( nEndPos ); - } - if( !getFlag( nFlags, OLE_HYPERLINK_ABSOLUTE ) ) - for( sal_Int16 nLevel = 0; nLevel < nUpLevels; ++nLevel ) - aModel.maTarget = CREATE_OUSTRING( "../" ) + aModel.maTarget; - } - else if( aGuid == BiffHelper::maGuidUrlMoniker ) - { - // URL, maybe relative and with leading '../' - sal_Int32 nBytes = mrStrm.readInt32(); - sal_Int64 nEndPos = mrStrm.tell() + ::std::max< sal_Int32 >( nBytes, 0 ); - aModel.maTarget = mrStrm.readNulUnicodeArray(); - mrStrm.seek( nEndPos ); - } - else - { - OSL_ENSURE( false, "BiffWorksheetFragment::importHyperlink - unsupported hyperlink moniker" ); - return; - } - } - } - - // target location - if( getFlag( nFlags, OLE_HYPERLINK_HASLOCATION ) ) - aModel.maLocation = readHyperlinkString( getTextEncoding(), true ); - - // try to read the SCREENTIP record + // try to read the optional following SCREENTIP record if( (mrStrm.getNextRecId() == BIFF_ID_SCREENTIP) && mrStrm.startNextRecord() ) { mrStrm.skip( 2 ); // repeated record id @@ -1230,6 +1150,11 @@ void BiffWorksheetFragment::importPTDefinition() mxPTContext->importRecord(); } +void BiffWorksheetFragment::importScenarios() +{ + getScenarios().createSheetScenarios( getSheetIndex() ).importScenarios( mrStrm ); +} + void BiffWorksheetFragment::importStandardWidth() { sal_uInt16 nWidth; diff --git a/oox/source/xls/worksheethelper.cxx b/oox/source/xls/worksheethelper.cxx index 2e7a1b1f31fd..be8ac3d359db 100644 --- a/oox/source/xls/worksheethelper.cxx +++ b/oox/source/xls/worksheethelper.cxx @@ -40,6 +40,7 @@ #include <com/sun/star/util/XMergeable.hpp> #include <com/sun/star/util/XNumberFormatsSupplier.hpp> #include <com/sun/star/util/XNumberFormatTypes.hpp> +#include <com/sun/star/drawing/XDrawPageSupplier.hpp> #include <com/sun/star/table/XColumnRowRange.hpp> #include <com/sun/star/sheet/TableValidationVisibility.hpp> #include <com/sun/star/sheet/ValidationType.hpp> @@ -91,6 +92,8 @@ using ::com::sun::star::util::XNumberFormatsSupplier; using ::com::sun::star::util::XNumberFormatTypes; using ::com::sun::star::awt::Point; using ::com::sun::star::awt::Size; +using ::com::sun::star::drawing::XDrawPage; +using ::com::sun::star::drawing::XDrawPageSupplier; using ::com::sun::star::table::BorderLine; using ::com::sun::star::table::CellAddress; using ::com::sun::star::table::CellRangeAddress; @@ -349,23 +352,6 @@ void ValidationModel::setBinErrorStyle( sal_uInt8 nErrorStyle ) mnErrorStyle = STATIC_ARRAY_SELECT( spnErrorStyles, nErrorStyle, XML_stop ); } -// ---------------------------------------------------------------------------- - -OleObjectModel::OleObjectModel() : - mnAspect( XML_DVASPECT_CONTENT ), - mnUpdateMode( XML_OLEUPDATE_ALWAYS ), - mnShapeId( 0 ), - mbAutoLoad( false ) -{ -} - -// ---------------------------------------------------------------------------- - -FormControlModel::FormControlModel() : - mnShapeId( 0 ) -{ -} - // ============================================================================ // ============================================================================ @@ -409,6 +395,9 @@ public: /** Returns the XTableRows interface for a range of rows. */ Reference< XTableRows > getRows( sal_Int32 nFirstRow, sal_Int32 nLastRow ) const; + /** Returns the XDrawPage interface of the draw page of the current sheet. */ + Reference< XDrawPage > getDrawPage() const; + /** Returns the absolute cell position in 1/100 mm. */ Point getCellPosition( sal_Int32 nCol, sal_Int32 nRow ) const; /** Returns the cell size in 1/100 mm. */ @@ -428,6 +417,8 @@ public: inline PageSettings& getPageSettings() { return maPageSett; } /** Returns the view settings for this sheet. */ inline SheetViewSettings& getSheetViewSettings() { return maSheetViewSett; } + /** Returns the VML drawing page for this sheet (OOX only!). */ + inline VmlDrawing& getVmlDrawing() { return *mxVmlDrawing; } /** Changes the current sheet type. */ inline void setSheetType( WorksheetType eSheetType ) { meSheetType = eSheetType; } @@ -447,10 +438,6 @@ public: void setDrawingPath( const OUString& rDrawingPath ); /** Sets the path to the legacy VML drawing fragment of this sheet. */ void setVmlDrawingPath( const OUString& rVmlDrawingPath ); - /** Sets additional data for an OLE object. */ - void setOleObject( const OleObjectModel& rModel ); - /** Sets additional data for an OCX form control. */ - void setFormControl( const FormControlModel& rModel ); /** Sets base width for all columns (without padding pixels). This value is only used, if base width has not been set with setDefaultColumnWidth(). */ @@ -486,8 +473,6 @@ private: typedef ::std::map< sal_Int32, RowModel > RowModelMap; typedef ::std::list< HyperlinkModel > HyperlinkModelList; typedef ::std::list< ValidationModel > ValidationModelList; - typedef ::std::map< sal_Int32, OleObjectModel > OleObjectModelMap; - typedef ::std::map< sal_Int32, FormControlModel > FormControlModelMap; struct XfIdRowRange { @@ -548,8 +533,10 @@ private: /** Merges the passed merged range and updates right/bottom cell borders. */ void finalizeMergedRange( const CellRangeAddress& rRange ); - /** Imports the drawing layer of the sheet. */ + /** Imports the drawing layer of the sheet (DrawingML part). */ void finalizeDrawing(); + /** Imports the drawing layer of the sheet (VML part). */ + void finalizeVmlDrawing(); /** Converts column properties for all columns in the sheet. */ void convertColumns(); @@ -567,6 +554,8 @@ private: void groupColumnsOrRows( sal_Int32 nFirstColRow, sal_Int32 nLastColRow, bool bCollapsed, bool bRows ); private: + typedef ::std::auto_ptr< VmlDrawing > VmlDrawingPtr; + const OUString maTrueFormula; /// Replacement formula for TRUE boolean cells. const OUString maFalseFormula; /// Replacement formula for FALSE boolean cells. const OUString maSheetCellRanges; /// Service name for a SheetCellRanges object. @@ -579,8 +568,6 @@ private: RowModelMap maRowModels; /// Rows sorted by row index. HyperlinkModelList maHyperlinks; /// Cell ranges containing hyperlinks. ValidationModelList maValidations; /// Cell ranges containing data validation settings. - OleObjectModelMap maOleObjects; /// OLE objects, mapped to VML shape identifier. - FormControlModelMap maFormControls; /// OCX form controls, mapped to VML shape identifier. XfIdRowRange maXfIdRowRange; /// Cached XF identifier for a range of rows. XfIdRangeMap maXfIdRanges; /// Collected XF identifiers for cell ranges. MergedRangeList maMergedRanges; /// Merged cell ranges. @@ -592,6 +579,7 @@ private: CommentsBuffer maComments; /// Buffer for all cell comments in this sheet. PageSettings maPageSett; /// Page/print settings for this sheet. SheetViewSettings maSheetViewSett; /// View settings for this sheet. + VmlDrawingPtr mxVmlDrawing; /// Collection of all VML shapes. OUString maDrawingPath; /// Path to DrawingML fragment. OUString maVmlDrawingPath; /// Path to legacy VML drawing fragment. ISegmentProgressBarRef mxProgressBar; /// Sheet progress bar. @@ -647,6 +635,11 @@ WorksheetData::WorksheetData( const WorkbookHelper& rHelper, ISegmentProgressBar maDefRowModel.mbHidden = false; maDefRowModel.mbCollapsed = false; + // buffers + if( getFilterType() == FILTER_OOX ) + mxVmlDrawing.reset( new VmlDrawing( *this ) ); + + // prepare progress bars if( mxProgressBar.get() ) { mxRowProgress = mxProgressBar->createSegment( 0.5 ); @@ -690,8 +683,7 @@ Reference< XSheetCellRanges > WorksheetData::getCellRangeList( const ApiCellRang Reference< XSheetCellRanges > xRanges; if( mxSheet.is() && !rRanges.empty() ) try { - Reference< XMultiServiceFactory > xFactory( getDocument(), UNO_QUERY_THROW ); - xRanges.set( xFactory->createInstance( maSheetCellRanges ), UNO_QUERY_THROW ); + xRanges.set( getDocumentFactory()->createInstance( maSheetCellRanges ), UNO_QUERY_THROW ); Reference< XSheetCellRangeContainer > xRangeCont( xRanges, UNO_QUERY_THROW ); xRangeCont->addRangeAddresses( ContainerHelper::vectorToSequence( rRanges ), sal_False ); } @@ -757,6 +749,20 @@ Reference< XTableRows > WorksheetData::getRows( sal_Int32 nFirstRow, sal_Int32 n return xRows; } +Reference< XDrawPage > WorksheetData::getDrawPage() const +{ + Reference< XDrawPage > xDrawPage; + try + { + Reference< XDrawPageSupplier > xDrawPageSupp( mxSheet, UNO_QUERY_THROW ); + xDrawPage = xDrawPageSupp->getDrawPage(); + } + catch( Exception& ) + { + } + return xDrawPage; +} + Point WorksheetData::getCellPosition( sal_Int32 nCol, sal_Int32 nRow ) const { Point aPoint; @@ -871,27 +877,15 @@ void WorksheetData::setVmlDrawingPath( const OUString& rVmlDrawingPath ) maVmlDrawingPath = rVmlDrawingPath; } -void WorksheetData::setOleObject( const OleObjectModel& rModel ) -{ - if( rModel.mnShapeId > 0 ) - maOleObjects[ rModel.mnShapeId ] = rModel; -} - -void WorksheetData::setFormControl( const FormControlModel& rModel ) -{ - if( rModel.mnShapeId > 0 ) - maFormControls[ rModel.mnShapeId ] = rModel; -} - void WorksheetData::setBaseColumnWidth( sal_Int32 nWidth ) { // do not modify width, if setDefaultColumnWidth() has been used if( !mbHasDefWidth && (nWidth > 0) ) { - /* #i3006# add 5 pixels padding to the width, assuming 1 pixel = - 1/96 inch. => 5/96 inch == 1.32 mm. */ + // #i3006# add 5 pixels padding to the width const UnitConverter& rUnitConv = getUnitConverter(); - maDefColModel.mfWidth = rUnitConv.scaleFromMm100( rUnitConv.scaleToMm100( nWidth, UNIT_DIGIT ) + 132, UNIT_DIGIT ); + maDefColModel.mfWidth = rUnitConv.scaleFromMm100( + rUnitConv.scaleToMm100( nWidth, UNIT_DIGIT ) + rUnitConv.scaleToMm100( 5, UNIT_SCREENX ), UNIT_DIGIT ); } } @@ -1014,6 +1008,7 @@ void WorksheetData::finalizeWorksheetImport() lclUpdateProgressBar( mxFinalProgress, 0.75 ); maComments.finalizeImport(); finalizeDrawing(); + finalizeVmlDrawing(); lclUpdateProgressBar( mxFinalProgress, 1.0 ); // reset current sheet index in global data @@ -1217,12 +1212,11 @@ void WorksheetData::finalizeHyperlink( const CellAddress& rAddress, const OUStri // #i54261# restrict creation of URL field to text cells case ::com::sun::star::table::CellContentType_TEXT: { - Reference< XMultiServiceFactory > xFactory( getDocument(), UNO_QUERY ); Reference< XText > xText( xCell, UNO_QUERY ); - if( xFactory.is() && xText.is() ) + if( xText.is() ) { // create a URL field object and set its properties - Reference< XTextContent > xUrlField( xFactory->createInstance( maUrlTextField ), UNO_QUERY ); + Reference< XTextContent > xUrlField( getDocumentFactory()->createInstance( maUrlTextField ), UNO_QUERY ); OSL_ENSURE( xUrlField.is(), "WorksheetData::finalizeHyperlink - cannot create text field" ); if( xUrlField.is() ) { @@ -1412,6 +1406,14 @@ void WorksheetData::finalizeDrawing() } } +void WorksheetData::finalizeVmlDrawing() +{ + OSL_ENSURE( (getFilterType() == FILTER_OOX) || (maVmlDrawingPath.getLength() == 0), + "WorksheetData::finalizeVmlDrawing - unexpected VML path" ); + if( (getFilterType() == FILTER_OOX) && (maVmlDrawingPath.getLength() > 0) ) + importOoxFragment( new OoxVmlDrawingFragment( *this, maVmlDrawingPath ) ); +} + void WorksheetData::convertColumns() { sal_Int32 nNextCol = 0; @@ -1717,6 +1719,11 @@ Reference< XTableRows > WorksheetHelper::getRows( sal_Int32 nFirstRow, sal_Int32 return mrSheetData.getRows( nFirstRow, nLastRow ); } +Reference< XDrawPage > WorksheetHelper::getDrawPage() const +{ + return mrSheetData.getDrawPage(); +} + Point WorksheetHelper::getCellPosition( sal_Int32 nCol, sal_Int32 nRow ) const { return mrSheetData.getCellPosition( nCol, nRow ); @@ -1762,6 +1769,11 @@ SheetViewSettings& WorksheetHelper::getSheetViewSettings() const return mrSheetData.getSheetViewSettings(); } +VmlDrawing& WorksheetHelper::getVmlDrawing() const +{ + return mrSheetData.getVmlDrawing(); +} + void WorksheetHelper::setStringCell( const Reference< XCell >& rxCell, const OUString& rText ) const { OSL_ENSURE( rxCell.is(), "WorksheetHelper::setStringCell - missing cell interface" ); @@ -2003,16 +2015,6 @@ void WorksheetHelper::setVmlDrawingPath( const OUString& rVmlDrawingPath ) mrSheetData.setVmlDrawingPath( rVmlDrawingPath ); } -void WorksheetHelper::setOleObject( const OleObjectModel& rModel ) -{ - mrSheetData.setOleObject( rModel ); -} - -void WorksheetHelper::setFormControl( const FormControlModel& rModel ) -{ - mrSheetData.setFormControl( rModel ); -} - void WorksheetHelper::setBaseColumnWidth( sal_Int32 nWidth ) { mrSheetData.setBaseColumnWidth( nWidth ); diff --git a/oox/source/xls/worksheetsettings.cxx b/oox/source/xls/worksheetsettings.cxx index 55a168329671..48cc9c3041df 100644 --- a/oox/source/xls/worksheetsettings.cxx +++ b/oox/source/xls/worksheetsettings.cxx @@ -153,7 +153,7 @@ void WorksheetSettings::importOutlinePr( const AttributeList& rAttribs ) void WorksheetSettings::importSheetProtection( const AttributeList& rAttribs ) { - maSheetProt.mnPasswordHash = lclGetCheckedHash( rAttribs.getHex( XML_password, 0 ) ); + maSheetProt.mnPasswordHash = lclGetCheckedHash( rAttribs.getIntegerHex( XML_password, 0 ) ); maSheetProt.mbSheet = rAttribs.getBool( XML_sheet, false ); maSheetProt.mbObjects = rAttribs.getBool( XML_objects, false ); maSheetProt.mbScenarios = rAttribs.getBool( XML_scenarios, false ); @@ -174,7 +174,7 @@ void WorksheetSettings::importSheetProtection( const AttributeList& rAttribs ) void WorksheetSettings::importChartProtection( const AttributeList& rAttribs ) { - maSheetProt.mnPasswordHash = lclGetCheckedHash( rAttribs.getHex( XML_password, 0 ) ); + maSheetProt.mnPasswordHash = lclGetCheckedHash( rAttribs.getIntegerHex( XML_password, 0 ) ); maSheetProt.mbSheet = rAttribs.getBool( XML_content, false ); maSheetProt.mbObjects = rAttribs.getBool( XML_objects, false ); } |