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

Generated by: LCOV version 1.10