LCOV - code coverage report
Current view: top level - sc/source/filter/oox - externallinkbuffer.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 70 373 18.8 %
Date: 2015-06-13 12:38:46 Functions: 16 65 24.6 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include "externallinkbuffer.hxx"
      21             : 
      22             : #include <com/sun/star/sheet/ComplexReference.hpp>
      23             : #include <com/sun/star/sheet/DDELinkInfo.hpp>
      24             : #include <com/sun/star/sheet/ExternalLinkType.hpp>
      25             : #include <com/sun/star/sheet/ExternalReference.hpp>
      26             : #include <com/sun/star/sheet/ReferenceFlags.hpp>
      27             : #include <com/sun/star/sheet/SingleReference.hpp>
      28             : #include <com/sun/star/sheet/XDDELinks.hpp>
      29             : #include <com/sun/star/sheet/XDDELink.hpp>
      30             : #include <com/sun/star/sheet/XDDELinkResults.hpp>
      31             : #include <com/sun/star/sheet/XExternalDocLink.hpp>
      32             : #include <com/sun/star/sheet/XExternalDocLinks.hpp>
      33             : #include <osl/diagnose.h>
      34             : #include <rtl/strbuf.hxx>
      35             : #include <oox/core/filterbase.hxx>
      36             : #include <oox/helper/attributelist.hxx>
      37             : #include <oox/token/properties.hxx>
      38             : #include "addressconverter.hxx"
      39             : #include "biffinputstream.hxx"
      40             : #include "excelhandlers.hxx"
      41             : #include "formulaparser.hxx"
      42             : #include "worksheetbuffer.hxx"
      43             : 
      44             : namespace oox {
      45             : namespace xls {
      46             : 
      47             : using namespace ::com::sun::star::sheet;
      48             : using namespace ::com::sun::star::table;
      49             : using namespace ::com::sun::star::uno;
      50             : 
      51             : using ::oox::core::Relation;
      52             : using ::oox::core::Relations;
      53             : 
      54             : namespace {
      55             : 
      56             : const sal_uInt16 BIFF12_EXTERNALBOOK_BOOK   = 0;
      57             : const sal_uInt16 BIFF12_EXTERNALBOOK_DDE    = 1;
      58             : const sal_uInt16 BIFF12_EXTERNALBOOK_OLE    = 2;
      59             : 
      60             : const sal_uInt16 BIFF12_EXTNAME_AUTOMATIC   = 0x0002;
      61             : const sal_uInt16 BIFF12_EXTNAME_PREFERPIC   = 0x0004;
      62             : const sal_uInt16 BIFF12_EXTNAME_STDDOCNAME  = 0x0008;
      63             : const sal_uInt16 BIFF12_EXTNAME_OLEOBJECT   = 0x0010;
      64             : const sal_uInt16 BIFF12_EXTNAME_ICONIFIED   = 0x0020;
      65             : 
      66             : } // namespace
      67             : 
      68           0 : ExternalNameModel::ExternalNameModel() :
      69             :     mbBuiltIn( false ),
      70             :     mbNotify( false ),
      71             :     mbPreferPic( false ),
      72             :     mbStdDocName( false ),
      73             :     mbOleObj( false ),
      74           0 :     mbIconified( false )
      75             : {
      76           0 : }
      77             : 
      78           0 : ExternalName::ExternalName( const ExternalLink& rParentLink ) :
      79             :     DefinedNameBase( rParentLink ),
      80             :     mrParentLink( rParentLink ),
      81           0 :     mbDdeLinkCreated( false )
      82             : {
      83           0 : }
      84             : 
      85           0 : void ExternalName::importDefinedName( const AttributeList& rAttribs )
      86             : {
      87           0 :     maModel.maName = rAttribs.getXString( XML_name, OUString() );
      88             :     OSL_ENSURE( !maModel.maName.isEmpty(), "ExternalName::importDefinedName - empty name" );
      89             :     // zero-based index into sheet list of externalBook
      90           0 :     maModel.mnSheet = rAttribs.getInteger( XML_sheetId, -1 );
      91           0 : }
      92             : 
      93           0 : void ExternalName::importDdeItem( const AttributeList& rAttribs )
      94             : {
      95           0 :     maModel.maName = rAttribs.getXString( XML_name, OUString() );
      96             :     OSL_ENSURE( !maModel.maName.isEmpty(), "ExternalName::importDdeItem - empty name" );
      97           0 :     maExtNameModel.mbOleObj     = false;
      98           0 :     maExtNameModel.mbStdDocName = rAttribs.getBool( XML_ole, false );
      99           0 :     maExtNameModel.mbNotify     = rAttribs.getBool( XML_advise, false );
     100           0 :     maExtNameModel.mbPreferPic  = rAttribs.getBool( XML_preferPic, false );
     101           0 : }
     102             : 
     103           0 : void ExternalName::importValues( const AttributeList& rAttribs )
     104             : {
     105           0 :     setResultSize( rAttribs.getInteger( XML_cols, 1 ), rAttribs.getInteger( XML_rows, 1 ) );
     106           0 : }
     107             : 
     108           0 : void ExternalName::importOleItem( const AttributeList& rAttribs )
     109             : {
     110           0 :     maModel.maName = rAttribs.getXString( XML_name, OUString() );
     111             :     OSL_ENSURE( !maModel.maName.isEmpty(), "ExternalName::importOleItem - empty name" );
     112           0 :     maExtNameModel.mbOleObj    = true;
     113           0 :     maExtNameModel.mbNotify    = rAttribs.getBool( XML_advise, false );
     114           0 :     maExtNameModel.mbPreferPic = rAttribs.getBool( XML_preferPic, false );
     115           0 :     maExtNameModel.mbIconified = rAttribs.getBool( XML_icon, false );
     116           0 : }
     117             : 
     118           0 : void ExternalName::importExternalName( SequenceInputStream& rStrm )
     119             : {
     120           0 :     rStrm >> maModel.maName;
     121             :     OSL_ENSURE( !maModel.maName.isEmpty(), "ExternalName::importExternalName - empty name" );
     122           0 : }
     123             : 
     124           0 : void ExternalName::importExternalNameFlags( SequenceInputStream& rStrm )
     125             : {
     126             :     sal_uInt16 nFlags;
     127             :     sal_Int32 nSheetId;
     128           0 :     nFlags = rStrm.readuInt16();
     129           0 :     nSheetId = rStrm.readInt32();
     130             :     // index into sheet list of EXTSHEETNAMES (one-based in BIFF12)
     131           0 :     maModel.mnSheet = nSheetId - 1;
     132             :     // no flag for built-in names, as in OOXML...
     133           0 :     maExtNameModel.mbNotify     = getFlag( nFlags, BIFF12_EXTNAME_AUTOMATIC );
     134           0 :     maExtNameModel.mbPreferPic  = getFlag( nFlags, BIFF12_EXTNAME_PREFERPIC );
     135           0 :     maExtNameModel.mbStdDocName = getFlag( nFlags, BIFF12_EXTNAME_STDDOCNAME );
     136           0 :     maExtNameModel.mbOleObj     = getFlag( nFlags, BIFF12_EXTNAME_OLEOBJECT );
     137           0 :     maExtNameModel.mbIconified  = getFlag( nFlags, BIFF12_EXTNAME_ICONIFIED );
     138             :     OSL_ENSURE( (mrParentLink.getLinkType() == LINKTYPE_OLE) == maExtNameModel.mbOleObj,
     139             :         "ExternalName::importExternalNameFlags - wrong OLE flag in external name" );
     140           0 : }
     141             : 
     142           0 : void ExternalName::importDdeItemValues( SequenceInputStream& rStrm )
     143             : {
     144             :     sal_Int32 nRows, nCols;
     145           0 :     nRows = rStrm.readInt32();
     146           0 :     nCols = rStrm.readInt32();
     147           0 :     setResultSize( nCols, nRows );
     148           0 : }
     149             : 
     150           0 : void ExternalName::importDdeItemBool( SequenceInputStream& rStrm )
     151             : {
     152           0 :     appendResultValue< double >( (rStrm.readuInt8() == 0) ? 0.0 : 1.0 );
     153           0 : }
     154             : 
     155           0 : void ExternalName::importDdeItemDouble( SequenceInputStream& rStrm )
     156             : {
     157           0 :     appendResultValue( rStrm.readDouble() );
     158           0 : }
     159             : 
     160           0 : void ExternalName::importDdeItemError( SequenceInputStream& rStrm )
     161             : {
     162           0 :     appendResultValue( BiffHelper::calcDoubleFromError( rStrm.readuInt8() ) );
     163           0 : }
     164             : 
     165           0 : void ExternalName::importDdeItemString( SequenceInputStream& rStrm )
     166             : {
     167           0 :     appendResultValue( BiffHelper::readString( rStrm ) );
     168           0 : }
     169             : 
     170             : #if 0
     171             : sal_Int32 ExternalName::getSheetCacheIndex() const
     172             : {
     173             :     OSL_ENSURE( mrParentLink.getLinkType() == LINKTYPE_DDE, "ExternalName::getSheetCacheIndex - unexpected link type" );
     174             :     sal_Int32 nCacheIdx = -1;
     175             :     switch( getFilterType() )
     176             :     {
     177             :         case FILTER_OOXML:
     178             :             // OOXML/BIFF12: zero-based index into sheet list, -1 means global name
     179             :             if( maModel.mnSheet >= 0 )
     180             :                 nCacheIdx = mrParentLink.getSheetIndex( maModel.mnSheet );
     181             :         break;
     182             :         case FILTER_BIFF:
     183             :             switch( getBiff() )
     184             :             {
     185             :                 case BIFF2:
     186             :                 case BIFF3:
     187             :                 case BIFF4:
     188             :                 break;
     189             :                 case BIFF5:
     190             :                     if( maModel.mnSheet > 0 )
     191             :                         if( const ExternalLink* pExtLink = getExternalLinks().getExternalLink( maModel.mnSheet ).get() )
     192             :                             if( pExtLink->getLinkType() == LINKTYPE_EXTERNAL )
     193             :                                 nCacheIdx = pExtLink->getSheetIndex();
     194             :                 break;
     195             :                 case BIFF8:
     196             :                     if( maModel.mnSheet > 0 )
     197             :                         nCacheIdx = mrParentLink.getSheetIndex( maModel.mnSheet - 1 );
     198             :                 break;
     199             :                 case BIFF_UNKNOWN:
     200             :                 break;
     201             :             }
     202             :         break;
     203             :         case FILTER_UNKNOWN:
     204             :         break;
     205             :     }
     206             :     return nCacheIdx;
     207             : }
     208             : #endif
     209             : 
     210           0 : bool ExternalName::getDdeItemInfo( DDEItemInfo& orItemInfo ) const
     211             : {
     212           0 :     if( (mrParentLink.getLinkType() == LINKTYPE_DDE) && !maModel.maName.isEmpty() )
     213             :     {
     214           0 :         orItemInfo.Item = maModel.maName;
     215           0 :         orItemInfo.Results = ContainerHelper::matrixToSequenceSequence( maResults );
     216           0 :         return true;
     217             :     }
     218           0 :     return false;
     219             : }
     220             : 
     221           0 : bool ExternalName::getDdeLinkData( OUString& orDdeServer, OUString& orDdeTopic, OUString& orDdeItem )
     222             : {
     223           0 :     if( (mrParentLink.getLinkType() == LINKTYPE_DDE) && !maModel.maName.isEmpty() )
     224             :     {
     225             :         // try to create a DDE link and to set the imported link results
     226           0 :         if( !mbDdeLinkCreated ) try
     227             :         {
     228           0 :             PropertySet aDocProps( getDocument() );
     229           0 :             Reference< XDDELinks > xDdeLinks( aDocProps.getAnyProperty( PROP_DDELinks ), UNO_QUERY_THROW );
     230           0 :             mxDdeLink = xDdeLinks->addDDELink( mrParentLink.getClassName(), mrParentLink.getTargetUrl(), maModel.maName, ::com::sun::star::sheet::DDELinkMode_DEFAULT );
     231           0 :             mbDdeLinkCreated = true;    // ignore if setting results fails
     232           0 :             if( !maResults.empty() )
     233             :             {
     234           0 :                 Reference< XDDELinkResults > xResults( mxDdeLink, UNO_QUERY_THROW );
     235           0 :                 xResults->setResults( ContainerHelper::matrixToSequenceSequence( maResults ) );
     236           0 :             }
     237             :         }
     238           0 :         catch( Exception& )
     239             :         {
     240             :             OSL_FAIL( "ExternalName::getDdeLinkData - cannot create DDE link" );
     241             :         }
     242             :         // get link data from created DDE link
     243           0 :         if( mxDdeLink.is() )
     244             :         {
     245           0 :             orDdeServer = mxDdeLink->getApplication();
     246           0 :             orDdeTopic = mxDdeLink->getTopic();
     247           0 :             orDdeItem = mxDdeLink->getItem();
     248           0 :             return true;
     249             :         }
     250             :     }
     251           0 :     return false;
     252             : }
     253             : 
     254             : // private --------------------------------------------------------------------
     255             : 
     256           0 : void ExternalName::setResultSize( sal_Int32 nColumns, sal_Int32 nRows )
     257             : {
     258             :     OSL_ENSURE( (mrParentLink.getLinkType() == LINKTYPE_DDE) || (mrParentLink.getLinkType() == LINKTYPE_OLE) ||
     259             :         (mrParentLink.getLinkType() == LINKTYPE_MAYBE_DDE_OLE), "ExternalName::setResultSize - wrong link type" );
     260             :     OSL_ENSURE( (nRows > 0) && (nColumns > 0), "ExternalName::setResultSize - invalid matrix size" );
     261           0 :     const CellAddress& rMaxPos = getAddressConverter().getMaxApiAddress();
     262           0 :     if( (0 < nRows) && (nRows <= rMaxPos.Row + 1) && (0 < nColumns) && (nColumns <= rMaxPos.Column + 1) )
     263           0 :         maResults.resize( static_cast< size_t >( nColumns ), static_cast< size_t >( nRows ), Any( BiffHelper::calcDoubleFromError( BIFF_ERR_NA ) ) );
     264             :     else
     265           0 :         maResults.clear();
     266           0 :     maCurrIt = maResults.begin();
     267           0 : }
     268             : 
     269           0 : void LinkSheetRange::setDeleted()
     270             : {
     271           0 :     meType = LINKSHEETRANGE_INTERNAL;
     272           0 :     mnDocLink = mnFirst = mnLast = -1;
     273           0 : }
     274             : 
     275           0 : void LinkSheetRange::setSameSheet()
     276             : {
     277           0 :     meType = LINKSHEETRANGE_SAMESHEET;
     278           0 :     mnDocLink = -1;
     279           0 :     mnFirst = mnLast = 0;
     280           0 : }
     281             : 
     282           0 : void LinkSheetRange::setRange( sal_Int32 nFirst, sal_Int32 nLast )
     283             : {
     284           0 :     meType = LINKSHEETRANGE_INTERNAL;
     285           0 :     mnDocLink = -1;
     286           0 :     mnFirst = ::std::min( nFirst, nLast );
     287           0 :     mnLast = ::std::max( nFirst, nLast );
     288           0 : }
     289             : 
     290           0 : void LinkSheetRange::setExternalRange( sal_Int32 nDocLink, sal_Int32 nFirst, sal_Int32 nLast )
     291             : {
     292           0 :     if( nDocLink < 0 )
     293             :     {
     294           0 :         setDeleted();
     295             :     }
     296             :     else
     297             :     {
     298           0 :         meType = LINKSHEETRANGE_EXTERNAL;
     299           0 :         mnDocLink = nDocLink;
     300           0 :         mnFirst = ::std::min( nFirst, nLast );
     301           0 :         mnLast = ::std::max( nFirst, nLast );
     302             :     }
     303           0 : }
     304             : 
     305         146 : ExternalLink::ExternalLink( const WorkbookHelper& rHelper ) :
     306             :     WorkbookHelper( rHelper ),
     307             :     meLinkType( LINKTYPE_UNKNOWN ),
     308         146 :     meFuncLibType( FUNCLIB_UNKNOWN )
     309             : {
     310         146 : }
     311             : 
     312           1 : void ExternalLink::importExternalReference( const AttributeList& rAttribs )
     313             : {
     314           1 :     maRelId = rAttribs.getString( R_TOKEN( id ), OUString() );
     315           1 : }
     316             : 
     317           1 : void ExternalLink::importExternalBook( const Relations& rRelations, const AttributeList& rAttribs )
     318             : {
     319           1 :     parseExternalReference( rRelations, rAttribs.getString( R_TOKEN( id ), OUString() ) );
     320           1 : }
     321             : 
     322           3 : void ExternalLink::importSheetName( const AttributeList& rAttribs )
     323             : {
     324           3 :     insertExternalSheet( rAttribs.getXString( XML_val, OUString() ) );
     325           3 : }
     326             : 
     327           0 : void ExternalLink::importDefinedName( const AttributeList& rAttribs )
     328             : {
     329           0 :     createExternalName()->importDefinedName( rAttribs );
     330           0 : }
     331             : 
     332           0 : void ExternalLink::importDdeLink( const AttributeList& rAttribs )
     333             : {
     334           0 :     OUString aDdeService = rAttribs.getXString( XML_ddeService, OUString() );
     335           0 :     OUString aDdeTopic = rAttribs.getXString( XML_ddeTopic, OUString() );
     336           0 :     setDdeOleTargetUrl( aDdeService, aDdeTopic, LINKTYPE_DDE );
     337           0 : }
     338             : 
     339           0 : ExternalNameRef ExternalLink::importDdeItem( const AttributeList& rAttribs )
     340             : {
     341           0 :     ExternalNameRef xExtName = createExternalName();
     342           0 :     xExtName->importDdeItem( rAttribs );
     343           0 :     return xExtName;
     344             : }
     345             : 
     346           0 : void ExternalLink::importOleLink( const Relations& rRelations, const AttributeList& rAttribs )
     347             : {
     348           0 :     OUString aProgId = rAttribs.getXString( XML_progId, OUString() );
     349           0 :     OUString aTargetUrl = rRelations.getExternalTargetFromRelId( rAttribs.getString( R_TOKEN( id ), OUString() ) );
     350           0 :     setDdeOleTargetUrl( aProgId, aTargetUrl, LINKTYPE_OLE );
     351           0 : }
     352             : 
     353           0 : ExternalNameRef ExternalLink::importOleItem( const AttributeList& rAttribs )
     354             : {
     355           0 :     ExternalNameRef xExtName = createExternalName();
     356           0 :     xExtName->importOleItem( rAttribs );
     357           0 :     return xExtName;
     358             : }
     359             : 
     360           0 : void ExternalLink::importExternalRef( SequenceInputStream& rStrm )
     361             : {
     362           0 :     rStrm >> maRelId;
     363           0 : }
     364             : 
     365           0 : void ExternalLink::importExternalSelf( SequenceInputStream& )
     366             : {
     367           0 :     meLinkType = LINKTYPE_SELF;
     368           0 : }
     369             : 
     370           0 : void ExternalLink::importExternalSame( SequenceInputStream& )
     371             : {
     372           0 :     meLinkType = LINKTYPE_SAME;
     373           0 : }
     374             : 
     375           0 : void ExternalLink::importExternalAddin( SequenceInputStream& )
     376             : {
     377           0 :     meLinkType = LINKTYPE_UNKNOWN;
     378           0 : }
     379             : 
     380           0 : void ExternalLink::importExternalBook( const Relations& rRelations, SequenceInputStream& rStrm )
     381             : {
     382           0 :     switch( rStrm.readuInt16() )
     383             :     {
     384             :         case BIFF12_EXTERNALBOOK_BOOK:
     385           0 :             parseExternalReference( rRelations, BiffHelper::readString( rStrm ) );
     386           0 :         break;
     387             :         case BIFF12_EXTERNALBOOK_DDE:
     388             :         {
     389           0 :             OUString aDdeService, aDdeTopic;
     390           0 :             rStrm >> aDdeService >> aDdeTopic;
     391           0 :             setDdeOleTargetUrl( aDdeService, aDdeTopic, LINKTYPE_DDE );
     392             :         }
     393           0 :         break;
     394             :         case BIFF12_EXTERNALBOOK_OLE:
     395             :         {
     396           0 :             OUString aTargetUrl = rRelations.getExternalTargetFromRelId( BiffHelper::readString( rStrm ) );
     397           0 :             OUString aProgId = BiffHelper::readString( rStrm );
     398           0 :             setDdeOleTargetUrl( aProgId, aTargetUrl, LINKTYPE_OLE );
     399             :         }
     400           0 :         break;
     401             :         default:
     402             :             OSL_FAIL( "ExternalLink::importExternalBook - unknown link type" );
     403             :     }
     404           0 : }
     405             : 
     406           0 : void ExternalLink::importExtSheetNames( SequenceInputStream& rStrm )
     407             : {
     408             :     // load external sheet names and create the sheet caches in the Calc document
     409             :     OSL_ENSURE( (meLinkType == LINKTYPE_EXTERNAL) || (meLinkType == LINKTYPE_LIBRARY),
     410             :         "ExternalLink::importExtSheetNames - invalid link type" );
     411           0 :     if( meLinkType == LINKTYPE_EXTERNAL )   // ignore sheets of external libraries
     412           0 :         for( sal_Int32 nSheet = 0, nCount = rStrm.readInt32(); !rStrm.isEof() && (nSheet < nCount); ++nSheet )
     413           0 :             insertExternalSheet( BiffHelper::readString( rStrm ) );
     414           0 : }
     415             : 
     416           0 : ExternalNameRef ExternalLink::importExternalName( SequenceInputStream& rStrm )
     417             : {
     418           0 :     ExternalNameRef xExtName = createExternalName();
     419           0 :     xExtName->importExternalName( rStrm );
     420           0 :     return xExtName;
     421             : }
     422             : 
     423         344 : ExternalLinkInfo ExternalLink::getLinkInfo() const
     424             : {
     425         344 :     ExternalLinkInfo aLinkInfo;
     426         344 :     switch( meLinkType )
     427             :     {
     428             :         case LINKTYPE_SELF:
     429             :         case LINKTYPE_SAME:
     430             :         case LINKTYPE_INTERNAL:
     431         341 :             aLinkInfo.Type = ::com::sun::star::sheet::ExternalLinkType::SELF;
     432         341 :         break;
     433             :         case LINKTYPE_EXTERNAL:
     434           3 :             aLinkInfo.Type = ::com::sun::star::sheet::ExternalLinkType::DOCUMENT;
     435           3 :             aLinkInfo.Data <<= maTargetUrl;
     436           3 :         break;
     437             :         case LINKTYPE_LIBRARY:
     438             :             // parser will return library function names in OPCODE_BAD string tokens
     439           0 :             aLinkInfo.Type = ::com::sun::star::sheet::ExternalLinkType::SPECIAL;
     440           0 :         break;
     441             :         case LINKTYPE_DDE:
     442             :         {
     443           0 :             aLinkInfo.Type = ::com::sun::star::sheet::ExternalLinkType::DDE;
     444           0 :             DDELinkInfo aDdeLinkInfo;
     445           0 :             aDdeLinkInfo.Service = maClassName;
     446           0 :             aDdeLinkInfo.Topic = maTargetUrl;
     447           0 :             ::std::vector< DDEItemInfo > aItemInfos;
     448           0 :             DDEItemInfo aItemInfo;
     449           0 :             for( ExternalNameVector::const_iterator aIt = maExtNames.begin(), aEnd = maExtNames.end(); aIt != aEnd; ++aIt )
     450           0 :                 if( (*aIt)->getDdeItemInfo( aItemInfo ) )
     451           0 :                     aItemInfos.push_back( aItemInfo );
     452           0 :             aDdeLinkInfo.Items = ContainerHelper::vectorToSequence( aItemInfos );
     453           0 :             aLinkInfo.Data <<= aDdeLinkInfo;
     454             :         }
     455           0 :         break;
     456             :         default:
     457           0 :             aLinkInfo.Type = ::com::sun::star::sheet::ExternalLinkType::UNKNOWN;
     458             :     }
     459         344 :     return aLinkInfo;
     460             : }
     461             : 
     462           0 : FunctionLibraryType ExternalLink::getFuncLibraryType() const
     463             : {
     464           0 :     return (meLinkType == LINKTYPE_LIBRARY) ? meFuncLibType : FUNCLIB_UNKNOWN;
     465             : }
     466             : 
     467           0 : sal_Int32 ExternalLink::getDocumentLinkIndex() const
     468             : {
     469             :     OSL_ENSURE( meLinkType == LINKTYPE_EXTERNAL, "ExternalLink::getDocumentLinkIndex - invalid link type" );
     470           0 :     return mxDocLink.is() ? mxDocLink->getTokenIndex() : -1;
     471             : }
     472             : 
     473           3 : sal_Int32 ExternalLink::getSheetCacheIndex( sal_Int32 nTabId ) const
     474             : {
     475             :     OSL_ENSURE( meLinkType == LINKTYPE_EXTERNAL, "ExternalLink::getSheetCacheIndex - invalid link type" );
     476             :     OSL_ENSURE( (nTabId == 0) || (getFilterType() == FILTER_OOXML) || (getBiff() == BIFF8),
     477             :         "ExternalLink::getSheetCacheIndex - invalid sheet index" );
     478           3 :     return ContainerHelper::getVectorElement( maSheetCaches, nTabId, -1 );
     479             : }
     480             : 
     481           3 : Reference< XExternalSheetCache > ExternalLink::getSheetCache( sal_Int32 nTabId ) const
     482             : {
     483           3 :     sal_Int32 nCacheIdx = getSheetCacheIndex( nTabId );
     484           3 :     if( mxDocLink.is() && (nCacheIdx >= 0) ) try
     485             :     {
     486             :         // existing mxDocLink implies that this is an external link
     487           3 :         Reference< XExternalSheetCache > xSheetCache( mxDocLink->getByIndex( nCacheIdx ), UNO_QUERY_THROW );
     488           3 :         return xSheetCache;
     489             :     }
     490           0 :     catch( Exception& )
     491             :     {
     492             :     }
     493           0 :     return 0;
     494             : }
     495             : 
     496           0 : void ExternalLink::getSheetRange( LinkSheetRange& orSheetRange, sal_Int32 nTabId1, sal_Int32 nTabId2 ) const
     497             : {
     498           0 :     switch( meLinkType )
     499             :     {
     500             :         case LINKTYPE_SAME:
     501           0 :             orSheetRange.setSameSheet();
     502           0 :         break;
     503             : 
     504             :         case LINKTYPE_SELF:
     505             :         case LINKTYPE_INTERNAL:
     506           0 :             orSheetRange.setRange( nTabId1, nTabId2 );
     507           0 :         break;
     508             : 
     509             :         case LINKTYPE_EXTERNAL:
     510             :         {
     511           0 :             sal_Int32 nDocLinkIdx = getDocumentLinkIndex();
     512           0 :             switch( getFilterType() )
     513             :             {
     514             :                 case FILTER_OOXML:
     515             :                     // BIFF12: passed indexes point into sheet list of EXTSHEETLIST
     516           0 :                     orSheetRange.setExternalRange( nDocLinkIdx, getSheetCacheIndex( nTabId1 ), getSheetCacheIndex( nTabId2 ) );
     517           0 :                 break;
     518             :                 case FILTER_BIFF:
     519           0 :                     switch( getBiff() )
     520             :                     {
     521             :                         case BIFF2:
     522             :                         case BIFF3:
     523             :                         case BIFF4:
     524           0 :                             orSheetRange.setExternalRange( nDocLinkIdx, getSheetCacheIndex( nTabId1 ), getSheetCacheIndex( nTabId2 ) );
     525           0 :                         break;
     526             :                         case BIFF5:
     527             :                             // BIFF5: first sheet from this external link, last sheet is passed in nTabId2
     528           0 :                             if( const ExternalLink* pExtLink2 = getExternalLinks().getExternalLink( nTabId2 ).get() )
     529           0 :                                 if( (pExtLink2->getLinkType() == LINKTYPE_EXTERNAL) && (maTargetUrl == pExtLink2->getTargetUrl()) )
     530           0 :                                     orSheetRange.setExternalRange( nDocLinkIdx, getSheetCacheIndex(), pExtLink2->getSheetCacheIndex() );
     531           0 :                         break;
     532             :                         case BIFF8:
     533             :                             // BIFF8: passed indexes point into sheet list of EXTERNALBOOK
     534           0 :                             orSheetRange.setExternalRange( nDocLinkIdx, getSheetCacheIndex( nTabId1 ), getSheetCacheIndex( nTabId2 ) );
     535           0 :                         break;
     536           0 :                         case BIFF_UNKNOWN: break;
     537             :                     }
     538           0 :                 break;
     539           0 :                 case FILTER_UNKNOWN: break;
     540             :             }
     541             :         }
     542           0 :         break;
     543             : 
     544             :         default:
     545             :             // unsupported/unexpected link type: #REF! error
     546           0 :             orSheetRange.setDeleted();
     547             :     }
     548           0 : }
     549             : 
     550           0 : ExternalNameRef ExternalLink::getNameByIndex( sal_Int32 nIndex ) const
     551             : {
     552           0 :     return maExtNames.get( nIndex );
     553             : }
     554             : 
     555             : // private --------------------------------------------------------------------
     556             : 
     557           1 : void ExternalLink::setExternalTargetUrl( const OUString& rTargetUrl, const OUString& rTargetType )
     558             : {
     559           1 :     meLinkType = LINKTYPE_UNKNOWN;
     560           1 :     if( rTargetType == CREATE_OFFICEDOC_RELATION_TYPE( "externalLinkPath" ) ||
     561           0 :             rTargetType == CREATE_OFFICEDOC_RELATION_TYPE_STRICT( "externalLinkPath" ) )
     562             :     {
     563           1 :         maTargetUrl = getBaseFilter().getAbsoluteUrl( rTargetUrl );
     564           1 :         if( !maTargetUrl.isEmpty() )
     565           1 :             meLinkType = LINKTYPE_EXTERNAL;
     566             :     }
     567           0 :     else if( rTargetType == CREATE_MSOFFICE_RELATION_TYPE( "xlExternalLinkPath/xlLibrary" ) )
     568             :     {
     569           0 :         meLinkType = LINKTYPE_LIBRARY;
     570           0 :         meFuncLibType = FunctionProvider::getFuncLibTypeFromLibraryName( rTargetUrl );
     571             :     }
     572             :     OSL_ENSURE( meLinkType != LINKTYPE_UNKNOWN, "ExternalLink::setExternalTargetUrl - empty target URL or unknown target type" );
     573             : 
     574             :     // create the external document link API object that will contain the sheet caches
     575           1 :     if( meLinkType == LINKTYPE_EXTERNAL ) try
     576             :     {
     577           1 :         PropertySet aDocProps( getDocument() );
     578           2 :         Reference< XExternalDocLinks > xDocLinks( aDocProps.getAnyProperty( PROP_ExternalDocLinks ), UNO_QUERY_THROW );
     579           2 :         mxDocLink = xDocLinks->addDocLink( maTargetUrl );
     580             :     }
     581           0 :     catch( Exception& )
     582             :     {
     583             :     }
     584           1 : }
     585             : 
     586           0 : void ExternalLink::setDdeOleTargetUrl( const OUString& rClassName, const OUString& rTargetUrl, ExternalLinkType eLinkType )
     587             : {
     588           0 :     maClassName = rClassName;
     589           0 :     maTargetUrl = rTargetUrl;
     590           0 :     meLinkType = (maClassName.isEmpty() || maTargetUrl.isEmpty()) ?  LINKTYPE_UNKNOWN : eLinkType;
     591             :     OSL_ENSURE( meLinkType == eLinkType, "ExternalLink::setDdeOleTargetUrl - missing classname or target" );
     592           0 : }
     593             : 
     594           1 : void ExternalLink::parseExternalReference( const Relations& rRelations, const OUString& rRelId )
     595             : {
     596           1 :     if( const Relation* pRelation = rRelations.getRelationFromRelId( rRelId ) )
     597           1 :         setExternalTargetUrl( pRelation->maTarget, pRelation->maType );
     598           1 : }
     599             : 
     600           3 : void ExternalLink::insertExternalSheet( const OUString& rSheetName )
     601             : {
     602             :     OSL_ENSURE( !rSheetName.isEmpty(), "ExternalLink::insertExternalSheet - empty sheet name" );
     603           3 :     if( mxDocLink.is() )
     604             :     {
     605           3 :         Reference< XExternalSheetCache > xSheetCache = mxDocLink->addSheetCache( rSheetName, false );
     606           3 :         sal_Int32 nCacheIdx = xSheetCache.is() ? xSheetCache->getTokenIndex() : -1;
     607           3 :         maSheetCaches.push_back( nCacheIdx );
     608             :     }
     609           3 : }
     610             : 
     611           0 : ExternalNameRef ExternalLink::createExternalName()
     612             : {
     613           0 :     ExternalNameRef xExtName( new ExternalName( *this ) );
     614           0 :     maExtNames.push_back( xExtName );
     615           0 :     return xExtName;
     616             : }
     617             : 
     618           0 : RefSheetsModel::RefSheetsModel() :
     619             :     mnExtRefId( -1 ),
     620             :     mnTabId1( -1 ),
     621           0 :     mnTabId2( -1 )
     622             : {
     623           0 : }
     624             : 
     625           0 : void RefSheetsModel::readBiff12Data( SequenceInputStream& rStrm )
     626             : {
     627           0 :     mnExtRefId = rStrm.readInt32();
     628           0 :     mnTabId1 = rStrm.readInt32();
     629           0 :     mnTabId2 = rStrm.readInt32();
     630           0 : }
     631             : 
     632         145 : ExternalLinkBuffer::ExternalLinkBuffer( const WorkbookHelper& rHelper ) :
     633             :     WorkbookHelper( rHelper ),
     634         145 :     mxSelfRef( new ExternalLink( rHelper ) ),
     635         290 :     mbUseRefSheets( false )
     636             : {
     637         145 :     mxSelfRef->setSelfLinkType();
     638         145 : }
     639             : 
     640           1 : ExternalLinkRef ExternalLinkBuffer::importExternalReference( const AttributeList& rAttribs )
     641             : {
     642           1 :     ExternalLinkRef xExtLink = createExternalLink();
     643           1 :     xExtLink->importExternalReference( rAttribs );
     644           1 :     maExtLinks.push_back( xExtLink );
     645           1 :     return xExtLink;
     646             : }
     647             : 
     648           0 : ExternalLinkRef ExternalLinkBuffer::importExternalRef( SequenceInputStream& rStrm )
     649             : {
     650           0 :     mbUseRefSheets = true;
     651           0 :     ExternalLinkRef xExtLink = createExternalLink();
     652           0 :     xExtLink->importExternalRef( rStrm );
     653           0 :     maExtLinks.push_back( xExtLink );
     654           0 :     return xExtLink;
     655             : }
     656             : 
     657           0 : void ExternalLinkBuffer::importExternalSelf( SequenceInputStream& rStrm )
     658             : {
     659           0 :     mbUseRefSheets = true;
     660           0 :     createExternalLink()->importExternalSelf( rStrm );
     661           0 : }
     662             : 
     663           0 : void ExternalLinkBuffer::importExternalSame( SequenceInputStream& rStrm )
     664             : {
     665           0 :     mbUseRefSheets = true;
     666           0 :     createExternalLink()->importExternalSame( rStrm );
     667           0 : }
     668             : 
     669           0 : void ExternalLinkBuffer::importExternalAddin( SequenceInputStream& rStrm )
     670             : {
     671           0 :     mbUseRefSheets = true;
     672           0 :     createExternalLink()->importExternalAddin( rStrm );
     673           0 : }
     674             : 
     675           0 : void ExternalLinkBuffer::importExternalSheets( SequenceInputStream& rStrm )
     676             : {
     677             :     OSL_ENSURE( mbUseRefSheets, "ExternalLinkBuffer::importExternalSheets - missing EXTERNALREFS records" );
     678           0 :     mbUseRefSheets = true;
     679             :     OSL_ENSURE( maRefSheets.empty(), "ExternalLinkBuffer::importExternalSheets - multiple EXTERNALSHEETS records" );
     680           0 :     maRefSheets.clear();
     681             :     sal_Int32 nRefCount;
     682           0 :     nRefCount = rStrm.readInt32();
     683           0 :     size_t nMaxCount = getLimitedValue< size_t, sal_Int64 >( nRefCount, 0, rStrm.getRemaining() / 12 );
     684           0 :     maRefSheets.reserve( nMaxCount );
     685           0 :     for( size_t nRefId = 0; !rStrm.isEof() && (nRefId < nMaxCount); ++nRefId )
     686             :     {
     687           0 :         RefSheetsModel aRefSheets;
     688           0 :         aRefSheets.readBiff12Data( rStrm );
     689           0 :         maRefSheets.push_back( aRefSheets );
     690             :     }
     691           0 : }
     692             : 
     693         341 : Sequence< ExternalLinkInfo > ExternalLinkBuffer::getLinkInfos() const
     694             : {
     695         341 :     ::std::vector< ExternalLinkInfo > aLinkInfos;
     696             :     // XML formula parser also used in BIFF12 documents, e.g. replacement formulas in unsupported conditional formattings
     697             :     OSL_ENSURE( getFilterType() == FILTER_OOXML, "ExternalLinkBuffer::getLinkInfos - unexpected file format" );
     698             :     // add entry for implicit index 0 (self reference to this document)
     699         341 :     aLinkInfos.push_back( mxSelfRef->getLinkInfo() );
     700         344 :     for( ExternalLinkVec::const_iterator aIt = maExtLinks.begin(), aEnd = maExtLinks.end(); aIt != aEnd; ++aIt )
     701           3 :         aLinkInfos.push_back( (*aIt)->getLinkInfo() );
     702         341 :     return ContainerHelper::vectorToSequence( aLinkInfos );
     703             : }
     704             : 
     705           0 : ExternalLinkRef ExternalLinkBuffer::getExternalLink( sal_Int32 nRefId, bool bUseRefSheets ) const
     706             : {
     707           0 :     ExternalLinkRef xExtLink;
     708           0 :     switch( getFilterType() )
     709             :     {
     710             :         case FILTER_OOXML:
     711             :             // OOXML: 0 = this document, otherwise one-based index into link list
     712           0 :             if( !bUseRefSheets || !mbUseRefSheets )
     713           0 :                 xExtLink = (nRefId == 0) ? mxSelfRef : maLinks.get( nRefId - 1 );
     714             :             // BIFF12: zero-based index into ref-sheets list
     715           0 :             else if( const RefSheetsModel* pRefSheets = getRefSheets( nRefId ) )
     716           0 :                 xExtLink = maLinks.get( pRefSheets->mnExtRefId );
     717           0 :         break;
     718             :         case FILTER_BIFF:
     719           0 :             switch( getBiff() )
     720             :             {
     721             :                 case BIFF2:
     722             :                 case BIFF3:
     723             :                 case BIFF4:
     724             :                     // one-based index to EXTERNSHEET records
     725           0 :                     xExtLink = maLinks.get( nRefId - 1 );
     726           0 :                 break;
     727             :                 case BIFF5:
     728           0 :                     if( nRefId < 0 )
     729             :                     {
     730             :                         // internal links in formula tokens have negative index
     731           0 :                         xExtLink = maLinks.get( -nRefId - 1 );
     732           0 :                         if( xExtLink.get() && !xExtLink->isInternalLink() )
     733           0 :                             xExtLink.reset();
     734             :                     }
     735             :                     else
     736             :                     {
     737             :                         // one-based index to EXTERNSHEET records
     738           0 :                         xExtLink = maLinks.get( nRefId - 1 );
     739             :                     }
     740           0 :                 break;
     741             :                 case BIFF8:
     742             :                     // zero-based index into REF list in EXTERNSHEET record
     743           0 :                     if( const RefSheetsModel* pRefSheets = getRefSheets( nRefId ) )
     744           0 :                         xExtLink = maLinks.get( pRefSheets->mnExtRefId );
     745           0 :                 break;
     746           0 :                 case BIFF_UNKNOWN: break;
     747             :             }
     748           0 :         break;
     749           0 :         case FILTER_UNKNOWN: break;
     750             :     }
     751           0 :     return xExtLink;
     752             : }
     753             : 
     754           0 : LinkSheetRange ExternalLinkBuffer::getSheetRange( sal_Int32 nRefId, sal_Int16 nTabId1, sal_Int16 nTabId2 ) const
     755             : {
     756             :     OSL_ENSURE( getBiff() <= BIFF5, "ExternalLinkBuffer::getSheetRange - wrong BIFF version" );
     757           0 :     LinkSheetRange aSheetRange;
     758           0 :     if( const ExternalLink* pExtLink = getExternalLink( nRefId ).get() )
     759           0 :         pExtLink->getSheetRange( aSheetRange, nTabId1, nTabId2 );
     760           0 :     return aSheetRange;
     761             : }
     762             : 
     763           0 : LinkSheetRange ExternalLinkBuffer::getSheetRange( sal_Int32 nRefId ) const
     764             : {
     765             :     OSL_ENSURE( ((getFilterType() == FILTER_OOXML) && mbUseRefSheets) || (getBiff() == BIFF8), "ExternalLinkBuffer::getSheetRange - wrong BIFF version" );
     766           0 :     LinkSheetRange aSheetRange;
     767           0 :     if( const ExternalLink* pExtLink = getExternalLink( nRefId ).get() )
     768           0 :         if( const RefSheetsModel* pRefSheets = getRefSheets( nRefId ) )
     769           0 :             pExtLink->getSheetRange( aSheetRange, pRefSheets->mnTabId1, pRefSheets->mnTabId2 );
     770           0 :     return aSheetRange;
     771             : }
     772             : 
     773             : // private --------------------------------------------------------------------
     774             : 
     775           1 : ExternalLinkRef ExternalLinkBuffer::createExternalLink()
     776             : {
     777           1 :     ExternalLinkRef xExtLink( new ExternalLink( *this ) );
     778           1 :     maLinks.push_back( xExtLink );
     779           1 :     return xExtLink;
     780             : }
     781             : 
     782           0 : const RefSheetsModel* ExternalLinkBuffer::getRefSheets( sal_Int32 nRefId ) const
     783             : {
     784           0 :     return ((0 <= nRefId) && (static_cast< size_t >( nRefId ) < maRefSheets.size())) ?
     785           0 :         &maRefSheets[ static_cast< size_t >( nRefId ) ] : 0;
     786             : }
     787             : 
     788             : } // namespace xls
     789          30 : } // namespace oox
     790             : 
     791             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11