summaryrefslogtreecommitdiff
path: root/sw
diff options
context:
space:
mode:
authorDaniel Arato (NISZ) <arato.daniel@nisz.hu>2021-04-26 15:04:17 +0200
committerLászló Németh <nemeth@numbertext.org>2021-05-04 15:38:21 +0200
commit65e52cb61d74b0c71b45b63b2da131bc6b621104 (patch)
tree5bed16832369fe3d4c41c865a24db09b95bf2409 /sw
parent7f0b5f8eb234d2e1cc40055b275799df503ea736 (diff)
tdf#141613 sw: fix crash at header/footer undo
Undoing the creation of a header/footer used to leave their corresponding document nodes intact, causing the node index of a previous undo entry to point to the wrong node. We now force the destruction of the header/footer nodes manually. We also cut the redo chain which loses the redo history, but solves another crash for now (when redoing the creation of the header). The proper solution would be to create a new SwUndo* derived class from scratch to represent the creation of a new header/footer section in the document. Regression from commit 8d8486f43c1a8a51157bfc3e0b87090b05a9229e (tdf#46561 sw: fix lost undo stack setting header/footer) Change-Id: I97188aa8ded802bc6b6fa88ddd83a95c40de8bc3 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/114667 Tested-by: László Németh <nemeth@numbertext.org> Reviewed-by: László Németh <nemeth@numbertext.org>
Diffstat (limited to 'sw')
-rw-r--r--sw/qa/uitest/writer_tests7/tdf46561.py13
-rw-r--r--sw/source/core/doc/docdesc.cxx84
2 files changed, 97 insertions, 0 deletions
diff --git a/sw/qa/uitest/writer_tests7/tdf46561.py b/sw/qa/uitest/writer_tests7/tdf46561.py
index 1c90dc3c404a..7d43ed8505eb 100644
--- a/sw/qa/uitest/writer_tests7/tdf46561.py
+++ b/sw/qa/uitest/writer_tests7/tdf46561.py
@@ -97,4 +97,17 @@ class tdf46561(UITestCase):
self.ui_test.close_doc()
+ # Check that former crash has been fixed
+ def test_tdf141613(self):
+ self.ui_test.create_doc_in_start_center("writer")
+
+ xWriterDoc = self.xUITest.getTopFocusWindow()
+ xWriterEdit = xWriterDoc.getChild("writer_edit")
+
+ xArgs = mkPropertyValues({"Text": "something"})
+ self.xUITest.executeCommandWithParameters(".uno:InsertText", xArgs)
+ self.xUITest.executeCommand(".uno:InsertPageHeader")
+ self.xUITest.executeCommand(".uno:Undo")
+ self.xUITest.executeCommand(".uno:Undo")
+
# vim: set shiftwidth=4 softtabstop=4 expandtab:
diff --git a/sw/source/core/doc/docdesc.cxx b/sw/source/core/doc/docdesc.cxx
index ee08206bd7ef..4f38197f7ce9 100644
--- a/sw/source/core/doc/docdesc.cxx
+++ b/sw/source/core/doc/docdesc.cxx
@@ -424,6 +424,90 @@ void SwDoc::ChgPageDesc( size_t i, const SwPageDesc &rChged )
GetIDocumentUndoRedo().AppendUndo(std::make_unique<SwUndoPageDesc>(rDesc, rChged, this));
}
+ else
+ {
+ SwUndoId nBeingUndone;
+ GetIDocumentUndoRedo().GetFirstRedoInfo(nullptr, &nBeingUndone);
+ if (SwUndoId::HEADER_FOOTER == nBeingUndone)
+ {
+ // The last format change is currently being undone. Remove header/footer and corresponding nodes.
+ auto rDescMasterHeaderFormat = rDesc.GetMaster().GetFormatAttr(RES_HEADER);
+ auto rDescLeftHeaderFormat = rDesc.GetLeft().GetFormatAttr(RES_HEADER);
+ auto rDescFirstLeftHeaderFormat = rDesc.GetFirstLeft().GetFormatAttr(RES_HEADER);
+ auto rDescMasterFooterFormat = rDesc.GetMaster().GetFormatAttr(RES_FOOTER);
+ auto rDescLeftFooterFormat = rDesc.GetLeft().GetFormatAttr(RES_FOOTER);
+ auto rDescFirstLeftFooterFormat = rDesc.GetFirstLeft().GetFormatAttr(RES_FOOTER);
+
+ auto rChgedMasterHeaderFormat = rChged.GetMaster().GetFormatAttr(RES_HEADER);
+ auto rChgedLeftHeaderFormat = rChged.GetLeft().GetFormatAttr(RES_HEADER);
+ auto rChgedFirstLeftHeaderFormat = rChged.GetFirstLeft().GetFormatAttr(RES_HEADER);
+ auto rChgedMasterFooterFormat = rChged.GetMaster().GetFormatAttr(RES_FOOTER);
+ auto rChgedLeftFooterFormat = rChged.GetLeft().GetFormatAttr(RES_FOOTER);
+ auto rChgedFirstLeftFooterFormat = rChged.GetFirstLeft().GetFormatAttr(RES_FOOTER);
+
+ rDesc.GetMaster().ResetFormatAttr(RES_HEADER);
+ rDesc.GetLeft().ResetFormatAttr(RES_HEADER);
+ rDesc.GetFirstLeft().ResetFormatAttr(RES_HEADER);
+ rDesc.GetMaster().ResetFormatAttr(RES_FOOTER);
+ rDesc.GetLeft().ResetFormatAttr(RES_FOOTER);
+ rDesc.GetFirstLeft().ResetFormatAttr(RES_FOOTER);
+
+ auto lDelHFFormat = [this](SwClient* pToRemove, SwFrameFormat* pFormat)
+ {
+ // Code taken from lcl_DelHFFormat
+ pFormat->Remove(pToRemove);
+ SwFormatContent& rCnt = const_cast<SwFormatContent&>(pFormat->GetContent());
+ if (rCnt.GetContentIdx())
+ {
+ SwNode* pNode = nullptr;
+ {
+ SwNodeIndex aIdx(*rCnt.GetContentIdx(), 0);
+ pNode = &aIdx.GetNode();
+ sal_uInt32 nEnd = pNode->EndOfSectionIndex();
+ while (aIdx < nEnd)
+ {
+ if (pNode->IsContentNode() &&
+ static_cast<SwContentNode*>(pNode)->HasWriterListeners())
+ {
+ SwCursorShell* pShell = SwIterator<SwCursorShell, SwContentNode>(*static_cast<SwContentNode*>(pNode)).First();
+ if (pShell)
+ {
+ pShell->ParkCursor(aIdx);
+ aIdx = nEnd - 1;
+ }
+ }
+ ++aIdx;
+ pNode = &aIdx.GetNode();
+ }
+ }
+ rCnt.SetNewContentIdx(nullptr);
+
+ ::sw::UndoGuard const undoGuard(GetIDocumentUndoRedo());
+
+ assert(pNode);
+ getIDocumentContentOperations().DeleteSection(pNode);
+ }
+ delete pFormat;
+ };
+
+ if (rDescMasterHeaderFormat.GetHeaderFormat() && rDescMasterHeaderFormat != rChgedMasterHeaderFormat)
+ lDelHFFormat(&rDescMasterHeaderFormat, rDescMasterHeaderFormat.GetHeaderFormat());
+ else if (rDescLeftHeaderFormat.GetHeaderFormat() && rDescLeftHeaderFormat != rChgedLeftHeaderFormat)
+ lDelHFFormat(&rDescLeftHeaderFormat, rDescLeftHeaderFormat.GetHeaderFormat());
+ else if (rDescFirstLeftHeaderFormat.GetHeaderFormat() && rDescFirstLeftHeaderFormat != rChgedFirstLeftHeaderFormat)
+ lDelHFFormat(&rDescFirstLeftHeaderFormat, rDescFirstLeftHeaderFormat.GetHeaderFormat());
+
+ else if (rDescMasterFooterFormat.GetFooterFormat() && rDescMasterFooterFormat != rChgedMasterFooterFormat)
+ lDelHFFormat(&rDescMasterFooterFormat, rDescMasterFooterFormat.GetFooterFormat());
+ else if (rDescLeftFooterFormat.GetFooterFormat() && rDescLeftFooterFormat != rChgedLeftFooterFormat)
+ lDelHFFormat(&rDescLeftFooterFormat, rDescLeftFooterFormat.GetFooterFormat());
+ else if (rDescFirstLeftFooterFormat.GetFooterFormat() && rDescFirstLeftFooterFormat != rChgedFirstLeftFooterFormat)
+ lDelHFFormat(&rDescFirstLeftFooterFormat, rDescFirstLeftFooterFormat.GetFooterFormat());
+
+ // FIXME: Disable redoing this change until we figure out how
+ GetIDocumentUndoRedo().ClearRedo();
+ }
+ }
::sw::UndoGuard const undoGuard(GetIDocumentUndoRedo());
// Mirror at first if needed.