[Libreoffice-commits] core.git: sw/inc sw/qa sw/source
Miklos Vajna (via logerrit)
logerrit at kemper.freedesktop.org
Tue Sep 28 06:11:14 UTC 2021
sw/inc/ndtxt.hxx | 6 +++++
sw/qa/core/txtnode/data/fly-anchor-undo.odt |binary
sw/qa/core/txtnode/txtnode.cxx | 25 +++++++++++++++++++++
sw/source/core/txtnode/ndtxt.cxx | 33 +++++++++++++++++-----------
sw/source/core/undo/undel.cxx | 2 +
5 files changed, 54 insertions(+), 12 deletions(-)
New commits:
commit 1734e97222324c137ecd084ad2464abdff2698d1
Author: Miklos Vajna <vmiklos at collabora.com>
AuthorDate: Mon Sep 27 19:59:54 2021 +0200
Commit: Miklos Vajna <vmiklos at collabora.com>
CommitDate: Tue Sep 28 08:10:40 2021 +0200
tdf#143819 sw: fix undo not restoring adjusted anchor
Regression from commit 0a4d77f35e96e4dfdf69cc5ceb788ddaa849084c
(SwTxtNode::Update: don't move anchors at insert position, 2014-10-06),
the problem is that in case backspace adjusts the anchor point of a fly
and undo does an insert (which now doesn't adjust the anchor point),
then the user action and its undo is not in sync.
Fix this by informing SwTextNode::Update() if an undo is in progress and
doing the old behavior in that case.
Change-Id: I0b3f3954be11420846f84287e486b993b2dc39e8
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/122727
Tested-by: Jenkins
Reviewed-by: Miklos Vajna <vmiklos at collabora.com>
diff --git a/sw/inc/ndtxt.hxx b/sw/inc/ndtxt.hxx
index 6b64fdef8b19..d3320d995d06 100644
--- a/sw/inc/ndtxt.hxx
+++ b/sw/inc/ndtxt.hxx
@@ -117,6 +117,9 @@ class SW_DLLPUBLIC SwTextNode final
Needed to avoid duplicate handling of attribute change actions. */
bool mbInSetOrResetAttr;
+ /// Is an undo operation in progress?
+ bool m_bInUndo;
+
std::optional< OUString > m_oNumStringCache;
css::uno::WeakReference<css::text::XTextContent> m_wXParagraph;
@@ -790,6 +793,7 @@ public:
/// sfx2::Metadatable
virtual ::sfx2::IXmlIdRegistry& GetRegistry() override;
virtual bool IsInClipboard() const override;
+ /// Is this node in the undo array?
virtual bool IsInUndo() const override;
virtual bool IsInContent() const override;
virtual css::uno::Reference< css::rdf::XMetadatable > MakeUnoObject() override;
@@ -811,6 +815,8 @@ public:
static bool IsIgnoredCharFormatForNumbering(const sal_uInt16 nWhich, bool bIsCharStyle = false);
void FormatDropNotify(const SwFormatDrop& rDrop) override
{ TriggerNodeUpdate(sw::LegacyModifyHint(&rDrop, &rDrop)); };
+
+ void SetInSwUndo(bool bInUndo);
};
inline SwpHints & SwTextNode::GetSwpHints()
diff --git a/sw/qa/core/txtnode/data/fly-anchor-undo.odt b/sw/qa/core/txtnode/data/fly-anchor-undo.odt
new file mode 100644
index 000000000000..dd2093161fa5
Binary files /dev/null and b/sw/qa/core/txtnode/data/fly-anchor-undo.odt differ
diff --git a/sw/qa/core/txtnode/txtnode.cxx b/sw/qa/core/txtnode/txtnode.cxx
index f4bb070ac972..5b43ee8591f0 100644
--- a/sw/qa/core/txtnode/txtnode.cxx
+++ b/sw/qa/core/txtnode/txtnode.cxx
@@ -154,6 +154,31 @@ CPPUNIT_TEST_FIXTURE(SwCoreTxtnodeTest, testTitleFieldInvalidate)
comphelper::LibreOfficeKit::setActive(false);
}
+CPPUNIT_TEST_FIXTURE(SwCoreTxtnodeTest, testFlyAnchorUndo)
+{
+ // Given a document with a fly frame, anchored after the last char of the document:
+ load(DATA_DIRECTORY, "fly-anchor-undo.odt");
+ SwXTextDocument* pTextDoc = dynamic_cast<SwXTextDocument*>(mxComponent.get());
+ SwDocShell* pShell = pTextDoc->GetDocShell();
+ SwDoc* pDoc = pShell->GetDoc();
+ const SwFrameFormats& rSpz = *pDoc->GetSpzFrameFormats();
+ sal_Int32 nExpected = rSpz[0]->GetAnchor().GetContentAnchor()->nContent.GetIndex();
+
+ // When deleting that last character and undoing it:
+ SwWrtShell* pWrtShell = pShell->GetWrtShell();
+ pWrtShell->SttEndDoc(/*bStt=*/false);
+ pWrtShell->DelLeft();
+ pWrtShell->Undo();
+
+ // Then make sure the anchor position after the undo is the same as the original:
+ sal_Int32 nActual = rSpz[0]->GetAnchor().GetContentAnchor()->nContent.GetIndex();
+ // Without the accompanying fix in place, this test would have failed with:
+ // - Expected: 3
+ // - Actual : 2
+ // i.e. the anchor position was left unchanged by the undo.
+ CPPUNIT_ASSERT_EQUAL(nExpected, nActual);
+}
+
CPPUNIT_PLUGIN_IMPLEMENT();
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/txtnode/ndtxt.cxx b/sw/source/core/txtnode/ndtxt.cxx
index 05548bb3e69b..8d5a58eccb25 100644
--- a/sw/source/core/txtnode/ndtxt.cxx
+++ b/sw/source/core/txtnode/ndtxt.cxx
@@ -194,7 +194,8 @@ SwTextNode::SwTextNode( const SwNodeIndex &rWhere, SwTextFormatColl *pTextColl,
m_bLastOutlineState( false ),
m_bNotifiable( false ),
mbEmptyListStyleSetDueToSetOutlineLevelAttr( false ),
- mbInSetOrResetAttr( false )
+ mbInSetOrResetAttr( false ),
+ m_bInUndo(false)
{
InitSwParaStatistics( true );
@@ -1426,20 +1427,23 @@ void SwTextNode::Update(
}
// at-char anchored flys shouldn't be moved, either.
- std::vector<SwFrameFormat*> const& rFlys(GetAnchoredFlys());
- for (size_t i = 0; i != rFlys.size(); ++i)
+ if (!m_bInUndo)
{
- SwFrameFormat const*const pFormat = rFlys[i];
- const SwFormatAnchor& rAnchor = pFormat->GetAnchor();
- const SwPosition* pContentAnchor = rAnchor.GetContentAnchor();
- if (rAnchor.GetAnchorId() == RndStdIds::FLY_AT_CHAR && pContentAnchor)
+ std::vector<SwFrameFormat*> const& rFlys(GetAnchoredFlys());
+ for (size_t i = 0; i != rFlys.size(); ++i)
{
- // The fly is at-char anchored and has an anchor position.
- SwIndex& rEndIdx = const_cast<SwIndex&>(pContentAnchor->nContent);
- if (&pContentAnchor->nNode.GetNode() == this && rEndIdx.GetIndex() == rPos.GetIndex())
+ SwFrameFormat const*const pFormat = rFlys[i];
+ const SwFormatAnchor& rAnchor = pFormat->GetAnchor();
+ const SwPosition* pContentAnchor = rAnchor.GetContentAnchor();
+ if (rAnchor.GetAnchorId() == RndStdIds::FLY_AT_CHAR && pContentAnchor)
{
- // The anchor position is exactly our insert position.
- rEndIdx.Assign(&aTmpIdxReg, rEndIdx.GetIndex());
+ // The fly is at-char anchored and has an anchor position.
+ SwIndex& rEndIdx = const_cast<SwIndex&>(pContentAnchor->nContent);
+ if (&pContentAnchor->nNode.GetNode() == this && rEndIdx.GetIndex() == rPos.GetIndex())
+ {
+ // The anchor position is exactly our insert position.
+ rEndIdx.Assign(&aTmpIdxReg, rEndIdx.GetIndex());
+ }
}
}
}
@@ -4859,6 +4863,11 @@ bool SwTextNode::SetAttr( const SfxItemSet& rSet )
return bRet;
}
+void SwTextNode::SetInSwUndo(bool bInUndo)
+{
+ m_bInUndo = bInUndo;
+}
+
namespace {
// Helper class for special handling of resetting attributes at text node:
// In constructor an instance of the helper class recognize whose attributes
diff --git a/sw/source/core/undo/undel.cxx b/sw/source/core/undo/undel.cxx
index f3fbf5eac553..790dd2e3ea67 100644
--- a/sw/source/core/undo/undel.cxx
+++ b/sw/source/core/undo/undel.cxx
@@ -1015,8 +1015,10 @@ void SwUndoDelete::UndoImpl(::sw::UndoRedoContext & rContext)
// SectionNode mode and selection from top to bottom:
// -> in StartNode is still the rest of the Join => delete
aPos.nContent.Assign( pTextNd, m_nSttContent );
+ pTextNd->SetInSwUndo(true);
OUString const ins( pTextNd->InsertText(*m_aSttStr, aPos.nContent,
SwInsertFlags::NOHINTEXPAND) );
+ pTextNd->SetInSwUndo(false);
assert(ins.getLength() == m_aSttStr->getLength()); // must succeed
(void) ins;
// METADATA: restore
More information about the Libreoffice-commits
mailing list