ooo-build r13205 - in trunk: . patches/test



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]