diff options
author | Jim Raykowski <raykowj@gmail.com> | 2021-10-17 21:10:06 -0800 |
---|---|---|
committer | Jim Raykowski <raykowj@gmail.com> | 2021-10-21 23:35:51 +0200 |
commit | 827c0f9766f148520aed7fe3abe2b138a157a6d3 (patch) | |
tree | 63ca113d18419c9718ea000034878502149bb288 /sw | |
parent | 0cd8050ec70a4a5f02801cc38e6486defdf83bd7 (diff) |
tdf#141634 Special end of para split for folded outline node
After split place the cursor on a new blank line after the folded
content and at the same level as the split outline node.
Change-Id: I4073a1c0047ab8479993d8e605cc038896cd4630
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/123747
Tested-by: Jenkins
Reviewed-by: Jim Raykowski <raykowj@gmail.com>
Diffstat (limited to 'sw')
-rw-r--r-- | sw/source/uibase/wrtsh/wrtsh1.cxx | 134 |
1 files changed, 124 insertions, 10 deletions
diff --git a/sw/source/uibase/wrtsh/wrtsh1.cxx b/sw/source/uibase/wrtsh/wrtsh1.cxx index 215cdf2980a5..e74ac03bdec0 100644 --- a/sw/source/uibase/wrtsh/wrtsh1.cxx +++ b/sw/source/uibase/wrtsh/wrtsh1.cxx @@ -105,6 +105,10 @@ #include <frmtool.hxx> #include <viewopt.hxx> +#include <IDocumentUndoRedo.hxx> +#include <UndoInsert.hxx> +#include <UndoCore.hxx> + using namespace sw::mark; using namespace com::sun::star; namespace { @@ -994,15 +998,121 @@ void SwWrtShell::InsertFootnote(const OUString &rStr, bool bEndNote, bool bEdit m_aNavigationMgr.addEntry(aPos); } +// tdf#141634 +static bool lcl_FoldedOutlineNodeEndOfParaSplit(SwWrtShell *pThis) +{ + SwTextNode* pTextNode = pThis->GetCursor()->GetNode().GetTextNode(); + if (pTextNode && pTextNode->IsOutline()) + { + bool bVisible = true; + pTextNode->GetAttrOutlineContentVisible(bVisible); + if (!bVisible) + { + const SwNodes& rNodes = pThis->GetNodes(); + const SwOutlineNodes& rOutlineNodes = rNodes.GetOutLineNds(); + SwOutlineNodes::size_type nPos; + (void) rOutlineNodes.Seek_Entry(pTextNode, &nPos); + + SwNode* pSttNd = rOutlineNodes[nPos]; + + // determine end node of folded outline content + SwNode* pEndNd = &rNodes.GetEndOfContent(); + if (rOutlineNodes.size() > nPos + 1) + pEndNd = rOutlineNodes[nPos + 1]; + + if (pThis->GetViewOptions()->IsTreatSubOutlineLevelsAsContent()) + { + // get the next outline node after the folded outline content (iPos) + // it is the next outline node with the same level or less + int nLevel = pSttNd->GetTextNode()->GetAttrOutlineLevel(); + SwOutlineNodes::size_type iPos = nPos; + while (++iPos < rOutlineNodes.size() && + rOutlineNodes[iPos]->GetTextNode()->GetAttrOutlineLevel() > nLevel); + + // get the correct end node + // the outline node may be in frames, headers, footers special section of doc model + SwNode* pStartOfSectionNodeSttNd = pSttNd->StartOfSectionNode(); + while (pStartOfSectionNodeSttNd->StartOfSectionNode() + != pStartOfSectionNodeSttNd->StartOfSectionNode()->StartOfSectionNode()) + { + pStartOfSectionNodeSttNd = pStartOfSectionNodeSttNd->StartOfSectionNode(); + } + pEndNd = pStartOfSectionNodeSttNd->EndOfSectionNode(); + + if (iPos < rOutlineNodes.size()) + { + SwNode* pStartOfSectionNode = rOutlineNodes[iPos]->StartOfSectionNode(); + while (pStartOfSectionNode->StartOfSectionNode() + != pStartOfSectionNode->StartOfSectionNode()->StartOfSectionNode()) + { + pStartOfSectionNode = pStartOfSectionNode->StartOfSectionNode(); + } + if (pStartOfSectionNodeSttNd == pStartOfSectionNode) + pEndNd = rOutlineNodes[iPos]; + } + } + + // table, text box, header, footer + if (pSttNd->GetTableBox() || pSttNd->GetIndex() < rNodes.GetEndOfExtras().GetIndex()) + { + // insert before section end node + if (pSttNd->EndOfSectionIndex() < pEndNd->GetIndex()) + { + SwNodeIndex aIdx(*pSttNd->EndOfSectionNode()); + while (aIdx.GetNode().IsEndNode()) + --aIdx; + ++aIdx; + pEndNd = &aIdx.GetNode(); + } + } + // if pSttNd isn't in table but pEndNd is then insert after table + else if (pEndNd->GetTableBox()) + { + pEndNd = pEndNd->FindTableNode(); + SwNodeIndex aIdx(*pEndNd, -1); + // account for nested tables + while (aIdx.GetNode().GetTableBox()) + { + pEndNd = aIdx.GetNode().FindTableNode(); + aIdx.Assign(*pEndNd, -1); + } + aIdx.Assign(*pEndNd->EndOfSectionNode(), +1); + pEndNd = &aIdx.GetNode(); + } + // end node determined + + // now insert the new outline node + SwDoc* pDoc = pThis->GetDoc(); + + // insert at end of tablebox doesn't work correct without + MakeAllOutlineContentTemporarilyVisible a(pDoc); + + SwTextNode* pNd = pDoc->GetNodes().MakeTextNode(*pEndNd, pTextNode->GetTextColl(), true); + + (void) rOutlineNodes.Seek_Entry(pNd, &nPos); + pThis->GotoOutline(nPos); + + if (pDoc->GetIDocumentUndoRedo().DoesUndo()) + { + pDoc->GetIDocumentUndoRedo().ClearRedo(); + pDoc->GetIDocumentUndoRedo().AppendUndo(std::make_unique<SwUndoInsert>(*pNd)); + pDoc->GetIDocumentUndoRedo().AppendUndo(std::make_unique<SwUndoFormatColl> + (*pNd, pNd->GetTextColl(), true, true)); + } + + pThis->SetModified(); + return true; + } + } + return false; +} + // SplitNode; also, because // - of deleting selected content; // - of reset of the Cursorstack if necessary. void SwWrtShell::SplitNode( bool bAutoFormat ) { - if (!lcl_IsAllowed(this)) - return; - ResetCursorStack(); if( !CanInsert() ) return; @@ -1010,16 +1120,20 @@ void SwWrtShell::SplitNode( bool bAutoFormat ) SwActContext aActContext(this); m_rView.GetEditWin().FlushInBuffer(); + StartUndo(SwUndoId::SPLITNODE); + bool bHasSel = HasSelection(); - if( bHasSel ) - { - StartUndo( SwUndoId::INSERT ); + if (bHasSel) DelRight(); - } - SwFEShell::SplitNode( bAutoFormat ); - if( bHasSel ) - EndUndo( SwUndoId::INSERT ); + bool bHandled = false; + if (GetViewOptions()->IsShowOutlineContentVisibilityButton() && IsEndPara()) + bHandled = lcl_FoldedOutlineNodeEndOfParaSplit(this); + + if (!bHandled) + SwFEShell::SplitNode( bAutoFormat ); + + EndUndo(SwUndoId::SPLITNODE); } // Turn on numbering |