[Libreoffice-commits] core.git: Branch 'feature/formula-core-rework' - sc/inc sc/Library_sc.mk sc/qa sc/source

Kohei Yoshida kohei.yoshida at gmail.com
Thu Mar 28 12:18:21 PDT 2013


 sc/Library_sc.mk                                       |    1 
 sc/inc/cell.hxx                                        |  278 -
 sc/inc/formulacell.hxx                                 |  305 +
 sc/qa/unit/subsequent_filters-test.cxx                 |    2 
 sc/qa/unit/ucalc.cxx                                   |    2 
 sc/source/core/data/attarray.cxx                       |    2 
 sc/source/core/data/autonamecache.cxx                  |    2 
 sc/source/core/data/cell.cxx                           | 1459 -------
 sc/source/core/data/cell2.cxx                          | 1749 ---------
 sc/source/core/data/cellvalue.cxx                      |    1 
 sc/source/core/data/colorscale.cxx                     |    2 
 sc/source/core/data/column.cxx                         |    1 
 sc/source/core/data/column2.cxx                        |    1 
 sc/source/core/data/column3.cxx                        |   10 
 sc/source/core/data/conditio.cxx                       |    2 
 sc/source/core/data/dociter.cxx                        |    1 
 sc/source/core/data/documen2.cxx                       |    1 
 sc/source/core/data/documen3.cxx                       |    1 
 sc/source/core/data/documen4.cxx                       |    1 
 sc/source/core/data/documen7.cxx                       |    1 
 sc/source/core/data/document.cxx                       |    1 
 sc/source/core/data/dpfilteredcache.cxx                |    2 
 sc/source/core/data/dpitemdata.cxx                     |    2 
 sc/source/core/data/dpshttab.cxx                       |    2 
 sc/source/core/data/dptabsrc.cxx                       |    2 
 sc/source/core/data/fillinfo.cxx                       |    2 
 sc/source/core/data/formulacell.cxx                    | 3208 +++++++++++++++++
 sc/source/core/data/formulaiter.cxx                    |    2 
 sc/source/core/data/postit.cxx                         |    2 
 sc/source/core/data/table1.cxx                         |    2 
 sc/source/core/data/table2.cxx                         |    2 
 sc/source/core/data/table3.cxx                         |    2 
 sc/source/core/data/table4.cxx                         |    2 
 sc/source/core/data/table5.cxx                         |    2 
 sc/source/core/data/table6.cxx                         |    2 
 sc/source/core/data/validat.cxx                        |    2 
 sc/source/core/tool/cellform.cxx                       |    2 
 sc/source/core/tool/chartarr.cxx                       |    2 
 sc/source/core/tool/chgtrack.cxx                       |    2 
 sc/source/core/tool/compiler.cxx                       |    2 
 sc/source/core/tool/consoli.cxx                        |    2 
 sc/source/core/tool/detfunc.cxx                        |    2 
 sc/source/core/tool/doubleref.cxx                      |    2 
 sc/source/core/tool/interpr1.cxx                       |    2 
 sc/source/core/tool/interpr2.cxx                       |    2 
 sc/source/core/tool/interpr3.cxx                       |    2 
 sc/source/core/tool/interpr4.cxx                       |    2 
 sc/source/core/tool/interpr5.cxx                       |    2 
 sc/source/core/tool/rangeseq.cxx                       |    2 
 sc/source/filter/dif/difexp.cxx                        |    2 
 sc/source/filter/excel/excdoc.cxx                      |    2 
 sc/source/filter/excel/excform.cxx                     |    2 
 sc/source/filter/excel/excform8.cxx                    |    2 
 sc/source/filter/excel/excimp8.cxx                     |    2 
 sc/source/filter/excel/excrecds.cxx                    |    2 
 sc/source/filter/excel/impop.cxx                       |    2 
 sc/source/filter/excel/xehelper.cxx                    |    2 
 sc/source/filter/excel/xelink.cxx                      |    2 
 sc/source/filter/excel/xestream.cxx                    |    2 
 sc/source/filter/excel/xetable.cxx                     |    2 
 sc/source/filter/excel/xicontent.cxx                   |    2 
 sc/source/filter/excel/xilink.cxx                      |    2 
 sc/source/filter/excel/xipivot.cxx                     |    2 
 sc/source/filter/excel/xistyle.cxx                     |    2 
 sc/source/filter/html/htmlexp.cxx                      |    2 
 sc/source/filter/lotus/lotimpop.cxx                    |    2 
 sc/source/filter/lotus/op.cxx                          |    2 
 sc/source/filter/oox/formulabuffer.cxx                 |    2 
 sc/source/filter/oox/sheetdatabuffer.cxx               |    2 
 sc/source/filter/orcus/interface.cxx                   |    2 
 sc/source/filter/qpro/biff.cxx                         |    2 
 sc/source/filter/qpro/qpro.cxx                         |    2 
 sc/source/filter/qpro/qprostyle.cxx                    |    2 
 sc/source/filter/starcalc/scflt.cxx                    |    2 
 sc/source/filter/xcl97/XclExpChangeTrack.cxx           |    2 
 sc/source/filter/xcl97/XclImpChangeTrack.cxx           |    2 
 sc/source/filter/xcl97/xcl97rec.cxx                    |    2 
 sc/source/filter/xml/XMLChangeTrackingExportHelper.cxx |    2 
 sc/source/filter/xml/XMLChangeTrackingImportHelper.cxx |    2 
 sc/source/filter/xml/XMLTrackedChangesContext.cxx      |    2 
 sc/source/filter/xml/xmlcelli.cxx                      |    2 
 sc/source/filter/xml/xmlexprt.cxx                      |    2 
 sc/source/ui/Accessibility/AccessibleCellBase.cxx      |    2 
 sc/source/ui/app/inputhdl.cxx                          |    2 
 sc/source/ui/app/transobj.cxx                          |    2 
 sc/source/ui/collab/sendfunc.cxx                       |    2 
 sc/source/ui/docshell/docfunc.cxx                      |    2 
 sc/source/ui/docshell/docsh.cxx                        |    2 
 sc/source/ui/docshell/docsh3.cxx                       |    2 
 sc/source/ui/docshell/docsh8.cxx                       |    2 
 sc/source/ui/docshell/externalrefmgr.cxx               |    2 
 sc/source/ui/docshell/impex.cxx                        |    2 
 sc/source/ui/docshell/macromgr.cxx                     |    2 
 sc/source/ui/docshell/tablink.cxx                      |    2 
 sc/source/ui/formdlg/dwfunctr.cxx                      |    2 
 sc/source/ui/formdlg/formula.cxx                       |    2 
 sc/source/ui/miscdlgs/anyrefdg.cxx                     |    2 
 sc/source/ui/miscdlgs/optsolver.cxx                    |    2 
 sc/source/ui/navipi/content.cxx                        |    2 
 sc/source/ui/undo/undoblk3.cxx                         |    2 
 sc/source/ui/undo/undocell.cxx                         |    2 
 sc/source/ui/unoobj/cellsuno.cxx                       |    2 
 sc/source/ui/unoobj/chart2uno.cxx                      |    2 
 sc/source/ui/unoobj/docuno.cxx                         |    2 
 sc/source/ui/unoobj/funcuno.cxx                        |    2 
 sc/source/ui/unoobj/textuno.cxx                        |    2 
 sc/source/ui/view/cellsh.cxx                           |    2 
 sc/source/ui/view/dbfunc3.cxx                          |    2 
 sc/source/ui/view/gridwin.cxx                          |    2 
 sc/source/ui/view/output.cxx                           |    2 
 sc/source/ui/view/output2.cxx                          |    2 
 sc/source/ui/view/printfun.cxx                         |    2 
 sc/source/ui/view/spelleng.cxx                         |    2 
 sc/source/ui/view/tabview4.cxx                         |    2 
 sc/source/ui/view/tabvwsh3.cxx                         |    2 
 sc/source/ui/view/tabvwsh5.cxx                         |    2 
 sc/source/ui/view/tabvwsha.cxx                         |    2 
 sc/source/ui/view/tabvwshc.cxx                         |    2 
 sc/source/ui/view/viewfun2.cxx                         |    2 
 sc/source/ui/view/viewfun4.cxx                         |    2 
 sc/source/ui/view/viewfun6.cxx                         |    2 
 sc/source/ui/view/viewfunc.cxx                         |    2 
 122 files changed, 3635 insertions(+), 3596 deletions(-)

New commits:
commit 18b4d6ceaccf4d431ccfe0ca92fffe9ffadaf426
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date:   Thu Mar 28 15:20:14 2013 -0400

    Move ScFormulaCell into its own header source files: formulacell.?xx.
    
    Change-Id: I65f2cb12c06784b5bcf6c6a2fad773825b6c409c

