summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--formula/source/core/api/vectortoken.cxx4
-rw-r--r--include/formula/vectortoken.hxx4
-rw-r--r--sc/inc/column.hxx9
-rw-r--r--sc/inc/document.hxx2
-rw-r--r--sc/inc/table.hxx1
-rw-r--r--sc/source/core/data/column.cxx21
-rw-r--r--sc/source/core/data/column2.cxx56
-rw-r--r--sc/source/core/data/document.cxx9
-rw-r--r--sc/source/core/data/formulacell.cxx90
-rw-r--r--sc/source/core/data/table1.cxx11
10 files changed, 183 insertions, 24 deletions
diff --git a/formula/source/core/api/vectortoken.cxx b/formula/source/core/api/vectortoken.cxx
index b7cab77e0136..0c2e45577198 100644
--- a/formula/source/core/api/vectortoken.cxx
+++ b/formula/source/core/api/vectortoken.cxx
@@ -23,9 +23,9 @@ const VectorArray& SingleVectorRefToken::GetArray() const
}
DoubleVectorRefToken::DoubleVectorRefToken(
- const std::vector<VectorArray>& rArrays, size_t nColSize, size_t nRowSize, bool bAbsStart, bool bAbsEnd ) :
+ const std::vector<VectorArray>& rArrays, size_t nRowSize, bool bAbsStart, bool bAbsEnd ) :
FormulaToken(svDoubleVectorRef, ocPush),
- maArrays(rArrays), mnColSize(nColSize), mnRowSize(nRowSize), mbAbsStart(bAbsStart), mbAbsEnd(bAbsEnd) {}
+ maArrays(rArrays), mnRowSize(nRowSize), mbAbsStart(bAbsStart), mbAbsEnd(bAbsEnd) {}
const std::vector<VectorArray>& DoubleVectorRefToken::GetArrays() const
{
diff --git a/include/formula/vectortoken.hxx b/include/formula/vectortoken.hxx
index 5af2690a5de6..90e28d836a75 100644
--- a/include/formula/vectortoken.hxx
+++ b/include/formula/vectortoken.hxx
@@ -39,7 +39,6 @@ class FORMULA_DLLPUBLIC DoubleVectorRefToken : public FormulaToken
{
std::vector<VectorArray> maArrays;
- size_t mnColSize;
size_t mnRowSize;
bool mbAbsStart:1; /// whether or not the start row position is absolute.
@@ -47,8 +46,7 @@ class FORMULA_DLLPUBLIC DoubleVectorRefToken : public FormulaToken
public:
DoubleVectorRefToken(
- const std::vector<VectorArray>& rArrays, size_t nColSize, size_t nRowSize,
- bool bAbsStart, bool bAbsEnd );
+ const std::vector<VectorArray>& rArrays, size_t nRowSize, bool bAbsStart, bool bAbsEnd );
const std::vector<VectorArray>& GetArrays() const;
};
diff --git a/sc/inc/column.hxx b/sc/inc/column.hxx
index 157bc173e98f..6b3202ae6f1c 100644
--- a/sc/inc/column.hxx
+++ b/sc/inc/column.hxx
@@ -106,6 +106,11 @@ struct ColDoubleEntry
{
SCROW mnStart;
std::vector<double> maData;
+
+ struct LessByPtr : std::binary_function<ColDoubleEntry*, ColDoubleEntry*, bool>
+ {
+ bool operator() (const ColDoubleEntry* p1, const ColDoubleEntry* p2) const;
+ };
};
class ScColumn
@@ -155,6 +160,9 @@ friend class ScDocumentImport;
static void SwapScriptTypes( ScriptType& rSrc, SCROW nSrcRow, ScriptType& rDest, SCROW nDestRow );
+ std::vector<ColEntry>::iterator Search( SCROW nRow );
+ std::vector<ColEntry>::const_iterator Search( SCROW nRow ) const;
+
public:
ScColumn();
~ScColumn();
@@ -452,6 +460,7 @@ public:
ScFormulaVectorState GetFormulaVectorState( SCROW nRow ) const;
formula::FormulaTokenRef ResolveStaticReference( SCROW nRow );
bool ResolveStaticReference( ScMatrix& rMat, SCCOL nMatCol, SCROW nRow1, SCROW nRow2 );
+ const double* FetchDoubleArray( SCROW nRow1, SCROW nRow2 ) const;
ScRefCellValue GetRefCellValue( SCROW );
diff --git a/sc/inc/document.hxx b/sc/inc/document.hxx
index cdb80e041e95..876c9d764eb0 100644
--- a/sc/inc/document.hxx
+++ b/sc/inc/document.hxx
@@ -1944,6 +1944,8 @@ public:
formula::FormulaTokenRef ResolveStaticReference( const ScAddress& rPos );
formula::FormulaTokenRef ResolveStaticReference( const ScRange& rRange );
+ const double* FetchDoubleArray( const ScAddress& rPos, SCROW nLength ) const;
+
private: // CLOOK-Impl-methods
/**
diff --git a/sc/inc/table.hxx b/sc/inc/table.hxx
index c04b902135d1..7c45a578274c 100644
--- a/sc/inc/table.hxx
+++ b/sc/inc/table.hxx
@@ -822,6 +822,7 @@ public:
ScFormulaVectorState GetFormulaVectorState( SCCOL nCol, SCROW nRow ) const;
formula::FormulaTokenRef ResolveStaticReference( SCCOL nCol, SCROW nRow );
formula::FormulaTokenRef ResolveStaticReference( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 );
+ const double* FetchDoubleArray( SCCOL nCol, SCROW nRow1, SCROW nRow2 ) const;
ScRefCellValue GetRefCellValue( SCCOL nCol, SCROW nRow );
diff --git a/sc/source/core/data/column.cxx b/sc/source/core/data/column.cxx
index 0c3e630e3a0c..17bbe687ceb8 100644
--- a/sc/source/core/data/column.cxx
+++ b/sc/source/core/data/column.cxx
@@ -50,6 +50,11 @@ bool ColEntry::Less::operator() (const ColEntry& r1, const ColEntry& r2) const
return r1.nRow < r2.nRow;
}
+bool ColDoubleEntry::LessByPtr::operator() (const ColDoubleEntry* p1, const ColDoubleEntry* p2) const
+{
+ return p1->mnStart < p2->mnStart;
+}
+
namespace {
inline bool IsAmbiguousScriptNonZero( sal_uInt8 nScript )
@@ -89,6 +94,22 @@ void ScColumn::SwapScriptTypes( ScriptType& rSrc, SCROW nSrcRow, ScriptType& rDe
rDest.set_empty(nDestRow, nDestRow);
}
+std::vector<ColEntry>::iterator ScColumn::Search( SCROW nRow )
+{
+ // Find first cell whose position is equal or greater than nRow.
+ ColEntry aBound;
+ aBound.nRow = nRow;
+ return std::lower_bound(maItems.begin(), maItems.end(), aBound, ColEntry::Less());
+}
+
+std::vector<ColEntry>::const_iterator ScColumn::Search( SCROW nRow ) const
+{
+ // Find first cell whose position is equal or greater than nRow.
+ ColEntry aBound;
+ aBound.nRow = nRow;
+ return std::lower_bound(maItems.begin(), maItems.end(), aBound, ColEntry::Less());
+}
+
ScColumn::ScColumn() :
maTextWidths(MAXROWCOUNT),
maScriptTypes(MAXROWCOUNT),
diff --git a/sc/source/core/data/column2.cxx b/sc/source/core/data/column2.cxx
index 6bcf2829af2c..25725ae5fa57 100644
--- a/sc/source/core/data/column2.cxx
+++ b/sc/source/core/data/column2.cxx
@@ -1591,12 +1591,8 @@ ScFormulaVectorState ScColumn::GetFormulaVectorState( SCROW nRow ) const
formula::FormulaTokenRef ScColumn::ResolveStaticReference( SCROW nRow )
{
+ std::vector<ColEntry>::iterator it = Search(nRow);
std::vector<ColEntry>::iterator itEnd = maItems.end();
- // Find first cell whose position is equal or greater than nRow1.
- ColEntry aBound;
- aBound.nRow = nRow;
- std::vector<ColEntry>::iterator it =
- std::lower_bound(maItems.begin(), itEnd, aBound, ColEntry::Less());
if (it == itEnd || it->nRow != nRow)
{
@@ -1633,12 +1629,8 @@ bool ScColumn::ResolveStaticReference( ScMatrix& rMat, SCCOL nMatCol, SCROW nRow
if (nRow1 > nRow2)
return false;
+ std::vector<ColEntry>::iterator it = Search(nRow1);
std::vector<ColEntry>::iterator itEnd = maItems.end();
- // Find first cell whose position is equal or greater than nRow1.
- ColEntry aBound;
- aBound.nRow = nRow1;
- std::vector<ColEntry>::iterator it =
- std::lower_bound(maItems.begin(), itEnd, aBound, ColEntry::Less());
for (; it != itEnd && it->nRow <= nRow2; ++it)
{
@@ -1668,6 +1660,50 @@ bool ScColumn::ResolveStaticReference( ScMatrix& rMat, SCCOL nMatCol, SCROW nRow
return true;
}
+const double* ScColumn::FetchDoubleArray( SCROW nRow1, SCROW nRow2 ) const
+{
+ if (nRow1 > nRow2)
+ return NULL;
+
+ ColDoubleEntry aBound;
+ aBound.mnStart = nRow1;
+ std::vector<ColDoubleEntry*>::const_iterator it =
+ std::lower_bound(maDoubles.begin(), maDoubles.end(), &aBound, ColDoubleEntry::LessByPtr());
+
+ if (it == maDoubles.end())
+ return NULL;
+
+ // There should never be an entry with empty double array. So we don't
+ // even bother checking for emptiness here.
+
+ const ColDoubleEntry& rEntry = **it;
+
+ if (rEntry.mnStart == nRow1)
+ {
+ SCROW nLastRow = rEntry.mnStart + rEntry.maData.size() - 1;
+ if (nLastRow < nRow2)
+ // Array is shorter than requested length.
+ return NULL;
+
+ return &rEntry.maData[0];
+ }
+
+ OSL_ASSERT(nRow1 < rEntry.mnStart);
+
+ if (it == maDoubles.begin())
+ // This is the very first array entry.
+ return NULL;
+
+ --it; // Go to previous array so that rEntry.mnStart < nRow1.
+ OSL_ASSERT((**it).mnStart < nRow1);
+ SCROW nLastRow = rEntry.mnStart + rEntry.maData.size() - 1;
+ if (nLastRow < nRow2)
+ // Array is shorter than requested length.
+ return NULL;
+
+ return &rEntry.maData[nRow1 - rEntry.mnStart];
+}
+
ScRefCellValue ScColumn::GetRefCellValue( SCROW nRow )
{
ScRefCellValue aCell; // start empty
diff --git a/sc/source/core/data/document.cxx b/sc/source/core/data/document.cxx
index 9a3dcf7b1668..c4f93c6e0e97 100644
--- a/sc/source/core/data/document.cxx
+++ b/sc/source/core/data/document.cxx
@@ -1593,6 +1593,15 @@ formula::FormulaTokenRef ScDocument::ResolveStaticReference( const ScRange& rRan
rRange.aStart.Col(), rRange.aStart.Row(), rRange.aEnd.Col(), rRange.aEnd.Row());
}
+const double* ScDocument::FetchDoubleArray( const ScAddress& rPos, SCROW nLength ) const
+{
+ SCTAB nTab = rPos.Tab();
+ if (!TableExists(nTab))
+ return NULL;
+
+ return maTabs[nTab]->FetchDoubleArray(rPos.Col(), rPos.Row(), rPos.Row()+nLength-1);
+}
+
bool ScDocument::CanFitBlock( const ScRange& rOld, const ScRange& rNew )
{
if ( rOld == rNew )
diff --git a/sc/source/core/data/formulacell.cxx b/sc/source/core/data/formulacell.cxx
index 3bfd458320fd..20ec752e4053 100644
--- a/sc/source/core/data/formulacell.cxx
+++ b/sc/source/core/data/formulacell.cxx
@@ -40,6 +40,7 @@
#include "tokenarray.hxx"
#include "formula/errorcodes.hxx"
+#include "formula/vectortoken.hxx"
#include "svl/intitem.hxx"
#include "rtl/strbuf.hxx"
@@ -2912,7 +2913,7 @@ ScFormulaCell::CompareState ScFormulaCell::CompareByTokenArray( ScFormulaCell *p
if (rRef != pOtherTok->GetSingleRef())
return NotEqual;
- if (rRef.IsColRel() || rRef.IsRowRel())
+ if (rRef.IsRowRel())
bInvariant = false;
}
break;
@@ -2927,10 +2928,10 @@ ScFormulaCell::CompareState ScFormulaCell::CompareByTokenArray( ScFormulaCell *p
if (rRef2 != pOtherTok->GetSingleRef2())
return NotEqual;
- if (rRef1.IsColRel() || rRef1.IsRowRel())
+ if (rRef1.IsRowRel())
bInvariant = false;
- if (rRef2.IsColRel() || rRef2.IsRowRel())
+ if (rRef2.IsRowRel())
bInvariant = false;
}
break;
@@ -2967,6 +2968,75 @@ bool ScFormulaCell::InterpretFormulaGroup()
if (xGroup->mbInvariant)
return InterpretInvariantFormulaGroup();
+ ScTokenArray aCode;
+ pCode->Reset();
+ for (const formula::FormulaToken* p = pCode->First(); p; p = pCode->Next())
+ {
+ // A reference can be either absolute or relative. If it's absolute,
+ // convert it to a static value token. If relative, convert it to a
+ // vector reference token. Note: we only care about relative vs
+ // absolute reference state for row directions.
+
+ const ScToken* pToken = static_cast<const ScToken*>(p);
+ switch (pToken->GetType())
+ {
+ case svSingleRef:
+ {
+ ScSingleRefData aRef = pToken->GetSingleRef();
+ aRef.CalcAbsIfRel(aPos);
+ ScAddress aRefPos(aRef.nCol, aRef.nRow, aRef.nTab);
+ if (aRef.IsRowRel())
+ {
+ // Fetch double array guarantees that the length of the
+ // returned array equals or greater than the requested
+ // length.
+ const double* pArray = pDocument->FetchDoubleArray(aRefPos, xGroup->mnLength);
+ if (!pArray)
+ return false;
+
+ formula::SingleVectorRefToken aTok(pArray, xGroup->mnLength);
+ aCode.AddToken(aTok);
+ }
+ else
+ {
+ // Absolute row reference.
+ formula::FormulaTokenRef pNewToken = pDocument->ResolveStaticReference(aRefPos);
+ if (!pNewToken)
+ return false;
+
+ aCode.AddToken(*pNewToken);
+ }
+ }
+ break;
+ case svDoubleRef:
+ {
+ ScComplexRefData aRef = pToken->GetDoubleRef();
+ aRef.CalcAbsIfRel(aPos);
+ if (aRef.Ref1.IsRowRel() || aRef.Ref2.IsRowRel())
+ {
+ // TODO: Implement this.
+ return false;
+ }
+ else
+ {
+ // Absolute row reference.
+ ScRange aRefRange(
+ aRef.Ref1.nCol, aRef.Ref1.nRow, aRef.Ref1.nTab,
+ aRef.Ref2.nCol, aRef.Ref2.nRow, aRef.Ref2.nTab);
+
+ formula::FormulaTokenRef pNewToken = pDocument->ResolveStaticReference(aRefRange);
+ if (!pNewToken)
+ return false;
+
+ aCode.AddToken(*pNewToken);
+ }
+ }
+ break;
+ default:
+ aCode.AddToken(*pToken);
+ }
+ }
+
// scan the formula ...
// have a document method: "Get2DRangeAsDoublesArray" that does the
// column-based heavy lifting call it for each absolute range from the
@@ -3001,7 +3071,7 @@ bool ScFormulaCell::InterpretInvariantFormulaGroup()
{
if (pCode->GetVectorState() == FormulaVectorCheckReference)
{
- // An invariant group should only have absolute references, and no
+ // An invariant group should only have absolute row references, and no
// external references are allowed.
ScTokenArray aCode;
@@ -3013,8 +3083,9 @@ bool ScFormulaCell::InterpretInvariantFormulaGroup()
{
case svSingleRef:
{
- const ScSingleRefData& rRef = pToken->GetSingleRef();
- ScAddress aRefPos(rRef.nCol, rRef.nRow, rRef.nTab);
+ ScSingleRefData aRef = pToken->GetSingleRef();
+ aRef.CalcAbsIfRel(aPos); // column may be relative.
+ ScAddress aRefPos(aRef.nCol, aRef.nRow, aRef.nTab);
formula::FormulaTokenRef pNewToken = pDocument->ResolveStaticReference(aRefPos);
if (!pNewToken)
return false;
@@ -3024,10 +3095,11 @@ bool ScFormulaCell::InterpretInvariantFormulaGroup()
break;
case svDoubleRef:
{
- const ScComplexRefData& rRef = pToken->GetDoubleRef();
+ ScComplexRefData aRef = pToken->GetDoubleRef();
+ aRef.CalcAbsIfRel(aPos); // column may be relative.
ScRange aRefRange(
- rRef.Ref1.nCol, rRef.Ref1.nRow, rRef.Ref1.nTab,
- rRef.Ref2.nCol, rRef.Ref2.nRow, rRef.Ref2.nTab);
+ aRef.Ref1.nCol, aRef.Ref1.nRow, aRef.Ref1.nTab,
+ aRef.Ref2.nCol, aRef.Ref2.nRow, aRef.Ref2.nTab);
formula::FormulaTokenRef pNewToken = pDocument->ResolveStaticReference(aRefRange);
if (!pNewToken)
diff --git a/sc/source/core/data/table1.cxx b/sc/source/core/data/table1.cxx
index 52e0bb98c8e2..a6c60425328f 100644
--- a/sc/source/core/data/table1.cxx
+++ b/sc/source/core/data/table1.cxx
@@ -2140,6 +2140,17 @@ formula::FormulaTokenRef ScTable::ResolveStaticReference( SCCOL nCol1, SCROW nRo
return formula::FormulaTokenRef(new ScMatrixToken(pMat));
}
+const double* ScTable::FetchDoubleArray( SCCOL nCol, SCROW nRow1, SCROW nRow2 ) const
+{
+ if (nRow2 < nRow1)
+ return NULL;
+
+ if (!ValidCol(nCol) || !ValidRow(nRow1) || !ValidRow(nRow2))
+ return NULL;
+
+ return aCol[nCol].FetchDoubleArray(nRow1, nRow1);
+}
+
ScRefCellValue ScTable::GetRefCellValue( SCCOL nCol, SCROW nRow )
{
if (!ValidColRow(nCol, nRow))