[ooo-build-commit] .: 3 commits - patches/dev300

Kohei Yoshida kohei at kemper.freedesktop.org
Mon Aug 16 11:41:55 PDT 2010


 patches/dev300/apply                                       |    5 
 patches/dev300/calc-extref-interpreter-rework-formula.diff |   95 
 patches/dev300/calc-extref-interpreter-rework-sc.diff      | 1793 +++++++++++++
 patches/dev300/dde-reconnect-on-load-cui.diff              |   13 
 patches/dev300/dde-reconnect-on-load-sc.diff               |   36 
 patches/dev300/dde-reconnect-on-load-sfx2.diff             |  364 ++
 patches/dev300/dde-reconnect-on-load-sw.diff               |    8 
 7 files changed, 2265 insertions(+), 49 deletions(-)

New commits:
commit 070d3446f56a7cd5145bdb37b05fc705a8def3dd
Author: Kohei Yoshida <kyoshida at novell.com>
Date:   Mon Aug 16 14:41:12 2010 -0400

    Fixed build breakage.
    
    SvxLinkManager -> sfx2::LinkManager etc.
    
    * patches/dev300/dde-reconnect-on-load-sc.diff:
    * patches/dev300/dde-reconnect-on-load-sfx2.diff:
    * patches/dev300/dde-reconnect-on-load-sw.diff:

