[Libreoffice-commits] core.git: Branch 'feature/formula-core-rework' - 16 commits - configure.ac sc/inc sc/source sfx2/source starmath/source svgio/source vcl/inc vcl/unx
Kohei Yoshida
kohei.yoshida at gmail.com
Tue Jul 2 20:34:03 PDT 2013
Rebased ref, commits from common ancestor:
commit 8c56ee1f1013c6be4c980ed17945c92b7370c4c8
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date: Tue Jul 2 23:32:11 2013 -0400
Not to forget this header...
Change-Id: I3f05923787ec87d5231433e4fad562326becae49
diff --git a/sc/source/core/tool/formulagroup.cxx b/sc/source/core/tool/formulagroup.cxx
index b4fd646..221a768 100644
--- a/sc/source/core/tool/formulagroup.cxx
+++ b/sc/source/core/tool/formulagroup.cxx
@@ -22,6 +22,10 @@
#define USE_DUMMY_INTERPRETER 1
+#if USE_DUMMY_INTERPRETER
+#include <cstdio>
+#endif
+
namespace sc {
ScMatrixRef FormulaGroupInterpreterSoftware::inverseMatrix(const ScMatrix& /*rMat*/)
commit b81d130626c20b806fc8a28524b38756eebc6c46
Author: Michael Meeks <michael.meeks at suse.com>
Date: Tue Jul 2 22:01:01 2013 +0100
Dummy formula group interpreter for testing.
diff --git a/sc/inc/formulagroup.hxx b/sc/inc/formulagroup.hxx
index 1c573c4..e645968 100644
--- a/sc/inc/formulagroup.hxx
+++ b/sc/inc/formulagroup.hxx
@@ -30,9 +30,8 @@ struct FormulaGroupContext : boost::noncopyable
};
/**
- * All the vectorized formula calculation code should be collected here.
- *
- * Abstract base class for formula group interpreters, and a factory.
+ * Abstract base class for vectorised formula group interpreters,
+ * plus a global instance factory.
*/
class SC_DLLPUBLIC FormulaGroupInterpreter
{
diff --git a/sc/source/core/tool/formulagroup.cxx b/sc/source/core/tool/formulagroup.cxx
index b20b437..b4fd646 100644
--- a/sc/source/core/tool/formulagroup.cxx
+++ b/sc/source/core/tool/formulagroup.cxx
@@ -20,6 +20,8 @@
#include <vector>
+#define USE_DUMMY_INTERPRETER 1
+
namespace sc {
ScMatrixRef FormulaGroupInterpreterSoftware::inverseMatrix(const ScMatrix& /*rMat*/)
@@ -108,14 +110,61 @@ bool FormulaGroupInterpreterSoftware::interpret(ScDocument& rDoc, const ScAddres
namespace opencl {
extern sc::FormulaGroupInterpreter *createFormulaGroupInterpreter();
}
-
FormulaGroupInterpreter *FormulaGroupInterpreter::msInstance = NULL;
+#if USE_DUMMY_INTERPRETER
+class FormulaGroupInterpreterDummy : public FormulaGroupInterpreter
+{
+ enum Mode {
+ WRITE_OUTPUT = 0
+ };
+ Mode meMode;
+public:
+ FormulaGroupInterpreterDummy()
+ {
+ const char *pValue = getenv("FORMULA_GROUP_DUMMY");
+ meMode = static_cast<Mode>(OString(pValue, strlen(pValue)).toInt32());
+ fprintf(stderr, "Using Dummy Formula Group interpreter mode %d\n", (int)meMode);
+ }
+
+ virtual ScMatrixRef inverseMatrix(const ScMatrix& /*rMat*/)
+ {
+ return ScMatrixRef();
+ }
+
+ virtual bool interpret(ScDocument& rDoc, const ScAddress& rTopPos,
+ const ScFormulaCellGroupRef& xGroup,
+ ScTokenArray& rCode)
+ {
+ (void)rCode;
+
+ // Write simple data back into the sheet
+ if (meMode == WRITE_OUTPUT)
+ {
+ double *pDoubles = new double[xGroup->mnLength];
+ for (sal_Int32 i = 0; i < xGroup->mnLength; i++)
+ pDoubles[i] = 42.0 + i;
+ rDoc.SetFormulaResults(rTopPos, pDoubles, xGroup->mnLength);
+ delete [] pDoubles;
+ }
+ return true;
+ }
+};
+#endif
+
/// load and/or configure the correct formula group interpreter
FormulaGroupInterpreter *FormulaGroupInterpreter::getStatic()
{
static bool bOpenCLEnabled = false;
+#if USE_DUMMY_INTERPRETER
+ if (getenv("FORMULA_GROUP_DUMMY"))
+ {
+ delete msInstance;
+ return msInstance = new sc::FormulaGroupInterpreterDummy();
+ }
+#endif
+
if ( msInstance &&
bOpenCLEnabled != ScInterpreter::GetGlobalConfig().mbOpenCLEnabled )
{
commit 1eb0aac39f366caf497534de00fb30b84ac1ba62
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date: Tue Jul 2 22:23:56 2013 -0400
Forgot to remove these debug statements.
Change-Id: I680750c43dce4b6e7f9b9ed0a6b8550bdf485a8c
diff --git a/sc/source/core/data/formulacell.cxx b/sc/source/core/data/formulacell.cxx
index 132ed5c..f8928e5 100644
--- a/sc/source/core/data/formulacell.cxx
+++ b/sc/source/core/data/formulacell.cxx
@@ -3115,12 +3115,8 @@ bool ScFormulaCell::InterpretFormulaGroup()
if (!xGroup || !pCode)
return false;
- fprintf(stdout, "ScFormulaCell::InterpretFormulaGroup: calc state = %d\n", xGroup->meCalcState);
if (xGroup->meCalcState == sc::GroupCalcDisabled)
- {
- fprintf(stdout, "ScFormulaCell::InterpretFormulaGroup: group calc disabled.\n");
return false;
- }
switch (pCode->GetVectorState())
{
@@ -3145,7 +3141,6 @@ bool ScFormulaCell::InterpretFormulaGroup()
GroupTokenConverter aConverter(aCxt, aCode, *pDocument, *this, aTopPos);
if (!aConverter.convert(*pCode))
{
- fprintf(stdout, "ScFormulaCell::InterpretFormulaGroup: disabling group calc due to failed conversion\n");
xGroup->meCalcState = sc::GroupCalcDisabled;
return false;
}
@@ -3153,7 +3148,6 @@ bool ScFormulaCell::InterpretFormulaGroup()
xGroup->meCalcState = sc::GroupCalcRunning;
if (!sc::FormulaGroupInterpreter::getStatic()->interpret(*pDocument, aTopPos, xGroup, aCode))
{
- fprintf(stdout, "ScFormulaCell::InterpretFormulaGroup: disabling group calc due to failed calculation\n");
xGroup->meCalcState = sc::GroupCalcDisabled;
return false;
}
commit ce7a2d39efc66ae682873a96030332b38ba3a4d6
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date: Tue Jul 2 22:10:25 2013 -0400
Detect circular dependency in formula groups to fallback to cell-based.
Change-Id: Icfb4fd4be4e0c1f6f450fb8ddce57c7b79568e6f
diff --git a/sc/inc/formulacell.hxx b/sc/inc/formulacell.hxx
index 52a1474..07b726a 100644
--- a/sc/inc/formulacell.hxx
+++ b/sc/inc/formulacell.hxx
@@ -24,6 +24,7 @@
#include "formula/tokenarray.hxx"
#include "svl/listener.hxx"
+#include "types.hxx"
#include <set>
@@ -40,19 +41,23 @@ struct ScSimilarFormulaDelta;
struct SC_DLLPUBLIC ScFormulaCellGroup
{
- sal_Int32 mnRefCount;
+ mutable size_t mnRefCount;
+
SCROW mnStart; // Start offset of that cell
SCROW mnLength; // How many of these do we have ?
bool mbInvariant;
+ sc::GroupCalcState meCalcState;
ScFormulaCellGroup();
~ScFormulaCellGroup();
};
-inline void intrusive_ptr_add_ref(ScFormulaCellGroup *p)
+
+inline void intrusive_ptr_add_ref(const ScFormulaCellGroup *p)
{
p->mnRefCount++;
}
-inline void intrusive_ptr_release(ScFormulaCellGroup *p)
+
+inline void intrusive_ptr_release(const ScFormulaCellGroup *p)
{
if( --p->mnRefCount == 0 )
delete p;
diff --git a/sc/inc/types.hxx b/sc/inc/types.hxx
index 445311e..5c11da5 100644
--- a/sc/inc/types.hxx
+++ b/sc/inc/types.hxx
@@ -56,6 +56,13 @@ const sal_uInt16 MatrixEdgeTop = 8;
const sal_uInt16 MatrixEdgeRight = 16;
const sal_uInt16 MatrixEdgeOpen = 32;
+enum GroupCalcState
+{
+ GroupCalcEnabled,
+ GroupCalcRunning,
+ GroupCalcDisabled
+};
+
}
#endif
diff --git a/sc/source/core/data/column2.cxx b/sc/source/core/data/column2.cxx
index 4becbb7..82daadf 100644
--- a/sc/source/core/data/column2.cxx
+++ b/sc/source/core/data/column2.cxx
@@ -2166,10 +2166,15 @@ bool appendDouble(
nLenRemain = 0;
}
+ sal_uInt16 nErr;
+ double fVal;
for (; itData != itDataEnd; ++itData)
{
ScFormulaCell& rFC = **itData;
- rArray.push_back(rFC.GetValue());
+ if (!rFC.GetErrorOrValue(nErr, fVal) || nErr)
+ return false;
+
+ rArray.push_back(fVal);
}
}
break;
@@ -2238,6 +2243,9 @@ const double* ScColumn::FetchDoubleArray( sc::FormulaGroupContext& rCxt, SCROW n
break;
case sc::element_type_formula:
{
+ sal_uInt16 nErr;
+ double fVal;
+
rCxt.maArrays.push_back(new sc::FormulaGroupContext::DoubleArrayType);
sc::FormulaGroupContext::DoubleArrayType& rArray = rCxt.maArrays.back();
rArray.reserve(nLenRequested);
@@ -2252,7 +2260,10 @@ const double* ScColumn::FetchDoubleArray( sc::FormulaGroupContext& rCxt, SCROW n
for (; it != itEnd; ++it)
{
ScFormulaCell& rCell = **it;
- rArray.push_back(rCell.GetValue()); // the cell may be interpreted.
+ if (!rCell.GetErrorOrValue(nErr, fVal) || nErr)
+ return NULL;
+
+ rArray.push_back(fVal);
}
return &rArray[0];
@@ -2264,7 +2275,10 @@ const double* ScColumn::FetchDoubleArray( sc::FormulaGroupContext& rCxt, SCROW n
for (; it != itEnd; ++it)
{
ScFormulaCell& rCell = **it;
- rArray.push_back(rCell.GetValue()); // the cell may be interpreted.
+ if (!rCell.GetErrorOrValue(nErr, fVal) || nErr)
+ return NULL;
+
+ rArray.push_back(fVal);
}
// Fill the remaining array with values from the following blocks.
diff --git a/sc/source/core/data/formulacell.cxx b/sc/source/core/data/formulacell.cxx
index a129726..132ed5c 100644
--- a/sc/source/core/data/formulacell.cxx
+++ b/sc/source/core/data/formulacell.cxx
@@ -382,7 +382,11 @@ void adjustDBRange(ScToken* pToken, ScDocument& rNewDoc, const ScDocument* pOldD
}
ScFormulaCellGroup::ScFormulaCellGroup() :
- mnRefCount(0), mnStart(0), mnLength(0), mbInvariant(false)
+ mnRefCount(0),
+ mnStart(0),
+ mnLength(0),
+ mbInvariant(false),
+ meCalcState(sc::GroupCalcEnabled)
{
}
@@ -1547,6 +1551,9 @@ void ScFormulaCell::SetDirty( bool bDirtyFlag )
void ScFormulaCell::SetDirtyVar()
{
bDirty = true;
+ if (xGroup)
+ xGroup->meCalcState = sc::GroupCalcEnabled;
+
// mark the sheet of this cell to be calculated
//#FIXME do we need to revert this remnant of old fake vba events? pDocument->AddCalculateTable( aPos.Tab() );
}
@@ -1611,7 +1618,7 @@ void ScFormulaCell::SetErrCode( sal_uInt16 n )
void ScFormulaCell::AddRecalcMode( ScRecalcMode nBits )
{
if ( (nBits & RECALCMODE_EMASK) != RECALCMODE_NORMAL )
- bDirty = true;
+ SetDirtyVar();
if ( nBits & RECALCMODE_ONLOAD_ONCE )
{ // OnLoadOnce nur zum Dirty setzen nach Filter-Import
nBits = (nBits & ~RECALCMODE_EMASK) | RECALCMODE_NORMAL;
@@ -2959,9 +2966,10 @@ class GroupTokenConverter
ScTokenArray& mrGroupTokens;
ScDocument& mrDoc;
ScFormulaCell& mrCell;
+ const ScAddress& mrPos;
public:
- GroupTokenConverter(sc::FormulaGroupContext& rCxt, ScTokenArray& rGroupTokens, ScDocument& rDoc, ScFormulaCell& rCell) :
- mrCxt(rCxt), mrGroupTokens(rGroupTokens), mrDoc(rDoc), mrCell(rCell) {}
+ GroupTokenConverter(sc::FormulaGroupContext& rCxt, ScTokenArray& rGroupTokens, ScDocument& rDoc, ScFormulaCell& rCell, const ScAddress& rPos) :
+ mrCxt(rCxt), mrGroupTokens(rGroupTokens), mrDoc(rDoc), mrCell(rCell), mrPos(rPos) {}
bool convert(ScTokenArray& rCode)
{
@@ -2979,8 +2987,7 @@ public:
case svSingleRef:
{
ScSingleRefData aRef = pToken->GetSingleRef();
- aRef.CalcAbsIfRel(mrCell.aPos);
- ScAddress aRefPos(aRef.nCol, aRef.nRow, aRef.nTab);
+ ScAddress aRefPos = aRef.toAbs(mrPos);
if (aRef.IsRowRel())
{
// Fetch double array guarantees that the length of the
@@ -3108,6 +3115,13 @@ bool ScFormulaCell::InterpretFormulaGroup()
if (!xGroup || !pCode)
return false;
+ fprintf(stdout, "ScFormulaCell::InterpretFormulaGroup: calc state = %d\n", xGroup->meCalcState);
+ if (xGroup->meCalcState == sc::GroupCalcDisabled)
+ {
+ fprintf(stdout, "ScFormulaCell::InterpretFormulaGroup: group calc disabled.\n");
+ return false;
+ }
+
switch (pCode->GetVectorState())
{
case FormulaVectorEnabled:
@@ -3126,10 +3140,26 @@ bool ScFormulaCell::InterpretFormulaGroup()
sc::FormulaGroupContext aCxt;
ScTokenArray aCode;
- GroupTokenConverter aConverter(aCxt, aCode, *pDocument, *this);
+ ScAddress aTopPos = aPos;
+ aTopPos.SetRow(xGroup->mnStart);
+ GroupTokenConverter aConverter(aCxt, aCode, *pDocument, *this, aTopPos);
if (!aConverter.convert(*pCode))
+ {
+ fprintf(stdout, "ScFormulaCell::InterpretFormulaGroup: disabling group calc due to failed conversion\n");
+ xGroup->meCalcState = sc::GroupCalcDisabled;
+ return false;
+ }
+
+ xGroup->meCalcState = sc::GroupCalcRunning;
+ if (!sc::FormulaGroupInterpreter::getStatic()->interpret(*pDocument, aTopPos, xGroup, aCode))
+ {
+ fprintf(stdout, "ScFormulaCell::InterpretFormulaGroup: disabling group calc due to failed calculation\n");
+ xGroup->meCalcState = sc::GroupCalcDisabled;
return false;
- return sc::FormulaGroupInterpreter::getStatic()->interpret(*pDocument, aPos, xGroup, aCode);
+ }
+
+ xGroup->meCalcState = sc::GroupCalcEnabled;
+ return true;
}
bool ScFormulaCell::InterpretInvariantFormulaGroup()
diff --git a/sc/source/core/tool/formulagroup.cxx b/sc/source/core/tool/formulagroup.cxx
index 79621ea..b20b437 100644
--- a/sc/source/core/tool/formulagroup.cxx
+++ b/sc/source/core/tool/formulagroup.cxx
@@ -33,18 +33,14 @@ bool FormulaGroupInterpreterSoftware::interpret(ScDocument& rDoc, const ScAddres
{
// Decompose the group into individual cells and calculate them individually.
- // Always set the top row to be the top of the group. Grouped formula
- // cells are to be calculated for its full segment at all times.
-
- ScAddress aTopPos = rTopPos;
- aTopPos.SetRow(xGroup->mnStart);
- ScAddress aTmpPos = aTopPos;
+ // The caller must ensure that the top position is the start position of
+ // the group.
+ ScAddress aTmpPos = rTopPos;
std::vector<double> aResults;
aResults.reserve(xGroup->mnLength);
- for (SCROW i = 0; i < xGroup->mnLength; ++i)
+ for (SCROW i = 0; i < xGroup->mnLength; ++i, aTmpPos.IncRow())
{
- aTmpPos.SetRow(aTopPos.Row() + i);
ScTokenArray aCode2;
for (const formula::FormulaToken* p = rCode.First(); p; p = rCode.Next())
{
@@ -103,7 +99,7 @@ bool FormulaGroupInterpreterSoftware::interpret(ScDocument& rDoc, const ScAddres
} // for loop end (xGroup->mnLength)
if (!aResults.empty())
- rDoc.SetFormulaResults(aTopPos, &aResults[0], aResults.size());
+ rDoc.SetFormulaResults(rTopPos, &aResults[0], aResults.size());
return true;
}
commit 041e7dce8097fe2a4fe1cc853cab463dd5ea72e5
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date: Tue Jul 2 18:55:29 2013 -0400
Actually we need to reset the top row to be the top of the group.
To ensure that a group of formula cells are either all clean or all
dirty at any given time. We'll fallback to non-grouped calculation
mode if that's not possible.
Change-Id: I8a5d4740571ca149d32a4630555e3c213c222ef3
diff --git a/sc/source/core/tool/formulagroup.cxx b/sc/source/core/tool/formulagroup.cxx
index 3dd43e3..79621ea 100644
--- a/sc/source/core/tool/formulagroup.cxx
+++ b/sc/source/core/tool/formulagroup.cxx
@@ -33,14 +33,18 @@ bool FormulaGroupInterpreterSoftware::interpret(ScDocument& rDoc, const ScAddres
{
// Decompose the group into individual cells and calculate them individually.
- ScAddress aTmpPos = rTopPos;
- SCROW nOffset = rTopPos.Row() - xGroup->mnStart;
- SCROW nLength = xGroup->mnLength - nOffset;
+ // Always set the top row to be the top of the group. Grouped formula
+ // cells are to be calculated for its full segment at all times.
+
+ ScAddress aTopPos = rTopPos;
+ aTopPos.SetRow(xGroup->mnStart);
+ ScAddress aTmpPos = aTopPos;
+
std::vector<double> aResults;
- aResults.reserve(nLength);
- for (SCROW i = 0; i < nLength; ++i)
+ aResults.reserve(xGroup->mnLength);
+ for (SCROW i = 0; i < xGroup->mnLength; ++i)
{
- aTmpPos.SetRow(rTopPos.Row() + i);
+ aTmpPos.SetRow(aTopPos.Row() + i);
ScTokenArray aCode2;
for (const formula::FormulaToken* p = rCode.First(); p; p = rCode.Next())
{
@@ -99,7 +103,7 @@ bool FormulaGroupInterpreterSoftware::interpret(ScDocument& rDoc, const ScAddres
} // for loop end (xGroup->mnLength)
if (!aResults.empty())
- rDoc.SetFormulaResults(rTopPos, &aResults[0], aResults.size());
+ rDoc.SetFormulaResults(aTopPos, &aResults[0], aResults.size());
return true;
}
commit 75cfc9a332b224597872960df22091ca76747058
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date: Tue Jul 2 16:47:31 2013 -0400
Be aware that the top row may not always be the top of the group.
Adjust the length and the starting row position for accordingly.
Change-Id: I2f9c5a515887b98334bad51c5409461d5dd1505d
diff --git a/sc/source/core/tool/formulagroup.cxx b/sc/source/core/tool/formulagroup.cxx
index 4754bd0..3dd43e3 100644
--- a/sc/source/core/tool/formulagroup.cxx
+++ b/sc/source/core/tool/formulagroup.cxx
@@ -18,6 +18,8 @@
#include "formula/vectortoken.hxx"
+#include <vector>
+
namespace sc {
ScMatrixRef FormulaGroupInterpreterSoftware::inverseMatrix(const ScMatrix& /*rMat*/)
@@ -29,12 +31,16 @@ bool FormulaGroupInterpreterSoftware::interpret(ScDocument& rDoc, const ScAddres
const ScFormulaCellGroupRef& xGroup,
ScTokenArray& rCode)
{
- // Until we implement group calculation for real, decompose the group into
- // individual formula token arrays for individual calculation.
+ // Decompose the group into individual cells and calculate them individually.
+
ScAddress aTmpPos = rTopPos;
- for (sal_Int32 i = 0; i < xGroup->mnLength; ++i)
+ SCROW nOffset = rTopPos.Row() - xGroup->mnStart;
+ SCROW nLength = xGroup->mnLength - nOffset;
+ std::vector<double> aResults;
+ aResults.reserve(nLength);
+ for (SCROW i = 0; i < nLength; ++i)
{
- aTmpPos.SetRow(xGroup->mnStart + i);
+ aTmpPos.SetRow(rTopPos.Row() + i);
ScTokenArray aCode2;
for (const formula::FormulaToken* p = rCode.First(); p; p = rCode.Next())
{
@@ -89,11 +95,12 @@ bool FormulaGroupInterpreterSoftware::interpret(ScDocument& rDoc, const ScAddres
aComp.CompileTokenArray(); // Create RPN token array.
ScInterpreter aInterpreter(pDest, &rDoc, aTmpPos, aCode2);
aInterpreter.Interpret();
- pDest->SetResultToken(aInterpreter.GetResultToken().get());
- pDest->ResetDirty();
- pDest->SetChanged(true);
+ aResults.push_back(aInterpreter.GetResultToken()->GetDouble());
} // for loop end (xGroup->mnLength)
+ if (!aResults.empty())
+ rDoc.SetFormulaResults(rTopPos, &aResults[0], aResults.size());
+
return true;
}
commit d61233a388284383a939e2f26a0e25b9ad243898
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date: Tue Jul 2 16:02:59 2013 -0400
Move this code from the column code back into the interpreter code.
Change-Id: I7830cdf3f09ed7b6ae6221212bfb84abcdeac523
diff --git a/sc/inc/column.hxx b/sc/inc/column.hxx
index 359b8ac..62e1ddf 100644
--- a/sc/inc/column.hxx
+++ b/sc/inc/column.hxx
@@ -409,9 +409,6 @@ public:
void ClearSelectionItems( const sal_uInt16* pWhich, const ScMarkData& rMark );
void ChangeSelectionIndent( bool bIncrement, const ScMarkData& rMark );
- double SumNumericCells( sc::ColumnBlockConstPosition& rPos, SCROW nRow1, SCROW nRow2 ) const;
- size_t CountNumericCells( sc::ColumnBlockConstPosition& rPos, SCROW nRow1, SCROW nRow2 ) const;
-
long GetNeededSize(
SCROW nRow, OutputDevice* pDev, double nPPTX, double nPPTY,
const Fraction& rZoomX, const Fraction& rZoomY,
diff --git a/sc/source/core/data/column.cxx b/sc/source/core/data/column.cxx
index 61f57ab..6a2dbd3 100644
--- a/sc/source/core/data/column.cxx
+++ b/sc/source/core/data/column.cxx
@@ -466,80 +466,6 @@ void ScColumn::ChangeSelectionIndent( bool bIncrement, const ScMarkData& rMark )
}
}
-namespace {
-
-class NumericCellAccumulator
-{
- double mfSum;
-public:
- NumericCellAccumulator() : mfSum(0.0) {}
-
- void operator() (size_t, double fVal)
- {
- mfSum += fVal;
- }
-
- void operator() (size_t, const ScFormulaCell* pCell)
- {
- ScFormulaCell& rCell = const_cast<ScFormulaCell&>(*pCell);
- if (rCell.IsValue())
- mfSum += rCell.GetValue();
- }
-
- double getSum() const { return mfSum; }
-};
-
-class NumericCellCounter
-{
- size_t mnCount;
-public:
- NumericCellCounter() : mnCount(0) {}
-
- void operator() (const sc::CellStoreType::value_type& rNode, size_t nOffset, size_t nDataSize)
- {
- switch (rNode.type)
- {
- case sc::element_type_numeric:
- mnCount += nDataSize;
- break;
- case sc::element_type_formula:
- {
- sc::formula_block::const_iterator it = sc::formula_block::begin(*rNode.data);
- std::advance(it, nOffset);
- sc::formula_block::const_iterator itEnd = it;
- std::advance(itEnd, nDataSize);
- for (; it != itEnd; ++it)
- {
- ScFormulaCell& rCell = const_cast<ScFormulaCell&>(**it);
- if (rCell.IsValueNoError())
- ++mnCount;
- }
- }
- break;
- default:
- ;
- }
- }
-
- size_t getCount() const { return mnCount; }
-};
-
-}
-
-double ScColumn::SumNumericCells( sc::ColumnBlockConstPosition& rPos, SCROW nRow1, SCROW nRow2 ) const
-{
- NumericCellAccumulator aFunc;
- rPos.miCellPos = sc::ParseFormulaNumeric(rPos.miCellPos, maCells, nRow1, nRow2, aFunc);
- return aFunc.getSum();
-}
-
-size_t ScColumn::CountNumericCells( sc::ColumnBlockConstPosition& rPos, SCROW nRow1, SCROW nRow2 ) const
-{
- NumericCellCounter aFunc;
- rPos.miCellPos = sc::ParseBlock(rPos.miCellPos, maCells, aFunc, nRow1, nRow2);
- return aFunc.getCount();
-}
-
void ScColumn::ClearSelectionItems( const sal_uInt16* pWhich,const ScMarkData& rMark )
{
SCROW nTop;
diff --git a/sc/source/core/tool/interpr6.cxx b/sc/source/core/tool/interpr6.cxx
index e31a062..03d87a9 100644
--- a/sc/source/core/tool/interpr6.cxx
+++ b/sc/source/core/tool/interpr6.cxx
@@ -24,6 +24,7 @@
#include "document.hxx"
#include "cellvalue.hxx"
#include "dociter.hxx"
+#include "mtvcellfunc.hxx"
#include "formula/token.hxx"
#include <rtl/logfile.hxx>
@@ -213,6 +214,62 @@ double ScInterpreter::GetGammaDist( double fX, double fAlpha, double fLambda )
namespace {
+class NumericCellAccumulator
+{
+ double mfSum;
+public:
+ NumericCellAccumulator() : mfSum(0.0) {}
+
+ void operator() (size_t, double fVal)
+ {
+ mfSum += fVal;
+ }
+
+ void operator() (size_t, const ScFormulaCell* pCell)
+ {
+ ScFormulaCell& rCell = const_cast<ScFormulaCell&>(*pCell);
+ if (rCell.IsValue())
+ mfSum += rCell.GetValue();
+ }
+
+ double getSum() const { return mfSum; }
+};
+
+class NumericCellCounter
+{
+ size_t mnCount;
+public:
+ NumericCellCounter() : mnCount(0) {}
+
+ void operator() (const sc::CellStoreType::value_type& rNode, size_t nOffset, size_t nDataSize)
+ {
+ switch (rNode.type)
+ {
+ case sc::element_type_numeric:
+ mnCount += nDataSize;
+ break;
+ case sc::element_type_formula:
+ {
+ sc::formula_block::const_iterator it = sc::formula_block::begin(*rNode.data);
+ std::advance(it, nOffset);
+ sc::formula_block::const_iterator itEnd = it;
+ std::advance(itEnd, nDataSize);
+ for (; it != itEnd; ++it)
+ {
+ ScFormulaCell& rCell = const_cast<ScFormulaCell&>(**it);
+ if (rCell.IsValueNoError())
+ ++mnCount;
+ }
+ }
+ break;
+ default:
+ ;
+ }
+ }
+
+ size_t getCount() const { return mnCount; }
+};
+
class FuncCount : public sc::ColumnSpanSet::ColumnAction
{
sc::ColumnBlockConstPosition maPos;
@@ -234,7 +291,9 @@ public:
if (!bVal)
return;
- mnCount += mpCol->CountNumericCells(maPos, nRow1, nRow2);
+ NumericCellCounter aFunc;
+ maPos.miCellPos = sc::ParseBlock(maPos.miCellPos, mpCol->GetCellStore(), aFunc, nRow1, nRow2);
+ mnCount += aFunc.getCount();
mnNumFmt = mpCol->GetNumberFormat(nRow2);
};
@@ -263,7 +322,9 @@ public:
if (!bVal)
return;
- mfSum += mpCol->SumNumericCells(maPos, nRow1, nRow2);
+ NumericCellAccumulator aFunc;
+ maPos.miCellPos = sc::ParseFormulaNumeric(maPos.miCellPos, mpCol->GetCellStore(), nRow1, nRow2, aFunc);
+ mfSum += aFunc.getSum();
mnNumFmt = mpCol->GetNumberFormat(nRow2);
};
commit 4277d968eb4407e22a3d4b467340a347e43e7ea9
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date: Tue Jul 2 15:43:57 2013 -0400
Move this to another file to distribute the compiler load.
interpr1.cxx is getting way too big....
Change-Id: Ic3e4879daebd09c8dcb86a42b305864dcc1c67c4
diff --git a/sc/source/core/tool/interpr1.cxx b/sc/source/core/tool/interpr1.cxx
index 93bcfef..8b738fa 100644
--- a/sc/source/core/tool/interpr1.cxx
+++ b/sc/source/core/tool/interpr1.cxx
@@ -58,8 +58,6 @@
#include "queryparam.hxx"
#include "queryentry.hxx"
#include "tokenarray.hxx"
-#include "columnspanset.hxx"
-#include "column.hxx"
#include <comphelper/processfactory.hxx>
#include <comphelper/string.hxx>
@@ -3852,771 +3850,6 @@ void ScInterpreter::ScMax( bool bTextAsZero )
PushDouble(nMax);
}
-namespace {
-
-class FuncCount : public sc::ColumnSpanSet::ColumnAction
-{
- sc::ColumnBlockConstPosition maPos;
- ScColumn* mpCol;
- size_t mnCount;
- sal_uInt32 mnNumFmt;
-
-public:
- FuncCount() : mnCount(0), mnNumFmt(0) {}
-
- virtual void startColumn(ScColumn* pCol)
- {
- mpCol = pCol;
- mpCol->InitBlockPosition(maPos);
- }
-
- virtual void execute(SCROW nRow1, SCROW nRow2, bool bVal)
- {
- if (!bVal)
- return;
-
- mnCount += mpCol->CountNumericCells(maPos, nRow1, nRow2);
- mnNumFmt = mpCol->GetNumberFormat(nRow2);
- };
-
- size_t getCount() const { return mnCount; }
- sal_uInt32 getNumberFormat() const { return mnNumFmt; }
-};
-
-class FuncSum : public sc::ColumnSpanSet::ColumnAction
-{
- sc::ColumnBlockConstPosition maPos;
- ScColumn* mpCol;
- double mfSum;
- sal_uInt32 mnNumFmt;
-
-public:
- FuncSum() : mfSum(0.0), mnNumFmt(0) {}
-
- virtual void startColumn(ScColumn* pCol)
- {
- mpCol = pCol;
- mpCol->InitBlockPosition(maPos);
- }
-
- virtual void execute(SCROW nRow1, SCROW nRow2, bool bVal)
- {
- if (!bVal)
- return;
-
- mfSum += mpCol->SumNumericCells(maPos, nRow1, nRow2);
- mnNumFmt = mpCol->GetNumberFormat(nRow2);
- };
-
- double getSum() const { return mfSum; }
- sal_uInt32 getNumberFormat() const { return mnNumFmt; }
-};
-
-void IterateMatrix(
- const ScMatrixRef& pMat, ScIterFunc eFunc, bool bTextAsZero,
- sal_uLong& rCount, short& rFuncFmtType, double& fRes, double& fMem, bool& bNull)
-{
- if (!pMat)
- return;
-
- rFuncFmtType = NUMBERFORMAT_NUMBER;
- switch (eFunc)
- {
- case ifAVERAGE:
- case ifSUM:
- {
- ScMatrix::IterateResult aRes = pMat->Sum(bTextAsZero);
- if (bNull)
- {
- bNull = false;
- fMem = aRes.mfFirst;
- fRes += aRes.mfRest;
- }
- else
- fRes += aRes.mfFirst + aRes.mfRest;
- rCount += aRes.mnCount;
- }
- break;
- case ifCOUNT:
- rCount += pMat->Count(bTextAsZero);
- break;
- case ifCOUNT2:
- rCount += pMat->Count(true);
- break;
- case ifPRODUCT:
- {
- ScMatrix::IterateResult aRes = pMat->Product(bTextAsZero);
- fRes *= aRes.mfRest;
- rCount += aRes.mnCount;
- }
- break;
- case ifSUMSQ:
- {
- ScMatrix::IterateResult aRes = pMat->SumSquare(bTextAsZero);
- fRes += aRes.mfRest;
- rCount += aRes.mnCount;
- }
- break;
- default:
- ;
- }
-}
-
-}
-
-double ScInterpreter::IterateParameters( ScIterFunc eFunc, bool bTextAsZero )
-{
- RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::IterateParameters" );
- short nParamCount = GetByte();
- double fRes = ( eFunc == ifPRODUCT ) ? 1.0 : 0.0;
- double fVal = 0.0;
- double fMem = 0.0; // first numeric value.
- bool bNull = true;
- sal_uLong nCount = 0;
- ScAddress aAdr;
- ScRange aRange;
- size_t nRefInList = 0;
- if ( nGlobalError && ( eFunc == ifCOUNT2 || eFunc == ifCOUNT ) )
- nGlobalError = 0;
- while (nParamCount-- > 0)
- {
- switch (GetStackType())
- {
- case svString:
- {
- if( eFunc == ifCOUNT )
- {
- String aStr( PopString() );
- sal_uInt32 nFIndex = 0; // damit default Land/Spr.
- if ( bTextAsZero || pFormatter->IsNumberFormat(aStr, nFIndex, fVal))
- nCount++;
- }
- else
- {
- switch ( eFunc )
- {
- case ifAVERAGE:
- case ifSUM:
- case ifSUMSQ:
- case ifPRODUCT:
- {
- if ( bTextAsZero )
- {
- Pop();
- nCount++;
- if ( eFunc == ifPRODUCT )
- fRes = 0.0;
- }
- else
- {
- while (nParamCount-- > 0)
- Pop();
- SetError( errNoValue );
- }
- }
- break;
- default:
- Pop();
- nCount++;
- }
- }
- }
- break;
- case svDouble :
- fVal = GetDouble();
- nCount++;
- 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
- }
- 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 );
- if ( nGlobalError && ( eFunc == ifCOUNT2 || eFunc == ifCOUNT ) )
- {
- nGlobalError = 0;
- if ( eFunc == ifCOUNT2 )
- ++nCount;
- break;
- }
- if (glSubTotal && pDok->RowFiltered( aAdr.Row(), aAdr.Tab()))
- {
- break;
- }
- ScRefCellValue aCell;
- aCell.assign(*pDok, aAdr);
- if (!aCell.isEmpty())
- {
- if( eFunc == ifCOUNT2 )
- {
- CellType eCellType = aCell.meType;
- if (eCellType != CELLTYPE_NONE)
- nCount++;
- if ( nGlobalError )
- nGlobalError = 0;
- }
- else if (aCell.hasNumeric())
- {
- nCount++;
- fVal = GetCellValue(aAdr, aCell);
- CurFmtToFuncFmt();
- 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 && aCell.hasString())
- {
- nCount++;
- if ( eFunc == ifPRODUCT )
- fRes = 0.0;
- }
- }
- }
- break;
- case svDoubleRef :
- case svRefList :
- {
- PopDoubleRef( aRange, nParamCount, nRefInList);
- if ( nGlobalError && ( eFunc == ifCOUNT2 || eFunc == ifCOUNT ) )
- {
- nGlobalError = 0;
- if ( eFunc == ifCOUNT2 )
- ++nCount;
- break;
- }
- if( eFunc == ifCOUNT2 )
- {
- ScCellIterator aIter( pDok, aRange, glSubTotal );
- for (bool bHas = aIter.first(); bHas; bHas = aIter.next())
- {
- if (!aIter.hasEmptyData())
- ++nCount;
- }
-
- if ( nGlobalError )
- nGlobalError = 0;
- }
- else
- {
- ScValueIterator aValIter( pDok, aRange, glSubTotal, bTextAsZero );
- sal_uInt16 nErr = 0;
- if (aValIter.GetFirst(fVal, nErr))
- {
- // placed the loop on the inside for performance reasons:
- aValIter.GetCurNumFmtInfo( nFuncFmtType, nFuncFmtIndex );
- switch( eFunc )
- {
- case ifAVERAGE:
- case ifSUM:
- do
- {
- SetError(nErr);
- if ( bNull && fVal != 0.0 )
- {
- bNull = false;
- fMem = fVal;
- }
- else
- fRes += fVal;
- nCount++;
- }
- while (aValIter.GetNext(fVal, nErr));
- break;
- case ifSUMSQ:
- do
- {
- SetError(nErr);
- fRes += fVal * fVal;
- nCount++;
- }
- while (aValIter.GetNext(fVal, nErr));
- break;
- case ifPRODUCT:
- do
- {
- SetError(nErr);
- fRes *= fVal;
- nCount++;
- }
- while (aValIter.GetNext(fVal, nErr));
- break;
- case ifCOUNT:
- do
- {
- if ( !nErr )
- nCount++;
- }
- while (aValIter.GetNext(fVal, nErr));
- break;
- default: ; // nothing
- }
- SetError( nErr );
- }
- }
- }
- break;
- case svExternalDoubleRef:
- {
- ScMatrixRef pMat;
- PopExternalDoubleRef(pMat);
- if (nGlobalError)
- break;
-
- IterateMatrix(pMat, eFunc, bTextAsZero, nCount, nFuncFmtType, fRes, fMem, bNull);
- }
- break;
- case svMatrix :
- {
- ScMatrixRef pMat = PopMatrix();
- IterateMatrix(pMat, eFunc, bTextAsZero, nCount, nFuncFmtType, fRes, fMem, bNull);
- }
- break;
- case svError:
- {
- PopError();
- if ( eFunc == ifCOUNT )
- {
- nGlobalError = 0;
- }
- else if ( eFunc == ifCOUNT2 )
- {
- nCount++;
- nGlobalError = 0;
- }
- }
- break;
- default :
- while (nParamCount-- > 0)
- PopError();
- SetError(errIllegalParameter);
- }
- }
- switch( eFunc )
- {
- case ifSUM: fRes = ::rtl::math::approxAdd( fRes, fMem ); break;
- case ifAVERAGE: fRes = div(::rtl::math::approxAdd( fRes, fMem ), nCount); break;
- case ifCOUNT2:
- case ifCOUNT: fRes = nCount; break;
- case ifPRODUCT: if ( !nCount ) fRes = 0.0; break;
- default: ; // nothing
- }
- // Bei Summen etc. macht ein bool-Ergebnis keinen Sinn
- // und Anzahl ist immer Number (#38345#)
- if( eFunc == ifCOUNT || nFuncFmtType == NUMBERFORMAT_LOGICAL )
- nFuncFmtType = NUMBERFORMAT_NUMBER;
- return fRes;
-}
-
-
-void ScInterpreter::ScSumSQ()
-{
- RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScSumSQ" );
- PushDouble( IterateParameters( ifSUMSQ ) );
-}
-
-
-void ScInterpreter::ScSum()
-{
- short nParamCount = GetByte();
- double fRes = 0.0;
- double fVal = 0.0;
- ScAddress aAdr;
- ScRange aRange;
- size_t nRefInList = 0;
- while (nParamCount-- > 0)
- {
- switch (GetStackType())
- {
- case svString:
- {
- while (nParamCount-- > 0)
- Pop();
- SetError( errNoValue );
- }
- break;
- case svDouble :
- fVal = GetDouble();
- fRes += fVal;
- nFuncFmtType = NUMBERFORMAT_NUMBER;
- break;
- case svExternalSingleRef:
- {
- ScExternalRefCache::TokenRef pToken;
- ScExternalRefCache::CellFormat aFmt;
- PopExternalSingleRef(pToken, &aFmt);
-
- if (!pToken)
- break;
-
- StackVar eType = pToken->GetType();
- if (eType == formula::svDouble)
- {
- fVal = pToken->GetDouble();
- if (aFmt.mbIsSet)
- {
- nFuncFmtType = aFmt.mnType;
- nFuncFmtIndex = aFmt.mnIndex;
- }
-
- fRes += fVal;
- }
- }
- break;
- case svSingleRef :
- {
- PopSingleRef( aAdr );
-
- if (glSubTotal && pDok->RowFiltered( aAdr.Row(), aAdr.Tab()))
- {
- break;
- }
- ScRefCellValue aCell;
- aCell.assign(*pDok, aAdr);
- if (!aCell.isEmpty())
- {
- if (aCell.hasNumeric())
- {
- fVal = GetCellValue(aAdr, aCell);
- CurFmtToFuncFmt();
- fRes += fVal;
- }
- }
- }
- break;
- case svDoubleRef :
- case svRefList :
- {
- PopDoubleRef( aRange, nParamCount, nRefInList);
-
- sc::ColumnSpanSet aSet(false);
- aSet.set(aRange, true);
- if (glSubTotal)
- // Skip all filtered rows and subtotal formula cells.
- pDok->MarkSubTotalCells(aSet, aRange, false);
-
- FuncSum aAction;
- aSet.executeColumnAction(*pDok, aAction);
- fRes = aAction.getSum();
-
- // Get the number format of the last iterated cell.
- nFuncFmtIndex = aAction.getNumberFormat();
- nFuncFmtType = pDok->GetFormatTable()->GetType(nFuncFmtIndex);
- }
- break;
- case svExternalDoubleRef:
- {
- ScMatrixRef pMat;
- PopExternalDoubleRef(pMat);
- if (nGlobalError)
- break;
-
- sal_uLong nCount = 0;
- double fMem = 0.0;
- bool bNull = true;
- IterateMatrix(pMat, ifSUM, false, nCount, nFuncFmtType, fRes, fMem, bNull);
- fRes += fMem;
- }
- break;
- case svMatrix :
- {
- ScMatrixRef pMat = PopMatrix();
- sal_uLong nCount = 0;
- double fMem = 0.0;
- bool bNull = true;
- IterateMatrix(pMat, ifSUM, false, nCount, nFuncFmtType, fRes, fMem, bNull);
- fRes += fMem;
- }
- break;
- case svError:
- {
- PopError();
- }
- break;
- default :
- while (nParamCount-- > 0)
- PopError();
- SetError(errIllegalParameter);
- }
- }
-
- if (nFuncFmtType == NUMBERFORMAT_LOGICAL)
- nFuncFmtType = NUMBERFORMAT_NUMBER;
-
- PushDouble(fRes);
-}
-
-
-void ScInterpreter::ScProduct()
-{
- RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScProduct" );
- PushDouble( IterateParameters( ifPRODUCT ) );
-}
-
-
-void ScInterpreter::ScAverage( bool bTextAsZero )
-{
- RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScAverage" );
- PushDouble( IterateParameters( ifAVERAGE, bTextAsZero ) );
-}
-
-void ScInterpreter::ScCount()
-{
- short nParamCount = GetByte();
- double fVal = 0.0;
- sal_uLong nCount = 0;
- ScAddress aAdr;
- ScRange aRange;
- size_t nRefInList = 0;
- if (nGlobalError)
- nGlobalError = 0;
-
- while (nParamCount-- > 0)
- {
- switch (GetStackType())
- {
- case svString:
- {
- String aStr( PopString() );
- sal_uInt32 nFIndex = 0; // damit default Land/Spr.
- if (pFormatter->IsNumberFormat(aStr, nFIndex, fVal))
- nCount++;
- }
- break;
- case svDouble :
- nCount++;
- nFuncFmtType = NUMBERFORMAT_NUMBER;
- break;
- case svExternalSingleRef:
- {
- ScExternalRefCache::TokenRef pToken;
- ScExternalRefCache::CellFormat aFmt;
- PopExternalSingleRef(pToken, &aFmt);
- if (nGlobalError)
- {
- nGlobalError = 0;
- break;
- }
-
- if (!pToken)
- break;
-
- StackVar eType = pToken->GetType();
- if (eType == formula::svDouble)
- {
- nCount++;
- if (aFmt.mbIsSet)
- {
- nFuncFmtType = aFmt.mnType;
- nFuncFmtIndex = aFmt.mnIndex;
- }
-
- if (nGlobalError)
- {
- nGlobalError = 0;
- nCount--;
- }
- }
- }
- break;
- case svSingleRef :
- {
- PopSingleRef( aAdr );
- if (nGlobalError)
- {
- nGlobalError = 0;
- break;
- }
- if (glSubTotal && pDok->RowFiltered( aAdr.Row(), aAdr.Tab()))
- {
- break;
- }
- ScRefCellValue aCell;
- aCell.assign(*pDok, aAdr);
- if (!aCell.isEmpty())
- {
- if (aCell.hasNumeric())
- {
- nCount++;
- CurFmtToFuncFmt();
- if (nGlobalError)
- {
- nGlobalError = 0;
- nCount--;
- }
- }
- }
- }
- break;
- case svDoubleRef :
- case svRefList :
- {
- PopDoubleRef( aRange, nParamCount, nRefInList);
- if (nGlobalError)
- {
- nGlobalError = 0;
- break;
- }
-
- sc::ColumnSpanSet aSet(false);
- aSet.set(aRange, true);
- if (glSubTotal)
- // Skip all filtered rows and subtotal formula cells.
- pDok->MarkSubTotalCells(aSet, aRange, false);
-
- FuncCount aAction;
- aSet.executeColumnAction(*pDok, aAction);
- nCount = aAction.getCount();
-
- // Get the number format of the last iterated cell.
- nFuncFmtIndex = aAction.getNumberFormat();
- nFuncFmtType = pDok->GetFormatTable()->GetType(nFuncFmtIndex);
- }
- break;
- case svExternalDoubleRef:
- {
- ScMatrixRef pMat;
- PopExternalDoubleRef(pMat);
- if (nGlobalError)
- break;
-
- double fMem = 0.0, fRes = 0.0;
- bool bNull = true;
- IterateMatrix(pMat, ifCOUNT, false, nCount, nFuncFmtType, fRes, fMem, bNull);
- }
- break;
- case svMatrix :
- {
- ScMatrixRef pMat = PopMatrix();
- double fMem = 0.0, fRes = 0.0;
- bool bNull = true;
- IterateMatrix(pMat, ifCOUNT, false, nCount, nFuncFmtType, fRes, fMem, bNull);
- }
- break;
- case svError:
- {
- PopError();
- nGlobalError = 0;
- }
- break;
- default :
- while (nParamCount-- > 0)
- PopError();
- SetError(errIllegalParameter);
- }
- }
-
- nFuncFmtType = NUMBERFORMAT_NUMBER;
-
- PushDouble(nCount);
-}
-
-
-void ScInterpreter::ScCount2()
-{
- RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScCount2" );
- PushDouble( IterateParameters( ifCOUNT2 ) );
-}
-
-
void ScInterpreter::GetStVarParams( double& rVal, double& rValCount,
bool bTextAsZero )
{
diff --git a/sc/source/core/tool/interpr6.cxx b/sc/source/core/tool/interpr6.cxx
index 7f712e3..e31a062 100644
--- a/sc/source/core/tool/interpr6.cxx
+++ b/sc/source/core/tool/interpr6.cxx
@@ -18,8 +18,17 @@
*/
-#include <rtl/logfile.hxx>
#include "interpre.hxx"
+#include "columnspanset.hxx"
+#include "column.hxx"
+#include "document.hxx"
+#include "cellvalue.hxx"
+#include "dociter.hxx"
+
+#include "formula/token.hxx"
+#include <rtl/logfile.hxx>
+
+using namespace formula;
double const fHalfMachEps = 0.5 * ::std::numeric_limits<double>::epsilon();
@@ -202,4 +211,768 @@ double ScInterpreter::GetGammaDist( double fX, double fAlpha, double fLambda )
return GetLowRegIGamma( fAlpha, fX / fLambda);
}
+namespace {
+
+class FuncCount : public sc::ColumnSpanSet::ColumnAction
+{
+ sc::ColumnBlockConstPosition maPos;
+ ScColumn* mpCol;
+ size_t mnCount;
+ sal_uInt32 mnNumFmt;
+
+public:
+ FuncCount() : mnCount(0), mnNumFmt(0) {}
+
+ virtual void startColumn(ScColumn* pCol)
+ {
+ mpCol = pCol;
+ mpCol->InitBlockPosition(maPos);
+ }
+
+ virtual void execute(SCROW nRow1, SCROW nRow2, bool bVal)
+ {
+ if (!bVal)
+ return;
+
+ mnCount += mpCol->CountNumericCells(maPos, nRow1, nRow2);
+ mnNumFmt = mpCol->GetNumberFormat(nRow2);
+ };
+
+ size_t getCount() const { return mnCount; }
+ sal_uInt32 getNumberFormat() const { return mnNumFmt; }
+};
+
+class FuncSum : public sc::ColumnSpanSet::ColumnAction
+{
+ sc::ColumnBlockConstPosition maPos;
+ ScColumn* mpCol;
+ double mfSum;
+ sal_uInt32 mnNumFmt;
+
+public:
+ FuncSum() : mfSum(0.0), mnNumFmt(0) {}
+
+ virtual void startColumn(ScColumn* pCol)
+ {
+ mpCol = pCol;
+ mpCol->InitBlockPosition(maPos);
+ }
+
+ virtual void execute(SCROW nRow1, SCROW nRow2, bool bVal)
+ {
+ if (!bVal)
+ return;
+
+ mfSum += mpCol->SumNumericCells(maPos, nRow1, nRow2);
+ mnNumFmt = mpCol->GetNumberFormat(nRow2);
+ };
+
+ double getSum() const { return mfSum; }
+ sal_uInt32 getNumberFormat() const { return mnNumFmt; }
+};
+
+void IterateMatrix(
+ const ScMatrixRef& pMat, ScIterFunc eFunc, bool bTextAsZero,
+ sal_uLong& rCount, short& rFuncFmtType, double& fRes, double& fMem, bool& bNull)
+{
+ if (!pMat)
+ return;
+
+ rFuncFmtType = NUMBERFORMAT_NUMBER;
+ switch (eFunc)
+ {
+ case ifAVERAGE:
+ case ifSUM:
+ {
+ ScMatrix::IterateResult aRes = pMat->Sum(bTextAsZero);
+ if (bNull)
+ {
+ bNull = false;
+ fMem = aRes.mfFirst;
+ fRes += aRes.mfRest;
+ }
+ else
+ fRes += aRes.mfFirst + aRes.mfRest;
+ rCount += aRes.mnCount;
+ }
+ break;
+ case ifCOUNT:
+ rCount += pMat->Count(bTextAsZero);
+ break;
+ case ifCOUNT2:
+ rCount += pMat->Count(true);
+ break;
+ case ifPRODUCT:
+ {
+ ScMatrix::IterateResult aRes = pMat->Product(bTextAsZero);
+ fRes *= aRes.mfRest;
+ rCount += aRes.mnCount;
+ }
+ break;
+ case ifSUMSQ:
+ {
+ ScMatrix::IterateResult aRes = pMat->SumSquare(bTextAsZero);
+ fRes += aRes.mfRest;
+ rCount += aRes.mnCount;
+ }
+ break;
+ default:
+ ;
+ }
+}
+
+}
+
+double ScInterpreter::IterateParameters( ScIterFunc eFunc, bool bTextAsZero )
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::IterateParameters" );
+ short nParamCount = GetByte();
+ double fRes = ( eFunc == ifPRODUCT ) ? 1.0 : 0.0;
+ double fVal = 0.0;
+ double fMem = 0.0; // first numeric value.
+ bool bNull = true;
+ sal_uLong nCount = 0;
+ ScAddress aAdr;
+ ScRange aRange;
+ size_t nRefInList = 0;
+ if ( nGlobalError && ( eFunc == ifCOUNT2 || eFunc == ifCOUNT ) )
+ nGlobalError = 0;
+ while (nParamCount-- > 0)
+ {
+ switch (GetStackType())
+ {
+ case svString:
+ {
+ if( eFunc == ifCOUNT )
+ {
+ String aStr( PopString() );
+ sal_uInt32 nFIndex = 0; // damit default Land/Spr.
+ if ( bTextAsZero || pFormatter->IsNumberFormat(aStr, nFIndex, fVal))
+ nCount++;
+ }
+ else
+ {
+ switch ( eFunc )
+ {
+ case ifAVERAGE:
+ case ifSUM:
+ case ifSUMSQ:
+ case ifPRODUCT:
+ {
+ if ( bTextAsZero )
+ {
+ Pop();
+ nCount++;
+ if ( eFunc == ifPRODUCT )
+ fRes = 0.0;
+ }
+ else
+ {
+ while (nParamCount-- > 0)
+ Pop();
+ SetError( errNoValue );
+ }
+ }
+ break;
+ default:
+ Pop();
+ nCount++;
+ }
+ }
+ }
+ break;
+ case svDouble :
+ fVal = GetDouble();
+ nCount++;
+ 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
+ }
+ 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 );
+ if ( nGlobalError && ( eFunc == ifCOUNT2 || eFunc == ifCOUNT ) )
+ {
+ nGlobalError = 0;
+ if ( eFunc == ifCOUNT2 )
+ ++nCount;
+ break;
+ }
+ if (glSubTotal && pDok->RowFiltered( aAdr.Row(), aAdr.Tab()))
+ {
+ break;
+ }
+ ScRefCellValue aCell;
+ aCell.assign(*pDok, aAdr);
+ if (!aCell.isEmpty())
+ {
+ if( eFunc == ifCOUNT2 )
+ {
+ CellType eCellType = aCell.meType;
+ if (eCellType != CELLTYPE_NONE)
+ nCount++;
+ if ( nGlobalError )
+ nGlobalError = 0;
+ }
+ else if (aCell.hasNumeric())
+ {
+ nCount++;
+ fVal = GetCellValue(aAdr, aCell);
+ CurFmtToFuncFmt();
+ 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 && aCell.hasString())
+ {
+ nCount++;
+ if ( eFunc == ifPRODUCT )
+ fRes = 0.0;
+ }
+ }
+ }
+ break;
+ case svDoubleRef :
+ case svRefList :
+ {
+ PopDoubleRef( aRange, nParamCount, nRefInList);
+ if ( nGlobalError && ( eFunc == ifCOUNT2 || eFunc == ifCOUNT ) )
+ {
+ nGlobalError = 0;
+ if ( eFunc == ifCOUNT2 )
+ ++nCount;
+ break;
+ }
+ if( eFunc == ifCOUNT2 )
+ {
+ ScCellIterator aIter( pDok, aRange, glSubTotal );
+ for (bool bHas = aIter.first(); bHas; bHas = aIter.next())
+ {
+ if (!aIter.hasEmptyData())
+ ++nCount;
+ }
+
+ if ( nGlobalError )
+ nGlobalError = 0;
+ }
+ else
+ {
+ ScValueIterator aValIter( pDok, aRange, glSubTotal, bTextAsZero );
+ sal_uInt16 nErr = 0;
+ if (aValIter.GetFirst(fVal, nErr))
+ {
+ // placed the loop on the inside for performance reasons:
+ aValIter.GetCurNumFmtInfo( nFuncFmtType, nFuncFmtIndex );
+ switch( eFunc )
+ {
+ case ifAVERAGE:
+ case ifSUM:
+ do
+ {
+ SetError(nErr);
+ if ( bNull && fVal != 0.0 )
+ {
+ bNull = false;
+ fMem = fVal;
+ }
+ else
+ fRes += fVal;
+ nCount++;
+ }
+ while (aValIter.GetNext(fVal, nErr));
+ break;
+ case ifSUMSQ:
+ do
+ {
+ SetError(nErr);
+ fRes += fVal * fVal;
+ nCount++;
+ }
+ while (aValIter.GetNext(fVal, nErr));
+ break;
+ case ifPRODUCT:
+ do
+ {
+ SetError(nErr);
+ fRes *= fVal;
+ nCount++;
+ }
+ while (aValIter.GetNext(fVal, nErr));
+ break;
+ case ifCOUNT:
+ do
+ {
+ if ( !nErr )
+ nCount++;
+ }
+ while (aValIter.GetNext(fVal, nErr));
+ break;
+ default: ; // nothing
+ }
+ SetError( nErr );
+ }
+ }
+ }
+ break;
+ case svExternalDoubleRef:
+ {
+ ScMatrixRef pMat;
+ PopExternalDoubleRef(pMat);
+ if (nGlobalError)
+ break;
+
+ IterateMatrix(pMat, eFunc, bTextAsZero, nCount, nFuncFmtType, fRes, fMem, bNull);
+ }
+ break;
+ case svMatrix :
+ {
+ ScMatrixRef pMat = PopMatrix();
+ IterateMatrix(pMat, eFunc, bTextAsZero, nCount, nFuncFmtType, fRes, fMem, bNull);
+ }
+ break;
+ case svError:
+ {
+ PopError();
+ if ( eFunc == ifCOUNT )
+ {
+ nGlobalError = 0;
+ }
+ else if ( eFunc == ifCOUNT2 )
+ {
+ nCount++;
+ nGlobalError = 0;
+ }
+ }
+ break;
+ default :
+ while (nParamCount-- > 0)
+ PopError();
+ SetError(errIllegalParameter);
+ }
+ }
+ switch( eFunc )
+ {
+ case ifSUM: fRes = ::rtl::math::approxAdd( fRes, fMem ); break;
+ case ifAVERAGE: fRes = div(::rtl::math::approxAdd( fRes, fMem ), nCount); break;
+ case ifCOUNT2:
+ case ifCOUNT: fRes = nCount; break;
+ case ifPRODUCT: if ( !nCount ) fRes = 0.0; break;
+ default: ; // nothing
+ }
+ // Bei Summen etc. macht ein bool-Ergebnis keinen Sinn
+ // und Anzahl ist immer Number (#38345#)
+ if( eFunc == ifCOUNT || nFuncFmtType == NUMBERFORMAT_LOGICAL )
+ nFuncFmtType = NUMBERFORMAT_NUMBER;
+ return fRes;
+}
+
+
+void ScInterpreter::ScSumSQ()
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScSumSQ" );
+ PushDouble( IterateParameters( ifSUMSQ ) );
+}
+
+
+void ScInterpreter::ScSum()
+{
+ short nParamCount = GetByte();
+ double fRes = 0.0;
+ double fVal = 0.0;
+ ScAddress aAdr;
+ ScRange aRange;
+ size_t nRefInList = 0;
+ while (nParamCount-- > 0)
+ {
+ switch (GetStackType())
+ {
+ case svString:
+ {
+ while (nParamCount-- > 0)
+ Pop();
+ SetError( errNoValue );
+ }
+ break;
+ case svDouble :
+ fVal = GetDouble();
+ fRes += fVal;
+ nFuncFmtType = NUMBERFORMAT_NUMBER;
+ break;
+ case svExternalSingleRef:
+ {
+ ScExternalRefCache::TokenRef pToken;
+ ScExternalRefCache::CellFormat aFmt;
+ PopExternalSingleRef(pToken, &aFmt);
+
+ if (!pToken)
+ break;
+
+ StackVar eType = pToken->GetType();
+ if (eType == formula::svDouble)
+ {
+ fVal = pToken->GetDouble();
+ if (aFmt.mbIsSet)
+ {
+ nFuncFmtType = aFmt.mnType;
+ nFuncFmtIndex = aFmt.mnIndex;
+ }
+
+ fRes += fVal;
+ }
+ }
+ break;
+ case svSingleRef :
+ {
+ PopSingleRef( aAdr );
+
+ if (glSubTotal && pDok->RowFiltered( aAdr.Row(), aAdr.Tab()))
+ {
+ break;
+ }
+ ScRefCellValue aCell;
+ aCell.assign(*pDok, aAdr);
+ if (!aCell.isEmpty())
+ {
+ if (aCell.hasNumeric())
+ {
+ fVal = GetCellValue(aAdr, aCell);
+ CurFmtToFuncFmt();
+ fRes += fVal;
+ }
+ }
+ }
+ break;
+ case svDoubleRef :
+ case svRefList :
+ {
+ PopDoubleRef( aRange, nParamCount, nRefInList);
+
+ sc::ColumnSpanSet aSet(false);
+ aSet.set(aRange, true);
+ if (glSubTotal)
+ // Skip all filtered rows and subtotal formula cells.
+ pDok->MarkSubTotalCells(aSet, aRange, false);
+
+ FuncSum aAction;
+ aSet.executeColumnAction(*pDok, aAction);
+ fRes = aAction.getSum();
+
+ // Get the number format of the last iterated cell.
+ nFuncFmtIndex = aAction.getNumberFormat();
+ nFuncFmtType = pDok->GetFormatTable()->GetType(nFuncFmtIndex);
+ }
+ break;
+ case svExternalDoubleRef:
+ {
+ ScMatrixRef pMat;
+ PopExternalDoubleRef(pMat);
+ if (nGlobalError)
+ break;
+
+ sal_uLong nCount = 0;
+ double fMem = 0.0;
+ bool bNull = true;
+ IterateMatrix(pMat, ifSUM, false, nCount, nFuncFmtType, fRes, fMem, bNull);
+ fRes += fMem;
+ }
+ break;
+ case svMatrix :
+ {
+ ScMatrixRef pMat = PopMatrix();
+ sal_uLong nCount = 0;
+ double fMem = 0.0;
+ bool bNull = true;
+ IterateMatrix(pMat, ifSUM, false, nCount, nFuncFmtType, fRes, fMem, bNull);
+ fRes += fMem;
+ }
+ break;
+ case svError:
+ {
+ PopError();
+ }
+ break;
+ default :
+ while (nParamCount-- > 0)
+ PopError();
+ SetError(errIllegalParameter);
+ }
+ }
+
+ if (nFuncFmtType == NUMBERFORMAT_LOGICAL)
+ nFuncFmtType = NUMBERFORMAT_NUMBER;
+
+ PushDouble(fRes);
+}
+
+
+void ScInterpreter::ScProduct()
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScProduct" );
+ PushDouble( IterateParameters( ifPRODUCT ) );
+}
+
+
+void ScInterpreter::ScAverage( bool bTextAsZero )
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScAverage" );
+ PushDouble( IterateParameters( ifAVERAGE, bTextAsZero ) );
+}
+
+void ScInterpreter::ScCount()
+{
+ short nParamCount = GetByte();
+ double fVal = 0.0;
+ sal_uLong nCount = 0;
+ ScAddress aAdr;
+ ScRange aRange;
+ size_t nRefInList = 0;
+ if (nGlobalError)
+ nGlobalError = 0;
+
+ while (nParamCount-- > 0)
+ {
+ switch (GetStackType())
+ {
+ case svString:
+ {
+ String aStr( PopString() );
+ sal_uInt32 nFIndex = 0; // damit default Land/Spr.
+ if (pFormatter->IsNumberFormat(aStr, nFIndex, fVal))
+ nCount++;
+ }
+ break;
+ case svDouble :
+ nCount++;
+ nFuncFmtType = NUMBERFORMAT_NUMBER;
+ break;
+ case svExternalSingleRef:
+ {
+ ScExternalRefCache::TokenRef pToken;
+ ScExternalRefCache::CellFormat aFmt;
+ PopExternalSingleRef(pToken, &aFmt);
+ if (nGlobalError)
+ {
+ nGlobalError = 0;
+ break;
+ }
+
+ if (!pToken)
+ break;
+
+ StackVar eType = pToken->GetType();
+ if (eType == formula::svDouble)
+ {
+ nCount++;
+ if (aFmt.mbIsSet)
+ {
+ nFuncFmtType = aFmt.mnType;
+ nFuncFmtIndex = aFmt.mnIndex;
+ }
+
+ if (nGlobalError)
+ {
+ nGlobalError = 0;
+ nCount--;
+ }
+ }
+ }
+ break;
+ case svSingleRef :
+ {
+ PopSingleRef( aAdr );
+ if (nGlobalError)
+ {
+ nGlobalError = 0;
+ break;
+ }
+ if (glSubTotal && pDok->RowFiltered( aAdr.Row(), aAdr.Tab()))
+ {
+ break;
+ }
+ ScRefCellValue aCell;
+ aCell.assign(*pDok, aAdr);
+ if (!aCell.isEmpty())
+ {
+ if (aCell.hasNumeric())
+ {
+ nCount++;
+ CurFmtToFuncFmt();
+ if (nGlobalError)
+ {
+ nGlobalError = 0;
+ nCount--;
+ }
+ }
+ }
+ }
+ break;
+ case svDoubleRef :
+ case svRefList :
+ {
+ PopDoubleRef( aRange, nParamCount, nRefInList);
+ if (nGlobalError)
+ {
+ nGlobalError = 0;
+ break;
+ }
+
+ sc::ColumnSpanSet aSet(false);
+ aSet.set(aRange, true);
+ if (glSubTotal)
+ // Skip all filtered rows and subtotal formula cells.
+ pDok->MarkSubTotalCells(aSet, aRange, false);
+
+ FuncCount aAction;
+ aSet.executeColumnAction(*pDok, aAction);
+ nCount = aAction.getCount();
+
+ // Get the number format of the last iterated cell.
+ nFuncFmtIndex = aAction.getNumberFormat();
+ nFuncFmtType = pDok->GetFormatTable()->GetType(nFuncFmtIndex);
+ }
+ break;
+ case svExternalDoubleRef:
+ {
+ ScMatrixRef pMat;
+ PopExternalDoubleRef(pMat);
+ if (nGlobalError)
+ break;
+
+ double fMem = 0.0, fRes = 0.0;
+ bool bNull = true;
+ IterateMatrix(pMat, ifCOUNT, false, nCount, nFuncFmtType, fRes, fMem, bNull);
+ }
+ break;
+ case svMatrix :
+ {
+ ScMatrixRef pMat = PopMatrix();
+ double fMem = 0.0, fRes = 0.0;
+ bool bNull = true;
+ IterateMatrix(pMat, ifCOUNT, false, nCount, nFuncFmtType, fRes, fMem, bNull);
+ }
+ break;
+ case svError:
+ {
+ PopError();
+ nGlobalError = 0;
+ }
+ break;
+ default :
+ while (nParamCount-- > 0)
+ PopError();
+ SetError(errIllegalParameter);
+ }
+ }
+
+ nFuncFmtType = NUMBERFORMAT_NUMBER;
+
+ PushDouble(nCount);
+}
+
+
+void ScInterpreter::ScCount2()
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScCount2" );
+ PushDouble( IterateParameters( ifCOUNT2 ) );
+}
+
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
commit 6f86d931b4266d00fec75c0124ac9fc3026a4f1b
Author: Frédéric Wang <fred.wang at free.fr>
Date: Sun Jun 30 17:34:40 2013 +0200
fdo#66283 - MathML export: remove useless mrow/mstyle with font commands
Change-Id: I57870a22ef915950fe177dcb75ab31a25f2520c8
Reviewed-on: https://gerrit.libreoffice.org/4634
Reviewed-by: Khaled Hosny <khaledhosny at eglug.org>
Tested-by: Khaled Hosny <khaledhosny at eglug.org>
diff --git a/starmath/source/mathmlexport.cxx b/starmath/source/mathmlexport.cxx
index a10765e..a523693 100644
--- a/starmath/source/mathmlexport.cxx
+++ b/starmath/source/mathmlexport.cxx
@@ -780,13 +780,15 @@ void SmXMLExport::ExportUnaryHorizontal(const SmNode *pNode, int nLevel)
ExportExpression(pNode, nLevel);
}
-void SmXMLExport::ExportExpression(const SmNode *pNode, int nLevel)
+void SmXMLExport::ExportExpression(const SmNode *pNode, int nLevel,
+ bool bNoMrowContainer /*=false*/)
{
SvXMLElementExport *pRow=0;
sal_uLong nSize = pNode->GetNumSubNodes();
// #i115443: nodes of type expression always need to be grouped with mrow statement
- if (nSize > 1 || (pNode && pNode->GetType() == NEXPRESSION))
+ if (!bNoMrowContainer &&
+ (nSize > 1 || (pNode && pNode->GetType() == NEXPRESSION)))
pRow = new SvXMLElementExport(*this, XML_NAMESPACE_MATH, XML_MROW, sal_True, sal_True);
for (sal_uInt16 i = 0; i < nSize; i++)
@@ -1290,8 +1292,6 @@ static bool lcl_HasEffectOnMathvariant( const SmTokenType eType )
void SmXMLExport::ExportFont(const SmNode *pNode, int nLevel)
{
- SvXMLElementExport *pElement = 0;
-
//
// gather the mathvariant attribut relevant data from all
// successively following SmFontNodes...
@@ -1328,10 +1328,8 @@ void SmXMLExport::ExportFont(const SmNode *pNode, int nLevel)
switch (pNode->GetToken().eType)
{
- //wrap a phantom element around everything*/
case TPHANTOM:
- pElement = new SvXMLElementExport(*this, XML_NAMESPACE_MATH,
- XML_MPHANTOM, sal_True,sal_True);
+ // No attribute needed. An <mphantom> element will be used below.
break;
case TBLACK:
AddAttribute(XML_NAMESPACE_MATH, XML_COLOR, XML_BLACK);
@@ -1455,15 +1453,15 @@ void SmXMLExport::ExportFont(const SmNode *pNode, int nLevel)
break;
}
- //for now we will just always export with a style and not worry about
- //anyone else for the moment.
{
- //wrap a style around it
- SvXMLElementExport aStyle(*this, XML_NAMESPACE_MATH, XML_MSTYLE, sal_True,sal_True);
- ExportExpression(pNode, nLevel);
+ // Wrap everything in an <mphantom> or <mstyle> element. These elements
+ // are mrow-like, so ExportExpression doesn't need to add an explicit
+ // <mrow> element. See #fdo 66283.
+ SvXMLElementExport aElement(*this, XML_NAMESPACE_MATH,
+ pNode->GetToken().eType == TPHANTOM ? XML_MPHANTOM : XML_MSTYLE,
+ sal_True, sal_True);
+ ExportExpression(pNode, nLevel, true);
}
-
- delete pElement;
}
diff --git a/starmath/source/mathmlexport.hxx b/starmath/source/mathmlexport.hxx
index 3cbaaae..d7ca75a 100644
--- a/starmath/source/mathmlexport.hxx
+++ b/starmath/source/mathmlexport.hxx
@@ -84,7 +84,8 @@ protected:
void ExportNodes(const SmNode *pNode, int nLevel);
void ExportTable(const SmNode *pNode, int nLevel);
void ExportLine(const SmNode *pNode, int nLevel);
- void ExportExpression(const SmNode *pNode, int nLevel);
+ void ExportExpression(const SmNode *pNode, int nLevel,
+ bool bNoMrowContainer = false);
void ExportText(const SmNode *pNode, int nLevel);
void ExportMath(const SmNode *pNode, int nLevel);
void ExportPolygon(const SmNode *pNode, int nLevel);
commit d2a71b952850cdf1a7efc5c0f86df9864201a950
Author: Michael Meeks <michael.meeks at suse.com>
Date: Tue Jul 2 21:58:12 2013 +0100
fdo#46990 - re-work new desktop checks, guard against NULL DESKTOP_SESSION.
Change-Id: Ia3e408b372989b757f7dde080849e38d315d53cd
diff --git a/vcl/unx/generic/desktopdetect/desktopdetector.cxx b/vcl/unx/generic/desktopdetect/desktopdetector.cxx
index a133449..d2d91de 100644
--- a/vcl/unx/generic/desktopdetect/desktopdetector.cxx
+++ b/vcl/unx/generic/desktopdetect/desktopdetector.cxx
@@ -42,11 +42,8 @@ static bool is_gnome_desktop( Display* pDisplay )
// warning: these checks are coincidental, GNOME does not
// explicitly advertise itself
-
- if ( "gnome" == getenv( "DESKTOP_SESSION" ) || NULL != getenv( "GNOME_DESKTOP_SESSION_ID" ) )
- {
+ if ( NULL != getenv( "GNOME_DESKTOP_SESSION_ID" ) )
ret = true;
- }
if( ! ret )
{
@@ -121,24 +118,6 @@ static bool is_gnome_desktop( Display* pDisplay )
return ret;
}
-static bool is_xfce_desktop( Display* pDisplay )
-{
- if ( "xfce" == getenv( "DESKTOP_SESSION" ) )
- {
- return true;
- }
- return false;
-}
-
-static bool is_mate_desktop( Display* pDisplay )
-{
- if ( "mate" == getenv( "DESKTOP_SESSION" ) )
- {
- return true;
- }
- return false;
-}
-
static bool bWasXError = false;
static inline bool WasXError()
@@ -369,18 +348,30 @@ DESKTOP_DETECTOR_PUBLIC DesktopType get_desktop_environment()
XErrorHandler pOldHdl = XSetErrorHandler( autodect_error_handler );
- if ( is_tde_desktop( pDisplay ) )
- ret = DESKTOP_TDE;
+ const char *pSession;
+ OString aDesktopSession;
+
+ if ( ( pSession = getenv( "DESKTOP_SESSION" ) ) )
+ aDesktopSession = OString( pSession, strlen( pSession ) );
+
+ // fast environment variable checks
+ if ( aDesktopSession.equalsIgnoreAsciiCase( "gnome" ) )
+ ret = DESKTOP_GNOME;
+ else if ( aDesktopSession.equalsIgnoreAsciiCase( "mate" ) )
+ ret = DESKTOP_MATE;
+ else if ( aDesktopSession.equalsIgnoreAsciiCase( "xfce" ) )
+ ret = DESKTOP_XFCE;
+
+ // these guys can be slower, with X property fetches,
+ // round-trips etc. and so are done later.
else if ( is_kde4_desktop( pDisplay ) )
ret = DESKTOP_KDE4;
else if ( is_gnome_desktop( pDisplay ) )
ret = DESKTOP_GNOME;
- else if ( is_xfce_desktop( pDisplay ) )
- ret = DESKTOP_XFCE;
- else if ( is_mate_desktop( pDisplay ) )
- ret = DESKTOP_MATE;
else if ( is_kde_desktop( pDisplay ) )
ret = DESKTOP_KDE;
+ else if ( is_tde_desktop( pDisplay ) )
+ ret = DESKTOP_TDE;
else
ret = DESKTOP_UNKNOWN;
diff --git a/vcl/unx/generic/plugadapt/salplug.cxx b/vcl/unx/generic/plugadapt/salplug.cxx
index fba45f1..4cb49f9 100644
--- a/vcl/unx/generic/plugadapt/salplug.cxx
+++ b/vcl/unx/generic/plugadapt/salplug.cxx
@@ -188,7 +188,9 @@ static SalInstance* autodetect_plugin()
// no server at all: dummy plugin
if ( desktop == DESKTOP_NONE )
pList = pHeadlessFallbackList;
- else if ( desktop == DESKTOP_GNOME || desktop == DESKTOP_XFCE || desktop == DESKTOP_MATE )
+ else if ( desktop == DESKTOP_GNOME ||
+ desktop == DESKTOP_XFCE ||
+ desktop == DESKTOP_MATE )
pList = pStandardFallbackList;
else if( desktop == DESKTOP_TDE )
pList = pTDEFallbackList;
@@ -287,7 +289,11 @@ void SalAbort( const OUString& rErrorText, bool bDumpCore )
_exit(1);
}
-static const char * desktop_strings[] = { "none", "unknown", "GNOME", "XFCE", "MATE", "TDE", "KDE", "KDE4" };
+// Order to match desktops.hxx' DesktopType
+static const char * desktop_strings[] = {
+ "none", "unknown", "GNOME",
+ "XFCE", "MATE", "TDE",
+ "KDE", "KDE4" };
const OUString& SalGetDesktopEnvironment()
{
commit f31fad32005c6709eaae71b49af31264e585478a
Author: Pader Rezso <rezso at rezso.net>
Date: Tue Jul 2 21:23:56 2013 +0100
fdo#46990 - detect MATE and XFCE desktops.
Change-Id: Id72860fc2e7d6b40f4fcb96b8f504a4f86a335b1
diff --git a/vcl/inc/unx/desktops.hxx b/vcl/inc/unx/desktops.hxx
index c97d708..e41add4 100644
--- a/vcl/inc/unx/desktops.hxx
+++ b/vcl/inc/unx/desktops.hxx
@@ -24,6 +24,8 @@ enum DesktopType {
DESKTOP_NONE, // headless, i.e. no X connection at all
DESKTOP_UNKNOWN, // unknown desktop, simple WM, etc.
DESKTOP_GNOME,
+ DESKTOP_XFCE,
+ DESKTOP_MATE,
DESKTOP_KDE,
DESKTOP_KDE4,
DESKTOP_TDE
diff --git a/vcl/unx/generic/desktopdetect/desktopdetector.cxx b/vcl/unx/generic/desktopdetect/desktopdetector.cxx
index f1d6c26..a133449 100644
--- a/vcl/unx/generic/desktopdetect/desktopdetector.cxx
+++ b/vcl/unx/generic/desktopdetect/desktopdetector.cxx
@@ -43,8 +43,10 @@ static bool is_gnome_desktop( Display* pDisplay )
// warning: these checks are coincidental, GNOME does not
// explicitly advertise itself
- if ( NULL != getenv( "GNOME_DESKTOP_SESSION_ID" ) )
+ if ( "gnome" == getenv( "DESKTOP_SESSION" ) || NULL != getenv( "GNOME_DESKTOP_SESSION_ID" ) )
+ {
ret = true;
+ }
if( ! ret )
{
@@ -119,6 +121,24 @@ static bool is_gnome_desktop( Display* pDisplay )
return ret;
}
+static bool is_xfce_desktop( Display* pDisplay )
+{
+ if ( "xfce" == getenv( "DESKTOP_SESSION" ) )
+ {
+ return true;
+ }
+ return false;
+}
+
+static bool is_mate_desktop( Display* pDisplay )
+{
+ if ( "mate" == getenv( "DESKTOP_SESSION" ) )
+ {
+ return true;
+ }
+ return false;
+}
+
static bool bWasXError = false;
static inline bool WasXError()
@@ -291,6 +311,10 @@ DESKTOP_DETECTOR_PUBLIC DesktopType get_desktop_environment()
return DESKTOP_KDE4;
if ( aOver.equalsIgnoreAsciiCase( "gnome" ) )
return DESKTOP_GNOME;
+ if ( aOver.equalsIgnoreAsciiCase( "xfce" ) )
+ return DESKTOP_XFCE;
+ if ( aOver.equalsIgnoreAsciiCase( "mate" ) )
+ return DESKTOP_MATE;
if ( aOver.equalsIgnoreAsciiCase( "kde" ) )
return DESKTOP_KDE;
if ( aOver.equalsIgnoreAsciiCase( "none" ) )
@@ -351,6 +375,10 @@ DESKTOP_DETECTOR_PUBLIC DesktopType get_desktop_environment()
ret = DESKTOP_KDE4;
else if ( is_gnome_desktop( pDisplay ) )
ret = DESKTOP_GNOME;
+ else if ( is_xfce_desktop( pDisplay ) )
+ ret = DESKTOP_XFCE;
+ else if ( is_mate_desktop( pDisplay ) )
+ ret = DESKTOP_MATE;
else if ( is_kde_desktop( pDisplay ) )
ret = DESKTOP_KDE;
else
diff --git a/vcl/unx/generic/plugadapt/salplug.cxx b/vcl/unx/generic/plugadapt/salplug.cxx
index 2eec717..fba45f1 100644
--- a/vcl/unx/generic/plugadapt/salplug.cxx
+++ b/vcl/unx/generic/plugadapt/salplug.cxx
@@ -188,7 +188,7 @@ static SalInstance* autodetect_plugin()
// no server at all: dummy plugin
if ( desktop == DESKTOP_NONE )
pList = pHeadlessFallbackList;
- else if ( desktop == DESKTOP_GNOME )
+ else if ( desktop == DESKTOP_GNOME || desktop == DESKTOP_XFCE || desktop == DESKTOP_MATE )
pList = pStandardFallbackList;
else if( desktop == DESKTOP_TDE )
pList = pTDEFallbackList;
@@ -287,7 +287,7 @@ void SalAbort( const OUString& rErrorText, bool bDumpCore )
_exit(1);
}
-static const char * desktop_strings[] = { "none", "unknown", "GNOME", "TDE", "KDE", "KDE4" };
+static const char * desktop_strings[] = { "none", "unknown", "GNOME", "XFCE", "MATE", "TDE", "KDE", "KDE4" };
const OUString& SalGetDesktopEnvironment()
{
commit 3887ba5677b1902fcf45f076d7a8e3ac96322dff
Author: Michael Meeks <michael.meeks at suse.com>
Date: Tue Jul 2 17:57:36 2013 +0100
Fix opencl path and linking issues on windows.
Change-Id: Ie39a3c02d6021ae200d6e3939ec9a14ed7f34d21
diff --git a/configure.ac b/configure.ac
index 66733ea..fdca180 100644
--- a/configure.ac
+++ b/configure.ac
@@ -9840,8 +9840,14 @@ elif test "z$with_opencl_sdk" = "z"; then
else
if test -d "$with_opencl_sdk/include"; then
ENABLE_OPENCL=TRUE
- OPENCL_CFLAGS="-I$with_opencl_sdk/include"
- OPENCL_LIBS="-L$with_opencl_sdk/lib/x86 -lOpenCL"
+ if test "$_os" = "WINNT"; then
+ PathFormat "$with_opencl_sdk"
+ OPENCL_CFLAGS="-I$formatted_path/include"
+ OPENCL_LIBS="-LIBPATH:$formatted_path/lib/x86 OpenCL.lib"
+ else
+ OPENCL_CFLAGS="-I$with_opencl_sdk/include"
+ OPENCL_LIBS="-L$with_opencl_sdk/lib/x86 -lOpenCL"
+ fi
AC_MSG_RESULT([found at path $with_opencl_sdk])
AC_DEFINE(HAVE_FEATURE_OPENCL)
else
commit 74b5f592dbbd499ef4c50601e92e393623244c4c
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date: Tue Jul 2 15:26:28 2013 -0400
Some feeble attempt to reduce dependency on token.hxx header.
But I didn't go far.
Change-Id: Iaf9cbac99812c1bf7d7f2db2ad5bb6231ea5e292
diff --git a/sc/inc/chart2uno.hxx b/sc/inc/chart2uno.hxx
index 6d53073..333a2db 100644
--- a/sc/inc/chart2uno.hxx
+++ b/sc/inc/chart2uno.hxx
@@ -23,7 +23,7 @@
#include "cellsuno.hxx" // for XModifyListenerArr_Impl / ScLinkListener
#include "rangelst.hxx"
#include "externalrefmgr.hxx"
-#include "token.hxx"
+#include "types.hxx"
#include "chartlis.hxx"
#include <svl/lstner.hxx>
diff --git a/sc/inc/types.hxx b/sc/inc/types.hxx
index 487afcd..445311e 100644
--- a/sc/inc/types.hxx
+++ b/sc/inc/types.hxx
@@ -10,6 +10,8 @@
#ifndef SC_TYPES_HXX
#define SC_TYPES_HXX
+#include "sal/types.h"
+
#include <boost/intrusive_ptr.hpp>
class ScMatrix;
diff --git a/sc/source/filter/inc/xichart.hxx b/sc/source/filter/inc/xichart.hxx
index c1a2cbc..308ca4c 100644
--- a/sc/source/filter/inc/xichart.hxx
+++ b/sc/source/filter/inc/xichart.hxx
@@ -28,7 +28,7 @@
#include <svl/itemset.hxx>
#include "rangelst.hxx"
-#include "token.hxx"
+#include "types.hxx"
#include "xlchart.hxx"
#include "xlstyle.hxx"
#include "xiescher.hxx"
commit 76f20ffd2f5aafe284fc52baac4b304d7e8edaca
Author: Armin Le Grand <alg at apache.org>
Date: Tue Jul 2 16:36:07 2013 +0000
Related: #i122594# Added same handling for outer SVG element
(cherry picked from commit d6dd461da975a4fcd7d58a1f03d0add9e5defa8b)
Conflicts:
svgio/source/svgreader/svgsvgnode.cxx
Change-Id: I99f5ce54a70d064ae83e56c0a23b77122dcc838c
diff --git a/svgio/source/svgreader/svgsvgnode.cxx b/svgio/source/svgreader/svgsvgnode.cxx
index 4aff559..0eb04dd 100644
--- a/svgio/source/svgreader/svgsvgnode.cxx
+++ b/svgio/source/svgreader/svgsvgnode.cxx
@@ -168,6 +168,64 @@ namespace svgio
{
if(getParent())
{
+ const bool bWidthIsRelative(!getWidth().isSet() || Unit_percent == getWidth().getUnit());
+ const bool bHeightIsRelative(!getWidth().isSet() || Unit_percent == getWidth().getUnit());
+ const SvgSvgNode* pParentSvgSvgNode = 0;
+ double fW(0.0);
+ double fH(0.0);
+
+ // #i122594# if width/height is not given, it's 100% (see 5.1.2 The svg element in SVG1.1 spec).
+ // If it is relative, the question is to what. The previous implementatin assumed relative to the
+ // local ViewBox which is implied by (4.2 Basic data types):
+ //
+ // "Note that the non-property <length> definition also allows a percentage unit identifier.
+ // The meaning of a percentage length value depends on the attribute for which the percentage
+ // length value has been specified. Two common cases are: (a) when a percentage length value
+ // represents a percentage of the viewport width or height (refer to the section that discusses
+ // units in general), and (b) when a percentage length value represents a percentage of the
+ // bounding box width or height on a given object (refer to the section that describes object
+ // bounding box units)."
+ //
+ // This is not closer specified for the SVG element itself as non-outmost element, but comparisons
+ // with common browsers shows that it's mostly interpreted relative to the viewBox of the parent.
+ // Adding code to search the parent SVG element and calculating width/height relative to it's
+ // viewBox width/height (and no longer to the local viewBox).
+ if(bWidthIsRelative || bHeightIsRelative)
+ {
+ for(const SvgNode* pParent = getParent(); pParent && !pParentSvgSvgNode; pParent = pParent->getParent())
+ {
+ pParentSvgSvgNode = dynamic_cast< const SvgSvgNode* >(pParent);
+ }
+ }
+
+ if(bWidthIsRelative)
+ {
+ fW = getWidth().isSet() ? getWidth().getNumber() * 0.01 : 1.0;
+
+ if(pParentSvgSvgNode)
+ {
+ fW *= pParentSvgSvgNode->getViewBox()->getWidth();
+ }
+ }
+ else
+ {
+ fW = getWidth().solve(*this, xcoordinate);
+ }
+
+ if(bHeightIsRelative)
+ {
+ fH = getHeight().isSet() ? getHeight().getNumber() * 0.01 : 1.0;
+
+ if(pParentSvgSvgNode)
+ {
+ fH *= pParentSvgSvgNode->getViewBox()->getHeight();
+ }
+ }
+ else
+ {
+ fH = getHeight().solve(*this, ycoordinate);
+ }
+
if(getViewBox())
{
// Svg defines that with no width or no height the viewBox content is empty,
@@ -177,64 +235,6 @@ namespace svgio
// create target range homing x,y, width and height as given
const double fX(getX().isSet() ? getX().solve(*this, xcoordinate) : 0.0);
const double fY(getY().isSet() ? getY().solve(*this, ycoordinate) : 0.0);
- const bool bWidthIsRelative(!getWidth().isSet() || Unit_percent == getWidth().getUnit());
- const bool bHeightIsRelative(!getWidth().isSet() || Unit_percent == getWidth().getUnit());
- const SvgSvgNode* pParentSvgSvgNode = 0;
- double fW(0.0);
- double fH(0.0);
-
- // #i122594# if width/height is not given, it's 100% (see 5.1.2 The svg element in SVG1.1 spec).
- // If it is relative, the question is to what. The previous implementatin assumed relative to the
- // local ViewBox which is implied by (4.2 Basic data types):
- //
- // "Note that the non-property <length> definition also allows a percentage unit identifier.
- // The meaning of a percentage length value depends on the attribute for which the percentage
- // length value has been specified. Two common cases are: (a) when a percentage length value
- // represents a percentage of the viewport width or height (refer to the section that discusses
- // units in general), and (b) when a percentage length value represents a percentage of the
- // bounding box width or height on a given object (refer to the section that describes object
- // bounding box units)."
- //
- // This is not closer specified for the SVG element itself as non-outmost element, but comparisons
- // with common browsers shows that it's mostly interpreted relative to the viewBox of the parent.
- // Adding code to search the parent SVG element and calculating width/height relative to it's
- // viewBox width/height (and no longer to the local viewBox).
- if(bWidthIsRelative || bHeightIsRelative)
- {
- for(const SvgNode* pParent = getParent(); pParent && !pParentSvgSvgNode; pParent = pParent->getParent())
- {
- pParentSvgSvgNode = dynamic_cast< const SvgSvgNode* >(pParent);
- }
- }
-
- if(bWidthIsRelative)
- {
- fW = getWidth().isSet() ? getWidth().getNumber() * 0.01 : 1.0;
-
- if(pParentSvgSvgNode)
- {
- fW *= pParentSvgSvgNode->getViewBox()->getWidth();
- }
- }
- else
- {
- fW = getWidth().solve(*this, xcoordinate);
- }
-
- if(bHeightIsRelative)
- {
- fH = getHeight().isSet() ? getHeight().getNumber() * 0.01 : 1.0;
-
- if(pParentSvgSvgNode)
... etc. - the rest is truncated
More information about the Libreoffice-commits
mailing list