tdf#146356 insert new paragraph before table of contents
Alt+Enter inserts the new paragraph before the content section
of a table of contents.
At the same time protected indexes now also have the header
protected.
Change-Id: Iff267691d96796158c1593c4269b76226840c952
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/164050
Tested-by: Jenkins
Tested-by: Gabor Kelemen <gabor.kelemen.extern@allotropia.de>
Reviewed-by: Michael Stahl <michael.stahl@allotropia.de>
(cherry picked from commit aebdc79dbc5bf059ee0921a00d2795e526a52c42)
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/164128
diff --git a/sw/source/core/doc/doctxm.cxx b/sw/source/core/doc/doctxm.cxx
index f03687d..d292230 100644
--- a/sw/source/core/doc/doctxm.cxx
+++ b/sw/source/core/doc/doctxm.cxx
@@ -1057,7 +1057,7 @@ void SwTOXBaseSection::Update(const SfxItemSet* pAttr,
SwSectionFormat* pSectFormat = rDoc.MakeSectionFormat();
rDoc.GetNodes().InsertTextSection(
*pHeadNd, *pSectFormat, headerData, nullptr, &aIdx.GetNode(), true, false);
pSectFormat->GetSection()->SetProtect(SwTOXBase::IsProtected());
if (pUndo)
{
pUndo->TitleSectionInserted(*pSectFormat);
diff --git a/sw/source/core/edit/edsect.cxx b/sw/source/core/edit/edsect.cxx
index a7e652a..04ed95f 100644
--- a/sw/source/core/edit/edsect.cxx
+++ b/sw/source/core/edit/edsect.cxx
@@ -308,89 +308,114 @@ static const SwNode* lcl_SpecialInsertNode(const SwPosition* pCurrentPos)
// pInnermostNode contains the section/table before/after which we should
// insert our empty paragraph, or it will be NULL if none is found.
const SwNode* pInnermostNode = nullptr;
const SwSection* pSection = nullptr;
{
const SwNode* pTableNode = rCurrentNode.FindTableNode();
const SwNode* pSectionNode = rCurrentNode.FindSectionNode();
// find the table/section which is close
if( pTableNode == nullptr )
{
pInnermostNode = pSectionNode;
pSection = &static_cast<const SwSectionNode*>(pSectionNode)->GetSection();
}
else if ( pSectionNode == nullptr )
pInnermostNode = pTableNode;
else
{
// compare and choose the larger one
pInnermostNode =
( pSectionNode->GetIndex() > pTableNode->GetIndex() )
? pSectionNode : pTableNode;
if (pSectionNode->GetIndex() > pTableNode->GetIndex())
{
pInnermostNode = pSectionNode;
pSection = &static_cast<const SwSectionNode*>(pSectionNode)->GetSection();
}
else
pInnermostNode = pTableNode;
}
}
// The previous version had a check to skip empty read-only sections. Those
// shouldn't occur, so we only need to check whether our pInnermostNode is
// inside a protected area.
// Now, pInnermostNode is NULL or the innermost section or table node.
if( (pInnermostNode != nullptr) && !pInnermostNode->IsProtect() )
bool bIsProtected = pInnermostNode->IsProtect();
if(pInnermostNode != nullptr)
{
OSL_ENSURE( pInnermostNode->IsTableNode() ||
pInnermostNode->IsSectionNode(), "wrong node found" );
OSL_ENSURE( ( pInnermostNode->GetIndex() <= rCurrentNode.GetIndex() )&&
( pInnermostNode->EndOfSectionNode()->GetIndex() >=
rCurrentNode.GetIndex() ), "wrong node found" );
// we now need to find the possible start/end positions
// we found a start if
// - we're at or just before a start node
// - there are only start nodes between the current and pInnermostNode
SwNodeIndex aBegin( pCurrentPos->GetNode() );
if( rCurrentNode.IsContentNode() &&
(pCurrentPos->GetContentIndex() == 0))
--aBegin;
while( (aBegin != pInnermostNode->GetIndex()) &&
aBegin.GetNode().IsStartNode() )
--aBegin;
bool bStart = ( aBegin == pInnermostNode->GetIndex() );
// we found an end if
// - we're at or just before an end node
// - there are only end nodes between the current node and
// pInnermostNode's end node or
// - there are only end nodes between the last table cell merged with
// the current cell and pInnermostNode's end node
SwNodeIndex aEnd( pCurrentPos->GetNode() );
if( rCurrentNode.IsContentNode() &&
( pCurrentPos->GetContentIndex() ==
rCurrentNode.GetContentNode()->Len() ) )
//special case - ToxSection
// - in this case the inner section could be tox header
// section but the new node should be before the content section
// protection of the tox should not prevent the insertion
// only protection outside needs to be checked
if( pSection &&
(SectionType::ToxHeader == pSection->GetType() ||
SectionType::ToxContent == pSection->GetType()))
{
++aEnd;
if (SectionType::ToxHeader == pSection->GetType())
pInnermostNode = pSection->GetParent()->GetFormat()->GetSectionNode();
bIsProtected = static_cast<const SwSectionNode*>(pInnermostNode)->IsInProtectSect();
}
// tdf#156492 handle cells merged vertically in the bottom right corner
if ( pInnermostNode->IsTableNode() )
// The previous version had a check to skip empty read-only sections. Those
// shouldn't occur, so we only need to check whether our pInnermostNode is
// inside a protected area.
// Now, pInnermostNode is NULL or the innermost section or table node.
if(!bIsProtected)
{
OSL_ENSURE( pInnermostNode->IsTableNode() ||
pInnermostNode->IsSectionNode(), "wrong node found" );
OSL_ENSURE( ( pInnermostNode->GetIndex() <= rCurrentNode.GetIndex() )&&
( pInnermostNode->EndOfSectionNode()->GetIndex() >=
rCurrentNode.GetIndex() ), "wrong node found" );
// we now need to find the possible start/end positions
// we found a start if
// - we're at or just before a start node
// - there are only start nodes between the current and pInnermostNode
SwNodeIndex aBegin( pCurrentPos->GetNode() );
if( rCurrentNode.IsContentNode() &&
(pCurrentPos->GetContentIndex() == 0))
--aBegin;
while( (aBegin != pInnermostNode->GetIndex()) &&
aBegin.GetNode().IsStartNode() )
--aBegin;
bool bStart = ( aBegin == pInnermostNode->GetIndex() );
// we found an end if
// - we're at or just before an end node
// - there are only end nodes between the current node and
// pInnermostNode's end node or
// - there are only end nodes between the last table cell merged with
// the current cell and pInnermostNode's end node
SwNodeIndex aEnd( pCurrentPos->GetNode() );
if( rCurrentNode.IsContentNode() &&
( pCurrentPos->GetContentIndex() ==
rCurrentNode.GetContentNode()->Len() ) )
{
const SwNode* pTableBoxStartNode = pCurrentPos->GetNode().FindTableBoxStartNode();
const SwTableBox* pTableBox = pTableBoxStartNode->GetTableBox();
if ( pTableBox && pTableBox->getRowSpan() > 1 )
++aEnd;
// tdf#156492 handle cells merged vertically in the bottom right corner
if ( pInnermostNode->IsTableNode() )
{
const SwTableNode* pTableNd = pInnermostNode->FindTableNode();
pTableBox = & pTableBox->FindEndOfRowSpan( pTableNd->GetTable(),
pTableBox->getRowSpan() );
pTableBoxStartNode = pTableBox->GetSttNd();
aEnd = pTableBoxStartNode->GetIndex() + 2;
const SwNode* pTableBoxStartNode = pCurrentPos->GetNode().FindTableBoxStartNode();
const SwTableBox* pTableBox = pTableBoxStartNode->GetTableBox();
if ( pTableBox && pTableBox->getRowSpan() > 1 )
{
const SwTableNode* pTableNd = pInnermostNode->FindTableNode();
pTableBox = & pTableBox->FindEndOfRowSpan( pTableNd->GetTable(),
pTableBox->getRowSpan() );
pTableBoxStartNode = pTableBox->GetSttNd();
aEnd = pTableBoxStartNode->GetIndex() + 2;
}
}
}
}
while( (aEnd != pInnermostNode->EndOfSectionNode()->GetIndex()) &&
aEnd.GetNode().IsEndNode() )
++aEnd;
bool bEnd = ( aEnd == pInnermostNode->EndOfSectionNode()->GetIndex() );
while( (aEnd != pInnermostNode->EndOfSectionNode()->GetIndex()) &&
aEnd.GetNode().IsEndNode() )
++aEnd;
bool bEnd = ( aEnd == pInnermostNode->EndOfSectionNode()->GetIndex() );
// evaluate result: if both start + end, end is preferred
if( bEnd )
pReturn = pInnermostNode->EndOfSectionNode();
else if ( bStart )
pReturn = pInnermostNode;
// evaluate result: if both start + end, end is preferred
if( bEnd )
pReturn = pInnermostNode->EndOfSectionNode();
else if ( bStart )
pReturn = pInnermostNode;
}
}
OSL_ENSURE( ( pReturn == nullptr ) || pReturn->IsStartNode() ||
diff --git a/xmloff/source/text/XMLSectionExport.cxx b/xmloff/source/text/XMLSectionExport.cxx
index fc3adc0..ad525b5 100644
--- a/xmloff/source/text/XMLSectionExport.cxx
+++ b/xmloff/source/text/XMLSectionExport.cxx
@@ -308,6 +308,12 @@ void XMLSectionExport::ExportIndexHeaderStart(
// export name, dammit!
Reference<XNamed> xName(rSection, UNO_QUERY);
GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_NAME, xName->getName());
Reference<XPropertySet> xPropSet(rSection, UNO_QUERY);
Any aAny = xPropSet->getPropertyValue("IsProtected");
if (*o3tl::doAccess<bool>(aAny))
{
GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_PROTECTED, XML_TRUE);
}
// format already handled -> export only start element
GetExport().StartElement( XML_NAMESPACE_TEXT, XML_INDEX_TITLE, true );