diff --git a/sc/Library_sc.mk b/sc/Library_sc.mk
index 46ab330..8d89830 100644
--- a/sc/Library_sc.mk
+++ b/sc/Library_sc.mk
@@ -143,6 +143,7 @@ $(eval $(call gb_Library_add_exception_objects,sc,\
 	sc/source/core/data/drawpage \
 	sc/source/core/data/drwlayer \
 	sc/source/core/data/fillinfo \
+	sc/source/core/data/formulacell \
 	sc/source/core/data/formulaiter \
 	sc/source/core/data/funcdesc \
 	sc/source/core/data/global \
diff --git a/sc/inc/cell.hxx b/sc/inc/cell.hxx
index 7395713..217cfab 100644
--- a/sc/inc/cell.hxx
+++ b/sc/inc/cell.hxx
@@ -300,284 +300,6 @@ private:
     ::std::vector<Item> maArray;
 };
 
-struct ScSimilarFormulaDelta;
-
-struct SC_DLLPUBLIC ScFormulaCellGroup
-{
-    sal_Int32              mnRefCount;
-    ScSimilarFormulaDelta *mpDelta;  // difference between items in column
-    sal_Int32              mnStart;  // Start offset of that cell
-    sal_Int32              mnLength; // How many of these do we have ?
-
-    ScFormulaCellGroup();
-    ~ScFormulaCellGroup();
-
-    bool IsCompatible( ScSimilarFormulaDelta *pDelta );
-};
-inline void intrusive_ptr_add_ref(ScFormulaCellGroup *p)
-{
-    p->mnRefCount++;
-}
-inline void intrusive_ptr_release(ScFormulaCellGroup *p)
-{
-    if( --p->mnRefCount == 0 )
-        delete p;
-}
-
-typedef ::boost::intrusive_ptr<ScFormulaCellGroup> ScFormulaCellGroupRef;
-
-enum ScMatrixMode {
-    MM_NONE      = 0,                   // No matrix formula
-    MM_FORMULA   = 1,                   // Upper left matrix formula cell
-    MM_REFERENCE = 2,                   // Remaining cells, via ocMatRef reference token
-    MM_FAKE      = 3                    // Interpret "as-if" matrix formula (legacy)
-};
-
-class SC_DLLPUBLIC ScFormulaCell : public ScBaseCell, public SvtListener
-{
-private:
-    ScFormulaResult aResult;
-    formula::FormulaGrammar::Grammar  eTempGrammar;   // used between string (creation) and (re)compilation
-    ScTokenArray*   pCode;              // The (new) token array
-    ScDocument*     pDocument;
-    ScFormulaCell*  pPrevious;
-    ScFormulaCell*  pNext;
-    ScFormulaCell*  pPreviousTrack;
-    ScFormulaCell*  pNextTrack;
-    ScFormulaCellGroupRef xGroup;       // re-factoring hack - group of formulae we're part of.
-    sal_uLong       nFormatIndex;       // Number format set by calculation
-    short           nFormatType;        // Number format type set by calculation
-    sal_uInt16      nSeenInIteration;   // Iteration cycle in which the cell was last encountered
-    sal_uInt8       cMatrixFlag;        // One of ScMatrixMode
-    bool            bDirty         : 1; // Must be (re)calculated
-    bool            bChanged       : 1; // Whether something changed regarding display/representation
-    bool            bRunning       : 1; // Already interpreting right now
-    bool            bCompile       : 1; // Must be (re)compiled
-    bool            bSubTotal      : 1; // Cell is part of or contains a SubTotal
-    bool            bIsIterCell    : 1; // Cell is part of a circular reference
-    bool            bInChangeTrack : 1; // Cell is in ChangeTrack
-    bool            bTableOpDirty  : 1; // Dirty flag for TableOp
-    bool            bNeedListening : 1; // Listeners need to be re-established after UpdateReference
-
-                    enum ScInterpretTailParameter
-                    {
-                        SCITP_NORMAL,
-                        SCITP_FROM_ITERATION,
-                        SCITP_CLOSE_ITERATION_CIRCLE
-                    };
-    void            InterpretTail( ScInterpretTailParameter );
-
-    ScFormulaCell( const ScFormulaCell& );
-
-public:
-
-#ifdef USE_MEMPOOL
-    DECL_FIXEDMEMPOOL_NEWDEL( ScFormulaCell )
-#endif
-
-    ScAddress       aPos;
-
-                    ~ScFormulaCell();
-
-    using ScBaseCell::Clone;
-
-    ScFormulaCell* Clone() const;
-
-    /** Empty formula cell, or with a preconstructed token array. */
-    ScFormulaCell( ScDocument*, const ScAddress&, const ScTokenArray* = NULL,
-                    const formula::FormulaGrammar::Grammar = formula::FormulaGrammar::GRAM_DEFAULT,
-                    sal_uInt8 = MM_NONE );
-
-    /** With formula string and grammar to compile with.
-       formula::FormulaGrammar::GRAM_DEFAULT effectively isformula::FormulaGrammar::GRAM_NATIVE_UI that
-        also includes formula::FormulaGrammar::CONV_UNSPECIFIED, therefor uses the address
-        convention associated with rPos::nTab by default. */
-    ScFormulaCell( ScDocument* pDoc, const ScAddress& rPos,
-                    const rtl::OUString& rFormula,
-                    const formula::FormulaGrammar::Grammar = formula::FormulaGrammar::GRAM_DEFAULT,
-                    sal_uInt8 cMatInd = MM_NONE );
-
-    ScFormulaCell( const ScFormulaCell& rCell, ScDocument& rDoc, const ScAddress& rPos, int nCloneFlags = SC_CLONECELL_DEFAULT );
-
-    size_t GetHash() const;
-
-    ScFormulaVectorState GetVectorState() const;
-
-    void            GetFormula( rtl::OUString& rFormula,
-                                const formula::FormulaGrammar::Grammar = formula::FormulaGrammar::GRAM_DEFAULT ) const;
-    void            GetFormula( rtl::OUStringBuffer& rBuffer,
-                                const formula::FormulaGrammar::Grammar = formula::FormulaGrammar::GRAM_DEFAULT ) const;
-
-    void            SetDirty( bool bDirtyFlag=true );
-    void            SetDirtyVar();
-    // If setting entire document dirty after load, no broadcasts but still append to FormulaTree.
-    void            SetDirtyAfterLoad();
-    inline void     ResetTableOpDirtyVar() { bTableOpDirty = false; }
-    void            SetTableOpDirty();
-    bool            IsDirtyOrInTableOpDirty() const;
-    bool            GetDirty() const { return bDirty; }
-    void            ResetDirty() { bDirty = false; }
-    bool            NeedsListening() const { return bNeedListening; }
-    void            SetNeedsListening( bool bVar ) { bNeedListening = bVar; }
-    void            Compile(const rtl::OUString& rFormula,
-                            bool bNoListening = false,
-                            const formula::FormulaGrammar::Grammar = formula::FormulaGrammar::GRAM_DEFAULT );
-    void            CompileTokenArray( bool bNoListening = false );
-    void            CompileXML( ScProgress& rProgress );        // compile temporary string tokens
-    void            CalcAfterLoad();
-    bool            MarkUsedExternalReferences();
-    void            Interpret();
-    inline bool     IsIterCell() const { return bIsIterCell; }
-    inline sal_uInt16   GetSeenInIteration() const { return nSeenInIteration; }
-
-    bool            HasOneReference( ScRange& r ) const;
-    /* Checks if the formula contains reference list that can be
-       expressed by one reference (like A1;A2;A3:A5 -> A1:A5). The
-       reference list is not required to be sorted (i.e. A3;A1;A2 is
-       still recognized as A1:A3), but no overlapping is allowed.
-       If one reference is recognized, the rRange is filled.
-
-       It is similar to HasOneReference(), but more general.
-     */
-    bool HasRefListExpressibleAsOneReference(ScRange& rRange) const;
-    bool            HasRelNameReference() const;
-    bool            HasColRowName() const;
-
-    bool            UpdateReference(UpdateRefMode eUpdateRefMode,
-                                    const ScRange& r,
-                                    SCsCOL nDx, SCsROW nDy, SCsTAB nDz,
-                                    ScDocument* pUndoDoc = NULL,
-                                    const ScAddress* pUndoCellPos = NULL );
-
-    void            TransposeReference();
-    void            UpdateTranspose( const ScRange& rSource, const ScAddress& rDest,
-                                        ScDocument* pUndoDoc );
-
-    void            UpdateGrow( const ScRange& rArea, SCCOL nGrowX, SCROW nGrowY );
-
-    void            UpdateInsertTab(SCTAB nTable, SCTAB nNewSheets = 1);
-    void            UpdateInsertTabAbs(SCTAB nTable);
-    bool            UpdateDeleteTab(SCTAB nTable, bool bIsMove = false, SCTAB nSheets = 1);
-    void            UpdateMoveTab(SCTAB nOldPos, SCTAB nNewPos, SCTAB nTabNo);
-    void            UpdateRenameTab(SCTAB nTable, const rtl::OUString& rName);
-    bool            TestTabRefAbs(SCTAB nTable);
-    void            UpdateCompile( bool bForceIfNameInUse = false );
-    void            FindRangeNamesInUse(std::set<sal_uInt16>& rIndexes) const;
-    bool            IsSubTotal() const                      { return bSubTotal; }
-    bool            IsChanged() const;
-    void            ResetChanged();
-    bool            IsEmpty();      // formula::svEmptyCell result
-                    // display as empty string if formula::svEmptyCell result
-    bool            IsEmptyDisplayedAsString();
-    bool            IsValue();      // also true if formula::svEmptyCell
-    bool            IsHybridValueCell(); // for cells after import to deal with inherited number formats
-    double          GetValue();
-    double          GetValueAlways();   // ignore errors
-    rtl::OUString   GetString();
-    const ScMatrix* GetMatrix();
-    bool            GetMatrixOrigin( ScAddress& rPos ) const;
-    void            GetResultDimensions( SCSIZE& rCols, SCSIZE& rRows );
-    sal_uInt16      GetMatrixEdge( ScAddress& rOrgPos );
-    sal_uInt16      GetErrCode();   // interpret first if necessary
-    sal_uInt16      GetRawError();  // don't interpret, just return code or result error
-    short           GetFormatType() const                   { return nFormatType; }
-    sal_uLong       GetFormatIndex() const                  { return nFormatIndex; }
-    void            GetFormatInfo( short& nType, sal_uLong& nIndex ) const
-                        { nType = nFormatType; nIndex = nFormatIndex; }
-    sal_uInt8       GetMatrixFlag() const                   { return cMatrixFlag; }
-    ScTokenArray*   GetCode() const                         { return pCode; }
-
-    bool            IsRunning() const                       { return bRunning; }
-    void            SetRunning( bool bVal )                 { bRunning = bVal; }
-    void            CompileDBFormula();
-    void            CompileDBFormula( bool bCreateFormulaString );
-    void            CompileNameFormula( bool bCreateFormulaString );
-    void            CompileColRowNameFormula();
-    ScFormulaCell*  GetPrevious() const                 { return pPrevious; }
-    ScFormulaCell*  GetNext() const                     { return pNext; }
-    void            SetPrevious( ScFormulaCell* pF )    { pPrevious = pF; }
-    void            SetNext( ScFormulaCell* pF )        { pNext = pF; }
-    ScFormulaCell*  GetPreviousTrack() const                { return pPreviousTrack; }
-    ScFormulaCell*  GetNextTrack() const                    { return pNextTrack; }
-    void            SetPreviousTrack( ScFormulaCell* pF )   { pPreviousTrack = pF; }
-    void            SetNextTrack( ScFormulaCell* pF )       { pNextTrack = pF; }
-
-    virtual void    Notify( SvtBroadcaster& rBC, const SfxHint& rHint);
-    void            SetCompile( bool bVal ) { bCompile = bVal; }
-    ScDocument*     GetDocument() const     { return pDocument; }
-    void            SetMatColsRows( SCCOL nCols, SCROW nRows, bool bDirtyFlag=true );
-    void            GetMatColsRows( SCCOL& nCols, SCROW& nRows ) const;
-
-                    // cell belongs to ChangeTrack and not to the real document
-    void            SetInChangeTrack( bool bVal ) { bInChangeTrack = bVal; }
-    bool            IsInChangeTrack() const { return bInChangeTrack; }
-
-                    // standard format for type and format
-                    // for format "Standard" possibly the format used in the formula cell
-    sal_uLong       GetStandardFormat( SvNumberFormatter& rFormatter, sal_uLong nFormat ) const;
-
-    // For import filters!
-    void            AddRecalcMode( formula::ScRecalcMode );
-    /** For import only: set a double result. */
-    void            SetHybridDouble( double n )     { aResult.SetHybridDouble( n); }
-    /** For import only: set a string result.
-        If for whatever reason you have to use both, SetHybridDouble() and
-        SetHybridString() or SetHybridFormula(), use SetHybridDouble() first
-        for performance reasons.*/
-    void            SetHybridString( const rtl::OUString& r )
-                        { aResult.SetHybridString( r); }
-    /** For import only: set a temporary formula string to be compiled later.
-        If for whatever reason you have to use both, SetHybridDouble() and
-        SetHybridString() or SetHybridFormula(), use SetHybridDouble() first
-        for performance reasons.*/
-    void            SetHybridFormula( const rtl::OUString& r,
-                                    const formula::FormulaGrammar::Grammar eGrammar )
-                        { aResult.SetHybridFormula( r); eTempGrammar = eGrammar; }
-
-    /**
-     * For import only: use for formula cells that return a number
-     * formatted as some kind of string
-     */
-    void SetHybridValueString( double nVal, const OUString& r )
-                        { aResult.SetHybridValueString( nVal, r ); }
-
-    void SetResultMatrix( SCCOL nCols, SCROW nRows, const ScConstMatrixRef& pMat, formula::FormulaToken* pUL )
-    {
-        aResult.SetMatrix(nCols, nRows, pMat, pUL);
-    }
-
-    /** For import only: set a double result.
-        Use this instead of SetHybridDouble() if there is no (temporary)
-        formula string because the formula is present as a token array, as it
-        is the case for binary Excel import.
-     */
-    void            SetResultDouble( double n )     { aResult.SetDouble( n); }
-
-    void            SetErrCode( sal_uInt16 n );
-    inline bool     IsHyperLinkCell() const { return pCode && pCode->IsHyperLink(); }
-    EditTextObject* CreateURLObject();
-    void            GetURLResult( rtl::OUString& rURL, rtl::OUString& rCellText );
-
-    /** Determines whether or not the result string contains more than one paragraph */
-    bool            IsMultilineResult();
-
-    void            MaybeInterpret();
-
-    // Temporary formula cell grouping API
-    ScFormulaCellGroupRef  GetCellGroup()
-        { return xGroup; }
-    void                   SetCellGroup( const ScFormulaCellGroupRef &xRef )
-        { xGroup = xRef; }
-    ScSimilarFormulaDelta *BuildDeltaTo( ScFormulaCell *pOther );
-    void                   ReleaseDelta( ScSimilarFormulaDelta *pDelta );
-    bool                   InterpretFormulaGroup();
-
-    // nOnlyNames may be one or more of SC_LISTENING_NAMES_*
-    void StartListeningTo( ScDocument* pDoc );
-    void EndListeningTo(
-        ScDocument* pDoc, ScTokenArray* pArr = NULL, ScAddress aPos = ScAddress() );
-};
-
 #endif
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/inc/formulacell.hxx b/sc/inc/formulacell.hxx
new file mode 100644
index 0000000..8bdcbc0
--- /dev/null
+++ b/sc/inc/formulacell.hxx
@@ -0,0 +1,305 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ *   Licensed to the Apache Software Foundation (ASF) under one or more
+ *   contributor license agreements. See the NOTICE file distributed
+ *   with this work for additional information regarding copyright
+ *   ownership. The ASF licenses this file to you under the Apache
+ *   License, Version 2.0 (the "License"); you may not use this file
+ *   except in compliance with the License. You may obtain a copy of
+ *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef SC_FORMULACELL_HXX
+#define SC_FORMULACELL_HXX
+
+#include "cell.hxx"
+
+struct ScSimilarFormulaDelta;
+
+struct SC_DLLPUBLIC ScFormulaCellGroup
+{
+    sal_Int32              mnRefCount;
+    ScSimilarFormulaDelta *mpDelta;  // difference between items in column
+    sal_Int32              mnStart;  // Start offset of that cell
+    sal_Int32              mnLength; // How many of these do we have ?
+
+    ScFormulaCellGroup();
+    ~ScFormulaCellGroup();
+
+    bool IsCompatible( ScSimilarFormulaDelta *pDelta );
+};
+inline void intrusive_ptr_add_ref(ScFormulaCellGroup *p)
+{
+    p->mnRefCount++;
+}
+inline void intrusive_ptr_release(ScFormulaCellGroup *p)
+{
+    if( --p->mnRefCount == 0 )
+        delete p;
+}
+
+typedef ::boost::intrusive_ptr<ScFormulaCellGroup> ScFormulaCellGroupRef;
+
+enum ScMatrixMode {
+    MM_NONE      = 0,                   // No matrix formula
+    MM_FORMULA   = 1,                   // Upper left matrix formula cell
+    MM_REFERENCE = 2,                   // Remaining cells, via ocMatRef reference token
+    MM_FAKE      = 3                    // Interpret "as-if" matrix formula (legacy)
+};
+
+class SC_DLLPUBLIC ScFormulaCell : public ScBaseCell, public SvtListener
+{
+private:
+    ScFormulaResult aResult;
+    formula::FormulaGrammar::Grammar  eTempGrammar;   // used between string (creation) and (re)compilation
+    ScTokenArray*   pCode;              // The (new) token array
+    ScDocument*     pDocument;
+    ScFormulaCell*  pPrevious;
+    ScFormulaCell*  pNext;
+    ScFormulaCell*  pPreviousTrack;
+    ScFormulaCell*  pNextTrack;
+    ScFormulaCellGroupRef xGroup;       // re-factoring hack - group of formulae we're part of.
+    sal_uLong       nFormatIndex;       // Number format set by calculation
+    short           nFormatType;        // Number format type set by calculation
+    sal_uInt16      nSeenInIteration;   // Iteration cycle in which the cell was last encountered
+    sal_uInt8       cMatrixFlag;        // One of ScMatrixMode
+    bool            bDirty         : 1; // Must be (re)calculated
+    bool            bChanged       : 1; // Whether something changed regarding display/representation
+    bool            bRunning       : 1; // Already interpreting right now
+    bool            bCompile       : 1; // Must be (re)compiled
+    bool            bSubTotal      : 1; // Cell is part of or contains a SubTotal
+    bool            bIsIterCell    : 1; // Cell is part of a circular reference
+    bool            bInChangeTrack : 1; // Cell is in ChangeTrack
+    bool            bTableOpDirty  : 1; // Dirty flag for TableOp
+    bool            bNeedListening : 1; // Listeners need to be re-established after UpdateReference
+
+                    enum ScInterpretTailParameter
+                    {
+                        SCITP_NORMAL,
+                        SCITP_FROM_ITERATION,
+                        SCITP_CLOSE_ITERATION_CIRCLE
+                    };
+    void            InterpretTail( ScInterpretTailParameter );
+
+    ScFormulaCell( const ScFormulaCell& );
+
+public:
+
+#ifdef USE_MEMPOOL
+    DECL_FIXEDMEMPOOL_NEWDEL( ScFormulaCell )
+#endif
+
+    ScAddress       aPos;
+
+                    ~ScFormulaCell();
+
+    using ScBaseCell::Clone;
+
+    ScFormulaCell* Clone() const;
+
+    /** Empty formula cell, or with a preconstructed token array. */
+    ScFormulaCell( ScDocument*, const ScAddress&, const ScTokenArray* = NULL,
+                    const formula::FormulaGrammar::Grammar = formula::FormulaGrammar::GRAM_DEFAULT,
+                    sal_uInt8 = MM_NONE );
+
+    /** With formula string and grammar to compile with.
+       formula::FormulaGrammar::GRAM_DEFAULT effectively isformula::FormulaGrammar::GRAM_NATIVE_UI that
+        also includes formula::FormulaGrammar::CONV_UNSPECIFIED, therefor uses the address
+        convention associated with rPos::nTab by default. */
+    ScFormulaCell( ScDocument* pDoc, const ScAddress& rPos,
+                    const rtl::OUString& rFormula,
+                    const formula::FormulaGrammar::Grammar = formula::FormulaGrammar::GRAM_DEFAULT,
+                    sal_uInt8 cMatInd = MM_NONE );
+
+    ScFormulaCell( const ScFormulaCell& rCell, ScDocument& rDoc, const ScAddress& rPos, int nCloneFlags = SC_CLONECELL_DEFAULT );
+
+    size_t GetHash() const;
+
+    ScFormulaVectorState GetVectorState() const;
+
+    void            GetFormula( rtl::OUString& rFormula,
+                                const formula::FormulaGrammar::Grammar = formula::FormulaGrammar::GRAM_DEFAULT ) const;
+    void            GetFormula( rtl::OUStringBuffer& rBuffer,
+                                const formula::FormulaGrammar::Grammar = formula::FormulaGrammar::GRAM_DEFAULT ) const;
+
+    void            SetDirty( bool bDirtyFlag=true );
+    void            SetDirtyVar();
+    // If setting entire document dirty after load, no broadcasts but still append to FormulaTree.
+    void            SetDirtyAfterLoad();
+    inline void     ResetTableOpDirtyVar() { bTableOpDirty = false; }
+    void            SetTableOpDirty();
+    bool            IsDirtyOrInTableOpDirty() const;
+    bool            GetDirty() const { return bDirty; }
+    void            ResetDirty() { bDirty = false; }
+    bool            NeedsListening() const { return bNeedListening; }
+    void            SetNeedsListening( bool bVar ) { bNeedListening = bVar; }
+    void            Compile(const rtl::OUString& rFormula,
+                            bool bNoListening = false,
+                            const formula::FormulaGrammar::Grammar = formula::FormulaGrammar::GRAM_DEFAULT );
+    void            CompileTokenArray( bool bNoListening = false );
+    void            CompileXML( ScProgress& rProgress );        // compile temporary string tokens
+    void            CalcAfterLoad();
+    bool            MarkUsedExternalReferences();
+    void            Interpret();
+    inline bool     IsIterCell() const { return bIsIterCell; }
+    inline sal_uInt16   GetSeenInIteration() const { return nSeenInIteration; }
+
+    bool            HasOneReference( ScRange& r ) const;
+    /* Checks if the formula contains reference list that can be
+       expressed by one reference (like A1;A2;A3:A5 -> A1:A5). The
+       reference list is not required to be sorted (i.e. A3;A1;A2 is
+       still recognized as A1:A3), but no overlapping is allowed.
+       If one reference is recognized, the rRange is filled.
+
+       It is similar to HasOneReference(), but more general.
+     */
+    bool HasRefListExpressibleAsOneReference(ScRange& rRange) const;
+    bool            HasRelNameReference() const;
+    bool            HasColRowName() const;
+
+    bool            UpdateReference(UpdateRefMode eUpdateRefMode,
+                                    const ScRange& r,
+                                    SCsCOL nDx, SCsROW nDy, SCsTAB nDz,
+                                    ScDocument* pUndoDoc = NULL,
+                                    const ScAddress* pUndoCellPos = NULL );
+
+    void            TransposeReference();
+    void            UpdateTranspose( const ScRange& rSource, const ScAddress& rDest,
+                                        ScDocument* pUndoDoc );
+
+    void            UpdateGrow( const ScRange& rArea, SCCOL nGrowX, SCROW nGrowY );
+
+    void            UpdateInsertTab(SCTAB nTable, SCTAB nNewSheets = 1);
+    void            UpdateInsertTabAbs(SCTAB nTable);
+    bool            UpdateDeleteTab(SCTAB nTable, bool bIsMove = false, SCTAB nSheets = 1);
+    void            UpdateMoveTab(SCTAB nOldPos, SCTAB nNewPos, SCTAB nTabNo);
+    void            UpdateRenameTab(SCTAB nTable, const rtl::OUString& rName);
+    bool            TestTabRefAbs(SCTAB nTable);
+    void            UpdateCompile( bool bForceIfNameInUse = false );
+    void            FindRangeNamesInUse(std::set<sal_uInt16>& rIndexes) const;
+    bool            IsSubTotal() const                      { return bSubTotal; }
+    bool            IsChanged() const;
+    void            ResetChanged();
+    bool            IsEmpty();      // formula::svEmptyCell result
+                    // display as empty string if formula::svEmptyCell result
+    bool            IsEmptyDisplayedAsString();
+    bool            IsValue();      // also true if formula::svEmptyCell
+    bool            IsHybridValueCell(); // for cells after import to deal with inherited number formats
+    double          GetValue();
+    double          GetValueAlways();   // ignore errors
+    rtl::OUString   GetString();
+    const ScMatrix* GetMatrix();
+    bool            GetMatrixOrigin( ScAddress& rPos ) const;
+    void            GetResultDimensions( SCSIZE& rCols, SCSIZE& rRows );
+    sal_uInt16      GetMatrixEdge( ScAddress& rOrgPos );
+    sal_uInt16      GetErrCode();   // interpret first if necessary
+    sal_uInt16      GetRawError();  // don't interpret, just return code or result error
+    short           GetFormatType() const                   { return nFormatType; }
+    sal_uLong       GetFormatIndex() const                  { return nFormatIndex; }
+    void            GetFormatInfo( short& nType, sal_uLong& nIndex ) const
+                        { nType = nFormatType; nIndex = nFormatIndex; }
+    sal_uInt8       GetMatrixFlag() const                   { return cMatrixFlag; }
+    ScTokenArray*   GetCode() const                         { return pCode; }
+
+    bool            IsRunning() const                       { return bRunning; }
+    void            SetRunning( bool bVal )                 { bRunning = bVal; }
+    void            CompileDBFormula();
+    void            CompileDBFormula( bool bCreateFormulaString );
+    void            CompileNameFormula( bool bCreateFormulaString );
+    void            CompileColRowNameFormula();
+    ScFormulaCell*  GetPrevious() const                 { return pPrevious; }
+    ScFormulaCell*  GetNext() const                     { return pNext; }
+    void            SetPrevious( ScFormulaCell* pF )    { pPrevious = pF; }
+    void            SetNext( ScFormulaCell* pF )        { pNext = pF; }
+    ScFormulaCell*  GetPreviousTrack() const                { return pPreviousTrack; }
+    ScFormulaCell*  GetNextTrack() const                    { return pNextTrack; }
+    void            SetPreviousTrack( ScFormulaCell* pF )   { pPreviousTrack = pF; }
+    void            SetNextTrack( ScFormulaCell* pF )       { pNextTrack = pF; }
+
+    virtual void    Notify( SvtBroadcaster& rBC, const SfxHint& rHint);
+    void            SetCompile( bool bVal ) { bCompile = bVal; }
+    ScDocument*     GetDocument() const     { return pDocument; }
+    void            SetMatColsRows( SCCOL nCols, SCROW nRows, bool bDirtyFlag=true );
+    void            GetMatColsRows( SCCOL& nCols, SCROW& nRows ) const;
+
+                    // cell belongs to ChangeTrack and not to the real document
+    void            SetInChangeTrack( bool bVal ) { bInChangeTrack = bVal; }
+    bool            IsInChangeTrack() const { return bInChangeTrack; }
+
+                    // standard format for type and format
+                    // for format "Standard" possibly the format used in the formula cell
+    sal_uLong       GetStandardFormat( SvNumberFormatter& rFormatter, sal_uLong nFormat ) const;
+
+    // For import filters!
+    void            AddRecalcMode( formula::ScRecalcMode );
+    /** For import only: set a double result. */
+    void            SetHybridDouble( double n )     { aResult.SetHybridDouble( n); }
+    /** For import only: set a string result.
+        If for whatever reason you have to use both, SetHybridDouble() and
+        SetHybridString() or SetHybridFormula(), use SetHybridDouble() first
+        for performance reasons.*/
+    void            SetHybridString( const rtl::OUString& r )
+                        { aResult.SetHybridString( r); }
+    /** For import only: set a temporary formula string to be compiled later.
+        If for whatever reason you have to use both, SetHybridDouble() and
+        SetHybridString() or SetHybridFormula(), use SetHybridDouble() first
+        for performance reasons.*/
+    void            SetHybridFormula( const rtl::OUString& r,
+                                    const formula::FormulaGrammar::Grammar eGrammar )
+                        { aResult.SetHybridFormula( r); eTempGrammar = eGrammar; }
+
+    /**
+     * For import only: use for formula cells that return a number
+     * formatted as some kind of string
+     */
+    void SetHybridValueString( double nVal, const OUString& r )
+                        { aResult.SetHybridValueString( nVal, r ); }
+
+    void SetResultMatrix( SCCOL nCols, SCROW nRows, const ScConstMatrixRef& pMat, formula::FormulaToken* pUL )
+    {
+        aResult.SetMatrix(nCols, nRows, pMat, pUL);
+    }
+
+    /** For import only: set a double result.
+        Use this instead of SetHybridDouble() if there is no (temporary)
+        formula string because the formula is present as a token array, as it
+        is the case for binary Excel import.
+     */
+    void            SetResultDouble( double n )     { aResult.SetDouble( n); }
+
+    void            SetErrCode( sal_uInt16 n );
+    inline bool     IsHyperLinkCell() const { return pCode && pCode->IsHyperLink(); }
+    EditTextObject* CreateURLObject();
+    void            GetURLResult( rtl::OUString& rURL, rtl::OUString& rCellText );
+
+    /** Determines whether or not the result string contains more than one paragraph */
+    bool            IsMultilineResult();
+
+    void            MaybeInterpret();
+
+    // Temporary formula cell grouping API
+    ScFormulaCellGroupRef  GetCellGroup()
+        { return xGroup; }
+    void                   SetCellGroup( const ScFormulaCellGroupRef &xRef )
+        { xGroup = xRef; }
+    ScSimilarFormulaDelta *BuildDeltaTo( ScFormulaCell *pOther );
+    void                   ReleaseDelta( ScSimilarFormulaDelta *pDelta );
+    bool                   InterpretFormulaGroup();
+
+    // nOnlyNames may be one or more of SC_LISTENING_NAMES_*
+    void StartListeningTo( ScDocument* pDoc );
+    void EndListeningTo(
+        ScDocument* pDoc, ScTokenArray* pArr = NULL, ScAddress aPos = ScAddress() );
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/qa/unit/subsequent_filters-test.cxx b/sc/qa/unit/subsequent_filters-test.cxx
index 130be28..a00b518 100644
--- a/sc/qa/unit/subsequent_filters-test.cxx
+++ b/sc/qa/unit/subsequent_filters-test.cxx
@@ -50,7 +50,7 @@
 #include <editeng/borderline.hxx>
 #include <dbdata.hxx>
 #include "validat.hxx"
-#include "cell.hxx"
+#include "formulacell.hxx"
 #include "drwlayer.hxx"
 #include "userdat.hxx"
 #include "dpobject.hxx"
diff --git a/sc/qa/unit/ucalc.cxx b/sc/qa/unit/ucalc.cxx
index 6d48956..6416340 100644
--- a/sc/qa/unit/ucalc.cxx
+++ b/sc/qa/unit/ucalc.cxx
@@ -33,7 +33,7 @@
 #include <osl/file.hxx>
 
 #include "scdll.hxx"
-#include "cell.hxx"
+#include "formulacell.hxx"
 #include "document.hxx"
 #include "stringutil.hxx"
 #include "scmatrix.hxx"
diff --git a/sc/source/core/data/attarray.cxx b/sc/source/core/data/attarray.cxx
index 29522130..d52bcc6 100644
--- a/sc/source/core/data/attarray.cxx
+++ b/sc/source/core/data/attarray.cxx
@@ -40,7 +40,7 @@
 #include "rechead.hxx"
 #include "globstr.hrc"
 #include "segmenttree.hxx"
-#include "cell.hxx"
+#include "formulacell.hxx"
 #include "cellvalue.hxx"
 #include "editutil.hxx"
 #include <rtl/strbuf.hxx>
diff --git a/sc/source/core/data/autonamecache.cxx b/sc/source/core/data/autonamecache.cxx
index 6629c51..1dca11e 100644
--- a/sc/source/core/data/autonamecache.cxx
+++ b/sc/source/core/data/autonamecache.cxx
@@ -22,7 +22,7 @@
 #include "autonamecache.hxx"
 #include "dociter.hxx"
 #include "queryparam.hxx"
-#include "cell.hxx"
+#include "formulacell.hxx"
 #include "cellvalue.hxx"
 #include "editutil.hxx"
 #include "document.hxx"
diff --git a/sc/source/core/data/cell.cxx b/sc/source/core/data/cell.cxx
index 66032a8..aa6e2a2 100644
--- a/sc/source/core/data/cell.cxx
+++ b/sc/source/core/data/cell.cxx
@@ -19,45 +19,15 @@
 
 #include "cell.hxx"
 
-#include "scitems.hxx"
-#include "attrib.hxx"
-#include "compiler.hxx"
-#include "interpre.hxx"
 #include "document.hxx"
-#include "docoptio.hxx"
-#include "rechead.hxx"
-#include "rangenam.hxx"
-#include "brdcst.hxx"
-#include "ddelink.hxx"
-#include "validat.hxx"
-#include "progress.hxx"
-#include "editutil.hxx"
-#include "recursionhelper.hxx"
-#include "externalrefmgr.hxx"
-#include "macromgr.hxx"
-#include "dbdata.hxx"
-#include "globalnames.hxx"
-#include "cellvalue.hxx"
+#include "formulacell.hxx"
 
-#include <svl/intitem.hxx>
 #include <svl/broadcast.hxx>
-#include <svl/zforlist.hxx>
-
-using namespace formula;
-// More or less arbitrary, of course all recursions must fit into available
-// stack space (which is what on all systems we don't know yet?). Choosing a
-// lower value may be better than trying a much higher value that also isn't
-// sufficient but temporarily leads to high memory consumption. On the other
-// hand, if the value fits all recursions, execution is quicker as no resumes
-// are necessary. Could be made a configurable option.
-// Allow for a year's calendar (366).
-const sal_uInt16 MAXRECURSION = 400;
 
 // STATIC DATA -----------------------------------------------------------
 
 #ifdef USE_MEMPOOL
 IMPL_FIXEDMEMPOOL_NEWDEL( ScValueCell )
-IMPL_FIXEDMEMPOOL_NEWDEL( ScFormulaCell )
 IMPL_FIXEDMEMPOOL_NEWDEL( ScStringCell )
 IMPL_FIXEDMEMPOOL_NEWDEL( ScNoteCell )
 #endif
@@ -104,108 +74,6 @@ ScBaseCell* lclCloneCell( const ScBaseCell& rSrcCell, ScDocument& rDestDoc, cons
     return 0;
 }
 
-void adjustRangeName(ScToken* pToken, ScDocument& rNewDoc, const ScDocument* pOldDoc, const ScAddress& aNewPos, const ScAddress& aOldPos)
-{
-    bool bOldGlobal = pToken->IsGlobal();
-    SCTAB aOldTab = aOldPos.Tab();
-    rtl::OUString aRangeName;
-    int nOldIndex = pToken->GetIndex();
-    ScRangeData* pOldRangeData = NULL;
-
-    //search the name of the RangeName
-    if (!bOldGlobal)
-    {
-        pOldRangeData = pOldDoc->GetRangeName(aOldTab)->findByIndex(nOldIndex);
-        if (!pOldRangeData)
-            return;     //might be an error in the formula array
-        aRangeName = pOldRangeData->GetUpperName();
-    }
-    else
-    {
-        pOldRangeData = pOldDoc->GetRangeName()->findByIndex(nOldIndex);
-        if (!pOldRangeData)
-            return;     //might be an error in the formula array
-        aRangeName = pOldRangeData->GetUpperName();
-    }
-
-    //find corresponding range name in new document
-    //first search for local range name then global range names
-    SCTAB aNewTab = aNewPos.Tab();
-    ScRangeName* pRangeName = rNewDoc.GetRangeName(aNewTab);
-    ScRangeData* pRangeData = NULL;
-    bool bNewGlobal = false;
-    //search local range names
-    if (pRangeName)
-    {
-        pRangeData = pRangeName->findByUpperName(aRangeName);
-    }
-    //search global range names
-    if (!pRangeData)
-    {
-        bNewGlobal = true;
-        pRangeName = rNewDoc.GetRangeName();
-        if (pRangeName)
-            pRangeData = pRangeName->findByUpperName(aRangeName);
-    }
-    //if no range name was found copy it
-    if (!pRangeData)
-    {
-        bNewGlobal = bOldGlobal;
-        pRangeData = new ScRangeData(*pOldRangeData, &rNewDoc);
-        ScTokenArray* pRangeNameToken = pRangeData->GetCode();
-        if (rNewDoc.GetPool() != const_cast<ScDocument*>(pOldDoc)->GetPool())
-        {
-            pRangeNameToken->ReadjustAbsolute3DReferences(pOldDoc, &rNewDoc, pRangeData->GetPos(), true);
-            pRangeNameToken->AdjustAbsoluteRefs(pOldDoc, aOldPos, aNewPos, false, true);
-        }
-
-        bool bInserted;
-        if (bNewGlobal)
-            bInserted = rNewDoc.GetRangeName()->insert(pRangeData);
-        else
-            bInserted = rNewDoc.GetRangeName(aNewTab)->insert(pRangeData);
-        if (!bInserted)
-        {
-            //if this happened we have a real problem
-            pRangeData = NULL;
-            pToken->SetIndex(0);
-            OSL_FAIL("inserting the range name should not fail");
-            return;
-        }
-    }
-    sal_Int32 nIndex = pRangeData->GetIndex();
-    pToken->SetIndex(nIndex);
-    pToken->SetGlobal(bNewGlobal);
-}
-
-void adjustDBRange(ScToken* pToken, ScDocument& rNewDoc, const ScDocument* pOldDoc)
-{
-    ScDBCollection* pOldDBCollection = pOldDoc->GetDBCollection();
-    if (!pOldDBCollection)
-        return;//strange error case, don't do anything
-    ScDBCollection::NamedDBs& aOldNamedDBs = pOldDBCollection->getNamedDBs();
-    ScDBData* pDBData = aOldNamedDBs.findByIndex(pToken->GetIndex());
-    if (!pDBData)
-        return; //invalid index
-    rtl::OUString aDBName = pDBData->GetUpperName();
-
-    //search in new document
-    ScDBCollection* pNewDBCollection = rNewDoc.GetDBCollection();
-    if (!pNewDBCollection)
-    {
-        pNewDBCollection = new ScDBCollection(&rNewDoc);
-        rNewDoc.SetDBCollection(pNewDBCollection);
-    }
-    ScDBCollection::NamedDBs& aNewNamedDBs = pNewDBCollection->getNamedDBs();
-    ScDBData* pNewDBData = aNewNamedDBs.findByUpperName(aDBName);
-    if (!pNewDBData)
-    {
-        pNewDBData = new ScDBData(*pDBData);
-        aNewNamedDBs.insert(pNewDBData);
-    }
-    pToken->SetIndex(pNewDBData->GetIndex());
-}
-
 } // namespace
 
 ScBaseCell* ScBaseCell::Clone( ScDocument& rDestDoc, int nCloneFlags ) const
@@ -388,1329 +256,4 @@ ScStringCell::~ScStringCell()
 }
 #endif
 