diff --git a/patches/dev300/dde-reconnect-on-load-sc.diff b/patches/dev300/dde-reconnect-on-load-sc.diff
index 83d0add..40e018f 100644
--- a/patches/dev300/dde-reconnect-on-load-sc.diff
+++ b/patches/dev300/dde-reconnect-on-load-sc.diff
@@ -40,7 +40,7 @@ index bb7b82f..8d9a9f0 100644
  
 +void ScDocShell::ReconnectDdeLink(SfxObjectShell& rServer)
 +{
-+    SvxLinkManager* pLinkManager = aDocument.GetLinkManager();
++    ::sfx2::LinkManager* pLinkManager = aDocument.GetLinkManager();
 +    if (!pLinkManager)
 +        return;
 +
diff --git a/patches/dev300/dde-reconnect-on-load-sfx2.diff b/patches/dev300/dde-reconnect-on-load-sfx2.diff
index ca6ec7e..f37559e 100644
--- a/patches/dev300/dde-reconnect-on-load-sfx2.diff
+++ b/patches/dev300/dde-reconnect-on-load-sfx2.diff
@@ -149,7 +149,7 @@ index 091ffb8..bffd379 100755
  static char const sViewId[] = "ViewId";
  static char const sPluginMode[] = "PluginMode";
  static char const sReadOnly[] = "ReadOnly";
-+static char const sDdeReconnect = "DDEReconnect";
++static char const sDdeReconnect[] = "DDEReconnect";
  static char const sStartPresentation[] = "StartPresentation";
  static char const sFrameName[] = "FrameName";
  static char const sMediaType[] = "MediaType";
diff --git a/patches/dev300/dde-reconnect-on-load-sw.diff b/patches/dev300/dde-reconnect-on-load-sw.diff
index 443e0f8..8ada332 100644
--- a/patches/dev300/dde-reconnect-on-load-sw.diff
+++ b/patches/dev300/dde-reconnect-on-load-sw.diff
@@ -19,7 +19,7 @@ index aa59379..3022ba2 100644
  #include <editeng/svxacorr.hxx>
  #include <editeng/langitem.hxx>
  #include <svx/fmshell.hxx>
-+#include <svx/linkmgr.hxx>
++#include <sfx2/linkmgr.hxx>
  
  #include <svtools/htmlcfg.hxx>
  #include <svx/ofaitem.hxx>
@@ -29,7 +29,7 @@ index aa59379..3022ba2 100644
  
 +void SwDocShell::ReconnectDdeLink(SfxObjectShell& rServer)
 +{
-+    SvxLinkManager& rLinkManager = pDoc->GetLinkManager();
++    ::sfx2::LinkManager& rLinkManager = pDoc->GetLinkManager();
 +    rLinkManager.ReconnectDdeLink(rServer);
 +}
 +
commit a61c1541deccddecab8e45b05ad987ed817ada9d
Author: Kohei Yoshida <kyoshida at novell.com>
Date:   Mon Aug 16 13:08:01 2010 -0400

    Ported external reference rework patches from ooo-build-3-2-1.
    
    With this change, external reference tokens are pushed with ocPush
    opcode, which allows external references to be used within OFFSET.
    
    * patches/dev300/apply:
    * patches/dev300/calc-extref-interpreter-rework-formula.diff:
    * patches/dev300/calc-extref-interpreter-rework-sc.diff:

diff --git a/patches/dev300/apply b/patches/dev300/apply
index ab59e68..306c232 100644
--- a/patches/dev300/apply
+++ b/patches/dev300/apply
@@ -3488,6 +3488,10 @@ dde-reconnect-on-load-cui.diff,  n#618846, n#618864, kohei
 # Properly display data field names in the data field options dialog.
 calc-dp-sort-fix.diff, n#629920, kohei
 
+# Treat external reference tokens with ocPush & dump ocExternalRef opcode.
+calc-extref-interpreter-rework-formula.diff, n#628876, kohei
+calc-extref-interpreter-rework-sc.diff,      n#628876, kohei
+
 [ GentooExperimental ]
 SectionOwner => hmth
 # jemalloc allocator
diff --git a/patches/dev300/calc-extref-interpreter-rework-formula.diff b/patches/dev300/calc-extref-interpreter-rework-formula.diff
new file mode 100644
index 0000000..67b1745
--- /dev/null
+++ b/patches/dev300/calc-extref-interpreter-rework-formula.diff
@@ -0,0 +1,95 @@
+diff --git formula/inc/formula/token.hxx formula/inc/formula/token.hxx
+index be1b2f6..8b4f53a 100644
+--- formula/inc/formula/token.hxx
++++ formula/inc/formula/token.hxx
+@@ -113,6 +113,7 @@ public:
+     inline  StackVar      		GetType() const         { return eType; }
+             BOOL                IsFunction() const; // pure functions, no operators
+             BOOL                IsMatrixFunction() const;   // if a function _always_ returns a Matrix
++            bool                IsExternalRef() const;
+             BYTE                GetParamCount() const;
+     inline  void                IncRef() const          { nRefCnt++; }
+     inline  void                DecRef() const
+diff --git formula/inc/formula/tokenarray.hxx formula/inc/formula/tokenarray.hxx
+index 042dbb9..5bbfaf4 100644
+--- formula/inc/formula/tokenarray.hxx
++++ formula/inc/formula/tokenarray.hxx
+@@ -126,6 +126,7 @@ public:
+     FormulaToken* LastRPN() { nIndex = nRPN; return PrevRPN(); }
+     FormulaToken* PrevRPN();
+ 
++    bool    HasExternalRef() const;
+     BOOL    HasOpCode( OpCode ) const;
+     BOOL    HasOpCodeRPN( OpCode ) const;
+     /// Token of type svIndex or opcode ocColRowName
+diff --git formula/source/core/api/FormulaCompiler.cxx formula/source/core/api/FormulaCompiler.cxx
+index 7e26cde..7395044 100644
+--- formula/source/core/api/FormulaCompiler.cxx
++++ formula/source/core/api/FormulaCompiler.cxx
+@@ -905,7 +905,7 @@ BOOL FormulaCompiler::GetToken()
+     }
+     if( pToken->GetOpCode() == ocSubTotal )
+         glSubTotal = TRUE;
+-    else if ( pToken->GetOpCode() == ocExternalRef )
++    else if ( pToken->IsExternalRef() )
+     {
+         return HandleExternalReference(*pToken);
+     }
+@@ -1187,7 +1187,7 @@ void FormulaCompiler::Factor()
+                 bCorrected = TRUE;
+             }
+         }
+-        else if ( eOp == ocExternalRef )
++        else if ( pToken->IsExternalRef() )
+         {
+             PutCode(pToken);
+             eOp = NextToken();
+@@ -1607,7 +1607,7 @@ FormulaToken* FormulaCompiler::CreateStringFromToken( rtl::OUStringBuffer& rBuff
+     }
+     if( bNext ) 
+     {
+-        if (eOp == ocExternalRef)
++        if (t->IsExternalRef())
+         {
+             CreateStringFromExternal(rBuffer, pTokenP);
+         }
+diff --git formula/source/core/api/token.cxx formula/source/core/api/token.cxx
+index ccc7406..028197c 100644
+--- formula/source/core/api/token.cxx
++++ formula/source/core/api/token.cxx
+@@ -145,6 +145,18 @@ BOOL FormulaToken::IsMatrixFunction() const
+     return formula::FormulaCompiler::IsMatrixFunction(GetOpCode());
+ }
+ 
++bool FormulaToken::IsExternalRef() const
++{
++    switch (eType)
++    {
++        case svExternalSingleRef:
++        case svExternalDoubleRef:
++        case svExternalName:
++            return true;
++    }
++    return false;
++}
++
+ BOOL FormulaToken::operator==( const FormulaToken& rToken ) const
+ {
+     // don't compare reference count!
+@@ -550,6 +562,16 @@ FormulaToken* FormulaTokenArray::PeekPrevNoSpaces()
+         return NULL;
+ }
+ 
++bool FormulaTokenArray::HasExternalRef() const
++{
++    for ( USHORT j=0; j < nLen; j++ )
++    {
++        if (pCode[j]->IsExternalRef())
++            return true;
++    }
++    return false;
++}
++
+ BOOL FormulaTokenArray::HasOpCode( OpCode eOp ) const
+ {
+     for ( USHORT j=0; j < nLen; j++ )
diff --git a/patches/dev300/calc-extref-interpreter-rework-sc.diff b/patches/dev300/calc-extref-interpreter-rework-sc.diff
new file mode 100644
index 0000000..57f5879
--- /dev/null
+++ b/patches/dev300/calc-extref-interpreter-rework-sc.diff
@@ -0,0 +1,1793 @@
+diff --git sc/inc/document.hxx sc/inc/document.hxx
+index f5a285d..2b5dc0f 100644
+--- sc/inc/document.hxx
++++ sc/inc/document.hxx
+@@ -501,7 +501,7 @@ public:
+     ScFieldEditEngine*	CreateFieldEditEngine();
+     void				DisposeFieldEditEngine(ScFieldEditEngine*& rpEditEngine);
+ 
+-    SC_DLLPUBLIC ScRangeName*	GetRangeName();
++    SC_DLLPUBLIC ScRangeName*	GetRangeName() const;
+     void			SetRangeName( ScRangeName* pNewRangeName );
+     SCTAB			GetMaxTableNumber() { return nMaxTableNumber; }
+     void			SetMaxTableNumber(SCTAB nNumber) { nMaxTableNumber = nNumber; }
+@@ -804,7 +804,7 @@ public:
+     SC_DLLPUBLIC void			GetValue( SCCOL nCol, SCROW nRow, SCTAB nTab, double& rValue );
+     SC_DLLPUBLIC double			RoundValueAsShown( double fVal, ULONG nFormat );
+     SC_DLLPUBLIC void			GetNumberFormat( SCCOL nCol, SCROW nRow, SCTAB nTab,
+-                                     sal_uInt32& rFormat );
++                                     sal_uInt32& rFormat ) const;
+     sal_uInt32      GetNumberFormat( const ScRange& rRange ) const;
+     SC_DLLPUBLIC sal_uInt32		GetNumberFormat( const ScAddress& ) const;
+                     /** If no number format attribute is set and the cell
+diff --git sc/inc/externalrefmgr.hxx sc/inc/externalrefmgr.hxx
+index 49627f2..44e9e68 100644
+--- sc/inc/externalrefmgr.hxx
++++ sc/inc/externalrefmgr.hxx
+@@ -684,7 +684,47 @@ private:
+ 
+     void insertRefCell(sal_uInt16 nFileId, const ScAddress& rCell);
+ 
+-    ScDocument* getSrcDocument(sal_uInt16 nFileId);
++    void fillCellFormat(sal_uInt32 nFmtIndex, ScExternalRefCache::CellFormat* pFmt) const;
++
++    ScExternalRefCache::TokenRef getSingleRefTokenFromSrcDoc(
++        sal_uInt16 nFileId, const ScDocument* pSrcDoc, const ScAddress& rCell, 
++        ScExternalRefCache::CellFormat* pFmt);
++
++    /**
++     * Retrieve a range token array from a source document instance. 
++     * 
++     * @param pSrcDoc pointer to the source document instance.
++     * @param rTabName name of the first table.
++     * @param rRange range specified.  Upon successful retrieval, this range 
++     *               gets modified to contain the correct table IDs, and in
++     *               case the range is larger than the data area of the source
++     *               document, it gets reduced to the data area.
++     * @param rCacheData an array of structs, with each struct containing the 
++     *                   table name and the data in the specified range.
++     * 
++     * @return range token array
++     */
++    ScExternalRefCache::TokenArrayRef getDoubleRefTokensFromSrcDoc(
++        const ScDocument* pSrcDoc, const String& rTabName, ScRange& rRange,
++        ::std::vector<ScExternalRefCache::SingleRangeData>& rCacheData);
++
++    /**
++     * Retrieve range name token array from a source document instance.
++     * 
++     * @param nFileId file ID of the source document.
++     * @param pSrcDoc pointer to the source document instance
++     * @param rName range name to retrieve.  Note that the range name lookup 
++     *              is case <i>in</i>-sensitive, and upon successful retrieval
++     *              of the range name array, this name gets updated to the
++     *              actual range name with the correct casing.
++     * 
++     * @return range name token array
++     */
++    ScExternalRefCache::TokenArrayRef getRangeNameTokensFromSrcDoc(
++        sal_uInt16 nFileId, const ScDocument* pSrcDoc, String& rName);
++    
++    const ScDocument* getInMemorySrcDocument(sal_uInt16 nFileId);
++    const ScDocument* getSrcDocument(sal_uInt16 nFileId);
+     SfxObjectShellRef loadSrcDocument(sal_uInt16 nFileId, String& rFilter);
+     bool isFileLoadable(const String& rFile) const;
+ 
+@@ -711,7 +751,7 @@ private:
+      */
+     void purgeStaleSrcDocument(sal_Int32 nTimeOut);
+ 
+-    sal_uInt32 getMappedNumberFormat(sal_uInt16 nFileId, sal_uInt32 nNumFmt, ScDocument* pSrcDoc);
++    sal_uInt32 getMappedNumberFormat(sal_uInt16 nFileId, sal_uInt32 nNumFmt, const ScDocument* pSrcDoc);
+ 
+ private:
+     /** cache of referenced ranges and names from source documents. */
+diff --git sc/source/core/data/cell.cxx sc/source/core/data/cell.cxx
+index cf9f40a..8104d0a 100644
+--- sc/source/core/data/cell.cxx
++++ sc/source/core/data/cell.cxx
+@@ -774,7 +774,7 @@ ScFormulaCell::ScFormulaCell( const ScFormulaCell& rCell, ScDocument& rDoc, cons
+         ScToken* t;
+         while ( ( t = static_cast<ScToken*>(pCode->GetNextReferenceOrName()) ) != NULL && !bCompile )
+         {
+-            if ( t->GetOpCode() == ocExternalRef )
++            if ( t->IsExternalRef() )
+             {
+                 // External name, cell, and area references.
+                 bCompile = true;
+diff --git sc/source/core/data/documen3.cxx sc/source/core/data/documen3.cxx
+index 27ed1f8..213b28d 100644
+--- sc/source/core/data/documen3.cxx
++++ sc/source/core/data/documen3.cxx
+@@ -93,7 +93,7 @@ using ::std::auto_ptr;
+ 
+ //------------------------------------------------------------------------
+ 
+-ScRangeName* ScDocument::GetRangeName()
++ScRangeName* ScDocument::GetRangeName() const
+ {
+     return pRangeName;
+ }
+diff --git sc/source/core/data/documen4.cxx sc/source/core/data/documen4.cxx
+index cbd55fd..48f3e2b 100644
+--- sc/source/core/data/documen4.cxx
++++ sc/source/core/data/documen4.cxx
+@@ -305,7 +305,7 @@ bool ScDocument::MarkUsedExternalReferences( ScTokenArray & rArr )
+         ScToken* t;
+         while (!bAllMarked && (t = static_cast<ScToken*>(rArr.GetNextReferenceOrName())) != NULL)
+         {
+-            if (t->GetOpCode() == ocExternalRef)
++            if (t->IsExternalRef())
+             {
+                 if (!pRefMgr)
+                     pRefMgr = GetExternalRefManager();
+diff --git sc/source/core/data/document.cxx sc/source/core/data/document.cxx
+index c32cf41..ea615c5 100644
+--- sc/source/core/data/document.cxx
++++ sc/source/core/data/document.cxx
+@@ -2722,7 +2722,7 @@ double ScDocument::GetValue( const ScAddress& rPos )
+ 
+ 
+ void ScDocument::GetNumberFormat( SCCOL nCol, SCROW nRow, SCTAB nTab,
+-                                  sal_uInt32& rFormat )
++                                  sal_uInt32& rFormat ) const
+ {
+     if (VALIDTAB(nTab))
+         if (pTab[nTab])
+diff --git sc/source/core/inc/interpre.hxx sc/source/core/inc/interpre.hxx
+index b28bfc1..65dc19d 100644
+--- sc/source/core/inc/interpre.hxx
++++ sc/source/core/inc/interpre.hxx
+@@ -35,6 +35,7 @@
+ #include "scdll.hxx"
+ #include "document.hxx"
+ #include "scmatrix.hxx"
++#include "externalrefmgr.hxx"
+ 
+ #include <math.h>
+ #include <map>
+@@ -305,10 +306,15 @@ void DoubleRefToVars( const ScToken* p,
+         SCCOL& rCol1, SCROW &rRow1, SCTAB& rTab1,
+         SCCOL& rCol2, SCROW &rRow2, SCTAB& rTab2,
+         BOOL bDontCheckForTableOp = FALSE );
+-ScDBRangeBase* PopDoubleRef();
++ScDBRangeBase* PopDBDoubleRef();
+ void PopDoubleRef(SCCOL& rCol1, SCROW &rRow1, SCTAB& rTab1,
+                           SCCOL& rCol2, SCROW &rRow2, SCTAB& rTab2,
+                           BOOL bDontCheckForTableOp = FALSE );
++void PopExternalSingleRef(sal_uInt16& rFileId, String& rTabName, ScSingleRefData& rRef);
++void PopExternalSingleRef(ScExternalRefCache::TokenRef& rToken, ScExternalRefCache::CellFormat* pFmt = NULL);
++void PopExternalDoubleRef(sal_uInt16& rFileId, String& rTabName, ScComplexRefData& rRef);
++void PopExternalDoubleRef(ScExternalRefCache::TokenArrayRef& rArray);
++void PopExternalDoubleRef(ScMatrixRef& rMat);
+ BOOL PopDoubleRefOrSingleRef( ScAddress& rAdr );
+ void PopDoubleRefPushMatrix();
+ // If MatrixFormula: convert formula::svDoubleRef to svMatrix, create JumpMatrix.
+@@ -326,7 +332,12 @@ void PushStringBuffer( const sal_Unicode* pString );
+ void PushString( const String& rString );
+ void PushSingleRef(SCCOL nCol, SCROW nRow, SCTAB nTab);
+ void PushDoubleRef(SCCOL nCol1, SCROW nRow1, SCTAB nTab1,
+-                                 SCCOL nCol2, SCROW nRow2, SCTAB nTab2);
++                   SCCOL nCol2, SCROW nRow2, SCTAB nTab2);
++void PushExternalSingleRef(sal_uInt16 nFileId, const String& rTabName, 
++                           SCCOL nCol, SCROW nRow, SCTAB nTab);
++void PushExternalDoubleRef(sal_uInt16 nFileId, const String& rTabName, 
++                           SCCOL nCol1, SCROW nRow1, SCTAB nTab1, 
++                           SCCOL nCol2, SCROW nRow2, SCTAB nTab2);
+ void PushMatrix(ScMatrix* pMat);
+ void PushError( USHORT nError );
+ /// Raw stack type without default replacements.
+@@ -338,11 +349,13 @@ formula::StackVar GetStackType( BYTE nParam );
+ BYTE GetByte() { return cPar; }
+ // generiert aus DoubleRef positionsabhaengige SingleRef
+ BOOL DoubleRefToPosSingleRef( const ScRange& rRange, ScAddress& rAdr );
++double GetDoubleFromMatrix(const ScMatrixRef& pMat);
+ double GetDouble();
+ double GetDoubleWithDefault(double nDefault);
+ BOOL IsMissing();
+ BOOL GetBool() { return GetDouble() != 0.0; }
+ const String& GetString();
++const String& GetStringFromMatrix(const ScMatrixRef& pMat);
+ // pop matrix and obtain one element, upper left or according to jump matrix
+ ScMatValType GetDoubleOrStringFromMatrix( double& rDouble, String& rString );
+ ScMatrixRef CreateMatrixFromDoubleRef( const formula::FormulaToken* pToken,
+@@ -538,7 +551,6 @@ BOOL SetSbxVariable( SbxVariable* pVar, SCCOL nCol, SCROW nRow, SCTAB nTab );
+ void ScErrorType();
+ void ScDBArea();
+ void ScColRowNameAuto();
+-void ScExternalRef();
+ void ScGetPivotData();
+ void ScHyperLink();
+ void ScBahtText();
+diff --git sc/source/core/tool/address.cxx sc/source/core/tool/address.cxx
+index 78d2c31..622a85b 100644
+--- sc/source/core/tool/address.cxx
++++ sc/source/core/tool/address.cxx
+@@ -1015,7 +1015,18 @@ lcl_ScAddress_Parse_OOo( const sal_Unicode* p, ScDocument* pDoc, ScAddress& rAdd
+             nBits = 0;
+ 
+         if (!bExtDoc && (!pDoc || !pDoc->GetTable( aTab, nTab )))
+-            nBits = 0;
++        {
++            // Specified table name is not found in this document.  Assume this is an external document.
++            bExtDoc = true;
++            aDocName = aTab;
++            xub_StrLen n = aTab.SearchBackward('.');
++            if (n != STRING_NOTFOUND && n > 0)
++                // Extension found.  Strip it.
++                aTab.Erase(n);
++            else
++                // No extension found.  This is probably not an external document.
++                nBits = 0;
++        }
+     }
+     else
+     {
+diff --git sc/source/core/tool/interpr1.cxx sc/source/core/tool/interpr1.cxx
+index 9c86e45..5646386 100644
+--- sc/source/core/tool/interpr1.cxx
++++ sc/source/core/tool/interpr1.cxx
+@@ -3106,6 +3106,59 @@ void ScInterpreter::ScMax( BOOL bTextAsZero )
+ #pragma optimize("",on)
+ #endif
+ 
++namespace {
++
++void IterateMatrix(
++    const ScMatrixRef& pMat, ScIterFunc eFunc, BOOL bTextAsZero, 
++    ULONG& rCount, short& rFuncFmtType, double& fVal, double& fRes, double& fMem, BOOL& bNull)
++{
++    if (!pMat)
++        return;
++
++    SCSIZE nC, nR;
++    rFuncFmtType = NUMBERFORMAT_NUMBER;
++    pMat->GetDimensions(nC, nR);
++    if( eFunc == ifCOUNT2 )
++        rCount += (ULONG) nC * nR;
++    else
++    {
++        for (SCSIZE nMatCol = 0; nMatCol < nC; nMatCol++)
++        {
++            for (SCSIZE nMatRow = 0; nMatRow < nR; nMatRow++)
++            {
++                if (!pMat->IsString(nMatCol,nMatRow))
++                {
++                    rCount++;
++                    fVal = pMat->GetDouble(nMatCol,nMatRow);
++                    switch( eFunc )
++                    {
++                        case ifAVERAGE:
++                        case ifSUM:
++                            if ( bNull && fVal != 0.0 )
++                            {
++                                bNull = FALSE;
++                                fMem = fVal;
++                            }
++                            else
++                                fRes += fVal;
++                            break;
++                        case ifSUMSQ:   fRes += fVal * fVal; break;
++                        case ifPRODUCT: fRes *= fVal; break;
++                        default: ; // nothing
++                    }
++                }
++                else if ( bTextAsZero )
++                {
++                    rCount++;
++                    if ( eFunc == ifPRODUCT )
++                        fRes = 0.0;
++                }
++            }
++        }
++    }
++}
++
++}
+ 
+ double ScInterpreter::IterateParameters( ScIterFunc eFunc, BOOL bTextAsZero )
+ {
+@@ -3187,6 +3240,71 @@ double ScInterpreter::IterateParameters( ScIterFunc eFunc, BOOL bTextAsZero )
+                 }
+                 nFuncFmtType = NUMBERFORMAT_NUMBER;
+                 break;
++            case svExternalSingleRef:
++            {
++                ScExternalRefCache::TokenRef pToken;
++                ScExternalRefCache::CellFormat aFmt;
++                PopExternalSingleRef(pToken, &aFmt);
++                if (nGlobalError && (eFunc == ifCOUNT2 || eFunc == ifCOUNT))
++                {
++                    nGlobalError = 0;
++                    if ( eFunc == ifCOUNT2 )
++                        ++nCount;
++                    break;
++                }
++
++                if (!pToken)
++                    break;
++
++                StackVar eType = pToken->GetType();
++                if (eFunc == ifCOUNT2)
++                {
++                    if (eType != formula::svEmptyCell)
++                        nCount++;
++                    if (nGlobalError)
++                        nGlobalError = 0;
++                }
++                else if (eType == formula::svDouble)
++                {
++                    nCount++;
++                    fVal = pToken->GetDouble();
++                    if (aFmt.mbIsSet)
++                    {
++                        nFuncFmtType = aFmt.mnType;
++                        nFuncFmtIndex = aFmt.mnIndex;
++                    }
++                    switch( eFunc )
++                    {
++                        case ifAVERAGE:
++                        case ifSUM:
++                            if ( bNull && fVal != 0.0 )
++                            {
++                                bNull = FALSE;
++                                fMem = fVal;
++                            }
++                            else
++                                fRes += fVal;
++                            break;
++                        case ifSUMSQ:   fRes += fVal * fVal; break;
++                        case ifPRODUCT: fRes *= fVal; break;
++                        case ifCOUNT:
++                            if ( nGlobalError )
++                            {    
++                                nGlobalError = 0;
++                                nCount--;
++                            }
++                            break;
++                        default: ; // nothing
++                    }
++                }
++                else if (bTextAsZero && eType == formula::svString)
++                {
++                    nCount++;
++                    if ( eFunc == ifPRODUCT )
++                        fRes = 0.0;
++                }
++            }
++            break;
+             case svSingleRef :
+             {
+                 PopSingleRef( aAdr );
+@@ -3333,53 +3451,20 @@ double ScInterpreter::IterateParameters( ScIterFunc eFunc, BOOL bTextAsZero )
+                 }
+             }
+             break;
++            case svExternalDoubleRef:
++            {
++                ScMatrixRef pMat;
++                PopExternalDoubleRef(pMat);
++                if (nGlobalError)
++                    break;
++
++                IterateMatrix(pMat, eFunc, bTextAsZero, nCount, nFuncFmtType, fVal, fMem, fRes, bNull);
++            }
++            break;
+             case svMatrix :
+             {
+                 ScMatrixRef pMat = PopMatrix();
+-                if (pMat)
+-                {
+-                    SCSIZE nC, nR;
+-                    nFuncFmtType = NUMBERFORMAT_NUMBER;
+-                    pMat->GetDimensions(nC, nR);
+-                    if( eFunc == ifCOUNT2 )
+-                        nCount += (ULONG) nC * nR;
+-                    else
+-                    {
+-                        for (SCSIZE nMatCol = 0; nMatCol < nC; nMatCol++)
+-                        {
+-                            for (SCSIZE nMatRow = 0; nMatRow < nR; nMatRow++)
+-                            {
+-                                if (!pMat->IsString(nMatCol,nMatRow))
+-                                {
+-                                    nCount++;
+-                                    fVal = pMat->GetDouble(nMatCol,nMatRow);
+-                                    switch( eFunc )
+-                                    {
+-                                        case ifAVERAGE:
+-                                        case ifSUM:
+-                                            if ( bNull && fVal != 0.0 )
+-                                            {
+-                                                bNull = FALSE;
+-                                                fMem = fVal;
+-                                            }
+-                                            else
+-                                                fRes += fVal;
+-                                            break;
+-                                        case ifSUMSQ:   fRes += fVal * fVal; break;
+-                                        case ifPRODUCT: fRes *= fVal; break;
+-                                        default: ; // nothing
+-                                    }
+-                                }
+-                                else if ( bTextAsZero )
+-                                {
+-                                    nCount++;
+-                                    if ( eFunc == ifPRODUCT )
+-                                        fRes = 0.0;
+-                                }
+-                            }
+-                        }
+-                    }
+-                }
++                IterateMatrix(pMat, eFunc, bTextAsZero, nCount, nFuncFmtType, fVal, fMem, fRes, bNull);
+             }
+             break;
+             case svError:
+@@ -4094,29 +4179,39 @@ void ScInterpreter::ScMatch()
+         SCCOL nCol2 = 0;
+         SCROW nRow2 = 0;
+         SCTAB nTab2 = 0;
+-        if (GetStackType() == svDoubleRef)
++
++        switch (GetStackType())
+         {
+-            PopDoubleRef(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
+-            if (nTab1 != nTab2 || (nCol1 != nCol2 && nRow1 != nRow2))
++            case svDoubleRef:
+             {
+-                PushIllegalParameter();
+-                return;
++                PopDoubleRef(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
++                if (nTab1 != nTab2 || (nCol1 != nCol2 && nRow1 != nRow2))
++                {
++                    PushIllegalParameter();
++                    return;
++                }
+             }
+-        }
+-        else if (GetStackType() == svMatrix)
+-        {
+-            pMatSrc = PopMatrix();
+-            if (!pMatSrc)
++            break;
++            case svMatrix:
++            case svExternalDoubleRef:
+             {
++                if (GetStackType() == svMatrix)
++                    pMatSrc = PopMatrix();
++                else
++                    PopExternalDoubleRef(pMatSrc);
++
++                if (!pMatSrc)
++                {
++                    PushIllegalParameter();
++                    return;
++                }
++            }
++            break;
++            default:
+                 PushIllegalParameter();
+                 return;
+-            }
+-        }
+-        else
+-        {
+-            PushIllegalParameter();
+-            return;
+         }
++
+         if (nGlobalError == 0)
+         {
+             double fVal;
+@@ -4174,6 +4269,32 @@ void ScInterpreter::ScMatch()
+                     }
+                 }
+                 break;
++                case svExternalSingleRef:
++                {
++                    ScExternalRefCache::TokenRef pToken;
++                    PopExternalSingleRef(pToken);
++                    if (!pToken)
++                    {
++                        PushInt(0);
++                        return;
++                    }
++                    if (pToken->GetType() == svDouble)
++                    {
++                        rEntry.bQueryByString = false;
++                        rEntry.nVal = pToken->GetDouble();
++                    }
++                    else
++                    {
++                        rEntry.bQueryByString = true;
++                        *rEntry.pStr = pToken->GetString();
++                    }
++                }
++                break;
++                case svExternalDoubleRef:
++                    // TODO: Implement this.
++                    PushIllegalParameter();
++                    return;
++                break;
+                 case svMatrix :
+                 {
+                     ScMatValType nType = GetDoubleOrStringFromMatrix(
+@@ -5861,7 +5982,7 @@ ScDBQueryParamBase* ScInterpreter::GetDBParams( BOOL& rMissingField )
+     if ( GetByte() == 3 )
+     {
+         // First, get the query criteria range.
+-        ::std::auto_ptr<ScDBRangeBase> pQueryRef( PopDoubleRef() );
++        ::std::auto_ptr<ScDBRangeBase> pQueryRef( PopDBDoubleRef() );
+         if (!pQueryRef.get())
+             return NULL;
+ 
+@@ -5919,7 +6040,7 @@ ScDBQueryParamBase* ScInterpreter::GetDBParams( BOOL& rMissingField )
+                 SetError( errIllegalParameter );
+         }
+ 
+-        auto_ptr<ScDBRangeBase> pDBRef( PopDoubleRef() );
++        auto_ptr<ScDBRangeBase> pDBRef( PopDBDoubleRef() );
+ 
+         if (nGlobalError || !pDBRef.get())
+             return NULL;
+@@ -5986,6 +6107,7 @@ ScDBQueryParamBase* ScInterpreter::GetDBParams( BOOL& rMissingField )
+ 
+ void ScInterpreter::DBIterator( ScIterFunc eFunc )
+ {
++//  StackPrinter __stack_printer__("ScInterpreter::DBIterator");
+     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::DBIterator" );
+     double nErg = 0.0;
+     double fMem = 0.0;
+@@ -6328,15 +6450,10 @@ void ScInterpreter::ScIndirect()
+         {
+             if (aExtInfo.mbExternal)
+             {
+-                /* TODO: future versions should implement a proper subroutine 
+-                 * token. This procedure here is a minimally invasive fix for 
+-                 * #i101645# in OOo3.1.1 */
+-                // Push a subroutine on the instruction code stack that 
+-                // resolves the external reference as the next instruction.
+-                aCode.Push( lcl_CreateExternalRefTokenArray( aPos, pDok, 
+-                            aExtInfo, aRefAd, &aRefAd2));
+-                // Signal subroutine call to interpreter.
+-                PushTempToken( new FormulaUnknownToken( ocCall));
++                PushExternalDoubleRef(
++                    aExtInfo.mnFileId, aExtInfo.maTabName, 
++                    aRefAd.Col(), aRefAd.Row(), aRefAd.Tab(),
++                    aRefAd2.Col(), aRefAd2.Row(), aRefAd2.Tab());
+             }
+             else
+                 PushDoubleRef( aRefAd.Col(), aRefAd.Row(), aRefAd.Tab(),
+@@ -6348,15 +6465,8 @@ void ScInterpreter::ScIndirect()
+         {
+             if (aExtInfo.mbExternal)
+             {
+-                /* TODO: future versions should implement a proper subroutine 
+-                 * token. This procedure here is a minimally invasive fix for 
+-                 * #i101645# in OOo3.1.1 */
+-                // Push a subroutine on the instruction code stack that 
+-                // resolves the external reference as the next instruction.
+-                aCode.Push( lcl_CreateExternalRefTokenArray( aPos, pDok, 
+-                            aExtInfo, aRefAd, NULL));
+-                // Signal subroutine call to interpreter.
+-                PushTempToken( new FormulaUnknownToken( ocCall));
++                PushExternalSingleRef(
++                    aExtInfo.mnFileId, aExtInfo.maTabName, aRefAd.Col(), aRefAd.Row(), aRefAd.Tab());
+             }
+             else
+                 PushSingleRef( aRefAd.Col(), aRefAd.Row(), aRefAd.Tab() );
+@@ -6540,6 +6650,44 @@ void ScInterpreter::ScOffset()
+                     PushDoubleRef(nCol1, nRow1, nTab1, nCol2, nRow2, nTab1);
+             }
+         }
++        else if (GetStackType() == svExternalSingleRef)
++        {
++            sal_uInt16 nFileId;
++            String aTabName;
++            ScSingleRefData aRef;
++            PopExternalSingleRef(nFileId, aTabName, aRef);
++            aRef.CalcAbsIfRel(aPos);
++            nCol1 = aRef.nCol;
++            nRow1 = aRef.nRow;
++            nTab1 = aRef.nTab;
++
++            if (nParamCount == 3 || (nColNew < 0 && nRowNew < 0))
++            {
++                nCol1 = (SCCOL)((long) nCol1 + nColPlus);
++                nRow1 = (SCROW)((long) nRow1 + nRowPlus);
++                if (!ValidCol(nCol1) || !ValidRow(nRow1))
++                    PushIllegalArgument();
++                else
++                    PushExternalSingleRef(nFileId, aTabName, nCol1, nRow1, nTab1);
++            }
++            else
++            {
++                if (nColNew < 0)
++                    nColNew = 1;
++                if (nRowNew < 0)
++                    nRowNew = 1;
++                nCol1 = (SCCOL)((long)nCol1+nColPlus);      // ! nCol1 wird veraendert!
++                nRow1 = (SCROW)((long)nRow1+nRowPlus);
++                nCol2 = (SCCOL)((long)nCol1+nColNew-1);
++                nRow2 = (SCROW)((long)nRow1+nRowNew-1);
++                PushIllegalArgument();
++                if (!ValidCol(nCol1) || !ValidRow(nRow1) ||
++                    !ValidCol(nCol2) || !ValidRow(nRow2))
++                    PushIllegalArgument();
++                else
++                    PushExternalDoubleRef(nFileId, aTabName, nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
++            }
++        }
+         else if (GetStackType() == svDoubleRef)
+         {
+             PopDoubleRef(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
+@@ -6557,6 +6705,33 @@ void ScInterpreter::ScOffset()
+             else
+                 PushDoubleRef(nCol1, nRow1, nTab1, nCol2, nRow2, nTab1);
+         }
++        else if (GetStackType() == svExternalDoubleRef)
++        {
++            sal_uInt16 nFileId;
++            String aTabName;
++            ScComplexRefData aRef;
++            PopExternalDoubleRef(nFileId, aTabName, aRef);
++            aRef.CalcAbsIfRel(aPos);
++            nCol1 = aRef.Ref1.nCol;
++            nRow1 = aRef.Ref1.nRow;
++            nTab1 = aRef.Ref1.nTab;
++            nCol2 = aRef.Ref2.nCol;
++            nRow2 = aRef.Ref2.nRow;
++            nTab2 = aRef.Ref2.nTab;
++            if (nColNew < 0)
++                nColNew = nCol2 - nCol1 + 1;
++            if (nRowNew < 0)
++                nRowNew = nRow2 - nRow1 + 1;
++            nCol1 = (SCCOL)((long)nCol1+nColPlus);
++            nRow1 = (SCROW)((long)nRow1+nRowPlus);
++            nCol2 = (SCCOL)((long)nCol1+nColNew-1);
++            nRow2 = (SCROW)((long)nRow1+nRowNew-1);
++            if (!ValidCol(nCol1) || !ValidRow(nRow1) ||
++                !ValidCol(nCol2) || !ValidRow(nRow2) || nTab1 != nTab2)
++                PushIllegalArgument();
++            else
++                PushExternalDoubleRef(nFileId, aTabName, nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
++        }
+         else
+             PushIllegalParameter();
+     }
+diff --git sc/source/core/tool/interpr4.cxx sc/source/core/tool/interpr4.cxx
+index 49c4d2a..5a824e5 100644
+--- sc/source/core/tool/interpr4.cxx
++++ sc/source/core/tool/interpr4.cxx
+@@ -1249,40 +1249,42 @@ void ScInterpreter::DoubleRefToVars( const ScToken* p,
+     }
+ }
+ 
+-ScDBRangeBase* ScInterpreter::PopDoubleRef()
++ScDBRangeBase* ScInterpreter::PopDBDoubleRef()
+ {
+-    if (!sp)
+-    {    
+-        SetError(errUnknownStackVariable);
+-        return NULL;
+-    }
+-
+-    --sp;
+-    FormulaToken* p = pStack[sp];
+-    switch (p->GetType())
++    StackVar eType = GetStackType();
++    switch (eType)
+     {
++        case svUnknown:
++            SetError(errUnknownStackVariable);
++        break;
+         case svError:
+-            nGlobalError = p->GetError();
++            PopError();
+         break;
+         case svDoubleRef:
+         {
+             SCCOL nCol1, nCol2;
+             SCROW nRow1, nRow2;
+             SCTAB nTab1, nTab2;
+-            DoubleRefToVars(static_cast<ScToken*>(p), 
+-                            nCol1, nRow1, nTab1, nCol2, nRow2, nTab2, false);
+-            
++            PopDoubleRef(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2, false);
++            if (nGlobalError)
++                break;
+             return new ScDBInternalRange(pDok,
+                 ScRange(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2));
+         }
+         case svMatrix:
++        case svExternalDoubleRef:
+         {
+-            ScMatrixRef pMat = static_cast<ScToken*>(p)->GetMatrix();
++            ScMatrixRef pMat;
++            if (eType == svMatrix)
++                pMat = PopMatrix();
++            else
++                PopExternalDoubleRef(pMat);
+             return new ScDBExternalRange(pDok, pMat);
+         }
+         default:
+             SetError( errIllegalParameter);
+     }
++
+     return NULL;
+ }
+ 
+@@ -1402,6 +1404,171 @@ void ScInterpreter::PopDoubleRef( ScRange& rRange, BOOL bDontCheckForTableOp )
+         SetError( errUnknownStackVariable);
+ }
+ 
++void ScInterpreter::PopExternalSingleRef(sal_uInt16& rFileId, String& rTabName, ScSingleRefData& rRef)
++{
++    if (!sp)
++    {
++        SetError(errUnknownStackVariable);
++        return;
++    }
++
++    --sp;
++    FormulaToken* p = pStack[sp];
++    StackVar eType = p->GetType();
++
++    if (eType == svError)
++    {
++        nGlobalError = p->GetError();
++        return;
++    }
++
++    if (eType != svExternalSingleRef)
++    {
++        SetError( errIllegalParameter);
++        return;
++    }
++
++    rFileId = p->GetIndex();
++    rTabName = p->GetString();
++    rRef = static_cast<ScToken*>(p)->GetSingleRef();
++}
++
++void ScInterpreter::PopExternalSingleRef(ScExternalRefCache::TokenRef& rToken, ScExternalRefCache::CellFormat* pFmt)
++{
++
++    sal_uInt16 nFileId;
++    String aTabName;
++    ScSingleRefData aData;
++    PopExternalSingleRef(nFileId, aTabName, aData);
++    if (nGlobalError)
++        return;
++
++    ScExternalRefManager* pRefMgr = pDok->GetExternalRefManager();
++    const String* pFile = pRefMgr->getExternalFileName(nFileId);
++    if (!pFile)
++    {
++        SetError(errNoName);
++        return;
++    }
++
++    if (aData.IsTabRel())
++    {
++        DBG_ERROR("ScCompiler::GetToken: external single reference must have an absolute table reference!");
++        SetError(errNoRef);
++        return;
++    }
++
++    aData.CalcAbsIfRel(aPos);
++    ScAddress aAddr(aData.nCol, aData.nRow, aData.nTab);
++    ScExternalRefCache::CellFormat aFmt;
++    ScExternalRefCache::TokenRef xNew = pRefMgr->getSingleRefToken(
++        nFileId, aTabName, aAddr, &aPos, NULL, &aFmt);
++
++    if (!xNew)
++    {
++        SetError(errNoRef);
++        return;
++    }
++
++    rToken = xNew;
++    if (pFmt)
++        *pFmt = aFmt;
++}
++
++void ScInterpreter::PopExternalDoubleRef(sal_uInt16& rFileId, String& rTabName, ScComplexRefData& rRef)
++{
++    if (!sp)
++    {
++        SetError(errUnknownStackVariable);
++        return;
++    }
++
++    --sp;
++    FormulaToken* p = pStack[sp];
++    StackVar eType = p->GetType();
++
++    if (eType == svError)
++    {
++        nGlobalError = p->GetError();
++        return;
++    }
++
++    if (eType != svExternalDoubleRef)
++    {
++        SetError( errIllegalParameter);
++        return;
++    }
++
++    rFileId = p->GetIndex();
++    rTabName = p->GetString();
++    rRef = static_cast<ScToken*>(p)->GetDoubleRef();
++}
++
++void ScInterpreter::PopExternalDoubleRef(ScExternalRefCache::TokenArrayRef& rArray)
++{
++    sal_uInt16 nFileId;
++    String aTabName;
++    ScComplexRefData aData;
++    PopExternalDoubleRef(nFileId, aTabName, aData);
++    if (nGlobalError)
++        return;
++
++    ScExternalRefManager* pRefMgr = pDok->GetExternalRefManager();
++    const String* pFile = pRefMgr->getExternalFileName(nFileId);
++    if (!pFile)
++    {
++        SetError(errNoName);
++        return;
++    }
++    if (aData.Ref1.IsTabRel() || aData.Ref2.IsTabRel())
++    {
++        DBG_ERROR("ScCompiler::GetToken: external double reference must have an absolute table reference!");
++        SetError(errNoRef);
++        return;
++    }
++
++    aData.CalcAbsIfRel(aPos);
++    ScRange aRange(aData.Ref1.nCol, aData.Ref1.nRow, aData.Ref1.nTab,
++                   aData.Ref2.nCol, aData.Ref2.nRow, aData.Ref2.nTab);
++    ScExternalRefCache::TokenArrayRef pArray = pRefMgr->getDoubleRefTokens(
++        nFileId, aTabName, aRange, &aPos);
++
++    if (!pArray)
++    {
++        SetError(errIllegalArgument);
++        return;
++    }
++
++    ScToken* pToken = static_cast<ScToken*>(pArray->First());
++    if (pToken->GetType() != svMatrix)
++    {
++        SetError(errIllegalArgument);
++        return;
++    }
++
++    if (pArray->Next())
++    {
++        // Can't handle more than one matrix per parameter.
++        SetError( errIllegalArgument);
++        return;
++    }
++
++    rArray = pArray;
++}
++
++void ScInterpreter::PopExternalDoubleRef(ScMatrixRef& rMat)
++{
++    ScExternalRefCache::TokenArrayRef pArray;
++    PopExternalDoubleRef(pArray);
++    if (nGlobalError)
++        return;
++
++    // For now, we only support single range data for external
++    // references, which means the array should only contain a
++    // single matrix token.
++    ScToken* p = static_cast<ScToken*>(pArray->First());
++    rMat = p->GetMatrix();
++}
+ 
+ BOOL ScInterpreter::PopDoubleRefOrSingleRef( ScAddress& rAdr )
+ {
+@@ -1684,6 +1851,40 @@ void ScInterpreter::PushDoubleRef(SCCOL nCol1, SCROW nRow1, SCTAB nTab1,
+ }
+ 
+ 
++void ScInterpreter::PushExternalSingleRef(
++    sal_uInt16 nFileId, const String& rTabName, SCCOL nCol, SCROW nRow, SCTAB nTab)
++{
++    if (!IfErrorPushError())
++    {
++        ScSingleRefData aRef;
++        aRef.InitFlags();
++        aRef.nCol = nCol;
++        aRef.nRow = nRow;
++        aRef.nTab = nTab;
++        PushTempTokenWithoutError( new ScExternalSingleRefToken(nFileId, rTabName, aRef)) ;
++    }
++}
++
++
++void ScInterpreter::PushExternalDoubleRef(
++    sal_uInt16 nFileId, const String& rTabName, 
++    SCCOL nCol1, SCROW nRow1, SCTAB nTab1, SCCOL nCol2, SCROW nRow2, SCTAB nTab2)
++{
++    if (!IfErrorPushError())
++    {
++        ScComplexRefData aRef;
++        aRef.InitFlags();
++        aRef.Ref1.nCol = nCol1;
++        aRef.Ref1.nRow = nRow1;
++        aRef.Ref1.nTab = nTab1;
++        aRef.Ref2.nCol = nCol2;
++        aRef.Ref2.nRow = nRow2;
++        aRef.Ref2.nTab = nTab2;
++        PushTempTokenWithoutError( new ScExternalDoubleRefToken(nFileId, rTabName, aRef) );
++    }
++}
++
++
+ void ScInterpreter::PushMatrix(ScMatrix* pMat)
+ {
+     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::PushMatrix" );
+@@ -1886,6 +2087,23 @@ BOOL ScInterpreter::DoubleRefToPosSingleRef( const ScRange& rRange, ScAddress& r
+     return bOk;
+ }
+ 
++double ScInterpreter::GetDoubleFromMatrix(const ScMatrixRef& pMat)
++{
++    if (!pMat)
++        return 0.0;
++
++    if ( !pJumpMatrix )
++        return pMat->GetDouble( 0 );
++
++    SCSIZE nCols, nRows, nC, nR;
++    pMat->GetDimensions( nCols, nRows);
++    pJumpMatrix->GetPos( nC, nR);
++    if ( nC < nCols && nR < nRows )
++        return pMat->GetDouble( nC, nR);
++
++    SetError( errNoValue);
++    return 0.0;
++}
+ 
+ double ScInterpreter::GetDouble()
+ {
+@@ -1921,26 +2139,28 @@ double ScInterpreter::GetDouble()
+                 nVal = 0.0;
+         }
+         break;
++        case svExternalSingleRef:
++        {
++            ScExternalRefCache::TokenRef pToken;
++            PopExternalSingleRef(pToken);
++            if (!nGlobalError && pToken)
++                nVal = pToken->GetDouble();
++        }
++        break;
++        case svExternalDoubleRef:
++        {
++            ScMatrixRef pMat;
++            PopExternalDoubleRef(pMat);
++            if (nGlobalError)
++                break;
++
++            nVal = GetDoubleFromMatrix(pMat);
++        }
++        break;
+         case svMatrix:
+         {
+             ScMatrixRef pMat = PopMatrix();
+-            if ( !pMat )
+-                nVal = 0.0;
+-            else if ( !pJumpMatrix )
+-                nVal = pMat->GetDouble( 0 );
+-            else
+-            {
+-                SCSIZE nCols, nRows, nC, nR;
+-                pMat->GetDimensions( nCols, nRows);
+-                pJumpMatrix->GetPos( nC, nR);
+-                if ( nC < nCols && nR < nRows )
+-                    nVal = pMat->GetDouble( nC, nR);
+-                else
+-                {
+-                    SetError( errNoValue);
+-                    nVal = 0.0;
+-                }
+-            }
++            nVal = GetDoubleFromMatrix(pMat);
+         }
+         break;
+         case svError:
+@@ -2029,30 +2249,23 @@ const String& ScInterpreter::GetString()
+             else
+                 return EMPTY_STRING;
+         }
++        case svExternalSingleRef:
++        {
++            ScExternalRefCache::TokenRef pToken;
++            PopExternalSingleRef(pToken);
++            return nGlobalError ? EMPTY_STRING : pToken->GetString();
++        }
++        case svExternalDoubleRef:
++        {
++            ScMatrixRef pMat;
++            PopExternalDoubleRef(pMat);
++            return GetStringFromMatrix(pMat);
++        }
+         //break;
+         case svMatrix:
+         {
+             ScMatrixRef pMat = PopMatrix();
+-            if ( !pMat )
+-                ;   // nothing
+-            else if ( !pJumpMatrix )
+-            {
+-                aTempStr = pMat->GetString( *pFormatter, 0, 0);
+-                return aTempStr;
+-            }
+-            else
+-            {
+-                SCSIZE nCols, nRows, nC, nR;
+-                pMat->GetDimensions( nCols, nRows);
+-                pJumpMatrix->GetPos( nC, nR);
+-                if ( nC < nCols && nR < nRows )
+-                {
+-                    aTempStr = pMat->GetString( *pFormatter, nC, nR);
+-                    return aTempStr;
+-                }
+-                else
+-                    SetError( errNoValue);
+-            }
++            return GetStringFromMatrix(pMat);
+         }
+         break;
+         default:
+@@ -2062,7 +2275,30 @@ const String& ScInterpreter::GetString()
+     return EMPTY_STRING;
+ }
+ 
+-
++const String& ScInterpreter::GetStringFromMatrix(const ScMatrixRef& pMat)
++{
++    if ( !pMat )
++        ;   // nothing
++    else if ( !pJumpMatrix )
++    {
++        aTempStr = pMat->GetString( *pFormatter, 0, 0);
++        return aTempStr;
++    }
++    else
++    {
++        SCSIZE nCols, nRows, nC, nR;
++        pMat->GetDimensions( nCols, nRows);
++        pJumpMatrix->GetPos( nC, nR);
++        if ( nC < nCols && nR < nRows )
++        {
++            aTempStr = pMat->GetString( *pFormatter, nC, nR);
++            return aTempStr;
++        }
++        else
++            SetError( errNoValue);
++    }
++    return EMPTY_STRING;
++}
+ 
+ ScMatValType ScInterpreter::GetDoubleOrStringFromMatrix( double& rDouble,
+         String& rString )
+@@ -3295,82 +3531,6 @@ void ScInterpreter::ScColRowNameAuto()
+         PushError( errNoRef );
+ }
+ 
+-void ScInterpreter::ScExternalRef()
+-{
+-    ScExternalRefManager* pRefMgr = pDok->GetExternalRefManager();
+-    const String* pFile = pRefMgr->getExternalFileName(pCur->GetIndex());
+-    if (!pFile)
+-        PushError(errNoName);
+-
+-    switch (pCur->GetType())
+-    {
+-        case svExternalSingleRef:
+-        {
+-            ScSingleRefData aData(static_cast<const ScToken*>(pCur)->GetSingleRef());
+-            if (aData.IsTabRel())
+-            {
+-                DBG_ERROR("ScCompiler::GetToken: external single reference must have an absolute table reference!");
+-                break;
+-            }
+-
+-            aData.CalcAbsIfRel(aPos);
+-            ScAddress aAddr(aData.nCol, aData.nRow, aData.nTab);
+-            ScExternalRefCache::CellFormat aFmt;
+-            ScExternalRefCache::TokenRef xNew = pRefMgr->getSingleRefToken(
+-                pCur->GetIndex(), pCur->GetString(), aAddr, &aPos, NULL, &aFmt);
+-
+-            if (!xNew)
+-                break;
+-
+-            PushTempToken( *xNew);      // push a clone
+-
+-            if (aFmt.mbIsSet)
+-            {
+-                nFuncFmtType = aFmt.mnType;
+-                nFuncFmtIndex = aFmt.mnIndex;
+-            }
+-            return;
+-        }
+-        //break;    // unreachable, prevent compiler warning
+-        case svExternalDoubleRef:
+-        {
+-            ScComplexRefData aData(static_cast<const ScToken*>(pCur)->GetDoubleRef());
+-            if (aData.Ref1.IsTabRel() || aData.Ref2.IsTabRel())
+-            {
+-                DBG_ERROR("ScCompiler::GetToken: external double reference must have an absolute table reference!");
+-                break;
+-            }
+-
+-            aData.CalcAbsIfRel(aPos);
+-            ScRange aRange(aData.Ref1.nCol, aData.Ref1.nRow, aData.Ref1.nTab,
+-                           aData.Ref2.nCol, aData.Ref2.nRow, aData.Ref2.nTab);
+-            ScExternalRefCache::TokenArrayRef xNew = pRefMgr->getDoubleRefTokens(
+-                pCur->GetIndex(), pCur->GetString(), aRange, &aPos);
+-
+-            if (!xNew)
+-                break;
+-
+-            ScToken* p = static_cast<ScToken*>(xNew->First());
+-            if (p->GetType() != svMatrix)
+-                break;
+-
+-            if (xNew->Next())
+-            {
+-                // Can't handle more than one matrix per parameter.
+-                SetError( errIllegalArgument);
+-                break;
+-            }
+-
+-            PushMatrix(p->GetMatrix());
+-            return;
+-        }
+-        //break;    // unreachable, prevent compiler warning
+-        default:
+-            ;
+-    }
+-    PushError(errNoRef);
+-}
+-
+ // --- internals ------------------------------------------------------------
+ 
+ 
+@@ -3443,6 +3603,7 @@ void ScInterpreter::GlobalExit()        // static
+ 
+ StackVar ScInterpreter::Interpret()
+ {
++//  StackPrinter __stack_printer__("ScInterpreter::Interpret");
+     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::Interpret" );
+     short nRetTypeExpr = NUMBERFORMAT_UNDEFINED;
+     ULONG nRetIndexExpr = 0;
+@@ -3526,7 +3687,6 @@ StackVar ScInterpreter::Interpret()
+                 case ocDBArea           : ScDBArea();                   break;
+                 case ocColRowNameAuto   : ScColRowNameAuto();           break;
+ // separated    case ocPush             : Push( (ScToken&) *pCur );     break;
+-                case ocExternalRef      : ScExternalRef();              break;
+                 case ocIf               : ScIfJump();                   break;
+                 case ocChose            : ScChoseJump();                break;
+                 case ocAdd              : ScAdd();                      break;
+@@ -3998,9 +4158,15 @@ StackVar ScInterpreter::Interpret()
+                     }
+                 }
+                 // no break
++                case svExternalDoubleRef:
+                 case svMatrix :
+                 {
+-                    ScMatrixRef xMat = PopMatrix();
++                    ScMatrixRef xMat;
++                    if (pCur->GetType() == svMatrix)
++                        xMat = PopMatrix();
++                    else
++                        PopExternalDoubleRef(xMat);
++
+                     if (xMat)
+                     {
+                         ScMatValType nMatValType;
+@@ -4045,6 +4211,23 @@ StackVar ScInterpreter::Interpret()
+                         SetError( errUnknownStackVariable);
+                 }
+                 break;
++                case svExternalSingleRef:
++                {
++                    ScExternalRefCache::TokenRef pToken;
++                    ScExternalRefCache::CellFormat aFmt;
++                    PopExternalSingleRef(pToken, &aFmt);
++                    if (nGlobalError)
++                        break;
++
++                    PushTempToken(*pToken);
++
++                    if (aFmt.mbIsSet)
++                    {
++                        nFuncFmtType = aFmt.mnType;
++                        nFuncFmtIndex = aFmt.mnIndex;
++                    }
++                }
++                break;
+                 default :
+                     SetError( errUnknownStackVariable);
+             }
+diff --git sc/source/core/tool/token.cxx sc/source/core/tool/token.cxx
+index 66665b0..fc368d0 100644
+--- sc/source/core/tool/token.cxx
++++ sc/source/core/tool/token.cxx
+@@ -240,7 +240,7 @@ void ScRawToken::SetName( USHORT n )
+ 
+ void ScRawToken::SetExternalSingleRef( sal_uInt16 nFileId, const String& rTabName, const ScSingleRefData& rRef )
+ {
+-    eOp = ocExternalRef;
++    eOp = ocPush;
+     eType = svExternalSingleRef;
+     nRefCnt = 0;
+ 
+@@ -255,7 +255,7 @@ void ScRawToken::SetExternalSingleRef( sal_uInt16 nFileId, const String& rTabNam
+ 
+ void ScRawToken::SetExternalDoubleRef( sal_uInt16 nFileId, const String& rTabName, const ScComplexRefData& rRef )
+ {
+-    eOp = ocExternalRef;
++    eOp = ocPush;
+     eType = svExternalDoubleRef;
+     nRefCnt = 0;
+ 
+@@ -269,7 +269,7 @@ void ScRawToken::SetExternalDoubleRef( sal_uInt16 nFileId, const String& rTabNam
+ 
+ void ScRawToken::SetExternalName( sal_uInt16 nFileId, const String& rName )
+ {
+-    eOp = ocExternalRef;
++    eOp = ocPush;
+     eType = svExternalName;
+     nRefCnt = 0;
+ 
+@@ -347,37 +347,26 @@ ScRawToken* ScRawToken::Clone() const
+         static USHORT nOffset = lcl_ScRawTokenOffset();     // offset of sbyte
+         USHORT n = nOffset;
+ 
+-        if (eOp == ocExternalRef)
++        switch( eType )
+         {
+-            switch (eType)
+-            {
+-                case svExternalSingleRef:
+-                case svExternalDoubleRef: n += sizeof(extref); break;
+-                case svExternalName:      n += sizeof(extname); break;
+-                default:
+-                {
+-                    DBG_ERROR1( "unknown ScRawToken::Clone() external type %d", int(eType));
+-                }
+-            }
+-        }
+-        else
+-        {
+-            switch( eType )
++            case svSep:         break;
++            case svByte:        n += sizeof(ScRawToken::sbyte); break;
++            case svDouble:      n += sizeof(double); break;
++            case svString:      n = sal::static_int_cast<USHORT>( n + GetStrLenBytes( cStr ) + GetStrLenBytes( 1 ) ); break;
++            case svSingleRef:
++            case svDoubleRef:   n += sizeof(aRef); break;
++            case svMatrix:      n += sizeof(ScMatrix*); break;
++            case svIndex:       n += sizeof(USHORT); break;
++            case svJump:        n += nJump[ 0 ] * 2 + 2; break;
++            case svExternal:    n = sal::static_int_cast<USHORT>( n + GetStrLenBytes( cStr+1 ) + GetStrLenBytes( 2 ) ); break;
++
++            // external references
++            case svExternalSingleRef:
++            case svExternalDoubleRef: n += sizeof(extref); break;
++            case svExternalName:      n += sizeof(extname); break;
++            default:
+             {
+-                case svSep:         break;
+-                case svByte:        n += sizeof(ScRawToken::sbyte); break;
+-                case svDouble:      n += sizeof(double); break;
+-                case svString:      n = sal::static_int_cast<USHORT>( n + GetStrLenBytes( cStr ) + GetStrLenBytes( 1 ) ); break;
+-                case svSingleRef:
+-                case svDoubleRef:   n += sizeof(aRef); break;
+-                case svMatrix:      n += sizeof(ScMatrix*); break;
+-                case svIndex:       n += sizeof(USHORT); break;
+-                case svJump:        n += nJump[ 0 ] * 2 + 2; break;
+-                case svExternal:    n = sal::static_int_cast<USHORT>( n + GetStrLenBytes( cStr+1 ) + GetStrLenBytes( 2 ) ); break;
+-                default:
+-                {
+-                    DBG_ERROR1( "unknown ScRawToken::Clone() type %d", int(eType));
+-                }
++                DBG_ERROR1( "unknown ScRawToken::Clone() type %d", int(eType));
+             }
+         }
+         p = (ScRawToken*) new BYTE[ n ];
+@@ -841,7 +830,7 @@ BOOL ScMatrixToken::operator==( const FormulaToken& r ) const
+ // ============================================================================
+ 
+ ScExternalSingleRefToken::ScExternalSingleRefToken( sal_uInt16 nFileId, const String& rTabName, const ScSingleRefData& r ) :
+-    ScToken( svExternalSingleRef, ocExternalRef),
++    ScToken( svExternalSingleRef, ocPush),
+     mnFileId(nFileId),
+     maTabName(rTabName),
+     maSingleRef(r)
+@@ -907,7 +896,7 @@ BOOL ScExternalSingleRefToken::operator ==( const FormulaToken& r ) const
+ // ============================================================================
+ 
+ ScExternalDoubleRefToken::ScExternalDoubleRefToken( sal_uInt16 nFileId, const String& rTabName, const ScComplexRefData& r ) :
+-    ScToken( svExternalDoubleRef, ocExternalRef),
++    ScToken( svExternalDoubleRef, ocPush),
+     mnFileId(nFileId),
+     maTabName(rTabName),
+     maDoubleRef(r)
+@@ -993,7 +982,7 @@ BOOL ScExternalDoubleRefToken::operator ==( const FormulaToken& r ) const
+ // ============================================================================
+ 
+ ScExternalNameToken::ScExternalNameToken( sal_uInt16 nFileId, const String& rName ) :
+-    ScToken( svExternalName, ocExternalRef),
++    ScToken( svExternalName, ocPush),
+     mnFileId(nFileId),
+     maName(rName)
+ {
+diff --git sc/source/filter/excel/xeformula.cxx sc/source/filter/excel/xeformula.cxx
+index 17124e8..3fa343a 100644
+--- sc/source/filter/excel/xeformula.cxx
++++ sc/source/filter/excel/xeformula.cxx
+@@ -2104,7 +2104,7 @@ void XclExpFmlaCompImpl::ProcessExternalName( const XclExpScToken& rTokData )
+             {
+                 for( FormulaToken* pScToken = xArray->First(); pScToken; pScToken = xArray->Next() )
+                 {
+-                    if( pScToken->GetOpCode() == ocExternalRef )
++                    if( pScToken->IsExternalRef() )
+                     {
+                         switch( pScToken->GetType() )
+                         {
+diff --git sc/source/filter/excel/xelink.cxx sc/source/filter/excel/xelink.cxx
+index 645abc2..efb0be6 100644
+--- sc/source/filter/excel/xelink.cxx
++++ sc/source/filter/excel/xelink.cxx
+@@ -968,7 +968,7 @@ void XclExpExtName::WriteAddData( XclExpStream& rStrm )
+             break;
+ 
+         const ScToken* p = static_cast<const ScToken*>(mpArray->First());
+-        if (p->GetOpCode() != ocExternalRef)
++        if (!p->IsExternalRef())
+             break;
+ 
+         switch (p->GetType())
+diff --git sc/source/ui/docshell/externalrefmgr.cxx sc/source/ui/docshell/externalrefmgr.cxx
+index 8291375..01af6d0 100644
+--- sc/source/ui/docshell/externalrefmgr.cxx
++++ sc/source/ui/docshell/externalrefmgr.cxx
+@@ -145,7 +145,7 @@ struct UpdateFormulaCell : public unary_function<ScFormulaCell*, void>
+         // External names, external cell and range references all have a
+         // ocExternalRef token.
+         const ScTokenArray* pCode = pCell->GetCode();
+-        if (!pCode->HasOpCode( ocExternalRef))
++        if (!pCode->HasExternalRef())
+             return;
+ 
+         ScTokenArray* pArray = pCell->GetCode();
+@@ -1362,7 +1362,7 @@ static FormulaToken* lcl_convertToToken(ScBaseCell* pCell)
+     return NULL;
+ }
+ 
+-static ScTokenArray* lcl_convertToTokenArray(ScDocument* pSrcDoc, ScRange& rRange,
++static ScTokenArray* lcl_convertToTokenArray(const ScDocument* pSrcDoc, ScRange& rRange,
+                                              vector<ScExternalRefCache::SingleRangeData>& rCacheData)
+ {
+     ScAddress& s = rRange.aStart;
+@@ -1665,6 +1665,27 @@ ScExternalRefCache::TokenRef ScExternalRefManager::getSingleRefToken(
+     if (pFmt)
+         pFmt->mbIsSet = false;
+ 
++    const ScDocument* pSrcDoc = getInMemorySrcDocument(nFileId);
++    if (pSrcDoc)
++    {   
++        // source document already loaded in memory.  Re-use this instance.
++        // We don't even cache data when the document is loaded.
++
++        SCTAB nTab;
++        if (!pSrcDoc->GetTable(rTabName, nTab))
++        {
++            // specified table name doesn't exist in the source document.
++            ScExternalRefCache::TokenRef pToken(new FormulaErrorToken(errNoRef));
++            return pToken;
++        }
++
++        if (pTab)
++            *pTab = nTab;
++
++        return getSingleRefTokenFromSrcDoc(
++            nFileId, pSrcDoc, ScAddress(rCell.Col(),rCell.Row(),nTab), pFmt);
++    }
++
+     // Check if the given table name and the cell position is cached.
+     sal_uInt32 nFmtIndex = 0;
+     ScExternalRefCache::TokenRef pToken = maRefCache.getCellData(
+@@ -1672,21 +1693,12 @@ ScExternalRefCache::TokenRef ScExternalRefManager::getSingleRefToken(
+     if (pToken)
+     {
+         // Cache hit !
+-        if (pFmt)
+-        {
+-            short nFmtType = mpDoc->GetFormatTable()->GetType(nFmtIndex);
+-            if (nFmtType != NUMBERFORMAT_UNDEFINED)
+-            {
+-                pFmt->mbIsSet = true;
+-                pFmt->mnIndex = nFmtIndex;
+-                pFmt->mnType = nFmtType;
+-            }
+-        }
++        fillCellFormat(nFmtIndex, pFmt);
+         return pToken;
+     }
+ 
+     // reference not cached.  read from the source document.
+-    ScDocument* pSrcDoc = getSrcDocument(nFileId);
++    pSrcDoc = getSrcDocument(nFileId);
+     if (!pSrcDoc)
+     {
+         // Source document not reachable.  Throw a reference error.
+@@ -1694,7 +1706,6 @@ ScExternalRefCache::TokenRef ScExternalRefManager::getSingleRefToken(
+         return pToken;
+     }
+ 
+-    ScBaseCell* pCell = NULL;
+     SCTAB nTab;
+     if (!pSrcDoc->GetTable(rTabName, nTab))
+     {
+@@ -1723,33 +1734,14 @@ ScExternalRefCache::TokenRef ScExternalRefManager::getSingleRefToken(
+         return pToken;
+     }
+ 
+-    pSrcDoc->GetCell(rCell.Col(), rCell.Row(), nTab, pCell);
+-    ScExternalRefCache::TokenRef pTok(lcl_convertToToken(pCell));
+-
+-    pSrcDoc->GetNumberFormat(rCell.Col(), rCell.Row(), nTab, nFmtIndex);
+-    nFmtIndex = getMappedNumberFormat(nFileId, nFmtIndex, pSrcDoc);
+-    if (pFmt)
+-    {
+-        short nFmtType = mpDoc->GetFormatTable()->GetType(nFmtIndex);
+-        if (nFmtType != NUMBERFORMAT_UNDEFINED)
+-        {
+-            pFmt->mbIsSet = true;
+-            pFmt->mnIndex = nFmtIndex;
+-            pFmt->mnType = nFmtType;
+-        }
+-    }
+-
+-    if (!pTok.get())
+-    {
+-        // Generate an error for unresolvable cells.
+-        pTok.reset( new FormulaErrorToken( errNoValue));
+-    }
++    pToken = getSingleRefTokenFromSrcDoc(
++        nFileId, pSrcDoc, ScAddress(rCell.Col(),rCell.Row(),nTab), pFmt);
+ 
+     // Now, insert the token into cache table but don't cache empty cells.
+-    if (pTok->GetType() != formula::svEmptyCell)
+-        maRefCache.setCellData(nFileId, rTabName, rCell.Col(), rCell.Row(), pTok, nFmtIndex);
++    if (pToken->GetType() != formula::svEmptyCell)
++        maRefCache.setCellData(nFileId, rTabName, rCell.Col(), rCell.Row(), pToken, nFmtIndex);
+ 
+-    return pTok;
++    return pToken;
+ }
+ 
+ ScExternalRefCache::TokenArrayRef ScExternalRefManager::getDoubleRefTokens(
+@@ -1760,6 +1752,15 @@ ScExternalRefCache::TokenArrayRef ScExternalRefManager::getDoubleRefTokens(
+ 
+     maybeLinkExternalFile(nFileId);
+ 
++    ScRange aRange(rRange);
++    const ScDocument* pSrcDoc = getInMemorySrcDocument(nFileId);
++    if (pSrcDoc)
++    {
++        // Document already loaded.
++        vector<ScExternalRefCache::SingleRangeData> aCacheData;
++        return getDoubleRefTokensFromSrcDoc(pSrcDoc, rTabName, aRange, aCacheData);
++    }
++
+     // Check if the given table name and the cell position is cached.
+     ScExternalRefCache::TokenArrayRef pArray = 
+         maRefCache.getCellRangeData(nFileId, rTabName, rRange);
+@@ -1767,7 +1768,7 @@ ScExternalRefCache::TokenArrayRef ScExternalRefManager::getDoubleRefTokens(
+         // Cache hit !
+         return pArray;
+ 
+-    ScDocument* pSrcDoc = getSrcDocument(nFileId);
++    pSrcDoc = getSrcDocument(nFileId);
+     if (!pSrcDoc)
+     {
+         // Source document is not reachable.  Throw a reference error.
+@@ -1776,38 +1777,8 @@ ScExternalRefCache::TokenArrayRef ScExternalRefManager::getDoubleRefTokens(
+         return pArray;
+     }
+ 
+-    SCTAB nTab1;
+-    if (!pSrcDoc->GetTable(rTabName, nTab1))
+-    {
+-        // specified table name doesn't exist in the source document.
+-        pArray.reset(new ScTokenArray);
+-        pArray->AddToken(FormulaErrorToken(errNoRef));
+-        return pArray;
+-    }
+-
+-    ScRange aRange(rRange);
+-    SCTAB nTabSpan = aRange.aEnd.Tab() - aRange.aStart.Tab();
+-
+     vector<ScExternalRefCache::SingleRangeData> aCacheData;
+-    aCacheData.reserve(nTabSpan+1);
+-    aCacheData.push_back(ScExternalRefCache::SingleRangeData());
+-    aCacheData.back().maTableName = ScGlobal::pCharClass->upper(rTabName);
+-
+-    for (SCTAB i = 1; i < nTabSpan + 1; ++i)
+-    {
+-        String aTabName;
+-        if (!pSrcDoc->GetName(nTab1 + 1, aTabName))
+-            // source document doesn't have any table by the specified name.
+-            break;
+-
+-        aCacheData.push_back(ScExternalRefCache::SingleRangeData());
+-        aCacheData.back().maTableName = ScGlobal::pCharClass->upper(aTabName);
+-    }
+-
+-    aRange.aStart.SetTab(nTab1);
+-    aRange.aEnd.SetTab(nTab1 + nTabSpan);
+-
+-    pArray.reset(lcl_convertToTokenArray(pSrcDoc, aRange, aCacheData));
++    pArray = getDoubleRefTokensFromSrcDoc(pSrcDoc, rTabName, aRange, aCacheData);    
+ 
+     if (pArray)
+         // Cache these values.
+@@ -1836,14 +1807,159 @@ ScExternalRefCache::TokenArrayRef ScExternalRefManager::getRangeNameTokens(sal_u
+ 
+     maybeLinkExternalFile(nFileId);
+ 
++    String aName = rName; // make a copy to have the casing corrected.
++    const ScDocument* pSrcDoc = getInMemorySrcDocument(nFileId);
++    if (pSrcDoc)
++    {
++        // Document already loaded in memory.
++        return getRangeNameTokensFromSrcDoc(nFileId, pSrcDoc, aName);
++    }
++
+     ScExternalRefCache::TokenArrayRef pArray = maRefCache.getRangeNameTokens(nFileId, rName);
+     if (pArray.get())
++        // This range name is cached.
+         return pArray;
+ 
+-    ScDocument* pSrcDoc = getSrcDocument(nFileId);
++    pSrcDoc = getSrcDocument(nFileId);
+     if (!pSrcDoc)
++        // failed to load document from disk.
+         return ScExternalRefCache::TokenArrayRef();
+ 
++    pArray = getRangeNameTokensFromSrcDoc(nFileId, pSrcDoc, aName);
++
++    if (pArray)
++        // Cache this range name array.
++        maRefCache.setRangeNameTokens(nFileId, aName, pArray);
++
++    return pArray;
++}
++
++void ScExternalRefManager::refreshAllRefCells(sal_uInt16 nFileId)
++{
++    RefCellMap::iterator itrFile = maRefCells.find(nFileId);
++    if (itrFile == maRefCells.end())
++        return;
++
++    RefCellSet& rRefCells = itrFile->second;
++    for_each(rRefCells.begin(), rRefCells.end(), UpdateFormulaCell());
++
++    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_REPAINT);
++    pVShell->PaintGrid();
++}
++
++void ScExternalRefManager::insertRefCell(sal_uInt16 nFileId, const ScAddress& rCell)
++{
++    RefCellMap::iterator itr = maRefCells.find(nFileId);
++    if (itr == maRefCells.end())
++    {
++        RefCellSet aRefCells;
++        pair<RefCellMap::iterator, bool> r = maRefCells.insert(
++            RefCellMap::value_type(nFileId, aRefCells));
++        if (!r.second)
++            // insertion failed.
++            return;
++
++        itr = r.first;
++    }
++
++    ScBaseCell* pCell = mpDoc->GetCell(rCell);
++    if (pCell && pCell->GetCellType() == CELLTYPE_FORMULA)
++        itr->second.insert(static_cast<ScFormulaCell*>(pCell));
++}
++
++void ScExternalRefManager::fillCellFormat(sal_uInt32 nFmtIndex, ScExternalRefCache::CellFormat* pFmt) const
++{
++    if (!pFmt)
++        return;
++
++    short nFmtType = mpDoc->GetFormatTable()->GetType(nFmtIndex);
++    if (nFmtType != NUMBERFORMAT_UNDEFINED)
++    {
++        pFmt->mbIsSet = true;
++        pFmt->mnIndex = nFmtIndex;
++        pFmt->mnType = nFmtType;
++    }
++}
++
++ScExternalRefCache::TokenRef ScExternalRefManager::getSingleRefTokenFromSrcDoc(
++    sal_uInt16 nFileId, const ScDocument* pSrcDoc, const ScAddress& rCell, 
++    ScExternalRefCache::CellFormat* pFmt)
++{
++    // Get the cell from src doc, and convert it into a token.
++    ScBaseCell* pCell = NULL;
++    pSrcDoc->GetCell(rCell.Col(), rCell.Row(), rCell.Tab(), pCell);
++    ScExternalRefCache::TokenRef pToken(lcl_convertToToken(pCell));
++
++    if (!pToken.get())
++    {
++        // Generate an error for unresolvable cells.
++        pToken.reset( new FormulaErrorToken( errNoValue));
++    }
++
++    // Get number format information.
++    sal_uInt32 nFmtIndex = 0;
++    pSrcDoc->GetNumberFormat(rCell.Col(), rCell.Row(), rCell.Tab(), nFmtIndex);
++    nFmtIndex = getMappedNumberFormat(nFileId, nFmtIndex, pSrcDoc);
++    fillCellFormat(nFmtIndex, pFmt);
++    return pToken;
++}
++
++ScExternalRefCache::TokenArrayRef ScExternalRefManager::getDoubleRefTokensFromSrcDoc(
++    const ScDocument* pSrcDoc, const String& rTabName, ScRange& rRange,
++    vector<ScExternalRefCache::SingleRangeData>& rCacheData)
++{
++    ScExternalRefCache::TokenArrayRef pArray;
++    SCTAB nTab1;
++
++    if (!pSrcDoc->GetTable(rTabName, nTab1))
++    {
++        // specified table name doesn't exist in the source document.
++        pArray.reset(new ScTokenArray);
++        pArray->AddToken(FormulaErrorToken(errNoRef));
++        return pArray;
++    }
++
++    ScRange aRange(rRange);
++    SCTAB nTabSpan = aRange.aEnd.Tab() - aRange.aStart.Tab();
++
++    vector<ScExternalRefCache::SingleRangeData> aCacheData;
++    aCacheData.reserve(nTabSpan+1);
++    aCacheData.push_back(ScExternalRefCache::SingleRangeData());
++    aCacheData.back().maTableName = ScGlobal::pCharClass->upper(rTabName);
++
++    for (SCTAB i = 1; i < nTabSpan + 1; ++i)
++    {
++        String aTabName;
++        if (!pSrcDoc->GetName(nTab1 + 1, aTabName))
++            // source document doesn't have any table by the specified name.
++            break;
++
++        aCacheData.push_back(ScExternalRefCache::SingleRangeData());
++        aCacheData.back().maTableName = ScGlobal::pCharClass->upper(aTabName);
++    }
++
++    aRange.aStart.SetTab(nTab1);
++    aRange.aEnd.SetTab(nTab1 + nTabSpan);
++
++    pArray.reset(lcl_convertToTokenArray(pSrcDoc, aRange, aCacheData));
++    rRange = aRange;
++    rCacheData.swap(aCacheData);
++    return pArray;
++}
++
++ScExternalRefCache::TokenArrayRef ScExternalRefManager::getRangeNameTokensFromSrcDoc(
++    sal_uInt16 nFileId, const ScDocument* pSrcDoc, String& rName)
++{
+     ScRangeName* pExtNames = pSrcDoc->GetRangeName();
+     String aUpperName = ScGlobal::pCharClass->upper(rName);
+     USHORT n;
+@@ -1896,55 +2012,37 @@ ScExternalRefCache::TokenArrayRef ScExternalRefManager::getRangeNameTokens(sal_u
+             pNew->AddToken(*pToken);
+     }
+ 
+-    // Make sure to pass the correctly-cased range name here.
+-    maRefCache.setRangeNameTokens(nFileId, pRangeData->GetName(), pNew);
++    rName = pRangeData->GetName(); // Get the correctly-cased name.
+     return pNew;
+ }
+ 
+-void ScExternalRefManager::refreshAllRefCells(sal_uInt16 nFileId)
++const ScDocument* ScExternalRefManager::getInMemorySrcDocument(sal_uInt16 nFileId)
+ {
+-    RefCellMap::iterator itrFile = maRefCells.find(nFileId);
+-    if (itrFile == maRefCells.end())
+-        return;
+-
+-    RefCellSet& rRefCells = itrFile->second;
+-    for_each(rRefCells.begin(), rRefCells.end(), UpdateFormulaCell());
+-
+-    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_REPAINT);
+-    pVShell->PaintGrid();
+-}
++    const String* pFileName = getExternalFileName(nFileId);
++    if (!pFileName)
++        return NULL;
+ 
+-void ScExternalRefManager::insertRefCell(sal_uInt16 nFileId, const ScAddress& rCell)
+-{
+-    RefCellMap::iterator itr = maRefCells.find(nFileId);
+-    if (itr == maRefCells.end())
++    TypeId aType(TYPE(ScDocShell));
++    ScDocShell* pShell = static_cast<ScDocShell*>(SfxObjectShell::GetFirst(&aType, false));
++    while (pShell)
+     {
+-        RefCellSet aRefCells;
+-        pair<RefCellMap::iterator, bool> r = maRefCells.insert(
+-            RefCellMap::value_type(nFileId, aRefCells));
+-        if (!r.second)
+-            // insertion failed.
+-            return;
+-
+-        itr = r.first;
++        SfxMedium* pMedium = pShell->GetMedium();
++        if (pMedium)
++        {
++            String aName = pMedium->GetName();
++            // TODO: We should make the case sensitivity platform dependent.
++            if (pFileName->EqualsIgnoreCaseAscii(aName))
++            {
++                // Found !
++                return pShell->GetDocument();
++            }
++        }
++        pShell = static_cast<ScDocShell*>(SfxObjectShell::GetNext(*pShell, &aType, false));
+     }
+-
+-    ScBaseCell* pCell = mpDoc->GetCell(rCell);
+-    if (pCell && pCell->GetCellType() == CELLTYPE_FORMULA)
+-        itr->second.insert(static_cast<ScFormulaCell*>(pCell));
++    return NULL;
+ }
+ 
+-ScDocument* ScExternalRefManager::getSrcDocument(sal_uInt16 nFileId)
++const ScDocument* ScExternalRefManager::getSrcDocument(sal_uInt16 nFileId)
+ {
+     if (!mpDoc->IsExecuteLinkEnabled())
+         return NULL;
+@@ -2414,7 +2512,7 @@ void ScExternalRefManager::purgeStaleSrcDocument(sal_Int32 nTimeOut)
+         maSrcDocTimer.Stop();
+ }
+ 
+-sal_uInt32 ScExternalRefManager::getMappedNumberFormat(sal_uInt16 nFileId, sal_uInt32 nNumFmt, ScDocument* pSrcDoc)
++sal_uInt32 ScExternalRefManager::getMappedNumberFormat(sal_uInt16 nFileId, sal_uInt32 nNumFmt, const ScDocument* pSrcDoc)
+ {
+     NumFmtMap::iterator itr = maNumFormatMap.find(nFileId);
+     if (itr == maNumFormatMap.end())
commit d3af2fd2d518b480f8f825f718bb8cbf5e87b214
Author: Kohei Yoshida <kyoshida at novell.com>
Date:   Mon Aug 16 11:54:34 2010 -0400

    Re-ported the DDE reconnect patch from ooo-build-3-2-1.
    
    The initial fix was not sufficient to cover all use cases.
    
    With this change, those documents that are loaded hidden get closed
    immediately after the DDE update is done, in order to avoid subsequent
    problem of loading them after the link is updated.
    
    * patches/dev300/apply:
    * patches/dev300/dde-reconnect-on-load-cui.diff:
    * patches/dev300/dde-reconnect-on-load-sc.diff:
    * patches/dev300/dde-reconnect-on-load-sfx2.diff:
    * patches/dev300/dde-reconnect-on-load-sw.diff:

diff --git a/patches/dev300/apply b/patches/dev300/apply
index ee708ee..ab59e68 100644
--- a/patches/dev300/apply
+++ b/patches/dev300/apply
@@ -3483,6 +3483,7 @@ calc-xls-import-biff2-file-sheet-name.diff, n#612902, kohei
 dde-reconnect-on-load-sc.diff,   n#618846, n#618864, kohei
 dde-reconnect-on-load-sw.diff,   n#618846, n#618864, kohei
 dde-reconnect-on-load-sfx2.diff, n#618846, n#618864, kohei
+dde-reconnect-on-load-cui.diff,  n#618846, n#618864, kohei
 
 # Properly display data field names in the data field options dialog.
 calc-dp-sort-fix.diff, n#629920, kohei
diff --git a/patches/dev300/dde-reconnect-on-load-cui.diff b/patches/dev300/dde-reconnect-on-load-cui.diff
new file mode 100644
index 0000000..2507465
--- /dev/null
+++ b/patches/dev300/dde-reconnect-on-load-cui.diff
@@ -0,0 +1,13 @@
+diff --git cui/source/dialogs/linkdlg.cxx cui/source/dialogs/linkdlg.cxx
+index 965aefe..a689d85 100644
+--- cui/source/dialogs/linkdlg.cxx
++++ cui/source/dialogs/linkdlg.cxx
+@@ -330,6 +330,8 @@ IMPL_LINK( SvBaseLinksDlg, UpdateNowClickHdl, PushButton *, EMPTYARG )
+             rListBox.Select( pE );
+             rListBox.MakeVisible( pE );
+         }
++
++        pNewMgr->CloseCachedComps();
+     }
+     return 0;
+ }
diff --git a/patches/dev300/dde-reconnect-on-load-sc.diff b/patches/dev300/dde-reconnect-on-load-sc.diff
index 8375926..83d0add 100644
--- a/patches/dev300/dde-reconnect-on-load-sc.diff
+++ b/patches/dev300/dde-reconnect-on-load-sc.diff
@@ -1,3 +1,35 @@
+diff --git sc/source/core/data/documen8.cxx sc/source/core/data/documen8.cxx
+index 1daa520..b210025 100644
+--- sc/source/core/data/documen8.cxx
++++ sc/source/core/data/documen8.cxx
+@@ -1097,6 +1097,7 @@ void ScDocument::UpdateDdeLinks()
+             if (pBase->ISA(ScDdeLink))
+                 ((ScDdeLink*)pBase)->TryUpdate();       // bei DDE-Links TryUpdate statt Update
+         }
++        pLinkManager->CloseCachedComps();
+     }
+ }
+ 
+@@ -1126,6 +1127,7 @@ BOOL ScDocument::UpdateDdeLink( const String& rAppl, const String& rTopic, const
+                 }
+             }
+         }
++        pLinkManager->CloseCachedComps();
+     }
+     return bFound;
+ }
+diff --git sc/source/core/tool/interpr2.cxx sc/source/core/tool/interpr2.cxx
+index 09b6408..b560f93 100644
+--- sc/source/core/tool/interpr2.cxx
++++ sc/source/core/tool/interpr2.cxx
+@@ -2218,6 +2218,7 @@ void ScInterpreter::ScDde()
+             PushNA();
+ 
+         pDok->DisableIdle( bOldDis );
++        pLinkMgr->CloseCachedComps();
+     }
+ }
+ 
 diff --git sc/source/ui/docshell/docsh6.cxx sc/source/ui/docshell/docsh6.cxx
 index bb7b82f..8d9a9f0 100644
 --- sc/source/ui/docshell/docsh6.cxx
@@ -8,7 +40,7 @@ index bb7b82f..8d9a9f0 100644
  
 +void ScDocShell::ReconnectDdeLink(SfxObjectShell& rServer)
 +{
-+    ::sfx2::LinkManager* pLinkManager = aDocument.GetLinkManager();
++    SvxLinkManager* pLinkManager = aDocument.GetLinkManager();
 +    if (!pLinkManager)
 +        return;
 +
@@ -48,10 +80,10 @@ index 1d69e26..4790d68 100644
              // cell reference
              aRange.aEnd = aRange.aStart;
 diff --git sc/source/ui/inc/docsh.hxx sc/source/ui/inc/docsh.hxx
-index 6bfaf40..07d8c3f 100755
+index d9d3629..7df6e9f 100755
 --- sc/source/ui/inc/docsh.hxx
 +++ sc/source/ui/inc/docsh.hxx
-@@ -319,6 +319,7 @@ public:
+@@ -324,6 +324,7 @@ public:
      ScDBData*       GetOldAutoDBRange();    // has to be deleted by caller!
      void            CancelAutoDBRange();    // called when dialog is cancelled
  
diff --git a/patches/dev300/dde-reconnect-on-load-sfx2.diff b/patches/dev300/dde-reconnect-on-load-sfx2.diff
index bdfe0d9..ca6ec7e 100644
--- a/patches/dev300/dde-reconnect-on-load-sfx2.diff
+++ b/patches/dev300/dde-reconnect-on-load-sfx2.diff
@@ -1,21 +1,87 @@
 diff --git sfx2/inc/sfx2/linkmgr.hxx sfx2/inc/sfx2/linkmgr.hxx
-index 6ff4e26..941321a 100644
+index 6ff4e26..8bdcad9 100644
 --- sfx2/inc/sfx2/linkmgr.hxx
 +++ sfx2/inc/sfx2/linkmgr.hxx
-@@ -90,6 +90,8 @@ public:
-                 // falls am Link schon alles eingestellt ist !
-     BOOL 		InsertDDELink( SvBaseLink* );
+@@ -33,10 +33,18 @@
+ #include <tools/string.hxx>
+ #include <svl/svarray.hxx>
  
-+    void        ReconnectDdeLink(SfxObjectShell& rServer);
++#include <vector>
 +
-     // den Link mit einem PseudoObject verbinden und in die Liste eintragen
-     BOOL InsertFileLink( sfx2::SvBaseLink&,
-                         USHORT nFileType,
+ class SfxObjectShell;
+ class Graphic;
+ class Size;
+ 
++namespace com { namespace sun { namespace star {
++    namespace lang {
++        class XComponent;
++    }
++}}}
++
+ namespace sfx2
+ {
+     // Damit der Link ueber den Status der zu ladenen Grafik informierten werden
+@@ -55,6 +63,10 @@ SV_DECL_PTRARR( SvLinkSources, SvLinkSourcePtr, 1, 1 )
+ 
+ class SFX2_DLLPUBLIC LinkManager
+ {
++    typedef ::std::vector< ::com::sun::star::uno::Reference< ::com::sun::star::lang::XComponent > >
++        CompVector;
++    CompVector maCachedComps;
++
+     SvBaseLinks		aLinkTbl;
+     SvLinkSources aServerTbl;
+ 
+@@ -74,6 +86,16 @@ public:
+                 LinkManager( SfxObjectShell * pCacheCont );
+                 ~LinkManager();
+ 
++    /**
++     * Insert a component loaded during link update, which needs to be closed 
++     * when the update is complete. 
++     * 
++     * @param xComp component loaded during link update.
++     */
++    void        InsertCachedComp(const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XComponent >& xComp);
++
++    void        CloseCachedComps();
++
+     SfxObjectShell*    GetPersist() const              { return pPersist; }
+     void        SetPersist( SfxObjectShell * p )   { pPersist = p; }
+ 
+@@ -100,6 +122,17 @@ public:
+             // falls am Link schon alles eingestellt ist !
+     BOOL InsertFileLink( sfx2::SvBaseLink& );
+ 
++    void ReconnectDdeLink(SfxObjectShell& rServer);
++
++    /**
++     * Reconnect the server document shell to a DDE link object.
++     * 
++     * @param rPath path to the server document
++     * @param rServer server document shell instance
++     * @param rLink link object of the client document
++     */
++    void LinkServerShell(const ::rtl::OUString& rPath, SfxObjectShell& rServer, ::sfx2::SvBaseLink& rLink) const;
++
+                 // erfrage die Strings fuer den Dialog
+     BOOL GetDisplayNames( const SvBaseLink *,
+                                     String* pType,
 diff --git sfx2/inc/sfx2/objsh.hxx sfx2/inc/sfx2/objsh.hxx
-index 9c6259b..a0ad22a 100755
+index 5215f94..7337da9 100755
 --- sfx2/inc/sfx2/objsh.hxx
 +++ sfx2/inc/sfx2/objsh.hxx
-@@ -520,6 +520,9 @@ public:
+@@ -127,6 +127,9 @@ namespace com { namespace sun { namespace star {
+     namespace document {
+         class XDocumentProperties;
+     }
++    namespace lang {
++        class XComponent;
++    }
+ } } }
+ 
+ typedef sal_uInt32 SfxObjectShellFlags;
+@@ -522,6 +525,9 @@ public:
                                              const String& rMimeType,
                                  const ::com::sun::star::uno::Any & rValue );
      virtual ::sfx2::SvLinkSource* 		DdeCreateLinkSource( const String& rItem );
@@ -25,6 +91,28 @@ index 9c6259b..a0ad22a 100755
  
      // Contents
      virtual SfxStyleSheetBasePool*	GetStyleSheetPool();
+@@ -629,6 +635,9 @@ public:
+     static SfxObjectShell*		CreateObject( const String& rServiceName, SfxObjectCreateMode = SFX_CREATE_MODE_STANDARD );
+     static SfxObjectShell*		CreateObjectByFactoryName( const String& rURL, SfxObjectCreateMode = SFX_CREATE_MODE_STANDARD );
+     static SfxObjectShell*      CreateAndLoadObject( const SfxItemSet& rSet, SfxFrame* pFrame=0 );
++    static ::com::sun::star::uno::Reference< ::com::sun::star::lang::XComponent >
++                                CreateAndLoadComponent( const SfxItemSet& rSet, SfxFrame* pFrame = NULL );
++    static SfxObjectShell*      GetShellFromComponent( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XComponent >& xComp );
+     static String				GetServiceNameFromFactory( const String& rFact );
+     BOOL						IsInPlaceActive();
+     BOOL						IsUIActive();
+diff --git sfx2/inc/sfx2/sfxsids.hrc sfx2/inc/sfx2/sfxsids.hrc
+index bf1cebb..a2f8d88 100644
+--- sfx2/inc/sfx2/sfxsids.hrc
++++ sfx2/inc/sfx2/sfxsids.hrc
+@@ -367,6 +367,7 @@
+ #define SID_OPENCOPY                        (SID_SFX_START + 674)
+ #define SID_SOURCEVIEW                      (SID_SFX_START + 675)
+ #define SID_DOC_STARTPRESENTATION           (SID_SFX_START + 695)
++#define SID_DDE_RECONNECT_ONLOAD            (SID_SFX_START + 696)
+ 
+ #define SID_PLUGFRAMEARG                    (SID_SFX_START + 666)
+ #define SID_NEWWINDOWFOREDIT                (SID_SFX_START + 667)
 diff --git sfx2/source/appl/appdde.cxx sfx2/source/appl/appdde.cxx
 index 789de8b..6134d9d 100644
 --- sfx2/source/appl/appdde.cxx
@@ -53,22 +141,110 @@ index 789de8b..6134d9d 100644
  //========================================================================
  
  long SfxViewFrame::DdeExecute
+diff --git sfx2/source/appl/appuno.cxx sfx2/source/appl/appuno.cxx
+index 091ffb8..bffd379 100755
+--- sfx2/source/appl/appuno.cxx
++++ sfx2/source/appl/appuno.cxx
+@@ -151,6 +151,7 @@ static char const sOpenNewView[] = "OpenNewView";
+ static char const sViewId[] = "ViewId";
+ static char const sPluginMode[] = "PluginMode";
+ static char const sReadOnly[] = "ReadOnly";
++static char const sDdeReconnect = "DDEReconnect";
+ static char const sStartPresentation[] = "StartPresentation";
+ static char const sFrameName[] = "FrameName";
+ static char const sMediaType[] = "MediaType";
+@@ -610,6 +611,14 @@ void TransformParameters( sal_uInt16 nSlotId, const ::com::sun::star::uno::Seque
+                     if (bOK)
+                         rSet.Put( SfxBoolItem( SID_DOC_READONLY, bVal ) );
+                 }
++                else if ( aName.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM(sDdeReconnect)) )
++                {
++                    sal_Bool bVal = sal_True;
++                    sal_Bool bOK = (rProp.Value >>= bVal);
++                    DBG_ASSERT( bOK, "invalid type for DDEReconnect" );
++                    if (bOK)
++                        rSet.Put( SfxBoolItem( SID_DDE_RECONNECT_ONLOAD, bVal ) );
++                }
+                 else if ( aName.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM(sStartPresentation)) )
+                 {
+                     sal_Bool bVal = sal_False;
+@@ -1009,6 +1018,8 @@ void TransformItems( sal_uInt16 nSlotId, const SfxItemSet& rSet, ::com::sun::sta
+                 nAdditional++;
+             if ( rSet.GetItemState( SID_DOC_READONLY ) == SFX_ITEM_SET )
+                 nAdditional++;
++            if ( rSet.GetItemState( SID_DDE_RECONNECT_ONLOAD ) == SFX_ITEM_SET )
++                nAdditional++;
+             if ( rSet.GetItemState( SID_DOC_STARTPRESENTATION ) == SFX_ITEM_SET )
+                 nAdditional++;
+             if ( rSet.GetItemState( SID_SELECTION ) == SFX_ITEM_SET )
+@@ -1425,6 +1436,11 @@ void TransformItems( sal_uInt16 nSlotId, const SfxItemSet& rSet, ::com::sun::sta
+                 pValue[nActProp].Name = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(sReadOnly));
+                 pValue[nActProp++].Value <<= ( ((SfxBoolItem*)pItem)->GetValue() );
+             }
++            if ( rSet.GetItemState( SID_DDE_RECONNECT_ONLOAD, sal_False, &pItem ) == SFX_ITEM_SET )
++            {
++                pValue[nActProp].Name = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(sDdeReconnect));
++                pValue[nActProp++].Value <<= ( ((SfxBoolItem*)pItem)->GetValue() );
++            }
+             if ( rSet.GetItemState( SID_DOC_STARTPRESENTATION, sal_False, &pItem ) == SFX_ITEM_SET )
+             {
+                 pValue[nActProp].Name = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(sStartPresentation));
 diff --git sfx2/source/appl/linkmgr2.cxx sfx2/source/appl/linkmgr2.cxx
-index 7653637..758f5e0 100644
+index 7653637..9011c39 100644
 --- sfx2/source/appl/linkmgr2.cxx
 +++ sfx2/source/appl/linkmgr2.cxx
-@@ -55,6 +55,9 @@
+@@ -55,6 +55,16 @@
  #define _SVSTDARR_STRINGSDTOR
  #include <svl/svstdarr.hxx>
  
++#include <com/sun/star/lang/XComponent.hpp>
++#include <com/sun/star/util/XCloseable.hpp>
++
++using ::com::sun::star::uno::UNO_QUERY;
++using ::com::sun::star::uno::Reference;
++using ::com::sun::star::lang::XComponent;
++using ::com::sun::star::util::XCloseable;
 +using ::rtl::OUString;
 +using ::rtl::OUStringBuffer;
 +
  namespace sfx2
  {
  
-@@ -209,6 +212,50 @@ BOOL LinkManager::InsertDDELink( SvBaseLink * pLink )
-     return Insert( pLink );
+@@ -89,6 +99,24 @@ LinkManager::~LinkManager()
+     }
+ }
+ 
++void LinkManager::InsertCachedComp(const Reference<XComponent>& xComp)
++{
++    maCachedComps.push_back(xComp);
++}
++
++void LinkManager::CloseCachedComps()
++{
++    CompVector::iterator itr = maCachedComps.begin(), itrEnd = maCachedComps.end();
++    for (; itr != itrEnd; ++itr)
++    {
++        Reference<XCloseable> xCloseable(*itr, UNO_QUERY);
++        if (!xCloseable.is())
++            continue;
++
++        xCloseable->close(true);
++    }
++    maCachedComps.clear();
++}
+ 
+ /************************************************************************
+ |*    LinkManager::Remove()
+@@ -329,6 +357,7 @@ void LinkManager::UpdateAllLinks(
+ 
+         pLink->Update();
+     }
++    CloseCachedComps();
+ }
+ 
+ /************************************************************************
+@@ -387,6 +416,56 @@ void MakeLnkName( String& rName, const String* pType, const String& rFile,
+         ((rName += cTokenSeperator ) += *pFilter).EraseLeadingChars().EraseTrailingChars();
  }
  
 +void LinkManager::ReconnectDdeLink(SfxObjectShell& rServer)
@@ -92,8 +268,9 @@ index 7653637..758f5e0 100644
 +            continue;
 +
 +        String aTmp;
-+        utl::LocalFileHelper::ConvertPhysicalNameToURL(aFile, aTmp);
-+        OUString aURL = aTmp;
++        OUString aURL = aFile;
++        if (utl::LocalFileHelper::ConvertPhysicalNameToURL(aFile, aTmp))
++            aURL = aTmp;
 +
 +        if (!aURL.equalsIgnoreAsciiCase(pMed->GetName()))
 +            // This DDE link is not associated with this server shell...  Skip it.
@@ -102,23 +279,49 @@ index 7653637..758f5e0 100644
 +        if (!aLink.Len())
 +            continue;
 +
-+        // Reconnect the server document shell to this DDE link object.
-+        ::sfx2::SvLinkSource* pSrvSrc = rServer.DdeCreateLinkSource(aLink);
-+        if (pSrvSrc)
-+        {
-+            ::com::sun::star::datatransfer::DataFlavor aFl;
-+            SotExchange::GetFormatDataFlavor(p->GetContentType(), aFl);
-+            p->SetObj(pSrvSrc);
-+            pSrvSrc->AddDataAdvise(
-+                p, aFl.MimeType,
-+                sfx2::LINKUPDATE_ONCALL == p->GetUpdateMode() ? ADVISEMODE_ONLYONCE : 0);
-+        }
++        LinkServerShell(aLink, rServer, *p);
++    }
++}
++
++void LinkManager::LinkServerShell(const OUString& rPath, SfxObjectShell& rServer, ::sfx2::SvBaseLink& rLink) const
++{
++    ::sfx2::SvLinkSource* pSrvSrc = rServer.DdeCreateLinkSource(rPath);
++    if (pSrvSrc)
++    {
++        ::com::sun::star::datatransfer::DataFlavor aFl;
++        SotExchange::GetFormatDataFlavor(rLink.GetContentType(), aFl);
++        rLink.SetObj(pSrvSrc);
++        pSrvSrc->AddDataAdvise(
++            &rLink, aFl.MimeType,
++            sfx2::LINKUPDATE_ONCALL == rLink.GetUpdateMode() ? ADVISEMODE_ONLYONCE : 0);
 +    }
 +}
++
+ BOOL LinkManager::InsertFileLink( sfx2::SvBaseLink& rLink,
+                                     USHORT nFileType,
+                                     const String& rFileNm,
+@@ -511,9 +590,8 @@ BOOL SvxInternalLink::Connect( sfx2::SvBaseLink* pLink )
+     SfxObjectShell* pFndShell = 0;
+     USHORT nUpdateMode = com::sun::star::document::UpdateDocMode::NO_UPDATE;
+     String sTopic, sItem, sReferer;
+-    if( pLink->GetLinkManager() &&
+-        pLink->GetLinkManager()->GetDisplayNames( pLink, 0, &sTopic, &sItem )
+-        && sTopic.Len() )
++    LinkManager* pLinkMgr = pLink->GetLinkManager();
++    if (pLinkMgr && pLinkMgr->GetDisplayNames(pLink, 0, &sTopic, &sItem) && sTopic.Len())
+     {
+         // erstmal nur ueber die DocumentShells laufen und die mit dem
+         // Namen heraussuchen:
+@@ -528,7 +606,7 @@ BOOL SvxInternalLink::Connect( sfx2::SvBaseLink* pLink )
+         TypeId aType( TYPE(SfxObjectShell) );
  
- // erfrage die Strings fuer den Dialog
- BOOL LinkManager::GetDisplayNames( const SvBaseLink * pLink,
-@@ -578,7 +625,23 @@ BOOL SvxInternalLink::Connect( sfx2::SvBaseLink* pLink )
+         BOOL bFirst = TRUE;
+-        SfxObjectShell* pShell = pLink->GetLinkManager()->GetPersist();
++        SfxObjectShell* pShell = pLinkMgr->GetPersist();
+         if( pShell && pShell->GetMedium() )
+         {
+             sReferer = pShell->GetMedium()->GetBaseURL();
+@@ -578,7 +656,23 @@ BOOL SvxInternalLink::Connect( sfx2::SvBaseLink* pLink )
      if( !sTopic.Len() )
          return FALSE;
  
@@ -143,21 +346,35 @@ index 7653637..758f5e0 100644
      {
          // dann versuche die Datei zu laden:
          INetURLObject aURL( sTopic );
-@@ -593,7 +656,7 @@ BOOL SvxInternalLink::Connect( sfx2::SvBaseLink* pLink )
+@@ -593,7 +687,11 @@ BOOL SvxInternalLink::Connect( sfx2::SvBaseLink* pLink )
              SfxStringItem aTarget( SID_TARGETNAME, String::CreateFromAscii("_blank") );
              SfxStringItem aReferer( SID_REFERER, sReferer );
              SfxUInt16Item aUpdate( SID_UPDATEDOCMODE, nUpdateMode );
 -            SfxBoolItem aReadOnly(SID_DOC_READONLY, TRUE);
 +            SfxBoolItem aReadOnly(SID_DOC_READONLY, false);
++
++            // Disable automatic re-connection to avoid this link instance 
++            // being destroyed at re-connection.
++            SfxBoolItem aDdeConnect(SID_DDE_RECONNECT_ONLOAD, false);
  
              // #i14200# (DDE-link crashes wordprocessor)
              SfxAllItemSet aArgs( SFX_APP()->GetPool() );
-@@ -605,28 +668,13 @@ BOOL SvxInternalLink::Connect( sfx2::SvBaseLink* pLink )
+@@ -604,29 +702,19 @@ BOOL SvxInternalLink::Connect( sfx2::SvBaseLink* pLink )
+             aArgs.Put(aName);
              aArgs.Put(aUpdate);
              aArgs.Put(aReadOnly);
-             pFndShell = SfxObjectShell::CreateAndLoadObject( aArgs );
--        }
--    }
+-            pFndShell = SfxObjectShell::CreateAndLoadObject( aArgs );
++            aArgs.Put(aDdeConnect);
++            Reference<XComponent> xComp = SfxObjectShell::CreateAndLoadComponent(aArgs);
++            pFndShell = SfxObjectShell::GetShellFromComponent(xComp);
++            if (xComp.is() && pFndShell)
++            {
++                pLinkMgr->InsertCachedComp(xComp);
++                pLinkMgr->LinkServerShell(sItem, *pFndShell, *pLink);
++                return true;
++            }
+         }
+     }
  
 -    BOOL bRet = FALSE;
 -    if( pFndShell )
@@ -175,26 +392,87 @@ index 7653637..758f5e0 100644
 -                                sfx2::LINKUPDATE_ONCALL == pLink->GetUpdateMode()
 -                                    ? ADVISEMODE_ONLYONCE
 -                                    : 0 );
-+            // When loading a new document, DDE links get connected during the loading.
-+            return true;
-         }
-     }
+-        }
+-    }
 -    return bRet;
-+
 +    return false;
  }
  
  
 diff --git sfx2/source/doc/objstor.cxx sfx2/source/doc/objstor.cxx
-index 474b4a0..1053023 100644
+index 474b4a0..7f3349d 100644
 --- sfx2/source/doc/objstor.cxx
 +++ sfx2/source/doc/objstor.cxx
-@@ -974,6 +974,8 @@ sal_Bool SfxObjectShell::DoLoad( SfxMedium *pMed )
+@@ -974,6 +974,16 @@ sal_Bool SfxObjectShell::DoLoad( SfxMedium *pMed )
              }
          }
  
-+        ReconnectDdeLinks(*this);
++        const SfxBoolItem* pDdeReconnectItem = static_cast<const SfxBoolItem*>(
++            SfxRequest::GetItem(pMedium->GetItemSet(), SID_DDE_RECONNECT_ONLOAD, false, TYPE(SfxBoolItem)));
++
++        bool bReconnectDde = true; // by default, we try to auto-connect DDE connections.
++        if (pDdeReconnectItem)
++            bReconnectDde = pDdeReconnectItem->GetValue();
++
++        if (bReconnectDde)
++            ReconnectDdeLinks(*this);
 +
  #if 0
          if ( pMedium->HasStorage_Impl() )
          {
+diff --git sfx2/source/doc/objxtor.cxx sfx2/source/doc/objxtor.cxx
+index 20d40e0..53af620 100755
+--- sfx2/source/doc/objxtor.cxx
++++ sfx2/source/doc/objxtor.cxx
+@@ -1079,6 +1079,12 @@ SfxObjectShell* SfxObjectShell::CreateObject( const String& rServiceName, SfxObj
+ 
+ SfxObjectShell* SfxObjectShell::CreateAndLoadObject( const SfxItemSet& rSet, SfxFrame* pFrame )
+ {
++    Reference<lang::XComponent> xComp = CreateAndLoadComponent(rSet, pFrame);
++    return GetShellFromComponent(xComp);
++}
++
++Reference<lang::XComponent> SfxObjectShell::CreateAndLoadComponent( const SfxItemSet& rSet, SfxFrame* pFrame )
++{
+     uno::Sequence < beans::PropertyValue > aProps;
+     TransformItems( SID_OPENDOC, rSet, aProps );
+     SFX_ITEMSET_ARG(&rSet, pFileNameItem, SfxStringItem, SID_FILE_NAME, FALSE);
+@@ -1099,20 +1105,31 @@ SfxObjectShell* SfxObjectShell::CreateAndLoadObject( const SfxItemSet& rSet, Sfx
+         xLoader = uno::Reference < frame::XComponentLoader >( comphelper::getProcessServiceFactory()->createInstance(
+             ::rtl::OUString::createFromAscii("com.sun.star.frame.Desktop") ), uno::UNO_QUERY );
+ 
+-    uno::Reference < lang::XUnoTunnel > xObj;
++    Reference <lang::XComponent> xComp;
+     try
+     {
+-        xObj = uno::Reference< lang::XUnoTunnel >( xLoader->loadComponentFromURL( aURL, aTarget, 0, aProps ), uno::UNO_QUERY );
++        xComp = xLoader->loadComponentFromURL(aURL, aTarget, 0, aProps);
+     }
+     catch( uno::Exception& )
+     {}
+ 
+-    if ( xObj.is() )
++    return xComp;
++}
++
++SfxObjectShell* SfxObjectShell::GetShellFromComponent( const Reference<lang::XComponent>& xComp )
++{
++    try
++    {
++        Reference<lang::XUnoTunnel> xTunnel(xComp, UNO_QUERY_THROW);
++        Sequence <sal_Int8> aSeq( SvGlobalName( SFX_GLOBAL_CLASSID ).GetByteSequence() );
++        sal_Int64 nHandle = xTunnel->getSomething( aSeq );
++        if (!nHandle)
++            return NULL;
++
++        return reinterpret_cast< SfxObjectShell* >(sal::static_int_cast< sal_IntPtr >(  nHandle ));
++    }
++    catch (const Exception&)
+     {
+-        ::com::sun::star::uno::Sequence < sal_Int8 > aSeq( SvGlobalName( SFX_GLOBAL_CLASSID ).GetByteSequence() );
+-        sal_Int64 nHandle = xObj->getSomething( aSeq );
+-        if ( nHandle )
+-            return reinterpret_cast< SfxObjectShell* >(sal::static_int_cast< sal_IntPtr >(  nHandle ));
+     }
+ 
+     return NULL;
diff --git a/patches/dev300/dde-reconnect-on-load-sw.diff b/patches/dev300/dde-reconnect-on-load-sw.diff
index ee386ce..443e0f8 100644
--- a/patches/dev300/dde-reconnect-on-load-sw.diff
+++ b/patches/dev300/dde-reconnect-on-load-sw.diff
@@ -1,8 +1,8 @@
 diff --git sw/inc/docsh.hxx sw/inc/docsh.hxx
-index 3840d59..9abc65e 100644
+index 6c2fd87..7a47dc2 100644
 --- sw/inc/docsh.hxx
 +++ sw/inc/docsh.hxx
-@@ -237,6 +237,8 @@ public:
+@@ -238,6 +238,8 @@ public:
      virtual long DdeSetData( const String& rItem, const String& rMimeType,
                                  const ::com::sun::star::uno::Any & rValue );
      virtual ::sfx2::SvLinkSource* DdeCreateLinkSource( const String& rItem );
@@ -12,24 +12,24 @@ index 3840d59..9abc65e 100644
                                     sal_uInt32 * pClipFormat,
                                     String * pAppName,
 diff --git sw/source/ui/app/docsh2.cxx sw/source/ui/app/docsh2.cxx
-index cea9d74..5a4a07d 100644
+index aa59379..3022ba2 100644
 --- sw/source/ui/app/docsh2.cxx
 +++ sw/source/ui/app/docsh2.cxx
 @@ -64,6 +64,7 @@
  #include <editeng/svxacorr.hxx>
  #include <editeng/langitem.hxx>
  #include <svx/fmshell.hxx>
-+#include <sfx2/linkmgr.hxx>
++#include <svx/linkmgr.hxx>
  
  #include <svtools/htmlcfg.hxx>
  #include <svx/ofaitem.hxx>
-@@ -1523,6 +1524,12 @@ long SwDocShell::DdeSetData( const String& rItem, const String& rMimeType,
+@@ -1564,6 +1565,12 @@ long SwDocShell::DdeSetData( const String& rItem, const String& rMimeType,
      return pDoc->CreateLinkSource( rItem );
  }
  

... etc. - the rest is truncated


More information about the ooo-build-commit mailing list