LCOV - code coverage report
Current view: top level - sc/source/filter/excel - xilink.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 183 385 47.5 %
Date: 2014-11-03 Functions: 54 75 72.0 %
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 "xilink.hxx"
      21             : #include "document.hxx"
      22             : #include "formulacell.hxx"
      23             : #include "scextopt.hxx"
      24             : #include "tablink.hxx"
      25             : #include "xistream.hxx"
      26             : #include "xihelper.hxx"
      27             : #include "xiname.hxx"
      28             : #include "excform.hxx"
      29             : #include "tokenarray.hxx"
      30             : #include "externalrefmgr.hxx"
      31             : #include "scmatrix.hxx"
      32             : #include <svl/sharedstringpool.hxx>
      33             : 
      34             : #include <vector>
      35             : #include <boost/ptr_container/ptr_vector.hpp>
      36             : 
      37             : using ::std::vector;
      38             : 
      39             : // *** Helper classes ***
      40             : 
      41             : // Cached external cells ======================================================
      42             : 
      43             : /**
      44             :  * Contains the address and value of an external referenced cell.
      45             :  * Note that this is non-copyable, so cannot be used in most stl/boost containers.
      46             :  */
      47           8 : class XclImpCrn : public XclImpCachedValue
      48             : {
      49             : public:
      50             :     /** Reads a cached value and stores it with its cell address. */
      51             :     explicit            XclImpCrn( XclImpStream& rStrm, const XclAddress& rXclPos );
      52             : 
      53           4 :     const XclAddress&   GetAddress() const { return maXclPos;}
      54             : 
      55             : private:
      56             :     XclAddress          maXclPos;       /// Excel position of the cached cell.
      57             : };
      58             : 
      59             : // Sheet in an external document ==============================================
      60             : 
      61             : /** Contains the name and sheet index of one sheet in an external document. */
      62             : class XclImpSupbookTab
      63             : {
      64             : public:
      65             :     /** Stores the sheet name and marks the sheet index as invalid.
      66             :         The sheet index is set while creating the Calc sheet with CreateTable(). */
      67             :     explicit            XclImpSupbookTab( const OUString& rTabName );
      68             :                         ~XclImpSupbookTab();
      69             : 
      70           8 :     inline const OUString& GetTabName() const { return maTabName; }
      71             : 
      72             :     /** Reads a CRN record (external referenced cell) at the specified address. */
      73             :     void                ReadCrn( XclImpStream& rStrm, const XclAddress& rXclPos );
      74             : 
      75             :     void                LoadCachedValues(ScExternalRefCache::TableTypeRef pCacheTable);
      76             : 
      77             : private:
      78             :     typedef boost::shared_ptr< XclImpCrn > XclImpCrnRef;
      79             :     typedef std::vector< XclImpCrnRef > XclImpCrnList;
      80             : 
      81             :     XclImpCrnList       maCrnList;      /// List of CRN records (cached cell values).
      82             :     OUString            maTabName;      /// Name of the external sheet.
      83             : };
      84             : 
      85             : // External document (SUPBOOK) ================================================
      86             : 
      87             : /** This class represents an external linked document (record SUPBOOK).
      88             :     @descr  Contains a list of all referenced sheets in the document. */
      89         184 : class XclImpSupbook : protected XclImpRoot
      90             : {
      91             : public:
      92             :     /** Reads the SUPBOOK record from stream. */
      93             :     explicit            XclImpSupbook( XclImpStream& rStrm );
      94             : 
      95             :     /** Reads an XCT record (count of following CRNs and current sheet). */
      96             :     void                ReadXct( XclImpStream& rStrm );
      97             :     /** Reads a CRN record (external referenced cell). */
      98             :     void                ReadCrn( XclImpStream& rStrm );
      99             :     /** Reads an EXTERNNAME record. */
     100             :     void                ReadExternname( XclImpStream& rStrm, ExcelToSc* pFormulaConv = NULL );
     101             : 
     102             :     /** Returns the SUPBOOK record type. */
     103        2318 :     inline XclSupbookType GetType() const { return meType; }
     104             : 
     105             :     /** Returns the URL of the external document. */
     106           4 :     inline const OUString& GetXclUrl() const { return maXclUrl; }
     107             : 
     108             :     /** Returns the external name specified by an index from the Excel document (one-based). */
     109             :     const XclImpExtName* GetExternName( sal_uInt16 nXclIndex ) const;
     110             :     /** Tries to decode the URL to OLE or DDE link components.
     111             :         @descr  For DDE links: Decodes to application name and topic.
     112             :         For OLE object links: Decodes to class name and document URL.
     113             :         @return  true = decoding was successful, returned strings are valid (not empty). */
     114             :     bool                GetLinkData( OUString& rApplic, OUString& rDoc ) const;
     115             :     /** Returns the specified macro name (1-based) or an empty string on error. */
     116             :     const OUString&     GetMacroName( sal_uInt16 nXclNameIdx ) const;
     117             : 
     118             :     const OUString&     GetTabName( sal_uInt16 nXtiTab ) const;
     119             : 
     120             :     sal_uInt16          GetTabCount() const;
     121             : 
     122             :     void                LoadCachedValues();
     123             : 
     124             :     svl::SharedStringPool& GetSharedStringPool();
     125             : 
     126             : private:
     127             :     typedef boost::ptr_vector< XclImpSupbookTab >  XclImpSupbookTabList;
     128             :     typedef boost::ptr_vector< XclImpExtName >     XclImpExtNameList;
     129             : 
     130             :     XclImpSupbookTabList maSupbTabList;     /// All sheet names of the document.
     131             :     XclImpExtNameList   maExtNameList;      /// All external names of the document.
     132             :     OUString            maXclUrl;           /// URL of the external document (Excel mode).
     133             :     XclSupbookType      meType;             /// Type of the supbook record.
     134             :     sal_uInt16          mnSBTab;            /// Current Excel sheet index from SUPBOOK for XCT/CRN records.
     135             : };
     136             : 
     137             : // Import link manager ========================================================
     138             : 
     139             : /** Contains the SUPBOOK index and sheet indexes of an external link.
     140             :     @descr  It is possible to enter a formula like =SUM(Sheet1:Sheet3!A1),
     141             :     therefore here occurs a sheet range. */
     142             : struct XclImpXti
     143             : {
     144             :     sal_uInt16          mnSupbook;      /// Index to SUPBOOK record.
     145             :     sal_uInt16          mnSBTabFirst;   /// Index to the first sheet of the range in the SUPBOOK.
     146             :     sal_uInt16          mnSBTabLast;    /// Index to the last sheet of the range in the SUPBOOK.
     147         154 :     inline explicit     XclImpXti() : mnSupbook( SAL_MAX_UINT16 ), mnSBTabFirst( SAL_MAX_UINT16 ), mnSBTabLast( SAL_MAX_UINT16 ) {}
     148             : };
     149             : 
     150         154 : inline XclImpStream& operator>>( XclImpStream& rStrm, XclImpXti& rXti )
     151             : {
     152         154 :     return rStrm >> rXti.mnSupbook >> rXti.mnSBTabFirst >> rXti.mnSBTabLast;
     153             : }
     154             : 
     155             : /** Implementation of the link manager. */
     156         284 : class XclImpLinkManagerImpl : protected XclImpRoot
     157             : {
     158             : public:
     159             :     explicit            XclImpLinkManagerImpl( const XclImpRoot& rRoot );
     160             : 
     161             :     /** Reads the EXTERNSHEET record. */
     162             :     void                ReadExternsheet( XclImpStream& rStrm );
     163             :     /** Reads a SUPBOOK record. */
     164             :     void                ReadSupbook( XclImpStream& rStrm );
     165             :     /** Reads an XCT record and appends it to the current SUPBOOK. */
     166             :     void                ReadXct( XclImpStream& rStrm );
     167             :     /** Reads a CRN record and appends it to the current SUPBOOK. */
     168             :     void                ReadCrn( XclImpStream& rStrm );
     169             :     /** Reads an EXTERNNAME record and appends it to the current SUPBOOK. */
     170             :     void                ReadExternname( XclImpStream& rStrm, ExcelToSc* pFormulaConv = NULL );
     171             : 
     172             :     /** Returns true, if the specified XTI entry contains an internal reference. */
     173             :     bool                IsSelfRef( sal_uInt16 nXtiIndex ) const;
     174             :     /** Returns the Calc sheet index range of the specified XTI entry.
     175             :         @return  true = XTI data found, returned sheet index range is valid. */
     176             :     bool                GetScTabRange(
     177             :                             SCTAB& rnFirstScTab, SCTAB& rnLastScTab,
     178             :                             sal_uInt16 nXtiIndex ) const;
     179             :     /** Returns the specified external name or 0 on error. */
     180             :     const XclImpExtName* GetExternName( sal_uInt16 nXtiIndex, sal_uInt16 nExtName ) const;
     181             : 
     182             :     /** Returns the absolute file URL of a supporting workbook specified by
     183             :         the index. */
     184             :     const OUString*       GetSupbookUrl( sal_uInt16 nXtiIndex ) const;
     185             : 
     186             :     const OUString&       GetSupbookTabName( sal_uInt16 nXti, sal_uInt16 nXtiTab ) const;
     187             : 
     188             :     /** Tries to decode the URL of the specified XTI entry to OLE or DDE link components.
     189             :         @descr  For DDE links: Decodes to application name and topic.
     190             :         For OLE object links: Decodes to class name and document URL.
     191             :         @return  true = decoding was successful, returned strings are valid (not empty). */
     192             :     bool                GetLinkData( OUString& rApplic, OUString& rTopic, sal_uInt16 nXtiIndex ) const;
     193             :     /** Returns the specified macro name or an empty string on error. */
     194             :     const OUString&     GetMacroName( sal_uInt16 nExtSheet, sal_uInt16 nExtName ) const;
     195             : 
     196             : private:
     197             :     /** Returns the specified XTI (link entry from BIFF8 EXTERNSHEET record). */
     198             :     const XclImpXti*    GetXti( sal_uInt16 nXtiIndex ) const;
     199             :     /** Returns the specified SUPBOOK (external document). */
     200             :     const XclImpSupbook* GetSupbook( sal_uInt16 nXtiIndex ) const;
     201             : 
     202             :     void                LoadCachedValues();
     203             : 
     204             : private:
     205             :     typedef ::std::vector< XclImpXti >  XclImpXtiVector;
     206             :     typedef boost::ptr_vector< XclImpSupbook > XclImpSupbookList;
     207             : 
     208             :     XclImpXtiVector     maXtiList;          /// List of all XTI structures.
     209             :     XclImpSupbookList   maSupbookList;      /// List of external documents.
     210             : };
     211             : 
     212             : // *** Implementation ***
     213             : 
     214             : // Excel sheet indexes ========================================================
     215             : 
     216             : // original Excel sheet names -------------------------------------------------
     217             : 
     218         414 : void XclImpTabInfo::AppendXclTabName( const OUString& rXclTabName, SCTAB nScTab )
     219             : {
     220         414 :     maTabNames[ rXclTabName ] = nScTab;
     221         414 : }
     222             : 
     223           0 : void XclImpTabInfo::InsertScTab( SCTAB nScTab )
     224             : {
     225           0 :     for( XclTabNameMap::iterator aIt = maTabNames.begin(), aEnd = maTabNames.end(); aIt != aEnd; ++aIt )
     226           0 :         if( aIt->second >= nScTab )
     227           0 :             ++aIt->second;
     228           0 : }
     229             : 
     230           4 : SCTAB XclImpTabInfo::GetScTabFromXclName( const OUString& rXclTabName ) const
     231             : {
     232           4 :     XclTabNameMap::const_iterator aIt = maTabNames.find( rXclTabName );
     233           4 :     return (aIt != maTabNames.end()) ? aIt->second : SCTAB_INVALID;
     234             : }
     235             : 
     236             : // record creation order - TABID record ---------------------------------------
     237             : 
     238         136 : void XclImpTabInfo::ReadTabid( XclImpStream& rStrm )
     239             : {
     240             :     OSL_ENSURE_BIFF( rStrm.GetRoot().GetBiff() == EXC_BIFF8 );
     241         136 :     if( rStrm.GetRoot().GetBiff() == EXC_BIFF8 )
     242             :     {
     243         136 :         rStrm.EnableDecryption();
     244         136 :         sal_Size nReadCount = rStrm.GetRecLeft() / 2;
     245             :         OSL_ENSURE( nReadCount <= 0xFFFF, "XclImpTabInfo::ReadTabid - record too long" );
     246         136 :         maTabIdVec.clear();
     247         136 :         maTabIdVec.reserve( nReadCount );
     248         548 :         for( sal_Size nIndex = 0; rStrm.IsValid() && (nIndex < nReadCount); ++nIndex )
     249             :             // zero index is not allowed in BIFF8, but it seems that it occurs in real life
     250         412 :             maTabIdVec.push_back( rStrm.ReaduInt16() );
     251             :     }
     252         136 : }
     253             : 
     254          52 : sal_uInt16 XclImpTabInfo::GetCurrentIndex( sal_uInt16 nCreatedId, sal_uInt16 nMaxTabId ) const
     255             : {
     256          52 :     sal_uInt16 nReturn = 0;
     257          52 :     for( ScfUInt16Vec::const_iterator aIt = maTabIdVec.begin(), aEnd = maTabIdVec.end(); aIt != aEnd; ++aIt )
     258             :     {
     259          52 :         sal_uInt16 nValue = *aIt;
     260          52 :         if( nValue == nCreatedId )
     261          52 :             return nReturn;
     262           0 :         if( nValue <= nMaxTabId )
     263           0 :             ++nReturn;
     264             :     }
     265           0 :     return 0;
     266             : }
     267             : 
     268             : // External names =============================================================
     269             : 
     270           0 : XclImpExtName::MOper::MOper(svl::SharedStringPool& rPool, XclImpStream& rStrm) :
     271           0 :     mxCached(new ScMatrix(0,0))
     272             : {
     273           0 :     SCSIZE nLastCol = rStrm.ReaduInt8();
     274           0 :     SCSIZE nLastRow = rStrm.ReaduInt16();
     275           0 :     mxCached->Resize(nLastCol+1, nLastRow+1);
     276           0 :     for (SCSIZE nRow = 0; nRow <= nLastRow; ++nRow)
     277             :     {
     278           0 :         for (SCSIZE nCol = 0; nCol <= nLastCol; ++nCol)
     279             :         {
     280             :             sal_uInt8 nOp;
     281           0 :             rStrm >> nOp;
     282           0 :             switch (nOp)
     283             :             {
     284             :                 case 0x01:
     285             :                 {
     286           0 :                     double fVal = rStrm.ReadDouble();
     287           0 :                     mxCached->PutDouble(fVal, nCol, nRow);
     288             :                 }
     289           0 :                 break;
     290             :                 case 0x02:
     291             :                 {
     292           0 :                     OUString aStr = rStrm.ReadUniString();
     293           0 :                     mxCached->PutString(rPool.intern(aStr), nCol, nRow);
     294             :                 }
     295           0 :                 break;
     296             :                 case 0x04:
     297             :                 {
     298           0 :                     bool bVal = rStrm.ReaduInt8();
     299           0 :                     mxCached->PutBoolean(bVal, nCol, nRow);
     300           0 :                     rStrm.Ignore(7);
     301             :                 }
     302           0 :                 break;
     303             :                 case 0x10:
     304             :                 {
     305           0 :                     sal_uInt8 nErr = rStrm.ReaduInt8();
     306             :                     // TODO: Map the error code from xls to calc.
     307           0 :                     mxCached->PutError(nErr, nCol, nRow);
     308           0 :                     rStrm.Ignore(7);
     309             :                 }
     310           0 :                 break;
     311             :                 default:
     312           0 :                     rStrm.Ignore(8);
     313             :             }
     314             :         }
     315             :     }
     316           0 : }
     317             : 
     318           0 : const ScMatrix& XclImpExtName::MOper::GetCache() const
     319             : {
     320           0 :     return *mxCached;
     321             : }
     322             : 
     323           0 : XclImpExtName::XclImpExtName( XclImpSupbook& rSupbook, XclImpStream& rStrm, XclSupbookType eSubType, ExcelToSc* pFormulaConv )
     324             :     : mpMOper(NULL)
     325           0 :     , mnStorageId(0)
     326             : {
     327           0 :     sal_uInt16 nFlags(0);
     328           0 :     sal_uInt8 nLen(0);
     329             : 
     330           0 :     rStrm >> nFlags >> mnStorageId >> nLen ;
     331           0 :     maName = rStrm.ReadUniString( nLen );
     332           0 :     if( ::get_flag( nFlags, EXC_EXTN_BUILTIN ) || !::get_flag( nFlags, EXC_EXTN_OLE_OR_DDE ) )
     333             :     {
     334           0 :         if( eSubType == EXC_SBTYPE_ADDIN )
     335             :         {
     336           0 :             meType = xlExtAddIn;
     337           0 :             maName = rStrm.GetRoot().GetScAddInName( maName );
     338             :         }
     339           0 :         else if ( (eSubType == EXC_SBTYPE_EUROTOOL) &&
     340           0 :                 maName.equalsIgnoreAsciiCase( "EUROCONVERT" ) )
     341           0 :             meType = xlExtEuroConvert;
     342             :         else
     343             :         {
     344           0 :             meType = xlExtName;
     345           0 :             maName = ScfTools::ConvertToScDefinedName( maName );
     346             :         }
     347             :     }
     348             :     else
     349             :     {
     350           0 :         meType = ::get_flagvalue( nFlags, EXC_EXTN_OLE, xlExtOLE, xlExtDDE );
     351             :     }
     352             : 
     353           0 :     switch (meType)
     354             :     {
     355             :         case xlExtDDE:
     356           0 :             if (rStrm.GetRecLeft() > 1)
     357           0 :                 mxDdeMatrix.reset(new XclImpCachedMatrix(rStrm));
     358           0 :         break;
     359             :         case xlExtName:
     360             :             // TODO: For now, only global external names are supported.  In future
     361             :             // we should extend this to supporting per-sheet external names.
     362           0 :             if (mnStorageId == 0)
     363             :             {
     364           0 :                 if (pFormulaConv)
     365             :                 {
     366           0 :                     const ScTokenArray* pArray = NULL;
     367             :                     sal_uInt16 nFmlaLen;
     368           0 :                     rStrm >> nFmlaLen;
     369           0 :                     vector<OUString> aTabNames;
     370           0 :                     sal_uInt16 nCount = rSupbook.GetTabCount();
     371           0 :                     aTabNames.reserve(nCount);
     372           0 :                     for (sal_uInt16 i = 0; i < nCount; ++i)
     373           0 :                         aTabNames.push_back(rSupbook.GetTabName(i));
     374             : 
     375           0 :                     pFormulaConv->ConvertExternName(pArray, rStrm, nFmlaLen, rSupbook.GetXclUrl(), aTabNames);
     376           0 :                     if (pArray)
     377           0 :                         mxArray.reset(pArray->Clone());
     378             :                 }
     379             :             }
     380           0 :         break;
     381             :         case xlExtOLE:
     382           0 :             mpMOper = new MOper(rSupbook.GetSharedStringPool(), rStrm);
     383           0 :         break;
     384             :         default:
     385             :             ;
     386             :     }
     387           0 : }
     388             : 
     389           0 : XclImpExtName::~XclImpExtName()
     390             : {
     391           0 :     delete mpMOper;
     392           0 : }
     393             : 
     394           0 : void XclImpExtName::CreateDdeData( ScDocument& rDoc, const OUString& rApplic, const OUString& rTopic ) const
     395             : {
     396           0 :     ScMatrixRef xResults;
     397           0 :     if( mxDdeMatrix.get() )
     398           0 :         xResults = mxDdeMatrix->CreateScMatrix(rDoc.GetSharedStringPool());
     399           0 :     rDoc.CreateDdeLink( rApplic, rTopic, maName, SC_DDE_DEFAULT, xResults );
     400           0 : }
     401             : 
     402           0 : void XclImpExtName::CreateExtNameData( ScDocument& rDoc, sal_uInt16 nFileId ) const
     403             : {
     404           0 :     if (!mxArray.get())
     405           0 :         return;
     406             : 
     407           0 :     ScExternalRefManager* pRefMgr = rDoc.GetExternalRefManager();
     408           0 :     pRefMgr->storeRangeNameTokens(nFileId, maName, *mxArray);
     409             : }
     410             : 
     411             : namespace {
     412             : 
     413             : /**
     414             :  * Decompose the name into sheet name and range name.  An OLE link name is
     415             :  * always formatted like this [ !Sheet1!R1C1:R5C2 ] and it always uses R1C1
     416             :  * notation.
     417             :  */
     418           0 : bool extractSheetAndRange(const OUString& rName, OUString& rSheet, OUString& rRange)
     419             : {
     420           0 :     sal_Int32 n = rName.getLength();
     421           0 :     const sal_Unicode* p = rName.getStr();
     422           0 :     OUStringBuffer aBuf;
     423           0 :     bool bInSheet = true;
     424           0 :     for (sal_Int32 i = 0; i < n; ++i, ++p)
     425             :     {
     426           0 :         if (i == 0)
     427             :         {
     428             :             // first character must be '!'.
     429           0 :             if (*p != '!')
     430           0 :                 return false;
     431           0 :             continue;
     432             :         }
     433             : 
     434           0 :         if (*p == '!')
     435             :         {
     436             :             // sheet name to range separator.
     437           0 :             if (!bInSheet)
     438           0 :                 return false;
     439           0 :             rSheet = aBuf.makeStringAndClear();
     440           0 :             bInSheet = false;
     441           0 :             continue;
     442             :         }
     443             : 
     444           0 :         aBuf.append(*p);
     445             :     }
     446             : 
     447           0 :     rRange = aBuf.makeStringAndClear();
     448           0 :     return true;
     449             : }
     450             : 
     451             : }
     452             : 
     453           0 : bool XclImpExtName::CreateOleData(ScDocument& rDoc, const OUString& rUrl,
     454             :                                   sal_uInt16& rFileId, OUString& rTabName, ScRange& rRange) const
     455             : {
     456           0 :     if (!mpMOper)
     457           0 :         return false;
     458             : 
     459           0 :     OUString aSheet, aRangeStr;
     460           0 :     if (!extractSheetAndRange(maName, aSheet, aRangeStr))
     461           0 :         return false;
     462             : 
     463           0 :     ScRange aRange;
     464           0 :     sal_uInt16 nRes = aRange.ParseAny(aRangeStr, &rDoc, formula::FormulaGrammar::CONV_XL_R1C1);
     465           0 :     if ((nRes & SCA_VALID) != SCA_VALID)
     466           0 :         return false;
     467             : 
     468           0 :     if (aRange.aStart.Tab() != aRange.aEnd.Tab())
     469             :         // We don't support multi-sheet range for this.
     470           0 :         return false;
     471             : 
     472           0 :     const ScMatrix& rCache = mpMOper->GetCache();
     473             :     SCSIZE nC, nR;
     474           0 :     rCache.GetDimensions(nC, nR);
     475           0 :     if (!nC || !nR)
     476             :         // cache matrix is empty.
     477           0 :         return false;
     478             : 
     479           0 :     ScExternalRefManager* pRefMgr = rDoc.GetExternalRefManager();
     480           0 :     sal_uInt16 nFileId = pRefMgr->getExternalFileId(rUrl);
     481           0 :     ScExternalRefCache::TableTypeRef xTab = pRefMgr->getCacheTable(nFileId, aSheet, true, NULL);
     482           0 :     if (!xTab)
     483             :         // cache table creation failed.
     484           0 :         return false;
     485             : 
     486           0 :     xTab->setWholeTableCached();
     487           0 :     for (SCSIZE i = 0; i < nR; ++i)
     488             :     {
     489           0 :         for (SCSIZE j = 0; j < nC; ++j)
     490             :         {
     491           0 :             SCCOL nCol = aRange.aStart.Col() + j;
     492           0 :             SCROW nRow = aRange.aStart.Row() + i;
     493             : 
     494           0 :             ScMatrixValue aVal = rCache.Get(j, i);
     495           0 :             switch (aVal.nType)
     496             :             {
     497             :                 case SC_MATVAL_BOOLEAN:
     498             :                 {
     499           0 :                     bool b = aVal.GetBoolean();
     500           0 :                     ScExternalRefCache::TokenRef pToken(new formula::FormulaDoubleToken(b ? 1.0 : 0.0));
     501           0 :                     xTab->setCell(nCol, nRow, pToken, 0, false);
     502             :                 }
     503           0 :                 break;
     504             :                 case SC_MATVAL_VALUE:
     505             :                 {
     506           0 :                     ScExternalRefCache::TokenRef pToken(new formula::FormulaDoubleToken(aVal.fVal));
     507           0 :                     xTab->setCell(nCol, nRow, pToken, 0, false);
     508             :                 }
     509           0 :                 break;
     510             :                 case SC_MATVAL_STRING:
     511             :                 {
     512           0 :                     const svl::SharedString aStr( aVal.GetString());
     513           0 :                     ScExternalRefCache::TokenRef pToken(new formula::FormulaStringToken(aStr));
     514           0 :                     xTab->setCell(nCol, nRow, pToken, 0, false);
     515             :                 }
     516           0 :                 break;
     517             :                 default:
     518             :                     ;
     519             :             }
     520           0 :         }
     521             :     }
     522             : 
     523           0 :     rFileId = nFileId;
     524           0 :     rTabName = aSheet;
     525           0 :     rRange = aRange;
     526           0 :     return true;
     527             : }
     528             : 
     529           0 : bool XclImpExtName::HasFormulaTokens() const
     530             : {
     531           0 :     return (mxArray.get() != NULL);
     532             : }
     533             : 
     534             : // Cached external cells ======================================================
     535             : 
     536           4 : XclImpCrn::XclImpCrn( XclImpStream& rStrm, const XclAddress& rXclPos ) :
     537             :     XclImpCachedValue( rStrm ),
     538           4 :     maXclPos( rXclPos )
     539             : {
     540           4 : }
     541             : 
     542             : // Sheet in an external document ==============================================
     543             : 
     544           4 : XclImpSupbookTab::XclImpSupbookTab( const OUString& rTabName ) :
     545           4 :     maTabName( rTabName )
     546             : {
     547           4 : }
     548             : 
     549           4 : XclImpSupbookTab::~XclImpSupbookTab()
     550             : {
     551           4 : }
     552             : 
     553           4 : void XclImpSupbookTab::ReadCrn( XclImpStream& rStrm, const XclAddress& rXclPos )
     554             : {
     555           4 :     XclImpCrnRef crnRef( new XclImpCrn(rStrm, rXclPos) );
     556           4 :     maCrnList.push_back( crnRef );
     557           4 : }
     558             : 
     559           4 : void XclImpSupbookTab::LoadCachedValues(ScExternalRefCache::TableTypeRef pCacheTable)
     560             : {
     561           4 :     if (maCrnList.empty())
     562           4 :         return;
     563             : 
     564           8 :     for (XclImpCrnList::iterator itCrnRef = maCrnList.begin(); itCrnRef != maCrnList.end(); ++itCrnRef)
     565             :     {
     566           4 :         const XclImpCrn* const pCrn = itCrnRef->get();
     567           4 :         const XclAddress& rAddr = pCrn->GetAddress();
     568           4 :         switch (pCrn->GetType())
     569             :         {
     570             :             case EXC_CACHEDVAL_BOOL:
     571             :             {
     572           0 :                 bool b = pCrn->GetBool();
     573           0 :                 ScExternalRefCache::TokenRef pToken(new formula::FormulaDoubleToken(b ? 1.0 : 0.0));
     574           0 :                 pCacheTable->setCell(rAddr.mnCol, rAddr.mnRow, pToken, 0, false);
     575             :             }
     576           0 :             break;
     577             :             case EXC_CACHEDVAL_DOUBLE:
     578             :             {
     579           0 :                 double f = pCrn->GetValue();
     580           0 :                 ScExternalRefCache::TokenRef pToken(new formula::FormulaDoubleToken(f));
     581           0 :                 pCacheTable->setCell(rAddr.mnCol, rAddr.mnRow, pToken, 0, false);
     582             :             }
     583           0 :             break;
     584             :             case EXC_CACHEDVAL_ERROR:
     585             :             {
     586           0 :                 double fError = XclTools::ErrorToDouble( pCrn->GetXclError() );
     587           0 :                 ScExternalRefCache::TokenRef pToken(new formula::FormulaDoubleToken(fError));
     588           0 :                 pCacheTable->setCell(rAddr.mnCol, rAddr.mnRow, pToken, 0, false);
     589             :             }
     590           0 :             break;
     591             :             case EXC_CACHEDVAL_STRING:
     592             :             {
     593           4 :                 const OUString& rStr = pCrn->GetString();
     594           4 :                 ScExternalRefCache::TokenRef pToken(new formula::FormulaStringToken(rStr));
     595           4 :                 pCacheTable->setCell(rAddr.mnCol, rAddr.mnRow, pToken, 0, false);
     596             :             }
     597           4 :             break;
     598             :             default:
     599             :                 ;
     600             :         }
     601             :     }
     602             : }
     603             : 
     604             : // External document (SUPBOOK) ================================================
     605             : 
     606          92 : XclImpSupbook::XclImpSupbook( XclImpStream& rStrm ) :
     607          92 :     XclImpRoot( rStrm.GetRoot() ),
     608             :     meType( EXC_SBTYPE_UNKNOWN ),
     609          92 :     mnSBTab( EXC_TAB_DELETED )
     610             : {
     611             :     sal_uInt16 nSBTabCnt;
     612          92 :     rStrm >> nSBTabCnt;
     613             : 
     614          92 :     if( rStrm.GetRecLeft() == 2 )
     615             :     {
     616          88 :         switch( rStrm.ReaduInt16() )
     617             :         {
     618          88 :             case EXC_SUPB_SELF:     meType = EXC_SBTYPE_SELF;   break;
     619           0 :             case EXC_SUPB_ADDIN:    meType = EXC_SBTYPE_ADDIN;  break;
     620             :             default:    OSL_FAIL( "XclImpSupbook::XclImpSupbook - unknown special SUPBOOK type" );
     621             :         }
     622         180 :         return;
     623             :     }
     624             : 
     625           4 :     OUString aEncUrl( rStrm.ReadUniString() );
     626           4 :     bool bSelf = false;
     627           4 :     XclImpUrlHelper::DecodeUrl( maXclUrl, bSelf, GetRoot(), aEncUrl );
     628             : 
     629           4 :     if( maXclUrl.equalsIgnoreAsciiCase( "\010EUROTOOL.XLA" ) )
     630             :     {
     631           0 :         meType = EXC_SBTYPE_EUROTOOL;
     632           0 :         maSupbTabList.push_back( new XclImpSupbookTab( maXclUrl ) );
     633             :     }
     634           4 :     else if( nSBTabCnt )
     635             :     {
     636           4 :         meType = EXC_SBTYPE_EXTERN;
     637           8 :         for( sal_uInt16 nSBTab = 0; nSBTab < nSBTabCnt; ++nSBTab )
     638             :         {
     639           4 :             OUString aTabName( rStrm.ReadUniString() );
     640           4 :             maSupbTabList.push_back( new XclImpSupbookTab( aTabName ) );
     641           4 :         }
     642             :     }
     643             :     else
     644             :     {
     645           0 :         meType = EXC_SBTYPE_SPECIAL;
     646             :         // create dummy list entry
     647           0 :         maSupbTabList.push_back( new XclImpSupbookTab( maXclUrl ) );
     648           4 :     }
     649             : }
     650             : 
     651           4 : void XclImpSupbook::ReadXct( XclImpStream& rStrm )
     652             : {
     653           4 :     rStrm.Ignore( 2 );
     654           4 :     rStrm >> mnSBTab;
     655           4 : }
     656             : 
     657           4 : void XclImpSupbook::ReadCrn( XclImpStream& rStrm )
     658             : {
     659           4 :     if (mnSBTab >= maSupbTabList.size())
     660           4 :         return;
     661           4 :     XclImpSupbookTab& rSbTab = maSupbTabList[mnSBTab];
     662             :     sal_uInt8 nXclColLast, nXclColFirst;
     663             :     sal_uInt16 nXclRow;
     664           4 :     rStrm >> nXclColLast >> nXclColFirst >> nXclRow;
     665             : 
     666           8 :     for( sal_uInt8 nXclCol = nXclColFirst; (nXclCol <= nXclColLast) && (rStrm.GetRecLeft() > 1); ++nXclCol )
     667           4 :         rSbTab.ReadCrn( rStrm, XclAddress( nXclCol, nXclRow ) );
     668             : }
     669             : 
     670           0 : void XclImpSupbook::ReadExternname( XclImpStream& rStrm, ExcelToSc* pFormulaConv )
     671             : {
     672           0 :     maExtNameList.push_back( new XclImpExtName( *this, rStrm, meType, pFormulaConv ) );
     673           0 : }
     674             : 
     675           0 : const XclImpExtName* XclImpSupbook::GetExternName( sal_uInt16 nXclIndex ) const
     676             : {
     677             :     OSL_ENSURE( nXclIndex > 0, "XclImpSupbook::GetExternName - index must be >0" );
     678           0 :     if (meType == EXC_SBTYPE_SELF || nXclIndex > maExtNameList.size())
     679           0 :         return NULL;
     680           0 :     return &maExtNameList[nXclIndex-1];
     681             : }
     682             : 
     683           0 : bool XclImpSupbook::GetLinkData( OUString& rApplic, OUString& rTopic ) const
     684             : {
     685           0 :     return (meType == EXC_SBTYPE_SPECIAL) && XclImpUrlHelper::DecodeLink( rApplic, rTopic, maXclUrl );
     686             : }
     687             : 
     688           2 : const OUString& XclImpSupbook::GetMacroName( sal_uInt16 nXclNameIdx ) const
     689             : {
     690             :     OSL_ENSURE( nXclNameIdx > 0, "XclImpSupbook::GetMacroName - index must be >0" );
     691           2 :     const XclImpName* pName = (meType == EXC_SBTYPE_SELF) ? GetNameManager().GetName( nXclNameIdx ) : 0;
     692           2 :     return (pName && pName->IsVBName()) ? pName->GetScName() : EMPTY_OUSTRING;
     693             : }
     694             : 
     695           4 : const OUString& XclImpSupbook::GetTabName( sal_uInt16 nXtiTab ) const
     696             : {
     697           4 :     if (nXtiTab >= maSupbTabList.size())
     698           0 :         return EMPTY_OUSTRING;
     699           4 :     return maSupbTabList[nXtiTab].GetTabName();
     700             : }
     701             : 
     702           0 : sal_uInt16 XclImpSupbook::GetTabCount() const
     703             : {
     704           0 :     return ulimit_cast<sal_uInt16>(maSupbTabList.size());
     705             : }
     706             : 
     707          92 : void XclImpSupbook::LoadCachedValues()
     708             : {
     709          92 :     if (meType != EXC_SBTYPE_EXTERN || GetExtDocOptions().GetDocSettings().mnLinkCnt > 0 || !GetDocShell())
     710         180 :         return;
     711             : 
     712           4 :     OUString aAbsUrl( ScGlobal::GetAbsDocName(maXclUrl, GetDocShell()) );
     713             : 
     714           4 :     ScExternalRefManager* pRefMgr = GetRoot().GetDoc().GetExternalRefManager();
     715           4 :     sal_uInt16 nFileId = pRefMgr->getExternalFileId(aAbsUrl);
     716             : 
     717           8 :     for (XclImpSupbookTabList::iterator itTab = maSupbTabList.begin(); itTab != maSupbTabList.end(); ++itTab)
     718             :     {
     719           4 :         const OUString& rTabName = itTab->GetTabName();
     720           4 :         ScExternalRefCache::TableTypeRef pCacheTable = pRefMgr->getCacheTable(nFileId, rTabName, true);
     721           4 :         itTab->LoadCachedValues(pCacheTable);
     722           4 :         pCacheTable->setWholeTableCached();
     723           8 :     }
     724             : }
     725             : 
     726           0 : svl::SharedStringPool& XclImpSupbook::GetSharedStringPool()
     727             : {
     728           0 :     return GetDoc().GetSharedStringPool();
     729             : }
     730             : 
     731             : // Import link manager ========================================================
     732             : 
     733         142 : XclImpLinkManagerImpl::XclImpLinkManagerImpl( const XclImpRoot& rRoot ) :
     734         142 :     XclImpRoot( rRoot )
     735             : {
     736         142 : }
     737             : 
     738          88 : void XclImpLinkManagerImpl::ReadExternsheet( XclImpStream& rStrm )
     739             : {
     740             :     sal_uInt16 nXtiCount;
     741          88 :     rStrm >> nXtiCount;
     742             :     OSL_ENSURE( static_cast< sal_Size >( nXtiCount * 6 ) == rStrm.GetRecLeft(), "XclImpLinkManagerImpl::ReadExternsheet - invalid count" );
     743          88 :     nXtiCount = static_cast< sal_uInt16 >( ::std::min< sal_Size >( nXtiCount, rStrm.GetRecLeft() / 6 ) );
     744             : 
     745             :     /*  #i104057# A weird external XLS generator writes multiple EXTERNSHEET
     746             :         records instead of only one as expected. Surprisingly, Excel seems to
     747             :         insert the entries of the second record before the entries of the first
     748             :         record. */
     749          88 :     XclImpXtiVector aNewEntries( nXtiCount );
     750         242 :     for( XclImpXtiVector::iterator aIt = aNewEntries.begin(), aEnd = aNewEntries.end(); rStrm.IsValid() && (aIt != aEnd); ++aIt )
     751         154 :         rStrm >> *aIt;
     752          88 :     maXtiList.insert( maXtiList.begin(), aNewEntries.begin(), aNewEntries.end() );
     753             : 
     754          88 :     LoadCachedValues();
     755          88 : }
     756             : 
     757          92 : void XclImpLinkManagerImpl::ReadSupbook( XclImpStream& rStrm )
     758             : {
     759          92 :     maSupbookList.push_back( new XclImpSupbook( rStrm ) );
     760          92 : }
     761             : 
     762           4 : void XclImpLinkManagerImpl::ReadXct( XclImpStream& rStrm )
     763             : {
     764           4 :     if( !maSupbookList.empty() )
     765           4 :         maSupbookList.back().ReadXct( rStrm );
     766           4 : }
     767             : 
     768           4 : void XclImpLinkManagerImpl::ReadCrn( XclImpStream& rStrm )
     769             : {
     770           4 :     if( !maSupbookList.empty() )
     771           4 :         maSupbookList.back().ReadCrn( rStrm );
     772           4 : }
     773             : 
     774           0 : void XclImpLinkManagerImpl::ReadExternname( XclImpStream& rStrm, ExcelToSc* pFormulaConv )
     775             : {
     776           0 :     if( !maSupbookList.empty() )
     777           0 :         maSupbookList.back().ReadExternname( rStrm, pFormulaConv );
     778           0 : }
     779             : 
     780        2318 : bool XclImpLinkManagerImpl::IsSelfRef( sal_uInt16 nXtiIndex ) const
     781             : {
     782        2318 :     const XclImpSupbook* pSupbook = GetSupbook( nXtiIndex );
     783        2318 :     return pSupbook && (pSupbook->GetType() == EXC_SBTYPE_SELF);
     784             : }
     785             : 
     786        2334 : bool XclImpLinkManagerImpl::GetScTabRange(
     787             :         SCTAB& rnFirstScTab, SCTAB& rnLastScTab, sal_uInt16 nXtiIndex ) const
     788             : {
     789        2334 :     if( const XclImpXti* pXti = GetXti( nXtiIndex ) )
     790             :     {
     791        2334 :         if (!maSupbookList.empty() && (pXti->mnSupbook < maSupbookList.size()) )
     792             :         {
     793        2334 :             rnFirstScTab = pXti->mnSBTabFirst;
     794        2334 :             rnLastScTab  = pXti->mnSBTabLast;
     795        2334 :             return true;
     796             :         }
     797             :     }
     798           0 :     return false;
     799             : }
     800             : 
     801           0 : const XclImpExtName* XclImpLinkManagerImpl::GetExternName( sal_uInt16 nXtiIndex, sal_uInt16 nExtName ) const
     802             : {
     803           0 :     const XclImpSupbook* pSupbook = GetSupbook( nXtiIndex );
     804           0 :     return pSupbook ? pSupbook->GetExternName( nExtName ) : 0;
     805             : }
     806             : 
     807           4 : const OUString* XclImpLinkManagerImpl::GetSupbookUrl( sal_uInt16 nXtiIndex ) const
     808             : {
     809           4 :     const XclImpSupbook* p = GetSupbook( nXtiIndex );
     810           4 :     if (!p)
     811           0 :         return NULL;
     812           4 :     return &p->GetXclUrl();
     813             : }
     814             : 
     815           4 : const OUString& XclImpLinkManagerImpl::GetSupbookTabName( sal_uInt16 nXti, sal_uInt16 nXtiTab ) const
     816             : {
     817           4 :     const XclImpSupbook* p = GetSupbook(nXti);
     818           4 :     return p ? p->GetTabName(nXtiTab) : EMPTY_OUSTRING;
     819             : }
     820             : 
     821           0 : bool XclImpLinkManagerImpl::GetLinkData( OUString& rApplic, OUString& rTopic, sal_uInt16 nXtiIndex ) const
     822             : {
     823           0 :     const XclImpSupbook* pSupbook = GetSupbook( nXtiIndex );
     824           0 :     return pSupbook && pSupbook->GetLinkData( rApplic, rTopic );
     825             : }
     826             : 
     827           2 : const OUString& XclImpLinkManagerImpl::GetMacroName( sal_uInt16 nExtSheet, sal_uInt16 nExtName ) const
     828             : {
     829           2 :     const XclImpSupbook* pSupbook = GetSupbook( nExtSheet );
     830           2 :     return pSupbook ? pSupbook->GetMacroName( nExtName ) : EMPTY_OUSTRING;
     831             : }
     832             : 
     833        4662 : const XclImpXti* XclImpLinkManagerImpl::GetXti( sal_uInt16 nXtiIndex ) const
     834             : {
     835        4662 :     return (nXtiIndex < maXtiList.size()) ? &maXtiList[ nXtiIndex ] : 0;
     836             : }
     837             : 
     838        2328 : const XclImpSupbook* XclImpLinkManagerImpl::GetSupbook( sal_uInt16 nXtiIndex ) const
     839             : {
     840        2328 :     if ( maSupbookList.empty() )
     841           0 :         return NULL;
     842        2328 :     const XclImpXti* pXti = GetXti( nXtiIndex );
     843        2328 :     if (!pXti || pXti->mnSupbook >= maSupbookList.size())
     844           0 :         return NULL;
     845        2328 :     return &(maSupbookList.at( pXti->mnSupbook ));
     846             : }
     847             : 
     848          88 : void XclImpLinkManagerImpl::LoadCachedValues()
     849             : {
     850             :     // Read all CRN records which can be accessed via XclImpSupbook, and store
     851             :     // the cached values to the external reference manager.
     852         180 :     for (XclImpSupbookList::iterator itSupbook = maSupbookList.begin(); itSupbook != maSupbookList.end(); ++itSupbook)
     853          92 :         itSupbook->LoadCachedValues();
     854          88 : }
     855             : 
     856         142 : XclImpLinkManager::XclImpLinkManager( const XclImpRoot& rRoot ) :
     857             :     XclImpRoot( rRoot ),
     858         142 :     mxImpl( new XclImpLinkManagerImpl( rRoot ) )
     859             : {
     860         142 : }
     861             : 
     862         284 : XclImpLinkManager::~XclImpLinkManager()
     863             : {
     864         284 : }
     865             : 
     866          88 : void XclImpLinkManager::ReadExternsheet( XclImpStream& rStrm )
     867             : {
     868          88 :     mxImpl->ReadExternsheet( rStrm );
     869          88 : }
     870             : 
     871          92 : void XclImpLinkManager::ReadSupbook( XclImpStream& rStrm )
     872             : {
     873          92 :     mxImpl->ReadSupbook( rStrm );
     874          92 : }
     875             : 
     876           4 : void XclImpLinkManager::ReadXct( XclImpStream& rStrm )
     877             : {
     878           4 :     mxImpl->ReadXct( rStrm );
     879           4 : }
     880             : 
     881           4 : void XclImpLinkManager::ReadCrn( XclImpStream& rStrm )
     882             : {
     883           4 :     mxImpl->ReadCrn( rStrm );
     884           4 : }
     885             : 
     886           0 : void XclImpLinkManager::ReadExternname( XclImpStream& rStrm, ExcelToSc* pFormulaConv )
     887             : {
     888           0 :     mxImpl->ReadExternname( rStrm, pFormulaConv );
     889           0 : }
     890             : 
     891        2318 : bool XclImpLinkManager::IsSelfRef( sal_uInt16 nXtiIndex ) const
     892             : {
     893        2318 :     return mxImpl->IsSelfRef( nXtiIndex );
     894             : }
     895             : 
     896        2334 : bool XclImpLinkManager::GetScTabRange(
     897             :         SCTAB& rnFirstScTab, SCTAB& rnLastScTab, sal_uInt16 nXtiIndex ) const
     898             : {
     899        2334 :     return mxImpl->GetScTabRange( rnFirstScTab, rnLastScTab, nXtiIndex );
     900             : }
     901             : 
     902           0 : const XclImpExtName* XclImpLinkManager::GetExternName( sal_uInt16 nXtiIndex, sal_uInt16 nExtName ) const
     903             : {
     904           0 :     return mxImpl->GetExternName( nXtiIndex, nExtName );
     905             : }
     906             : 
     907           4 : const OUString* XclImpLinkManager::GetSupbookUrl( sal_uInt16 nXtiIndex ) const
     908             : {
     909           4 :     return mxImpl->GetSupbookUrl(nXtiIndex);
     910             : }
     911             : 
     912           4 : const OUString& XclImpLinkManager::GetSupbookTabName( sal_uInt16 nXti,  sal_uInt16 nXtiTab ) const
     913             : {
     914           4 :     return mxImpl->GetSupbookTabName(nXti, nXtiTab);
     915             : }
     916             : 
     917           0 : bool XclImpLinkManager::GetLinkData( OUString& rApplic, OUString& rTopic, sal_uInt16 nXtiIndex ) const
     918             : {
     919           0 :     return mxImpl->GetLinkData( rApplic, rTopic, nXtiIndex );
     920             : }
     921             : 
     922           2 : const OUString& XclImpLinkManager::GetMacroName( sal_uInt16 nExtSheet, sal_uInt16 nExtName ) const
     923             : {
     924           2 :     return mxImpl->GetMacroName( nExtSheet, nExtName );
     925          48 : }
     926             : 
     927             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10