summaryrefslogtreecommitdiff
path: root/sc/source/core/data/column4.cxx
diff options
context:
space:
mode:
authorKohei Yoshida <kohei.yoshida@collabora.com>2014-04-07 14:13:20 -0400
committerKohei Yoshida <kohei.yoshida@collabora.com>2014-04-07 14:43:16 -0400
commit355baf573425165cbc1c789a6271eb29940e1f76 (patch)
tree42050f8ac0a293b75e3745d511fe2e086e88cd42 /sc/source/core/data/column4.cxx
parent137c288978fb8f4aee259fabfdcb9252b1b011d3 (diff)
fdo#75741: Re-implement CompileNameFormula for formula groups.
Change-Id: I57e1e464ac5f7abc10ce5ea5752e036ddb6cf6d7
Diffstat (limited to 'sc/source/core/data/column4.cxx')
-rw-r--r--sc/source/core/data/column4.cxx151
1 files changed, 151 insertions, 0 deletions
diff --git a/sc/source/core/data/column4.cxx b/sc/source/core/data/column4.cxx
index 2f216233e800..7a360d09a673 100644
--- a/sc/source/core/data/column4.cxx
+++ b/sc/source/core/data/column4.cxx
@@ -16,18 +16,23 @@
#include <cellvalues.hxx>
#include <columnspanset.hxx>
#include <listenercontext.hxx>
+#include <tokenstringcontext.hxx>
#include <mtvcellfunc.hxx>
#include <clipcontext.hxx>
#include <attrib.hxx>
#include <patattr.hxx>
#include <docpool.hxx>
#include <conditio.hxx>
+#include <formulagroup.hxx>
+#include <tokenarray.hxx>
#include <svl/sharedstringpool.hxx>
#include <vector>
#include <cassert>
+#include <boost/shared_ptr.hpp>
+
bool ScColumn::IsMerged( SCROW nRow ) const
{
return pAttrArray->IsMerged(nRow);
@@ -544,4 +549,150 @@ void ScColumn::GetNotesInRange(SCROW nStartRow, SCROW nEndRow,
std::for_each(it, itEnd, NoteEntryCollector(rNotes, nTab, nCol, nStartRow, nEndRow));
}
+namespace {
+
+class PreRangeNameUpdateHandler
+{
+ ScDocument* mpDoc;
+ boost::shared_ptr<sc::EndListeningContext> mpEndListenCxt;
+ boost::shared_ptr<sc::CompileFormulaContext> mpCompileFormulaCxt;
+
+public:
+ PreRangeNameUpdateHandler( ScDocument* pDoc ) :
+ mpDoc(pDoc),
+ mpEndListenCxt(new sc::EndListeningContext(*pDoc)),
+ mpCompileFormulaCxt(new sc::CompileFormulaContext(pDoc)) {}
+
+ void operator() ( sc::FormulaGroupEntry& rEntry )
+ {
+ // Perform end listening, remove from formula tree, and set them up
+ // for re-compilation.
+
+ ScFormulaCell* pTop = NULL;
+
+ if (rEntry.mbShared)
+ {
+ // Only inspect the code from the top cell.
+ pTop = *rEntry.mpCells;
+ }
+ else
+ pTop = rEntry.mpCell;
+
+ ScTokenArray* pCode = pTop->GetCode();
+
+ boost::unordered_set<OpCode> aOps;
+ aOps.insert(ocBad);
+ aOps.insert(ocColRowName);
+ aOps.insert(ocName);
+ bool bRecompile = pCode->HasOpCodes(aOps);
+
+ if (bRecompile)
+ {
+ // Get the formula string.
+ OUString aFormula = pTop->GetFormula(*mpCompileFormulaCxt);
+ sal_Int32 n = aFormula.getLength();
+ if (pTop->GetMatrixFlag() != MM_NONE && n > 0)
+ {
+ if (aFormula[0] == '{' && aFormula[n-1] == '}')
+ aFormula = aFormula.copy(1, n-2);
+ }
+
+ if (rEntry.mbShared)
+ {
+ ScFormulaCell** pp = rEntry.mpCells;
+ ScFormulaCell** ppEnd = pp + rEntry.mnLength;
+ for (; pp != ppEnd; ++pp)
+ {
+ ScFormulaCell* p = *pp;
+ p->EndListeningTo(*mpEndListenCxt);
+ mpDoc->RemoveFromFormulaTree(p);
+ }
+ }
+ else
+ {
+ rEntry.mpCell->EndListeningTo(*mpEndListenCxt);
+ mpDoc->RemoveFromFormulaTree(rEntry.mpCell);
+ }
+
+ pCode->Clear();
+ pTop->SetHybridFormula(aFormula, mpDoc->GetGrammar());
+ }
+ }
+};
+
+class PostRangeNameUpdateHandler
+{
+ ScDocument* mpDoc;
+ boost::shared_ptr<sc::CompileFormulaContext> mpCompileFormulaCxt;
+
+public:
+ PostRangeNameUpdateHandler( ScDocument* pDoc ) :
+ mpDoc(pDoc),
+ mpCompileFormulaCxt(new sc::CompileFormulaContext(pDoc)) {}
+
+ void operator() ( sc::FormulaGroupEntry& rEntry )
+ {
+ if (rEntry.mbShared)
+ {
+ ScFormulaCell* pTop = *rEntry.mpCells;
+ OUString aFormula = pTop->GetHybridFormula();
+
+ // Create a new token array from the hybrid formula string, and
+ // set it to the group.
+ ScCompiler aComp(*mpCompileFormulaCxt, pTop->aPos);
+ ScTokenArray* pNewCode = aComp.CompileString(aFormula);
+ ScFormulaCellGroupRef xGroup = pTop->GetCellGroup();
+ assert(xGroup);
+ xGroup->setCode(pNewCode);
+ xGroup->compileCode(*mpDoc, pTop->aPos, mpDoc->GetGrammar());
+
+ // Propagate the new token array to all formula cells in the group.
+ ScFormulaCell** pp = rEntry.mpCells;
+ ScFormulaCell** ppEnd = pp + rEntry.mnLength;
+ for (; pp != ppEnd; ++pp)
+ {
+ ScFormulaCell* p = *pp;
+ p->SyncSharedCode();
+ p->SetDirty();
+ }
+ }
+ else
+ {
+ ScFormulaCell* pCell = rEntry.mpCell;
+ OUString aFormula = pCell->GetHybridFormula();
+
+ // Create token array from formula string.
+ ScCompiler aComp(*mpCompileFormulaCxt, pCell->aPos);
+ ScTokenArray* pNewCode = aComp.CompileString(aFormula);
+
+ // Generate RPN tokens.
+ ScCompiler aComp2(mpDoc, pCell->aPos, *pNewCode);
+ aComp2.CompileTokenArray();
+
+ pCell->SetCode(pNewCode);
+ pCell->SetDirty();
+ }
+ }
+};
+
+}
+
+void ScColumn::PreprocessRangeNameUpdate()
+{
+ // Collect all formula groups.
+ std::vector<sc::FormulaGroupEntry> aGroups = GetFormulaGroupEntries();
+
+ PreRangeNameUpdateHandler aFunc(pDocument);
+ std::for_each(aGroups.begin(), aGroups.end(), aFunc);
+}
+
+void ScColumn::PostprocessRangeNameUpdate()
+{
+ // Collect all formula groups.
+ std::vector<sc::FormulaGroupEntry> aGroups = GetFormulaGroupEntries();
+
+ PostRangeNameUpdateHandler aFunc(pDocument);
+ std::for_each(aGroups.begin(), aGroups.end(), aFunc);
+}
+
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */