[PATCH] fdo#36933: Fixed array comparison with external references.

Kohei Yoshida kyoshida at novell.com
Mon May 9 19:54:59 PDT 2011


---
 sc/source/core/inc/interpre.hxx  |    1 +
 sc/source/core/tool/interpr1.cxx |   32 +++++++++++++++++
 sc/source/core/tool/interpr4.cxx |   71 +++++++++++++++++++++++++++++--------
 3 files changed, 88 insertions(+), 16 deletions(-)

diff --git a/sc/source/core/inc/interpre.hxx b/sc/source/core/inc/interpre.hxx
index ce59c16..7caee75 100644
--- a/sc/source/core/inc/interpre.hxx
+++ b/sc/source/core/inc/interpre.hxx
@@ -316,6 +316,7 @@ void PopExternalSingleRef(ScExternalRefCache::TokenRef& rToken, ScExternalRefCac
 void PopExternalDoubleRef(sal_uInt16& rFileId, String& rTabName, ScComplexRefData& rRef);
 void PopExternalDoubleRef(ScExternalRefCache::TokenArrayRef& rArray);
 void PopExternalDoubleRef(ScMatrixRef& rMat);
+void GetExternalDoubleRef(sal_uInt16 nFileId, const String& rTabName, const ScComplexRefData& aData, ScExternalRefCache::TokenArrayRef& rArray);
 sal_Bool PopDoubleRefOrSingleRef( ScAddress& rAdr );
 void PopDoubleRefPushMatrix();
 // If MatrixFormula: convert formula::svDoubleRef to svMatrix, create JumpMatrix.
diff --git a/sc/source/core/tool/interpr1.cxx b/sc/source/core/tool/interpr1.cxx
index 8beb6f1..1999bff 100644
--- a/sc/source/core/tool/interpr1.cxx
+++ b/sc/source/core/tool/interpr1.cxx
@@ -810,6 +810,38 @@ double ScInterpreter::Compare()
                 }
             }
             break;
+            case svExternalSingleRef:
+            {
+                ScMatrixRef pMat = GetMatrix();
+                if (!pMat)
+                {
+                    SetError( errIllegalParameter);
+                    break;
+                }
+
+                SCSIZE nC, nR;
+                pMat->GetDimensions(nC, nR);
+                if (!nC || !nR)
+                {
+                    SetError( errIllegalParameter);
+                    break;
+                }
+                if (pMat->IsEmpty(0, 0))
+                    aComp.bEmpty[i] = true;
+                else if (pMat->IsString(0, 0))
+                {
+                    *aComp.pVal[i] = pMat->GetString(0, 0);
+                    aComp.bVal[i] = false;
+                }
+                else
+                {
+                    aComp.nVal[i] = pMat->GetDouble(0, 0);
+                    aComp.bVal[i] = true;
+                }
+            }
+            break;
+            case svExternalDoubleRef:
+                // TODO: Find out how to handle this...
             default:
                 SetError( errIllegalParameter);
             break;
diff --git a/sc/source/core/tool/interpr4.cxx b/sc/source/core/tool/interpr4.cxx
index 551a1c2..bfe5b6b 100644
--- a/sc/source/core/tool/interpr4.cxx
+++ b/sc/source/core/tool/interpr4.cxx
@@ -1519,6 +1519,28 @@ void ScInterpreter::PopExternalDoubleRef(ScExternalRefCache::TokenArrayRef& rArr
     if (nGlobalError)
         return;
 
+    GetExternalDoubleRef(nFileId, aTabName, aData, rArray);
+    if (nGlobalError)
+        return;
+}
+
+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();
+}
+
+void ScInterpreter::GetExternalDoubleRef(
+    sal_uInt16 nFileId, const String& rTabName, const ScComplexRefData& rData, ScExternalRefCache::TokenArrayRef& rArray)
+{
     ScExternalRefManager* pRefMgr = pDok->GetExternalRefManager();
     const String* pFile = pRefMgr->getExternalFileName(nFileId);
     if (!pFile)
@@ -1526,18 +1548,19 @@ void ScInterpreter::PopExternalDoubleRef(ScExternalRefCache::TokenArrayRef& rArr
         SetError(errNoName);
         return;
     }
-    if (aData.Ref1.IsTabRel() || aData.Ref2.IsTabRel())
+    if (rData.Ref1.IsTabRel() || rData.Ref2.IsTabRel())
     {
         OSL_FAIL("ScCompiler::GetToken: external double reference must have an absolute table reference!");
         SetError(errNoRef);
         return;
     }
 
+    ScComplexRefData aData(rData);
     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);
+        nFileId, rTabName, aRange, &aPos);
 
     if (!pArray)
     {
@@ -1562,20 +1585,6 @@ void ScInterpreter::PopExternalDoubleRef(ScExternalRefCache::TokenArrayRef& rArr
     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();
-}
-
 sal_Bool ScInterpreter::PopDoubleRefOrSingleRef( ScAddress& rAdr )
 {
     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::PopDoubleRefOrSingleRef" );
@@ -1643,6 +1652,7 @@ bool ScInterpreter::ConvertMatrixParameters()
                 case svDouble:
                 case svString:
                 case svSingleRef:
+                case svExternalSingleRef:
                 case svMissing:
                 case svError:
                 case svEmptyCell:
@@ -1700,6 +1710,35 @@ bool ScInterpreter::ConvertMatrixParameters()
                     }
                 }
                 break;
+                case svExternalDoubleRef:
+                {
+                    ScParameterClassification::Type eType =
+                        ScParameterClassification::GetParameterType( pCur, nParams - i);
+                    if (eType == ScParameterClassification::Array)
+                    {
+                        sal_uInt16 nFileId = p->GetIndex();
+                        const String& rTabName = p->GetString();
+                        const ScComplexRefData& rRef = static_cast<ScToken*>(p)->GetDoubleRef();
+                        ScExternalRefCache::TokenArrayRef pArray;
+                        GetExternalDoubleRef(nFileId, rTabName, rRef, pArray);
+                        if (nGlobalError)
+                            break;
+
+                        ScToken* pTemp = static_cast<ScToken*>(pArray->First());
+                        if (!pTemp)
+                            break;
+
+                        ScMatrixRef pMat = pTemp->GetMatrix();
+                        if (pMat)
+                        {
+                            ScToken* pNew = new ScMatrixToken( pMat);
+                            pNew->IncRef();
+                            pStack[ sp - i ] = pNew;
+                            p->DecRef();    // p may be dead now!
+                        }
+                    }
+                }
+                break;
                 case svRefList:
                 {
                     ScParameterClassification::Type eType =
-- 
1.7.3.4


--=-ChWmTbS2MuC2GE8sk2Z7--



More information about the LibreOffice mailing list