ScAttrArray::HasAttrib needs to process the default pattern if none set
Change-Id: I00f82387ce67ce7d6e8708c7def994767cd79b6f
Reviewed-on: https://gerrit.libreoffice.org/36269
Tested-by: Jenkins <ci@libreoffice.org>
Reviewed-by: Markus Mohrhard <markus.mohrhard@googlemail.com>
diff --git a/sc/inc/attarray.hxx b/sc/inc/attarray.hxx
index a78d774..e43ff92 100644
--- a/sc/inc/attarray.hxx
+++ b/sc/inc/attarray.hxx
@@ -101,6 +101,7 @@ friend class ScHorizontalAttrIterator;
void RemoveCellCharAttribs( SCROW nStartRow, SCROW nEndRow,
const ScPatternAttr* pPattern, ScEditDataArray* pDataArray );
void SetDefaultIfNotInit( SCSIZE nNeeded = 1 );
bool HasAttrib_Impl(const ScPatternAttr* pPattern, HasAttrFlags nMask, SCROW nRow1, SCROW nRow2, SCSIZE i) const;
ScAttrArray(const ScAttrArray&) = delete;
ScAttrArray& operator=(const ScAttrArray&) = delete;
diff --git a/sc/source/core/data/attarray.cxx b/sc/source/core/data/attarray.cxx
index a55f8dc..bb81939 100644
--- a/sc/source/core/data/attarray.cxx
+++ b/sc/source/core/data/attarray.cxx
@@ -1286,12 +1286,147 @@ void ScAttrArray::ApplyBlockFrame( const SvxBoxItem* pLineOuter, const SvxBoxInf
}
}
// Test if field contains specific attribute
bool ScAttrArray::HasAttrib_Impl(const ScPatternAttr* pPattern, HasAttrFlags nMask, SCROW nRow1, SCROW nRow2, SCSIZE i) const
{
bool bFound = false;
if ( nMask & HasAttrFlags::Merged )
{
const ScMergeAttr* pMerge =
static_cast<const ScMergeAttr*>( &pPattern->GetItem( ATTR_MERGE ) );
if ( pMerge->GetColMerge() > 1 || pMerge->GetRowMerge() > 1 )
bFound = true;
}
if ( nMask & ( HasAttrFlags::Overlapped | HasAttrFlags::NotOverlapped | HasAttrFlags::AutoFilter ) )
{
const ScMergeFlagAttr* pMergeFlag =
static_cast<const ScMergeFlagAttr*>( &pPattern->GetItem( ATTR_MERGE_FLAG ) );
if ( (nMask & HasAttrFlags::Overlapped) && pMergeFlag->IsOverlapped() )
bFound = true;
if ( (nMask & HasAttrFlags::NotOverlapped) && !pMergeFlag->IsOverlapped() )
bFound = true;
if ( (nMask & HasAttrFlags::AutoFilter) && pMergeFlag->HasAutoFilter() )
bFound = true;
}
if ( nMask & HasAttrFlags::Lines )
{
const SvxBoxItem* pBox =
static_cast<const SvxBoxItem*>( &pPattern->GetItem( ATTR_BORDER ) );
if ( pBox->GetLeft() || pBox->GetRight() || pBox->GetTop() || pBox->GetBottom() )
bFound = true;
}
if ( nMask & HasAttrFlags::Shadow )
{
const SvxShadowItem* pShadow =
static_cast<const SvxShadowItem*>( &pPattern->GetItem( ATTR_SHADOW ) );
if ( pShadow->GetLocation() != SvxShadowLocation::NONE )
bFound = true;
}
if ( nMask & HasAttrFlags::Conditional )
{
bool bContainsCondFormat =
!static_cast<const ScCondFormatItem&>(pPattern->GetItem( ATTR_CONDITIONAL )).GetCondFormatData().empty();
if ( bContainsCondFormat )
bFound = true;
}
if ( nMask & HasAttrFlags::Protected )
{
const ScProtectionAttr* pProtect =
static_cast<const ScProtectionAttr*>( &pPattern->GetItem( ATTR_PROTECTION ) );
bool bFoundTemp = false;
if ( pProtect->GetProtection() || pProtect->GetHideCell() )
bFoundTemp = true;
bool bContainsCondFormat = pData &&
!static_cast<const ScCondFormatItem&>(pPattern->GetItem( ATTR_CONDITIONAL )).GetCondFormatData().empty();
if ( bContainsCondFormat && nCol != -1 ) // pDocument->GetCondResult() is valid only for real columns.
{
SCROW nRowStartCond = std::max<SCROW>( nRow1, i ? pData[i-1].nRow + 1: 0 );
SCROW nRowEndCond = std::min<SCROW>( nRow2, pData[i].nRow );
bool bFoundCond = false;
for(SCROW nRowCond = nRowStartCond; nRowCond <= nRowEndCond && !bFoundCond; ++nRowCond)
{
const SfxItemSet* pSet = pDocument->GetCondResult( nCol, nRowCond, nTab );
const SfxPoolItem* pItem;
if( pSet && pSet->GetItemState( ATTR_PROTECTION, true, &pItem ) == SfxItemState::SET )
{
const ScProtectionAttr* pCondProtect = static_cast<const ScProtectionAttr*>(pItem);
if( pCondProtect->GetProtection() || pCondProtect->GetHideCell() )
bFoundCond = true;
else
break;
}
else
{
// well it is not true that we found one
// but existing one + cell where conditional
// formatting does not remove it
// => we should use the existing protection setting
bFoundCond = bFoundTemp;
}
}
bFoundTemp = bFoundCond;
}
if(bFoundTemp)
bFound = true;
}
if ( nMask & HasAttrFlags::Rotate )
{
const SfxInt32Item* pRotate =
static_cast<const SfxInt32Item*>( &pPattern->GetItem( ATTR_ROTATE_VALUE ) );
// 90 or 270 degrees is former SvxOrientationItem - only look for other values
// (see ScPatternAttr::GetCellOrientation)
sal_Int32 nAngle = pRotate->GetValue();
if ( nAngle != 0 && nAngle != 9000 && nAngle != 27000 )
bFound = true;
}
if ( nMask & HasAttrFlags::NeedHeight )
{
if (pPattern->GetCellOrientation() != SVX_ORIENTATION_STANDARD)
bFound = true;
else if (static_cast<const SfxBoolItem&>(pPattern->GetItem( ATTR_LINEBREAK )).GetValue())
bFound = true;
else if ((SvxCellHorJustify)static_cast<const SvxHorJustifyItem&>(pPattern->
GetItem( ATTR_HOR_JUSTIFY )).GetValue() == SvxCellHorJustify::Block)
bFound = true;
else if (!static_cast<const ScCondFormatItem&>(pPattern->GetItem(ATTR_CONDITIONAL)).GetCondFormatData().empty())
bFound = true;
else if (static_cast<const SfxInt32Item&>(pPattern->GetItem( ATTR_ROTATE_VALUE )).GetValue())
bFound = true;
}
if ( nMask & ( HasAttrFlags::ShadowRight | HasAttrFlags::ShadowDown ) )
{
const SvxShadowItem* pShadow =
static_cast<const SvxShadowItem*>( &pPattern->GetItem( ATTR_SHADOW ));
SvxShadowLocation eLoc = pShadow->GetLocation();
if ( nMask & HasAttrFlags::ShadowRight )
if ( eLoc == SvxShadowLocation::TopRight || eLoc == SvxShadowLocation::BottomRight )
bFound = true;
if ( nMask & HasAttrFlags::ShadowDown )
if ( eLoc == SvxShadowLocation::BottomLeft || eLoc == SvxShadowLocation::BottomRight )
bFound = true;
}
if ( nMask & HasAttrFlags::RightOrCenter )
{
// called only if the sheet is LTR, so physical=logical alignment can be assumed
SvxCellHorJustify eHorJust = (SvxCellHorJustify)
static_cast<const SvxHorJustifyItem&>( pPattern->GetItem( ATTR_HOR_JUSTIFY )).GetValue();
if ( eHorJust == SvxCellHorJustify::Right || eHorJust == SvxCellHorJustify::Center )
bFound = true;
}
return bFound;
}
// Test if field contains specific attribute
bool ScAttrArray::HasAttrib( SCROW nRow1, SCROW nRow2, HasAttrFlags nMask ) const
{
if ( !pData )
return false;
if (!pData)
{
return HasAttrib_Impl(pDocument->GetDefPattern(), nMask, 0, MAXROW, 0);
}
SCSIZE nStartIndex;
SCSIZE nEndIndex;
@@ -1305,133 +1440,7 @@ bool ScAttrArray::HasAttrib( SCROW nRow1, SCROW nRow2, HasAttrFlags nMask ) cons
for (SCSIZE i=nStartIndex; i<=nEndIndex && !bFound; i++)
{
const ScPatternAttr* pPattern = pData[i].pPattern;
if ( nMask & HasAttrFlags::Merged )
{
const ScMergeAttr* pMerge =
static_cast<const ScMergeAttr*>( &pPattern->GetItem( ATTR_MERGE ) );
if ( pMerge->GetColMerge() > 1 || pMerge->GetRowMerge() > 1 )
bFound = true;
}
if ( nMask & ( HasAttrFlags::Overlapped | HasAttrFlags::NotOverlapped | HasAttrFlags::AutoFilter ) )
{
const ScMergeFlagAttr* pMergeFlag =
static_cast<const ScMergeFlagAttr*>( &pPattern->GetItem( ATTR_MERGE_FLAG ) );
if ( (nMask & HasAttrFlags::Overlapped) && pMergeFlag->IsOverlapped() )
bFound = true;
if ( (nMask & HasAttrFlags::NotOverlapped) && !pMergeFlag->IsOverlapped() )
bFound = true;
if ( (nMask & HasAttrFlags::AutoFilter) && pMergeFlag->HasAutoFilter() )
bFound = true;
}
if ( nMask & HasAttrFlags::Lines )
{
const SvxBoxItem* pBox =
static_cast<const SvxBoxItem*>( &pPattern->GetItem( ATTR_BORDER ) );
if ( pBox->GetLeft() || pBox->GetRight() || pBox->GetTop() || pBox->GetBottom() )
bFound = true;
}
if ( nMask & HasAttrFlags::Shadow )
{
const SvxShadowItem* pShadow =
static_cast<const SvxShadowItem*>( &pPattern->GetItem( ATTR_SHADOW ) );
if ( pShadow->GetLocation() != SvxShadowLocation::NONE )
bFound = true;
}
if ( nMask & HasAttrFlags::Conditional )
{
bool bContainsCondFormat =
!static_cast<const ScCondFormatItem&>(pPattern->GetItem( ATTR_CONDITIONAL )).GetCondFormatData().empty();
if ( bContainsCondFormat )
bFound = true;
}
if ( nMask & HasAttrFlags::Protected )
{
const ScProtectionAttr* pProtect =
static_cast<const ScProtectionAttr*>( &pPattern->GetItem( ATTR_PROTECTION ) );
bool bFoundTemp = false;
if ( pProtect->GetProtection() || pProtect->GetHideCell() )
bFoundTemp = true;
bool bContainsCondFormat =
!static_cast<const ScCondFormatItem&>(pPattern->GetItem( ATTR_CONDITIONAL )).GetCondFormatData().empty();
if ( bContainsCondFormat && nCol != -1 ) // pDocument->GetCondResult() is valid only for real columns.
{
SCROW nRowStartCond = std::max<SCROW>( nRow1, i ? pData[i-1].nRow + 1: 0 );
SCROW nRowEndCond = std::min<SCROW>( nRow2, pData[i].nRow );
bool bFoundCond = false;
for(SCROW nRowCond = nRowStartCond; nRowCond <= nRowEndCond && !bFoundCond; ++nRowCond)
{
const SfxItemSet* pSet = pDocument->GetCondResult( nCol, nRowCond, nTab );
const SfxPoolItem* pItem;
if( pSet && pSet->GetItemState( ATTR_PROTECTION, true, &pItem ) == SfxItemState::SET )
{
const ScProtectionAttr* pCondProtect = static_cast<const ScProtectionAttr*>(pItem);
if( pCondProtect->GetProtection() || pCondProtect->GetHideCell() )
bFoundCond = true;
else
break;
}
else
{
// well it is not true that we found one
// but existing one + cell where conditional
// formatting does not remove it
// => we should use the existing protection setting
bFoundCond = bFoundTemp;
}
}
bFoundTemp = bFoundCond;
}
if(bFoundTemp)
bFound = true;
}
if ( nMask & HasAttrFlags::Rotate )
{
const SfxInt32Item* pRotate =
static_cast<const SfxInt32Item*>( &pPattern->GetItem( ATTR_ROTATE_VALUE ) );
// 90 or 270 degrees is former SvxOrientationItem - only look for other values
// (see ScPatternAttr::GetCellOrientation)
sal_Int32 nAngle = pRotate->GetValue();
if ( nAngle != 0 && nAngle != 9000 && nAngle != 27000 )
bFound = true;
}
if ( nMask & HasAttrFlags::NeedHeight )
{
if (pPattern->GetCellOrientation() != SVX_ORIENTATION_STANDARD)
bFound = true;
else if (static_cast<const SfxBoolItem&>(pPattern->GetItem( ATTR_LINEBREAK )).GetValue())
bFound = true;
else if ((SvxCellHorJustify)static_cast<const SvxHorJustifyItem&>(pPattern->
GetItem( ATTR_HOR_JUSTIFY )).GetValue() == SvxCellHorJustify::Block)
bFound = true;
else if (!static_cast<const ScCondFormatItem&>(pPattern->GetItem(ATTR_CONDITIONAL)).GetCondFormatData().empty())
bFound = true;
else if (static_cast<const SfxInt32Item&>(pPattern->GetItem( ATTR_ROTATE_VALUE )).GetValue())
bFound = true;
}
if ( nMask & ( HasAttrFlags::ShadowRight | HasAttrFlags::ShadowDown ) )
{
const SvxShadowItem* pShadow =
static_cast<const SvxShadowItem*>( &pPattern->GetItem( ATTR_SHADOW ));
SvxShadowLocation eLoc = pShadow->GetLocation();
if ( nMask & HasAttrFlags::ShadowRight )
if ( eLoc == SvxShadowLocation::TopRight || eLoc == SvxShadowLocation::BottomRight )
bFound = true;
if ( nMask & HasAttrFlags::ShadowDown )
if ( eLoc == SvxShadowLocation::BottomLeft || eLoc == SvxShadowLocation::BottomRight )
bFound = true;
}
if ( nMask & HasAttrFlags::RightOrCenter )
{
// called only if the sheet is LTR, so physical=logical alignment can be assumed
SvxCellHorJustify eHorJust = (SvxCellHorJustify)
static_cast<const SvxHorJustifyItem&>( pPattern->GetItem( ATTR_HOR_JUSTIFY )).GetValue();
if ( eHorJust == SvxCellHorJustify::Right || eHorJust == SvxCellHorJustify::Center )
bFound = true;
}
bFound = HasAttrib_Impl(pPattern, nMask, nRow1, nRow2, i);
}
return bFound;