LCOV - code coverage report
Current view: top level - sc/source/ui/docshell - externalrefmgr.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 488 1349 36.2 %
Date: 2012-08-25 Functions: 66 156 42.3 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 465 2507 18.5 %

           Branch data     Line data    Source code
       1                 :            : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2                 :            : /*************************************************************************
       3                 :            :  *
       4                 :            :  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       5                 :            :  *
       6                 :            :  * Copyright 2000, 2010 Oracle and/or its affiliates.
       7                 :            :  *
       8                 :            :  * OpenOffice.org - a multi-platform office productivity suite
       9                 :            :  *
      10                 :            :  * This file is part of OpenOffice.org.
      11                 :            :  *
      12                 :            :  * OpenOffice.org is free software: you can redistribute it and/or modify
      13                 :            :  * it under the terms of the GNU Lesser General Public License version 3
      14                 :            :  * only, as published by the Free Software Foundation.
      15                 :            :  *
      16                 :            :  * OpenOffice.org is distributed in the hope that it will be useful,
      17                 :            :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      18                 :            :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      19                 :            :  * GNU Lesser General Public License version 3 for more details
      20                 :            :  * (a copy is included in the LICENSE file that accompanied this code).
      21                 :            :  *
      22                 :            :  * You should have received a copy of the GNU Lesser General Public License
      23                 :            :  * version 3 along with OpenOffice.org.  If not, see
      24                 :            :  * <http://www.openoffice.org/license.html>
      25                 :            :  * for a copy of the LGPLv3 License.
      26                 :            :  *
      27                 :            :  ************************************************************************/
      28                 :            : 
      29                 :            : #include "externalrefmgr.hxx"
      30                 :            : #include "document.hxx"
      31                 :            : #include "token.hxx"
      32                 :            : #include "tokenarray.hxx"
      33                 :            : #include "address.hxx"
      34                 :            : #include "tablink.hxx"
      35                 :            : #include "docsh.hxx"
      36                 :            : #include "scextopt.hxx"
      37                 :            : #include "rangenam.hxx"
      38                 :            : #include "cell.hxx"
      39                 :            : #include "viewdata.hxx"
      40                 :            : #include "tabvwsh.hxx"
      41                 :            : #include "sc.hrc"
      42                 :            : #include "globstr.hrc"
      43                 :            : 
      44                 :            : #include "sfx2/app.hxx"
      45                 :            : #include "sfx2/docfilt.hxx"
      46                 :            : #include "sfx2/docfile.hxx"
      47                 :            : #include "sfx2/fcontnr.hxx"
      48                 :            : #include "sfx2/sfxsids.hrc"
      49                 :            : #include "sfx2/objsh.hxx"
      50                 :            : #include "svl/broadcast.hxx"
      51                 :            : #include "svl/smplhint.hxx"
      52                 :            : #include "svl/itemset.hxx"
      53                 :            : #include "svl/stritem.hxx"
      54                 :            : #include "svl/urihelper.hxx"
      55                 :            : #include "svl/zformat.hxx"
      56                 :            : #include "sfx2/linkmgr.hxx"
      57                 :            : #include "tools/urlobj.hxx"
      58                 :            : #include "unotools/ucbhelper.hxx"
      59                 :            : #include "unotools/localfilehelper.hxx"
      60                 :            : #include "vcl/msgbox.hxx"
      61                 :            : 
      62                 :            : #include <memory>
      63                 :            : #include <algorithm>
      64                 :            : 
      65                 :            : #include <boost/scoped_ptr.hpp>
      66                 :            : 
      67                 :            : using ::std::auto_ptr;
      68                 :            : using ::com::sun::star::uno::Any;
      69                 :            : using ::rtl::OUString;
      70                 :            : using ::std::vector;
      71                 :            : using ::std::find;
      72                 :            : using ::std::find_if;
      73                 :            : using ::std::remove_if;
      74                 :            : using ::std::distance;
      75                 :            : using ::std::pair;
      76                 :            : using ::std::list;
      77                 :            : using ::std::unary_function;
      78                 :            : using namespace formula;
      79                 :            : 
      80                 :            : #define SRCDOC_LIFE_SPAN     6000       // 1 minute (in 100th of a sec)
      81                 :            : #define SRCDOC_SCAN_INTERVAL 1000*5     // every 5 seconds (in msec)
      82                 :            : 
      83                 :            : namespace {
      84                 :            : 
      85                 :          0 : class TabNameSearchPredicate : public unary_function<ScExternalRefCache::TableName, bool>
      86                 :            : {
      87                 :            : public:
      88                 :          0 :     explicit TabNameSearchPredicate(const OUString& rSearchName) :
      89                 :          0 :         maSearchName(ScGlobal::pCharClass->uppercase(rSearchName))
      90                 :            :     {
      91                 :          0 :     }
      92                 :            : 
      93                 :          0 :     bool operator()(const ScExternalRefCache::TableName& rTabNameSet) const
      94                 :            :     {
      95                 :            :         // Ok, I'm doing case insensitive search here.
      96                 :          0 :         return rTabNameSet.maUpperName.equals(maSearchName);
      97                 :            :     }
      98                 :            : 
      99                 :            : private:
     100                 :            :     OUString maSearchName;
     101                 :            : };
     102                 :            : 
     103                 :            : class FindSrcFileByName : public unary_function<ScExternalRefManager::SrcFileData, bool>
     104                 :            : {
     105                 :            : public:
     106                 :        122 :     FindSrcFileByName(const OUString& rMatchName) :
     107                 :        122 :         mrMatchName(rMatchName)
     108                 :            :     {
     109                 :        122 :     }
     110                 :            : 
     111                 :        111 :     bool operator()(const ScExternalRefManager::SrcFileData& rSrcData) const
     112                 :            :     {
     113                 :        111 :         return rSrcData.maFileName.equals(mrMatchName);
     114                 :            :     }
     115                 :            : 
     116                 :            : private:
     117                 :            :     const OUString& mrMatchName;
     118                 :            : };
     119                 :            : 
     120                 :            : class NotifyLinkListener : public unary_function<ScExternalRefManager::LinkListener*,  void>
     121                 :            : {
     122                 :            : public:
     123                 :          0 :     NotifyLinkListener(sal_uInt16 nFileId, ScExternalRefManager::LinkUpdateType eType) :
     124                 :          0 :         mnFileId(nFileId), meType(eType) {}
     125                 :            : 
     126                 :          0 :     NotifyLinkListener(const NotifyLinkListener& r) :
     127                 :          0 :         mnFileId(r.mnFileId), meType(r.meType) {}
     128                 :            : 
     129                 :          0 :     void operator() (ScExternalRefManager::LinkListener* p) const
     130                 :            :     {
     131                 :          0 :         p->notify(mnFileId, meType);
     132                 :          0 :     }
     133                 :            : private:
     134                 :            :     sal_uInt16 mnFileId;
     135                 :            :     ScExternalRefManager::LinkUpdateType meType;
     136                 :            : };
     137                 :            : 
     138                 :            : struct UpdateFormulaCell : public unary_function<ScFormulaCell*, void>
     139                 :            : {
     140                 :          0 :     void operator() (ScFormulaCell* pCell) const
     141                 :            :     {
     142                 :            :         // Check to make sure the cell really contains ocExternalRef.
     143                 :            :         // External names, external cell and range references all have a
     144                 :            :         // ocExternalRef token.
     145                 :          0 :         const ScTokenArray* pCode = pCell->GetCode();
     146         [ #  # ]:          0 :         if (!pCode->HasExternalRef())
     147                 :          0 :             return;
     148                 :            : 
     149                 :          0 :         ScTokenArray* pArray = pCell->GetCode();
     150         [ #  # ]:          0 :         if (pArray)
     151                 :            :             // Clear the error code, or a cell with error won't get re-compiled.
     152                 :          0 :             pArray->SetCodeError(0);
     153                 :            : 
     154                 :          0 :         pCell->SetCompile(true);
     155                 :          0 :         pCell->CompileTokenArray();
     156                 :          0 :         pCell->SetDirty();
     157                 :            :     }
     158                 :            : };
     159                 :            : 
     160                 :            : class RemoveFormulaCell : public unary_function<pair<const sal_uInt16, ScExternalRefManager::RefCellSet>, void>
     161                 :            : {
     162                 :            : public:
     163                 :        229 :     explicit RemoveFormulaCell(ScFormulaCell* p) : mpCell(p) {}
     164                 :         18 :     void operator() (pair<const sal_uInt16, ScExternalRefManager::RefCellSet>& r) const
     165                 :            :     {
     166                 :         18 :         r.second.erase(mpCell);
     167                 :         18 :     }
     168                 :            : private:
     169                 :            :     ScFormulaCell* mpCell;
     170                 :            : };
     171                 :            : 
     172                 :            : class ConvertFormulaToStatic : public unary_function<ScFormulaCell*, void>
     173                 :            : {
     174                 :            : public:
     175                 :          0 :     explicit ConvertFormulaToStatic(ScDocument* pDoc) : mpDoc(pDoc) {}
     176                 :          0 :     void operator() (ScFormulaCell* pCell) const
     177                 :            :     {
     178                 :          0 :         ScAddress aPos = pCell->aPos;
     179                 :            : 
     180                 :            :         // We don't check for empty cells because empty external cells are
     181                 :            :         // treated as having a value of 0.
     182                 :            : 
     183 [ #  # ][ #  # ]:          0 :         if (pCell->IsValue())
     184                 :            :         {
     185                 :            :             // Turn this into value cell.
     186         [ #  # ]:          0 :             double fVal = pCell->GetValue();
     187 [ #  # ][ #  # ]:          0 :             mpDoc->PutCell(aPos, new ScValueCell(fVal));
                 [ #  # ]
     188                 :            :         }
     189                 :            :         else
     190                 :            :         {
     191                 :            :             // string cell otherwise.
     192         [ #  # ]:          0 :             rtl::OUString aVal = pCell->GetString();
     193 [ #  # ][ #  # ]:          0 :             mpDoc->PutCell(aPos, new ScStringCell(aVal));
                 [ #  # ]
     194                 :            :         }
     195                 :          0 :     }
     196                 :            : private:
     197                 :            :     ScDocument* mpDoc;
     198                 :            : };
     199                 :            : 
     200                 :            : /**
     201                 :            :  * Check whether a named range contains an external reference to a
     202                 :            :  * particular document.
     203                 :            :  */
     204                 :          0 : bool hasRefsToSrcDoc(ScRangeData& rData, sal_uInt16 nFileId)
     205                 :            : {
     206                 :          0 :     ScTokenArray* pArray = rData.GetCode();
     207         [ #  # ]:          0 :     if (!pArray)
     208                 :          0 :         return false;
     209                 :            : 
     210                 :          0 :     pArray->Reset();
     211                 :          0 :     ScToken* p = static_cast<ScToken*>(pArray->GetNextReference());
     212         [ #  # ]:          0 :     for (; p; p = static_cast<ScToken*>(pArray->GetNextReference()))
     213                 :            :     {
     214         [ #  # ]:          0 :         if (!p->IsExternalRef())
     215                 :          0 :             continue;
     216                 :            : 
     217         [ #  # ]:          0 :         if (p->GetIndex() == nFileId)
     218                 :          0 :             return true;
     219                 :            :     }
     220                 :          0 :     return false;
     221                 :            : }
     222                 :            : 
     223                 :            : class EraseRangeByIterator : unary_function<ScRangeName::iterator, void>
     224                 :            : {
     225                 :            :     ScRangeName& mrRanges;
     226                 :            : public:
     227                 :          0 :     EraseRangeByIterator(ScRangeName& rRanges) : mrRanges(rRanges) {}
     228                 :          0 :     void operator() (const ScRangeName::iterator& itr)
     229                 :            :     {
     230                 :          0 :         mrRanges.erase(itr);
     231                 :          0 :     }
     232                 :            : };
     233                 :            : 
     234                 :            : /**
     235                 :            :  * Remove all named ranges that contain references to specified source
     236                 :            :  * document.
     237                 :            :  */
     238                 :          0 : void removeRangeNamesBySrcDoc(ScRangeName& rRanges, sal_uInt16 nFileId)
     239                 :            : {
     240 [ #  # ][ #  # ]:          0 :     ScRangeName::iterator itr = rRanges.begin(), itrEnd = rRanges.end();
     241         [ #  # ]:          0 :     vector<ScRangeName::iterator> v;
     242 [ #  # ][ #  # ]:          0 :     for (; itr != itrEnd; ++itr)
                 [ #  # ]
     243                 :            :     {
     244 [ #  # ][ #  # ]:          0 :         if (hasRefsToSrcDoc(*itr->second, nFileId))
                 [ #  # ]
     245         [ #  # ]:          0 :             v.push_back(itr);
     246                 :            :     }
     247         [ #  # ]:          0 :     for_each(v.begin(), v.end(), EraseRangeByIterator(rRanges));
     248                 :          0 : }
     249                 :            : 
     250                 :            : }
     251                 :            : 
     252                 :            : // ============================================================================
     253                 :            : 
     254                 :         12 : ScExternalRefCache::Table::Table()
     255 [ +  - ][ +  - ]:         12 :     : meReferenced( REFERENCED_MARKED )
     256                 :            :       // Prevent accidental data loss due to lack of knowledge.
     257                 :            : {
     258                 :         12 : }
     259                 :            : 
     260         [ +  - ]:          3 : ScExternalRefCache::Table::~Table()
     261                 :            : {
     262                 :          3 : }
     263                 :            : 
     264                 :          0 : void ScExternalRefCache::Table::setReferencedFlag( ScExternalRefCache::Table::ReferencedFlag eFlag )
     265                 :            : {
     266                 :          0 :     meReferenced = eFlag;
     267                 :          0 : }
     268                 :            : 
     269                 :          0 : void ScExternalRefCache::Table::setReferenced( bool bReferenced )
     270                 :            : {
     271         [ #  # ]:          0 :     if (meReferenced != REFERENCED_PERMANENT)
     272         [ #  # ]:          0 :         meReferenced = (bReferenced ? REFERENCED_MARKED : UNREFERENCED);
     273                 :          0 : }
     274                 :            : 
     275                 :          0 : ScExternalRefCache::Table::ReferencedFlag ScExternalRefCache::Table::getReferencedFlag() const
     276                 :            : {
     277                 :          0 :     return meReferenced;
     278                 :            : }
     279                 :            : 
     280                 :          0 : bool ScExternalRefCache::Table::isReferenced() const
     281                 :            : {
     282                 :          0 :     return meReferenced != UNREFERENCED;
     283                 :            : }
     284                 :            : 
     285                 :        189 : void ScExternalRefCache::Table::setCell(SCCOL nCol, SCROW nRow, TokenRef pToken, sal_uLong nFmtIndex, bool bSetCacheRange)
     286                 :            : {
     287                 :            :     using ::std::pair;
     288         [ +  - ]:        189 :     RowsDataType::iterator itrRow = maRows.find(nRow);
     289 [ +  - ][ +  + ]:        189 :     if (itrRow == maRows.end())
     290                 :            :     {
     291                 :            :         // This row does not exist yet.
     292                 :            :         pair<RowsDataType::iterator, bool> res = maRows.insert(
     293 [ +  - ][ +  - ]:         48 :             RowsDataType::value_type(nRow, RowDataType()));
         [ +  - ][ +  - ]
                 [ +  - ]
     294                 :            : 
     295         [ +  - ]:         48 :         if (!res.second)
     296                 :        189 :             return;
     297                 :            : 
     298                 :         48 :         itrRow = res.first;
     299                 :            :     }
     300                 :            : 
     301                 :            :     // Insert this token into the specified column location.  I don't need to
     302                 :            :     // check for existing data.  Just overwrite it.
     303         [ +  - ]:        189 :     RowDataType& rRow = itrRow->second;
     304         [ +  - ]:        189 :     ScExternalRefCache::Cell aCell;
     305         [ +  - ]:        189 :     aCell.mxToken = pToken;
     306                 :        189 :     aCell.mnFmtIndex = nFmtIndex;
     307 [ +  - ][ +  - ]:        189 :     rRow.insert(RowDataType::value_type(nCol, aCell));
                 [ +  - ]
     308         [ +  + ]:        189 :     if (bSetCacheRange)
     309 [ +  - ][ +  - ]:        189 :         setCachedCell(nCol, nRow);
     310                 :            : }
     311                 :            : 
     312                 :          0 : ScExternalRefCache::TokenRef ScExternalRefCache::Table::getCell(SCCOL nCol, SCROW nRow, sal_uInt32* pnFmtIndex) const
     313                 :            : {
     314         [ #  # ]:          0 :     RowsDataType::const_iterator itrTable = maRows.find(nRow);
     315 [ #  # ][ #  # ]:          0 :     if (itrTable == maRows.end())
     316                 :            :     {
     317                 :            :         // this table doesn't have the specified row.
     318         [ #  # ]:          0 :         return getEmptyOrNullToken(nCol, nRow);
     319                 :            :     }
     320                 :            : 
     321         [ #  # ]:          0 :     const RowDataType& rRowData = itrTable->second;
     322         [ #  # ]:          0 :     RowDataType::const_iterator itrRow = rRowData.find(nCol);
     323 [ #  # ][ #  # ]:          0 :     if (itrRow == rRowData.end())
     324                 :            :     {
     325                 :            :         // this row doesn't have the specified column.
     326         [ #  # ]:          0 :         return getEmptyOrNullToken(nCol, nRow);
     327                 :            :     }
     328                 :            : 
     329         [ #  # ]:          0 :     const Cell& rCell = itrRow->second;
     330         [ #  # ]:          0 :     if (pnFmtIndex)
     331                 :          0 :         *pnFmtIndex = rCell.mnFmtIndex;
     332                 :            : 
     333                 :          0 :     return rCell.mxToken;
     334                 :            : }
     335                 :            : 
     336                 :          0 : bool ScExternalRefCache::Table::hasRow( SCROW nRow ) const
     337                 :            : {
     338         [ #  # ]:          0 :     RowsDataType::const_iterator itrRow = maRows.find(nRow);
     339         [ #  # ]:          0 :     return itrRow != maRows.end();
     340                 :            : }
     341                 :            : 
     342                 :          6 : void ScExternalRefCache::Table::getAllRows(vector<SCROW>& rRows, SCROW nLow, SCROW nHigh) const
     343                 :            : {
     344         [ +  - ]:          6 :     vector<SCROW> aRows;
     345         [ +  - ]:          6 :     aRows.reserve(maRows.size());
     346 [ +  - ][ +  - ]:          6 :     RowsDataType::const_iterator itr = maRows.begin(), itrEnd = maRows.end();
     347         [ +  + ]:         33 :     for (; itr != itrEnd; ++itr)
     348 [ +  - ][ +  - ]:         27 :         if (nLow <= itr->first && itr->first <= nHigh)
         [ +  - ][ +  - ]
                 [ +  - ]
     349 [ +  - ][ +  - ]:         27 :             aRows.push_back(itr->first);
     350                 :            : 
     351                 :            :     // hash map is not ordered, so we need to explicitly sort it.
     352         [ +  - ]:          6 :     ::std::sort(aRows.begin(), aRows.end());
     353                 :          6 :     rRows.swap(aRows);
     354                 :          6 : }
     355                 :            : 
     356                 :          0 : ::std::pair< SCROW, SCROW > ScExternalRefCache::Table::getRowRange() const
     357                 :            : {
     358                 :          0 :     ::std::pair< SCROW, SCROW > aRange( 0, 0 );
     359         [ #  # ]:          0 :     if( !maRows.empty() )
     360                 :            :     {
     361                 :            :         // iterate over entire container (hash map is not sorted by key)
     362 [ #  # ][ #  # ]:          0 :         RowsDataType::const_iterator itr = maRows.begin(), itrEnd = maRows.end();
     363         [ #  # ]:          0 :         aRange.first = itr->first;
     364         [ #  # ]:          0 :         aRange.second = itr->first + 1;
     365         [ #  # ]:          0 :         while( ++itr != itrEnd )
     366                 :            :         {
     367 [ #  # ][ #  # ]:          0 :             if( itr->first < aRange.first )
     368         [ #  # ]:          0 :                 aRange.first = itr->first;
     369 [ #  # ][ #  # ]:          0 :             else if( itr->first >= aRange.second )
     370         [ #  # ]:          0 :                 aRange.second = itr->first + 1;
     371                 :            :         }
     372                 :            :     }
     373                 :          0 :     return aRange;
     374                 :            : }
     375                 :            : 
     376                 :         27 : void ScExternalRefCache::Table::getAllCols(SCROW nRow, vector<SCCOL>& rCols, SCCOL nLow, SCCOL nHigh) const
     377                 :            : {
     378         [ +  - ]:         27 :     RowsDataType::const_iterator itrRow = maRows.find(nRow);
     379 [ +  - ][ +  - ]:         27 :     if (itrRow == maRows.end())
     380                 :            :         // this table doesn't have the specified row.
     381                 :         27 :         return;
     382                 :            : 
     383         [ +  - ]:         27 :     const RowDataType& rRowData = itrRow->second;
     384         [ +  - ]:         27 :     vector<SCCOL> aCols;
     385         [ +  - ]:         27 :     aCols.reserve(rRowData.size());
     386 [ +  - ][ +  - ]:         27 :     RowDataType::const_iterator itrCol = rRowData.begin(), itrColEnd = rRowData.end();
     387         [ +  + ]:         81 :     for (; itrCol != itrColEnd; ++itrCol)
     388 [ +  - ][ +  - ]:         54 :         if (nLow <= itrCol->first && itrCol->first <= nHigh)
         [ +  - ][ +  - ]
                 [ +  - ]
     389 [ +  - ][ +  - ]:         54 :             aCols.push_back(itrCol->first);
     390                 :            : 
     391                 :            :     // hash map is not ordered, so we need to explicitly sort it.
     392         [ +  - ]:         27 :     ::std::sort(aCols.begin(), aCols.end());
     393                 :         27 :     rCols.swap(aCols);
     394                 :            : }
     395                 :            : 
     396                 :          0 : ::std::pair< SCCOL, SCCOL > ScExternalRefCache::Table::getColRange( SCROW nRow ) const
     397                 :            : {
     398                 :          0 :     ::std::pair< SCCOL, SCCOL > aRange( 0, 0 );
     399                 :            : 
     400         [ #  # ]:          0 :     RowsDataType::const_iterator itrRow = maRows.find( nRow );
     401 [ #  # ][ #  # ]:          0 :     if (itrRow == maRows.end())
     402                 :            :         // this table doesn't have the specified row.
     403                 :            :         return aRange;
     404                 :            : 
     405         [ #  # ]:          0 :     const RowDataType& rRowData = itrRow->second;
     406         [ #  # ]:          0 :     if( !rRowData.empty() )
     407                 :            :     {
     408                 :            :         // iterate over entire container (hash map is not sorted by key)
     409 [ #  # ][ #  # ]:          0 :         RowDataType::const_iterator itr = rRowData.begin(), itrEnd = rRowData.end();
     410         [ #  # ]:          0 :         aRange.first = itr->first;
     411         [ #  # ]:          0 :         aRange.second = itr->first + 1;
     412         [ #  # ]:          0 :         while( ++itr != itrEnd )
     413                 :            :         {
     414 [ #  # ][ #  # ]:          0 :             if( itr->first < aRange.first )
     415         [ #  # ]:          0 :                 aRange.first = itr->first;
     416 [ #  # ][ #  # ]:          0 :             else if( itr->first >= aRange.second )
     417         [ #  # ]:          0 :                 aRange.second = itr->first + 1;
     418                 :            :         }
     419                 :            :     }
     420                 :            :     return aRange;
     421                 :            : }
     422                 :            : 
     423                 :          0 : void ScExternalRefCache::Table::getAllNumberFormats(vector<sal_uInt32>& rNumFmts) const
     424                 :            : {
     425 [ #  # ][ #  # ]:          0 :     RowsDataType::const_iterator itrRow = maRows.begin(), itrRowEnd = maRows.end();
     426         [ #  # ]:          0 :     for (; itrRow != itrRowEnd; ++itrRow)
     427                 :            :     {
     428         [ #  # ]:          0 :         const RowDataType& rRowData = itrRow->second;
     429 [ #  # ][ #  # ]:          0 :         RowDataType::const_iterator itrCol = rRowData.begin(), itrColEnd = rRowData.end();
     430         [ #  # ]:          0 :         for (; itrCol != itrColEnd; ++itrCol)
     431                 :            :         {
     432         [ #  # ]:          0 :             const Cell& rCell = itrCol->second;
     433         [ #  # ]:          0 :             rNumFmts.push_back(rCell.mnFmtIndex);
     434                 :            :         }
     435                 :            :     }
     436                 :          0 : }
     437                 :            : 
     438                 :          0 : bool ScExternalRefCache::Table::isRangeCached(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2) const
     439                 :            : {
     440         [ #  # ]:          0 :     return maCachedRanges.In(ScRange(nCol1, nRow1, 0, nCol2, nRow2, 0));
     441                 :            : }
     442                 :            : 
     443                 :        270 : void ScExternalRefCache::Table::setCachedCell(SCCOL nCol, SCROW nRow)
     444                 :            : {
     445                 :        270 :     setCachedCellRange(nCol, nRow, nCol, nRow);
     446                 :        270 : }
     447                 :            : 
     448                 :        288 : void ScExternalRefCache::Table::setCachedCellRange(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2)
     449                 :            : {
     450                 :        288 :     ScRange aRange(nCol1, nRow1, 0, nCol2, nRow2, 0);
     451 [ +  + ][ +  - ]:        288 :     if ( maCachedRanges.empty() )
     452         [ +  - ]:         12 :         maCachedRanges.Append(aRange);
     453                 :            :     else
     454         [ +  - ]:        276 :         maCachedRanges.Join(aRange);
     455                 :            : 
     456         [ +  - ]:        288 :     String aStr;
     457 [ +  - ][ +  - ]:        288 :     maCachedRanges.Format(aStr, SCA_VALID);
     458                 :        288 : }
     459                 :            : 
     460                 :          0 : void ScExternalRefCache::Table::setWholeTableCached()
     461                 :            : {
     462                 :          0 :     setCachedCellRange(0, 0, MAXCOL, MAXROW);
     463                 :          0 : }
     464                 :            : 
     465                 :          0 : bool ScExternalRefCache::Table::isInCachedRanges(SCCOL nCol, SCROW nRow) const
     466                 :            : {
     467         [ #  # ]:          0 :     return maCachedRanges.In(ScRange(nCol, nRow, 0, nCol, nRow, 0));
     468                 :            : }
     469                 :            : 
     470                 :          0 : ScExternalRefCache::TokenRef ScExternalRefCache::Table::getEmptyOrNullToken(
     471                 :            :     SCCOL nCol, SCROW nRow) const
     472                 :            : {
     473         [ #  # ]:          0 :     if (isInCachedRanges(nCol, nRow))
     474                 :            :     {
     475 [ #  # ][ #  # ]:          0 :         TokenRef p(new ScEmptyCellToken(false, false));
     476         [ #  # ]:          0 :         return p;
     477                 :            :     }
     478                 :          0 :     return TokenRef();
     479                 :            : }
     480                 :            : 
     481                 :            : // ----------------------------------------------------------------------------
     482                 :            : 
     483                 :         24 : ScExternalRefCache::TableName::TableName(const OUString& rUpper, const OUString& rReal) :
     484                 :         24 :     maUpperName(rUpper), maRealName(rReal)
     485                 :            : {
     486                 :         24 : }
     487                 :            : 
     488                 :            : // ----------------------------------------------------------------------------
     489                 :            : 
     490                 :        129 : ScExternalRefCache::CellFormat::CellFormat() :
     491                 :        129 :     mbIsSet(false), mnType(NUMBERFORMAT_ALL), mnIndex(0)
     492                 :            : {
     493                 :        129 : }
     494                 :            : 
     495                 :            : // ----------------------------------------------------------------------------
     496                 :            : 
     497         [ +  - ]:        275 : ScExternalRefCache::ScExternalRefCache()
     498                 :            : {
     499                 :        275 : }
     500         [ +  - ]:        262 : ScExternalRefCache::~ScExternalRefCache()
     501                 :            : {
     502                 :        262 : }
     503                 :            : 
     504                 :         87 : const OUString* ScExternalRefCache::getRealTableName(sal_uInt16 nFileId, const OUString& rTabName) const
     505                 :            : {
     506         [ +  - ]:         87 :     DocDataType::const_iterator itrDoc = maDocs.find(nFileId);
     507 [ -  + ][ +  - ]:         87 :     if (itrDoc == maDocs.end())
     508                 :            :     {
     509                 :            :         // specified document is not cached.
     510                 :          0 :         return NULL;
     511                 :            :     }
     512                 :            : 
     513         [ +  - ]:         87 :     const DocItem& rDoc = itrDoc->second;
     514                 :            :     TableNameIndexMap::const_iterator itrTabId = rDoc.maTableNameIndex.find(
     515 [ +  - ][ +  - ]:         87 :         ScGlobal::pCharClass->uppercase(rTabName));
     516 [ -  + ][ +  - ]:         87 :     if (itrTabId == rDoc.maTableNameIndex.end())
     517                 :            :     {
     518                 :            :         // the specified table is not in cache.
     519                 :          0 :         return NULL;
     520                 :            :     }
     521                 :            : 
     522         [ +  - ]:         87 :     return &rDoc.maTableNames[itrTabId->second].maRealName;
     523                 :            : }
     524                 :            : 
     525                 :          0 : const OUString* ScExternalRefCache::getRealRangeName(sal_uInt16 nFileId, const OUString& rRangeName) const
     526                 :            : {
     527         [ #  # ]:          0 :     DocDataType::const_iterator itrDoc = maDocs.find(nFileId);
     528 [ #  # ][ #  # ]:          0 :     if (itrDoc == maDocs.end())
     529                 :            :     {
     530                 :            :         // specified document is not cached.
     531                 :          0 :         return NULL;
     532                 :            :     }
     533                 :            : 
     534         [ #  # ]:          0 :     const DocItem& rDoc = itrDoc->second;
     535                 :            :     NamePairMap::const_iterator itr = rDoc.maRealRangeNameMap.find(
     536 [ #  # ][ #  # ]:          0 :         ScGlobal::pCharClass->uppercase(rRangeName));
     537 [ #  # ][ #  # ]:          0 :     if (itr == rDoc.maRealRangeNameMap.end())
     538                 :            :         // range name not found.
     539                 :          0 :         return NULL;
     540                 :            : 
     541         [ #  # ]:          0 :     return &itr->second;
     542                 :            : }
     543                 :            : 
     544                 :          0 : ScExternalRefCache::TokenRef ScExternalRefCache::getCellData(
     545                 :            :     sal_uInt16 nFileId, const OUString& rTabName, SCCOL nCol, SCROW nRow, sal_uInt32* pnFmtIndex)
     546                 :            : {
     547         [ #  # ]:          0 :     DocDataType::const_iterator itrDoc = maDocs.find(nFileId);
     548 [ #  # ][ #  # ]:          0 :     if (itrDoc == maDocs.end())
     549                 :            :     {
     550                 :            :         // specified document is not cached.
     551                 :          0 :         return TokenRef();
     552                 :            :     }
     553                 :            : 
     554         [ #  # ]:          0 :     const DocItem& rDoc = itrDoc->second;
     555                 :            :     TableNameIndexMap::const_iterator itrTabId = rDoc.maTableNameIndex.find(
     556 [ #  # ][ #  # ]:          0 :         ScGlobal::pCharClass->uppercase(rTabName));
     557 [ #  # ][ #  # ]:          0 :     if (itrTabId == rDoc.maTableNameIndex.end())
     558                 :            :     {
     559                 :            :         // the specified table is not in cache.
     560                 :          0 :         return TokenRef();
     561                 :            :     }
     562                 :            : 
     563         [ #  # ]:          0 :     const TableTypeRef& pTableData = rDoc.maTables[itrTabId->second];
     564         [ #  # ]:          0 :     if (!pTableData.get())
     565                 :            :     {
     566                 :            :         // the table data is not instantiated yet.
     567                 :          0 :         return TokenRef();
     568                 :            :     }
     569                 :            : 
     570         [ #  # ]:          0 :     return pTableData->getCell(nCol, nRow, pnFmtIndex);
     571                 :            : }
     572                 :            : 
     573                 :          0 : ScExternalRefCache::TokenArrayRef ScExternalRefCache::getCellRangeData(
     574                 :            :     sal_uInt16 nFileId, const OUString& rTabName, const ScRange& rRange)
     575                 :            : {
     576         [ #  # ]:          0 :     DocDataType::iterator itrDoc = maDocs.find(nFileId);
     577 [ #  # ][ #  # ]:          0 :     if (itrDoc == maDocs.end())
     578                 :            :         // specified document is not cached.
     579         [ #  # ]:          0 :         return TokenArrayRef();
     580                 :            : 
     581         [ #  # ]:          0 :     DocItem& rDoc = itrDoc->second;
     582                 :            : 
     583                 :            :     TableNameIndexMap::iterator itrTabId = rDoc.maTableNameIndex.find(
     584 [ #  # ][ #  # ]:          0 :         ScGlobal::pCharClass->uppercase(rTabName));
     585 [ #  # ][ #  # ]:          0 :     if (itrTabId == rDoc.maTableNameIndex.end())
     586                 :            :         // the specified table is not in cache.
     587         [ #  # ]:          0 :         return TokenArrayRef();
     588                 :            : 
     589                 :          0 :     const ScAddress& s = rRange.aStart;
     590                 :          0 :     const ScAddress& e = rRange.aEnd;
     591                 :            : 
     592                 :          0 :     SCTAB nTab1 = s.Tab(), nTab2 = e.Tab();
     593                 :          0 :     SCCOL nCol1 = s.Col(), nCol2 = e.Col();
     594                 :          0 :     SCROW nRow1 = s.Row(), nRow2 = e.Row();
     595                 :            : 
     596                 :            :     // Make sure I have all the tables cached.
     597         [ #  # ]:          0 :     size_t nTabFirstId = itrTabId->second;
     598                 :          0 :     size_t nTabLastId  = nTabFirstId + nTab2 - nTab1;
     599         [ #  # ]:          0 :     if (nTabLastId >= rDoc.maTables.size())
     600                 :            :         // not all tables are cached.
     601         [ #  # ]:          0 :         return TokenArrayRef();
     602                 :            : 
     603                 :          0 :     ScRange aCacheRange( nCol1, nRow1, static_cast<SCTAB>(nTabFirstId), nCol2, nRow2, static_cast<SCTAB>(nTabLastId));
     604                 :            : 
     605         [ #  # ]:          0 :     RangeArrayMap::const_iterator itrRange = rDoc.maRangeArrays.find( aCacheRange);
     606 [ #  # ][ #  # ]:          0 :     if (itrRange != rDoc.maRangeArrays.end())
     607                 :            :         // Cache hit!
     608 [ #  # ][ #  # ]:          0 :         return itrRange->second;
     609                 :            : 
     610                 :          0 :     ::boost::scoped_ptr<ScRange> pNewRange;
     611         [ #  # ]:          0 :     TokenArrayRef pArray;
     612                 :          0 :     bool bFirstTab = true;
     613         [ #  # ]:          0 :     for (size_t nTab = nTabFirstId; nTab <= nTabLastId; ++nTab)
     614                 :            :     {
     615         [ #  # ]:          0 :         TableTypeRef pTab = rDoc.maTables[nTab];
     616         [ #  # ]:          0 :         if (!pTab.get())
     617         [ #  # ]:          0 :             return TokenArrayRef();
     618                 :            : 
     619                 :          0 :         SCCOL nDataCol1 = nCol1, nDataCol2 = nCol2;
     620                 :          0 :         SCROW nDataRow1 = nRow1, nDataRow2 = nRow2;
     621                 :            : 
     622 [ #  # ][ #  # ]:          0 :         if (!pTab->isRangeCached(nDataCol1, nDataRow1, nDataCol2, nDataRow2))
     623                 :            :         {
     624                 :            :             // specified range is not entirely within cached ranges.
     625         [ #  # ]:          0 :             return TokenArrayRef();
     626                 :            :         }
     627                 :            : 
     628                 :            :         ScMatrixRef xMat = new ScMatrix(
     629 [ #  # ][ #  # ]:          0 :             static_cast<SCSIZE>(nDataCol2-nDataCol1+1), static_cast<SCSIZE>(nDataRow2-nDataRow1+1));
     630                 :            : 
     631                 :            :         // Only fill non-empty cells, for better performance.
     632         [ #  # ]:          0 :         vector<SCROW> aRows;
     633         [ #  # ]:          0 :         pTab->getAllRows(aRows, nDataRow1, nDataRow2);
     634 [ #  # ][ #  # ]:          0 :         for (vector<SCROW>::const_iterator itr = aRows.begin(), itrEnd = aRows.end(); itr != itrEnd; ++itr)
         [ #  # ][ #  # ]
                 [ #  # ]
     635                 :            :         {
     636         [ #  # ]:          0 :             SCROW nRow = *itr;
     637         [ #  # ]:          0 :             vector<SCCOL> aCols;
     638         [ #  # ]:          0 :             pTab->getAllCols(nRow, aCols, nDataCol1, nDataCol2);
     639 [ #  # ][ #  # ]:          0 :             for (vector<SCCOL>::const_iterator itrCol = aCols.begin(), itrColEnd = aCols.end(); itrCol != itrColEnd; ++itrCol)
         [ #  # ][ #  # ]
                 [ #  # ]
     640                 :            :             {
     641         [ #  # ]:          0 :                 SCCOL nCol = *itrCol;
     642         [ #  # ]:          0 :                 TokenRef pToken = pTab->getCell(nCol, nRow);
     643         [ #  # ]:          0 :                 if (!pToken)
     644                 :            :                     // This should never happen!
     645         [ #  # ]:          0 :                     return TokenArrayRef();
     646                 :            : 
     647                 :          0 :                 SCSIZE nC = nCol - nDataCol1, nR = nRow - nDataRow1;
     648      [ #  #  # ]:          0 :                 switch (pToken->GetType())
     649                 :            :                 {
     650                 :            :                     case svDouble:
     651 [ #  # ][ #  # ]:          0 :                         xMat->PutDouble(pToken->GetDouble(), nC, nR);
     652                 :          0 :                     break;
     653                 :            :                     case svString:
     654 [ #  # ][ #  # ]:          0 :                         xMat->PutString(pToken->GetString(), nC, nR);
                 [ #  # ]
     655                 :          0 :                     break;
     656                 :            :                     default:
     657                 :            :                         ;
     658                 :            :                 }
     659 [ #  # ][ #  # ]:          0 :             }
     660         [ #  # ]:          0 :         }
     661                 :            : 
     662         [ #  # ]:          0 :         if (!bFirstTab)
     663         [ #  # ]:          0 :             pArray->AddOpCode(ocSep);
     664                 :            : 
     665 [ #  # ][ #  # ]:          0 :         ScMatrixToken aToken(xMat);
     666         [ #  # ]:          0 :         if (!pArray)
     667 [ #  # ][ #  # ]:          0 :             pArray.reset(new ScTokenArray);
                 [ #  # ]
     668         [ #  # ]:          0 :         pArray->AddToken(aToken);
     669                 :            : 
     670                 :          0 :         bFirstTab = false;
     671                 :            : 
     672         [ #  # ]:          0 :         if (!pNewRange)
     673 [ #  # ][ #  # ]:          0 :             pNewRange.reset(new ScRange(nDataCol1, nDataRow1, 0, nDataCol2, nDataRow2, 0));
     674                 :            :         else
     675         [ #  # ]:          0 :             pNewRange->ExtendTo(ScRange(nDataCol1, nDataRow1, 0, nDataCol2, nDataRow2, 0));
     676 [ #  # ][ #  # ]:          0 :     }
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     677                 :            : 
     678         [ #  # ]:          0 :     if (pNewRange)
     679 [ #  # ][ #  # ]:          0 :         rDoc.maRangeArrays.insert( RangeArrayMap::value_type(*pNewRange, pArray));
                 [ #  # ]
     680 [ #  # ][ #  # ]:          0 :     return pArray;
                 [ #  # ]
     681                 :            : }
     682                 :            : 
     683                 :          0 : ScExternalRefCache::TokenArrayRef ScExternalRefCache::getRangeNameTokens(sal_uInt16 nFileId, const OUString& rName)
     684                 :            : {
     685         [ #  # ]:          0 :     DocItem* pDoc = getDocItem(nFileId);
     686         [ #  # ]:          0 :     if (!pDoc)
     687         [ #  # ]:          0 :         return TokenArrayRef();
     688                 :            : 
     689                 :          0 :     RangeNameMap& rMap = pDoc->maRangeNames;
     690                 :            :     RangeNameMap::const_iterator itr = rMap.find(
     691 [ #  # ][ #  # ]:          0 :         ScGlobal::pCharClass->uppercase(rName));
     692 [ #  # ][ #  # ]:          0 :     if (itr == rMap.end())
     693         [ #  # ]:          0 :         return TokenArrayRef();
     694                 :            : 
     695 [ #  # ][ #  # ]:          0 :     return itr->second;
     696                 :            : }
     697                 :            : 
     698                 :          0 : void ScExternalRefCache::setRangeNameTokens(sal_uInt16 nFileId, const OUString& rName, TokenArrayRef pArray)
     699                 :            : {
     700         [ #  # ]:          0 :     DocItem* pDoc = getDocItem(nFileId);
     701         [ #  # ]:          0 :     if (!pDoc)
     702                 :          0 :         return;
     703                 :            : 
     704 [ #  # ][ #  # ]:          0 :     String aUpperName = ScGlobal::pCharClass->uppercase(rName);
     705                 :          0 :     RangeNameMap& rMap = pDoc->maRangeNames;
     706 [ #  # ][ #  # ]:          0 :     rMap.insert(RangeNameMap::value_type(aUpperName, pArray));
                 [ #  # ]
     707 [ #  # ][ #  # ]:          0 :     pDoc->maRealRangeNameMap.insert(NamePairMap::value_type(aUpperName, rName));
                 [ #  # ]
     708                 :            : }
     709                 :            : 
     710                 :        135 : void ScExternalRefCache::setCellData(sal_uInt16 nFileId, const OUString& rTabName, SCCOL nCol, SCROW nRow,
     711                 :            :                                      TokenRef pToken, sal_uLong nFmtIndex)
     712                 :            : {
     713 [ +  - ][ +  - ]:        135 :     if (!isDocInitialized(nFileId))
     714                 :            :         return;
     715                 :            : 
     716                 :            :     using ::std::pair;
     717         [ +  - ]:        135 :     DocItem* pDocItem = getDocItem(nFileId);
     718         [ +  - ]:        135 :     if (!pDocItem)
     719                 :            :         return;
     720                 :            : 
     721                 :        135 :     DocItem& rDoc = *pDocItem;
     722                 :            : 
     723                 :            :     // See if the table by this name already exists.
     724                 :            :     TableNameIndexMap::iterator itrTabName = rDoc.maTableNameIndex.find(
     725 [ +  - ][ +  - ]:        135 :         ScGlobal::pCharClass->uppercase(rTabName));
     726 [ +  - ][ +  - ]:        135 :     if (itrTabName == rDoc.maTableNameIndex.end())
     727                 :            :         // Table not found.  Maybe the table name or the file id is wrong ???
     728                 :            :         return;
     729                 :            : 
     730         [ +  - ]:        135 :     TableTypeRef& pTableData = rDoc.maTables[itrTabName->second];
     731         [ +  + ]:        135 :     if (!pTableData.get())
     732 [ +  - ][ +  - ]:         12 :         pTableData.reset(new Table);
                 [ +  - ]
     733                 :            : 
     734 [ +  - ][ +  - ]:        135 :     pTableData->setCell(nCol, nRow, pToken, nFmtIndex);
     735         [ +  - ]:        135 :     pTableData->setCachedCell(nCol, nRow);
     736                 :            : }
     737                 :            : 
     738                 :         18 : void ScExternalRefCache::setCellRangeData(sal_uInt16 nFileId, const ScRange& rRange, const vector<SingleRangeData>& rData,
     739                 :            :                                           const TokenArrayRef& pArray)
     740                 :            : {
     741                 :            :     using ::std::pair;
     742 [ +  - ][ +  - ]:         18 :     if (rData.empty() || !isDocInitialized(nFileId))
         [ -  + ][ +  - ]
     743                 :            :         // nothing to cache
     744                 :            :         return;
     745                 :            : 
     746                 :            :     // First, get the document item for the given file ID.
     747         [ +  - ]:         18 :     DocItem* pDocItem = getDocItem(nFileId);
     748         [ +  - ]:         18 :     if (!pDocItem)
     749                 :            :         return;
     750                 :            : 
     751                 :         18 :     DocItem& rDoc = *pDocItem;
     752                 :            : 
     753                 :            :     // Now, find the table position of the first table to cache.
     754 [ +  - ][ +  - ]:         18 :     const String& rFirstTabName = rData.front().maTableName;
     755                 :            :     TableNameIndexMap::iterator itrTabName = rDoc.maTableNameIndex.find(
     756 [ +  - ][ +  - ]:         18 :         ScGlobal::pCharClass->uppercase(rFirstTabName));
                 [ +  - ]
     757 [ -  + ][ +  - ]:         18 :     if (itrTabName == rDoc.maTableNameIndex.end())
     758                 :            :     {
     759                 :            :         // table index not found.
     760                 :            :         return;
     761                 :            :     }
     762                 :            : 
     763         [ +  - ]:         18 :     size_t nTabFirstId = itrTabName->second;
     764                 :         18 :     SCROW nRow1 = rRange.aStart.Row(), nRow2 = rRange.aEnd.Row();
     765                 :         18 :     SCCOL nCol1 = rRange.aStart.Col(), nCol2 = rRange.aEnd.Col();
     766                 :         18 :     vector<SingleRangeData>::const_iterator itrDataBeg = rData.begin(), itrDataEnd = rData.end();
     767 [ +  - ][ +  + ]:         36 :     for (vector<SingleRangeData>::const_iterator itrData = itrDataBeg; itrData != itrDataEnd; ++itrData)
     768                 :            :     {
     769         [ +  - ]:         18 :         size_t i = nTabFirstId + ::std::distance(itrDataBeg, itrData);
     770                 :         18 :         TableTypeRef& pTabData = rDoc.maTables[i];
     771         [ -  + ]:         18 :         if (!pTabData.get())
     772 [ #  # ][ #  # ]:          0 :             pTabData.reset(new Table);
                 [ #  # ]
     773                 :            : 
     774         [ +  + ]:         81 :         for (SCROW nRow = nRow1; nRow <= nRow2; ++nRow)
     775                 :            :         {
     776         [ +  + ]:        126 :             for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol)
     777                 :            :             {
     778                 :         63 :                 SCSIZE nC = nCol - nCol1, nR = nRow - nRow1;
     779                 :         63 :                 TokenRef pToken;
     780                 :         63 :                 const ScMatrixRef& pMat = itrData->mpRangeData;
     781 [ +  + ][ +  - ]:         63 :                 if (pMat->IsEmpty(nC, nR))
     782                 :            :                     // Don't cache empty cells.
     783                 :          9 :                     continue;
     784                 :            : 
     785 [ +  - ][ +  - ]:         54 :                 if (pMat->IsValue(nC, nR))
     786 [ +  - ][ +  - ]:         54 :                     pToken.reset(new formula::FormulaDoubleToken(pMat->GetDouble(nC, nR)));
         [ +  - ][ +  - ]
     787 [ #  # ][ #  # ]:          0 :                 else if (pMat->IsString(nC, nR))
     788 [ #  # ][ #  # ]:          0 :                     pToken.reset(new formula::FormulaStringToken(pMat->GetString(nC, nR)));
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     789                 :            : 
     790         [ +  - ]:         54 :                 if (pToken)
     791                 :            :                     // Don't mark this cell 'cached' here, for better performance.
     792 [ +  - ][ +  - ]:         54 :                     pTabData->setCell(nCol, nRow, pToken, 0, false);
     793 [ +  - ][ +  + ]:         63 :             }
     794                 :            :         }
     795                 :            :         // Mark the whole range 'cached'.
     796         [ +  - ]:         18 :         pTabData->setCachedCellRange(nCol1, nRow1, nCol2, nRow2);
     797                 :            :     }
     798                 :            : 
     799                 :         18 :     size_t nTabLastId = nTabFirstId + rRange.aEnd.Tab() - rRange.aStart.Tab();
     800                 :         18 :     ScRange aCacheRange( nCol1, nRow1, static_cast<SCTAB>(nTabFirstId), nCol2, nRow2, static_cast<SCTAB>(nTabLastId));
     801                 :            : 
     802 [ +  - ][ +  - ]:         18 :     rDoc.maRangeArrays.insert( RangeArrayMap::value_type( aCacheRange, pArray));
         [ +  - ][ +  - ]
                 [ +  - ]
     803                 :            : }
     804                 :            : 
     805                 :        327 : bool ScExternalRefCache::isDocInitialized(sal_uInt16 nFileId)
     806                 :            : {
     807                 :        327 :     DocItem* pDoc = getDocItem(nFileId);
     808         [ -  + ]:        327 :     if (!pDoc)
     809                 :          0 :         return false;
     810                 :            : 
     811                 :        327 :     return pDoc->mbInitFromSource;
     812                 :            : }
     813                 :            : 
     814                 :         33 : static bool lcl_getTableDataIndex(const ScExternalRefCache::TableNameIndexMap& rMap, const String& rName, size_t& rIndex)
     815                 :            : {
     816 [ +  - ][ +  - ]:         33 :     ScExternalRefCache::TableNameIndexMap::const_iterator itr = rMap.find(rName);
     817 [ +  + ][ +  - ]:         33 :     if (itr == rMap.end())
     818                 :         24 :         return false;
     819                 :            : 
     820         [ +  - ]:          9 :     rIndex = itr->second;
     821                 :         33 :     return true;
     822                 :            : }
     823                 :            : 
     824                 :          9 : void ScExternalRefCache::initializeDoc(sal_uInt16 nFileId, const vector<OUString>& rTabNames)
     825                 :            : {
     826         [ +  - ]:          9 :     DocItem* pDoc = getDocItem(nFileId);
     827         [ +  - ]:          9 :     if (!pDoc)
     828                 :          9 :         return;
     829                 :            : 
     830                 :          9 :     size_t n = rTabNames.size();
     831                 :            : 
     832                 :            :     // table name list - the list must include all table names in the source
     833                 :            :     // document and only to be populated when loading the source document, not
     834                 :            :     // when loading cached data from, say, Excel XCT/CRN records.
     835         [ +  - ]:          9 :     vector<TableName> aNewTabNames;
     836         [ +  - ]:          9 :     aNewTabNames.reserve(n);
     837 [ +  - ][ +  + ]:         33 :     for (vector<OUString>::const_iterator itr = rTabNames.begin(), itrEnd = rTabNames.end();
     838                 :            :           itr != itrEnd; ++itr)
     839                 :            :     {
     840         [ +  - ]:         24 :         TableName aNameItem(ScGlobal::pCharClass->uppercase(*itr), *itr);
     841         [ +  - ]:         24 :         aNewTabNames.push_back(aNameItem);
     842                 :         24 :     }
     843                 :          9 :     pDoc->maTableNames.swap(aNewTabNames);
     844                 :            : 
     845                 :            :     // data tables - preserve any existing data that may have been set during
     846                 :            :     // file import.
     847         [ +  - ]:          9 :     vector<TableTypeRef> aNewTables(n);
     848         [ +  + ]:         33 :     for (size_t i = 0; i < n; ++i)
     849                 :            :     {
     850                 :            :         size_t nIndex;
     851 [ +  - ][ +  - ]:         24 :         if (lcl_getTableDataIndex(pDoc->maTableNameIndex, pDoc->maTableNames[i].maUpperName, nIndex))
         [ +  - ][ -  + ]
     852                 :            :         {
     853         [ #  # ]:          0 :             aNewTables[i] = pDoc->maTables[nIndex];
     854                 :            :         }
     855                 :            :     }
     856                 :          9 :     pDoc->maTables.swap(aNewTables);
     857                 :            : 
     858                 :            :     // name index map
     859         [ +  - ]:          9 :     TableNameIndexMap aNewNameIndex;
     860         [ +  + ]:         33 :     for (size_t i = 0; i < n; ++i)
     861         [ +  - ]:         24 :         aNewNameIndex.insert(TableNameIndexMap::value_type(pDoc->maTableNames[i].maUpperName, i));
     862         [ +  - ]:          9 :     pDoc->maTableNameIndex.swap(aNewNameIndex);
     863                 :            : 
     864         [ +  - ]:          9 :     pDoc->mbInitFromSource = true;
     865                 :            : }
     866                 :            : 
     867                 :          0 : String ScExternalRefCache::getTableName(sal_uInt16 nFileId, size_t nCacheId) const
     868                 :            : {
     869         [ #  # ]:          0 :     if( DocItem* pDoc = getDocItem( nFileId ) )
     870         [ #  # ]:          0 :         if( nCacheId < pDoc->maTableNames.size() )
     871                 :          0 :             return pDoc->maTableNames[ nCacheId ].maRealName;
     872                 :          0 :     return EMPTY_STRING;
     873                 :            : }
     874                 :            : 
     875                 :          3 : void ScExternalRefCache::getAllTableNames(sal_uInt16 nFileId, vector<OUString>& rTabNames) const
     876                 :            : {
     877                 :          3 :     rTabNames.clear();
     878                 :          3 :     DocItem* pDoc = getDocItem(nFileId);
     879         [ -  + ]:          3 :     if (!pDoc)
     880                 :          3 :         return;
     881                 :            : 
     882                 :          3 :     size_t n = pDoc->maTableNames.size();
     883                 :          3 :     rTabNames.reserve(n);
     884 [ +  - ][ +  - ]:         15 :     for (vector<TableName>::const_iterator itr = pDoc->maTableNames.begin(), itrEnd = pDoc->maTableNames.end();
         [ +  + ][ +  - ]
     885                 :            :           itr != itrEnd; ++itr)
     886         [ +  - ]:         12 :         rTabNames.push_back(itr->maRealName);
     887                 :            : }
     888                 :            : 
     889                 :          0 : SCsTAB ScExternalRefCache::getTabSpan( sal_uInt16 nFileId, const OUString& rStartTabName, const OUString& rEndTabName ) const
     890                 :            : {
     891         [ #  # ]:          0 :     DocItem* pDoc = getDocItem(nFileId);
     892         [ #  # ]:          0 :     if (!pDoc)
     893                 :          0 :         return -1;
     894                 :            : 
     895         [ #  # ]:          0 :     vector<TableName>::const_iterator itrBeg = pDoc->maTableNames.begin();
     896         [ #  # ]:          0 :     vector<TableName>::const_iterator itrEnd = pDoc->maTableNames.end();
     897                 :            : 
     898                 :            :     vector<TableName>::const_iterator itrStartTab = ::std::find_if( itrBeg, itrEnd,
     899 [ #  # ][ #  # ]:          0 :             TabNameSearchPredicate( rStartTabName));
     900 [ #  # ][ #  # ]:          0 :     if (itrStartTab == itrEnd)
     901                 :          0 :         return -1;
     902                 :            : 
     903                 :            :     vector<TableName>::const_iterator itrEndTab = ::std::find_if( itrBeg, itrEnd,
     904 [ #  # ][ #  # ]:          0 :             TabNameSearchPredicate( rEndTabName));
     905 [ #  # ][ #  # ]:          0 :     if (itrEndTab == itrEnd)
     906                 :          0 :         return 0;
     907                 :            : 
     908         [ #  # ]:          0 :     size_t nStartDist = ::std::distance( itrBeg, itrStartTab);
     909         [ #  # ]:          0 :     size_t nEndDist = ::std::distance( itrBeg, itrEndTab);
     910         [ #  # ]:          0 :     return nStartDist <= nEndDist ? static_cast<SCsTAB>(nEndDist - nStartDist + 1) : -static_cast<SCsTAB>(nStartDist - nEndDist + 1);
     911                 :            : }
     912                 :            : 
     913                 :          0 : void ScExternalRefCache::getAllNumberFormats(vector<sal_uInt32>& rNumFmts) const
     914                 :            : {
     915                 :            :     using ::std::sort;
     916                 :            :     using ::std::unique;
     917                 :            : 
     918         [ #  # ]:          0 :     vector<sal_uInt32> aNumFmts;
     919 [ #  # ][ #  # ]:          0 :     for (DocDataType::const_iterator itrDoc = maDocs.begin(), itrDocEnd = maDocs.end();
                 [ #  # ]
     920                 :            :           itrDoc != itrDocEnd; ++itrDoc)
     921                 :            :     {
     922         [ #  # ]:          0 :         const vector<TableTypeRef>& rTables = itrDoc->second.maTables;
     923 [ #  # ][ #  # ]:          0 :         for (vector<TableTypeRef>::const_iterator itrTab = rTables.begin(), itrTabEnd = rTables.end();
     924                 :            :               itrTab != itrTabEnd; ++itrTab)
     925                 :            :         {
     926         [ #  # ]:          0 :             TableTypeRef pTab = *itrTab;
     927         [ #  # ]:          0 :             if (!pTab)
     928                 :          0 :                 continue;
     929                 :            : 
     930 [ #  # ][ #  # ]:          0 :             pTab->getAllNumberFormats(aNumFmts);
     931         [ #  # ]:          0 :         }
     932                 :            :     }
     933                 :            : 
     934                 :            :     // remove duplicates.
     935         [ #  # ]:          0 :     sort(aNumFmts.begin(), aNumFmts.end());
     936 [ #  # ][ #  # ]:          0 :     aNumFmts.erase(unique(aNumFmts.begin(), aNumFmts.end()), aNumFmts.end());
     937                 :          0 :     rNumFmts.swap(aNumFmts);
     938                 :          0 : }
     939                 :            : 
     940                 :          0 : bool ScExternalRefCache::hasCacheTable(sal_uInt16 nFileId, const OUString& rTabName) const
     941                 :            : {
     942         [ #  # ]:          0 :     DocItem* pDoc = getDocItem(nFileId);
     943         [ #  # ]:          0 :     if (!pDoc)
     944                 :          0 :         return false;
     945                 :            : 
     946 [ #  # ][ #  # ]:          0 :     String aUpperName = ScGlobal::pCharClass->uppercase(rTabName);
     947 [ #  # ][ #  # ]:          0 :     vector<TableName>::const_iterator itrBeg = pDoc->maTableNames.begin(), itrEnd = pDoc->maTableNames.end();
     948                 :            :     vector<TableName>::const_iterator itr = ::std::find_if(
     949 [ #  # ][ #  # ]:          0 :         itrBeg, itrEnd, TabNameSearchPredicate(aUpperName));
                 [ #  # ]
     950                 :            : 
     951 [ #  # ][ #  # ]:          0 :     return itr != itrEnd;
     952                 :            : }
     953                 :            : 
     954                 :          0 : size_t ScExternalRefCache::getCacheTableCount(sal_uInt16 nFileId) const
     955                 :            : {
     956                 :          0 :     DocItem* pDoc = getDocItem(nFileId);
     957         [ #  # ]:          0 :     return pDoc ? pDoc->maTables.size() : 0;
     958                 :            : }
     959                 :            : 
     960                 :          0 : bool ScExternalRefCache::setCacheDocReferenced( sal_uInt16 nFileId )
     961                 :            : {
     962                 :          0 :     DocItem* pDocItem = getDocItem(nFileId);
     963         [ #  # ]:          0 :     if (!pDocItem)
     964                 :          0 :         return areAllCacheTablesReferenced();
     965                 :            : 
     966 [ #  # ][ #  # ]:          0 :     for (::std::vector<TableTypeRef>::iterator itrTab = pDocItem->maTables.begin();
     967                 :          0 :             itrTab != pDocItem->maTables.end(); ++itrTab)
     968                 :            :     {
     969         [ #  # ]:          0 :         if ((*itrTab).get())
     970                 :          0 :             (*itrTab)->setReferenced( true);
     971                 :            :     }
     972                 :          0 :     addCacheDocToReferenced( nFileId);
     973                 :          0 :     return areAllCacheTablesReferenced();
     974                 :            : }
     975                 :            : 
     976                 :          0 : bool ScExternalRefCache::setCacheTableReferenced( sal_uInt16 nFileId, const OUString& rTabName, size_t nSheets, bool bPermanent )
     977                 :            : {
     978                 :          0 :     DocItem* pDoc = getDocItem(nFileId);
     979         [ #  # ]:          0 :     if (pDoc)
     980                 :            :     {
     981                 :          0 :         size_t nIndex = 0;
     982 [ #  # ][ #  # ]:          0 :         String aTabNameUpper = ScGlobal::pCharClass->uppercase( rTabName);
     983 [ #  # ][ #  # ]:          0 :         if (lcl_getTableDataIndex( pDoc->maTableNameIndex, aTabNameUpper, nIndex))
     984                 :            :         {
     985         [ #  # ]:          0 :             size_t nStop = ::std::min( nIndex + nSheets, pDoc->maTables.size());
     986         [ #  # ]:          0 :             for (size_t i = nIndex; i < nStop; ++i)
     987                 :            :             {
     988         [ #  # ]:          0 :                 TableTypeRef pTab = pDoc->maTables[i];
     989         [ #  # ]:          0 :                 if (pTab.get())
     990                 :            :                 {
     991                 :            :                     Table::ReferencedFlag eNewFlag = (bPermanent ?
     992                 :            :                             Table::REFERENCED_PERMANENT :
     993         [ #  # ]:          0 :                             Table::REFERENCED_MARKED);
     994                 :          0 :                     Table::ReferencedFlag eOldFlag = pTab->getReferencedFlag();
     995 [ #  # ][ #  # ]:          0 :                     if (eOldFlag != Table::REFERENCED_PERMANENT && eNewFlag != eOldFlag)
     996                 :            :                     {
     997                 :          0 :                         pTab->setReferencedFlag( eNewFlag);
     998         [ #  # ]:          0 :                         addCacheTableToReferenced( nFileId, i);
     999                 :            :                     }
    1000                 :            :                 }
    1001         [ #  # ]:          0 :             }
    1002         [ #  # ]:          0 :         }
    1003                 :            :     }
    1004                 :          0 :     return areAllCacheTablesReferenced();
    1005                 :            : }
    1006                 :            : 
    1007                 :          0 : void ScExternalRefCache::setAllCacheTableReferencedStati( bool bReferenced )
    1008                 :            : {
    1009         [ #  # ]:          0 :     if (bReferenced)
    1010                 :            :     {
    1011                 :          0 :         maReferenced.reset(0);
    1012 [ #  # ][ #  # ]:          0 :         for (DocDataType::iterator itrDoc = maDocs.begin(); itrDoc != maDocs.end(); ++itrDoc)
                 [ #  # ]
    1013                 :            :         {
    1014         [ #  # ]:          0 :             ScExternalRefCache::DocItem& rDocItem = (*itrDoc).second;
    1015 [ #  # ][ #  # ]:          0 :             for (::std::vector<TableTypeRef>::iterator itrTab = rDocItem.maTables.begin();
    1016                 :          0 :                     itrTab != rDocItem.maTables.end(); ++itrTab)
    1017                 :            :             {
    1018         [ #  # ]:          0 :                 if ((*itrTab).get())
    1019                 :          0 :                     (*itrTab)->setReferenced( true);
    1020                 :            :             }
    1021                 :            :         }
    1022                 :            :     }
    1023                 :            :     else
    1024                 :            :     {
    1025                 :          0 :         size_t nDocs = 0;
    1026 [ #  # ][ #  # ]:          0 :         for (DocDataType::const_iterator itrDoc = maDocs.begin(); itrDoc != maDocs.end(); ++itrDoc)
                 [ #  # ]
    1027                 :            :         {
    1028 [ #  # ][ #  # ]:          0 :             if (nDocs <= (*itrDoc).first)
    1029         [ #  # ]:          0 :                 nDocs  = (*itrDoc).first + 1;
    1030                 :            :         }
    1031                 :          0 :         maReferenced.reset( nDocs);
    1032                 :            : 
    1033 [ #  # ][ #  # ]:          0 :         for (DocDataType::iterator itrDoc = maDocs.begin(); itrDoc != maDocs.end(); ++itrDoc)
                 [ #  # ]
    1034                 :            :         {
    1035         [ #  # ]:          0 :             ScExternalRefCache::DocItem& rDocItem = (*itrDoc).second;
    1036         [ #  # ]:          0 :             sal_uInt16 nFileId = (*itrDoc).first;
    1037                 :          0 :             size_t nTables = rDocItem.maTables.size();
    1038                 :          0 :             ReferencedStatus::DocReferenced & rDocReferenced = maReferenced.maDocs[nFileId];
    1039                 :            :             // All referenced => non-existing tables evaluate as completed.
    1040         [ #  # ]:          0 :             rDocReferenced.maTables.resize( nTables, true);
    1041         [ #  # ]:          0 :             for (size_t i=0; i < nTables; ++i)
    1042                 :            :             {
    1043                 :          0 :                 TableTypeRef & xTab = rDocItem.maTables[i];
    1044         [ #  # ]:          0 :                 if (xTab.get())
    1045                 :            :                 {
    1046         [ #  # ]:          0 :                     if (xTab->getReferencedFlag() == Table::REFERENCED_PERMANENT)
    1047         [ #  # ]:          0 :                         addCacheTableToReferenced( nFileId, i);
    1048                 :            :                     else
    1049                 :            :                     {
    1050                 :          0 :                         xTab->setReferencedFlag( Table::UNREFERENCED);
    1051         [ #  # ]:          0 :                         rDocReferenced.maTables[i] = false;
    1052                 :          0 :                         rDocReferenced.mbAllTablesReferenced = false;
    1053                 :            :                         // An addCacheTableToReferenced() actually may have
    1054                 :            :                         // resulted in mbAllReferenced been set. Clear it.
    1055                 :          0 :                         maReferenced.mbAllReferenced = false;
    1056                 :            :                     }
    1057                 :            :                 }
    1058                 :            :             }
    1059                 :            :         }
    1060                 :            :     }
    1061                 :          0 : }
    1062                 :            : 
    1063                 :          0 : void ScExternalRefCache::addCacheTableToReferenced( sal_uInt16 nFileId, size_t nIndex )
    1064                 :            : {
    1065         [ #  # ]:          0 :     if (nFileId >= maReferenced.maDocs.size())
    1066                 :          0 :         return;
    1067                 :            : 
    1068                 :          0 :     ::std::vector<bool> & rTables = maReferenced.maDocs[nFileId].maTables;
    1069                 :          0 :     size_t nTables = rTables.size();
    1070         [ #  # ]:          0 :     if (nIndex >= nTables)
    1071                 :          0 :         return;
    1072                 :            : 
    1073         [ #  # ]:          0 :     if (!rTables[nIndex])
    1074                 :            :     {
    1075                 :          0 :         rTables[nIndex] = true;
    1076                 :          0 :         size_t i = 0;
    1077 [ #  # ][ #  # ]:          0 :         while (i < nTables && rTables[i])
         [ #  # ][ #  # ]
           [ #  #  #  # ]
    1078                 :          0 :             ++i;
    1079         [ #  # ]:          0 :         if (i == nTables)
    1080                 :            :         {
    1081                 :          0 :             maReferenced.maDocs[nFileId].mbAllTablesReferenced = true;
    1082                 :          0 :             maReferenced.checkAllDocs();
    1083                 :            :         }
    1084                 :            :     }
    1085                 :            : }
    1086                 :            : 
    1087                 :          0 : void ScExternalRefCache::addCacheDocToReferenced( sal_uInt16 nFileId )
    1088                 :            : {
    1089         [ #  # ]:          0 :     if (nFileId >= maReferenced.maDocs.size())
    1090                 :          0 :         return;
    1091                 :            : 
    1092         [ #  # ]:          0 :     if (!maReferenced.maDocs[nFileId].mbAllTablesReferenced)
    1093                 :            :     {
    1094                 :          0 :         ::std::vector<bool> & rTables = maReferenced.maDocs[nFileId].maTables;
    1095                 :          0 :         size_t nSize = rTables.size();
    1096         [ #  # ]:          0 :         for (size_t i=0; i < nSize; ++i)
    1097                 :          0 :             rTables[i] = true;
    1098                 :          0 :         maReferenced.maDocs[nFileId].mbAllTablesReferenced = true;
    1099                 :          0 :         maReferenced.checkAllDocs();
    1100                 :            :     }
    1101                 :            : }
    1102                 :            : 
    1103                 :          0 : bool ScExternalRefCache::areAllCacheTablesReferenced() const
    1104                 :            : {
    1105                 :          0 :     return maReferenced.mbAllReferenced;
    1106                 :            : }
    1107                 :            : 
    1108                 :        275 : ScExternalRefCache::ReferencedStatus::ReferencedStatus() :
    1109                 :        275 :     mbAllReferenced(false)
    1110                 :            : {
    1111         [ +  - ]:        275 :     reset(0);
    1112                 :        275 : }
    1113                 :            : 
    1114                 :        275 : void ScExternalRefCache::ReferencedStatus::reset( size_t nDocs )
    1115                 :            : {
    1116         [ -  + ]:        275 :     if (nDocs)
    1117                 :            :     {
    1118                 :          0 :         mbAllReferenced = false;
    1119         [ #  # ]:          0 :         DocReferencedVec aRefs( nDocs);
    1120                 :          0 :         maDocs.swap( aRefs);
    1121                 :            :     }
    1122                 :            :     else
    1123                 :            :     {
    1124                 :        275 :         mbAllReferenced = true;
    1125         [ +  - ]:        275 :         DocReferencedVec aRefs;
    1126                 :        275 :         maDocs.swap( aRefs);
    1127                 :            :     }
    1128                 :        275 : }
    1129                 :            : 
    1130                 :          0 : void ScExternalRefCache::ReferencedStatus::checkAllDocs()
    1131                 :            : {
    1132 [ #  # ][ #  # ]:          0 :     for (DocReferencedVec::const_iterator itr = maDocs.begin(); itr != maDocs.end(); ++itr)
                 [ #  # ]
    1133                 :            :     {
    1134         [ #  # ]:          0 :         if (!(*itr).mbAllTablesReferenced)
    1135                 :          0 :             return;
    1136                 :            :     }
    1137                 :          0 :     mbAllReferenced = true;
    1138                 :            : }
    1139                 :            : 
    1140                 :          0 : ScExternalRefCache::TableTypeRef ScExternalRefCache::getCacheTable(sal_uInt16 nFileId, size_t nTabIndex) const
    1141                 :            : {
    1142                 :          0 :     DocItem* pDoc = getDocItem(nFileId);
    1143 [ #  # ][ #  # ]:          0 :     if (!pDoc || nTabIndex >= pDoc->maTables.size())
                 [ #  # ]
    1144                 :          0 :         return TableTypeRef();
    1145                 :            : 
    1146                 :          0 :     return pDoc->maTables[nTabIndex];
    1147                 :            : }
    1148                 :            : 
    1149                 :          9 : ScExternalRefCache::TableTypeRef ScExternalRefCache::getCacheTable(sal_uInt16 nFileId, const OUString& rTabName, bool bCreateNew, size_t* pnIndex)
    1150                 :            : {
    1151                 :            :     // In API, the index is transported as cached sheet ID of type sal_Int32 in
    1152                 :            :     // sheet::SingleReference.Sheet or sheet::ComplexReference.Reference1.Sheet
    1153                 :            :     // in a sheet::FormulaToken, choose a sensible value for N/A. Effectively
    1154                 :            :     // being 0xffffffff
    1155                 :          9 :     const size_t nNotAvailable = static_cast<size_t>( static_cast<sal_Int32>( -1));
    1156                 :            : 
    1157         [ +  - ]:          9 :     DocItem* pDoc = getDocItem(nFileId);
    1158         [ -  + ]:          9 :     if (!pDoc)
    1159                 :            :     {
    1160         [ #  # ]:          0 :         if (pnIndex) *pnIndex = nNotAvailable;
    1161         [ #  # ]:          0 :         return TableTypeRef();
    1162                 :            :     }
    1163                 :            : 
    1164                 :          9 :     DocItem& rDoc = *pDoc;
    1165                 :            : 
    1166                 :            :     size_t nIndex;
    1167 [ +  - ][ +  - ]:          9 :     String aTabNameUpper = ScGlobal::pCharClass->uppercase(rTabName);
    1168 [ +  - ][ +  - ]:          9 :     if (lcl_getTableDataIndex(rDoc.maTableNameIndex, aTabNameUpper, nIndex))
    1169                 :            :     {
    1170                 :            :         // specified table found.
    1171         [ -  + ]:          9 :         if( pnIndex ) *pnIndex = nIndex;
    1172 [ -  + ][ #  # ]:          9 :         if (bCreateNew && !rDoc.maTables[nIndex])
                 [ -  + ]
    1173 [ #  # ][ #  # ]:          0 :             rDoc.maTables[nIndex].reset(new Table);
                 [ #  # ]
    1174                 :            : 
    1175         [ +  - ]:          9 :         return rDoc.maTables[nIndex];
    1176                 :            :     }
    1177                 :            : 
    1178         [ #  # ]:          0 :     if (!bCreateNew)
    1179                 :            :     {
    1180         [ #  # ]:          0 :         if (pnIndex) *pnIndex = nNotAvailable;
    1181         [ #  # ]:          0 :         return TableTypeRef();
    1182                 :            :     }
    1183                 :            : 
    1184                 :            :     // Specified table doesn't exist yet.  Create one.
    1185                 :          0 :     nIndex = rDoc.maTables.size();
    1186         [ #  # ]:          0 :     if( pnIndex ) *pnIndex = nIndex;
    1187 [ #  # ][ #  # ]:          0 :     TableTypeRef pTab(new Table);
                 [ #  # ]
    1188         [ #  # ]:          0 :     rDoc.maTables.push_back(pTab);
    1189 [ #  # ][ #  # ]:          0 :     rDoc.maTableNames.push_back(TableName(aTabNameUpper, rTabName));
    1190                 :            :     rDoc.maTableNameIndex.insert(
    1191 [ #  # ][ #  # ]:          0 :         TableNameIndexMap::value_type(aTabNameUpper, nIndex));
    1192 [ #  # ][ +  - ]:          9 :     return pTab;
                 [ #  # ]
    1193                 :            : }
    1194                 :            : 
    1195                 :          3 : void ScExternalRefCache::clearCache(sal_uInt16 nFileId)
    1196                 :            : {
    1197                 :          3 :     maDocs.erase(nFileId);
    1198                 :          3 : }
    1199                 :            : 
    1200                 :        501 : ScExternalRefCache::DocItem* ScExternalRefCache::getDocItem(sal_uInt16 nFileId) const
    1201                 :            : {
    1202                 :            :     using ::std::pair;
    1203         [ +  - ]:        501 :     DocDataType::iterator itrDoc = maDocs.find(nFileId);
    1204 [ +  - ][ +  + ]:        501 :     if (itrDoc == maDocs.end())
    1205                 :            :     {
    1206                 :            :         // specified document is not cached.
    1207                 :            :         pair<DocDataType::iterator, bool> res = maDocs.insert(
    1208 [ +  - ][ +  - ]:          9 :                 DocDataType::value_type(nFileId, DocItem()));
         [ +  - ][ +  - ]
                 [ +  - ]
    1209                 :            : 
    1210         [ -  + ]:          9 :         if (!res.second)
    1211                 :            :             // insertion failed.
    1212                 :          0 :             return NULL;
    1213                 :            : 
    1214                 :          9 :         itrDoc = res.first;
    1215                 :            :     }
    1216                 :            : 
    1217         [ +  - ]:        501 :     return &itrDoc->second;
    1218                 :            : }
    1219                 :            : 
    1220                 :            : // ============================================================================
    1221                 :            : 
    1222                 :          6 : ScExternalRefLink::ScExternalRefLink(ScDocument* pDoc, sal_uInt16 nFileId, const String& rFilter) :
    1223                 :            :     ::sfx2::SvBaseLink(::sfx2::LINKUPDATE_ONCALL, FORMAT_FILE),
    1224                 :            :     mnFileId(nFileId),
    1225                 :            :     maFilterName(rFilter),
    1226                 :            :     mpDoc(pDoc),
    1227         [ +  - ]:          6 :     mbDoRefresh(true)
    1228                 :            : {
    1229                 :          6 : }
    1230                 :            : 
    1231         [ #  # ]:          0 : ScExternalRefLink::~ScExternalRefLink()
    1232                 :            : {
    1233         [ #  # ]:          0 : }
    1234                 :            : 
    1235                 :          0 : void ScExternalRefLink::Closed()
    1236                 :            : {
    1237                 :          0 :     ScExternalRefManager* pMgr = mpDoc->GetExternalRefManager();
    1238                 :          0 :     pMgr->breakLink(mnFileId);
    1239                 :          0 : }
    1240                 :            : 
    1241                 :          6 : ::sfx2::SvBaseLink::UpdateResult ScExternalRefLink::DataChanged(const String& /*rMimeType*/, const Any& /*rValue*/)
    1242                 :            : {
    1243         [ +  - ]:          6 :     if (!mbDoRefresh)
    1244                 :          6 :         return SUCCESS;
    1245                 :            : 
    1246                 :          0 :     rtl::OUString aFile, aFilter;
    1247 [ #  # ][ #  # ]:          0 :     mpDoc->GetLinkManager()->GetDisplayNames(this, NULL, &aFile, NULL, &aFilter);
    1248         [ #  # ]:          0 :     ScExternalRefManager* pMgr = mpDoc->GetExternalRefManager();
    1249                 :            : 
    1250 [ #  # ][ #  # ]:          0 :     if (!pMgr->isFileLoadable(aFile))
    1251                 :          0 :         return ERROR_GENERAL;
    1252                 :            : 
    1253         [ #  # ]:          0 :     const OUString* pCurFile = pMgr->getExternalFileName(mnFileId);
    1254         [ #  # ]:          0 :     if (!pCurFile)
    1255                 :          0 :         return ERROR_GENERAL;
    1256                 :            : 
    1257         [ #  # ]:          0 :     if (pCurFile->equals(aFile))
    1258                 :            :     {
    1259                 :            :         // Refresh the current source document.
    1260         [ #  # ]:          0 :         pMgr->refreshNames(mnFileId);
    1261                 :            :     }
    1262                 :            :     else
    1263                 :            :     {
    1264                 :            :         // The source document has changed.
    1265         [ #  # ]:          0 :         ScDocShell* pDocShell = ScDocShell::GetViewData()->GetDocShell();
    1266         [ #  # ]:          0 :         ScDocShellModificator aMod(*pDocShell);
    1267         [ #  # ]:          0 :         pMgr->switchSrcFile(mnFileId, aFile, aFilter);
    1268         [ #  # ]:          0 :         maFilterName = aFilter;
    1269 [ #  # ][ #  # ]:          0 :         aMod.SetDocumentModified();
    1270                 :            :     }
    1271                 :            : 
    1272                 :          6 :     return SUCCESS;
    1273                 :            : }
    1274                 :            : 
    1275                 :          0 : void ScExternalRefLink::Edit(Window* pParent, const Link& /*rEndEditHdl*/)
    1276                 :            : {
    1277         [ #  # ]:          0 :     SvBaseLink::Edit(pParent, LINK(this, ScExternalRefLink, ExternalRefEndEditHdl));
    1278                 :          0 : }
    1279                 :            : 
    1280                 :         12 : void ScExternalRefLink::SetDoReferesh(bool b)
    1281                 :            : {
    1282                 :         12 :     mbDoRefresh = b;
    1283                 :         12 : }
    1284                 :            : 
    1285                 :          0 : IMPL_LINK_NOARG(ScExternalRefLink, ExternalRefEndEditHdl)
    1286                 :            : {
    1287                 :          0 :     return 0;
    1288                 :            : }
    1289                 :            : 
    1290                 :            : // ============================================================================
    1291                 :            : 
    1292                 :        156 : static FormulaToken* lcl_convertToToken(ScBaseCell* pCell)
    1293                 :            : {
    1294 [ +  + ][ -  + ]:        156 :     if (!pCell || pCell->HasEmptyData())
                 [ +  + ]
    1295                 :            :     {
    1296 [ -  + ][ #  # ]:         21 :         bool bInherited = (pCell && pCell->GetCellType() == CELLTYPE_FORMULA);
    1297         [ +  - ]:         21 :         return new ScEmptyCellToken( bInherited, false);
    1298                 :            :     }
    1299                 :            : 
    1300   [ -  +  +  -  :        135 :     switch (pCell->GetCellType())
                      - ]
    1301                 :            :     {
    1302                 :            :         case CELLTYPE_EDIT:
    1303                 :            :         {
    1304         [ #  # ]:          0 :             rtl::OUString aStr = static_cast<ScEditCell*>(pCell)->GetString();
    1305 [ #  # ][ #  # ]:          0 :             return new formula::FormulaStringToken(aStr);
         [ #  # ][ #  # ]
    1306                 :            :         }
    1307                 :            :         case CELLTYPE_STRING:
    1308                 :            :         {
    1309                 :         78 :             rtl::OUString aStr = static_cast<ScStringCell*>(pCell)->GetString();
    1310 [ +  - ][ +  - ]:         78 :             return new formula::FormulaStringToken(aStr);
         [ +  - ][ +  - ]
    1311                 :            :         }
    1312                 :            :         case CELLTYPE_VALUE:
    1313                 :            :         {
    1314                 :         57 :             double fVal = static_cast<ScValueCell*>(pCell)->GetValue();
    1315         [ +  - ]:         57 :             return new formula::FormulaDoubleToken(fVal);
    1316                 :            :         }
    1317                 :            :         case CELLTYPE_FORMULA:
    1318                 :            :         {
    1319         [ #  # ]:          0 :             ScFormulaCell* pFCell = static_cast<ScFormulaCell*>(pCell);
    1320                 :          0 :             sal_uInt16 nError = pFCell->GetErrCode();
    1321         [ #  # ]:          0 :             if (nError)
    1322         [ #  # ]:          0 :                 return new FormulaErrorToken( nError);
    1323         [ #  # ]:          0 :             else if (pFCell->IsValue())
    1324                 :            :             {
    1325                 :          0 :                 double fVal = pFCell->GetValue();
    1326         [ #  # ]:          0 :                 return new formula::FormulaDoubleToken(fVal);
    1327                 :            :             }
    1328                 :            :             else
    1329                 :            :             {
    1330         [ #  # ]:          0 :                 rtl::OUString aStr = pFCell->GetString();
    1331 [ #  # ][ #  # ]:          0 :                 return new formula::FormulaStringToken(aStr);
         [ #  # ][ #  # ]
    1332                 :            :             }
    1333                 :            :         }
    1334                 :            :         default:
    1335                 :            :             OSL_FAIL("attempted to convert an unknown cell type.");
    1336                 :            :     }
    1337                 :            : 
    1338                 :        156 :     return NULL;
    1339                 :            : }
    1340                 :            : 
    1341                 :         18 : static ScTokenArray* lcl_convertToTokenArray(const ScDocument* pSrcDoc, ScRange& rRange,
    1342                 :            :                                              vector<ScExternalRefCache::SingleRangeData>& rCacheData)
    1343                 :            : {
    1344                 :         18 :     ScAddress& s = rRange.aStart;
    1345                 :         18 :     ScAddress& e = rRange.aEnd;
    1346                 :            : 
    1347                 :         18 :     SCTAB nTab1 = s.Tab(), nTab2 = e.Tab();
    1348                 :         18 :     SCCOL nCol1 = s.Col(), nCol2 = e.Col();
    1349                 :         18 :     SCROW nRow1 = s.Row(), nRow2 = e.Row();
    1350                 :            : 
    1351         [ -  + ]:         18 :     if (nTab2 != nTab1)
    1352                 :            :         // For now, we don't support multi-sheet ranges intentionally because
    1353                 :            :         // we don't have a way to express them in a single token.  In the
    1354                 :            :         // future we can introduce a new stack variable type svMatrixList with
    1355                 :            :         // a new token type that can store a 3D matrix value and convert a 3D
    1356                 :            :         // range to it.
    1357                 :          0 :         return NULL;
    1358                 :            : 
    1359                 :         18 :     ::boost::scoped_ptr<ScRange> pUsedRange;
    1360                 :            : 
    1361                 :            :     SAL_WNODEPRECATED_DECLARATIONS_PUSH
    1362 [ +  - ][ +  - ]:         18 :     auto_ptr<ScTokenArray> pArray(new ScTokenArray);
    1363                 :            :     SAL_WNODEPRECATED_DECLARATIONS_POP
    1364                 :         18 :     bool bFirstTab = true;
    1365                 :            :     vector<ScExternalRefCache::SingleRangeData>::iterator
    1366                 :         18 :         itrCache = rCacheData.begin(), itrCacheEnd = rCacheData.end();
    1367                 :            : 
    1368 [ +  + ][ +  - ]:         36 :     for (SCTAB nTab = nTab1; nTab <= nTab2 && itrCache != itrCacheEnd; ++nTab, ++itrCache)
         [ +  - ][ +  + ]
    1369                 :            :     {
    1370                 :            :         // Only loop within the data area.
    1371                 :         18 :         SCCOL nDataCol1 = nCol1, nDataCol2 = nCol2;
    1372                 :         18 :         SCROW nDataRow1 = nRow1, nDataRow2 = nRow2;
    1373                 :            :         bool bShrunk;
    1374 [ +  - ][ -  + ]:         18 :         if (!pSrcDoc->ShrinkToUsedDataArea( bShrunk, nTab, nDataCol1, nDataRow1, nDataCol2, nDataRow2, false))
    1375                 :            :             // no data within specified range.
    1376                 :          0 :             continue;
    1377                 :            : 
    1378         [ -  + ]:         18 :         if (pUsedRange.get())
    1379                 :            :             // Make sure the used area only grows, not shrinks.
    1380         [ #  # ]:          0 :             pUsedRange->ExtendTo(ScRange(nDataCol1, nDataRow1, 0, nDataCol2, nDataRow2, 0));
    1381                 :            :         else
    1382 [ +  - ][ +  - ]:         18 :             pUsedRange.reset(new ScRange(nDataCol1, nDataRow1, 0, nDataCol2, nDataRow2, 0));
    1383                 :            : 
    1384                 :            :         ScMatrixRef xMat = new ScMatrix(
    1385 [ +  - ][ +  - ]:         18 :             static_cast<SCSIZE>(nCol2-nCol1+1), static_cast<SCSIZE>(nRow2-nRow1+1));
    1386                 :            : 
    1387         [ +  + ]:         36 :         for (SCCOL nCol = nDataCol1; nCol <= nDataCol2; ++nCol)
    1388                 :            :         {
    1389         [ +  + ]:         81 :             for (SCROW nRow = nDataRow1; nRow <= nDataRow2; ++nRow)
    1390                 :            :             {
    1391                 :         63 :                 SCSIZE nC = nCol - nCol1, nR = nRow - nRow1;
    1392                 :            :                 ScBaseCell* pCell;
    1393         [ +  - ]:         63 :                 pSrcDoc->GetCell(nCol, nRow, nTab, pCell);
    1394 [ +  - ][ +  - ]:         63 :                 if (!pCell || pCell->HasEmptyData())
         [ -  + ][ -  + ]
    1395                 :            :                     // Skip empty cells.  Matrix's default values are empty elements.
    1396                 :          0 :                     continue;
    1397                 :            : 
    1398   [ -  -  +  -  :         63 :                 switch (pCell->GetCellType())
                      - ]
    1399                 :            :                 {
    1400                 :            :                     case CELLTYPE_EDIT:
    1401                 :            :                     {
    1402         [ #  # ]:          0 :                         rtl::OUString aStr = static_cast<ScEditCell*>(pCell)->GetString();
    1403         [ #  # ]:          0 :                         xMat->PutString(aStr, nC, nR);
    1404                 :            :                     }
    1405                 :          0 :                     break;
    1406                 :            :                     case CELLTYPE_STRING:
    1407                 :            :                     {
    1408                 :          0 :                         rtl::OUString aStr = static_cast<ScStringCell*>(pCell)->GetString();
    1409         [ #  # ]:          0 :                         xMat->PutString(aStr, nC, nR);
    1410                 :            :                     }
    1411                 :          0 :                     break;
    1412                 :            :                     case CELLTYPE_VALUE:
    1413                 :            :                     {
    1414                 :         63 :                         double fVal = static_cast<ScValueCell*>(pCell)->GetValue();
    1415         [ +  - ]:         63 :                         xMat->PutDouble(fVal, nC, nR);
    1416                 :            :                     }
    1417                 :         63 :                     break;
    1418                 :            :                     case CELLTYPE_FORMULA:
    1419                 :            :                     {
    1420         [ #  # ]:          0 :                         ScFormulaCell* pFCell = static_cast<ScFormulaCell*>(pCell);
    1421         [ #  # ]:          0 :                         sal_uInt16 nError = pFCell->GetErrCode();
    1422         [ #  # ]:          0 :                         if (nError)
    1423         [ #  # ]:          0 :                             xMat->PutDouble( CreateDoubleError( nError), nC, nR);
    1424 [ #  # ][ #  # ]:          0 :                         else if (pFCell->IsValue())
    1425                 :            :                         {
    1426         [ #  # ]:          0 :                             double fVal = pFCell->GetValue();
    1427         [ #  # ]:          0 :                             xMat->PutDouble(fVal, nC, nR);
    1428                 :            :                         }
    1429                 :            :                         else
    1430                 :            :                         {
    1431         [ #  # ]:          0 :                             rtl::OUString aStr = pFCell->GetString();
    1432         [ #  # ]:          0 :                             xMat->PutString(aStr, nC, nR);
    1433                 :            :                         }
    1434                 :            :                     }
    1435                 :         63 :                     break;
    1436                 :            :                     default:
    1437                 :            :                         OSL_FAIL("attempted to convert an unknown cell type.");
    1438                 :            :                 }
    1439                 :            :             }
    1440                 :            :         }
    1441         [ -  + ]:         18 :         if (!bFirstTab)
    1442         [ #  # ]:          0 :             pArray->AddOpCode(ocSep);
    1443                 :            : 
    1444 [ +  - ][ +  - ]:         18 :         ScMatrixToken aToken(xMat);
    1445         [ +  - ]:         18 :         pArray->AddToken(aToken);
    1446                 :            : 
    1447         [ +  - ]:         18 :         itrCache->mpRangeData = xMat;
    1448                 :            : 
    1449                 :         18 :         bFirstTab = false;
    1450 [ +  - ][ +  - ]:         18 :     }
    1451                 :            : 
    1452         [ -  + ]:         18 :     if (!pUsedRange.get())
    1453                 :          0 :         return NULL;
    1454                 :            : 
    1455                 :         18 :     s.SetCol(pUsedRange->aStart.Col());
    1456                 :         18 :     s.SetRow(pUsedRange->aStart.Row());
    1457                 :         18 :     e.SetCol(pUsedRange->aEnd.Col());
    1458                 :         18 :     e.SetRow(pUsedRange->aEnd.Row());
    1459                 :            : 
    1460 [ +  - ][ +  - ]:         18 :     return pArray.release();
    1461                 :            : }
    1462                 :            : 
    1463                 :          0 : static ScTokenArray* lcl_fillEmptyMatrix(const ScRange& rRange)
    1464                 :            : {
    1465                 :          0 :     SCSIZE nC = static_cast<SCSIZE>(rRange.aEnd.Col()-rRange.aStart.Col()+1);
    1466                 :          0 :     SCSIZE nR = static_cast<SCSIZE>(rRange.aEnd.Row()-rRange.aStart.Row()+1);
    1467 [ #  # ][ #  # ]:          0 :     ScMatrixRef xMat = new ScMatrix(nC, nR);
    1468                 :            : 
    1469 [ #  # ][ #  # ]:          0 :     ScMatrixToken aToken(xMat);
    1470                 :            :     SAL_WNODEPRECATED_DECLARATIONS_PUSH
    1471 [ #  # ][ #  # ]:          0 :     auto_ptr<ScTokenArray> pArray(new ScTokenArray);
    1472                 :            :     SAL_WNODEPRECATED_DECLARATIONS_POP
    1473         [ #  # ]:          0 :     pArray->AddToken(aToken);
    1474 [ #  # ][ #  # ]:          0 :     return pArray.release();
                 [ #  # ]
    1475                 :            : }
    1476                 :            : 
    1477                 :        275 : ScExternalRefManager::ScExternalRefManager(ScDocument* pDoc) :
    1478                 :            :     mpDoc(pDoc),
    1479                 :            :     mbInReferenceMarking(false),
    1480 [ +  - ][ +  - ]:        275 :     mbUserInteractionEnabled(true)
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    1481                 :            : {
    1482         [ +  - ]:        275 :     maSrcDocTimer.SetTimeoutHdl( LINK(this, ScExternalRefManager, TimeOutHdl) );
    1483         [ +  - ]:        275 :     maSrcDocTimer.SetTimeout(SRCDOC_SCAN_INTERVAL);
    1484                 :        275 : }
    1485                 :            : 
    1486 [ +  - ][ +  - ]:        262 : ScExternalRefManager::~ScExternalRefManager()
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    1487                 :            : {
    1488         [ +  - ]:        262 :     clear();
    1489         [ -  + ]:        524 : }
    1490                 :            : 
    1491                 :          0 : OUString ScExternalRefManager::getCacheTableName(sal_uInt16 nFileId, size_t nTabIndex) const
    1492                 :            : {
    1493         [ #  # ]:          0 :     return maRefCache.getTableName(nFileId, nTabIndex);
    1494                 :            : }
    1495                 :            : 
    1496                 :          0 : ScExternalRefCache::TableTypeRef ScExternalRefManager::getCacheTable(sal_uInt16 nFileId, size_t nTabIndex) const
    1497                 :            : {
    1498                 :          0 :     return maRefCache.getCacheTable(nFileId, nTabIndex);
    1499                 :            : }
    1500                 :            : 
    1501                 :          9 : ScExternalRefCache::TableTypeRef ScExternalRefManager::getCacheTable(
    1502                 :            :     sal_uInt16 nFileId, const OUString& rTabName, bool bCreateNew, size_t* pnIndex)
    1503                 :            : {
    1504                 :          9 :     return maRefCache.getCacheTable(nFileId, rTabName, bCreateNew, pnIndex);
    1505                 :            : }
    1506                 :            : 
    1507                 :            : // ============================================================================
    1508                 :            : 
    1509                 :          0 : ScExternalRefManager::LinkListener::LinkListener()
    1510                 :            : {
    1511                 :          0 : }
    1512                 :            : 
    1513                 :          0 : ScExternalRefManager::LinkListener::~LinkListener()
    1514                 :            : {
    1515         [ #  # ]:          0 : }
    1516                 :            : 
    1517                 :            : // ----------------------------------------------------------------------------
    1518                 :            : 
    1519                 :       2048 : ScExternalRefManager::ApiGuard::ApiGuard(ScDocument* pDoc) :
    1520                 :       2048 :     mpMgr(pDoc->GetExternalRefManager()),
    1521                 :       2048 :     mbOldInteractionEnabled(mpMgr->mbUserInteractionEnabled)
    1522                 :            : {
    1523                 :            :     // We don't want user interaction handled in the API.
    1524                 :       2048 :     mpMgr->mbUserInteractionEnabled = false;
    1525                 :       2048 : }
    1526                 :            : 
    1527                 :       2048 : ScExternalRefManager::ApiGuard::~ApiGuard()
    1528                 :            : {
    1529                 :            :     // Restore old value.
    1530                 :       2048 :     mpMgr->mbUserInteractionEnabled = mbOldInteractionEnabled;
    1531                 :       2048 : }
    1532                 :            : 
    1533                 :            : // ----------------------------------------------------------------------------
    1534                 :            : 
    1535                 :          3 : void ScExternalRefManager::getAllCachedTableNames(sal_uInt16 nFileId, vector<OUString>& rTabNames) const
    1536                 :            : {
    1537                 :          3 :     maRefCache.getAllTableNames(nFileId, rTabNames);
    1538                 :          3 : }
    1539                 :            : 
    1540                 :          0 : SCsTAB ScExternalRefManager::getCachedTabSpan( sal_uInt16 nFileId, const OUString& rStartTabName, const OUString& rEndTabName ) const
    1541                 :            : {
    1542                 :          0 :     return maRefCache.getTabSpan( nFileId, rStartTabName, rEndTabName);
    1543                 :            : }
    1544                 :            : 
    1545                 :          0 : void ScExternalRefManager::getAllCachedNumberFormats(vector<sal_uInt32>& rNumFmts) const
    1546                 :            : {
    1547                 :          0 :     maRefCache.getAllNumberFormats(rNumFmts);
    1548                 :          0 : }
    1549                 :            : 
    1550                 :          0 : bool ScExternalRefManager::hasCacheTable(sal_uInt16 nFileId, const OUString& rTabName) const
    1551                 :            : {
    1552                 :          0 :     return maRefCache.hasCacheTable(nFileId, rTabName);
    1553                 :            : }
    1554                 :            : 
    1555                 :          0 : size_t ScExternalRefManager::getCacheTableCount(sal_uInt16 nFileId) const
    1556                 :            : {
    1557                 :          0 :     return maRefCache.getCacheTableCount(nFileId);
    1558                 :            : }
    1559                 :            : 
    1560                 :          4 : sal_uInt16 ScExternalRefManager::getExternalFileCount() const
    1561                 :            : {
    1562                 :          4 :     return static_cast< sal_uInt16 >( maSrcFiles.size() );
    1563                 :            : }
    1564                 :            : 
    1565                 :          0 : bool ScExternalRefManager::markUsedByLinkListeners()
    1566                 :            : {
    1567                 :          0 :     bool bAllMarked = false;
    1568 [ #  # ][ #  # ]:          0 :     for (LinkListenerMap::const_iterator itr = maLinkListeners.begin();
         [ #  # ][ #  # ]
    1569 [ #  # ][ #  # ]:          0 :             itr != maLinkListeners.end() && !bAllMarked; ++itr)
                 [ #  # ]
           [ #  #  #  # ]
    1570                 :            :     {
    1571 [ #  # ][ #  # ]:          0 :         if (!(*itr).second.empty())
    1572 [ #  # ][ #  # ]:          0 :             bAllMarked = maRefCache.setCacheDocReferenced( (*itr).first);
    1573                 :            :         /* TODO: LinkListeners should remember the table they're listening to.
    1574                 :            :          * As is, listening to one table will mark all tables of the document
    1575                 :            :          * being referenced. */
    1576                 :            :     }
    1577                 :          0 :     return bAllMarked;
    1578                 :            : }
    1579                 :            : 
    1580                 :          0 : bool ScExternalRefManager::markUsedExternalRefCells()
    1581                 :            : {
    1582 [ #  # ][ #  # ]:          0 :     RefCellMap::iterator itr = maRefCells.begin(), itrEnd = maRefCells.end();
    1583         [ #  # ]:          0 :     for (; itr != itrEnd; ++itr)
    1584                 :            :     {
    1585 [ #  # ][ #  # ]:          0 :         RefCellSet::iterator itrCell = itr->second.begin(), itrCellEnd = itr->second.end();
    1586 [ #  # ][ #  # ]:          0 :         for (; itrCell != itrCellEnd; ++itrCell)
                 [ #  # ]
    1587                 :            :         {
    1588         [ #  # ]:          0 :             ScFormulaCell* pCell = *itrCell;
    1589         [ #  # ]:          0 :             bool bUsed = pCell->MarkUsedExternalReferences();
    1590         [ #  # ]:          0 :             if (bUsed)
    1591                 :            :                 // Return true when at least one cell references external docs.
    1592                 :          0 :                 return true;
    1593                 :            :         }
    1594                 :            :     }
    1595                 :          0 :     return false;
    1596                 :            : }
    1597                 :            : 
    1598                 :          0 : bool ScExternalRefManager::setCacheTableReferenced( sal_uInt16 nFileId, const OUString& rTabName, size_t nSheets )
    1599                 :            : {
    1600                 :          0 :     return maRefCache.setCacheTableReferenced( nFileId, rTabName, nSheets, false);
    1601                 :            : }
    1602                 :            : 
    1603                 :          0 : void ScExternalRefManager::setAllCacheTableReferencedStati( bool bReferenced )
    1604                 :            : {
    1605                 :          0 :     mbInReferenceMarking = !bReferenced;
    1606                 :          0 :     maRefCache.setAllCacheTableReferencedStati( bReferenced );
    1607                 :          0 : }
    1608                 :            : 
    1609                 :          0 : void ScExternalRefManager::storeRangeNameTokens(sal_uInt16 nFileId, const OUString& rName, const ScTokenArray& rArray)
    1610                 :            : {
    1611 [ #  # ][ #  # ]:          0 :     ScExternalRefCache::TokenArrayRef pArray(rArray.Clone());
    1612 [ #  # ][ #  # ]:          0 :     maRefCache.setRangeNameTokens(nFileId, rName, pArray);
         [ #  # ][ #  # ]
    1613                 :          0 : }
    1614                 :            : 
    1615                 :            : namespace {
    1616                 :            : 
    1617                 :            : /**
    1618                 :            :  * Put a single cell data into internal cache table.
    1619                 :            :  *
    1620                 :            :  * @param pFmt optional cell format index that may need to be stored with
    1621                 :            :  *             the cell value.
    1622                 :            :  */
    1623                 :        156 : void putCellDataIntoCache(
    1624                 :            :     ScExternalRefCache& rRefCache, const ScExternalRefCache::TokenRef& pToken,
    1625                 :            :     sal_uInt16 nFileId, const String& rTabName, const ScAddress& rCell,
    1626                 :            :     const ScExternalRefCache::CellFormat* pFmt)
    1627                 :            : {
    1628                 :            :     // Now, insert the token into cache table but don't cache empty cells.
    1629         [ +  + ]:        156 :     if (pToken->GetType() != formula::svEmptyCell)
    1630                 :            :     {
    1631 [ +  + ][ +  - ]:        135 :         sal_uLong nFmtIndex = (pFmt && pFmt->mbIsSet) ? pFmt->mnIndex : 0;
    1632 [ +  - ][ +  - ]:        135 :         rRefCache.setCellData(nFileId, rTabName, rCell.Col(), rCell.Row(), pToken, nFmtIndex);
    1633                 :            :     }
    1634                 :        156 : }
    1635                 :            : 
    1636                 :            : /**
    1637                 :            :  * Put the data into our internal cache table.
    1638                 :            :  *
    1639                 :            :  * @param rRefCache cache table set.
    1640                 :            :  * @param pArray single range data to be returned.
    1641                 :            :  * @param nFileId external file ID
    1642                 :            :  * @param rTabName name of the table where the data should be cached.
    1643                 :            :  * @param rCacheData range data to be cached.
    1644                 :            :  * @param rCacheRange original cache range, including the empty region if
    1645                 :            :  *                    any.
    1646                 :            :  * @param rDataRange reduced cache range that includes only the non-empty
    1647                 :            :  *                   data area.
    1648                 :            :  */
    1649                 :         18 : void putRangeDataIntoCache(
    1650                 :            :     ScExternalRefCache& rRefCache, ScExternalRefCache::TokenArrayRef& pArray,
    1651                 :            :     sal_uInt16 nFileId, const String& rTabName,
    1652                 :            :     const vector<ScExternalRefCache::SingleRangeData>& rCacheData,
    1653                 :            :     const ScRange& rCacheRange, const ScRange& rDataRange)
    1654                 :            : {
    1655         [ +  - ]:         18 :     if (pArray)
    1656                 :            :         // Cache these values.
    1657                 :         18 :         rRefCache.setCellRangeData(nFileId, rDataRange, rCacheData, pArray);
    1658                 :            :     else
    1659                 :            :     {
    1660                 :            :         // Array is empty.  Fill it with an empty matrix of the required size.
    1661 [ #  # ][ #  # ]:          0 :         pArray.reset(lcl_fillEmptyMatrix(rCacheRange));
    1662                 :            : 
    1663                 :            :         // Make sure to set this range 'cached', to prevent unnecessarily
    1664                 :            :         // accessing the src document time and time again.
    1665                 :            :         ScExternalRefCache::TableTypeRef pCacheTab =
    1666 [ #  # ][ #  # ]:          0 :             rRefCache.getCacheTable(nFileId, rTabName, true, NULL);
    1667         [ #  # ]:          0 :         if (pCacheTab)
    1668                 :            :             pCacheTab->setCachedCellRange(
    1669 [ #  # ][ #  # ]:          0 :                 rCacheRange.aStart.Col(), rCacheRange.aStart.Row(), rCacheRange.aEnd.Col(), rCacheRange.aEnd.Row());
    1670                 :            :     }
    1671                 :         18 : }
    1672                 :            : 
    1673                 :            : /**
    1674                 :            :  * When accessing an external document for the first time, we need to
    1675                 :            :  * populate the cache with all its sheet names (whether they are referenced
    1676                 :            :  * or not) in the correct order.  Many client codes that use external
    1677                 :            :  * references make this assumption.
    1678                 :            :  *
    1679                 :            :  * @param rRefCache cache table set.
    1680                 :            :  * @param pSrcDoc source document instance.
    1681                 :            :  * @param nFileId external file ID associated with the source document.
    1682                 :            :  */
    1683                 :        174 : void initDocInCache(ScExternalRefCache& rRefCache, const ScDocument* pSrcDoc, sal_uInt16 nFileId)
    1684                 :            : {
    1685         [ -  + ]:        174 :     if (!pSrcDoc)
    1686                 :          0 :         return;
    1687                 :            : 
    1688         [ +  + ]:        174 :     if (rRefCache.isDocInitialized(nFileId))
    1689                 :            :         // Already initialized.  No need to do this twice.
    1690                 :        165 :         return;
    1691                 :            : 
    1692                 :          9 :     SCTAB nTabCount = pSrcDoc->GetTableCount();
    1693         [ +  - ]:          9 :     if (nTabCount)
    1694                 :            :     {
    1695                 :            :         // Populate the cache with all table names in the source document.
    1696         [ +  - ]:          9 :         vector<OUString> aTabNames;
    1697         [ +  - ]:          9 :         aTabNames.reserve(nTabCount);
    1698         [ +  + ]:         33 :         for (SCTAB i = 0; i < nTabCount; ++i)
    1699                 :            :         {
    1700                 :         24 :             OUString aName;
    1701         [ +  - ]:         24 :             pSrcDoc->GetName(i, aName);
    1702         [ +  - ]:         24 :             aTabNames.push_back(aName);
    1703                 :         24 :         }
    1704         [ +  - ]:        174 :         rRefCache.initializeDoc(nFileId, aTabNames);
    1705                 :            :     }
    1706                 :            : }
    1707                 :            : 
    1708                 :            : }
    1709                 :            : 
    1710                 :        156 : ScExternalRefCache::TokenRef ScExternalRefManager::getSingleRefToken(
    1711                 :            :     sal_uInt16 nFileId, const OUString& rTabName, const ScAddress& rCell,
    1712                 :            :     const ScAddress* pCurPos, SCTAB* pTab, ScExternalRefCache::CellFormat* pFmt)
    1713                 :            : {
    1714         [ +  + ]:        156 :     if (pCurPos)
    1715         [ +  - ]:         69 :         insertRefCell(nFileId, *pCurPos);
    1716                 :            : 
    1717         [ +  - ]:        156 :     maybeLinkExternalFile(nFileId);
    1718                 :            : 
    1719         [ +  + ]:        156 :     if (pTab)
    1720                 :         87 :         *pTab = -1;
    1721                 :            : 
    1722         [ +  + ]:        156 :     if (pFmt)
    1723                 :         69 :         pFmt->mbIsSet = false;
    1724                 :            : 
    1725         [ +  - ]:        156 :     const ScDocument* pSrcDoc = getInMemorySrcDocument(nFileId);
    1726         [ +  - ]:        156 :     if (pSrcDoc)
    1727                 :            :     {
    1728                 :            :         // source document already loaded in memory.  Re-use this instance.
    1729                 :            :         SCTAB nTab;
    1730 [ +  - ][ -  + ]:        156 :         if (!pSrcDoc->GetTable(rTabName, nTab))
    1731                 :            :         {
    1732                 :            :             // specified table name doesn't exist in the source document.
    1733 [ #  # ][ #  # ]:          0 :             ScExternalRefCache::TokenRef pToken(new FormulaErrorToken(errNoRef));
    1734         [ #  # ]:          0 :             return pToken;
    1735                 :            :         }
    1736                 :            : 
    1737         [ +  + ]:        156 :         if (pTab)
    1738                 :         87 :             *pTab = nTab;
    1739                 :            : 
    1740                 :            :         ScExternalRefCache::TokenRef pToken =
    1741                 :            :             getSingleRefTokenFromSrcDoc(
    1742         [ +  - ]:        156 :                 nFileId, pSrcDoc, ScAddress(rCell.Col(),rCell.Row(),nTab), pFmt);
    1743                 :            : 
    1744 [ +  - ][ +  - ]:        156 :         putCellDataIntoCache(maRefCache, pToken, nFileId, rTabName, rCell, pFmt);
                 [ +  - ]
    1745         [ +  - ]:        156 :         return pToken;
    1746                 :            :     }
    1747                 :            : 
    1748                 :            :     // Check if the given table name and the cell position is cached.
    1749                 :          0 :     sal_uInt32 nFmtIndex = 0;
    1750                 :            :     ScExternalRefCache::TokenRef pToken = maRefCache.getCellData(
    1751         [ #  # ]:          0 :         nFileId, rTabName, rCell.Col(), rCell.Row(), &nFmtIndex);
    1752         [ #  # ]:          0 :     if (pToken)
    1753                 :            :     {
    1754                 :            :         // Cache hit !
    1755         [ #  # ]:          0 :         fillCellFormat(nFmtIndex, pFmt);
    1756                 :          0 :         return pToken;
    1757                 :            :     }
    1758                 :            : 
    1759                 :            :     // reference not cached.  read from the source document.
    1760         [ #  # ]:          0 :     pSrcDoc = getSrcDocument(nFileId);
    1761         [ #  # ]:          0 :     if (!pSrcDoc)
    1762                 :            :     {
    1763                 :            :         // Source document not reachable.  Throw a reference error.
    1764 [ #  # ][ #  # ]:          0 :         pToken.reset(new FormulaErrorToken(errNoRef));
                 [ #  # ]
    1765                 :          0 :         return pToken;
    1766                 :            :     }
    1767                 :            : 
    1768                 :            :     SCTAB nTab;
    1769 [ #  # ][ #  # ]:          0 :     if (!pSrcDoc->GetTable(rTabName, nTab))
    1770                 :            :     {
    1771                 :            :         // specified table name doesn't exist in the source document.
    1772 [ #  # ][ #  # ]:          0 :         pToken.reset(new FormulaErrorToken(errNoRef));
                 [ #  # ]
    1773                 :          0 :         return pToken;
    1774                 :            :     }
    1775                 :            : 
    1776         [ #  # ]:          0 :     if (pTab)
    1777                 :          0 :         *pTab = nTab;
    1778                 :            : 
    1779                 :          0 :     SCCOL nDataCol1 = 0, nDataCol2 = MAXCOL;
    1780                 :          0 :     SCROW nDataRow1 = 0, nDataRow2 = MAXROW;
    1781         [ #  # ]:          0 :     bool bData = pSrcDoc->ShrinkToDataArea(nTab, nDataCol1, nDataRow1, nDataCol2, nDataRow2);
    1782 [ #  # ][ #  # ]:          0 :     if (!bData || rCell.Col() < nDataCol1 || nDataCol2 < rCell.Col() || rCell.Row() < nDataRow1 || nDataRow2 < rCell.Row())
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    1783                 :            :     {
    1784                 :            :         // requested cell is outside the data area.  Don't even bother caching
    1785                 :            :         // this data, but add it to the cached range to prevent accessing the
    1786                 :            :         // source document time and time again.
    1787                 :            :         ScExternalRefCache::TableTypeRef pCacheTab =
    1788         [ #  # ]:          0 :             maRefCache.getCacheTable(nFileId, rTabName, true, NULL);
    1789         [ #  # ]:          0 :         if (pCacheTab)
    1790         [ #  # ]:          0 :             pCacheTab->setCachedCell(rCell.Col(), rCell.Row());
    1791                 :            : 
    1792 [ #  # ][ #  # ]:          0 :         pToken.reset(new ScEmptyCellToken(false, false));
                 [ #  # ]
    1793         [ #  # ]:          0 :         return pToken;
    1794                 :            :     }
    1795                 :            : 
    1796                 :            :     pToken = getSingleRefTokenFromSrcDoc(
    1797 [ #  # ][ #  # ]:          0 :         nFileId, pSrcDoc, ScAddress(rCell.Col(),rCell.Row(),nTab), pFmt);
                 [ #  # ]
    1798                 :            : 
    1799 [ #  # ][ #  # ]:          0 :     putCellDataIntoCache(maRefCache, pToken, nFileId, rTabName, rCell, pFmt);
                 [ #  # ]
    1800         [ #  # ]:        156 :     return pToken;
    1801                 :            : }
    1802                 :            : 
    1803                 :         18 : ScExternalRefCache::TokenArrayRef ScExternalRefManager::getDoubleRefTokens(
    1804                 :            :     sal_uInt16 nFileId, const OUString& rTabName, const ScRange& rRange, const ScAddress* pCurPos)
    1805                 :            : {
    1806         [ +  - ]:         18 :     if (pCurPos)
    1807         [ +  - ]:         18 :         insertRefCell(nFileId, *pCurPos);
    1808                 :            : 
    1809         [ +  - ]:         18 :     maybeLinkExternalFile(nFileId);
    1810                 :            : 
    1811                 :         18 :     ScRange aDataRange(rRange);
    1812         [ +  - ]:         18 :     const ScDocument* pSrcDoc = getInMemorySrcDocument(nFileId);
    1813         [ +  - ]:         18 :     if (pSrcDoc)
    1814                 :            :     {
    1815                 :            :         // Document already loaded in memory.
    1816         [ +  - ]:         18 :         vector<ScExternalRefCache::SingleRangeData> aCacheData;
    1817                 :            :         ScExternalRefCache::TokenArrayRef pArray =
    1818         [ +  - ]:         18 :             getDoubleRefTokensFromSrcDoc(pSrcDoc, rTabName, aDataRange, aCacheData);
    1819                 :            : 
    1820                 :            :         // Put the data into cache.
    1821 [ +  - ][ +  - ]:         18 :         putRangeDataIntoCache(maRefCache, pArray, nFileId, rTabName, aCacheData, rRange, aDataRange);
                 [ +  - ]
    1822 [ +  - ][ +  - ]:         18 :         return pArray;
    1823                 :            :     }
    1824                 :            : 
    1825                 :            :     // Check if the given table name and the cell position is cached.
    1826                 :            :     ScExternalRefCache::TokenArrayRef pArray =
    1827         [ #  # ]:          0 :         maRefCache.getCellRangeData(nFileId, rTabName, rRange);
    1828         [ #  # ]:          0 :     if (pArray)
    1829                 :            :         // Cache hit !
    1830         [ #  # ]:          0 :         return pArray;
    1831                 :            : 
    1832         [ #  # ]:          0 :     pSrcDoc = getSrcDocument(nFileId);
    1833         [ #  # ]:          0 :     if (!pSrcDoc)
    1834                 :            :     {
    1835                 :            :         // Source document is not reachable.  Throw a reference error.
    1836 [ #  # ][ #  # ]:          0 :         pArray.reset(new ScTokenArray);
                 [ #  # ]
    1837 [ #  # ][ #  # ]:          0 :         pArray->AddToken(FormulaErrorToken(errNoRef));
                 [ #  # ]
    1838         [ #  # ]:          0 :         return pArray;
    1839                 :            :     }
    1840                 :            : 
    1841         [ #  # ]:          0 :     vector<ScExternalRefCache::SingleRangeData> aCacheData;
    1842 [ #  # ][ #  # ]:          0 :     pArray = getDoubleRefTokensFromSrcDoc(pSrcDoc, rTabName, aDataRange, aCacheData);
                 [ #  # ]
    1843                 :            : 
    1844                 :            :     // Put the data into cache.
    1845 [ #  # ][ #  # ]:          0 :     putRangeDataIntoCache(maRefCache, pArray, nFileId, rTabName, aCacheData, rRange, aDataRange);
                 [ #  # ]
    1846 [ #  # ][ #  # ]:         18 :     return pArray;
    1847                 :            : }
    1848                 :            : 
    1849                 :          0 : ScExternalRefCache::TokenArrayRef ScExternalRefManager::getRangeNameTokens(
    1850                 :            :     sal_uInt16 nFileId, const OUString& rName, const ScAddress* pCurPos)
    1851                 :            : {
    1852         [ #  # ]:          0 :     if (pCurPos)
    1853         [ #  # ]:          0 :         insertRefCell(nFileId, *pCurPos);
    1854                 :            : 
    1855         [ #  # ]:          0 :     maybeLinkExternalFile(nFileId);
    1856                 :            : 
    1857                 :          0 :     OUString aName = rName; // make a copy to have the casing corrected.
    1858         [ #  # ]:          0 :     const ScDocument* pSrcDoc = getInMemorySrcDocument(nFileId);
    1859         [ #  # ]:          0 :     if (pSrcDoc)
    1860                 :            :     {
    1861                 :            :         // Document already loaded in memory.
    1862                 :            :         ScExternalRefCache::TokenArrayRef pArray =
    1863         [ #  # ]:          0 :             getRangeNameTokensFromSrcDoc(nFileId, pSrcDoc, aName);
    1864                 :            : 
    1865         [ #  # ]:          0 :         if (pArray)
    1866                 :            :             // Cache this range name array.
    1867 [ #  # ][ #  # ]:          0 :             maRefCache.setRangeNameTokens(nFileId, aName, pArray);
                 [ #  # ]
    1868                 :            : 
    1869 [ #  # ][ #  # ]:          0 :         return pArray;
    1870                 :            :     }
    1871                 :            : 
    1872         [ #  # ]:          0 :     ScExternalRefCache::TokenArrayRef pArray = maRefCache.getRangeNameTokens(nFileId, rName);
    1873         [ #  # ]:          0 :     if (pArray.get())
    1874                 :            :         // This range name is cached.
    1875         [ #  # ]:          0 :         return pArray;
    1876                 :            : 
    1877         [ #  # ]:          0 :     pSrcDoc = getSrcDocument(nFileId);
    1878         [ #  # ]:          0 :     if (!pSrcDoc)
    1879                 :            :         // failed to load document from disk.
    1880         [ #  # ]:          0 :         return ScExternalRefCache::TokenArrayRef();
    1881                 :            : 
    1882 [ #  # ][ #  # ]:          0 :     pArray = getRangeNameTokensFromSrcDoc(nFileId, pSrcDoc, aName);
                 [ #  # ]
    1883                 :            : 
    1884         [ #  # ]:          0 :     if (pArray)
    1885                 :            :         // Cache this range name array.
    1886 [ #  # ][ #  # ]:          0 :         maRefCache.setRangeNameTokens(nFileId, aName, pArray);
                 [ #  # ]
    1887                 :            : 
    1888 [ #  # ][ #  # ]:          0 :     return pArray;
    1889                 :            : }
    1890                 :            : 
    1891                 :          0 : void ScExternalRefManager::refreshAllRefCells(sal_uInt16 nFileId)
    1892                 :            : {
    1893         [ #  # ]:          0 :     RefCellMap::iterator itrFile = maRefCells.find(nFileId);
    1894 [ #  # ][ #  # ]:          0 :     if (itrFile == maRefCells.end())
    1895                 :            :         return;
    1896                 :            : 
    1897         [ #  # ]:          0 :     RefCellSet& rRefCells = itrFile->second;
    1898         [ #  # ]:          0 :     for_each(rRefCells.begin(), rRefCells.end(), UpdateFormulaCell());
    1899                 :            : 
    1900         [ #  # ]:          0 :     ScViewData* pViewData = ScDocShell::GetViewData();
    1901         [ #  # ]:          0 :     if (!pViewData)
    1902                 :            :         return;
    1903                 :            : 
    1904                 :          0 :     ScTabViewShell* pVShell = pViewData->GetViewShell();
    1905         [ #  # ]:          0 :     if (!pVShell)
    1906                 :            :         return;
    1907                 :            : 
    1908                 :            :     // Repainting the grid also repaints the texts, but is there a better way
    1909                 :            :     // to refresh texts?
    1910         [ #  # ]:          0 :     pVShell->Invalidate(FID_REPAINT);
    1911         [ #  # ]:          0 :     pVShell->PaintGrid();
    1912                 :            : }
    1913                 :            : 
    1914                 :         87 : void ScExternalRefManager::insertRefCell(sal_uInt16 nFileId, const ScAddress& rCell)
    1915                 :            : {
    1916         [ +  - ]:         87 :     RefCellMap::iterator itr = maRefCells.find(nFileId);
    1917 [ +  - ][ +  + ]:         87 :     if (itr == maRefCells.end())
    1918                 :            :     {
    1919         [ +  - ]:          6 :         RefCellSet aRefCells;
    1920                 :            :         pair<RefCellMap::iterator, bool> r = maRefCells.insert(
    1921 [ +  - ][ +  - ]:          6 :             RefCellMap::value_type(nFileId, aRefCells));
    1922         [ -  + ]:          6 :         if (!r.second)
    1923                 :            :             // insertion failed.
    1924                 :         87 :             return;
    1925                 :            : 
    1926         [ +  - ]:          6 :         itr = r.first;
    1927                 :            :     }
    1928                 :            : 
    1929         [ +  - ]:         87 :     ScBaseCell* pCell = mpDoc->GetCell(rCell);
    1930 [ +  - ][ +  - ]:         87 :     if (pCell && pCell->GetCellType() == CELLTYPE_FORMULA)
                 [ +  - ]
    1931 [ +  - ][ +  - ]:         87 :         itr->second.insert(static_cast<ScFormulaCell*>(pCell));
                 [ +  - ]
    1932                 :            : }
    1933                 :            : 
    1934                 :        156 : void ScExternalRefManager::fillCellFormat(sal_uLong nFmtIndex, ScExternalRefCache::CellFormat* pFmt) const
    1935                 :            : {
    1936         [ +  + ]:        156 :     if (!pFmt)
    1937                 :        156 :         return;
    1938                 :            : 
    1939                 :         69 :     short nFmtType = mpDoc->GetFormatTable()->GetType(nFmtIndex);
    1940         [ +  - ]:         69 :     if (nFmtType != NUMBERFORMAT_UNDEFINED)
    1941                 :            :     {
    1942                 :         69 :         pFmt->mbIsSet = true;
    1943                 :         69 :         pFmt->mnIndex = nFmtIndex;
    1944                 :         69 :         pFmt->mnType = nFmtType;
    1945                 :            :     }
    1946                 :            : }
    1947                 :            : 
    1948                 :        156 : ScExternalRefCache::TokenRef ScExternalRefManager::getSingleRefTokenFromSrcDoc(
    1949                 :            :     sal_uInt16 nFileId, const ScDocument* pSrcDoc, const ScAddress& rCell,
    1950                 :            :     ScExternalRefCache::CellFormat* pFmt)
    1951                 :            : {
    1952                 :            :     // Get the cell from src doc, and convert it into a token.
    1953                 :        156 :     ScBaseCell* pCell = NULL;
    1954         [ +  - ]:        156 :     pSrcDoc->GetCell(rCell.Col(), rCell.Row(), rCell.Tab(), pCell);
    1955         [ +  - ]:        156 :     ScExternalRefCache::TokenRef pToken(lcl_convertToToken(pCell));
    1956                 :            : 
    1957         [ -  + ]:        156 :     if (!pToken.get())
    1958                 :            :     {
    1959                 :            :         // Generate an error for unresolvable cells.
    1960 [ #  # ][ #  # ]:          0 :         pToken.reset( new FormulaErrorToken( errNoValue));
                 [ #  # ]
    1961                 :            :     }
    1962                 :            : 
    1963                 :            :     // Get number format information.
    1964                 :        156 :     sal_uInt32 nFmtIndex = 0;
    1965         [ +  - ]:        156 :     pSrcDoc->GetNumberFormat(rCell.Col(), rCell.Row(), rCell.Tab(), nFmtIndex);
    1966         [ +  - ]:        156 :     nFmtIndex = getMappedNumberFormat(nFileId, nFmtIndex, pSrcDoc);
    1967         [ +  - ]:        156 :     fillCellFormat(nFmtIndex, pFmt);
    1968                 :        156 :     return pToken;
    1969                 :            : }
    1970                 :            : 
    1971                 :         18 : ScExternalRefCache::TokenArrayRef ScExternalRefManager::getDoubleRefTokensFromSrcDoc(
    1972                 :            :     const ScDocument* pSrcDoc, const OUString& rTabName, ScRange& rRange,
    1973                 :            :     vector<ScExternalRefCache::SingleRangeData>& rCacheData)
    1974                 :            : {
    1975         [ +  - ]:         18 :     ScExternalRefCache::TokenArrayRef pArray;
    1976                 :            :     SCTAB nTab1;
    1977                 :            : 
    1978 [ +  - ][ -  + ]:         18 :     if (!pSrcDoc->GetTable(rTabName, nTab1))
    1979                 :            :     {
    1980                 :            :         // specified table name doesn't exist in the source document.
    1981 [ #  # ][ #  # ]:          0 :         pArray.reset(new ScTokenArray);
                 [ #  # ]
    1982 [ #  # ][ #  # ]:          0 :         pArray->AddToken(FormulaErrorToken(errNoRef));
                 [ #  # ]
    1983                 :            :         return pArray;
    1984                 :            :     }
    1985                 :            : 
    1986                 :         18 :     ScRange aRange(rRange);
    1987                 :         18 :     SCTAB nTabSpan = aRange.aEnd.Tab() - aRange.aStart.Tab();
    1988                 :            : 
    1989         [ +  - ]:         18 :     vector<ScExternalRefCache::SingleRangeData> aCacheData;
    1990         [ +  - ]:         18 :     aCacheData.reserve(nTabSpan+1);
    1991 [ +  - ][ +  - ]:         18 :     aCacheData.push_back(ScExternalRefCache::SingleRangeData());
                 [ +  - ]
    1992 [ +  - ][ +  - ]:         18 :     aCacheData.back().maTableName = ScGlobal::pCharClass->uppercase(rTabName);
    1993                 :            : 
    1994         [ -  + ]:         18 :     for (SCTAB i = 1; i < nTabSpan + 1; ++i)
    1995                 :            :     {
    1996                 :          0 :         OUString aTabName;
    1997 [ #  # ][ #  # ]:          0 :         if (!pSrcDoc->GetName(nTab1 + 1, aTabName))
    1998                 :            :             // source document doesn't have any table by the specified name.
    1999                 :            :             break;
    2000                 :            : 
    2001 [ #  # ][ #  # ]:          0 :         aCacheData.push_back(ScExternalRefCache::SingleRangeData());
                 [ #  # ]
    2002 [ #  # ][ #  # ]:          0 :         aCacheData.back().maTableName = ScGlobal::pCharClass->uppercase(aTabName);
                 [ #  # ]
    2003                 :          0 :     }
    2004                 :            : 
    2005                 :         18 :     aRange.aStart.SetTab(nTab1);
    2006                 :         18 :     aRange.aEnd.SetTab(nTab1 + nTabSpan);
    2007                 :            : 
    2008 [ +  - ][ +  - ]:         18 :     pArray.reset(lcl_convertToTokenArray(pSrcDoc, aRange, aCacheData));
    2009                 :         18 :     rRange = aRange;
    2010                 :         18 :     rCacheData.swap(aCacheData);
    2011                 :         18 :     return pArray;
    2012                 :            : }
    2013                 :            : 
    2014                 :          0 : ScExternalRefCache::TokenArrayRef ScExternalRefManager::getRangeNameTokensFromSrcDoc(
    2015                 :            :     sal_uInt16 nFileId, const ScDocument* pSrcDoc, OUString& rName)
    2016                 :            : {
    2017         [ #  # ]:          0 :     ScRangeName* pExtNames = pSrcDoc->GetRangeName();
    2018 [ #  # ][ #  # ]:          0 :     String aUpperName = ScGlobal::pCharClass->uppercase(rName);
    2019 [ #  # ][ #  # ]:          0 :     const ScRangeData* pRangeData = pExtNames->findByUpperName(aUpperName);
    2020         [ #  # ]:          0 :     if (!pRangeData)
    2021         [ #  # ]:          0 :         return ScExternalRefCache::TokenArrayRef();
    2022                 :            : 
    2023                 :            :     // Parse all tokens in this external range data, and replace each absolute
    2024                 :            :     // reference token with an external reference token, and cache them.  Also
    2025                 :            :     // register the source document with the link manager if it's a new
    2026                 :            :     // source.
    2027                 :            : 
    2028 [ #  # ][ #  # ]:          0 :     ScExternalRefCache::TokenArrayRef pNew(new ScTokenArray);
                 [ #  # ]
    2029                 :            : 
    2030         [ #  # ]:          0 :     ScTokenArray aCode(*pRangeData->GetCode());
    2031 [ #  # ][ #  # ]:          0 :     for (const FormulaToken* pToken = aCode.First(); pToken; pToken = aCode.Next())
                 [ #  # ]
    2032                 :            :     {
    2033                 :          0 :         bool bTokenAdded = false;
    2034      [ #  #  # ]:          0 :         switch (pToken->GetType())
    2035                 :            :         {
    2036                 :            :             case svSingleRef:
    2037                 :            :             {
    2038         [ #  # ]:          0 :                 const ScSingleRefData& rRef = static_cast<const ScToken*>(pToken)->GetSingleRef();
    2039                 :          0 :                 OUString aTabName;
    2040         [ #  # ]:          0 :                 pSrcDoc->GetName(rRef.nTab, aTabName);
    2041 [ #  # ][ #  # ]:          0 :                 ScExternalSingleRefToken aNewToken(nFileId, aTabName, static_cast<const ScToken*>(pToken)->GetSingleRef());
         [ #  # ][ #  # ]
    2042         [ #  # ]:          0 :                 pNew->AddToken(aNewToken);
    2043         [ #  # ]:          0 :                 bTokenAdded = true;
    2044                 :            :             }
    2045                 :          0 :             break;
    2046                 :            :             case svDoubleRef:
    2047                 :            :             {
    2048         [ #  # ]:          0 :                 const ScSingleRefData& rRef = static_cast<const ScToken*>(pToken)->GetSingleRef();
    2049                 :          0 :                 OUString aTabName;
    2050         [ #  # ]:          0 :                 pSrcDoc->GetName(rRef.nTab, aTabName);
    2051 [ #  # ][ #  # ]:          0 :                 ScExternalDoubleRefToken aNewToken(nFileId, aTabName, static_cast<const ScToken*>(pToken)->GetDoubleRef());
         [ #  # ][ #  # ]
    2052         [ #  # ]:          0 :                 pNew->AddToken(aNewToken);
    2053         [ #  # ]:          0 :                 bTokenAdded = true;
    2054                 :            :             }
    2055                 :          0 :             break;
    2056                 :            :             default:
    2057                 :            :                 ;   // nothing
    2058                 :            :         }
    2059                 :            : 
    2060         [ #  # ]:          0 :         if (!bTokenAdded)
    2061         [ #  # ]:          0 :             pNew->AddToken(*pToken);
    2062                 :            :     }
    2063                 :            : 
    2064                 :          0 :     rName = pRangeData->GetName(); // Get the correctly-cased name.
    2065 [ #  # ][ #  # ]:          0 :     return pNew;
         [ #  # ][ #  # ]
    2066                 :            : }
    2067                 :            : 
    2068                 :        174 : const ScDocument* ScExternalRefManager::getInMemorySrcDocument(sal_uInt16 nFileId)
    2069                 :            : {
    2070         [ +  - ]:        174 :     const OUString* pFileName = getExternalFileName(nFileId);
    2071         [ -  + ]:        174 :     if (!pFileName)
    2072                 :          0 :         return NULL;
    2073                 :            : 
    2074                 :        174 :     ScDocument* pSrcDoc = NULL;
    2075         [ +  - ]:        174 :     TypeId aType(TYPE(ScDocShell));
    2076         [ +  - ]:        174 :     ScDocShell* pShell = static_cast<ScDocShell*>(SfxObjectShell::GetFirst(&aType, false));
    2077         [ +  - ]:       4578 :     while (pShell)
    2078                 :            :     {
    2079                 :       4578 :         SfxMedium* pMedium = pShell->GetMedium();
    2080 [ +  - ][ +  - ]:       4578 :         if (pMedium && !pMedium->GetName().isEmpty())
         [ +  + ][ +  + ]
    2081                 :            :         {
    2082                 :            :             // TODO: We should make the case sensitivity platform dependent.
    2083 [ +  - ][ +  - ]:        174 :             if (pFileName->equalsIgnoreAsciiCase(pMedium->GetName()))
    2084                 :            :             {
    2085                 :            :                 // Found !
    2086                 :        174 :                 pSrcDoc = pShell->GetDocument();
    2087                 :        174 :                 break;
    2088                 :            :             }
    2089                 :            :         }
    2090                 :            :         else
    2091                 :            :         {
    2092                 :            :             // handle unsaved documents here
    2093 [ +  - ][ +  - ]:       4404 :             OUString aName = pShell->GetName();
    2094         [ -  + ]:       4404 :             if (pFileName->equalsIgnoreAsciiCase(aName))
    2095                 :            :             {
    2096                 :            :                 // Found !
    2097         [ #  # ]:          0 :                 SrcShell aSrcDoc;
    2098         [ #  # ]:          0 :                 aSrcDoc.maShell = pShell;
    2099 [ #  # ][ #  # ]:          0 :                 maUnsavedDocShells.insert(DocShellMap::value_type(nFileId, aSrcDoc));
                 [ #  # ]
    2100         [ #  # ]:          0 :                 StartListening(*pShell);
    2101                 :          0 :                 pSrcDoc = pShell->GetDocument();
    2102         [ #  # ]:       4404 :                 break;
    2103         [ +  - ]:       4404 :             }
    2104                 :            :         }
    2105         [ +  - ]:       4404 :         pShell = static_cast<ScDocShell*>(SfxObjectShell::GetNext(*pShell, &aType, false));
    2106                 :            :     }
    2107                 :            : 
    2108         [ +  - ]:        174 :     initDocInCache(maRefCache, pSrcDoc, nFileId);
    2109                 :        174 :     return pSrcDoc;
    2110                 :            : }
    2111                 :            : 
    2112                 :          0 : const ScDocument* ScExternalRefManager::getSrcDocument(sal_uInt16 nFileId)
    2113                 :            : {
    2114         [ #  # ]:          0 :     if (!mpDoc->IsExecuteLinkEnabled())
    2115                 :          0 :         return NULL;
    2116                 :            : 
    2117         [ #  # ]:          0 :     DocShellMap::iterator itrEnd = maDocShells.end();
    2118         [ #  # ]:          0 :     DocShellMap::iterator itr = maDocShells.find(nFileId);
    2119                 :            : 
    2120         [ #  # ]:          0 :     if (itr != itrEnd)
    2121                 :            :     {
    2122                 :            :         // document already loaded.
    2123                 :            : 
    2124         [ #  # ]:          0 :         SfxObjectShell* p = itr->second.maShell;
    2125 [ #  # ][ #  # ]:          0 :         itr->second.maLastAccess = Time( Time::SYSTEM );
                 [ #  # ]
    2126                 :          0 :         return static_cast<ScDocShell*>(p)->GetDocument();
    2127                 :            :     }
    2128                 :            : 
    2129         [ #  # ]:          0 :     itrEnd = maUnsavedDocShells.end();
    2130         [ #  # ]:          0 :     itr = maUnsavedDocShells.find(nFileId);
    2131         [ #  # ]:          0 :     if (itr != itrEnd)
    2132                 :            :     {
    2133                 :            :         //document is unsaved document
    2134                 :            : 
    2135         [ #  # ]:          0 :         SfxObjectShell* p = itr->second.maShell;
    2136 [ #  # ][ #  # ]:          0 :         itr->second.maLastAccess = Time( Time::SYSTEM );
                 [ #  # ]
    2137                 :          0 :         return static_cast<ScDocShell*>(p)->GetDocument();
    2138                 :            :     }
    2139                 :            : 
    2140         [ #  # ]:          0 :     const OUString* pFile = getExternalFileName(nFileId);
    2141         [ #  # ]:          0 :     if (!pFile)
    2142                 :            :         // no file name associated with this ID.
    2143                 :          0 :         return NULL;
    2144                 :            : 
    2145                 :          0 :     OUString aFilter;
    2146         [ #  # ]:          0 :     SrcShell aSrcDoc;
    2147 [ #  # ][ #  # ]:          0 :     aSrcDoc.maShell = loadSrcDocument(nFileId, aFilter);
                 [ #  # ]
    2148         [ #  # ]:          0 :     if (!aSrcDoc.maShell.Is())
    2149                 :            :     {
    2150                 :            :         // source document could not be loaded.
    2151                 :          0 :         return NULL;
    2152                 :            :     }
    2153                 :            : 
    2154         [ #  # ]:          0 :     if (maDocShells.empty())
    2155                 :            :     {
    2156                 :            :         // If this is the first source document insertion, start up the timer.
    2157         [ #  # ]:          0 :         maSrcDocTimer.Start();
    2158                 :            :     }
    2159                 :            : 
    2160 [ #  # ][ #  # ]:          0 :     maDocShells.insert(DocShellMap::value_type(nFileId, aSrcDoc));
                 [ #  # ]
    2161                 :          0 :     SfxObjectShell* p = aSrcDoc.maShell;
    2162                 :          0 :     ScDocument* pSrcDoc = static_cast<ScDocShell*>(p)->GetDocument();
    2163         [ #  # ]:          0 :     initDocInCache(maRefCache, pSrcDoc, nFileId);
    2164         [ #  # ]:          0 :     return pSrcDoc;
    2165                 :            : }
    2166                 :            : 
    2167                 :          0 : SfxObjectShellRef ScExternalRefManager::loadSrcDocument(sal_uInt16 nFileId, OUString& rFilter)
    2168                 :            : {
    2169         [ #  # ]:          0 :     const SrcFileData* pFileData = getExternalFileData(nFileId);
    2170         [ #  # ]:          0 :     if (!pFileData)
    2171                 :          0 :         return NULL;
    2172                 :            : 
    2173                 :            :     // Always load the document by using the path created from the relative
    2174                 :            :     // path.  If the referenced document is not there, simply exit.  The
    2175                 :            :     // original file name should be used only when the relative path is not
    2176                 :            :     // given.
    2177                 :          0 :     OUString aFile = pFileData->maFileName;
    2178         [ #  # ]:          0 :     maybeCreateRealFileName(nFileId);
    2179         [ #  # ]:          0 :     if (!pFileData->maRealFileName.isEmpty())
    2180                 :          0 :         aFile = pFileData->maRealFileName;
    2181                 :            : 
    2182 [ #  # ][ #  # ]:          0 :     if (!isFileLoadable(aFile))
    2183                 :          0 :         return NULL;
    2184                 :            : 
    2185                 :          0 :     OUString aOptions = pFileData->maFilterOptions;
    2186         [ #  # ]:          0 :     if ( !pFileData->maFilterName.isEmpty() )
    2187                 :          0 :         rFilter = pFileData->maFilterName;      // don't overwrite stored filter with guessed filter
    2188                 :            :     else
    2189         [ #  # ]:          0 :         ScDocumentLoader::GetFilterName(aFile, rFilter, aOptions, true, false);;
    2190         [ #  # ]:          0 :     ScDocumentLoader::GetFilterName(aFile, rFilter, aOptions, true, false);
    2191 [ #  # ][ #  # ]:          0 :     const SfxFilter* pFilter = ScDocShell::Factory().GetFilterContainer()->GetFilter4FilterName(rFilter);
         [ #  # ][ #  # ]
                 [ #  # ]
    2192                 :            : 
    2193         [ #  # ]:          0 :     if (pFileData->maRelativeName.isEmpty())
    2194                 :            :     {
    2195                 :            :         // Generate a relative file path.
    2196 [ #  # ][ #  # ]:          0 :         INetURLObject aBaseURL(getOwnDocumentName());
    2197 [ #  # ][ #  # ]:          0 :         aBaseURL.insertName(OUString(RTL_CONSTASCII_USTRINGPARAM("content.xml")));
    2198                 :            : 
    2199                 :            :         OUString aStr = URIHelper::simpleNormalizedMakeRelative(
    2200 [ #  # ][ #  # ]:          0 :             aBaseURL.GetMainURL(INetURLObject::NO_DECODE), aFile);
    2201                 :            : 
    2202 [ #  # ][ #  # ]:          0 :         setRelativeFileName(nFileId, aStr);
    2203                 :            :     }
    2204                 :            : 
    2205 [ #  # ][ #  # ]:          0 :     SfxItemSet* pSet = new SfxAllItemSet(SFX_APP()->GetPool());
                 [ #  # ]
    2206         [ #  # ]:          0 :     if (!aOptions.isEmpty())
    2207 [ #  # ][ #  # ]:          0 :         pSet->Put(SfxStringItem(SID_FILE_FILTEROPTIONS, aOptions));
         [ #  # ][ #  # ]
                 [ #  # ]
    2208                 :            : 
    2209                 :            :     // make medium hidden to prevent assertion from progress bar
    2210 [ #  # ][ #  # ]:          0 :     pSet->Put( SfxBoolItem(SID_HIDDEN, true) );
                 [ #  # ]
    2211                 :            : 
    2212                 :            :     SAL_WNODEPRECATED_DECLARATIONS_PUSH
    2213 [ #  # ][ #  # ]:          0 :     auto_ptr<SfxMedium> pMedium(new SfxMedium(aFile, STREAM_STD_READ, pFilter, pSet));
         [ #  # ][ #  # ]
    2214                 :            :     SAL_WNODEPRECATED_DECLARATIONS_POP
    2215 [ #  # ][ #  # ]:          0 :     if (pMedium->GetError() != ERRCODE_NONE)
    2216                 :          0 :         return NULL;
    2217                 :            : 
    2218                 :            :     // To load encrypted documents with password, user interaction needs to be enabled.
    2219         [ #  # ]:          0 :     pMedium->UseInteractionHandler(mbUserInteractionEnabled);
    2220                 :            : 
    2221 [ #  # ][ #  # ]:          0 :     ScDocShell* pNewShell = new ScDocShell(SFX_CREATE_MODE_INTERNAL);
    2222                 :          0 :     SfxObjectShellRef aRef = pNewShell;
    2223                 :            : 
    2224                 :            :     // increment the recursive link count of the source document.
    2225                 :          0 :     ScExtDocOptions* pExtOpt = mpDoc->GetExtDocOptions();
    2226 [ #  # ][ #  # ]:          0 :     sal_uInt32 nLinkCount = pExtOpt ? pExtOpt->GetDocSettings().mnLinkCnt : 0;
    2227                 :          0 :     ScDocument* pSrcDoc = pNewShell->GetDocument();
    2228                 :          0 :     pSrcDoc->EnableExecuteLink(false); // to prevent circular access of external references.
    2229         [ #  # ]:          0 :     pSrcDoc->EnableUndo(false);
    2230                 :          0 :     pSrcDoc->EnableAdjustHeight(false);
    2231                 :            : 
    2232                 :          0 :     ScExtDocOptions* pExtOptNew = pSrcDoc->GetExtDocOptions();
    2233         [ #  # ]:          0 :     if (!pExtOptNew)
    2234                 :            :     {
    2235 [ #  # ][ #  # ]:          0 :         pExtOptNew = new ScExtDocOptions;
    2236         [ #  # ]:          0 :         pSrcDoc->SetExtDocOptions(pExtOptNew);
    2237                 :            :     }
    2238         [ #  # ]:          0 :     pExtOptNew->GetDocSettings().mnLinkCnt = nLinkCount + 1;
    2239                 :            : 
    2240         [ #  # ]:          0 :     pNewShell->DoLoad(pMedium.release());
    2241                 :            : 
    2242                 :            :     // with UseInteractionHandler, options may be set by dialog during DoLoad
    2243         [ #  # ]:          0 :     OUString aNew = ScDocumentLoader::GetOptions(*pNewShell->GetMedium());
    2244 [ #  # ][ #  # ]:          0 :     if (!aNew.isEmpty() && aNew != aOptions)
                 [ #  # ]
    2245                 :          0 :         aOptions = aNew;
    2246         [ #  # ]:          0 :     setFilterData(nFileId, rFilter, aOptions);    // update the filter data, including the new options
    2247                 :            : 
    2248 [ #  # ][ #  # ]:          0 :     return aRef;
    2249                 :            : }
    2250                 :            : 
    2251                 :          0 : bool ScExternalRefManager::isFileLoadable(const OUString& rFile) const
    2252                 :            : {
    2253         [ #  # ]:          0 :     if (rFile.isEmpty())
    2254                 :          0 :         return false;
    2255                 :            : 
    2256 [ #  # ][ #  # ]:          0 :     if (isOwnDocument(rFile))
    2257                 :          0 :         return false;
    2258                 :          0 :     rtl::OUString aPhysical;
    2259 [ #  # ][ #  # ]:          0 :     if (utl::LocalFileHelper::ConvertURLToPhysicalName(rFile, aPhysical) && !aPhysical.isEmpty())
         [ #  # ][ #  # ]
    2260                 :            :     {
    2261                 :            :         // #i114504# try IsFolder/Exists only for file URLs
    2262                 :            : 
    2263 [ #  # ][ #  # ]:          0 :         if (utl::UCBContentHelper::IsFolder(rFile))
    2264                 :          0 :             return false;
    2265                 :            : 
    2266         [ #  # ]:          0 :         return utl::UCBContentHelper::Exists(rFile);
    2267                 :            :     }
    2268                 :            :     else
    2269                 :          0 :         return true;    // for http and others, Exists doesn't work, but the URL can still be opened
    2270                 :            : }
    2271                 :            : 
    2272                 :        174 : void ScExternalRefManager::maybeLinkExternalFile(sal_uInt16 nFileId)
    2273                 :            : {
    2274 [ +  - ][ +  + ]:        174 :     if (maLinkedDocs.count(nFileId))
    2275                 :            :         // file alerady linked, or the link has been broken.
    2276                 :            :         return;
    2277                 :            : 
    2278                 :            :     // Source document not linked yet.  Link it now.
    2279         [ +  - ]:          6 :     const OUString* pFileName = getExternalFileName(nFileId);
    2280         [ +  - ]:          6 :     if (!pFileName)
    2281                 :            :         return;
    2282                 :            : 
    2283                 :          6 :     OUString aFilter, aOptions;
    2284         [ +  - ]:          6 :     const SrcFileData* pFileData = getExternalFileData(nFileId);
    2285         [ +  - ]:          6 :     if (pFileData)
    2286                 :            :     {
    2287                 :          6 :         aFilter = pFileData->maFilterName;
    2288                 :          6 :         aOptions = pFileData->maFilterOptions;
    2289                 :            :     }
    2290                 :            :     // If a filter was already set (for example, loading the cached table),
    2291                 :            :     // don't call GetFilterName which has to access the source file.
    2292         [ +  - ]:          6 :     if (aFilter.isEmpty())
    2293         [ +  - ]:          6 :         ScDocumentLoader::GetFilterName(*pFileName, aFilter, aOptions, true, false);
    2294         [ +  - ]:          6 :     sfx2::LinkManager* pLinkMgr = mpDoc->GetLinkManager();
    2295 [ +  - ][ +  - ]:          6 :     ScExternalRefLink* pLink = new ScExternalRefLink(mpDoc, nFileId, aFilter);
         [ +  - ][ +  - ]
    2296                 :            :     OSL_ENSURE(pFileName, "ScExternalRefManager::insertExternalFileLink: file name pointer is NULL");
    2297         [ +  - ]:          6 :     String aTmp = aFilter;
    2298 [ +  - ][ +  - ]:          6 :     pLinkMgr->InsertFileLink(*pLink, OBJECT_CLIENT_FILE, *pFileName, &aTmp);
                 [ +  - ]
    2299                 :            : 
    2300                 :          6 :     pLink->SetDoReferesh(false);
    2301         [ +  - ]:          6 :     pLink->Update();
    2302                 :          6 :     pLink->SetDoReferesh(true);
    2303                 :            : 
    2304 [ +  - ][ +  - ]:        174 :     maLinkedDocs.insert(LinkedDocMap::value_type(nFileId, true));
                 [ +  - ]
    2305                 :            : }
    2306                 :            : 
    2307                 :        299 : void ScExternalRefManager::SrcFileData::maybeCreateRealFileName(const String& rOwnDocName)
    2308                 :            : {
    2309         [ -  + ]:        299 :     if (maRelativeName.isEmpty())
    2310                 :            :         // No relative path given.  Nothing to do.
    2311                 :            :         return;
    2312                 :            : 
    2313         [ #  # ]:          0 :     if (!maRealFileName.isEmpty())
    2314                 :            :         // Real file name already created.  Nothing to do.
    2315                 :            :         return;
    2316                 :            : 
    2317                 :            :     // Formulate the absolute file path from the relative path.
    2318                 :          0 :     const OUString& rRelPath = maRelativeName;
    2319 [ #  # ][ #  # ]:          0 :     INetURLObject aBaseURL(rOwnDocName);
    2320 [ #  # ][ #  # ]:          0 :     aBaseURL.insertName(OUString(RTL_CONSTASCII_USTRINGPARAM("content.xml")));
    2321                 :          0 :     bool bWasAbs = false;
    2322 [ #  # ][ #  # ]:        299 :     maRealFileName = aBaseURL.smartRel2Abs(rRelPath, bWasAbs).GetMainURL(INetURLObject::NO_DECODE);
         [ #  # ][ #  # ]
    2323                 :            : }
    2324                 :            : 
    2325                 :        299 : void ScExternalRefManager::maybeCreateRealFileName(sal_uInt16 nFileId)
    2326                 :            : {
    2327         [ -  + ]:        299 :     if (nFileId >= maSrcFiles.size())
    2328                 :        299 :         return;
    2329                 :            : 
    2330 [ +  - ][ +  - ]:        299 :     maSrcFiles[nFileId].maybeCreateRealFileName(getOwnDocumentName());
         [ +  - ][ +  - ]
    2331                 :            : }
    2332                 :            : 
    2333                 :        404 : OUString ScExternalRefManager::getOwnDocumentName() const
    2334                 :            : {
    2335                 :        404 :     SfxObjectShell* pShell = mpDoc->GetDocumentShell();
    2336         [ -  + ]:        404 :     if (!pShell)
    2337                 :            :         // This should not happen!
    2338                 :          0 :         return OUString();
    2339                 :            : 
    2340                 :        404 :     SfxMedium* pMed = pShell->GetMedium();
    2341         [ +  + ]:        404 :     if (!pMed)
    2342                 :        393 :         return OUString();
    2343                 :            : 
    2344                 :        404 :     return pMed->GetName();
    2345                 :            : }
    2346                 :            : 
    2347                 :        105 : bool ScExternalRefManager::isOwnDocument(const OUString& rFile) const
    2348                 :            : {
    2349                 :        105 :     return getOwnDocumentName().equals(rFile);
    2350                 :            : }
    2351                 :            : 
    2352                 :        105 : void ScExternalRefManager::convertToAbsName(OUString& rFile) const
    2353                 :            : {
    2354                 :            :     // unsaved documents have no AbsName
    2355         [ +  - ]:        105 :     TypeId aType(TYPE(ScDocShell));
    2356         [ +  - ]:        105 :     ScDocShell* pShell = static_cast<ScDocShell*>(SfxObjectShell::GetFirst(&aType, false));
    2357         [ +  + ]:       2880 :     while (pShell)
    2358                 :            :     {
    2359 [ +  - ][ +  - ]:       2775 :         if (rFile == rtl::OUString(pShell->GetName()))
                 [ +  - ]
    2360                 :        105 :             return;
    2361                 :            : 
    2362         [ +  - ]:       2775 :         pShell = static_cast<ScDocShell*>(SfxObjectShell::GetNext(*pShell, &aType, false));
    2363                 :            :     }
    2364                 :            : 
    2365                 :        105 :     SfxObjectShell* pDocShell = mpDoc->GetDocumentShell();
    2366 [ +  - ][ +  - ]:        105 :     rFile = ScGlobal::GetAbsDocName(rFile, pDocShell);
         [ +  - ][ +  - ]
                 [ +  - ]
    2367                 :            : }
    2368                 :            : 
    2369                 :        122 : sal_uInt16 ScExternalRefManager::getExternalFileId(const OUString& rFile)
    2370                 :            : {
    2371 [ +  - ][ +  - ]:        122 :     vector<SrcFileData>::const_iterator itrBeg = maSrcFiles.begin(), itrEnd = maSrcFiles.end();
    2372         [ +  - ]:        122 :     vector<SrcFileData>::const_iterator itr = find_if(itrBeg, itrEnd, FindSrcFileByName(rFile));
    2373 [ +  - ][ +  + ]:        122 :     if (itr != itrEnd)
    2374                 :            :     {
    2375         [ +  - ]:        111 :         size_t nId = distance(itrBeg, itr);
    2376                 :        111 :         return static_cast<sal_uInt16>(nId);
    2377                 :            :     }
    2378                 :            : 
    2379         [ +  - ]:         11 :     SrcFileData aData;
    2380                 :         11 :     aData.maFileName = rFile;
    2381         [ +  - ]:         11 :     maSrcFiles.push_back(aData);
    2382         [ +  - ]:        122 :     return static_cast<sal_uInt16>(maSrcFiles.size() - 1);
    2383                 :            : }
    2384                 :            : 
    2385                 :        299 : const OUString* ScExternalRefManager::getExternalFileName(sal_uInt16 nFileId, bool bForceOriginal)
    2386                 :            : {
    2387         [ -  + ]:        299 :     if (nFileId >= maSrcFiles.size())
    2388                 :          0 :         return NULL;
    2389                 :            : 
    2390         [ -  + ]:        299 :     if (bForceOriginal)
    2391                 :          0 :         return &maSrcFiles[nFileId].maFileName;
    2392                 :            : 
    2393                 :        299 :     maybeCreateRealFileName(nFileId);
    2394                 :            : 
    2395         [ -  + ]:        299 :     if (!maSrcFiles[nFileId].maRealFileName.isEmpty())
    2396                 :          0 :         return &maSrcFiles[nFileId].maRealFileName;
    2397                 :            : 
    2398                 :        299 :     return &maSrcFiles[nFileId].maFileName;
    2399                 :            : }
    2400                 :            : 
    2401                 :          0 : bool ScExternalRefManager::hasExternalFile(sal_uInt16 nFileId) const
    2402                 :            : {
    2403                 :          0 :     return nFileId < maSrcFiles.size();
    2404                 :            : }
    2405                 :            : 
    2406                 :          0 : bool ScExternalRefManager::hasExternalFile(const OUString& rFile) const
    2407                 :            : {
    2408                 :          0 :     vector<SrcFileData>::const_iterator itrBeg = maSrcFiles.begin(), itrEnd = maSrcFiles.end();
    2409         [ #  # ]:          0 :     vector<SrcFileData>::const_iterator itr = find_if(itrBeg, itrEnd, FindSrcFileByName(rFile));
    2410         [ #  # ]:          0 :     return itr != itrEnd;
    2411                 :            : }
    2412                 :            : 
    2413                 :          6 : const ScExternalRefManager::SrcFileData* ScExternalRefManager::getExternalFileData(sal_uInt16 nFileId) const
    2414                 :            : {
    2415         [ -  + ]:          6 :     if (nFileId >= maSrcFiles.size())
    2416                 :          0 :         return NULL;
    2417                 :            : 
    2418                 :          6 :     return &maSrcFiles[nFileId];
    2419                 :            : }
    2420                 :            : 
    2421                 :         87 : const OUString* ScExternalRefManager::getRealTableName(sal_uInt16 nFileId, const OUString& rTabName) const
    2422                 :            : {
    2423                 :         87 :     return maRefCache.getRealTableName(nFileId, rTabName);
    2424                 :            : }
    2425                 :            : 
    2426                 :          0 : const OUString* ScExternalRefManager::getRealRangeName(sal_uInt16 nFileId, const OUString& rRangeName) const
    2427                 :            : {
    2428                 :          0 :     return maRefCache.getRealRangeName(nFileId, rRangeName);
    2429                 :            : }
    2430                 :            : 
    2431                 :            : template<typename MapContainer>
    2432                 :          0 : void lcl_removeByFileId(sal_uInt16 nFileId, MapContainer& rMap)
    2433                 :            : {
    2434         [ #  # ]:          0 :     typename MapContainer::iterator itr = rMap.find(nFileId);
    2435 [ #  # ][ #  # ]:          0 :     if (itr != rMap.end())
    2436                 :            :     {
    2437                 :            :         // Close this document shell.
    2438 [ #  # ][ #  # ]:          0 :         itr->second.maShell->DoClose();
    2439         [ #  # ]:          0 :         rMap.erase(itr);
    2440                 :            :     }
    2441                 :          0 : }
    2442                 :            : 
    2443                 :          3 : void ScExternalRefManager::clearCache(sal_uInt16 nFileId)
    2444                 :            : {
    2445                 :          3 :     maRefCache.clearCache(nFileId);
    2446                 :          3 : }
    2447                 :            : 
    2448                 :          0 : void ScExternalRefManager::refreshNames(sal_uInt16 nFileId)
    2449                 :            : {
    2450                 :          0 :     clearCache(nFileId);
    2451                 :          0 :     lcl_removeByFileId(nFileId, maDocShells);
    2452                 :            : 
    2453         [ #  # ]:          0 :     if (maDocShells.empty())
    2454                 :          0 :         maSrcDocTimer.Stop();
    2455                 :            : 
    2456                 :            :     // Update all cells containing names from this source document.
    2457                 :          0 :     refreshAllRefCells(nFileId);
    2458                 :            : 
    2459                 :          0 :     notifyAllLinkListeners(nFileId, LINK_MODIFIED);
    2460                 :          0 : }
    2461                 :            : 
    2462                 :          0 : void ScExternalRefManager::breakLink(sal_uInt16 nFileId)
    2463                 :            : {
    2464                 :            :     // Turn all formula cells referencing this external document into static
    2465                 :            :     // cells.
    2466         [ #  # ]:          0 :     RefCellMap::iterator itrRefs = maRefCells.find(nFileId);
    2467 [ #  # ][ #  # ]:          0 :     if (itrRefs != maRefCells.end())
    2468                 :            :     {
    2469                 :            :         // Make a copy because removing the formula cells below will modify
    2470                 :            :         // the original container.
    2471 [ #  # ][ #  # ]:          0 :         RefCellSet aSet = itrRefs->second;
    2472         [ #  # ]:          0 :         for_each(aSet.begin(), aSet.end(), ConvertFormulaToStatic(mpDoc));
    2473         [ #  # ]:          0 :         maRefCells.erase(nFileId);
    2474                 :            :     }
    2475                 :            : 
    2476                 :            :     // Remove all named ranges that reference this document.
    2477                 :            : 
    2478                 :            :     // Global named ranges.
    2479         [ #  # ]:          0 :     ScRangeName* pRanges = mpDoc->GetRangeName();
    2480         [ #  # ]:          0 :     if (pRanges)
    2481         [ #  # ]:          0 :         removeRangeNamesBySrcDoc(*pRanges, nFileId);
    2482                 :            : 
    2483                 :            :     // Sheet-local named ranges.
    2484 [ #  # ][ #  # ]:          0 :     for (SCTAB i = 0, n = mpDoc->GetTableCount(); i < n; ++i)
    2485                 :            :     {
    2486         [ #  # ]:          0 :         pRanges = mpDoc->GetRangeName(i);
    2487         [ #  # ]:          0 :         if (pRanges)
    2488         [ #  # ]:          0 :             removeRangeNamesBySrcDoc(*pRanges, nFileId);
    2489                 :            :     }
    2490                 :            : 
    2491         [ #  # ]:          0 :     clearCache(nFileId);
    2492         [ #  # ]:          0 :     lcl_removeByFileId(nFileId, maDocShells);
    2493                 :            : 
    2494         [ #  # ]:          0 :     if (maDocShells.empty())
    2495         [ #  # ]:          0 :         maSrcDocTimer.Stop();
    2496                 :            : 
    2497         [ #  # ]:          0 :     LinkedDocMap::iterator itr = maLinkedDocs.find(nFileId);
    2498 [ #  # ][ #  # ]:          0 :     if (itr != maLinkedDocs.end())
    2499         [ #  # ]:          0 :         itr->second = false;
    2500                 :            : 
    2501         [ #  # ]:          0 :     notifyAllLinkListeners(nFileId, LINK_BROKEN);
    2502                 :          0 : }
    2503                 :            : 
    2504                 :          0 : void ScExternalRefManager::switchSrcFile(sal_uInt16 nFileId, const OUString& rNewFile, const OUString& rNewFilter)
    2505                 :            : {
    2506                 :          0 :     maSrcFiles[nFileId].maFileName = rNewFile;
    2507         [ #  # ]:          0 :     maSrcFiles[nFileId].maRelativeName = OUString();
    2508         [ #  # ]:          0 :     maSrcFiles[nFileId].maRealFileName = OUString();
    2509         [ #  # ]:          0 :     if (!maSrcFiles[nFileId].maFilterName.equals(rNewFilter))
    2510                 :            :     {
    2511                 :            :         // Filter type has changed.
    2512                 :          0 :         maSrcFiles[nFileId].maFilterName = rNewFilter;
    2513         [ #  # ]:          0 :         maSrcFiles[nFileId].maFilterOptions = OUString();
    2514                 :            :     }
    2515                 :          0 :     refreshNames(nFileId);
    2516                 :          0 : }
    2517                 :            : 
    2518                 :          0 : void ScExternalRefManager::setRelativeFileName(sal_uInt16 nFileId, const OUString& rRelUrl)
    2519                 :            : {
    2520         [ #  # ]:          0 :     if (nFileId >= maSrcFiles.size())
    2521                 :          0 :         return;
    2522                 :          0 :     maSrcFiles[nFileId].maRelativeName = rRelUrl;
    2523                 :            : }
    2524                 :            : 
    2525                 :          0 : void ScExternalRefManager::setFilterData(sal_uInt16 nFileId, const OUString& rFilterName, const OUString& rOptions)
    2526                 :            : {
    2527         [ #  # ]:          0 :     if (nFileId >= maSrcFiles.size())
    2528                 :          0 :         return;
    2529                 :          0 :     maSrcFiles[nFileId].maFilterName = rFilterName;
    2530                 :          0 :     maSrcFiles[nFileId].maFilterOptions = rOptions;
    2531                 :            : }
    2532                 :            : 
    2533                 :        262 : void ScExternalRefManager::clear()
    2534                 :            : {
    2535         [ +  - ]:        262 :     DocShellMap::iterator itrEnd = maDocShells.end();
    2536 [ +  - ][ -  + ]:        262 :     for (DocShellMap::iterator itr = maDocShells.begin(); itr != itrEnd; ++itr)
    2537 [ #  # ][ #  # ]:          0 :         itr->second.maShell->DoClose();
    2538                 :            : 
    2539         [ +  - ]:        262 :     maDocShells.clear();
    2540         [ +  - ]:        262 :     maSrcDocTimer.Stop();
    2541                 :        262 : }
    2542                 :            : 
    2543                 :        243 : bool ScExternalRefManager::hasExternalData() const
    2544                 :            : {
    2545                 :        243 :     return !maSrcFiles.empty();
    2546                 :            : }
    2547                 :            : 
    2548                 :          4 : void ScExternalRefManager::resetSrcFileData(const OUString& rBaseFileUrl)
    2549                 :            : {
    2550 [ #  # ][ +  - ]:          4 :     for (vector<SrcFileData>::iterator itr = maSrcFiles.begin(), itrEnd = maSrcFiles.end();
                 [ -  + ]
    2551                 :            :           itr != itrEnd; ++itr)
    2552                 :            :     {
    2553                 :            :         // Re-generate relative file name from the absolute file name.
    2554         [ #  # ]:          0 :         OUString aAbsName = itr->maRealFileName;
    2555         [ #  # ]:          0 :         if (aAbsName.isEmpty())
    2556         [ #  # ]:          0 :             aAbsName = itr->maFileName;
    2557                 :            : 
    2558         [ #  # ]:          0 :         itr->maRelativeName = URIHelper::simpleNormalizedMakeRelative(
    2559         [ #  # ]:          0 :             rBaseFileUrl, aAbsName);
    2560                 :          0 :     }
    2561                 :          4 : }
    2562                 :            : 
    2563                 :        229 : void ScExternalRefManager::removeRefCell(ScFormulaCell* pCell)
    2564                 :            : {
    2565 [ +  - ][ +  - ]:        229 :     for_each(maRefCells.begin(), maRefCells.end(), RemoveFormulaCell(pCell));
                 [ +  - ]
    2566                 :        229 : }
    2567                 :            : 
    2568                 :          0 : void ScExternalRefManager::addLinkListener(sal_uInt16 nFileId, LinkListener* pListener)
    2569                 :            : {
    2570         [ #  # ]:          0 :     LinkListenerMap::iterator itr = maLinkListeners.find(nFileId);
    2571 [ #  # ][ #  # ]:          0 :     if (itr == maLinkListeners.end())
    2572                 :            :     {
    2573                 :            :         pair<LinkListenerMap::iterator, bool> r = maLinkListeners.insert(
    2574 [ #  # ][ #  # ]:          0 :             LinkListenerMap::value_type(nFileId, LinkListeners()));
         [ #  # ][ #  # ]
                 [ #  # ]
    2575         [ #  # ]:          0 :         if (!r.second)
    2576                 :            :         {
    2577                 :            :             OSL_FAIL("insertion of new link listener list failed");
    2578                 :          0 :             return;
    2579                 :            :         }
    2580                 :            : 
    2581                 :          0 :         itr = r.first;
    2582                 :            :     }
    2583                 :            : 
    2584         [ #  # ]:          0 :     LinkListeners& rList = itr->second;
    2585         [ #  # ]:          0 :     rList.insert(pListener);
    2586                 :            : }
    2587                 :            : 
    2588                 :          0 : void ScExternalRefManager::removeLinkListener(sal_uInt16 nFileId, LinkListener* pListener)
    2589                 :            : {
    2590         [ #  # ]:          0 :     LinkListenerMap::iterator itr = maLinkListeners.find(nFileId);
    2591 [ #  # ][ #  # ]:          0 :     if (itr == maLinkListeners.end())
    2592                 :            :         // no listeners for a specified file.
    2593                 :          0 :         return;
    2594                 :            : 
    2595         [ #  # ]:          0 :     LinkListeners& rList = itr->second;
    2596         [ #  # ]:          0 :     rList.erase(pListener);
    2597                 :            : 
    2598         [ #  # ]:          0 :     if (rList.empty())
    2599                 :            :         // No more listeners for this file.  Remove its entry.
    2600         [ #  # ]:          0 :         maLinkListeners.erase(itr);
    2601                 :            : }
    2602                 :            : 
    2603                 :          0 : void ScExternalRefManager::removeLinkListener(LinkListener* pListener)
    2604                 :            : {
    2605 [ #  # ][ #  # ]:          0 :     LinkListenerMap::iterator itr = maLinkListeners.begin(), itrEnd = maLinkListeners.end();
    2606         [ #  # ]:          0 :     for (; itr != itrEnd; ++itr)
    2607 [ #  # ][ #  # ]:          0 :         itr->second.erase(pListener);
    2608                 :          0 : }
    2609                 :            : 
    2610                 :          0 : void ScExternalRefManager::notifyAllLinkListeners(sal_uInt16 nFileId, LinkUpdateType eType)
    2611                 :            : {
    2612         [ #  # ]:          0 :     LinkListenerMap::iterator itr = maLinkListeners.find(nFileId);
    2613 [ #  # ][ #  # ]:          0 :     if (itr == maLinkListeners.end())
    2614                 :            :         // no listeners for a specified file.
    2615                 :          0 :         return;
    2616                 :            : 
    2617         [ #  # ]:          0 :     LinkListeners& rList = itr->second;
    2618 [ #  # ][ #  # ]:          0 :     for_each(rList.begin(), rList.end(), NotifyLinkListener(nFileId, eType));
                 [ #  # ]
    2619                 :            : }
    2620                 :            : 
    2621                 :          0 : void ScExternalRefManager::purgeStaleSrcDocument(sal_Int32 nTimeOut)
    2622                 :            : {
    2623         [ #  # ]:          0 :     DocShellMap aNewDocShells;
    2624 [ #  # ][ #  # ]:          0 :     DocShellMap::iterator itr = maDocShells.begin(), itrEnd = maDocShells.end();
    2625         [ #  # ]:          0 :     for (; itr != itrEnd; ++itr)
    2626                 :            :     {
    2627                 :            :         // in 100th of a second.
    2628 [ #  # ][ #  # ]:          0 :         sal_Int32 nSinceLastAccess = (Time( Time::SYSTEM ) - itr->second.maLastAccess).GetTime();
                 [ #  # ]
    2629         [ #  # ]:          0 :         if (nSinceLastAccess < nTimeOut)
    2630 [ #  # ][ #  # ]:          0 :             aNewDocShells.insert(*itr);
    2631                 :            :         else
    2632                 :            :             // Timed out.  Let's close this.
    2633 [ #  # ][ #  # ]:          0 :             itr->second.maShell->DoClose();
    2634                 :            :     }
    2635         [ #  # ]:          0 :     maDocShells.swap(aNewDocShells);
    2636                 :            : 
    2637         [ #  # ]:          0 :     if (maDocShells.empty())
    2638 [ #  # ][ #  # ]:          0 :         maSrcDocTimer.Stop();
    2639                 :          0 : }
    2640                 :            : 
    2641                 :        156 : sal_uInt32 ScExternalRefManager::getMappedNumberFormat(sal_uInt16 nFileId, sal_uInt32 nNumFmt, const ScDocument* pSrcDoc)
    2642                 :            : {
    2643         [ +  - ]:        156 :     NumFmtMap::iterator itr = maNumFormatMap.find(nFileId);
    2644 [ +  - ][ +  + ]:        156 :     if (itr == maNumFormatMap.end())
    2645                 :            :     {
    2646                 :            :         // Number formatter map is not initialized for this external document.
    2647                 :            :         pair<NumFmtMap::iterator, bool> r = maNumFormatMap.insert(
    2648 [ +  - ][ +  - ]:          6 :             NumFmtMap::value_type(nFileId, SvNumberFormatterMergeMap()));
    2649                 :            : 
    2650         [ -  + ]:          6 :         if (!r.second)
    2651                 :            :             // insertion failed.
    2652                 :          0 :             return nNumFmt;
    2653                 :            : 
    2654                 :          6 :         itr = r.first;
    2655 [ +  - ][ +  - ]:          6 :         mpDoc->GetFormatTable()->MergeFormatter( *pSrcDoc->GetFormatTable());
                 [ +  - ]
    2656 [ +  - ][ +  - ]:          6 :         SvNumberFormatterMergeMap aMap = mpDoc->GetFormatTable()->ConvertMergeTableToMap();
    2657 [ +  - ][ +  - ]:          6 :         itr->second.swap(aMap);
    2658                 :            :     }
    2659         [ +  - ]:        156 :     const SvNumberFormatterMergeMap& rMap = itr->second;
    2660         [ +  - ]:        156 :     SvNumberFormatterMergeMap::const_iterator itrNumFmt = rMap.find(nNumFmt);
    2661 [ +  - ][ -  + ]:        156 :     if (itrNumFmt != rMap.end())
    2662                 :            :         // mapped value found.
    2663         [ #  # ]:          0 :         return itrNumFmt->second;
    2664                 :            : 
    2665                 :        156 :     return nNumFmt;
    2666                 :            : }
    2667                 :            : 
    2668                 :          0 : void ScExternalRefManager::transformUnsavedRefToSavedRef( SfxObjectShell* pShell )
    2669                 :            : {
    2670         [ #  # ]:          0 :     DocShellMap::iterator itr = maUnsavedDocShells.begin();
    2671 [ #  # ][ #  # ]:          0 :     while( itr != maUnsavedDocShells.end() )
    2672                 :            :     {
    2673 [ #  # ][ #  # ]:          0 :         if (&(itr->second.maShell) == pShell)
    2674                 :            :         {
    2675                 :            :             // found that the shell is marked as unsaved
    2676 [ #  # ][ #  # ]:          0 :             rtl::OUString aFileURL = pShell->GetMedium()->GetURLObject().GetMainURL(INetURLObject::DECODE_TO_IURI);
    2677 [ #  # ][ #  # ]:          0 :             switchSrcFile(itr->first, aFileURL, rtl::OUString());
    2678         [ #  # ]:          0 :             EndListening(*pShell);
    2679 [ #  # ][ #  # ]:          0 :             maUnsavedDocShells.erase(itr++);
    2680                 :            :         }
    2681                 :            :     }
    2682                 :          0 : }
    2683                 :            : 
    2684                 :          0 : void ScExternalRefManager::Notify( SfxBroadcaster&, const SfxHint& rHint )
    2685                 :            : {
    2686         [ #  # ]:          0 :     if ( rHint.ISA( SfxEventHint ) )
    2687                 :            :     {
    2688                 :          0 :         sal_uLong nEventId = ((SfxEventHint&)rHint).GetEventId();
    2689      [ #  #  # ]:          0 :         switch ( nEventId )
    2690                 :            :         {
    2691                 :            :             case SFX_EVENT_PREPARECLOSEDOC:
    2692                 :            :                 {
    2693                 :          0 :                     SfxObjectShell* pObjShell = static_cast<const SfxEventHint&>( rHint ).GetObjShell();
    2694                 :          0 :                     ScDocShell* pDocShell = static_cast< ScDocShell* >( pObjShell );
    2695                 :            :                     WarningBox aBox(  pDocShell->GetActiveDialogParent(), WinBits( WB_OK ),
    2696 [ #  # ][ #  # ]:          0 :                                         ScGlobal::GetRscString( STR_CLOSE_WITH_UNSAVED_REFS ) );
                 [ #  # ]
    2697 [ #  # ][ #  # ]:          0 :                     aBox.Execute();
    2698                 :            :                 }
    2699                 :          0 :                 break;
    2700                 :            :             case SFX_EVENT_SAVEDOCDONE:
    2701                 :            :             case SFX_EVENT_SAVEASDOCDONE:
    2702                 :            :                 {
    2703                 :          0 :                     SfxObjectShell* pObjShell = static_cast<const SfxEventHint&>( rHint ).GetObjShell();
    2704                 :          0 :                     transformUnsavedRefToSavedRef(pObjShell);
    2705                 :            :                 }
    2706                 :          0 :                 break;
    2707                 :            :             default:
    2708                 :          0 :                 break;
    2709                 :            :         }
    2710                 :            :     }
    2711                 :          0 : }
    2712                 :            : 
    2713                 :          0 : IMPL_LINK(ScExternalRefManager, TimeOutHdl, AutoTimer*, pTimer)
    2714                 :            : {
    2715         [ #  # ]:          0 :     if (pTimer == &maSrcDocTimer)
    2716                 :          0 :         purgeStaleSrcDocument(SRCDOC_LIFE_SPAN);
    2717                 :            : 
    2718                 :          0 :     return 0;
    2719                 :            : }
    2720                 :            : 
    2721                 :            : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10