[Libreoffice-commits] core.git: Branch 'libreoffice-4-2' - formula/source include/formula sc/inc sc/source

Kohei Yoshida kohei.yoshida at collabora.com
Tue Apr 8 09:33:14 PDT 2014


 formula/source/core/api/token.cxx       |   13 ++
 include/formula/tokenarray.hxx          |   12 ++
 sc/inc/column.hxx                       |   13 ++
 sc/inc/document.hxx                     |   12 ++
 sc/inc/formulacell.hxx                  |    8 +
 sc/inc/formulagroup.hxx                 |   18 +++
 sc/inc/table.hxx                        |    6 +
 sc/source/core/data/column.cxx          |   44 +++------
 sc/source/core/data/column2.cxx         |   21 ----
 sc/source/core/data/column4.cxx         |  152 ++++++++++++++++++++++++++++++++
 sc/source/core/data/documen4.cxx        |   11 --
 sc/source/core/data/document10.cxx      |   26 +++++
 sc/source/core/data/formulacell.cxx     |   76 ++++++----------
 sc/source/core/data/table4.cxx          |    6 -
 sc/source/core/data/table7.cxx          |   13 ++
 sc/source/core/tool/formulagroup.cxx    |    6 +
 sc/source/filter/oox/workbookhelper.cxx |    4 
 sc/source/ui/docshell/docfunc.cxx       |   11 --
 sc/source/ui/undo/undocell.cxx          |    4 
 sc/source/ui/undo/undorangename.cxx     |    6 -
 sc/source/ui/unoobj/nameuno.cxx         |    4 
 sc/source/ui/view/viewfunc.cxx          |    5 -
 22 files changed, 334 insertions(+), 137 deletions(-)

New commits:
commit 3a9b9a41c567c4e8f6c6bec0a4bb35dc581d577e
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Mon Apr 7 14:13:20 2014 -0400

    fdo#75741: Re-implement CompileNameFormula for formula groups.
    
    (cherry picked from commit 355baf573425165cbc1c789a6271eb29940e1f76)
    (cherry picked from commit 615f6aa293a6da90da94e6e78828198ffbc0ca5e)
    
    Conflicts:
    	sc/inc/document.hxx
    	sc/source/core/data/column4.cxx
    	sc/source/core/data/document10.cxx
    	sc/source/core/data/table7.cxx
    	sc/source/ui/docshell/docfunc.cxx
    	sc/source/ui/undo/undocell.cxx
    	sc/source/ui/unoobj/nameuno.cxx
    
    Change-Id: I57e1e464ac5f7abc10ce5ea5752e036ddb6cf6d7
    Reviewed-on: https://gerrit.libreoffice.org/8889
    Reviewed-by: Fridrich Strba <fridrich at documentfoundation.org>
    Tested-by: Fridrich Strba <fridrich at documentfoundation.org>

diff --git a/formula/source/core/api/token.cxx b/formula/source/core/api/token.cxx
index ae1655e..7499a2b 100644
--- a/formula/source/core/api/token.cxx
+++ b/formula/source/core/api/token.cxx
@@ -605,6 +605,19 @@ bool FormulaTokenArray::HasNameOrColRowName() const
     return false;
 }
 
+bool FormulaTokenArray::HasOpCodes( const boost::unordered_set<OpCode>& rOpCodes ) const
+{
+    FormulaToken** p = pCode;
+    FormulaToken** pEnd = p + static_cast<size_t>(nLen);
+    for (; p != pEnd; ++p)
+    {
+        OpCode eOp = (*p)->GetOpCode();
+        if (rOpCodes.count(eOp) > 0)
+            return true;
+    }
+
+    return false;
+}
 
 FormulaTokenArray::FormulaTokenArray() :
     pCode(NULL),
diff --git a/include/formula/tokenarray.hxx b/include/formula/tokenarray.hxx
index 9f8fed0..a479c10 100644
--- a/include/formula/tokenarray.hxx
+++ b/include/formula/tokenarray.hxx
@@ -26,6 +26,8 @@
 #include <tools/solar.h>
 #include <com/sun/star/sheet/FormulaToken.hpp>
 