-// ============================================================================
-
-//
-//      ScFormulaCell
-//
-
-ScFormulaCell::ScFormulaCell( ScDocument* pDoc, const ScAddress& rPos,
-                              const rtl::OUString& rFormula,
-                              const FormulaGrammar::Grammar eGrammar,
-                              sal_uInt8 cMatInd ) :
-    ScBaseCell( CELLTYPE_FORMULA ),
-    eTempGrammar( eGrammar),
-    pCode( NULL ),
-    pDocument( pDoc ),
-    pPrevious(0),
-    pNext(0),
-    pPreviousTrack(0),
-    pNextTrack(0),
-    nFormatIndex(0),
-    nFormatType( NUMBERFORMAT_NUMBER ),
-    nSeenInIteration(0),
-    cMatrixFlag ( cMatInd ),
-    bDirty( true ), // -> Because of the use of the Auto Pilot Function was: cMatInd != 0
-    bChanged( false ),
-    bRunning( false ),
-    bCompile( false ),
-    bSubTotal( false ),
-    bIsIterCell( false ),
-    bInChangeTrack( false ),
-    bTableOpDirty( false ),
-    bNeedListening( false ),
-    aPos( rPos )
-{
-    Compile( rFormula, true, eGrammar );    // bNoListening, Insert does that
-    if (!pCode)
-        // We need to have a non-NULL token array instance at all times.
-        pCode = new ScTokenArray;
-}
-
-// Used by import filters
-
-ScFormulaCell::ScFormulaCell( ScDocument* pDoc, const ScAddress& rPos,
-                              const ScTokenArray* pArr,
-                              const FormulaGrammar::Grammar eGrammar, sal_uInt8 cInd ) :
-    ScBaseCell( CELLTYPE_FORMULA ),
-    eTempGrammar( eGrammar),
-    pCode( pArr ? new ScTokenArray( *pArr ) : new ScTokenArray ),
-    pDocument( pDoc ),
-    pPrevious(0),
-    pNext(0),
-    pPreviousTrack(0),
-    pNextTrack(0),
-    nFormatIndex(0),
-    nFormatType( NUMBERFORMAT_NUMBER ),
-    nSeenInIteration(0),
-    cMatrixFlag ( cInd ),
-    bDirty( NULL != pArr ), // -> Because of the use of the Auto Pilot Function was: cInd != 0
-    bChanged( false ),
-    bRunning( false ),
-    bCompile( false ),
-    bSubTotal( false ),
-    bIsIterCell( false ),
-    bInChangeTrack( false ),
-    bTableOpDirty( false ),
-    bNeedListening( false ),
-    aPos( rPos )
-{
-    // UPN-Array generation
-    if( pCode->GetLen() && !pCode->GetCodeError() && !pCode->GetCodeLen() )
-    {
-        ScCompiler aComp( pDocument, aPos, *pCode);
-        aComp.SetGrammar(eTempGrammar);
-        bSubTotal = aComp.CompileTokenArray();
-        nFormatType = aComp.GetNumFormatType();
-    }
-    else
-    {
-        pCode->Reset();
-        if ( pCode->GetNextOpCodeRPN( ocSubTotal ) )
-            bSubTotal = true;
-    }
-
-    if (bSubTotal)
-        pDocument->AddSubTotalCell(this);
-}
-
-ScFormulaCell::ScFormulaCell( const ScFormulaCell& rCell, ScDocument& rDoc, const ScAddress& rPos, int nCloneFlags ) :
-    ScBaseCell( rCell ),
-    SvtListener(),
-    aResult( rCell.aResult ),
-    eTempGrammar( rCell.eTempGrammar),
-    pDocument( &rDoc ),
-    pPrevious(0),
-    pNext(0),
-    pPreviousTrack(0),
-    pNextTrack(0),
-    nFormatIndex( &rDoc == rCell.pDocument ? rCell.nFormatIndex : 0 ),
-    nFormatType( rCell.nFormatType ),
-    nSeenInIteration(0),
-    cMatrixFlag ( rCell.cMatrixFlag ),
-    bDirty( rCell.bDirty ),
-    bChanged( rCell.bChanged ),
-    bRunning( false ),
-    bCompile( rCell.bCompile ),
-    bSubTotal( rCell.bSubTotal ),
-    bIsIterCell( false ),
-    bInChangeTrack( false ),
-    bTableOpDirty( false ),
-    bNeedListening( false ),
-    aPos( rPos )
-{
-    pCode = rCell.pCode->Clone();
-
-    //  set back any errors and recompile
-    //  not in the Clipboard - it must keep the received error flag
-    //  Special Length=0: as bad cells are generated, then they are also retained
-    if ( pCode->GetCodeError() && !pDocument->IsClipboard() && pCode->GetLen() )
-    {
-        pCode->SetCodeError( 0 );
-        bCompile = true;
-    }
-    //! Compile ColRowNames on URM_MOVE/URM_COPY _after_ UpdateReference
-    bool bCompileLater = false;
-    bool bClipMode = rCell.pDocument->IsClipboard();
-
-    //update ScNameTokens
-    if (!pDocument->IsClipOrUndo() || rDoc.IsUndo())
-    {
-        if (!pDocument->IsClipboardSource() || aPos.Tab() != rCell.aPos.Tab())
-        {
-            ScToken* pToken = NULL;
-            while((pToken = static_cast<ScToken*>(pCode->GetNextName()))!= NULL)
-            {
-                OpCode eOpCode = pToken->GetOpCode();
-                if (eOpCode == ocName)
-                    adjustRangeName(pToken, rDoc, rCell.pDocument, aPos, rCell.aPos);
-                else if (eOpCode == ocDBArea)
-                    adjustDBRange(pToken, rDoc, rCell.pDocument);
-            }
-        }
-
-        bool bCopyBetweenDocs = pDocument->GetPool() != rCell.pDocument->GetPool();
-        if (bCopyBetweenDocs && !(nCloneFlags & SC_CLONECELL_NOMAKEABS_EXTERNAL))
-        {
-            pCode->ReadjustAbsolute3DReferences( rCell.pDocument, &rDoc, rCell.aPos);
-        }
-
-        pCode->AdjustAbsoluteRefs( rCell.pDocument, rCell.aPos, aPos, false, bCopyBetweenDocs );
-    }
-
-    if ( nCloneFlags & SC_CLONECELL_ADJUST3DREL )
-        pCode->ReadjustRelative3DReferences( rCell.aPos, aPos );
-
-    if( !bCompile )
-    {   // Name references with references and ColRowNames
-        pCode->Reset();
-        ScToken* t;
-        while ( ( t = static_cast<ScToken*>(pCode->GetNextReferenceOrName()) ) != NULL && !bCompile )
-        {
-            if ( t->IsExternalRef() )
-            {
-                // External name, cell, and area references.
-                bCompile = true;
-            }
-            else if ( t->GetType() == svIndex )
-            {
-                ScRangeData* pRangeData = rDoc.GetRangeName()->findByIndex( t->GetIndex() );
-                if( pRangeData )
-                {
-                    if( pRangeData->HasReferences() )
-                        bCompile = true;
-                }
-                else
-                    bCompile = true;    // invalid reference!
-            }
-            else if ( t->GetOpCode() == ocColRowName )
-            {
-                bCompile = true;        // new lookup needed
-                bCompileLater = bClipMode;
-            }
-        }
-    }
-    if( bCompile )
-    {
-        if ( !bCompileLater && bClipMode )
-        {
-            // Merging ranges needs the actual positions after UpdateReference.
-            // ColRowNames need new lookup after positions are adjusted.
-            bCompileLater = pCode->HasOpCode( ocRange) || pCode->HasOpCode( ocColRowName);
-        }
-        if ( !bCompileLater )
-        {
-            // bNoListening, not at all if in Clipboard/Undo,
-            // and not from Clipboard either, instead after Insert(Clone) and UpdateReference.
-            CompileTokenArray( true );
-        }
-    }
-
-    if( nCloneFlags & SC_CLONECELL_STARTLISTENING )
-        StartListeningTo( &rDoc );
-
-    if (bSubTotal)
-        pDocument->AddSubTotalCell(this);
-}
-
-ScFormulaCell::~ScFormulaCell()
-{
-    pDocument->RemoveFromFormulaTree( this );
-    pDocument->RemoveSubTotalCell(this);
-    if (pCode->HasOpCode(ocMacro))
-        pDocument->GetMacroManager()->RemoveDependentCell(this);
-
-    if (pDocument->HasExternalRefManager())
-        pDocument->GetExternalRefManager()->removeRefCell(this);
-
-    delete pCode;
-#if OSL_DEBUG_LEVEL > 0
-    eCellType = CELLTYPE_DESTROYED;
-#endif
-}
-
-ScFormulaCell* ScFormulaCell::Clone() const
-{
-    return new ScFormulaCell(*this, *pDocument, aPos);
-}
-
-size_t ScFormulaCell::GetHash() const
-{
-    return pCode->GetHash();
-}
-
-ScFormulaVectorState ScFormulaCell::GetVectorState() const
-{
-    return pCode->GetVectorState();
-}
-
-void ScFormulaCell::GetFormula( rtl::OUStringBuffer& rBuffer,
-                                const FormulaGrammar::Grammar eGrammar ) const
-{
-    if( pCode->GetCodeError() && !pCode->GetLen() )
-    {
-        rBuffer = rtl::OUStringBuffer( ScGlobal::GetErrorString( pCode->GetCodeError()));
-        return;
-    }
-    else if( cMatrixFlag == MM_REFERENCE )
-    {
-        // Reference to another cell that contains a matrix formula.
-        pCode->Reset();
-        ScToken* p = static_cast<ScToken*>(pCode->GetNextReferenceRPN());
-        if( p )
-        {
-            /* FIXME: original GetFormula() code obtained
-             * pCell only if (!this->IsInChangeTrack()),
-             * GetEnglishFormula() omitted that test.
-             * Can we live without in all cases? */
-            ScFormulaCell* pCell = NULL;
-            ScSingleRefData& rRef = p->GetSingleRef();
-            rRef.CalcAbsIfRel( aPos );
-            if ( rRef.Valid() )
-                pCell = pDocument->GetFormulaCell(
-                    ScAddress(rRef.nCol, rRef.nRow, rRef.nTab));
-
-            if (pCell)
-            {
-                pCell->GetFormula( rBuffer, eGrammar);
-                return;
-            }
-            else
-            {
-                ScCompiler aComp( pDocument, aPos, *pCode);
-                aComp.SetGrammar(eGrammar);
-                aComp.CreateStringFromTokenArray( rBuffer );
-            }
-        }
-        else
-        {
-            OSL_FAIL("ScFormulaCell::GetFormula: not a matrix");
-        }
-    }
-    else
-    {
-        ScCompiler aComp( pDocument, aPos, *pCode);
-        aComp.SetGrammar(eGrammar);
-        aComp.CreateStringFromTokenArray( rBuffer );
-    }
-
-    sal_Unicode ch('=');
-    rBuffer.insert( 0, &ch, 1 );
-    if( cMatrixFlag )
-    {
-        sal_Unicode ch2('{');
-        rBuffer.insert( 0, &ch2, 1);
-        rBuffer.append( sal_Unicode('}'));
-    }
-}
-
-void ScFormulaCell::GetFormula( rtl::OUString& rFormula, const FormulaGrammar::Grammar eGrammar ) const
-{
-    rtl::OUStringBuffer rBuffer( rFormula );
-    GetFormula( rBuffer, eGrammar );
-    rFormula = rBuffer.makeStringAndClear();
-}
-
-void ScFormulaCell::GetResultDimensions( SCSIZE& rCols, SCSIZE& rRows )
-{
-    MaybeInterpret();
-
-    const ScMatrix* pMat = NULL;
-    if (!pCode->GetCodeError() && aResult.GetType() == svMatrixCell &&
-            ((pMat = static_cast<const ScToken*>(aResult.GetToken().get())->GetMatrix()) != 0))
-        pMat->GetDimensions( rCols, rRows );
-    else
-    {
-        rCols = 0;
-        rRows = 0;
-    }
-}
-
-void ScFormulaCell::Compile( const rtl::OUString& rFormula, bool bNoListening,
-                            const FormulaGrammar::Grammar eGrammar )
-{
-    if ( pDocument->IsClipOrUndo() )
-        return;
-    bool bWasInFormulaTree = pDocument->IsInFormulaTree( this );
-    if ( bWasInFormulaTree )
-        pDocument->RemoveFromFormulaTree( this );
-    // pCode may not deleted for queries, but must be empty
-    if ( pCode )
-        pCode->Clear();
-    ScTokenArray* pCodeOld = pCode;
-    ScCompiler aComp( pDocument, aPos);
-    aComp.SetGrammar(eGrammar);
-    pCode = aComp.CompileString( rFormula );
-    if ( pCodeOld )
-        delete pCodeOld;
-    if( !pCode->GetCodeError() )
-    {
-        if ( !pCode->GetLen() && !aResult.GetHybridFormula().isEmpty() && rFormula == aResult.GetHybridFormula() )
-        {   // not recursive CompileTokenArray/Compile/CompileTokenArray
-            if ( rFormula[0] == '=' )
-                pCode->AddBad( rFormula.copy(1) );
-            else
-                pCode->AddBad( rFormula );
-        }
-        bCompile = true;
-        CompileTokenArray( bNoListening );
-    }
-    else
-    {
-        bChanged = true;
-        pDocument->SetTextWidth(aPos, TEXTWIDTH_DIRTY);
-        pDocument->SetScriptType(aPos, SC_SCRIPTTYPE_UNKNOWN);
-    }
-    if ( bWasInFormulaTree )
-        pDocument->PutInFormulaTree( this );
-}
-
-
-void ScFormulaCell::CompileTokenArray( bool bNoListening )
-{
-    // Not already compiled?
-    if( !pCode->GetLen() && !aResult.GetHybridFormula().isEmpty() )
-        Compile( aResult.GetHybridFormula(), bNoListening, eTempGrammar);
-    else if( bCompile && !pDocument->IsClipOrUndo() && !pCode->GetCodeError() )
-    {
-        // RPN length may get changed
-        bool bWasInFormulaTree = pDocument->IsInFormulaTree( this );
-        if ( bWasInFormulaTree )
-            pDocument->RemoveFromFormulaTree( this );
-
-        // Loading from within filter? No listening yet!
-        if( pDocument->IsInsertingFromOtherDoc() )
-            bNoListening = true;
-
-        if( !bNoListening && pCode->GetCodeLen() )
-            EndListeningTo( pDocument );
-        ScCompiler aComp(pDocument, aPos, *pCode);
-        aComp.SetGrammar(pDocument->GetGrammar());
-        bSubTotal = aComp.CompileTokenArray();
-        if( !pCode->GetCodeError() )
-        {
-            nFormatType = aComp.GetNumFormatType();
-            nFormatIndex = 0;
-            bChanged = true;
-            aResult.SetToken( NULL);
-            bCompile = false;
-            if ( !bNoListening )
-                StartListeningTo( pDocument );
-        }
-        if ( bWasInFormulaTree )
-            pDocument->PutInFormulaTree( this );
-
-        if (bSubTotal)
-            pDocument->AddSubTotalCell(this);
-    }
-}
-
-
-void ScFormulaCell::CompileXML( ScProgress& rProgress )
-{
-    if ( cMatrixFlag == MM_REFERENCE )
-    {   // is already token code via ScDocFunc::EnterMatrix, ScDocument::InsertMatrixFormula
-        // just establish listeners
-        StartListeningTo( pDocument );
-        return ;
-    }
-
-    ScCompiler aComp( pDocument, aPos, *pCode);
-    aComp.SetGrammar(eTempGrammar);
-    rtl::OUString aFormula, aFormulaNmsp;
-    aComp.CreateStringFromXMLTokenArray( aFormula, aFormulaNmsp );
-    pDocument->DecXMLImportedFormulaCount( aFormula.getLength() );
-    rProgress.SetStateCountDownOnPercent( pDocument->GetXMLImportedFormulaCount() );
-    // pCode may not deleted for queries, but must be empty
-    if ( pCode )
-        pCode->Clear();
-    ScTokenArray* pCodeOld = pCode;
-    pCode = aComp.CompileString( aFormula, aFormulaNmsp );
-    delete pCodeOld;
-    if( !pCode->GetCodeError() )
-    {
-        if ( !pCode->GetLen() )
-        {
-            if ( aFormula[0] == '=' )
-                pCode->AddBad( aFormula.copy( 1 ) );
-            else
-                pCode->AddBad( aFormula );
-        }
-        bSubTotal = aComp.CompileTokenArray();
-        if( !pCode->GetCodeError() )
-        {
-            nFormatType = aComp.GetNumFormatType();
-            nFormatIndex = 0;
-            bChanged = true;
-            bCompile = false;
-            StartListeningTo( pDocument );
-        }
-
-        if (bSubTotal)
-            pDocument->AddSubTotalCell(this);
-    }
-    else
-    {
-        bChanged = true;
-        pDocument->SetTextWidth(aPos, TEXTWIDTH_DIRTY);
-        pDocument->SetScriptType(aPos, SC_SCRIPTTYPE_UNKNOWN);
-    }
-
-    //  Same as in Load: after loading, it must be known if ocMacro is in any formula
-    //  (for macro warning, CompileXML is called at the end of loading XML file)
-    if ( !pDocument->GetHasMacroFunc() && pCode->HasOpCodeRPN( ocMacro ) )
-        pDocument->SetHasMacroFunc( true );
-
-    //volatile cells must be added here for import
-    if( pCode->IsRecalcModeAlways() || pCode->IsRecalcModeForced() ||
-        pCode->IsRecalcModeOnLoad() || pCode->IsRecalcModeOnLoadOnce() )
-    {
-        // During load, only those cells that are marked explicitly dirty get
-        // recalculated.  So we need to set it dirty here.
-        SetDirtyVar();
-        pDocument->PutInFormulaTree(this);
-    }
-}
-
-
-void ScFormulaCell::CalcAfterLoad()
-{
-    bool bNewCompiled = false;
-    // If a Calc 1.0-doc is read, we have a result, but no token array
-    if( !pCode->GetLen() && !aResult.GetHybridFormula().isEmpty() )
-    {
-        Compile( aResult.GetHybridFormula(), true, eTempGrammar);
-        aResult.SetToken( NULL);
-        bDirty = true;
-        bNewCompiled = true;
-    }
-    // The UPN array is not created when a Calc 3.0-Doc has been read as the Range Names exist until now.
-    if( pCode->GetLen() && !pCode->GetCodeLen() && !pCode->GetCodeError() )
-    {
-        ScCompiler aComp(pDocument, aPos, *pCode);
-        aComp.SetGrammar(pDocument->GetGrammar());
-        bSubTotal = aComp.CompileTokenArray();
-        nFormatType = aComp.GetNumFormatType();
-        nFormatIndex = 0;
-        bDirty = true;
-        bCompile = false;
-        bNewCompiled = true;
-
-        if (bSubTotal)
-            pDocument->AddSubTotalCell(this);
-    }
-
-    // On OS/2 with broken FPU exception, we can somehow store /0 without Err503. Later on in
-    // the BLC Lib NumberFormatter crashes when doing a fabs (NAN) (# 32739 #).
-    // We iron this out here for all systems, such that we also have an Err503 here.
-    if ( aResult.IsValue() && !::rtl::math::isFinite( aResult.GetDouble() ) )
-    {
-        OSL_FAIL("Formula cell INFINITY!!! Where does this document come from?");
-        aResult.SetResultError( errIllegalFPOperation );
-        bDirty = true;
-    }
-
-    // DoubleRefs for binary operators were always a Matrix before version v5.0.
-    // Now this is only the case when when in an array formula, otherwise it's an implicit intersection
-    if ( pDocument->GetSrcVersion() < SC_MATRIX_DOUBLEREF &&
-            GetMatrixFlag() == MM_NONE && pCode->HasMatrixDoubleRefOps() )
-    {
-        cMatrixFlag = MM_FORMULA;
-        SetMatColsRows( 1, 1);
-    }
-
-    // Do the cells need to be calculated? After Load cells can contain an error code, and then start
-    // the listener and Recalculate (if needed) if not RECALCMODE_NORMAL
-    if( !bNewCompiled || !pCode->GetCodeError() )
-    {
-        StartListeningTo( pDocument );
-        if( !pCode->IsRecalcModeNormal() )
-            bDirty = true;
-    }
-    if ( pCode->IsRecalcModeAlways() )
-    {   // random(), today(), now() always stay in the FormulaTree, so that they are calculated
-        // for each F9
-        bDirty = true;
-    }
-    // No SetDirty yet, as no all Listeners are known yet (only in SetDirtyAfterLoad)
-}
-
-
-bool ScFormulaCell::MarkUsedExternalReferences()
-{
-    return pCode && pDocument->MarkUsedExternalReferences( *pCode);
-}
-
-
-void ScFormulaCell::Interpret()
-{
-    if (!IsDirtyOrInTableOpDirty() || pDocument->GetRecursionHelper().IsInReturn())
-        return;     // no double/triple processing
-
-    //! HACK:
-    //  If the call originates from a Reschedule in DdeLink update, leave dirty
-    //  Better: Do a Dde Link Update without Reschedule or do it completely asynchronously!
-    if ( pDocument->IsInDdeLinkUpdate() )
-        return;
-
-    if (bRunning)
-    {
-        if (!pDocument->GetDocOptions().IsIter())
-        {
-            aResult.SetResultError( errCircularReference );
-            return;
-        }
-
-        if (aResult.GetResultError() == errCircularReference)
-            aResult.SetResultError( 0 );
-
-        // Start or add to iteration list.
-        if (!pDocument->GetRecursionHelper().IsDoingIteration() ||
-                !pDocument->GetRecursionHelper().GetRecursionInIterationStack().top()->bIsIterCell)
-            pDocument->GetRecursionHelper().SetInIterationReturn( true);
-
-        return;
-    }
-    // no multiple interprets for GetErrCode, IsValue, GetValue and
-    // different entry point recursions. Would also lead to premature
-    // convergence in iterations.
-    if (pDocument->GetRecursionHelper().GetIteration() && nSeenInIteration ==
-            pDocument->GetRecursionHelper().GetIteration())
-        return ;
-
-    ScRecursionHelper& rRecursionHelper = pDocument->GetRecursionHelper();
-    bool bOldRunning = bRunning;
-    if (rRecursionHelper.GetRecursionCount() > MAXRECURSION)
-    {
-        bRunning = true;
-        rRecursionHelper.SetInRecursionReturn( true);
-    }
-    else
-    {
-        if ( ! InterpretFormulaGroup() )
-            InterpretTail( SCITP_NORMAL);
-    }
-
-    // While leaving a recursion or iteration stack, insert its cells to the
-    // recursion list in reverse order.
-    if (rRecursionHelper.IsInReturn())
-    {
-        if (rRecursionHelper.GetRecursionCount() > 0 ||
-                !rRecursionHelper.IsDoingRecursion())
-            rRecursionHelper.Insert( this, bOldRunning, aResult);
-        bool bIterationFromRecursion = false;
-        bool bResumeIteration = false;
-        do
-        {
-            if ((rRecursionHelper.IsInIterationReturn() &&
-                        rRecursionHelper.GetRecursionCount() == 0 &&
-                        !rRecursionHelper.IsDoingIteration()) ||
-                    bIterationFromRecursion || bResumeIteration)
-            {
-                ScFormulaCell* pIterCell = this; // scope for debug convenience
-                bool & rDone = rRecursionHelper.GetConvergingReference();
-                rDone = false;
-                if (!bIterationFromRecursion && bResumeIteration)
-                {
-                    bResumeIteration = false;
-                    // Resuming iteration expands the range.
-                    ScFormulaRecursionList::const_iterator aOldStart(
-                            rRecursionHelper.GetLastIterationStart());
-                    rRecursionHelper.ResumeIteration();
-                    // Mark new cells being in iteration.
-                    for (ScFormulaRecursionList::const_iterator aIter(
-                                rRecursionHelper.GetIterationStart()); aIter !=
-                            aOldStart; ++aIter)
-                    {
-                        pIterCell = (*aIter).pCell;
-                        pIterCell->bIsIterCell = true;
-                    }
-                    // Mark older cells dirty again, in case they converted
-                    // without accounting for all remaining cells in the circle
-                    // that weren't touched so far, e.g. conditional. Restore
-                    // backuped result.
-                    sal_uInt16 nIteration = rRecursionHelper.GetIteration();
-                    for (ScFormulaRecursionList::const_iterator aIter(
-                                aOldStart); aIter !=
-                            rRecursionHelper.GetIterationEnd(); ++aIter)
-                    {
-                        pIterCell = (*aIter).pCell;
-                        if (pIterCell->nSeenInIteration == nIteration)
-                        {
-                            if (!pIterCell->bDirty || aIter == aOldStart)
-                            {
-                                pIterCell->aResult = (*aIter).aPreviousResult;
-                            }
-                            --pIterCell->nSeenInIteration;
-                        }
-                        pIterCell->bDirty = true;
-                    }
-                }
-                else
-                {
-                    bResumeIteration = false;
-                    // Close circle once.
-                    rRecursionHelper.GetList().back().pCell->InterpretTail(
-                            SCITP_CLOSE_ITERATION_CIRCLE);
-                    // Start at 1, init things.
-                    rRecursionHelper.StartIteration();
-                    // Mark all cells being in iteration.
-                    for (ScFormulaRecursionList::const_iterator aIter(
-                                rRecursionHelper.GetIterationStart()); aIter !=
-                            rRecursionHelper.GetIterationEnd(); ++aIter)
-                    {
-                        pIterCell = (*aIter).pCell;
-                        pIterCell->bIsIterCell = true;
-                    }
-                }
-                bIterationFromRecursion = false;
-                sal_uInt16 nIterMax = pDocument->GetDocOptions().GetIterCount();
-                for ( ; rRecursionHelper.GetIteration() <= nIterMax && !rDone;
-                        rRecursionHelper.IncIteration())
-                {
-                    rDone = true;
-                    for ( ScFormulaRecursionList::iterator aIter(
-                                rRecursionHelper.GetIterationStart()); aIter !=
-                            rRecursionHelper.GetIterationEnd() &&
-                            !rRecursionHelper.IsInReturn(); ++aIter)
-                    {
-                        pIterCell = (*aIter).pCell;
-                        if (pIterCell->IsDirtyOrInTableOpDirty() &&
-                                rRecursionHelper.GetIteration() !=
-                                pIterCell->GetSeenInIteration())
-                        {
-                            (*aIter).aPreviousResult = pIterCell->aResult;
-                            pIterCell->InterpretTail( SCITP_FROM_ITERATION);
-                        }
-                        rDone = rDone && !pIterCell->IsDirtyOrInTableOpDirty();
-                    }
-                    if (rRecursionHelper.IsInReturn())
-                    {
-                        bResumeIteration = true;
-                        break;  // for
-                        // Don't increment iteration.
-                    }
-                }
-                if (!bResumeIteration)
-                {
-                    if (rDone)
-                    {
-                        for (ScFormulaRecursionList::const_iterator aIter(
-                                    rRecursionHelper.GetIterationStart());
-                                aIter != rRecursionHelper.GetIterationEnd();
-                                ++aIter)
-                        {
-                            pIterCell = (*aIter).pCell;
-                            pIterCell->bIsIterCell = false;
-                            pIterCell->nSeenInIteration = 0;
-                            pIterCell->bRunning = (*aIter).bOldRunning;
-                        }
-                    }
-                    else
-                    {
-                        for (ScFormulaRecursionList::const_iterator aIter(
-                                    rRecursionHelper.GetIterationStart());
-                                aIter != rRecursionHelper.GetIterationEnd();
-                                ++aIter)
-                        {
-                            pIterCell = (*aIter).pCell;
-                            pIterCell->bIsIterCell = false;
-                            pIterCell->nSeenInIteration = 0;
-                            pIterCell->bRunning = (*aIter).bOldRunning;
-                            // If one cell didn't converge, all cells of this
-                            // circular dependency don't, no matter whether
-                            // single cells did.
-                            pIterCell->bDirty = false;
-                            pIterCell->bTableOpDirty = false;
-                            pIterCell->aResult.SetResultError( errNoConvergence);
-                            pIterCell->bChanged = true;
-                            pDocument->SetTextWidth(pIterCell->aPos, TEXTWIDTH_DIRTY);
-                            pDocument->SetScriptType(pIterCell->aPos, SC_SCRIPTTYPE_UNKNOWN);
-                        }
-                    }
-                    // End this iteration and remove entries.
-                    rRecursionHelper.EndIteration();
-                    bResumeIteration = rRecursionHelper.IsDoingIteration();
-                }
-            }
-            if (rRecursionHelper.IsInRecursionReturn() &&
-                    rRecursionHelper.GetRecursionCount() == 0 &&
-                    !rRecursionHelper.IsDoingRecursion())
-            {
-                bIterationFromRecursion = false;
-                // Iterate over cells known so far, start with the last cell
-                // encountered, inserting new cells if another recursion limit
-                // is reached. Repeat until solved.
-                rRecursionHelper.SetDoingRecursion( true);
-                do
-                {
-                    rRecursionHelper.SetInRecursionReturn( false);
-                    for (ScFormulaRecursionList::const_iterator aIter(
-                                rRecursionHelper.GetIterationStart());
-                            !rRecursionHelper.IsInReturn() && aIter !=
-                            rRecursionHelper.GetIterationEnd(); ++aIter)
-                    {
-                        ScFormulaCell* pCell = (*aIter).pCell;
-                        if (pCell->IsDirtyOrInTableOpDirty())
-                        {
-                            pCell->InterpretTail( SCITP_NORMAL);
-                            if (!pCell->IsDirtyOrInTableOpDirty() && !pCell->IsIterCell())
-                                pCell->bRunning = (*aIter).bOldRunning;
-                        }
-                    }
-                } while (rRecursionHelper.IsInRecursionReturn());
-                rRecursionHelper.SetDoingRecursion( false);
-                if (rRecursionHelper.IsInIterationReturn())
-                {
-                    if (!bResumeIteration)
-                        bIterationFromRecursion = true;
-                }
-                else if (bResumeIteration ||
-                        rRecursionHelper.IsDoingIteration())
-                    rRecursionHelper.GetList().erase(
-                            rRecursionHelper.GetIterationStart(),
-                            rRecursionHelper.GetLastIterationStart());
-                else
-                    rRecursionHelper.Clear();
-            }
-        } while (bIterationFromRecursion || bResumeIteration);
-    }
-}
-
-void ScFormulaCell::InterpretTail( ScInterpretTailParameter eTailParam )
-{
-    class RecursionCounter
-    {
-        ScRecursionHelper&  rRec;
-        bool                bStackedInIteration;
-        public:
-        RecursionCounter( ScRecursionHelper& r, ScFormulaCell* p ) : rRec(r)
-        {
-            bStackedInIteration = rRec.IsDoingIteration();
-            if (bStackedInIteration)
-                rRec.GetRecursionInIterationStack().push( p);
-            rRec.IncRecursionCount();
-        }
-        ~RecursionCounter()
-        {
-            rRec.DecRecursionCount();
-            if (bStackedInIteration)
-                rRec.GetRecursionInIterationStack().pop();
-        }
-    } aRecursionCounter( pDocument->GetRecursionHelper(), this);
-    nSeenInIteration = pDocument->GetRecursionHelper().GetIteration();
-    if( !pCode->GetCodeLen() && !pCode->GetCodeError() )
-    {
-        // #i11719# no UPN and no error and no token code but result string present
-        // => interpretation of this cell during name-compilation and unknown names
-        // => can't exchange underlying code array in CompileTokenArray() /
-        // Compile() because interpreter's token iterator would crash or pCode
-        // would be deleted twice if this cell was interpreted during
-        // compilation.
-        // This should only be a temporary condition and, since we set an
-        // error, if ran into it again we'd bump into the dirty-clearing
-        // condition further down.
-        if ( !pCode->GetLen() && !aResult.GetHybridFormula().isEmpty() )
-        {
-            pCode->SetCodeError( errNoCode );
-            // This is worth an assertion; if encountered in daily work
-            // documents we might need another solution. Or just confirm correctness.
-            OSL_FAIL( "ScFormulaCell::Interpret: no UPN, no error, no token, but hybrid formula string" );
-            return;
-        }
-        CompileTokenArray();
-    }
-
-    if( pCode->GetCodeLen() && pDocument )
-    {
-        class StackCleaner
-        {
-            ScDocument*     pDoc;
-            ScInterpreter*  pInt;
-            public:
-            StackCleaner( ScDocument* pD, ScInterpreter* pI )
-                : pDoc(pD), pInt(pI)
-                {}
-            ~StackCleaner()
-            {
-                delete pInt;
-                pDoc->DecInterpretLevel();
-            }
-        };
-        pDocument->IncInterpretLevel();
-        ScInterpreter* p = new ScInterpreter( this, pDocument, aPos, *pCode );
-        StackCleaner aStackCleaner( pDocument, p);
-        sal_uInt16 nOldErrCode = aResult.GetResultError();
-        if ( nSeenInIteration == 0 )
-        {   // Only the first time
-            // With bChanged=false, if a newly compiled cell has a result of
-            // 0.0, no change is detected and the cell will not be repainted.
-            // bChanged = false;
-            aResult.SetResultError( 0 );
-        }
-
-        switch ( aResult.GetResultError() )
-        {
-            case errCircularReference :     // will be determined again if so
-                aResult.SetResultError( 0 );
-            break;
-        }
-
-        bool bOldRunning = bRunning;
-        bRunning = true;
-        p->Interpret();
-        if (pDocument->GetRecursionHelper().IsInReturn() && eTailParam != SCITP_CLOSE_ITERATION_CIRCLE)
-        {
-            if (nSeenInIteration > 0)
-                --nSeenInIteration;     // retry when iteration is resumed
-            return;
-        }
-        bRunning = bOldRunning;
-
-        // #i102616# For single-sheet saving consider only content changes, not format type,
-        // because format type isn't set on loading (might be changed later)
-        bool bContentChanged = false;
-
-        // Do not create a HyperLink() cell if the formula results in an error.
-        if( p->GetError() && pCode->IsHyperLink())
-            pCode->SetHyperLink(false);
-
-        if( p->GetError() && p->GetError() != errCircularReference)
-        {
-            bDirty = false;
-            bTableOpDirty = false;
-            bChanged = true;
-        }
-        if (eTailParam == SCITP_FROM_ITERATION && IsDirtyOrInTableOpDirty())
-        {
-            bool bIsValue = aResult.IsValue();  // the previous type
-            // Did it converge?
-            if ((bIsValue && p->GetResultType() == svDouble && fabs(
-                            p->GetNumResult() - aResult.GetDouble()) <=
-                        pDocument->GetDocOptions().GetIterEps()) ||
-                    (!bIsValue && p->GetResultType() == svString &&
-                     p->GetStringResult() == aResult.GetString()))
-            {
-                // A convergence in the first iteration doesn't necessarily
-                // mean that it's done, it may be as not all related cells
-                // of a circle changed their values yet. If the set really
-                // converges it will do so also during the next iteration. This
-                // fixes situations like of #i44115#. If this wasn't wanted an
-                // initial "uncalculated" value would be needed for all cells
-                // of a circular dependency => graph needed before calculation.
-                if (nSeenInIteration > 1 ||
-                        pDocument->GetDocOptions().GetIterCount() == 1)
-                {
-                    bDirty = false;
-                    bTableOpDirty = false;
-                }
-            }
-        }
-
-        // New error code?
-        if( p->GetError() != nOldErrCode )
-        {
-            bChanged = true;
-            // bContentChanged only has to be set if the file content would be changed
-            if ( aResult.GetCellResultType() != svUnknown )
-                bContentChanged = true;
-        }
-        // Different number format?
-        if( nFormatType != p->GetRetFormatType() )
-        {
-            nFormatType = p->GetRetFormatType();
-            bChanged = true;
-        }
-        if( nFormatIndex != p->GetRetFormatIndex() )
-        {
-            nFormatIndex = p->GetRetFormatIndex();
-            bChanged = true;
-        }
-
-        // In case of changes just obtain the result, no temporary and
-        // comparison needed anymore.
-        if (bChanged)
-        {
-            // #i102616# Compare anyway if the sheet is still marked unchanged for single-sheet saving
-            // Also handle special cases of initial results after loading.
-            if ( !bContentChanged && pDocument->IsStreamValid(aPos.Tab()) )
-            {
-                ScFormulaResult aNewResult( p->GetResultToken().get());
-                StackVar eOld = aResult.GetCellResultType();
-                StackVar eNew = aNewResult.GetCellResultType();
-                if ( eOld == svUnknown && ( eNew == svError || ( eNew == svDouble && aNewResult.GetDouble() == 0.0 ) ) )
-                {
-                    // ScXMLTableRowCellContext::EndElement doesn't call SetFormulaResultDouble for 0
-                    // -> no change
-                }
-                else
-                {
-                    if ( eOld == svHybridCell || eOld == svHybridValueCell )     // string result from SetFormulaResultString?
-                        eOld = svString;            // ScHybridCellToken has a valid GetString method
-
-                    // #i106045# use approxEqual to compare with stored value
-                    bContentChanged = (eOld != eNew ||
-                            (eNew == svDouble && !rtl::math::approxEqual( aResult.GetDouble(), aNewResult.GetDouble() )) ||
-                            (eNew == svString && aResult.GetString() != aNewResult.GetString()));
-                }
-            }
-
-            aResult.SetToken( p->GetResultToken().get() );
-        }
-        else
-        {
-            ScFormulaResult aNewResult( p->GetResultToken().get());
-            StackVar eOld = aResult.GetCellResultType();
-            StackVar eNew = aNewResult.GetCellResultType();
-            bChanged = (eOld != eNew ||
-                    (eNew == svDouble && aResult.GetDouble() != aNewResult.GetDouble()) ||
-                    (eNew == svString && aResult.GetString() != aNewResult.GetString()));
-
-            // #i102616# handle special cases of initial results after loading (only if the sheet is still marked unchanged)
-            if ( bChanged && !bContentChanged && pDocument->IsStreamValid(aPos.Tab()) )
-            {
-                if ( ( eOld == svUnknown && ( eNew == svError || ( eNew == svDouble && aNewResult.GetDouble() == 0.0 ) ) ) ||
-                     ( (eOld == svHybridCell || eOld == svHybridValueCell) && eNew == svString && aResult.GetString() == aNewResult.GetString() ) ||
-                     ( eOld == svDouble && eNew == svDouble && rtl::math::approxEqual( aResult.GetDouble(), aNewResult.GetDouble() ) ) )
-                {
-                    // no change, see above
-                }
-                else
-                    bContentChanged = true;
-            }
-
-            aResult.Assign( aNewResult);
-        }
-
-        // Precision as shown?
-        if ( aResult.IsValue() && !p->GetError()
-          && pDocument->GetDocOptions().IsCalcAsShown()
-          && nFormatType != NUMBERFORMAT_DATE
-          && nFormatType != NUMBERFORMAT_TIME
-          && nFormatType != NUMBERFORMAT_DATETIME )
-        {
-            sal_uLong nFormat = pDocument->GetNumberFormat( aPos );
-            if ( nFormatIndex && (nFormat % SV_COUNTRY_LANGUAGE_OFFSET) == 0 )
-                nFormat = nFormatIndex;
-            if ( (nFormat % SV_COUNTRY_LANGUAGE_OFFSET) == 0 )
-                nFormat = ScGlobal::GetStandardFormat(
-                    *pDocument->GetFormatTable(), nFormat, nFormatType );
-            aResult.SetDouble( pDocument->RoundValueAsShown(
-                        aResult.GetDouble(), nFormat));
-        }
-        if (eTailParam == SCITP_NORMAL)
-        {
-            bDirty = false;
-            bTableOpDirty = false;
-        }
-        if( aResult.GetMatrix() )
-        {
-            // If the formula wasn't entered as a matrix formula, live on with
-            // the upper left corner and let reference counting delete the matrix.
-            if( cMatrixFlag != MM_FORMULA && !pCode->IsHyperLink() )
-                aResult.SetToken( aResult.GetCellResultToken().get());
-        }
-        if ( aResult.IsValue() && !::rtl::math::isFinite( aResult.GetDouble() ) )
-        {
-            // Coded double error may occur via filter import.
-            sal_uInt16 nErr = GetDoubleErrorValue( aResult.GetDouble());
-            aResult.SetResultError( nErr);
-            bChanged = bContentChanged = true;
-        }
-        if( bChanged )
-        {
-            pDocument->SetTextWidth(aPos, TEXTWIDTH_DIRTY);
-            pDocument->SetScriptType(aPos, SC_SCRIPTTYPE_UNKNOWN);
-        }
-        if (bContentChanged && pDocument->IsStreamValid(aPos.Tab()))
-        {
-            // pass bIgnoreLock=true, because even if called from pending row height update,
-            // a changed result must still reset the stream flag
-            pDocument->SetStreamValid(aPos.Tab(), false, true);
-        }
-        if ( !pCode->IsRecalcModeAlways() )
-            pDocument->RemoveFromFormulaTree( this );
-
-        //  FORCED cells also immediately tested for validity (start macro possibly)
-
-        if ( pCode->IsRecalcModeForced() )
-        {
-            sal_uLong nValidation = ((const SfxUInt32Item*) pDocument->GetAttr(
-                    aPos.Col(), aPos.Row(), aPos.Tab(), ATTR_VALIDDATA ))->GetValue();
-            if ( nValidation )
-            {
-                const ScValidationData* pData = pDocument->GetValidationEntry( nValidation );
-                ScRefCellValue aTmpCell(this);
-                if ( pData && !pData->IsDataValid(aTmpCell, aPos))
-                    pData->DoCalcError( this );
-            }
-        }
-
-        // Reschedule slows the whole thing down considerably, thus only execute on percent change
-        ScProgress::GetInterpretProgress()->SetStateCountDownOnPercent(
-            pDocument->GetFormulaCodeInTree()/MIN_NO_CODES_PER_PROGRESS_UPDATE );
-
-        switch (p->GetVolatileType())
-        {
-            case ScInterpreter::VOLATILE:
-                // Volatile via built-in volatile functions.  No actions needed.
-            break;
-            case ScInterpreter::VOLATILE_MACRO:
-                // The formula contains a volatile macro.
-                pCode->SetExclusiveRecalcModeAlways();
-                pDocument->PutInFormulaTree(this);
-                StartListeningTo(pDocument);
-            break;
-            case ScInterpreter::NOT_VOLATILE:
-                if (pCode->IsRecalcModeAlways())
-                {
-                    // The formula was previously volatile, but no more.
-                    EndListeningTo(pDocument);
-                    pCode->SetExclusiveRecalcModeNormal();
-                }
-                else
-                {
-                    // non-volatile formula.  End listening to the area in case
-                    // it's listening due to macro module change.
-                    pDocument->EndListeningArea(BCA_LISTEN_ALWAYS, this);
-                }
-                pDocument->RemoveFromFormulaTree(this);
-            break;
-            default:
-                ;
-        }
-    }
-    else
-    {
-        // Cells with compiler errors should not be marked dirty forever
-        OSL_ENSURE( pCode->GetCodeError(), "no UPN-Code und no errors ?!?!" );
-        bDirty = false;
-        bTableOpDirty = false;
-    }
-}
-
-
-void ScFormulaCell::SetMatColsRows( SCCOL nCols, SCROW nRows, bool bDirtyFlag )
-{
-    ScMatrixFormulaCellToken* pMat = aResult.GetMatrixFormulaCellTokenNonConst();
-    if (pMat)
-        pMat->SetMatColsRows( nCols, nRows );
-    else if (nCols || nRows)
-    {
-        aResult.SetToken( new ScMatrixFormulaCellToken( nCols, nRows));
-        // Setting the new token actually forces an empty result at this top
-        // left cell, so have that recalculated.
-        SetDirty( bDirtyFlag );
-    }
-}
-
-
-void ScFormulaCell::GetMatColsRows( SCCOL & nCols, SCROW & nRows ) const
-{
-    const ScMatrixFormulaCellToken* pMat = aResult.GetMatrixFormulaCellToken();
-    if (pMat)
-        pMat->GetMatColsRows( nCols, nRows);
-    else
-    {
-        nCols = 0;
-        nRows = 0;
-    }
-}
-
-
-sal_uLong ScFormulaCell::GetStandardFormat( SvNumberFormatter& rFormatter, sal_uLong nFormat ) const
-{
-    if ( nFormatIndex && (nFormat % SV_COUNTRY_LANGUAGE_OFFSET) == 0 )
-        return nFormatIndex;
-    //! not ScFormulaCell::IsValue(), that could reinterpret the formula again.
-    if ( aResult.IsValue() )
-        return ScGlobal::GetStandardFormat( aResult.GetDouble(), rFormatter, nFormat, nFormatType );
-    else
-        return ScGlobal::GetStandardFormat( rFormatter, nFormat, nFormatType );
-}
-
-
-void ScFormulaCell::Notify( SvtBroadcaster&, const SfxHint& rHint)
-{
-    if ( !pDocument->IsInDtorClear() && !pDocument->GetHardRecalcState() )
-    {
-        const ScHint* p = PTR_CAST( ScHint, &rHint );
-        sal_uLong nHint = (p ? p->GetId() : 0);
-        if (nHint & (SC_HINT_DATACHANGED | SC_HINT_DYING | SC_HINT_TABLEOPDIRTY))
-        {
-            bool bForceTrack = false;
-            if ( nHint & SC_HINT_TABLEOPDIRTY )
-            {
-                bForceTrack = !bTableOpDirty;
-                if ( !bTableOpDirty )
-                {
-                    pDocument->AddTableOpFormulaCell( this );
-                    bTableOpDirty = true;
-                }
-            }
-            else
-            {
-                bForceTrack = !bDirty;
-                SetDirtyVar();
-            }
-            // Don't remove from FormulaTree to put in FormulaTrack to
-            // put in FormulaTree again and again, only if necessary.
-            // Any other means except RECALCMODE_ALWAYS by which a cell could
-            // be in FormulaTree if it would notify other cells through
-            // FormulaTrack which weren't in FormulaTrack/FormulaTree before?!?
-            // Yes. The new TableOpDirty made it necessary to have a
-            // forced mode where formulas may still be in FormulaTree from
-            // TableOpDirty but have to notify dependents for normal dirty.
-            if ( (bForceTrack || !pDocument->IsInFormulaTree( this )
-                    || pCode->IsRecalcModeAlways())
-                    && !pDocument->IsInFormulaTrack( this ) )
-                pDocument->AppendToFormulaTrack( this );
-        }
-    }
-}
-
-void ScFormulaCell::SetDirty( bool bDirtyFlag )
-{
-    if ( !IsInChangeTrack() )
-    {
-        if ( pDocument->GetHardRecalcState() )
-            SetDirtyVar();
-        else
-        {
-            // Multiple Formulas avoid tracking in Load and Copy compileAll
-            // by Scenario and Copy Block From Clip.
-            // If unconditional required Formula tracking is set before SetDirty
-            // bDirty = false, eg in CompileTokenArray
-            if ( !bDirty || !pDocument->IsInFormulaTree( this ) )
-            {
-                if( bDirtyFlag )
-                    SetDirtyVar();
-                pDocument->AppendToFormulaTrack( this );
-                pDocument->TrackFormulas();
-            }
-        }
-
-        if (pDocument->IsStreamValid(aPos.Tab()))
-            pDocument->SetStreamValid(aPos.Tab(), false);
-    }
-}
-
-void ScFormulaCell::SetDirtyVar()
-{
-    bDirty = true;
-    // 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() );
-}
-
-void ScFormulaCell::SetDirtyAfterLoad()
-{
-    bDirty = true;
-    if ( !pDocument->GetHardRecalcState() )
-        pDocument->PutInFormulaTree( this );
-}
-
-void ScFormulaCell::SetTableOpDirty()
-{
-    if ( !IsInChangeTrack() )
-    {
-        if ( pDocument->GetHardRecalcState() )
-            bTableOpDirty = true;
-        else
-        {
-            if ( !bTableOpDirty || !pDocument->IsInFormulaTree( this ) )
-            {
-                if ( !bTableOpDirty )
-                {
-                    pDocument->AddTableOpFormulaCell( this );
-                    bTableOpDirty = true;
-                }
-                pDocument->AppendToFormulaTrack( this );
-                pDocument->TrackFormulas( SC_HINT_TABLEOPDIRTY );
-            }
-        }
-    }
-}
-
-
-bool ScFormulaCell::IsDirtyOrInTableOpDirty() const
-{
-    return bDirty || (bTableOpDirty && pDocument->IsInInterpreterTableOp());
-}
-
-
-void ScFormulaCell::SetErrCode( sal_uInt16 n )
-{
-    /* FIXME: check the numerous places where ScTokenArray::GetCodeError() is
-     * used whether it is solely for transport of a simple result error and get
-     * rid of that abuse. */
-    pCode->SetCodeError( n );
-    // Hard set errors are transported as result type value per convention,
-    // e.g. via clipboard. ScFormulaResult::IsValue() and
-    // ScFormulaResult::GetDouble() handle that.
-    aResult.SetResultError( n );
-}
-
-void ScFormulaCell::AddRecalcMode( ScRecalcMode nBits )
-{
-    if ( (nBits & RECALCMODE_EMASK) != RECALCMODE_NORMAL )
-        bDirty = true;
-    if ( nBits & RECALCMODE_ONLOAD_ONCE )
-    {   // OnLoadOnce nur zum Dirty setzen nach Filter-Import
-        nBits = (nBits & ~RECALCMODE_EMASK) | RECALCMODE_NORMAL;
-    }
-    pCode->AddRecalcMode( nBits );
-}
-
-// Dynamically create the URLField on a mouse-over action on a hyperlink() cell.
-void ScFormulaCell::GetURLResult( rtl::OUString& rURL, rtl::OUString& rCellText )
-{
-    rtl::OUString aCellString;
-
-    Color* pColor;
-
-    // Cell Text uses the Cell format while the URL uses
-    // the default format for the type.
-    sal_uLong nCellFormat = pDocument->GetNumberFormat( aPos );
-    SvNumberFormatter* pFormatter = pDocument->GetFormatTable();
-
-    if ( (nCellFormat % SV_COUNTRY_LANGUAGE_OFFSET) == 0 )
-        nCellFormat = GetStandardFormat( *pFormatter,nCellFormat );
-
-   sal_uLong nURLFormat = ScGlobal::GetStandardFormat( *pFormatter,nCellFormat, NUMBERFORMAT_NUMBER);
-
-    if ( IsValue() )
-    {
-        double fValue = GetValue();
-        pFormatter->GetOutputString( fValue, nCellFormat, rCellText, &pColor );
-    }
-    else
-    {
-        aCellString = GetString();
-        pFormatter->GetOutputString( aCellString, nCellFormat, rCellText, &pColor );
-    }
-    ScConstMatrixRef xMat( aResult.GetMatrix());
-    if (xMat)
-    {
-        // determine if the matrix result is a string or value.
-        if (!xMat->IsValue(0, 1))
-            rURL = xMat->GetString(0, 1);
-        else
-            pFormatter->GetOutputString(
-                xMat->GetDouble(0, 1), nURLFormat, rURL, &pColor);
-    }
-
-    if(rURL.isEmpty())
-    {
-        if(IsValue())
-            pFormatter->GetOutputString( GetValue(), nURLFormat, rURL, &pColor );
-        else
-            pFormatter->GetOutputString( aCellString, nURLFormat, rURL, &pColor );
-    }
-}
-
-bool ScFormulaCell::IsMultilineResult()
-{
-    if (!IsValue())
-        return aResult.IsMultiline();
-    return false;
-}
-
-void ScFormulaCell::MaybeInterpret()
-{
-    if (!IsDirtyOrInTableOpDirty())
-        return;
-
-    if (pDocument->GetAutoCalc() || (cMatrixFlag != MM_NONE))
-        Interpret();
-}
-
-EditTextObject* ScFormulaCell::CreateURLObject()
-{
-    rtl::OUString aCellText;
-    rtl::OUString aURL;
-    GetURLResult( aURL, aCellText );
-
-    return ScEditUtil::CreateURLObjectFromURL( *pDocument, aURL, aCellText );
-}
-
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/core/data/cell2.cxx b/sc/source/core/data/cell2.cxx
index b443d65..9d8b1b9 100644
--- a/sc/source/core/data/cell2.cxx
+++ b/sc/source/core/data/cell2.cxx
@@ -17,34 +17,14 @@
  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
  */
 
