summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sc/Library_sc.mk1
-rw-r--r--sc/inc/token.hxx24
-rw-r--r--sc/inc/types.hxx13
-rw-r--r--sc/source/core/data/formulacell.cxx4
-rw-r--r--sc/source/core/data/types.cxx24
-rw-r--r--sc/source/core/inc/interpre.hxx11
-rw-r--r--sc/source/core/tool/formulagroup.cxx6
-rw-r--r--sc/source/core/tool/interpr1.cxx244
-rw-r--r--sc/source/core/tool/interpr4.cxx39
-rw-r--r--sc/source/core/tool/interpr5.cxx14
-rw-r--r--sc/source/core/tool/token.cxx41
11 files changed, 355 insertions, 66 deletions
diff --git a/sc/Library_sc.mk b/sc/Library_sc.mk
index 3c06eafaeffd..bd1a9a3b2805 100644
--- a/sc/Library_sc.mk
+++ b/sc/Library_sc.mk
@@ -181,6 +181,7 @@ $(eval $(call gb_Library_add_exception_objects,sc,\
sc/source/core/data/table5 \
sc/source/core/data/table6 \
sc/source/core/data/tabprotection \
+ sc/source/core/data/types \
sc/source/core/data/userdat \
sc/source/core/data/validat \
sc/source/core/tool/addincfg \
diff --git a/sc/inc/token.hxx b/sc/inc/token.hxx
index 9603a8729e9b..32cdf5ad1869 100644
--- a/sc/inc/token.hxx
+++ b/sc/inc/token.hxx
@@ -33,6 +33,9 @@
#include "scmatrix.hxx"
#include "calcmacros.hxx"
+// Matrix token constants.
+#define MATRIX_TOKEN_HAS_RANGE 1
+
class ScJumpMatrix;
typedef ::std::vector< ScComplexRefData > ScRefList;
@@ -176,6 +179,27 @@ public:
virtual FormulaToken* Clone() const { return new ScMatrixToken(*this); }
};
+/**
+ * Token storing matrix that represents values in sheet range. It stores
+ * both the values in matrix form, and the range address the matrix
+ * represents.
+ */
+class ScMatrixRangeToken : public ScToken
+{
+ ScMatrixRef mpMatrix;
+ ScComplexRefData maRef;
+public:
+ ScMatrixRangeToken( const ScMatrixRef& p, const ScComplexRefData& rRef );
+ ScMatrixRangeToken( const ScMatrixRangeToken& r );
+
+ virtual sal_uInt8 GetByte() const;
+ virtual const ScMatrix* GetMatrix() const;
+ virtual ScMatrix* GetMatrix();
+ virtual const ScComplexRefData& GetDoubleRef() const;
+ virtual ScComplexRefData& GetDoubleRef();
+ virtual bool operator==( const formula::FormulaToken& rToken ) const;
+ virtual FormulaToken* Clone() const;
+};
class ScExternalSingleRefToken : public ScToken
{
diff --git a/sc/inc/types.hxx b/sc/inc/types.hxx
index 5c11da518976..f03ccc0149ec 100644
--- a/sc/inc/types.hxx
+++ b/sc/inc/types.hxx
@@ -63,6 +63,19 @@ enum GroupCalcState
GroupCalcDisabled
};
+struct RangeMatrix
+{
+ ScMatrixRef mpMat;
+ sal_Int32 mnCol1;
+ sal_Int32 mnRow1;
+ sal_Int32 mnCol2;
+ sal_Int32 mnRow2;
+
+ RangeMatrix();
+
+ bool isRangeValid() const;
+};
+
}
#endif
diff --git a/sc/source/core/data/formulacell.cxx b/sc/source/core/data/formulacell.cxx
index da2f75bbb617..4f0b90e03139 100644
--- a/sc/source/core/data/formulacell.cxx
+++ b/sc/source/core/data/formulacell.cxx
@@ -3520,7 +3520,9 @@ bool ScFormulaCell::InterpretFormulaGroup()
return false;
}
- if (mxGroup->mbInvariant)
+ // TODO : Disable invariant formula group interpretation for now in order
+ // to get implicit intersection to work.
+ if (mxGroup->mbInvariant && false)
return InterpretInvariantFormulaGroup();
sc::FormulaGroupContext aCxt;
diff --git a/sc/source/core/data/types.cxx b/sc/source/core/data/types.cxx
new file mode 100644
index 000000000000..566d088ffe29
--- /dev/null
+++ b/sc/source/core/data/types.cxx
@@ -0,0 +1,24 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "types.hxx"
+#include "scmatrix.hxx"
+
+namespace sc {
+
+RangeMatrix::RangeMatrix() : mpMat(NULL), mnCol1(-1), mnRow1(-1), mnCol2(-1), mnRow2(-1) {}
+
+bool RangeMatrix::isRangeValid() const
+{
+ return mnCol1 >= 0 && mnRow1 >= 0 && mnCol2 >= 0 && mnRow2 >= 0 && mnCol1 <= mnCol2 && mnRow1 <= mnRow2;
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/core/inc/interpre.hxx b/sc/source/core/inc/interpre.hxx
index 8cf87b0bf9f6..bb9f9194aafb 100644
--- a/sc/source/core/inc/interpre.hxx
+++ b/sc/source/core/inc/interpre.hxx
@@ -51,6 +51,12 @@ class ScToken;
class ScJumpMatrix;
struct ScRefCellValue;
+namespace sc {
+
+struct RangeMatrix;
+
+}
+
#define MAXSTACK (4096 / sizeof(formula::FormulaToken*))
class ScTokenStack
@@ -298,6 +304,7 @@ inline void MatrixDoubleRefToMatrix(); // if MatrixFormula: PopDoubleRefPus
// If MatrixFormula or ForceArray: ConvertMatrixParameters()
inline bool MatrixParameterConversion();
ScMatrixRef PopMatrix();
+sc::RangeMatrix PopRangeMatrix();
void QueryMatrixType(ScMatrixRef& xMat, short& rRetTypeExpr, sal_uLong& rRetIndexExpr);
void PushDouble(double nVal);
@@ -338,6 +345,8 @@ ScMatrixRef CreateMatrixFromDoubleRef( const formula::FormulaToken* pToken,
inline ScTokenMatrixMap& GetTokenMatrixMap();
ScTokenMatrixMap* CreateTokenMatrixMap();
ScMatrixRef GetMatrix();
+sc::RangeMatrix GetRangeMatrix();
+
void ScTableOp(); // repeated operations
void ScErrCell(); // special handling for
// error cell
@@ -373,7 +382,7 @@ double Compare();
/** @param pOptions
NULL means case sensitivity document option is to be used!
*/
-ScMatrixRef CompareMat( ScCompareOptions* pOptions = NULL );
+sc::RangeMatrix CompareMat( ScCompareOptions* pOptions = NULL );
ScMatrixRef QueryMat( const ScMatrixRef& pMat, ScCompareOptions& rOptions );
void ScEqual();
void ScNotEqual();
diff --git a/sc/source/core/tool/formulagroup.cxx b/sc/source/core/tool/formulagroup.cxx
index 4ac4b6be8112..40f4befe32d7 100644
--- a/sc/source/core/tool/formulagroup.cxx
+++ b/sc/source/core/tool/formulagroup.cxx
@@ -93,7 +93,11 @@ bool FormulaGroupInterpreterSoftware::interpret(ScDocument& rDoc, const ScAddres
if (p2->IsStartFixed() && p2->IsEndFixed())
{
// Cached the converted token for absolute range referene.
- formula::FormulaTokenRef xTok(new ScMatrixToken(pMat));
+ ScComplexRefData aRef;
+ ScRange aRefRange = rTopPos;
+ aRefRange.aEnd.SetRow(rTopPos.Row() + nRowEnd);
+ aRef.InitRange(aRefRange);
+ formula::FormulaTokenRef xTok(new ScMatrixRangeToken(pMat, aRef));
aCachedTokens.insert(CachedTokensType::value_type(p, xTok));
aCode2.AddToken(*xTok);
}
diff --git a/sc/source/core/tool/interpr1.cxx b/sc/source/core/tool/interpr1.cxx
index a4d0d55ad2cb..fb7b7dd2e99e 100644
--- a/sc/source/core/tool/interpr1.cxx
+++ b/sc/source/core/tool/interpr1.cxx
@@ -1081,11 +1081,11 @@ double ScInterpreter::Compare()
}
-ScMatrixRef ScInterpreter::CompareMat( ScCompareOptions* pOptions )
+sc::RangeMatrix ScInterpreter::CompareMat( ScCompareOptions* pOptions )
{
String aVal1, aVal2;
ScCompare aComp( &aVal1, &aVal2 );
- ScMatrixRef pMat[2];
+ sc::RangeMatrix aMat[2];
ScAddress aAdr;
for( short i = 1; i >= 0; i-- )
{
@@ -1127,11 +1127,11 @@ ScMatrixRef ScInterpreter::CompareMat( ScCompareOptions* pOptions )
break;
case svDoubleRef:
case svMatrix:
- pMat[ i ] = GetMatrix();
- if ( !pMat[ i ] )
+ aMat[i] = GetRangeMatrix();
+ if (!aMat[i].mpMat)
SetError( errIllegalParameter);
else
- pMat[i]->SetErrorInterpreter( NULL);
+ aMat[i].mpMat->SetErrorInterpreter(NULL);
// errors are transported as DoubleError inside matrix
break;
default:
@@ -1139,82 +1139,88 @@ ScMatrixRef ScInterpreter::CompareMat( ScCompareOptions* pOptions )
break;
}
}
- ScMatrixRef pResMat = NULL;
+
+ sc::RangeMatrix aRes;
if( !nGlobalError )
{
- if ( pMat[0] && pMat[1] )
+ if (aMat[0].mpMat && aMat[1].mpMat)
{
SCSIZE nC0, nC1;
SCSIZE nR0, nR1;
- pMat[0]->GetDimensions( nC0, nR0 );
- pMat[1]->GetDimensions( nC1, nR1 );
+ aMat[0].mpMat->GetDimensions(nC0, nR0);
+ aMat[1].mpMat->GetDimensions(nC1, nR1);
SCSIZE nC = std::max( nC0, nC1 );
SCSIZE nR = std::max( nR0, nR1 );
- pResMat = GetNewMat( nC, nR);
- if ( !pResMat )
- return NULL;
+ aRes.mpMat = GetNewMat( nC, nR);
+ if (!aRes.mpMat)
+ return aRes;
for ( SCSIZE j=0; j<nC; j++ )
{
for ( SCSIZE k=0; k<nR; k++ )
{
SCSIZE nCol = j, nRow = k;
- if ( pMat[0]->ValidColRowOrReplicated( nCol, nRow ) &&
- pMat[1]->ValidColRowOrReplicated( nCol, nRow ))
+ if (aMat[0].mpMat->ValidColRowOrReplicated(nCol, nRow) &&
+ aMat[1].mpMat->ValidColRowOrReplicated(nCol, nRow))
{
for ( short i=1; i>=0; i-- )
{
- if ( pMat[i]->IsString(j,k) )
+ if (aMat[i].mpMat->IsString(j, k))
{
aComp.bVal[i] = false;
- *aComp.pVal[i] = pMat[i]->GetString(j,k);
- aComp.bEmpty[i] = pMat[i]->IsEmpty(j,k);
+ *aComp.pVal[i] = aMat[i].mpMat->GetString(j, k);
+ aComp.bEmpty[i] = aMat[i].mpMat->IsEmpty(j, k);
}
else
{
aComp.bVal[i] = true;
- aComp.nVal[i] = pMat[i]->GetDouble(j,k);
+ aComp.nVal[i] = aMat[i].mpMat->GetDouble(j, k);
aComp.bEmpty[i] = false;
}
}
- pResMat->PutDouble( CompareFunc( aComp, pOptions ), j,k );
+ aRes.mpMat->PutDouble(CompareFunc(aComp, pOptions), j, k);
}
else
- pResMat->PutString( ScGlobal::GetRscString(STR_NO_VALUE), j,k );
+ aRes.mpMat->PutString(ScGlobal::GetRscString(STR_NO_VALUE), j, k);
}
}
}
- else if ( pMat[0] || pMat[1] )
+ else if (aMat[0].mpMat || aMat[1].mpMat)
{
- short i = ( pMat[0] ? 0 : 1);
+ short i = ( aMat[0].mpMat ? 0 : 1);
SCSIZE nC, nR;
- pMat[i]->GetDimensions( nC, nR );
- pResMat = GetNewMat( nC, nR);
- if ( !pResMat )
- return NULL;
+ aMat[i].mpMat->GetDimensions(nC, nR);
+ aRes.mpMat = GetNewMat( nC, nR);
+ if (!aRes.mpMat)
+ return aRes;
+
+ aRes.mnCol1 = aMat[i].mnCol1;
+ aRes.mnRow1 = aMat[i].mnRow1;
+ aRes.mnCol2 = aMat[i].mnCol2;
+ aRes.mnRow2 = aMat[i].mnRow2;
for (SCSIZE j = 0; j < nC; ++j)
{
for (SCSIZE k = 0; k < nR; ++k)
{
- if ( pMat[i]->IsValue(j,k) )
+ if (aMat[i].mpMat->IsValue(j, k))
{
aComp.bVal[i] = true;
- aComp.nVal[i] = pMat[i]->GetDouble(j,k);
+ aComp.nVal[i] = aMat[i].mpMat->GetDouble(j, k);
aComp.bEmpty[i] = false;
}
else
{
aComp.bVal[i] = false;
- *aComp.pVal[i] = pMat[i]->GetString(j,k);
- aComp.bEmpty[i] = pMat[i]->IsEmpty(j,k);
+ *aComp.pVal[i] = aMat[i].mpMat->GetString(j, k);
+ aComp.bEmpty[i] = aMat[i].mpMat->IsEmpty(j, k);
}
- pResMat->PutDouble( CompareFunc(aComp, pOptions), j, k);
+ aRes.mpMat->PutDouble(CompareFunc(aComp, pOptions), j, k);
}
}
}
}
nCurFmtType = nFuncFmtType = NUMBERFORMAT_LOGICAL;
- return pResMat;
+ return aRes;
}
@@ -1228,7 +1234,7 @@ ScMatrixRef ScInterpreter::QueryMat( const ScMatrixRef& pMat, ScCompareOptions&
PushString(rItem.maString);
else
PushDouble(rItem.mfVal);
- ScMatrixRef pResultMatrix = CompareMat( &rOptions);
+ ScMatrixRef pResultMatrix = CompareMat( &rOptions).mpMat;
nCurFmtType = nSaveCurFmtType;
nFuncFmtType = nSaveFuncFmtType;
if (nGlobalError || !pResultMatrix)
@@ -1264,19 +1270,56 @@ ScMatrixRef ScInterpreter::QueryMat( const ScMatrixRef& pMat, ScCompareOptions&
return pResultMatrix;
}
+namespace {
+
+double applyImplicitIntersection(const sc::RangeMatrix& rMat, const ScAddress& rPos)
+{
+ if (rMat.mnRow1 <= rPos.Row() && rPos.Row() <= rMat.mnRow2 && rMat.mnCol1 == rMat.mnCol2)
+ {
+ SCROW nOffset = rPos.Row() - rMat.mnRow1;
+ return rMat.mpMat->GetDouble(0, nOffset);
+ }
+
+ if (rMat.mnCol1 <= rPos.Col() && rPos.Col() <= rMat.mnCol2 && rMat.mnRow1 == rMat.mnRow2)
+ {
+ SCROW nOffset = rPos.Col() - rMat.mnCol1;
+ return rMat.mpMat->GetDouble(nOffset, 0);
+ }
+
+ double fVal;
+ rtl::math::setNan(&fVal);
+ return fVal;
+}
+
+}
void ScInterpreter::ScEqual()
{
if ( GetStackType(1) == svMatrix || GetStackType(2) == svMatrix )
{
- ScMatrixRef pMat = CompareMat();
- if ( !pMat )
+ sc::RangeMatrix aMat = CompareMat();
+ if (!aMat.mpMat)
+ {
PushIllegalParameter();
- else
+ return;
+ }
+
+ if (aMat.isRangeValid())
{
- pMat->CompareEqual();
- PushMatrix( pMat );
+ // This matrix represents a range reference. Apply implicit intersection.
+ double fVal = applyImplicitIntersection(aMat, aPos);
+ if (rtl::math::isNan(fVal))
+ {
+ PushError(errCellNoValue);
+ return;
+ }
+
+ PushInt(fVal == 0.0);
+ return;
}
+
+ aMat.mpMat->CompareEqual();
+ PushMatrix(aMat.mpMat);
}
else
PushInt( Compare() == 0 );
@@ -1287,14 +1330,29 @@ void ScInterpreter::ScNotEqual()
{
if ( GetStackType(1) == svMatrix || GetStackType(2) == svMatrix )
{
- ScMatrixRef pMat = CompareMat();
- if ( !pMat )
+ sc::RangeMatrix aMat = CompareMat();
+ if (!aMat.mpMat)
+ {
PushIllegalParameter();
- else
+ return;
+ }
+
+ if (aMat.isRangeValid())
{
- pMat->CompareNotEqual();
- PushMatrix( pMat );
+ // This matrix represents a range reference. Apply implicit intersection.
+ double fVal = applyImplicitIntersection(aMat, aPos);
+ if (rtl::math::isNan(fVal))
+ {
+ PushError(errCellNoValue);
+ return;
+ }
+
+ PushInt(fVal != 0.0);
+ return;
}
+
+ aMat.mpMat->CompareNotEqual();
+ PushMatrix(aMat.mpMat);
}
else
PushInt( Compare() != 0 );
@@ -1305,14 +1363,29 @@ void ScInterpreter::ScLess()
{
if ( GetStackType(1) == svMatrix || GetStackType(2) == svMatrix )
{
- ScMatrixRef pMat = CompareMat();
- if ( !pMat )
+ sc::RangeMatrix aMat = CompareMat();
+ if (!aMat.mpMat)
+ {
PushIllegalParameter();
- else
+ return;
+ }
+
+ if (aMat.isRangeValid())
{
- pMat->CompareLess();
- PushMatrix( pMat );
+ // This matrix represents a range reference. Apply implicit intersection.
+ double fVal = applyImplicitIntersection(aMat, aPos);
+ if (rtl::math::isNan(fVal))
+ {
+ PushError(errCellNoValue);
+ return;
+ }
+
+ PushInt(fVal < 0.0);
+ return;
}
+
+ aMat.mpMat->CompareLess();
+ PushMatrix(aMat.mpMat);
}
else
PushInt( Compare() < 0 );
@@ -1323,14 +1396,29 @@ void ScInterpreter::ScGreater()
{
if ( GetStackType(1) == svMatrix || GetStackType(2) == svMatrix )
{
- ScMatrixRef pMat = CompareMat();
- if ( !pMat )
+ sc::RangeMatrix aMat = CompareMat();
+ if (!aMat.mpMat)
+ {
PushIllegalParameter();
- else
+ return;
+ }
+
+ if (aMat.isRangeValid())
{
- pMat->CompareGreater();
- PushMatrix( pMat );
+ // This matrix represents a range reference. Apply implicit intersection.
+ double fVal = applyImplicitIntersection(aMat, aPos);
+ if (rtl::math::isNan(fVal))
+ {
+ PushError(errCellNoValue);
+ return;
+ }
+
+ PushInt(fVal > 0.0);
+ return;
}
+
+ aMat.mpMat->CompareGreater();
+ PushMatrix(aMat.mpMat);
}
else
PushInt( Compare() > 0 );
@@ -1341,14 +1429,29 @@ void ScInterpreter::ScLessEqual()
{
if ( GetStackType(1) == svMatrix || GetStackType(2) == svMatrix )
{
- ScMatrixRef pMat = CompareMat();
- if ( !pMat )
+ sc::RangeMatrix aMat = CompareMat();
+ if (!aMat.mpMat)
+ {
PushIllegalParameter();
- else
+ return;
+ }
+
+ if (aMat.isRangeValid())
{
- pMat->CompareLessEqual();
- PushMatrix( pMat );
+ // This matrix represents a range reference. Apply implicit intersection.
+ double fVal = applyImplicitIntersection(aMat, aPos);
+ if (rtl::math::isNan(fVal))
+ {
+ PushError(errCellNoValue);
+ return;
+ }
+
+ PushInt(fVal <= 0.0);
+ return;
}
+
+ aMat.mpMat->CompareLessEqual();
+ PushMatrix(aMat.mpMat);
}
else
PushInt( Compare() <= 0 );
@@ -1359,14 +1462,29 @@ void ScInterpreter::ScGreaterEqual()
{
if ( GetStackType(1) == svMatrix || GetStackType(2) == svMatrix )
{
- ScMatrixRef pMat = CompareMat();
- if ( !pMat )
+ sc::RangeMatrix aMat = CompareMat();
+ if (!aMat.mpMat)
+ {
PushIllegalParameter();
- else
+ return;
+ }
+
+ if (aMat.isRangeValid())
{
- pMat->CompareGreaterEqual();
- PushMatrix( pMat );
+ // This matrix represents a range reference. Apply implicit intersection.
+ double fVal = applyImplicitIntersection(aMat, aPos);
+ if (rtl::math::isNan(fVal))
+ {
+ PushError(errCellNoValue);
+ return;
+ }
+
+ PushInt(fVal >= 0.0);
+ return;
}
+
+ aMat.mpMat->CompareGreaterEqual();
+ PushMatrix(aMat.mpMat);
}
else
PushInt( Compare() >= 0 );
diff --git a/sc/source/core/tool/interpr4.cxx b/sc/source/core/tool/interpr4.cxx
index c6025d4bde7d..7beb5804575a 100644
--- a/sc/source/core/tool/interpr4.cxx
+++ b/sc/source/core/tool/interpr4.cxx
@@ -1794,6 +1794,45 @@ ScMatrixRef ScInterpreter::PopMatrix()
return NULL;
}
+sc::RangeMatrix ScInterpreter::PopRangeMatrix()
+{
+ sc::RangeMatrix aRet;
+ if (sp)
+ {
+ switch (pStack[sp-1]->GetType())
+ {
+ case svMatrix:
+ {
+ --sp;
+ FormulaToken* p = pStack[sp];
+ ScToken* p2 = static_cast<ScToken*>(p);
+ aRet.mpMat = p2->GetMatrix();
+ if (aRet.mpMat)
+ {
+ aRet.mpMat->SetErrorInterpreter(this);
+ if (p2->GetByte() == MATRIX_TOKEN_HAS_RANGE)
+ {
+ const ScComplexRefData& rRef = p2->GetDoubleRef();
+ if (!rRef.Ref1.IsColRel() && !rRef.Ref1.IsRowRel() && !rRef.Ref2.IsColRel() && !rRef.Ref2.IsRowRel())
+ {
+ aRet.mnCol1 = rRef.Ref1.Col();
+ aRet.mnRow1 = rRef.Ref1.Row();
+ aRet.mnCol2 = rRef.Ref2.Col();
+ aRet.mnRow2 = rRef.Ref2.Row();
+ }
+ }
+ }
+ else
+ SetError( errUnknownVariable);
+ }
+ break;
+ default:
+ aRet.mpMat = PopMatrix();
+ }
+ }
+ return aRet;
+}
+
void ScInterpreter::QueryMatrixType(ScMatrixRef& xMat, short& rRetTypeExpr, sal_uLong& rRetIndexExpr)
{
if (xMat)
diff --git a/sc/source/core/tool/interpr5.cxx b/sc/source/core/tool/interpr5.cxx
index ad7d799cd075..a033693d5c9c 100644
--- a/sc/source/core/tool/interpr5.cxx
+++ b/sc/source/core/tool/interpr5.cxx
@@ -494,6 +494,20 @@ ScMatrixRef ScInterpreter::GetMatrix()
return pMat;
}
+sc::RangeMatrix ScInterpreter::GetRangeMatrix()
+{
+ sc::RangeMatrix aRet;
+ switch (GetRawStackType())
+ {
+ case svMatrix:
+ aRet = PopRangeMatrix();
+ break;
+ default:
+ aRet.mpMat = GetMatrix();
+ }
+ return aRet;
+}
+
void ScInterpreter::ScMatValue()
{
if ( MustHaveParamCount( GetByte(), 3 ) )
diff --git a/sc/source/core/tool/token.cxx b/sc/source/core/tool/token.cxx
index e5627ff5a0d6..9f5a7e6bf752 100644
--- a/sc/source/core/tool/token.cxx
+++ b/sc/source/core/tool/token.cxx
@@ -804,6 +804,47 @@ bool ScMatrixToken::operator==( const FormulaToken& r ) const
return FormulaToken::operator==( r ) && pMatrix == static_cast<const ScToken&>(r).GetMatrix();
}
+ScMatrixRangeToken::ScMatrixRangeToken( const ScMatrixRef& p, const ScComplexRefData& rRef ) :
+ ScToken(formula::svMatrix), mpMatrix(p), maRef(rRef) {}
+
+ScMatrixRangeToken::ScMatrixRangeToken( const ScMatrixRangeToken& r ) :
+ ScToken(r), mpMatrix(r.mpMatrix), maRef(r.maRef) {}
+
+sal_uInt8 ScMatrixRangeToken::GetByte() const
+{
+ return MATRIX_TOKEN_HAS_RANGE;
+}
+
+const ScMatrix* ScMatrixRangeToken::GetMatrix() const
+{
+ return mpMatrix.get();
+}
+
+ScMatrix* ScMatrixRangeToken::GetMatrix()
+{
+ return mpMatrix.get();
+}
+
+const ScComplexRefData& ScMatrixRangeToken::GetDoubleRef() const
+{
+ return maRef;
+}
+
+ScComplexRefData& ScMatrixRangeToken::GetDoubleRef()
+{
+ return maRef;
+}
+
+bool ScMatrixRangeToken::operator==( const FormulaToken& r ) const
+{
+ return FormulaToken::operator==(r) && mpMatrix == static_cast<const ScToken&>(r).GetMatrix();
+}
+
+FormulaToken* ScMatrixRangeToken::Clone() const
+{
+ return new ScMatrixRangeToken(*this);
+}
+
// ============================================================================
ScExternalSingleRefToken::ScExternalSingleRefToken( sal_uInt16 nFileId, const String& rTabName, const ScSingleRefData& r ) :