ooo-build r13205 - in trunk: . patches/test
- From: kyoshida svn gnome org
- To: svn-commits-list gnome org
- Subject: ooo-build r13205 - in trunk: . patches/test
- Date: Mon, 14 Jul 2008 21:13:15 +0000 (UTC)
Author: kyoshida
Date: Mon Jul 14 21:13:14 2008
New Revision: 13205
URL: http://svn.gnome.org/viewvc/ooo-build?rev=13205&view=rev
Log:
2008-07-14 Kohei Yoshida <kyoshida novell com>
* patches/test/calc-external-defined-names.diff: refresh, modify, and
break link support added.
Modified:
trunk/ChangeLog
trunk/patches/test/calc-external-defined-names.diff
Modified: trunk/patches/test/calc-external-defined-names.diff
==============================================================================
--- trunk/patches/test/calc-external-defined-names.diff (original)
+++ trunk/patches/test/calc-external-defined-names.diff Mon Jul 14 21:13:14 2008
@@ -135,10 +135,10 @@
@return TRUE = Sheet created, rnTab contains valid sheet index. */
diff --git sc/inc/externalrefmgr.hxx sc/inc/externalrefmgr.hxx
new file mode 100644
-index 0000000..b5427ec
+index 0000000..303d90b
--- /dev/null
+++ sc/inc/externalrefmgr.hxx
-@@ -0,0 +1,164 @@
+@@ -0,0 +1,210 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
@@ -172,12 +172,15 @@
+#ifndef SC_EXTERNALREFMGR_HXX
+#define SC_EXTERNALREFMGR_HXX
+
-+#include "sfx2/objsh.hxx"
-+#include "sfx2/lnkbase.hxx"
+#include "global.hxx"
+#include "address.hxx"
++#include "sfx2/objsh.hxx"
++#include "sfx2/lnkbase.hxx"
++#include "tools/time.hxx"
++#include "vcl/timer.hxx"
+
+#include <hash_map>
++#include <hash_set>
+#include <boost/shared_ptr.hpp>
+#include <vector>
+
@@ -191,28 +194,32 @@
+class ScExternalRefLink : public ::sfx2::SvBaseLink
+{
+public:
-+ ScExternalRefLink(ScDocument* pDoc, const String& rFile, const String& rFilter);
++ ScExternalRefLink(ScDocument* pDoc, sal_uInt16 nFileId, const String& rFilter);
+ virtual ~ScExternalRefLink();
+
+ virtual void Closed();
+ virtual void DataChanged(const String& rMimeType, const ::com::sun::star::uno::Any & rValue);
+ virtual void Edit(Window* pParent, const Link& rEndEditHdl);
+
++ void SetDoReferesh(bool b);
++
+private:
+ ScExternalRefLink(); // disabled
+ ScExternalRefLink(const ScExternalRefLink&); // disabled
+
+ DECL_LINK(EndEditHdl, void*);
+
-+ String maFileName;
++ sal_uInt16 mnFileId;
+ String maFilterName;
+ ScDocument* mpDoc;
++ bool mbDoRefresh;
+};
+
+// ============================================================================
+
+class ScExternalRefManager
+{
++private:
+ struct AddressHash
+ {
+ size_t operator()(const ScAddress& rAddr) const
@@ -232,13 +239,23 @@
+ }
+ };
+
++ struct SrcDoc
++ {
++ SfxObjectShellRef maShell;
++ Time maLastAccess;
++ };
++
+ typedef ::boost::shared_ptr<ScToken> TokenRef;
+ typedef ::boost::shared_ptr<ScTokenArray> TokenArrayRef;
+
-+ typedef ::std::hash_map<String, SfxObjectShellRef, ScStringHashCode, ::std::equal_to<String> > DocShellMap;
++ typedef ::std::hash_map<sal_uInt16, SrcDoc > DocShellMap;
+ typedef ::std::hash_map<ScAddress, TokenRef, AddressHash, ::std::equal_to<ScAddress> > SingleTokenMap;
+ typedef ::std::hash_map<ScRange, TokenArrayRef, RangeHash, ::std::equal_to<ScRange> > DoubleTokenMap;
+ typedef ::std::hash_map<String, TokenArrayRef, ScStringHashCode, ::std::equal_to<String> > RangeNameMap;
++ typedef ::std::hash_set<sal_uInt16, ScStringHashCode, ::std::equal_to<String> > LinkedDocSet;
++
++ typedef ::std::hash_set<ScAddress, AddressHash, ::std::equal_to<ScAddress> > RefCellSet;
++ typedef ::std::hash_map<sal_uInt16, RefCellSet> RefCellMap;
+
+ /**
+ * Cached content of a single external document
@@ -250,39 +267,56 @@
+ RangeNameMap maRangeNames;
+ };
+ typedef ::boost::shared_ptr<DocCache> DocCacheRef;
-+
-+ typedef ::std::hash_map<String, DocCacheRef, ScStringHashCode, ::std::equal_to<String> > DocCacheMap;
++ typedef ::std::hash_map<sal_uInt16, DocCacheRef> DocCacheMap;
+
+public:
+ explicit ScExternalRefManager(ScDocument* pDoc);
+ ~ScExternalRefManager();
+
-+ ScToken* getSingleRefToken(const String& rFile, const ScAddress& rCell);
-+ ScTokenArray* getDoubleRefTokens(const String& rFile, const ScRange& rRange);
++ ScToken* getSingleRefToken(sal_uInt16 nFileId, const ScAddress& rCell, const ScAddress& rCurPos);
++ ScTokenArray* getDoubleRefTokens(sal_uInt16 nFileId, const ScRange& rRange, const ScAddress& rCurPos);
+
+ /**
+ * Get an array of tokens corresponding with a specified name in a
+ * specified file.
+ *
-+ * @return a new instance of ScTokenArray. The caller must manage its
-+ * life cycle.
++ * @return ScTokenArray instance
+ */
-+ ScTokenArray* getRangeNameTokens(const String& rFile, const String& rName, const ScAddress& rCurPos);
++ ScTokenArray* getRangeNameTokens(sal_uInt16 nFileId, const String& rName, const ScAddress& rCurPos);
+
+ sal_uInt16 getExternalFileId(const String& rFile);
+ const String* getExternalFileName(sal_uInt16 nIndex) const;
+
-+ void refreshNames(const String& rFile);
-+ void switchSrcFile(const String& rOldFile, const String& rNewFile);
++ void refreshNames(sal_uInt16 nFileId);
++ void switchSrcFile(sal_uInt16 nFileId, const String& rNewFile);
++ void removeSrcDocument(sal_uInt16 nFileId, bool bBreakLink);
+ void clear();
+
+private:
+ ScExternalRefManager();
+ ScExternalRefManager(const ScExternalRefManager&);
+
-+ DocCache* getDocumentCache(const String& rFile);
-+ ScDocument* getSrcDocument(const String& rFile);
-+ void insertExternalFileLink(const String& rFile, const String& rFilterName);
++ ScToken* getSingleRefToken(sal_uInt16 nFileId, const ScAddress& rCell);
++ ScTokenArray* getDoubleRefTokens(sal_uInt16 nFileId, const ScRange& rRange);
++
++ void refreshAllReferencingCells(sal_uInt16 nFileId);
++
++ void insertReferencingCell(sal_uInt16 nFileId, const ScAddress& rCell);
++
++ DocCache* getDocumentCache(sal_uInt16 nFileId);
++ ScDocument* getSrcDocument(sal_uInt16 nFileId);
++ SfxObjectShellRef loadSrcDocument(const String& rFile, String& rFilter);
++ void insertExternalFileLink(sal_uInt16 nFileId, const String& rFilterName);
++
++ bool compileTokensByCell(const ScAddress& rCell);
++
++ /**
++ * Purge those source document instances that have not been accessed for
++ * the specified duration.
++ *
++ * @param nTimeOut time out value in 100th of a second
++ */
++ void purgeStaleSrcDocument(sal_Int32 nTimeOut);
+
+private:
+ ScDocument* mpDoc;
@@ -297,8 +331,20 @@
+ /** cache only of referenced ranges and names from source documents. */
+ DocCacheMap maCachedDocContents;
+
++ /** list of source documents that are managed by the link manager. */
++ LinkedDocSet maLinkedDocs;
++
++ /**
++ * List of referencing cells that may contain external names. There is
++ * one list per source document.
++ */
++ RefCellMap maRefCells;
++
+ /** original source file index. */
+ ::std::vector<String> maFileNames;
++
++ AutoTimer maSrcDocTimer;
++ DECL_LINK(TimeOutHdl, AutoTimer*);
+};
+
+
@@ -363,10 +409,18 @@
/** Xcl import may play dirty tricks with OpCode!=ocExternal.
Others don't use! */
diff --git sc/source/core/data/documen2.cxx sc/source/core/data/documen2.cxx
-index 6dd6697..69e45fb 100644
+index 6dd6697..60a3a4a 100644
--- sc/source/core/data/documen2.cxx
+++ sc/source/core/data/documen2.cxx
-@@ -140,6 +140,7 @@ ScDocument::ScDocument( ScDocumentMode eMode,
+@@ -93,6 +93,7 @@
+ #include "listenercalls.hxx"
+ #include "recursionhelper.hxx"
+ #include "lookupcache.hxx"
++#include "externalrefmgr.hxx"
+ #include <com/sun/star/document/XVbaEventsHelper.hpp>
+
+ // pImpl because including lookupcache.hxx in document.hxx isn't wanted, and
+@@ -140,6 +141,7 @@ ScDocument::ScDocument( ScDocumentMode eMode,
pScriptTypeData( NULL ),
pCacheFieldEditEngine( NULL ),
pDocProtection( NULL ),
@@ -374,6 +428,18 @@
pViewOptions( NULL ),
pDocOptions( NULL ),
pExtDocOptions( NULL ),
+@@ -369,6 +371,11 @@ ScDocument::~ScDocument()
+ pLinkManager->Remove( 0, pLinkManager->GetLinks().Count() );
+ }
+
++ if (pExternalRefMgr.get())
++ // Destroy the external ref mgr instance here because it has a timer
++ // which needs to be stopped before the app closes.
++ pExternalRefMgr.reset(NULL);
++
+ ScAddInAsync::RemoveDocument( this );
+ ScAddInListener::RemoveDocument( this );
+ delete pChartListenerCollection; // vor pBASM wg. evtl. Listener!
diff --git sc/source/core/data/documen3.cxx sc/source/core/data/documen3.cxx
index 541e2e4..20dae1e 100644
--- sc/source/core/data/documen3.cxx
@@ -413,7 +479,7 @@
const String& rFilterName, const String& rFilterOpt, const String& rTabName )
{
diff --git sc/source/core/tool/compiler.cxx sc/source/core/tool/compiler.cxx
-index 7caea76..106514c 100644
+index 7caea76..10e0ccb 100644
--- sc/source/core/tool/compiler.cxx
+++ sc/source/core/tool/compiler.cxx
@@ -73,9 +73,13 @@
@@ -601,10 +667,10 @@
+ SetError(errNoName);
+
+ const String& rName = pToken->GetString();
-+ ScTokenArray* pNew = pRefMgr->getRangeNameTokens(*pFile, rName, aPos);
++ ScTokenArray* pNew = pRefMgr->getRangeNameTokens(pToken->GetIndex(), rName, aPos);
+ if (pNew)
+ {
-+ PushTokenArray(pNew, true);
++ PushTokenArray(pNew->Clone(), true);
+ return GetToken();
+ }
+ SetError(errNoName);
@@ -801,7 +867,7 @@
break;
diff --git sc/source/filter/excel/tokstack.cxx sc/source/filter/excel/tokstack.cxx
-index 20ada63..091de84 100644
+index 20ada63..821a4ad 100644
--- sc/source/filter/excel/tokstack.cxx
+++ sc/source/filter/excel/tokstack.cxx
@@ -395,6 +395,16 @@ void TokenPool::GetElement( const UINT16 nId )
@@ -838,7 +904,7 @@
default:
DBG_ERROR("-TokenPool::GetElementRek(): Zustand undefiniert!?");
}
-@@ -724,6 +744,24 @@ const TokenId TokenPool::StoreMatrix( SCSIZE nC, SCSIZE nR )
+@@ -724,9 +744,28 @@ const TokenId TokenPool::StoreMatrix( SCSIZE nC, SCSIZE nR )
return ( const TokenId ) nElementAkt;
}
@@ -863,6 +929,10 @@
void TokenPool::Reset( void )
{
nP_IdAkt = nP_IdLast = nElementAkt = nP_StrAkt = nP_DblAkt = nP_ErrAkt = nP_RefTrAkt = nP_ExtAkt = nP_NlfAkt = nP_MatrixAkt = 0;
++ maExtNames.clear();
+ }
+
+
diff --git sc/source/filter/excel/xilink.cxx sc/source/filter/excel/xilink.cxx
index e351863..b58f6ec 100644
--- sc/source/filter/excel/xilink.cxx
@@ -966,10 +1036,10 @@
For OLE object links: Decodes to class name and document URL.
diff --git sc/source/ui/docshell/externalrefmgr.cxx sc/source/ui/docshell/externalrefmgr.cxx
new file mode 100644
-index 0000000..52074f9
+index 0000000..adb7452
--- /dev/null
+++ sc/source/ui/docshell/externalrefmgr.cxx
-@@ -0,0 +1,564 @@
+@@ -0,0 +1,788 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
@@ -1017,6 +1087,9 @@
+#include "scextopt.hxx"
+#include "rangenam.hxx"
+#include "cell.hxx"
++#include "viewdata.hxx"
++#include "tabvwsh.hxx"
++#include "sc.hrc"
+
+#include "sfx2/app.hxx"
+#include "sfx2/docfilt.hxx"
@@ -1024,6 +1097,8 @@
+#include "sfx2/fcontnr.hxx"
+#include "sfx2/sfxsids.hrc"
+#include "sfx2/objsh.hxx"
++#include "svtools/broadcast.hxx"
++#include "svtools/smplhint.hxx"
+#include "svtools/itemset.hxx"
+#include "svtools/stritem.hxx"
+#include "svx/linkmgr.hxx"
@@ -1037,11 +1112,12 @@
+using ::std::find;
+using ::std::distance;
+
-+ScExternalRefLink::ScExternalRefLink(ScDocument* pDoc, const String& rFile, const String& rFilter) :
++ScExternalRefLink::ScExternalRefLink(ScDocument* pDoc, sal_uInt16 nFileId, const String& rFilter) :
+ ::sfx2::SvBaseLink(::sfx2::LINKUPDATE_ONCALL, FORMAT_FILE),
-+ maFileName(rFile),
++ mnFileId(nFileId),
+ maFilterName(rFilter),
-+ mpDoc(pDoc)
++ mpDoc(pDoc),
++ mbDoRefresh(true)
+{
+}
+
@@ -1051,24 +1127,31 @@
+
+void ScExternalRefLink::Closed()
+{
-+ fprintf(stdout, "ScExternalRefLink::Closed: --begin\n");
-+ fprintf(stdout, "ScExternalRefLink::Closed: --end\n");
++ ScExternalRefManager* pMgr = mpDoc->GetExternalRefManager();
++ pMgr->removeSrcDocument(mnFileId, true);
+}
+
+void ScExternalRefLink::DataChanged(const String& /*rMimeType*/, const Any& /*rValue*/)
+{
++ if (!mbDoRefresh)
++ return;
++
+ String aFile, aFilter;
+ mpDoc->GetLinkManager()->GetDisplayNames(this, NULL, &aFile, NULL, &aFilter);
+ ScExternalRefManager* pMgr = mpDoc->GetExternalRefManager();
++ const String* pCurFile = pMgr->getExternalFileName(mnFileId);
++ if (!pCurFile)
++ return;
+
-+ if (maFileName.Equals(aFile))
++ if (pCurFile->Equals(aFile))
+ {
-+ pMgr->refreshNames(aFile);
++ // Refresh the current source document.
++ pMgr->refreshNames(mnFileId);
+ }
+ else
+ {
-+ pMgr->switchSrcFile(maFileName, aFile);
-+ maFileName = aFile;
++ // The source document has changed.
++ pMgr->switchSrcFile(mnFileId, aFile);
+ maFilterName = aFilter;
+ }
+}
@@ -1078,6 +1161,11 @@
+ SvBaseLink::Edit(pParent, LINK(this, ScExternalRefLink, EndEditHdl));
+}
+
++void ScExternalRefLink::SetDoReferesh(bool b)
++{
++ mbDoRefresh = b;
++}
++
+IMPL_LINK(ScExternalRefLink, EndEditHdl, void*, EMPTYARG)
+{
+ return 0;
@@ -1214,6 +1302,9 @@
+ScExternalRefManager::ScExternalRefManager(ScDocument* pDoc) :
+ mpDoc(pDoc)
+{
++ maSrcDocTimer.SetTimeoutHdl( LINK(this, ScExternalRefManager, TimeOutHdl) );
++// maSrcDocTimer.SetTimeout(60000*5); // every 5 minutes
++ maSrcDocTimer.SetTimeout(1000*2); // every 2 seconds
+}
+
+ScExternalRefManager::~ScExternalRefManager()
@@ -1221,17 +1312,24 @@
+ clear();
+}
+
-+ScToken* ScExternalRefManager::getSingleRefToken(const String& rFile, const ScAddress& rCell)
++ScToken* ScExternalRefManager::getSingleRefToken(sal_uInt16 nFileId, const ScAddress& rCell, const ScAddress& rCurPos)
++{
++ // TODO: add the current cell position to the list.
++ return getSingleRefToken(nFileId, rCell);
++}
++
++ScToken* ScExternalRefManager::getSingleRefToken(sal_uInt16 nFileId, const ScAddress& rCell)
+{
+ {
+ String aStr;
+ rCell.Format(aStr, SCA_ABS_3D);
++ const String *pFile = getExternalFileName(nFileId);
+ fprintf(stdout, "ScExternalRefManager::getSingleRefToken: --begin (file = '%s'; address = '%s')\n",
-+ rtl::OUStringToOString(rFile, RTL_TEXTENCODING_UTF8).getStr(),
++ rtl::OUStringToOString(*pFile, RTL_TEXTENCODING_UTF8).getStr(),
+ rtl::OUStringToOString(aStr, RTL_TEXTENCODING_UTF8).getStr());
+ }
+
-+ SingleTokenMap& rMap = getDocumentCache(rFile)->maSingleTokens;
++ SingleTokenMap& rMap = getDocumentCache(nFileId)->maSingleTokens;
+ SingleTokenMap::iterator itr = rMap.find(rCell);
+ if (itr != rMap.end())
+ {
@@ -1241,7 +1339,7 @@
+ }
+
+ // reference not cached. read from the source document.
-+ ScDocument* pSrcDoc = getSrcDocument(rFile);
++ ScDocument* pSrcDoc = getSrcDocument(nFileId);
+ if (!pSrcDoc)
+ return NULL;
+
@@ -1260,17 +1358,24 @@
+ return pTok.get();
+}
+
-+ScTokenArray* ScExternalRefManager::getDoubleRefTokens(const String& rFile, const ScRange& rRange)
++ScTokenArray* ScExternalRefManager::getDoubleRefTokens(sal_uInt16 nFileId, const ScRange& rRange, const ScAddress& rCurPos)
++{
++ // TODO: add the current cell position to the list of affected cells.
++ return getDoubleRefTokens(nFileId, rRange);
++}
++
++ScTokenArray* ScExternalRefManager::getDoubleRefTokens(sal_uInt16 nFileId, const ScRange& rRange)
+{
+ {
+ String aStr;
+ rRange.Format(aStr, SCR_ABS_3D, mpDoc);
++ const String *pFile = getExternalFileName(nFileId);
+ fprintf(stdout, "ScExternalRefManager::getDoubleRefToken: --begin (file = '%s'; range = '%s)\n",
-+ rtl::OUStringToOString(rFile, RTL_TEXTENCODING_UTF8).getStr(),
++ rtl::OUStringToOString(*pFile, RTL_TEXTENCODING_UTF8).getStr(),
+ rtl::OUStringToOString(aStr, RTL_TEXTENCODING_UTF8).getStr());
+ }
+
-+ DoubleTokenMap& rMap = getDocumentCache(rFile)->maDoubleTokens;
++ DoubleTokenMap& rMap = getDocumentCache(nFileId)->maDoubleTokens;
+ DoubleTokenMap::iterator itr = rMap.find(rRange);
+ if (itr != rMap.end())
+ {
@@ -1280,7 +1385,7 @@
+ }
+
+ // reference not cached. read from the source document.
-+ ScDocument* pSrcDoc = getSrcDocument(rFile);
++ ScDocument* pSrcDoc = getSrcDocument(nFileId);
+ if (!pSrcDoc)
+ return NULL;
+
@@ -1297,26 +1402,31 @@
+ return pArray.get();
+}
+
-+ScTokenArray* ScExternalRefManager::getRangeNameTokens(const String& rFile, const String& rName, const ScAddress& rCurPos)
++ScTokenArray* ScExternalRefManager::getRangeNameTokens(sal_uInt16 nFileId, const String& rName, const ScAddress& rCurPos)
+{
-+ String aCellStr;
-+ rCurPos.Format(aCellStr, SCA_ABS_3D);
-+ fprintf(stdout, "ScExternalRefManager::getRangeNameTokens: --begin (file = '%s'; name = '%s'; pos = '%s')\n",
-+ rtl::OUStringToOString(rFile, RTL_TEXTENCODING_UTF8).getStr(),
-+ rtl::OUStringToOString(rName, RTL_TEXTENCODING_UTF8).getStr(),
-+ rtl::OUStringToOString(aCellStr, RTL_TEXTENCODING_UTF8).getStr());
++ {
++ String aCellStr;
++ rCurPos.Format(aCellStr, SCA_ABS_3D);
++ const String* pFile = getExternalFileName(nFileId);
++ fprintf(stdout, "ScExternalRefManager::getRangeNameTokens: --begin (file = '%s'; name = '%s'; pos = '%s')\n",
++ rtl::OUStringToOString(*pFile, RTL_TEXTENCODING_UTF8).getStr(),
++ rtl::OUStringToOString(rName, RTL_TEXTENCODING_UTF8).getStr(),
++ rtl::OUStringToOString(aCellStr, RTL_TEXTENCODING_UTF8).getStr());
++ }
++
++ insertReferencingCell(nFileId, rCurPos);
+
+ // First, check if this name has already been cached.
-+ RangeNameMap& rMap = getDocumentCache(rFile)->maRangeNames;
++ RangeNameMap& rMap = getDocumentCache(nFileId)->maRangeNames;
+ RangeNameMap::iterator itr = rMap.find(rName);
+ if (itr != rMap.end())
+ {
+ fprintf(stdout, "ScExternalRefManager::getRangeNameTokens: name is cached\n");
+ // this name is cached.
-+ return itr->second->Clone();
++ return itr->second.get();
+ }
+
-+ ScDocument* pSrcDoc = getSrcDocument(rFile);
++ ScDocument* pSrcDoc = getSrcDocument(nFileId);
+ if (!pSrcDoc)
+ return NULL;
+
@@ -1355,7 +1465,7 @@
+ // source document, and convert it to a static value.
+
+ aRef.CalcAbsIfRel(rCurPos);
-+ ScToken* pTok = getSingleRefToken(rFile, ScAddress(aRef.nCol, aRef.nRow, aRef.nTab));
++ ScToken* pTok = getSingleRefToken(nFileId, ScAddress(aRef.nCol, aRef.nRow, aRef.nTab));
+ if (pTok)
+ {
+ pNew->AddToken(*pTok);
@@ -1378,7 +1488,7 @@
+ SCsCOL nCol2 = aComRef.Ref2.nCol;
+ SCsROW nRow2 = aComRef.Ref2.nRow;
+
-+ ScTokenArray* pArray = getDoubleRefTokens(rFile, ScRange(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2));
++ ScTokenArray* pArray = getDoubleRefTokens(nFileId, ScRange(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2));
+ if (pArray)
+ {
+ for (ScToken* p = pArray->First(); p; p = pArray->Next())
@@ -1397,77 +1507,210 @@
+
+ rMap.insert(RangeNameMap::value_type(rName, pNew));
+ fprintf(stdout, "ScExternalRefManager::getRangeNameTokens: --end\n");
-+ return pNew->Clone();
++ return pNew.get();
+}
+
-+ScExternalRefManager::DocCache* ScExternalRefManager::getDocumentCache(const String& rFile)
++void ScExternalRefManager::refreshAllReferencingCells(sal_uInt16 nFileId)
+{
-+ DocCacheMap::iterator itr = maCachedDocContents.find(rFile);
-+ if (itr == maCachedDocContents.end())
++ fprintf(stdout, "ScExternalRefManager::refreshAllReferencingCells: --begin\n");
++ RefCellMap::iterator itr = maRefCells.find(nFileId);
++ if (itr == maRefCells.end())
++ {
++ const String* pFile = getExternalFileName(nFileId);
++ if (pFile)
++ {
++ fprintf(stdout, "ScExternalRefManager::refreshAllReferencingCells: no referencing cells for names from '%s'\n",
++ rtl::OUStringToOString(*pFile, RTL_TEXTENCODING_UTF8).getStr());
++ }
++ else
++ fprintf(stdout, "ScExternalRefManager::refreshAllReferencingCells: file name not found (file ID = %d)\n", nFileId);
++ return;
++ }
++
++ RefCellSet aNewSet;
++ RefCellSet& rSet = itr->second;
++ RefCellSet::const_iterator itrSet = rSet.begin(), itrSetEnd = rSet.end();
++ for (; itrSet != itrSetEnd; ++itrSet)
+ {
-+ DocCacheRef pCache(new DocCache);
-+ maCachedDocContents.insert(DocCacheMap::value_type(rFile, pCache));
-+ return pCache.get();
++ if (compileTokensByCell(*itrSet))
++ // Cell still contains an external name/ref token.
++ aNewSet.insert(*itrSet);
+ }
++ rSet.swap(aNewSet);
+
-+ return itr->second.get();
++ ScViewData* pViewData = ScDocShell::GetViewData();
++ if (!pViewData)
++ return;
++
++ ScTabViewShell* pVShell = pViewData->GetViewShell();
++ if (!pVShell)
++ return;
++
++ // Repainting the grid also repaints the texts, but is there a better way
++ // to refresh texts?
++ pVShell->Invalidate(FID_TAB_TOGGLE_GRID);
++ pVShell->PaintGrid();
++}
++
++void ScExternalRefManager::insertReferencingCell(sal_uInt16 nFileId, const ScAddress& rCell)
++{
++ RefCellMap::iterator itr = maRefCells.find(nFileId);
++ if (itr != maRefCells.end())
++ {
++ itr->second.insert(rCell);
++ return;
++ }
++
++ RefCellSet aSet;
++ aSet.insert(rCell);
++ maRefCells.insert(RefCellMap::value_type(nFileId, aSet));
+}
+
-+ScDocument* ScExternalRefManager::getSrcDocument(const String& rFile)
++ScExternalRefManager::DocCache* ScExternalRefManager::getDocumentCache(
++ sal_uInt16 nFileId)
++{
++ DocCacheMap::iterator itr = maCachedDocContents.find(nFileId);
++ if (itr != maCachedDocContents.end())
++ return itr->second.get();
++
++ DocCacheRef pCache(new DocCache);
++ maCachedDocContents.insert(DocCacheMap::value_type(nFileId, pCache));
++ return pCache.get();
++}
++
++ScDocument* ScExternalRefManager::getSrcDocument(sal_uInt16 nFileId)
+{
+ DocShellMap::iterator itrEnd = maDocShells.end();
-+ DocShellMap::iterator itr = maDocShells.find(rFile);
-+ if (itr == itrEnd)
++ DocShellMap::iterator itr = maDocShells.find(nFileId);
++
++ if (itr != itrEnd)
+ {
-+ fprintf(stdout, "ScExternalRefManager::getSourceDocument: file not found: '%s'\n",
-+ rtl::OUStringToOString(rFile, RTL_TEXTENCODING_UTF8).getStr());
++ SfxObjectShell* p = itr->second.maShell;
++ itr->second.maLastAccess = Time();
++ return static_cast<ScDocShell*>(p)->GetDocument();
++ }
+
-+ String aFilter, aOptions;
-+ ScDocumentLoader::GetFilterName(rFile, aFilter, aOptions, true, false);
-+ const SfxFilter* pFilter = ScDocShell::Factory().GetFilterContainer()->GetFilter4FilterName(aFilter);
-+
-+ SfxItemSet* pSet = new SfxAllItemSet(SFX_APP()->GetPool());
-+ if (aOptions.Len())
-+ pSet->Put(SfxStringItem(SID_FILE_FILTEROPTIONS, aOptions));
-+
-+ auto_ptr<SfxMedium> pMedium(new SfxMedium(rFile, STREAM_STD_READ, FALSE, pFilter, pSet));
-+ if (pMedium->GetError() != ERRCODE_NONE)
-+ return NULL;
-+
-+ pMedium->UseInteractionHandler(false);
-+
-+ ScDocShell* pNewShell = new ScDocShell(SFX_CREATE_MODE_INTERNAL);
-+ SfxObjectShellRef aRef = pNewShell;
-+
-+ // increment the recursive link count of the source document.
-+ ScExtDocOptions* pExtOpt = mpDoc->GetExtDocOptions();
-+ sal_uInt32 nLinkCount = pExtOpt ? pExtOpt->GetDocSettings().mnLinkCnt : 0;
-+ ScDocument* pSrcDoc = pNewShell->GetDocument();
-+ ScExtDocOptions* pExtOptNew = pSrcDoc->GetExtDocOptions();
-+ if (!pExtOptNew)
-+ {
-+ pExtOptNew = new ScExtDocOptions;
-+ pSrcDoc->SetExtDocOptions(pExtOptNew);
-+ }
-+ pExtOptNew->GetDocSettings().mnLinkCnt = nLinkCount + 1;
++ const String* pFile = getExternalFileName(nFileId);
++ if (!pFile)
++ {
++ fprintf(stdout, "ScExternalRefManager::getSrcDocument: no file name associated with the ID of %d\n", nFileId);
++ return NULL;
++ }
+
-+ pNewShell->DoLoad(pMedium.release());
++ fprintf(stdout, "ScExternalRefManager::getSourceDocument: file not found: '%s'\n",
++ rtl::OUStringToOString(*pFile, RTL_TEXTENCODING_UTF8).getStr());
+
-+ maDocShells.insert(DocShellMap::value_type(rFile, aRef));
-+ insertExternalFileLink(rFile, aFilter);
-+ return pSrcDoc;
++ String aFilter;
++ SrcDoc aSrcDoc;
++ aSrcDoc.maShell = loadSrcDocument(*pFile, aFilter);
++ if (maDocShells.empty())
++ {
++ // If this is the first source document insertion, start up the timer.
++ maSrcDocTimer.Start();
+ }
+
-+ SfxObjectShell* p = itr->second;
++ maDocShells.insert(DocShellMap::value_type(nFileId, aSrcDoc));
++ if (!maLinkedDocs.count(nFileId))
++ {
++ insertExternalFileLink(nFileId, aFilter);
++ maLinkedDocs.insert(nFileId);
++ }
++ SfxObjectShell* p = aSrcDoc.maShell;
+ return static_cast<ScDocShell*>(p)->GetDocument();
+}
+
-+void ScExternalRefManager::insertExternalFileLink(const String& rFile, const String& rFilterName)
++SfxObjectShellRef ScExternalRefManager::loadSrcDocument(const String& rFile, String& rFilter)
++{
++ String aOptions;
++ ScDocumentLoader::GetFilterName(rFile, rFilter, aOptions, true, false);
++ const SfxFilter* pFilter = ScDocShell::Factory().GetFilterContainer()->GetFilter4FilterName(rFilter);
++
++ SfxItemSet* pSet = new SfxAllItemSet(SFX_APP()->GetPool());
++ if (aOptions.Len())
++ pSet->Put(SfxStringItem(SID_FILE_FILTEROPTIONS, aOptions));
++
++ auto_ptr<SfxMedium> pMedium(new SfxMedium(rFile, STREAM_STD_READ, FALSE, pFilter, pSet));
++ if (pMedium->GetError() != ERRCODE_NONE)
++ return NULL;
++
++ pMedium->UseInteractionHandler(false);
++
++ ScDocShell* pNewShell = new ScDocShell(SFX_CREATE_MODE_INTERNAL);
++ SfxObjectShellRef aRef = pNewShell;
++
++ // increment the recursive link count of the source document.
++ ScExtDocOptions* pExtOpt = mpDoc->GetExtDocOptions();
++ sal_uInt32 nLinkCount = pExtOpt ? pExtOpt->GetDocSettings().mnLinkCnt : 0;
++ ScDocument* pSrcDoc = pNewShell->GetDocument();
++ ScExtDocOptions* pExtOptNew = pSrcDoc->GetExtDocOptions();
++ if (!pExtOptNew)
++ {
++ pExtOptNew = new ScExtDocOptions;
++ pSrcDoc->SetExtDocOptions(pExtOptNew);
++ }
++ pExtOptNew->GetDocSettings().mnLinkCnt = nLinkCount + 1;
++
++ pNewShell->DoLoad(pMedium.release());
++ return aRef;
++}
++
++void ScExternalRefManager::insertExternalFileLink(sal_uInt16 nFileId, const String& rFilterName)
+{
+ SvxLinkManager* pLinkMgr = mpDoc->GetLinkManager();
-+ ScExternalRefLink* pLink = new ScExternalRefLink(mpDoc, rFile, rFilterName);
-+ pLinkMgr->InsertFileLink(*pLink, OBJECT_CLIENT_FILE, rFile, &rFilterName);
++ ScExternalRefLink* pLink = new ScExternalRefLink(mpDoc, nFileId, rFilterName);
++ const String* pFileName = getExternalFileName(nFileId);
++ DBG_ASSERT(pFileName, "ScExternalRefManager::insertExternalFileLink: file name pointer is NULL");
++ pLinkMgr->InsertFileLink(*pLink, OBJECT_CLIENT_FILE, *pFileName, &rFilterName);
++
++ pLink->SetDoReferesh(false);
+ pLink->Update();
++ pLink->SetDoReferesh(true);
++}
++
++bool ScExternalRefManager::compileTokensByCell(const ScAddress& rCell)
++{
++ String aStr;
++ rCell.Format(aStr, SCA_ABS_3D);
++ fprintf(stdout, "ScExternalRefManager::compileTokensByCell: --begin (cell = '%s')\n",
++ rtl::OUStringToOString(aStr, RTL_TEXTENCODING_UTF8).getStr());
++
++ ScBaseCell* pCell;
++ mpDoc->GetCell(rCell.Col(), rCell.Row(), rCell.Tab(), pCell);
++
++ if (!pCell || pCell->GetCellType() != CELLTYPE_FORMULA)
++ {
++ fprintf(stdout, "ScExternalRefManager::compileTokensByCell: --end (not a valid formula cell)\n");
++ return false;
++ }
++
++ ScFormulaCell* pFC = static_cast<ScFormulaCell*>(pCell);
++
++ // Check to make sure the cell really contains ocExternalName.
++ bool bCompile = false;
++ ScTokenArray* pCode = pFC->GetCode();
++ pCode->Reset();
++ for (ScToken* p = pCode->First(); p; p = pCode->Next())
++ {
++ // TODO: once we have implemented a new token for the external
++ // references, we will also query for that token type.
++ if (p->GetOpCode() == ocExternalName)
++ {
++ bCompile = true;
++ break;
++ }
++ }
++ if (!bCompile)
++ {
++ fprintf(stdout, "ScExternalRefManager::compileTokensByCell: --end (cell doesn't contain any external name)\n");
++ return false;
++ }
++
++ pFC->SetCompile(true);
++ pFC->CompileTokenArray();
++ pFC->SetDirty();
++
++ fprintf(stdout, "ScExternalRefManager::compileTokensByCell: --end (cell re-compiled)\n");
++ return true;
+}
+
+sal_uInt16 ScExternalRefManager::getExternalFileId(const String& rFile)
@@ -1494,46 +1737,97 @@
+ return &maFileNames[nIndex];
+}
+
-+void ScExternalRefManager::refreshNames(const String& rFile)
++template<typename MapContainer>
++static void lcl_removeByFileId(sal_uInt16 nFileId, MapContainer& rMap)
++{
++ typename MapContainer::iterator itr = rMap.find(nFileId);
++ if (itr != rMap.end())
++ rMap.erase(itr);
++}
++
++void ScExternalRefManager::refreshNames(sal_uInt16 nFileId)
+{
+ fprintf(stdout, "ScExternalRefManager::refreshNames: --begin\n");
-+ // 1. Find the cached content (DocCache) for a given file name.
-+ // 2. Clear the single and double reference caches.
-+ // 3. Re-parse the cached names from the source documents.
-+ // 4. Update those cells that contain the cached names.
+
++ removeSrcDocument(nFileId, false);
+
++ // Update all cells containing names from this source document.
++ refreshAllReferencingCells(nFileId);
++ fprintf(stdout, "ScExternalRefManager::refreshNames: --end\n");
+}
+
-+void ScExternalRefManager::switchSrcFile(const String& rOldFile, const String& rNewFile)
++void ScExternalRefManager::switchSrcFile(sal_uInt16 nFileId, const String& rNewFile)
+{
++ const String* pOldFile = getExternalFileName(nFileId);
+ fprintf(stdout, "ScExternalRefManager::switchSrcFile: --begin (old file = '%s'; new file = '%s')\n",
-+ rtl::OUStringToOString(rOldFile, RTL_TEXTENCODING_UTF8).getStr(),
++ rtl::OUStringToOString(*pOldFile, RTL_TEXTENCODING_UTF8).getStr(),
+ rtl::OUStringToOString(rNewFile, RTL_TEXTENCODING_UTF8).getStr());
+
-+ /**
-+ * This is a tricky one. First, remove all cached data associated with
-+ * the old file (and purge the cached source document if it's still
-+ * alive), swap the file location with the new one, then recalculate those
-+ * cells that contain reference to the old file.
-+ *
-+ * To implement this, I need to switch from storing the file path string
-+ * with the external name token, to storing the index of it and storing
-+ * the string itself with ScExternalRefManager. This way I can just
-+ * switch the file name here centrally instead of converting the token
-+ * arrays of all affected cells.
-+ */
++ removeSrcDocument(nFileId, false);
++ maFileNames[nFileId] = rNewFile;
++ refreshAllReferencingCells(nFileId);
++}
++
++void ScExternalRefManager::removeSrcDocument(sal_uInt16 nFileId, bool bBreakLink)
++{
++ const String* pFile = getExternalFileName(nFileId);
++ if (pFile)
++ {
++ fprintf(stdout, "ScExternalRefManager::removeSrcFile: --begin (file = '%s')\n",
++ rtl::OUStringToOString(*pFile, RTL_TEXTENCODING_UTF8).getStr());
++ }
++
++ lcl_removeByFileId(nFileId, maCachedDocContents);
++ lcl_removeByFileId(nFileId, maDocShells);
++
++ if (bBreakLink)
++ maLinkedDocs.erase(nFileId);
++
++ if (maDocShells.empty())
++ maSrcDocTimer.Stop();
++
++ fprintf(stdout, "ScExternalRefManager::removeSrcFile: --end\n");
+}
+
+void ScExternalRefManager::clear()
+{
+ DocShellMap::iterator itrEnd = maDocShells.end();
+ for (DocShellMap::iterator itr = maDocShells.begin(); itr != itrEnd; ++itr)
-+ itr->second->DoClose();
++ itr->second.maShell->DoClose();
+
+ maDocShells.clear();
++ maSrcDocTimer.Stop();
++}
++
++void ScExternalRefManager::purgeStaleSrcDocument(sal_Int32 nTimeOut)
++{
++ DocShellMap aNewDocShells;
++ DocShellMap::iterator itr = maDocShells.begin(), itrEnd = maDocShells.end();
++ for (; itr != itrEnd; ++itr)
++ {
++ // in 100th of a second.
++ sal_Int32 nSinceLastAccess = (Time() - itr->second.maLastAccess).GetTime();
++ const String* pStr = getExternalFileName(itr->first);
++ if (pStr)
++ fprintf(stdout, "ScExternalRefManager::purgeStaleSrcDocument: file = '%s'; since last access = %ld\n",
++ rtl::OUStringToOString(*pStr, RTL_TEXTENCODING_UTF8).getStr(), nSinceLastAccess);
++
++ if (nSinceLastAccess < nTimeOut)
++ aNewDocShells.insert(*itr);
++ }
++ maDocShells.swap(aNewDocShells);
++
++ if (maDocShells.empty())
++ maSrcDocTimer.Stop();
+}
+
++IMPL_LINK(ScExternalRefManager, TimeOutHdl, AutoTimer*, pTimer)
++{
++ if (pTimer == &maSrcDocTimer)
++ purgeStaleSrcDocument(1000); // max life span is 10 seconds (TODO: configure this).
++
++ return 0;
++}
diff --git sc/source/ui/docshell/makefile.mk sc/source/ui/docshell/makefile.mk
index db83fec..6286dfb 100644
--- sc/source/ui/docshell/makefile.mk
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]