[Libreoffice-commits] core.git: formula/source include/formula sc/source

Libreoffice Gerrit user logerrit at kemper.freedesktop.org
Fri Jul 13 19:06:03 UTC 2018


 formula/source/core/api/FormulaCompiler.cxx |   17 +++----
 formula/source/core/api/token.cxx           |   28 ++++++++----
 include/formula/tokenarray.hxx              |   64 +++++++++++++---------------
 sc/source/core/data/formulacell.cxx         |    3 -
 sc/source/core/tool/interpr2.cxx            |    6 --
 sc/source/core/tool/interpr4.cxx            |    8 ---
 sc/source/core/tool/interpr7.cxx            |    3 -
 7 files changed, 65 insertions(+), 64 deletions(-)

New commits:
commit a5803a66fd9d71b72521d712ba4391ddd570bffa
Author:     Eike Rathke <erack at redhat.com>
AuthorDate: Fri Jul 13 19:29:12 2018 +0200
Commit:     Eike Rathke <erack at redhat.com>
CommitDate: Fri Jul 13 21:05:37 2018 +0200

    Rework FormulaTokenArray ScRecalcMode in preparation for tdf#94925
    
    Strictly order the exclusive bits by priority, let AddRecalcMode()
    handle all sets except forced ALWAYS or NORMAL.
    
    Introduce ONLOAD_LENIENT and ONLOAD_MUST splitting ONLOAD to be
    able to distinguish later during OOXML import.
    
    Change-Id: I188de2d53a2d54df32d24eeeb148c4f9e87e7cfc
    Reviewed-on: https://gerrit.libreoffice.org/57402
    Reviewed-by: Eike Rathke <erack at redhat.com>
    Tested-by: Jenkins

diff --git a/formula/source/core/api/FormulaCompiler.cxx b/formula/source/core/api/FormulaCompiler.cxx
index 671d2c2b9f62..ac42bd3df588 100644
--- a/formula/source/core/api/FormulaCompiler.cxx
+++ b/formula/source/core/api/FormulaCompiler.cxx
@@ -1428,14 +1428,15 @@ void FormulaCompiler::Factor()
             switch( eOp )
             {
                     // Functions recalculated on every document load.
-                    // Don't use SetExclusiveRecalcModeOnLoad() which would
-                    // override ModeAlways, use
-                    // AddRecalcMode(ScRecalcMode::ONLOAD) instead.
+                    // ONLOAD_LENIENT here to be able to distinguish and not
+                    // force a recalc (if not in an ALWAYS or ONLOAD_MUST
+                    // context) but keep an imported result from for example
+                    // OOXML a DDE call. Will be recalculated for ODFF.
                 case ocConvertOOo :
                 case ocDde:
                 case ocMacro:
                 case ocExternal:
-                    pArr->AddRecalcMode( ScRecalcMode::ONLOAD );
+                    pArr->AddRecalcMode( ScRecalcMode::ONLOAD_LENIENT );
                 break;
                     // If the referred cell is moved the value changes.
                 case ocColumn :
@@ -1443,15 +1444,15 @@ void FormulaCompiler::Factor()
                     pArr->SetRecalcModeOnRefMove();
                 break;
                     // ocCell needs recalc on move for some possible type values.
-                    // and recalc mode on load, fdo#60646
+                    // And recalc mode on load, tdf#60645
                 case ocCell :
                     pArr->SetRecalcModeOnRefMove();
-                    pArr->AddRecalcMode( ScRecalcMode::ONLOAD );
+                    pArr->AddRecalcMode( ScRecalcMode::ONLOAD_MUST );
                 break;
                 case ocHyperLink :
-                    // cell with hyperlink needs to be calculated on load to
+                    // Cell with hyperlink needs to be calculated on load to
                     // get its matrix result generated.
-                    pArr->AddRecalcMode( ScRecalcMode::ONLOAD );
+                    pArr->AddRecalcMode( ScRecalcMode::ONLOAD_MUST );
                     pArr->SetHyperLink( true);
                 break;
                 default:
diff --git a/formula/source/core/api/token.cxx b/formula/source/core/api/token.cxx
index 42b19f8543c0..a8fb0b42541d 100644
--- a/formula/source/core/api/token.cxx
+++ b/formula/source/core/api/token.cxx
@@ -845,15 +845,27 @@ FormulaToken* FormulaTokenArray::AddStringXML( const OUString& rStr )
 
 void FormulaTokenArray::AddRecalcMode( ScRecalcMode nBits )
 {
-    //! Order is important.
-    if ( nBits & ScRecalcMode::ALWAYS )
-        SetExclusiveRecalcModeAlways();
-    else if ( !IsRecalcModeAlways() )
+    const unsigned nExclusive = static_cast<sal_uInt8>(nBits & ScRecalcMode::EMask);
+    if (nExclusive)
     {
-        if ( nBits & ScRecalcMode::ONLOAD )
-            SetExclusiveRecalcModeOnLoad();
-        else if ( nBits & ScRecalcMode::ONLOAD_ONCE && !IsRecalcModeOnLoad() )
-            SetExclusiveRecalcModeOnLoadOnce();
+        unsigned nExBit;
+        if (nExclusive & (nExclusive - 1))
+        {
+            // More than one bit set, use highest priority.
+            for (nExBit = 1; (nExBit & static_cast<sal_uInt8>(ScRecalcMode::EMask)) != 0; nExBit <<= 1)
+            {
+                if (nExclusive & nExBit)
+                    break;
+            }
+        }
+        else
+        {
+            // Only one bit is set.
+            nExBit = nExclusive;
+        }
+        // Set exclusive bit if priority is higher than existing.
+        if (nExBit < static_cast<sal_uInt8>(nMode & ScRecalcMode::EMask))
+            SetMaskedRecalcMode( static_cast<ScRecalcMode>(nExBit));
     }
     SetCombinedBitsRecalcMode( nBits );
 }
diff --git a/include/formula/tokenarray.hxx b/include/formula/tokenarray.hxx
index 45669d1ad529..d4111f798d5c 100644
--- a/include/formula/tokenarray.hxx
+++ b/include/formula/tokenarray.hxx
@@ -48,24 +48,26 @@ class SharedStringPool;
 
 }
 
