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
This commit is contained in:
@@ -1428,14 +1428,15 @@ void FormulaCompiler::Factor()
|
|||||||
switch( eOp )
|
switch( eOp )
|
||||||
{
|
{
|
||||||
// Functions recalculated on every document load.
|
// Functions recalculated on every document load.
|
||||||
// Don't use SetExclusiveRecalcModeOnLoad() which would
|
// ONLOAD_LENIENT here to be able to distinguish and not
|
||||||
// override ModeAlways, use
|
// force a recalc (if not in an ALWAYS or ONLOAD_MUST
|
||||||
// AddRecalcMode(ScRecalcMode::ONLOAD) instead.
|
// context) but keep an imported result from for example
|
||||||
|
// OOXML a DDE call. Will be recalculated for ODFF.
|
||||||
case ocConvertOOo :
|
case ocConvertOOo :
|
||||||
case ocDde:
|
case ocDde:
|
||||||
case ocMacro:
|
case ocMacro:
|
||||||
case ocExternal:
|
case ocExternal:
|
||||||
pArr->AddRecalcMode( ScRecalcMode::ONLOAD );
|
pArr->AddRecalcMode( ScRecalcMode::ONLOAD_LENIENT );
|
||||||
break;
|
break;
|
||||||
// If the referred cell is moved the value changes.
|
// If the referred cell is moved the value changes.
|
||||||
case ocColumn :
|
case ocColumn :
|
||||||
@@ -1443,15 +1444,15 @@ void FormulaCompiler::Factor()
|
|||||||
pArr->SetRecalcModeOnRefMove();
|
pArr->SetRecalcModeOnRefMove();
|
||||||
break;
|
break;
|
||||||
// ocCell needs recalc on move for some possible type values.
|
// 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 :
|
case ocCell :
|
||||||
pArr->SetRecalcModeOnRefMove();
|
pArr->SetRecalcModeOnRefMove();
|
||||||
pArr->AddRecalcMode( ScRecalcMode::ONLOAD );
|
pArr->AddRecalcMode( ScRecalcMode::ONLOAD_MUST );
|
||||||
break;
|
break;
|
||||||
case ocHyperLink :
|
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.
|
// get its matrix result generated.
|
||||||
pArr->AddRecalcMode( ScRecalcMode::ONLOAD );
|
pArr->AddRecalcMode( ScRecalcMode::ONLOAD_MUST );
|
||||||
pArr->SetHyperLink( true);
|
pArr->SetHyperLink( true);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@@ -845,15 +845,27 @@ FormulaToken* FormulaTokenArray::AddStringXML( const OUString& rStr )
|
|||||||
|
|
||||||
void FormulaTokenArray::AddRecalcMode( ScRecalcMode nBits )
|
void FormulaTokenArray::AddRecalcMode( ScRecalcMode nBits )
|
||||||
{
|
{
|
||||||
//! Order is important.
|
const unsigned nExclusive = static_cast<sal_uInt8>(nBits & ScRecalcMode::EMask);
|
||||||
if ( nBits & ScRecalcMode::ALWAYS )
|
if (nExclusive)
|
||||||
SetExclusiveRecalcModeAlways();
|
|
||||||
else if ( !IsRecalcModeAlways() )
|
|
||||||
{
|
{
|
||||||
if ( nBits & ScRecalcMode::ONLOAD )
|
unsigned nExBit;
|
||||||
SetExclusiveRecalcModeOnLoad();
|
if (nExclusive & (nExclusive - 1))
|
||||||
else if ( nBits & ScRecalcMode::ONLOAD_ONCE && !IsRecalcModeOnLoad() )
|
{
|
||||||
SetExclusiveRecalcModeOnLoadOnce();
|
// 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 );
|
SetCombinedBitsRecalcMode( nBits );
|
||||||
}
|
}
|
||||||
|
@@ -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,
|
// Only one of the exclusive bits can be set and one must be set,
|
||||||
// handled by TokenArray SetRecalcMode... methods
|
// handled by TokenArray SetExclusiveRecalcMode...() methods.
|
||||||
|
// Exclusive bits are ordered by priority, AddRecalcMode() relies on that.
|
||||||
enum class ScRecalcMode : sal_uInt8
|
enum class ScRecalcMode : sal_uInt8
|
||||||
{
|
{
|
||||||
NORMAL = 0x01, // exclusive
|
ALWAYS = 0x01, // exclusive, always
|
||||||
ALWAYS = 0x02, // exclusive, always
|
ONLOAD_MUST = 0x02, // exclusive, always after load
|
||||||
ONLOAD = 0x04, // exclusive, always after load
|
ONLOAD_LENIENT = 0x04, // exclusive, lenient after load (eg. macros not always, aliens, ...)
|
||||||
ONLOAD_ONCE = 0x08, // exclusive, once after load
|
ONLOAD_ONCE = 0x08, // exclusive, once after load, import filter
|
||||||
FORCED = 0x10, // combined, also if cell isn't visible
|
NORMAL = 0x10, // exclusive
|
||||||
ONREFMOVE = 0x20, // combined, if reference was moved
|
FORCED = 0x20, // combined, also if cell isn't visible, for macros with side effects
|
||||||
EMask = NORMAL | ALWAYS | ONLOAD | ONLOAD_ONCE // mask of exclusive bits
|
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
|
namespace o3tl
|
||||||
{
|
{
|
||||||
template<> struct typed_flags<ScRecalcMode> : is_typed_flags<ScRecalcMode, 0x3f> {};
|
template<> struct typed_flags<ScRecalcMode> : is_typed_flags<ScRecalcMode, 0x7f> {};
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace formula
|
namespace formula
|
||||||
@@ -281,16 +283,6 @@ public:
|
|||||||
*/
|
*/
|
||||||
sal_uInt16 RemoveToken( sal_uInt16 nOffset, sal_uInt16 nCount );
|
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();
|
FormulaTokenArray();
|
||||||
/** Assignment with incrementing references of FormulaToken entries
|
/** Assignment with incrementing references of FormulaToken entries
|
||||||
(not copied!) */
|
(not copied!) */
|
||||||
@@ -390,9 +382,21 @@ public:
|
|||||||
bool IsHyperLink() const { return bHyperLink; }
|
bool IsHyperLink() const { return bHyperLink; }
|
||||||
|
|
||||||
ScRecalcMode GetRecalcMode() const { return nMode; }
|
ScRecalcMode GetRecalcMode() const { return nMode; }
|
||||||
/** Bits aren't set directly but validated and
|
|
||||||
maybe handled according to priority if more
|
void SetCombinedBitsRecalcMode( ScRecalcMode nBits )
|
||||||
than one exclusive bit was set. */
|
{ 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 AddRecalcMode( ScRecalcMode nBits );
|
||||||
|
|
||||||
void ClearRecalcMode() { nMode = ScRecalcMode::NORMAL; }
|
void ClearRecalcMode() { nMode = ScRecalcMode::NORMAL; }
|
||||||
@@ -400,10 +404,6 @@ public:
|
|||||||
{ SetMaskedRecalcMode( ScRecalcMode::NORMAL ); }
|
{ SetMaskedRecalcMode( ScRecalcMode::NORMAL ); }
|
||||||
void SetExclusiveRecalcModeAlways()
|
void SetExclusiveRecalcModeAlways()
|
||||||
{ SetMaskedRecalcMode( ScRecalcMode::ALWAYS ); }
|
{ SetMaskedRecalcMode( ScRecalcMode::ALWAYS ); }
|
||||||
void SetExclusiveRecalcModeOnLoad()
|
|
||||||
{ SetMaskedRecalcMode( ScRecalcMode::ONLOAD ); }
|
|
||||||
void SetExclusiveRecalcModeOnLoadOnce()
|
|
||||||
{ SetMaskedRecalcMode( ScRecalcMode::ONLOAD_ONCE ); }
|
|
||||||
void SetRecalcModeForced()
|
void SetRecalcModeForced()
|
||||||
{ nMode |= ScRecalcMode::FORCED; }
|
{ nMode |= ScRecalcMode::FORCED; }
|
||||||
void SetRecalcModeOnRefMove()
|
void SetRecalcModeOnRefMove()
|
||||||
@@ -412,10 +412,6 @@ public:
|
|||||||
{ return bool(nMode & ScRecalcMode::NORMAL); }
|
{ return bool(nMode & ScRecalcMode::NORMAL); }
|
||||||
bool IsRecalcModeAlways() const
|
bool IsRecalcModeAlways() const
|
||||||
{ return bool(nMode & ScRecalcMode::ALWAYS); }
|
{ 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
|
bool IsRecalcModeForced() const
|
||||||
{ return bool(nMode & ScRecalcMode::FORCED); }
|
{ return bool(nMode & ScRecalcMode::FORCED); }
|
||||||
bool IsRecalcModeOnRefMove() const
|
bool IsRecalcModeOnRefMove() const
|
||||||
|
@@ -1371,8 +1371,7 @@ void ScFormulaCell::CompileXML( sc::CompileFormulaContext& rCxt, ScProgress& rPr
|
|||||||
pDocument->CheckLinkFormulaNeedingCheck(*pCode);
|
pDocument->CheckLinkFormulaNeedingCheck(*pCode);
|
||||||
|
|
||||||
//volatile cells must be added here for import
|
//volatile cells must be added here for import
|
||||||
if( pCode->IsRecalcModeAlways() || pCode->IsRecalcModeForced() ||
|
if( !pCode->IsRecalcModeNormal() || pCode->IsRecalcModeForced())
|
||||||
pCode->IsRecalcModeOnLoad() || pCode->IsRecalcModeOnLoadOnce() )
|
|
||||||
{
|
{
|
||||||
// During load, only those cells that are marked explicitly dirty get
|
// During load, only those cells that are marked explicitly dirty get
|
||||||
// recalculated. So we need to set it dirty here.
|
// recalculated. So we need to set it dirty here.
|
||||||
|
@@ -2744,9 +2744,7 @@ void ScInterpreter::ScDde()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Need to reinterpret after loading (build links)
|
// Need to reinterpret after loading (build links)
|
||||||
|
rArr.AddRecalcMode( ScRecalcMode::ONLOAD_LENIENT );
|
||||||
if ( rArr.IsRecalcModeNormal() )
|
|
||||||
rArr.SetExclusiveRecalcModeOnLoad();
|
|
||||||
|
|
||||||
// while the link is not evaluated, idle must be disabled (to avoid circular references)
|
// while the link is not evaluated, idle must be disabled (to avoid circular references)
|
||||||
|
|
||||||
|
@@ -2645,8 +2645,7 @@ void ScInterpreter::ScExternal()
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// enable asyncs after loading
|
// enable asyncs after loading
|
||||||
if ( rArr.IsRecalcModeNormal() )
|
rArr.AddRecalcMode( ScRecalcMode::ONLOAD_LENIENT );
|
||||||
rArr.SetExclusiveRecalcModeOnLoad();
|
|
||||||
// assure identical handler with identical call?
|
// assure identical handler with identical call?
|
||||||
double nErg = 0.0;
|
double nErg = 0.0;
|
||||||
ppParam[0] = &nErg;
|
ppParam[0] = &nErg;
|
||||||
@@ -3006,10 +3005,7 @@ void ScInterpreter::ScExternal()
|
|||||||
|
|
||||||
if ( aCall.HasVarRes() ) // handle async functions
|
if ( aCall.HasVarRes() ) // handle async functions
|
||||||
{
|
{
|
||||||
if ( rArr.IsRecalcModeNormal() )
|
rArr.AddRecalcMode( ScRecalcMode::ONLOAD_LENIENT );
|
||||||
{
|
|
||||||
rArr.SetExclusiveRecalcModeOnLoad();
|
|
||||||
}
|
|
||||||
uno::Reference<sheet::XVolatileResult> xRes = aCall.GetVarRes();
|
uno::Reference<sheet::XVolatileResult> xRes = aCall.GetVarRes();
|
||||||
ScAddInListener* pLis = ScAddInListener::Get( xRes );
|
ScAddInListener* pLis = ScAddInListener::Get( xRes );
|
||||||
if ( !pLis )
|
if ( !pLis )
|
||||||
|
@@ -310,8 +310,7 @@ void ScInterpreter::ScWebservice()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Need to reinterpret after loading (build links)
|
// Need to reinterpret after loading (build links)
|
||||||
if (rArr.IsRecalcModeNormal())
|
rArr.AddRecalcMode( ScRecalcMode::ONLOAD_LENIENT );
|
||||||
rArr.SetExclusiveRecalcModeOnLoad();
|
|
||||||
|
|
||||||
// while the link is not evaluated, idle must be disabled (to avoid circular references)
|
// while the link is not evaluated, idle must be disabled (to avoid circular references)
|
||||||
bool bOldEnabled = pDok->IsIdleEnabled();
|
bool bOldEnabled = pDok->IsIdleEnabled();
|
||||||
|
Reference in New Issue
Block a user