+#include <boost/unordered_set.hpp>
+
 namespace formula
 {
 
@@ -124,6 +126,16 @@ public:
     /// Token of type svIndex or opcode ocColRowName
     bool    HasNameOrColRowName() const;
 
+    /**
+     * Check if the token array contains any of specified opcode tokens.
+     *
+     * @param rOpCodes collection of opcodes to check against.
+     *
+     * @return true if the token array contains at least one of the specified
+     *         opcode tokens, false otherwise.
+     */
+    bool HasOpCodes( const boost::unordered_set<OpCode>& rOpCodes ) const;
+
     FormulaToken** GetArray() const  { return pCode; }
     FormulaToken** GetCode()  const  { return pRPN; }
     sal_uInt16    GetLen() const     { return nLen; }
diff --git a/sc/inc/column.hxx b/sc/inc/column.hxx
index 33a1bf7..edf6aca 100644
--- a/sc/inc/column.hxx
+++ b/sc/inc/column.hxx
@@ -40,6 +40,7 @@ namespace formula { struct VectorRefArray; }
 namespace sc {
 
 struct FormulaGroupContext;
+struct FormulaGroupEntry;
 class StartListeningContext;
 class EndListeningContext;
 class CopyFromClipContext;
@@ -362,6 +363,11 @@ public:
     void        SetTabNo(SCTAB nNewTab);
     void        FindRangeNamesInUse(SCROW nRow1, SCROW nRow2, std::set<sal_uInt16>& rIndexes) const;
 
+    void PreprocessRangeNameUpdate(
+        sc::EndListeningContext& rEndListenCxt, sc::CompileFormulaContext& rCompileCxt );
+
+    void PostprocessRangeNameUpdate( sc::CompileFormulaContext& rCompileCxt );
+
     const SfxPoolItem*      GetAttr( SCROW nRow, sal_uInt16 nWhich ) const;
     const ScPatternAttr*    GetPattern( SCROW nRow ) const;
     const ScPatternAttr*    GetMostUsedPattern( SCROW nStartRow, SCROW nEndRow ) const;
@@ -463,7 +469,6 @@ public:
 
     void CompileDBFormula( sc::CompileFormulaContext& rCxt );
     void CompileDBFormula( sc::CompileFormulaContext& rCxt, bool bCreateFormulaString );
-    void CompileNameFormula( sc::CompileFormulaContext& rCxt, bool bCreateFormulaString );
     void CompileColRowNameFormula( sc::CompileFormulaContext& rCxt );
 
     sal_Int32   GetMaxStringLen( SCROW nRowStart, SCROW nRowEnd, rtl_TextEncoding eCharSet ) const;
@@ -584,6 +589,12 @@ private:
     void DeleteCells(
         sc::ColumnBlockPosition& rBlockPos, SCROW nRow1, SCROW nRow2, sal_uInt16 nDelFlag,
         std::vector<SCROW>& rDeleted );
+
+    /**
+     * Get all non-grouped formula cells and formula cell groups in the whole
+     * column.
+     */
+    std::vector<sc::FormulaGroupEntry> GetFormulaGroupEntries();
 };
 
 #endif
diff --git a/sc/inc/document.hxx b/sc/inc/document.hxx
index 809689b..b4e86f3 100644
--- a/sc/inc/document.hxx
+++ b/sc/inc/document.hxx
@@ -507,6 +507,17 @@ public:
     SC_DLLPUBLIC ScRangeName* GetRangeName() const;
     void SetRangeName(SCTAB nTab, ScRangeName* pNew);
     void SetRangeName( ScRangeName* pNewRangeName );
+
+    /**
+     * Call this immediately before updating all named ranges.
+     */
+    SC_DLLPUBLIC void PreprocessRangeNameUpdate();
+
+    /**
+     * Call this immediately after all named ranges have been updated.
+     */
+    SC_DLLPUBLIC void PostprocessRangeNameUpdate();
+
     SCTAB           GetMaxTableNumber() { return static_cast<SCTAB>(maTabs.size()) - 1; }
     void            SetMaxTableNumber(SCTAB nNumber) { nMaxTableNumber = nNumber; }
 
@@ -1948,7 +1959,6 @@ public:
 
     void            CompileDBFormula();
     void            CompileDBFormula( bool bCreateFormulaString );
-    SC_DLLPUBLIC void CompileNameFormula( bool bCreateFormulaString );
     void            CompileColRowNameFormula();
 
     /** Maximum string length of a column, e.g. for dBase export.
diff --git a/sc/inc/formulacell.hxx b/sc/inc/formulacell.hxx
index 2d696c3..69023a7 100644
--- a/sc/inc/formulacell.hxx
+++ b/sc/inc/formulacell.hxx
@@ -76,6 +76,7 @@ struct SC_DLLPUBLIC ScFormulaCellGroup : boost::noncopyable
     void scheduleCompilation();
 
     void setCode( const ScTokenArray& rCode );
+    void setCode( ScTokenArray* pCode );
     void compileCode(
         ScDocument& rDoc, const ScAddress& rPos, formula::FormulaGrammar::Grammar eGram );
     void compileOpenCLKernel();
@@ -303,11 +304,12 @@ public:
     ScTokenArray* GetCode();
     const ScTokenArray* GetCode() const;
 
+    void SetCode( ScTokenArray* pNew );
+
     bool            IsRunning() const;
     void            SetRunning( bool bVal );
     void CompileDBFormula( sc::CompileFormulaContext& rCxt );
     void CompileDBFormula( sc::CompileFormulaContext& rCxt, bool bCreateFormulaString );
-    void CompileNameFormula( sc::CompileFormulaContext& rCxt, bool bCreateFormulaString );
     void CompileColRowNameFormula( sc::CompileFormulaContext& rCxt );
     ScFormulaCell*  GetPrevious() const;
     ScFormulaCell*  GetNext() const;
@@ -344,6 +346,8 @@ public:
     void SetHybridFormula(
         const OUString& r, const formula::FormulaGrammar::Grammar eGrammar );
 
+    OUString GetHybridFormula() const;
+
     void SetResultMatrix( SCCOL nCols, SCROW nRows, const ScConstMatrixRef& pMat, formula::FormulaToken* pUL );
 
     /** For import only: set a double result.
@@ -393,6 +397,8 @@ public:
     ScTokenArray* GetSharedCode();
     const ScTokenArray* GetSharedCode() const;
 
+    void SyncSharedCode();
+
     bool IsPostponedDirty() const;
 };
 
diff --git a/sc/inc/formulagroup.hxx b/sc/inc/formulagroup.hxx
index bb0e0b4..4761c0a 100644
--- a/sc/inc/formulagroup.hxx
+++ b/sc/inc/formulagroup.hxx
@@ -24,9 +24,27 @@
 
 class ScDocument;
 class ScTokenArray;
+class ScFormulaCell;
 
 namespace sc {
 
+struct FormulaGroupEntry
+{
+    union
+    {
+        ScFormulaCell* mpCell;   // non-shared formula cell
+        ScFormulaCell** mpCells; // pointer to the top formula cell in a shared group.
+    };
+
+    size_t mnRow;
+    size_t mnLength;
+    bool mbShared;
+
+    FormulaGroupEntry( ScFormulaCell** pCells, size_t nRow, size_t nLength );
+
+    FormulaGroupEntry( ScFormulaCell* pCell, size_t nRow );
+};
+
 struct FormulaGroupContext : boost::noncopyable
 {
     typedef AlignedAllocator<double,256> DoubleAllocType;
diff --git a/sc/inc/table.hxx b/sc/inc/table.hxx
index 77e5996..f6d9a32 100644
--- a/sc/inc/table.hxx
+++ b/sc/inc/table.hxx
@@ -849,6 +849,11 @@ public:
     void SetRangeName(ScRangeName* pNew);
     ScRangeName* GetRangeName() const;
 
+    void PreprocessRangeNameUpdate(
+        sc::EndListeningContext& rEndListenCxt, sc::CompileFormulaContext& rCompileCxt );
+
+    void PostprocessRangeNameUpdate( sc::CompileFormulaContext& rCompileCxt );
+
     ScConditionalFormatList* GetCondFormList();
     const ScConditionalFormatList* GetCondFormList() const;
     void SetCondFormList( ScConditionalFormatList* pList );
@@ -1007,7 +1012,6 @@ private:
     bool        TestTabRefAbs(SCTAB nTable) const;
     void CompileDBFormula( sc::CompileFormulaContext& rCxt );
     void CompileDBFormula( sc::CompileFormulaContext& rCxt, bool bCreateFormulaString );
-    void CompileNameFormula( sc::CompileFormulaContext& rCxt, bool bCreateFormulaString );
     void CompileColRowNameFormula( sc::CompileFormulaContext& rCxt );
     void        RebuildFormulaGroups();
 
diff --git a/sc/source/core/data/column.cxx b/sc/source/core/data/column.cxx
index 518766d..a4a38df 100644
--- a/sc/source/core/data/column.cxx
+++ b/sc/source/core/data/column.cxx
@@ -44,6 +44,7 @@
 #include <listenercontext.hxx>
 #include <refhint.hxx>
 #include <stlalgorithm.hxx>
+#include <formulagroup.hxx>
 
 #include <svl/poolcach.hxx>
 #include <svl/zforlist.hxx>
@@ -2331,23 +2332,6 @@ void ScColumn::MarkSubTotalCells( sc::ColumnSpanSet& rSet, SCROW nRow1, SCROW nR
 
 namespace {
 
-struct FormulaGroup
-{
-    struct {
-        ScFormulaCell* mpCell;   // non-shared formula cell
-        ScFormulaCell** mpCells; // pointer to the top formula cell in a shared group.
-    };
-    size_t mnRow;
-    size_t mnLength;
-    bool mbShared;
-
-    FormulaGroup( ScFormulaCell** pCells, size_t nRow, size_t nLength ) :
-        mpCells(pCells), mnRow(nRow), mnLength(nLength), mbShared(true) {}
-
-    FormulaGroup( ScFormulaCell* pCell, size_t nRow ) :
-        mpCell(pCell), mnRow(nRow), mnLength(0), mbShared(false) {}
-};
-
 class SharedTopFormulaCellPicker : std::unary_function<sc::CellStoreType::value_type, void>
 {
 public:
@@ -2422,7 +2406,7 @@ public:
     }
 };
 
-class UpdateRefOnNonCopy : std::unary_function<FormulaGroup, void>
+class UpdateRefOnNonCopy : std::unary_function<sc::FormulaGroupEntry, void>
 {
     SCCOL mnCol;
     SCROW mnTab;
@@ -2430,7 +2414,7 @@ class UpdateRefOnNonCopy : std::unary_function<FormulaGroup, void>
     ScDocument* mpUndoDoc;
     bool mbUpdated;
 
-    void updateRefOnShift( FormulaGroup& rGroup )
+    void updateRefOnShift( sc::FormulaGroupEntry& rGroup )
     {
         if (!rGroup.mbShared)
         {
@@ -2492,7 +2476,7 @@ class UpdateRefOnNonCopy : std::unary_function<FormulaGroup, void>
         }
     }
 
-    void updateRefOnMove( FormulaGroup& rGroup )
+    void updateRefOnMove( sc::FormulaGroupEntry& rGroup )
     {
         if (!rGroup.mbShared)
         {
@@ -2603,7 +2587,7 @@ public:
         mnCol(nCol), mnTab(nTab), mpCxt(pCxt),
         mpUndoDoc(pUndoDoc), mbUpdated(false) {}
 
-    void operator() ( FormulaGroup& rGroup )
+    void operator() ( sc::FormulaGroupEntry& rGroup )
     {
         switch (mpCxt->meMode)
         {
@@ -2661,21 +2645,21 @@ public:
 
 class FormulaGroupPicker : public SharedTopFormulaCellPicker
 {
-    std::vector<FormulaGroup>& mrGroups;
+    std::vector<sc::FormulaGroupEntry>& mrGroups;
 
 public:
-    FormulaGroupPicker( std::vector<FormulaGroup>& rGroups ) : mrGroups(rGroups) {}
+    FormulaGroupPicker( std::vector<sc::FormulaGroupEntry>& rGroups ) : mrGroups(rGroups) {}
 
     virtual ~FormulaGroupPicker() {}
 
     virtual void processNonShared( ScFormulaCell* pCell, size_t nRow )
     {
-        mrGroups.push_back(FormulaGroup(pCell, nRow));
+        mrGroups.push_back(sc::FormulaGroupEntry(pCell, nRow));
     }
 
     virtual void processSharedTop( ScFormulaCell** ppCells, size_t nRow, size_t nLength )
     {
-        mrGroups.push_back(FormulaGroup(ppCells, nRow, nLength));
+        mrGroups.push_back(sc::FormulaGroupEntry(ppCells, nRow, nLength));
     }
 };
 
@@ -2748,8 +2732,7 @@ bool ScColumn::UpdateReference( sc::RefUpdateContext& rCxt, ScDocument* pUndoDoc
     sc::SharedFormulaUtil::splitFormulaCellGroups(maCells, aBounds);
 
     // Collect all formula groups.
-    std::vector<FormulaGroup> aGroups;
-    std::for_each(maCells.begin(), maCells.end(), FormulaGroupPicker(aGroups));
+    std::vector<sc::FormulaGroupEntry> aGroups = GetFormulaGroupEntries();
 
     // Process all collected formula groups.
     UpdateRefOnNonCopy aHandler(nCol, nTab, &rCxt, pUndoDoc);
@@ -2760,6 +2743,13 @@ bool ScColumn::UpdateReference( sc::RefUpdateContext& rCxt, ScDocument* pUndoDoc
     return aHandler.isUpdated();
 }
 
+std::vector<sc::FormulaGroupEntry> ScColumn::GetFormulaGroupEntries()
+{
+    std::vector<sc::FormulaGroupEntry> aGroups;
+    std::for_each(maCells.begin(), maCells.end(), FormulaGroupPicker(aGroups));
+    return aGroups;
+}
+
 namespace {
 
 class UpdateTransHandler
diff --git a/sc/source/core/data/column2.cxx b/sc/source/core/data/column2.cxx
index 1c18aff..f6825e2 100644
--- a/sc/source/core/data/column2.cxx
+++ b/sc/source/core/data/column2.cxx
@@ -3199,21 +3199,6 @@ public:
     }
 };
 
-class CompileNameFormulaHandler
-{
-    sc::CompileFormulaContext& mrCxt;
-    bool mbCreateFormulaString;
-
-public:
-    CompileNameFormulaHandler( sc::CompileFormulaContext& rCxt, bool bCreateFormulaString) :
-        mrCxt(rCxt), mbCreateFormulaString(bCreateFormulaString) {}
-
-    void operator() (size_t, ScFormulaCell* p)
-    {
-        p->CompileNameFormula(mrCxt, mbCreateFormulaString);
-    }
-};
-
 struct CompileColRowNameFormulaHandler
 {
     sc::CompileFormulaContext& mrCxt;
@@ -3242,12 +3227,6 @@ void ScColumn::CompileDBFormula( sc::CompileFormulaContext& rCxt, bool bCreateFo
     RegroupFormulaCells();
 }
 
-void ScColumn::CompileNameFormula( sc::CompileFormulaContext& rCxt, bool bCreateFormulaString )
-{
-    CompileNameFormulaHandler aFunc(rCxt, bCreateFormulaString);
-    sc::ProcessFormula(maCells, aFunc);
-}
-
 void ScColumn::CompileColRowNameFormula( sc::CompileFormulaContext& rCxt )
 {
     CompileColRowNameFormulaHandler aFunc(rCxt);
diff --git a/sc/source/core/data/column4.cxx b/sc/source/core/data/column4.cxx
index a024665..e25de16 100644
--- a/sc/source/core/data/column4.cxx
+++ b/sc/source/core/data/column4.cxx
@@ -15,18 +15,23 @@
 #include <document.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>
+
 void ScColumn::DeleteBeforeCopyFromClip( sc::CopyFromClipContext& rCxt, const ScColumn& rClipCol )
 {
     sc::CopyFromClipContext::Range aRange = rCxt.getDestRange();
@@ -120,4 +125,151 @@ void ScColumn::DeleteBeforeCopyFromClip( sc::CopyFromClipContext& rCxt, const Sc
     BroadcastCells(aDeletedRows, SC_HINT_DATACHANGED);
 }
 
+namespace {
+
+class PreRangeNameUpdateHandler
+{
+    ScDocument* mpDoc;
+    sc::EndListeningContext& mrEndListenCxt;
+    sc::CompileFormulaContext& mrCompileFormulaCxt;
+
+public:
+    PreRangeNameUpdateHandler( ScDocument* pDoc, sc::EndListeningContext& rEndListenCxt, sc::CompileFormulaContext& rCompileCxt ) :
+        mpDoc(pDoc),
+        mrEndListenCxt(rEndListenCxt),
+        mrCompileFormulaCxt(rCompileCxt) {}
+
+    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(mrCompileFormulaCxt);
+            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(mrEndListenCxt);
+                    mpDoc->RemoveFromFormulaTree(p);
+                }
+            }
+            else
+            {
+                rEntry.mpCell->EndListeningTo(mrEndListenCxt);
+                mpDoc->RemoveFromFormulaTree(rEntry.mpCell);
+            }
+
+            pCode->Clear();
+            pTop->SetHybridFormula(aFormula, mpDoc->GetGrammar());
+        }
+    }
+};
+
+class PostRangeNameUpdateHandler
+{
+    ScDocument* mpDoc;
+    sc::CompileFormulaContext& mrCompileFormulaCxt;
+
+public:
+    PostRangeNameUpdateHandler( ScDocument* pDoc, sc::CompileFormulaContext& rCompileCxt ) :
+        mpDoc(pDoc),
+        mrCompileFormulaCxt(rCompileCxt) {}
+
+    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(mrCompileFormulaCxt, 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(mrCompileFormulaCxt, 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(
+    sc::EndListeningContext& rEndListenCxt, sc::CompileFormulaContext& rCompileCxt )
+{
+    // Collect all formula groups.
+    std::vector<sc::FormulaGroupEntry> aGroups = GetFormulaGroupEntries();
+
+    PreRangeNameUpdateHandler aFunc(pDocument, rEndListenCxt, rCompileCxt);
+    std::for_each(aGroups.begin(), aGroups.end(), aFunc);
+}
+
+void ScColumn::PostprocessRangeNameUpdate( sc::CompileFormulaContext& rCompileCxt )
+{
+    // Collect all formula groups.
+    std::vector<sc::FormulaGroupEntry> aGroups = GetFormulaGroupEntries();
+
+    PostRangeNameUpdateHandler aFunc(pDocument, rCompileCxt);
+    std::for_each(aGroups.begin(), aGroups.end(), aFunc);
+}
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/core/data/documen4.cxx b/sc/source/core/data/documen4.cxx
index fb45385..8a4e3ec 100644
--- a/sc/source/core/data/documen4.cxx
+++ b/sc/source/core/data/documen4.cxx
@@ -559,17 +559,6 @@ void ScDocument::CompileDBFormula( bool bCreateFormulaString )
     }
 }
 
-void ScDocument::CompileNameFormula( bool bCreateFormulaString )
-{
-    sc::CompileFormulaContext aCxt(this);
-    TableContainer::iterator it = maTabs.begin();
-    for (;it != maTabs.end(); ++it)
-    {
-        if (*it)
-            (*it)->CompileNameFormula(aCxt, bCreateFormulaString);
-    }
-}
-
 void ScDocument::CompileColRowNameFormula()
 {
     sc::CompileFormulaContext aCxt(this);
diff --git a/sc/source/core/data/document10.cxx b/sc/source/core/data/document10.cxx
index 00640b3..ba95499 100644
--- a/sc/source/core/data/document10.cxx
+++ b/sc/source/core/data/document10.cxx
@@ -14,6 +14,8 @@
 #include <table.hxx>
 #include <tokenarray.hxx>
 #include <editutil.hxx>
+#include <listenercontext.hxx>
+#include <tokenstringcontext.hxx>
 
 // Add totally brand-new methods to this source file.
 
@@ -41,4 +43,28 @@ void ScDocument::DeleteBeforeCopyFromClip( sc::CopyFromClipContext& rCxt, const
     }
 }
 
+void ScDocument::PreprocessRangeNameUpdate()
+{
+    sc::EndListeningContext aEndListenCxt(*this);
+    sc::CompileFormulaContext aCompileCxt(this);
+
+    TableContainer::iterator it = maTabs.begin(), itEnd = maTabs.end();
+    for (; it != itEnd; ++it)
+    {
+        ScTable* p = *it;
+        p->PreprocessRangeNameUpdate(aEndListenCxt, aCompileCxt);
+    }
+}
+
+void ScDocument::PostprocessRangeNameUpdate()
+{
+    sc::CompileFormulaContext aCompileCxt(this);
+    TableContainer::iterator it = maTabs.begin(), itEnd = maTabs.end();
+    for (; it != itEnd; ++it)
+    {
+        ScTable* p = *it;
+        p->PostprocessRangeNameUpdate(aCompileCxt);
+    }
+}
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/core/data/formulacell.cxx b/sc/source/core/data/formulacell.cxx
index 10c4c14..78c4fb0 100644
--- a/sc/source/core/data/formulacell.cxx
+++ b/sc/source/core/data/formulacell.cxx
@@ -473,6 +473,14 @@ void ScFormulaCellGroup::setCode( const ScTokenArray& rCode )
     mpCode->GenHash();
 }
 
+void ScFormulaCellGroup::setCode( ScTokenArray* pCode )
+{
+    delete mpCode;
+    mpCode = pCode; // takes ownership of the token array.
+    mbInvariant = mpCode->IsInvariant();
+    mpCode->GenHash();
+}
+
 void ScFormulaCellGroup::compileCode(
     ScDocument& rDoc, const ScAddress& rPos, FormulaGrammar::Grammar eGram )
 {
@@ -2057,6 +2065,11 @@ void ScFormulaCell::SetHybridFormula( const OUString& r,
     aResult.SetHybridFormula( r); eTempGrammar = eGrammar;
 }
 
+OUString ScFormulaCell::GetHybridFormula() const
+{
+    return aResult.GetHybridFormula();
+}
+
 // Dynamically create the URLField on a mouse-over action on a hyperlink() cell.
 void ScFormulaCell::GetURLResult( OUString& rURL, OUString& rCellText )
 {
@@ -3385,6 +3398,13 @@ const ScTokenArray* ScFormulaCell::GetCode() const
     return pCode;
 }
 
+void ScFormulaCell::SetCode( ScTokenArray* pNew )
+{
+    assert(!mxGroup); // Don't call this if it's shared.
+    delete pCode;
+    pCode = pNew; // takes ownership.
+}
+
 bool ScFormulaCell::IsRunning() const
 {
     return bRunning;
@@ -3461,53 +3481,6 @@ void ScFormulaCell::CompileDBFormula( sc::CompileFormulaContext& rCxt, bool bCre
     }
 }
 
-void ScFormulaCell::CompileNameFormula( sc::CompileFormulaContext& rCxt, bool bCreateFormulaString )
-{
-    // Two phases must be called after each other
-    // 1. Formula String with old generated names
-    // 2. Formula String with new generated names
-    if ( bCreateFormulaString )
-    {
-        bool bRecompile = false;
-        pCode->Reset();
-        for ( FormulaToken* p = pCode->First(); p && !bRecompile; p = pCode->Next() )
-        {
-            switch ( p->GetOpCode() )
-            {
-                case ocBad:             // in case RangeName goes bad
-                case ocColRowName:      // in case the names are the same
-                    bRecompile = true;
-                break;
-                default:
-                    if ( p->GetType() == svIndex )
-                        bRecompile = true;  // RangeName
-            }
-        }
-        if ( bRecompile )
-        {
-            OUString aFormula = GetFormula(rCxt);
-            if ( GetMatrixFlag() != MM_NONE && !aFormula.isEmpty() )
-            {
-                if ( aFormula[ aFormula.getLength()-1 ] == '}' )
-                    aFormula = aFormula.copy( 0, aFormula.getLength()-1 );
-                if ( aFormula[0] == '{' )
-                    aFormula = aFormula.copy( 1 );
-            }
-            EndListeningTo( pDocument );
-            pDocument->RemoveFromFormulaTree( this );
-            pCode->Clear();
-            SetHybridFormula(aFormula, rCxt.getGrammar());
-        }
-    }
-    else if ( !pCode->GetLen() && !aResult.GetHybridFormula().isEmpty() )
-    {
-        rCxt.setGrammar(eTempGrammar);
-        Compile(rCxt, aResult.GetHybridFormula(), false);
-        aResult.SetToken( NULL);
-        SetDirty();
-    }
-}
-
 void ScFormulaCell::CompileColRowNameFormula( sc::CompileFormulaContext& rCxt )
 {
     pCode->Reset();
@@ -4066,6 +4039,15 @@ const ScTokenArray* ScFormulaCell::GetSharedCode() const
     return mxGroup ? mxGroup->mpCode : NULL;
 }
 
+void ScFormulaCell::SyncSharedCode()
+{
+    if (!mxGroup)
+        // Not a shared formula cell.
+        return;
+
+    pCode = mxGroup->mpCode;
+}
+
 bool ScFormulaCell::IsPostponedDirty() const
 {
     return mbPostponedDirty;
diff --git a/sc/source/core/data/table4.cxx b/sc/source/core/data/table4.cxx
index 9a50176..bfefd30 100644
--- a/sc/source/core/data/table4.cxx
+++ b/sc/source/core/data/table4.cxx
@@ -2068,12 +2068,6 @@ void ScTable::CompileDBFormula( sc::CompileFormulaContext& rCxt, bool bCreateFor
         aCol[i].CompileDBFormula(rCxt, bCreateFormulaString);
 }
 
-void ScTable::CompileNameFormula( sc::CompileFormulaContext& rCxt, bool bCreateFormulaString )
-{
-    for (SCCOL i = 0; i <= MAXCOL; ++i)
-        aCol[i].CompileNameFormula(rCxt, bCreateFormulaString);
-}
-
 void ScTable::CompileColRowNameFormula( sc::CompileFormulaContext& rCxt )
 {
     for (SCCOL i = 0; i <= MAXCOL; ++i)
diff --git a/sc/source/core/data/table7.cxx b/sc/source/core/data/table7.cxx
index 858514c..e8e82d4 100644
--- a/sc/source/core/data/table7.cxx
+++ b/sc/source/core/data/table7.cxx
@@ -41,4 +41,17 @@ void ScTable::DeleteBeforeCopyFromClip( sc::CopyFromClipContext& rCxt, const ScT
     SetStreamValid(false);
 }
 
+void ScTable::PreprocessRangeNameUpdate(
+    sc::EndListeningContext& rEndListenCxt, sc::CompileFormulaContext& rCompileCxt )
+{
+    for (SCCOL i = 0; i <= MAXCOL; ++i)
+        aCol[i].PreprocessRangeNameUpdate(rEndListenCxt, rCompileCxt);
+}
+
+void ScTable::PostprocessRangeNameUpdate( sc::CompileFormulaContext& rCompileCxt )
+{
+    for (SCCOL i = 0; i <= MAXCOL; ++i)
+        aCol[i].PostprocessRangeNameUpdate(rCompileCxt);
+}
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/core/tool/formulagroup.cxx b/sc/source/core/tool/formulagroup.cxx
index e662195..736d48c 100644
--- a/sc/source/core/tool/formulagroup.cxx
+++ b/sc/source/core/tool/formulagroup.cxx
@@ -40,6 +40,12 @@ extern "C" void getOpenCLDeviceInfo(size_t*, size_t*);
 
 namespace sc {
 
+FormulaGroupEntry::FormulaGroupEntry( ScFormulaCell** pCells, size_t nRow, size_t nLength ) :
+    mpCells(pCells), mnRow(nRow), mnLength(nLength), mbShared(true) {}
+
+FormulaGroupEntry::FormulaGroupEntry( ScFormulaCell* pCell, size_t nRow ) :
+    mpCell(pCell), mnRow(nRow), mnLength(0), mbShared(false) {}
+
 size_t FormulaGroupContext::ColKey::Hash::operator ()( const FormulaGroupContext::ColKey& rKey ) const
 {
     return rKey.mnTab * MAXCOLCOUNT + rKey.mnCol;
diff --git a/sc/source/filter/oox/workbookhelper.cxx b/sc/source/filter/oox/workbookhelper.cxx
index 32c8bd6..fba445f 100644
--- a/sc/source/filter/oox/workbookhelper.cxx
+++ b/sc/source/filter/oox/workbookhelper.cxx
@@ -601,8 +601,6 @@ void WorkbookGlobals::initialize( bool bWorkbookFile )
         mpDoc->EnableAdjustHeight(true);
         // disable automatic update of linked sheets and DDE links
         mpDoc->EnableExecuteLink(false);
-        // #i79890# disable automatic update of defined names
-        mpDoc->CompileNameFormula(true);
 
         mxProgressBar.reset( new SegmentProgressBar( mrBaseFilter.getStatusIndicator(), ScGlobal::GetRscString(STR_LOAD_DOC) ) );
         mxFmlaParser.reset( new FormulaParser( *this ) );
@@ -637,8 +635,6 @@ void WorkbookGlobals::finalize()
     {
         // #i74668# do not insert default sheets
         mpDocShell->SetEmpty(false);
-        // #i79890# Compile named ranges before re-enabling row height adjustment. (no idea why).
-        mpDoc->CompileNameFormula(false);
         // enable automatic update of linked sheets and DDE links
         mpDoc->EnableExecuteLink(true);
         // #i79826# enable updating automatic row height after loading the document
diff --git a/sc/source/ui/docshell/docfunc.cxx b/sc/source/ui/docshell/docfunc.cxx
index 72e7e46..bcb45b6 100644
--- a/sc/source/ui/docshell/docfunc.cxx
+++ b/sc/source/ui/docshell/docfunc.cxx
@@ -4865,13 +4865,13 @@ bool ScDocFunc::SetNewRangeNames( ScRangeName* pNewRanges, bool bModifyDoc, SCTA
     sal_Bool bCompile = ( !pDoc->IsImportingXML() && pDoc->GetNamedRangesLockCount() == 0 );
 
     if ( bCompile )
-        pDoc->CompileNameFormula( sal_True );   // CreateFormulaString
+        pDoc->PreprocessRangeNameUpdate();
     if (nTab >= 0)
         pDoc->SetRangeName( nTab, pNewRanges ); // takes ownership
     else
         pDoc->SetRangeName( pNewRanges );       // takes ownership
     if ( bCompile )
-        pDoc->CompileNameFormula( false );  // CompileFormulaString
+        pDoc->PostprocessRangeNameUpdate();
 
     if (bModifyDoc)
     {
@@ -4895,12 +4895,9 @@ void ScDocFunc::ModifyAllRangeNames( const boost::ptr_map<OUString, ScRangeName>
                 new ScUndoAllRangeNames(&rDocShell, aOldRangeMap, rRangeMap));
     }
 
-    pDoc->CompileNameFormula(true);
-
-    // set all range names
+    pDoc->PreprocessRangeNameUpdate();
     pDoc->SetAllRangeNames(rRangeMap);
-
-    pDoc->CompileNameFormula(false);
+    pDoc->PostprocessRangeNameUpdate();
 
     aModificator.SetDocumentModified();
     SFX_APP()->Broadcast(SfxSimpleHint(SC_HINT_AREAS_CHANGED));
diff --git a/sc/source/ui/undo/undocell.cxx b/sc/source/ui/undo/undocell.cxx
index 2a22f59..02f67a9 100644
--- a/sc/source/ui/undo/undocell.cxx
+++ b/sc/source/ui/undo/undocell.cxx
@@ -1042,7 +1042,7 @@ OUString ScUndoRangeNames::GetComment() const
 void ScUndoRangeNames::DoChange( sal_Bool bUndo )
 {
     ScDocument* pDoc = pDocShell->GetDocument();
-    pDoc->CompileNameFormula( sal_True );   // CreateFormulaString
+    pDoc->PreprocessRangeNameUpdate();
 
     if ( bUndo )
     {
@@ -1059,7 +1059,7 @@ void ScUndoRangeNames::DoChange( sal_Bool bUndo )
             pDoc->SetRangeName( new ScRangeName( *pNewRanges ) );
     }
 
-    pDoc->CompileNameFormula( false );  // CompileFormulaString
+    pDoc->PostprocessRangeNameUpdate();
 
     SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_AREAS_CHANGED ) );
 }
diff --git a/sc/source/ui/undo/undorangename.cxx b/sc/source/ui/undo/undorangename.cxx
index baf39b2..172f802 100644
--- a/sc/source/ui/undo/undorangename.cxx
+++ b/sc/source/ui/undo/undorangename.cxx
@@ -77,11 +77,9 @@ void ScUndoAllRangeNames::DoChange(const boost::ptr_map<OUString, ScRangeName>&
 {
     ScDocument& rDoc = *pDocShell->GetDocument();
 
-    rDoc.CompileNameFormula(true);
-
+    rDoc.PreprocessRangeNameUpdate();
     rDoc.SetAllRangeNames(rNames);
-
-    rDoc.CompileNameFormula(true);
+    rDoc.PostprocessRangeNameUpdate();
 
     SFX_APP()->Broadcast(SfxSimpleHint(SC_HINT_AREAS_CHANGED));
 }
diff --git a/sc/source/ui/unoobj/nameuno.cxx b/sc/source/ui/unoobj/nameuno.cxx
index c67e577..87ed766 100644
--- a/sc/source/ui/unoobj/nameuno.cxx
+++ b/sc/source/ui/unoobj/nameuno.cxx
@@ -745,13 +745,13 @@ sal_Bool SAL_CALL ScNamedRangesObj::hasByName( const OUString& aName )
 /** called from the XActionLockable interface methods on initial locking */
 void ScNamedRangesObj::lock()
 {
-    pDocShell->GetDocument()->CompileNameFormula( sal_True ); // CreateFormulaString
+    pDocShell->GetDocument()->PreprocessRangeNameUpdate();
 }
 
 /** called from the XActionLockable interface methods on final unlock */
 void ScNamedRangesObj::unlock()
 {
-    pDocShell->GetDocument()->CompileNameFormula( false ); // CompileFormulaString
+    pDocShell->GetDocument()->PostprocessRangeNameUpdate();
 }
 
 // document::XActionLockable
diff --git a/sc/source/ui/view/viewfunc.cxx b/sc/source/ui/view/viewfunc.cxx
index b967526..dd4e562 100644
--- a/sc/source/ui/view/viewfunc.cxx
+++ b/sc/source/ui/view/viewfunc.cxx
@@ -2765,7 +2765,7 @@ bool ScViewFunc::InsertName( const OUString& rName, const OUString& rSymbol,
     {
         ScDocShellModificator aModificator( *pDocSh );
 
-        pDoc->CompileNameFormula( true );   // CreateFormulaString
+        pDoc->PreprocessRangeNameUpdate();
 
         // input available yet? Then remove beforehand (=change)
         ScRangeData* pData = pList->findByUpperName(ScGlobal::pCharClass->uppercase(rName));
@@ -2779,7 +2779,8 @@ bool ScViewFunc::InsertName( const OUString& rName, const OUString& rSymbol,
             bOk = true;
         pNewEntry = NULL;   // never delete, insert took ownership
 
-        pDoc->CompileNameFormula( false );  // CompileFormulaString
+        pDoc->PostprocessRangeNameUpdate();
+
         aModificator.SetDocumentModified();
         SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_AREAS_CHANGED ) );
     }


More information about the Libreoffice-commits mailing list