diff options
Diffstat (limited to 'sc/source/filter/inc/externallinkbuffer.hxx')
-rw-r--r-- | sc/source/filter/inc/externallinkbuffer.hxx | 350 |
1 files changed, 350 insertions, 0 deletions
diff --git a/sc/source/filter/inc/externallinkbuffer.hxx b/sc/source/filter/inc/externallinkbuffer.hxx new file mode 100644 index 000000000..374a54b38 --- /dev/null +++ b/sc/source/filter/inc/externallinkbuffer.hxx @@ -0,0 +1,350 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include <ostream> + +#include <com/sun/star/sheet/ExternalLinkInfo.hpp> +#include <oox/helper/containerhelper.hxx> +#include "defnamesbuffer.hxx" +#include "formulabase.hxx" + +namespace com::sun::star { + namespace sheet { struct DDEItemInfo; } + namespace sheet { class XDDELink; } + namespace sheet { class XExternalDocLink; } + namespace sheet { class XExternalSheetCache; } +} + +namespace oox::core { + class Relations; +} + +namespace oox::xls { + +struct ExternalNameModel +{ + bool mbNotify; /// Notify application on data change. + bool mbPreferPic; /// Picture link. + bool mbStdDocName; /// Name is the StdDocumentName for DDE. + bool mbOleObj; /// Name is an OLE object. + bool mbIconified; /// Iconified object link. + + explicit ExternalNameModel(); +}; + +class ExternalLink; + +class ExternalName : public DefinedNameBase +{ +public: + explicit ExternalName( const ExternalLink& rParentLink ); + + /** Appends the passed value to the result set. */ + template< typename Type > + void appendResultValue( const Type& rValue ) + { if( maCurrIt != maResults.end() ) (*maCurrIt++) <<= rValue; } + + /** Imports the definedName element. */ + void importDefinedName( const AttributeList& rAttribs ); + /** Imports the ddeItem element describing an item of a DDE link. */ + void importDdeItem( const AttributeList& rAttribs ); + /** Imports the values element containing the size of the DDE result matrix. */ + void importValues( const AttributeList& rAttribs ); + /** Imports the oleItem element describing an object of an OLE link. */ + void importOleItem( const AttributeList& rAttribs ); + + /** Imports the EXTERNALNAME record containing the name (only). */ + void importExternalName( SequenceInputStream& rStrm ); + /** Imports the EXTERNALNAMEFLAGS record containing the settings of an external name. */ + void importExternalNameFlags( SequenceInputStream& rStrm ); + /** Imports the DDEITEMVALUES record containing the size of the DDE result matrix. */ + void importDdeItemValues( SequenceInputStream& rStrm ); + /** Imports the DDEITEM_BOOL record containing a boolean value in a link result. */ + void importDdeItemBool( SequenceInputStream& rStrm ); + /** Imports the DDEITEM_DOUBLE record containing a double value in a link result. */ + void importDdeItemDouble( SequenceInputStream& rStrm ); + /** Imports the DDEITEM_ERROR record containing an error code in a link result. */ + void importDdeItemError( SequenceInputStream& rStrm ); + /** Imports the DDEITEM_STRING record containing a string in a link result. */ + void importDdeItemString( SequenceInputStream& rStrm ); + + /** Returns the DDE item info needed by the XML formula parser. */ + bool getDdeItemInfo( + css::sheet::DDEItemInfo& orItemInfo ) const; + + /** Returns the complete DDE link data of this DDE item. */ + bool getDdeLinkData( + OUString& orDdeServer, + OUString& orDdeTopic, + OUString& orDdeItem ); + +private: + /** Sets the size of the result matrix. */ + void setResultSize( sal_Int32 nColumns, sal_Int32 nRows ); + +private: + typedef Matrix< css::uno::Any > ResultMatrix; + + const ExternalLink& mrParentLink; /// External link this name belongs to. + ExternalNameModel maExtNameModel; /// Additional name data. + ResultMatrix maResults; /// DDE/OLE link results. + ResultMatrix::iterator maCurrIt; /// Current position in result matrix. + css::uno::Reference< css::sheet::XDDELink > + mxDdeLink; /// Interface of a DDE link. + bool mbDdeLinkCreated; /// True = already tried to create the DDE link. +}; + +typedef std::shared_ptr< ExternalName > ExternalNameRef; + +/** Contains indexes for a range of sheets in the spreadsheet document. */ +class LinkSheetRange +{ +public: + explicit LinkSheetRange() { setDeleted(); } + + /** Sets this struct to deleted state. */ + void setDeleted(); + /** Sets this struct to "use current sheet" state. */ + void setSameSheet(); + /** Sets the passed absolute sheet range to the members of this struct. */ + void setRange( sal_Int32 nFirst, sal_Int32 nLast ); + /** Sets the passed external sheet cache range to the members of this struct. */ + void setExternalRange( sal_Int32 nDocLink, sal_Int32 nFirst, sal_Int32 nLast ); + + /** Returns true, if the sheet indexes are valid and different. */ + bool isDeleted() const { return mnFirst < 0; } + /** Returns true, if the sheet range points to an external document. */ + bool isExternal() const { return !isDeleted() && (meType == LINKSHEETRANGE_EXTERNAL); } + /** Returns true, if the sheet indexes are valid and different. */ + bool isSameSheet() const { return meType == LINKSHEETRANGE_SAMESHEET; } + /** Returns true, if the sheet indexes are valid and different. */ + bool is3dRange() const { return (0 <= mnFirst) && (mnFirst < mnLast); } + + sal_Int32 getDocLinkIndex() const { return mnDocLink; } + sal_Int32 getFirstSheet() const { return mnFirst; } + sal_Int32 getLastSheet() const { return mnLast; } + +private: + enum LinkSheetRangeType + { + LINKSHEETRANGE_INTERNAL, /// Sheet range in the own document. + LINKSHEETRANGE_EXTERNAL, /// Sheet range in an external document. + LINKSHEETRANGE_SAMESHEET /// Current sheet depending on context. + }; + + LinkSheetRangeType meType; /// Link sheet range type. + sal_Int32 mnDocLink; /// Document link token index for external links. + sal_Int32 mnFirst; /// Index of the first sheet or index of first external sheet cache. + sal_Int32 mnLast; /// Index of the last sheet or index of last external sheet cache. +}; + +enum class ExternalLinkType +{ + Self, /// Link refers to the current workbook. + Same, /// Link refers to the current sheet. + External, /// Link refers to an external spreadsheet document. + // let's ignore xlStartup and xlAlternateStartup for now + PathMissing, /// Just for round-tripping (FIXME: Functionality not actually implemented after all.) + Library, /// Link refers to an external add-in. + DDE, /// DDE link. + OLE, /// OLE link. + Unknown /// Unknown or unsupported link type. +}; + +template< typename charT, typename traits > +inline std::basic_ostream<charT, traits> & operator <<( + std::basic_ostream<charT, traits> & stream, const ExternalLinkType& type ) +{ + switch (type) + { + case ExternalLinkType::Self: return stream << "self"; + case ExternalLinkType::Same: return stream << "same"; + case ExternalLinkType::External: return stream << "external"; + case ExternalLinkType::PathMissing: return stream << "pathmissing"; + case ExternalLinkType::Library: return stream << "library"; + case ExternalLinkType::DDE: return stream << "dde"; + case ExternalLinkType::OLE: return stream << "ole"; + case ExternalLinkType::Unknown: return stream << "unknown"; + default: return stream << static_cast<int>(type); + } +} + +class ExternalLink : public WorkbookHelper +{ +public: + explicit ExternalLink( const WorkbookHelper& rHelper ); + + /** Imports the externalReference element containing the relation identifier. */ + void importExternalReference( const AttributeList& rAttribs ); + /** Imports the externalBook element describing an externally linked document. */ + void importExternalBook( const ::oox::core::Relations& rRelations, const AttributeList& rAttribs ); + /** Imports the sheetName element containing the sheet name in an externally linked document. */ + void importSheetName( const AttributeList& rAttribs ); + /** Imports the definedName element describing an external name. */ + void importDefinedName( const AttributeList& rAttribs ); + /** Imports the ddeLink element describing a DDE link. */ + void importDdeLink( const AttributeList& rAttribs ); + /** Imports the ddeItem element describing an item of a DDE link. */ + ExternalNameRef importDdeItem( const AttributeList& rAttribs ); + /** Imports the oleLink element describing an OLE link. */ + void importOleLink( const ::oox::core::Relations& rRelations, const AttributeList& rAttribs ); + /** Imports the oleItem element describing an object of an OLE link. */ + ExternalNameRef importOleItem( const AttributeList& rAttribs ); + + /** Imports the EXTERNALBOOK record describing an externally linked document, DDE link, or OLE link. */ + void importExternalBook( const ::oox::core::Relations& rRelations, SequenceInputStream& rStrm ); + /** Imports the EXTSHEETNAMES record containing the sheet names in an externally linked document. */ + void importExtSheetNames( SequenceInputStream& rStrm ); + /** Imports the EXTERNALNAME record describing an external name. */ + ExternalNameRef importExternalName( SequenceInputStream& rStrm ); + /** Imports the EXTERNALREF record from the passed stream. */ + void importExternalRef( SequenceInputStream& rStrm ); + /** Imports the EXTERNALSELF record from the passed stream. */ + void importExternalSelf( SequenceInputStream& rStrm ); + /** Imports the EXTERNALSAME record from the passed stream. */ + void importExternalSame( SequenceInputStream& rStrm ); + /** Imports the EXTERNALADDIN record from the passed stream. */ + void importExternalAddin( SequenceInputStream& rStrm ); + + /** Sets the link type to 'self reference'. */ + void setSelfLinkType() { meLinkType = ExternalLinkType::Self; } + + /** Returns the type of this external link. */ + ExternalLinkType getLinkType() const { return meLinkType; } + + /** Returns the relation identifier for the external link fragment. */ + const OUString& getRelId() const { return maRelId; } + /** Returns the class name of this external link. */ + const OUString& getClassName() const { return maClassName; } + /** Returns the target URL of this external link. */ + const OUString& getTargetUrl() const { return maTargetUrl; } + /** Returns the link info needed by the XML formula parser. */ + css::sheet::ExternalLinkInfo getLinkInfo() const; + + /** Returns the type of the external library if this is a library link. */ + FunctionLibraryType getFuncLibraryType() const; + + /** Returns the token index of the external document. */ + sal_Int32 getDocumentLinkIndex() const; + /** Returns the external sheet cache index or for the passed sheet. */ + sal_Int32 getSheetCacheIndex( sal_Int32 nTabId ) const; + /** Returns the sheet cache of the external sheet with the passed index. */ + css::uno::Reference< css::sheet::XExternalSheetCache > + getSheetCache( sal_Int32 nTabId ) const; + + /** Returns the internal sheet range or range of external sheet caches for the passed sheet range (BIFF only). */ + void getSheetRange( LinkSheetRange& orSheetRange, sal_Int32 nTabId1, sal_Int32 nTabId2 ) const; + + /** Returns the external name with the passed zero-based index. */ + ExternalNameRef getNameByIndex( sal_Int32 nIndex ) const; + +private: + void setExternalTargetUrl( const OUString& rTargetUrl, const OUString& rTargetType ); + void setDdeOleTargetUrl( const OUString& rClassName, const OUString& rTargetUrl, ExternalLinkType eLinkType ); + void parseExternalReference( const ::oox::core::Relations& rRelations, const OUString& rRelId ); + + /** Creates an external document link and the sheet cache for the passed sheet name. */ + void insertExternalSheet( const OUString& rSheetName ); + + ExternalNameRef createExternalName(); + +private: + ExternalLinkType meLinkType; /// Type of this link object. + FunctionLibraryType meFuncLibType; /// Type of the function library, if link type is ExternalLinkType::Library. + OUString maRelId; /// Relation identifier for the external link fragment. + OUString maClassName; /// DDE service, OLE class name. + OUString maTargetUrl; /// Target link, DDE topic, OLE target. + css::uno::Reference< css::sheet::XExternalDocLink > + mxDocLink; /// Interface for an external document. + std::vector< sal_Int32 > maSheetCaches; /// External sheet cache indexes. + RefVector< ExternalName > maExtNames; /// Defined names in external document. +}; + +typedef std::shared_ptr< ExternalLink > ExternalLinkRef; + +/** Represents a REF entry in the BIFF12 EXTERNALSHEETS or in the BIFF8 + EXTERNSHEET record. + + This struct is used to map ref identifiers to external books (BIFF12: + EXTERNALREF records, BIFF8: EXTERNALBOOK records), and provides sheet + indexes into the sheet list of the external document. + */ +struct RefSheetsModel +{ + sal_Int32 mnExtRefId; /// Zero-based index into list of external documents. + sal_Int32 mnTabId1; /// Zero-based index to first sheet in external document. + sal_Int32 mnTabId2; /// Zero-based index to last sheet in external document. + + explicit RefSheetsModel(); + + void readBiff12Data( SequenceInputStream& rStrm ); +}; + +class ExternalLinkBuffer : public WorkbookHelper +{ +public: + explicit ExternalLinkBuffer( const WorkbookHelper& rHelper ); + + /** Imports the externalReference element containing . */ + ExternalLinkRef importExternalReference( const AttributeList& rAttribs ); + + /** Imports the EXTERNALREF record from the passed stream. */ + ExternalLinkRef importExternalRef( SequenceInputStream& rStrm ); + /** Imports the EXTERNALSELF record from the passed stream. */ + void importExternalSelf( SequenceInputStream& rStrm ); + /** Imports the EXTERNALSAME record from the passed stream. */ + void importExternalSame( SequenceInputStream& rStrm ); + /** Imports the EXTERNALADDIN record from the passed stream. */ + void importExternalAddin( SequenceInputStream& rStrm ); + /** Imports the EXTERNALSHEETS record from the passed stream. */ + void importExternalSheets( SequenceInputStream& rStrm ); + + /** Returns the sequence of link infos needed by the XML formula parser. */ + css::uno::Sequence< css::sheet::ExternalLinkInfo > + getLinkInfos() const; + + /** Returns the external link for the passed reference identifier. */ + ExternalLinkRef getExternalLink( sal_Int32 nRefId, bool bUseRefSheets = true ) const; + + /** Returns the sheet range for the specified reference (BIFF8 only). */ + LinkSheetRange getSheetRange( sal_Int32 nRefId ) const; + +private: + /** Creates a new external link and inserts it into the list of links. */ + ExternalLinkRef createExternalLink(); + + /** Returns the specified sheet indexes for a reference identifier. */ + const RefSheetsModel* getRefSheets( sal_Int32 nRefId ) const; + +private: + typedef RefVector< ExternalLink > ExternalLinkVec; + typedef ::std::vector< RefSheetsModel > RefSheetsModelVec; + + ExternalLinkRef mxSelfRef; /// Implicit self reference at index 0. + ExternalLinkVec maLinks; /// List of link structures for all kinds of links. + ExternalLinkVec maExtLinks; /// Real external links needed for formula parser. + RefSheetsModelVec maRefSheets; /// Sheet indexes for reference ids. + bool mbUseRefSheets; /// True = use maRefSheets list (BIFF12 only). +}; + +} // namespace oox::xls + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |