diff options
author | Eike Rathke <erack@redhat.com> | 2018-07-13 19:29:12 +0200 |
---|---|---|
committer | Eike Rathke <erack@redhat.com> | 2018-07-13 21:05:37 +0200 |
commit | a5803a66fd9d71b72521d712ba4391ddd570bffa (patch) | |
tree | e0155db119242e9a88b3a41007e7de91634a01ec | |
parent | e92dcc0632dbdecbc561a35530c21ea66c04f85a (diff) |
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@redhat.com>
Tested-by: Jenkins
-rw-r--r-- | formula/source/core/api/FormulaCompiler.cxx | 17 | ||||
-rw-r--r-- | formula/source/core/api/token.cxx | 28 | ||||
-rw-r--r-- | include/formula/tokenarray.hxx | 64 | ||||
-rw-r--r-- | sc/source/core/data/formulacell.cxx | 3 | ||||
-rw-r--r-- | sc/source/core/tool/interpr2.cxx | 6 | ||||
-rw-r--r-- | sc/source/core/tool/interpr4.cxx | 8 | ||||
-rw-r--r-- | sc/source/core/tool/interpr7.cxx | 3 |
7 files changed, 65 insertions, 64 deletions
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(); |