-// RecalcMode access only via TokenArray SetRecalcMode / IsRecalcMode...
+// RecalcMode access only via TokenArray SetExclusiveRecalcMode...() /
+// IsRecalcMode...()
 
-// Only one of the exclusive bits can be set,
-// handled by TokenArray SetRecalcMode... methods
+// Only one of the exclusive bits can be set and one must be set,
+// handled by TokenArray SetExclusiveRecalcMode...() methods.
+// Exclusive bits are ordered by priority, AddRecalcMode() relies on that.
 enum class ScRecalcMode : sal_uInt8
 {
-    NORMAL       = 0x01,    // exclusive
-    ALWAYS       = 0x02,    // exclusive, always
-    ONLOAD       = 0x04,    // exclusive, always after load
-    ONLOAD_ONCE  = 0x08,    // exclusive, once after load
-    FORCED       = 0x10,    // combined, also if cell isn't visible
-    ONREFMOVE    = 0x20,    // combined, if reference was moved
-    EMask        = NORMAL | ALWAYS | ONLOAD | ONLOAD_ONCE  // mask of exclusive bits
+    ALWAYS         = 0x01,  // exclusive, always
+    ONLOAD_MUST    = 0x02,  // exclusive, always after load
+    ONLOAD_LENIENT = 0x04,  // exclusive, lenient after load (eg. macros not always, aliens, ...)
+    ONLOAD_ONCE    = 0x08,  // exclusive, once after load, import filter
+    NORMAL         = 0x10,  // exclusive
+    FORCED         = 0x20,  // combined, also if cell isn't visible, for macros with side effects
+    ONREFMOVE      = 0x40,  // combined, if reference was moved
+    EMask          = ALWAYS | ONLOAD_MUST | ONLOAD_LENIENT | ONLOAD_ONCE | NORMAL   // mask of exclusive bits
 };