-#include <algorithm>
-#include <deque>
-
-#include <boost/bind.hpp>
-#include <sal/macros.h>
-#include <vcl/mapmod.hxx>
-#include <editeng/editobj.hxx>
-#include <editeng/editstat.hxx>
-#include "editeng/fieldupdater.hxx"
-
 #include "cell.hxx"
-#include "compiler.hxx"
-#include "formula/errorcodes.hxx"
+
 #include "document.hxx"
-#include "rangenam.hxx"
-#include "rechead.hxx"
-#include "refupdat.hxx"
-#include "scmatrix.hxx"
 #include "editutil.hxx"
-#include "chgtrack.hxx"
-#include "externalrefmgr.hxx"
-#include "scitems.hxx"
-#include "patattr.hxx"
-#include <rtl/strbuf.hxx>
 
-#include <cstdio>
-
-using namespace formula;
+#include "editeng/editobj.hxx"
+#include "editeng/editstat.hxx"
+#include "editeng/fieldupdater.hxx"
 
 // STATIC DATA -----------------------------------------------------------
 
@@ -260,1725 +240,4 @@ SCROW ScEditDataArray::Item::GetRow() const
     return mnRow;
 }
 
-// ============================================================================
-
-namespace
-{
-
-using std::deque;
-
-typedef SCCOLROW(*DimensionSelector)(const ScSingleRefData&);
-
-
-static SCCOLROW lcl_GetCol(const ScSingleRefData& rData)
-{
-    return rData.nCol;
-}
-
-
-static SCCOLROW lcl_GetRow(const ScSingleRefData& rData)
-{
-    return rData.nRow;
-}
-
-
-static SCCOLROW lcl_GetTab(const ScSingleRefData& rData)
-{
-    return rData.nTab;
-}
-
-
-/** Check if both references span the same range in selected dimension.
- */
-static bool
-lcl_checkRangeDimension(
-        const SingleDoubleRefProvider& rRef1,
-        const SingleDoubleRefProvider& rRef2,
-        const DimensionSelector aWhich)
-{
-    return
-        aWhich(rRef1.Ref1) == aWhich(rRef2.Ref1)
-        && aWhich(rRef1.Ref2) == aWhich(rRef2.Ref2);
-}
-
-
-static bool
-lcl_checkRangeDimensions(
-        const SingleDoubleRefProvider& rRef1,
-        const SingleDoubleRefProvider& rRef2,
-        bool& bCol, bool& bRow, bool& bTab)
-{
-    const bool bSameCols(lcl_checkRangeDimension(rRef1, rRef2, lcl_GetCol));
-    const bool bSameRows(lcl_checkRangeDimension(rRef1, rRef2, lcl_GetRow));
-    const bool bSameTabs(lcl_checkRangeDimension(rRef1, rRef2, lcl_GetTab));
-
-    // Test if exactly two dimensions are equal
-    if (!(bSameCols ^ bSameRows ^ bSameTabs)
-            && (bSameCols || bSameRows || bSameTabs))
-    {
-        bCol = !bSameCols;
-        bRow = !bSameRows;
-        bTab = !bSameTabs;
-        return true;
-    }
-    return false;
-}
-
-
-/** Check if references in given reference list can possibly
-    form a range. To do that, two of their dimensions must be the same.
- */
-static bool
-lcl_checkRangeDimensions(
-        const deque<ScToken*>::const_iterator aBegin,
-        const deque<ScToken*>::const_iterator aEnd,
-        bool& bCol, bool& bRow, bool& bTab)
-{
-    deque<ScToken*>::const_iterator aCur(aBegin);
-    ++aCur;
-    const SingleDoubleRefProvider aRef(**aBegin);
-    bool bOk(false);
-    {
-        const SingleDoubleRefProvider aRefCur(**aCur);
-        bOk = lcl_checkRangeDimensions(aRef, aRefCur, bCol, bRow, bTab);
-    }
-    while (bOk && aCur != aEnd)
-    {
-        const SingleDoubleRefProvider aRefCur(**aCur);
-        bool bColTmp(false);
-        bool bRowTmp(false);
-        bool bTabTmp(false);
-        bOk = lcl_checkRangeDimensions(aRef, aRefCur, bColTmp, bRowTmp, bTabTmp);
-        bOk = bOk && (bCol == bColTmp && bRow == bRowTmp && bTab == bTabTmp);
-        ++aCur;
-    }
-
-    if (bOk && aCur == aEnd)
-    {
-        return true;
-    }
-    return false;
-}
-
-
-bool
-lcl_lessReferenceBy(
-        const ScToken* const pRef1, const ScToken* const pRef2,
-        const DimensionSelector aWhich)
-{
-    const SingleDoubleRefProvider rRef1(*pRef1);
-    const SingleDoubleRefProvider rRef2(*pRef2);
-    return aWhich(rRef1.Ref1) < aWhich(rRef2.Ref1);
-}
-
-
-/** Returns true if range denoted by token pRef2 starts immediately after
-    range denoted by token pRef1. Dimension, in which the comparison takes
-    place, is given by aWhich.
- */
-bool
-lcl_isImmediatelyFollowing(
-        const ScToken* const pRef1, const ScToken* const pRef2,
-        const DimensionSelector aWhich)
-{
-    const SingleDoubleRefProvider rRef1(*pRef1);
-    const SingleDoubleRefProvider rRef2(*pRef2);
-    return aWhich(rRef2.Ref1) - aWhich(rRef1.Ref2) == 1;
-}
-
-
-static bool
-lcl_checkIfAdjacent(
-        const deque<ScToken*>& rReferences,
-        const DimensionSelector aWhich)
-{
-    typedef deque<ScToken*>::const_iterator Iter;
-    Iter aBegin(rReferences.begin());
-    Iter aEnd(rReferences.end());
-    Iter aBegin1(aBegin);
-    ++aBegin1, --aEnd;
-    return std::equal(
-            aBegin, aEnd, aBegin1,
-            boost::bind(lcl_isImmediatelyFollowing, _1, _2, aWhich));
-}
-
-
-static void
-lcl_fillRangeFromRefList(
-        const deque<ScToken*>& rReferences, ScRange& rRange)
-{
-    const ScSingleRefData aStart(
-            SingleDoubleRefProvider(*rReferences.front()).Ref1);
-    rRange.aStart.Set(aStart.nCol, aStart.nRow, aStart.nTab);
-    const ScSingleRefData aEnd(
-            SingleDoubleRefProvider(*rReferences.back()).Ref2);
-    rRange.aEnd.Set(aEnd.nCol, aEnd.nRow, aEnd.nTab);
-}
-
-
-static bool
-lcl_refListFormsOneRange(
-        const ScAddress& aPos, deque<ScToken*>& rReferences,
-        ScRange& rRange)
-{
-    std::for_each(
-            rReferences.begin(), rReferences.end(),
-            bind(&ScToken::CalcAbsIfRel, _1, aPos))
-        ;
-    if (rReferences.size() == 1) {
-        lcl_fillRangeFromRefList(rReferences, rRange);
-        return true;
-    }
-
-    bool bCell(false);
-    bool bRow(false);
-    bool bTab(false);
-    if (lcl_checkRangeDimensions(rReferences.begin(), rReferences.end(),
-            bCell, bRow, bTab))
-    {
-        DimensionSelector aWhich;
-        if (bCell)
-        {
-            aWhich = lcl_GetCol;
-        }
-        else if (bRow)
-        {
-            aWhich = lcl_GetRow;
-        }
-        else if (bTab)
-        {
-            aWhich = lcl_GetTab;
-        }
-        else
-        {
-            OSL_FAIL( "lcl_checkRangeDimensions shouldn't allow that!");
-            aWhich = lcl_GetRow;    // initialize to avoid warning
-        }
-        // Sort the references by start of range
-        std::sort(rReferences.begin(), rReferences.end(),
-                boost::bind(lcl_lessReferenceBy, _1, _2, aWhich));
-        if (lcl_checkIfAdjacent(rReferences, aWhich))
-        {
-            lcl_fillRangeFromRefList(rReferences, rRange);
-            return true;
-        }
-    }
-    return false;
-}
-
-
-bool lcl_isReference(const FormulaToken& rToken)
-{
-    return
-        rToken.GetType() == svSingleRef ||
-        rToken.GetType() == svDoubleRef;
-}
-
-}
-
-bool ScFormulaCell::IsEmpty()
-{
-    MaybeInterpret();
-    return aResult.GetCellResultType() == formula::svEmptyCell;
-}
-
-bool ScFormulaCell::IsEmptyDisplayedAsString()
-{
-    MaybeInterpret();
-    return aResult.IsEmptyDisplayedAsString();
-}
-
-bool ScFormulaCell::IsValue()
-{
-    MaybeInterpret();
-    return aResult.IsValue();
-}
-
-bool ScFormulaCell::IsHybridValueCell()
-{
-    return aResult.GetType() == formula::svHybridValueCell;
-}
-
-double ScFormulaCell::GetValue()
-{
-    MaybeInterpret();
-    if ((!pCode->GetCodeError() || pCode->GetCodeError() == errDoubleRef) &&
-            !aResult.GetResultError())
-        return aResult.GetDouble();
-    return 0.0;
-}
-
-double ScFormulaCell::GetValueAlways()
-{
-    // for goal seek: return result value even if error code is set
-    MaybeInterpret();
-    return aResult.GetDouble();
-}
-
-rtl::OUString ScFormulaCell::GetString()
-{
-    MaybeInterpret();
-    if ((!pCode->GetCodeError() || pCode->GetCodeError() == errDoubleRef) &&
-            !aResult.GetResultError())
-        return aResult.GetString();
-    return rtl::OUString();
-}
-
-const ScMatrix* ScFormulaCell::GetMatrix()
-{
-    if ( pDocument->GetAutoCalc() )
-    {
-        if( IsDirtyOrInTableOpDirty()
-        // Was stored !bDirty but an accompanying matrix cell was bDirty?
-        || (!bDirty && cMatrixFlag == MM_FORMULA && !aResult.GetMatrix()))
-            Interpret();
-    }
-    return aResult.GetMatrix().get();
-}
-
-bool ScFormulaCell::GetMatrixOrigin( ScAddress& rPos ) const
-{
-    switch ( cMatrixFlag )
-    {
-        case MM_FORMULA :
-            rPos = aPos;
-            return true;
-        case MM_REFERENCE :
-        {
-            pCode->Reset();
-            ScToken* t = static_cast<ScToken*>(pCode->GetNextReferenceRPN());
-            if( t )
-            {
-                ScSingleRefData& rRef = t->GetSingleRef();
-                rRef.CalcAbsIfRel( aPos );
-                if ( rRef.Valid() )
-                {
-                    rPos.Set( rRef.nCol, rRef.nRow, rRef.nTab );
-                    return true;
-                }
-            }
-        }
-        break;
-    }
-    return false;
-}
-
-
-/*
- Edge-Values:
-
-   8
- 4   16
-   2
-
- inside: 1
- outside: 0
- (reserved: open: 32)
- */
-
-sal_uInt16 ScFormulaCell::GetMatrixEdge( ScAddress& rOrgPos )
-{
-    switch ( cMatrixFlag )
-    {
-        case MM_FORMULA :
-        case MM_REFERENCE :
-        {
-            static SCCOL nC;
-            static SCROW nR;
-            ScAddress aOrg;
-            if ( !GetMatrixOrigin( aOrg ) )
-                return 0;               // bad luck..
-            if ( aOrg != rOrgPos )
-            {   // First time or a different matrix than last time.
-                rOrgPos = aOrg;
-                ScFormulaCell* pFCell;
-                if ( cMatrixFlag == MM_REFERENCE )
-                    pFCell = pDocument->GetFormulaCell(aOrg);
-                else
-                    pFCell = this;      // this MM_FORMULA
-                // There's only one this, don't compare pFCell==this.
-                if ( pFCell && pFCell->GetCellType() == CELLTYPE_FORMULA
-                  && pFCell->cMatrixFlag == MM_FORMULA )
-                {
-                    pFCell->GetMatColsRows( nC, nR );
-                    if ( nC == 0 || nR == 0 )
-                    {
-                        // No ScMatrixFormulaCellToken available yet, calculate new.
-                        nC = 1;
-                        nR = 1;
-                        ScAddress aTmpOrg;
-                        ScFormulaCell* pCell;
-                        ScAddress aAdr( aOrg );
-                        aAdr.IncCol();

... etc. - the rest is truncated


More information about the Libreoffice-commits mailing list