diff options
Diffstat (limited to 'sc/source/ui/docshell/externalrefmgr.cxx')
-rw-r--r-- | sc/source/ui/docshell/externalrefmgr.cxx | 76 |
1 files changed, 75 insertions, 1 deletions
diff --git a/sc/source/ui/docshell/externalrefmgr.cxx b/sc/source/ui/docshell/externalrefmgr.cxx index f9de3e8c0c48..1bfdc8b5b88f 100644 --- a/sc/source/ui/docshell/externalrefmgr.cxx +++ b/sc/source/ui/docshell/externalrefmgr.cxx @@ -74,6 +74,7 @@ using ::rtl::OUString; using ::std::vector; using ::std::find; using ::std::find_if; +using ::std::remove_if; using ::std::distance; using ::std::pair; using ::std::list; @@ -85,7 +86,7 @@ using namespace formula; namespace { -class TabNameSearchPredicate : public unary_function<bool, ScExternalRefCache::TableName> +class TabNameSearchPredicate : public unary_function<ScExternalRefCache::TableName, bool> { public: explicit TabNameSearchPredicate(const String& rSearchName) : @@ -201,6 +202,56 @@ private: ScDocument* mpDoc; }; +/** + * Check whether a named range contains an external reference to a + * particular document. + */ +bool hasRefsToSrcDoc(ScRangeData& rData, sal_uInt16 nFileId) +{ + ScTokenArray* pArray = rData.GetCode(); + if (!pArray) + return false; + + pArray->Reset(); + ScToken* p = static_cast<ScToken*>(pArray->GetNextReference()); + for (; p; p = static_cast<ScToken*>(pArray->GetNextReference())) + { + if (!p->IsExternalRef()) + continue; + + if (p->GetIndex() == nFileId) + return true; + } + return false; +} + +class EraseRangeByIterator : unary_function<ScRangeName::iterator, void> +{ + ScRangeName& mrRanges; +public: + EraseRangeByIterator(ScRangeName& rRanges) : mrRanges(rRanges) {} + void operator() (const ScRangeName::iterator& itr) + { + mrRanges.erase(itr); + } +}; + +/** + * Remove all named ranges that contain references to specified source + * document. + */ +void removeRangeNamesBySrcDoc(ScRangeName& rRanges, sal_uInt16 nFileId) +{ + ScRangeName::iterator itr = rRanges.begin(), itrEnd = rRanges.end(); + vector<ScRangeName::iterator> v; + for (; itr != itrEnd; ++itr) + { + if (hasRefsToSrcDoc(*itr, nFileId)) + v.push_back(itr); + } + for_each(v.begin(), v.end(), EraseRangeByIterator(rRanges)); +} + } // ============================================================================ @@ -2358,9 +2409,14 @@ void lcl_removeByFileId(sal_uInt16 nFileId, MapContainer& rMap) { typename MapContainer::iterator itr = rMap.find(nFileId); if (itr != rMap.end()) + { + // Close this document shell. + itr->second.maShell->DoClose(); rMap.erase(itr); + } } + void ScExternalRefManager::refreshNames(sal_uInt16 nFileId) { maRefCache.clearCache(nFileId); @@ -2389,6 +2445,21 @@ void ScExternalRefManager::breakLink(sal_uInt16 nFileId) maRefCells.erase(nFileId); } + // Remove all named ranges that reference this document. + + // Global named ranges. + ScRangeName* pRanges = mpDoc->GetRangeName(); + if (pRanges) + removeRangeNamesBySrcDoc(*pRanges, nFileId); + + // Sheet-local named ranges. + for (SCTAB i = 0, n = mpDoc->GetTableCount(); i < n; ++i) + { + pRanges = mpDoc->GetRangeName(i); + if (pRanges) + removeRangeNamesBySrcDoc(*pRanges, nFileId); + } + lcl_removeByFileId(nFileId, maDocShells); if (maDocShells.empty()) @@ -2528,6 +2599,9 @@ void ScExternalRefManager::purgeStaleSrcDocument(sal_Int32 nTimeOut) sal_Int32 nSinceLastAccess = (Time() - itr->second.maLastAccess).GetTime(); if (nSinceLastAccess < nTimeOut) aNewDocShells.insert(*itr); + else + // Timed out. Let's close this. + itr->second.maShell->DoClose(); } maDocShells.swap(aNewDocShells); |