-// If new bits are to be defined, AddRecalcMode has to be adjusted!
 namespace o3tl
 {
-    template<> struct typed_flags<ScRecalcMode> : is_typed_flags<ScRecalcMode, 0x3f> {};
+    template<> struct typed_flags<ScRecalcMode> : is_typed_flags<ScRecalcMode, 0x7f> {};
 }
 
 namespace formula
@@ -281,16 +283,6 @@ public:
      */
     sal_uInt16              RemoveToken( sal_uInt16 nOffset, sal_uInt16 nCount );
 
-    void            SetCombinedBitsRecalcMode( ScRecalcMode nBits )
-                                { nMode |= (nBits & ~ScRecalcMode::EMask); }
-    ScRecalcMode    GetCombinedBitsRecalcMode() const
-                                { return nMode & ~ScRecalcMode::EMask; }
-                            /** Exclusive bits already set in nMode are
-                                zero'ed, nBits may contain combined bits, but
-                                only one exclusive bit may be set! */
-    void            SetMaskedRecalcMode( ScRecalcMode nBits )
-                                { nMode = GetCombinedBitsRecalcMode() | nBits; }
-
     FormulaTokenArray();
     /** Assignment with incrementing references of FormulaToken entries
         (not copied!) */
@@ -390,20 +382,28 @@ public:
     bool      IsHyperLink() const       { return bHyperLink; }
 
     ScRecalcMode    GetRecalcMode() const { return nMode; }
-                            /** Bits aren't set directly but validated and
-                                maybe handled according to priority if more
-                                than one exclusive bit was set. */
-            void            AddRecalcMode( ScRecalcMode nBits );
+
+    void            SetCombinedBitsRecalcMode( ScRecalcMode nBits )
+                                { nMode |= (nBits & ~ScRecalcMode::EMask); }
+    ScRecalcMode    GetCombinedBitsRecalcMode() const
+                                { return nMode & ~ScRecalcMode::EMask; }
+
+                    /** Exclusive bits already set in nMode are zero'ed, nBits
+                        may contain combined bits, but only one exclusive bit
+                        may be set! */
+    void            SetMaskedRecalcMode( ScRecalcMode nBits )
+                                { nMode = GetCombinedBitsRecalcMode() | nBits; }
+
+                    /** Bits aren't set directly but validated and handled
+                        according to priority if more than one exclusive bit
+                        was set. */
+    void            AddRecalcMode( ScRecalcMode nBits );
 
     void            ClearRecalcMode() { nMode = ScRecalcMode::NORMAL; }
     void            SetExclusiveRecalcModeNormal()
                                 { SetMaskedRecalcMode( ScRecalcMode::NORMAL ); }
     void            SetExclusiveRecalcModeAlways()
                                 { SetMaskedRecalcMode( ScRecalcMode::ALWAYS ); }
-    void            SetExclusiveRecalcModeOnLoad()
-                                { SetMaskedRecalcMode( ScRecalcMode::ONLOAD ); }
-    void            SetExclusiveRecalcModeOnLoadOnce()
-                                { SetMaskedRecalcMode( ScRecalcMode::ONLOAD_ONCE ); }
     void            SetRecalcModeForced()
                                 { nMode |= ScRecalcMode::FORCED; }
     void            SetRecalcModeOnRefMove()
@@ -412,10 +412,6 @@ public:
                                 { return bool(nMode & ScRecalcMode::NORMAL); }
     bool            IsRecalcModeAlways() const
                                 { return bool(nMode & ScRecalcMode::ALWAYS); }
-    bool            IsRecalcModeOnLoad() const
-                                { return bool(nMode & ScRecalcMode::ONLOAD); }
-    bool            IsRecalcModeOnLoadOnce() const
-                                { return bool(nMode & ScRecalcMode::ONLOAD_ONCE); }
     bool            IsRecalcModeForced() const
                                 { return bool(nMode & ScRecalcMode::FORCED); }
     bool            IsRecalcModeOnRefMove() const
diff --git a/sc/source/core/data/formulacell.cxx b/sc/source/core/data/formulacell.cxx
index e370deaacb6c..7377144d8b5b 100644
--- a/sc/source/core/data/formulacell.cxx
+++ b/sc/source/core/data/formulacell.cxx
@@ -1371,8 +1371,7 @@ void ScFormulaCell::CompileXML( sc::CompileFormulaContext& rCxt, ScProgress& rPr
     pDocument->CheckLinkFormulaNeedingCheck(*pCode);
 
     //volatile cells must be added here for import
-    if( pCode->IsRecalcModeAlways() || pCode->IsRecalcModeForced() ||
-        pCode->IsRecalcModeOnLoad() || pCode->IsRecalcModeOnLoadOnce() )
+    if( !pCode->IsRecalcModeNormal() || pCode->IsRecalcModeForced())
     {
         // During load, only those cells that are marked explicitly dirty get
         // recalculated.  So we need to set it dirty here.
diff --git a/sc/source/core/tool/interpr2.cxx b/sc/source/core/tool/interpr2.cxx
index 682867b8ef18..299fecb359f3 100644
--- a/sc/source/core/tool/interpr2.cxx
+++ b/sc/source/core/tool/interpr2.cxx
@@ -2743,10 +2743,8 @@ void ScInterpreter::ScDde()
             return;
         }
 
-            // Need to reinterpret after loading (build links)
-
-        if ( rArr.IsRecalcModeNormal() )
-            rArr.SetExclusiveRecalcModeOnLoad();
+        // Need to reinterpret after loading (build links)
+        rArr.AddRecalcMode( ScRecalcMode::ONLOAD_LENIENT );
 
             //  while the link is not evaluated, idle must be disabled (to avoid circular references)
 
diff --git a/sc/source/core/tool/interpr4.cxx b/sc/source/core/tool/interpr4.cxx
index 6194fa5abe02..138ee8c14f1b 100644
--- a/sc/source/core/tool/interpr4.cxx
+++ b/sc/source/core/tool/interpr4.cxx
@@ -2645,8 +2645,7 @@ void ScInterpreter::ScExternal()
                 else
                 {
                     // enable asyncs after loading
-                    if ( rArr.IsRecalcModeNormal() )
-                        rArr.SetExclusiveRecalcModeOnLoad();
+                    rArr.AddRecalcMode( ScRecalcMode::ONLOAD_LENIENT );
                     // assure identical handler with identical call?
                     double nErg = 0.0;
                     ppParam[0] = &nErg;
@@ -3006,10 +3005,7 @@ void ScInterpreter::ScExternal()
 
             if ( aCall.HasVarRes() )                        // handle async functions
             {
-                if ( rArr.IsRecalcModeNormal() )
-                {
-                    rArr.SetExclusiveRecalcModeOnLoad();
-                }
+                rArr.AddRecalcMode( ScRecalcMode::ONLOAD_LENIENT );
                 uno::Reference<sheet::XVolatileResult> xRes = aCall.GetVarRes();
                 ScAddInListener* pLis = ScAddInListener::Get( xRes );
                 if ( !pLis )
diff --git a/sc/source/core/tool/interpr7.cxx b/sc/source/core/tool/interpr7.cxx
index cdd0991978e4..ab8e0092985a 100644
--- a/sc/source/core/tool/interpr7.cxx
+++ b/sc/source/core/tool/interpr7.cxx
@@ -310,8 +310,7 @@ void ScInterpreter::ScWebservice()
         }
 
         // Need to reinterpret after loading (build links)
-        if (rArr.IsRecalcModeNormal())
-            rArr.SetExclusiveRecalcModeOnLoad();
+        rArr.AddRecalcMode( ScRecalcMode::ONLOAD_LENIENT );
 
         //  while the link is not evaluated, idle must be disabled (to avoid circular references)
         bool bOldEnabled = pDok->IsIdleEnabled();


More information about the Libreoffice-commits mailing list