summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiklos Vajna <vmiklos@collabora.com>2022-05-06 15:21:45 +0200
committerMiklos Vajna <vmiklos@collabora.com>2022-05-10 10:38:37 +0200
commit46a9ca4b551b2d08b04e2b0cc28ea51579abf40f (patch)
tree59546e16bd123cdd5f4217a80e8eb20e327445ad
parentf63c415e21453a558b894c141efe7a0431ff96d9 (diff)
sw: don't copy useless char escapement to next node on split
Unless autocorrect notices such a just-typed content, pressing enter at the end of a paragraph which ends with superscript or subscript text will carry over that formatting to the next paragraph, which is hardly wanted by any user. Technically this is not copying: paragraph split works by creating a next text node, moving all content & formatting to this next node, then move part of the content back to the previous node, which is all content in case of an enter at the end of a paragraph. Copying character formatting over to the next text node makes sense: e.g. paragraph alignment or boldness is probably something a user wants to continue using in the next text node. But superscript is typically created by autocorrect in English text for "1st" and similar input, this is usually unwanted in the next paragraph. Fix the problem by special-casing the RES_CHRATR_ESCAPEMENT case and remove the matching SvxEscapementItem from the hints of the just created next paragraph in case it's there. A possible future improvement would be to support this when there are other active (direct formatting) hints, in which case going via SwDoc::ResetAttrs() is probably a better choice, but the effects of that for undo and redlining is not clear. (cherry picked from commit 71019ec15bd3fe15385443b68614fd2402e0040f) Conflicts: sw/qa/core/txtnode/txtnode.cxx Change-Id: I57feb99d9a31f16c277eba44f464ab49936b65aa Reviewed-on: https://gerrit.libreoffice.org/c/core/+/134043 Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice@gmail.com> Reviewed-by: Miklos Vajna <vmiklos@collabora.com>
-rw-r--r--sw/CppunitTest_sw_core_txtnode.mk1
-rw-r--r--sw/qa/core/txtnode/txtnode.cxx26
-rw-r--r--sw/source/core/txtnode/ndtxt.cxx31
3 files changed, 58 insertions, 0 deletions
diff --git a/sw/CppunitTest_sw_core_txtnode.mk b/sw/CppunitTest_sw_core_txtnode.mk
index 54aa0865cce3..441e415267b7 100644
--- a/sw/CppunitTest_sw_core_txtnode.mk
+++ b/sw/CppunitTest_sw_core_txtnode.mk
@@ -21,6 +21,7 @@ $(eval $(call gb_CppunitTest_use_libraries,sw_core_txtnode, \
comphelper \
cppu \
cppuhelper \
+ editeng \
sal \
sfx \
svxcore \
diff --git a/sw/qa/core/txtnode/txtnode.cxx b/sw/qa/core/txtnode/txtnode.cxx
index 9d3c798dc0fa..fbbecc7cb6fa 100644
--- a/sw/qa/core/txtnode/txtnode.cxx
+++ b/sw/qa/core/txtnode/txtnode.cxx
@@ -16,6 +16,7 @@
#include <vcl/scheduler.hxx>
#include <sfx2/lokhelper.hxx>
#include <test/lokcallback.hxx>
+#include <editeng/escapementitem.hxx>
#include <IDocumentStatistics.hxx>
#include <fmtanchr.hxx>
@@ -158,6 +159,31 @@ CPPUNIT_TEST_FIXTURE(SwCoreTxtnodeTest, testTitleFieldInvalidate)
comphelper::LibreOfficeKit::setActive(false);
}
+CPPUNIT_TEST_FIXTURE(SwCoreTxtnodeTest, testSplitNodeSuperscriptCopy)
+{
+ // Given a document with superscript text at the end of a paragraph:
+ SwDoc* pDoc = createSwDoc();
+ SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+ pWrtShell->Insert("1st");
+ pWrtShell->Left(CRSR_SKIP_CHARS, /*bSelect=*/true, 2, /*bBasicCall=*/false);
+ SfxItemSet aSet(pWrtShell->GetAttrPool(),
+ svl::Items<RES_CHRATR_ESCAPEMENT, RES_CHRATR_ESCAPEMENT>{});
+ SvxEscapementItem aItem(SvxEscapement::Superscript, RES_CHRATR_ESCAPEMENT);
+ aSet.Put(aItem);
+ pWrtShell->SetAttrSet(aSet);
+
+ // When hitting enter at the end of the paragraph:
+ pWrtShell->SttEndDoc(/*bStt=*/false);
+ pWrtShell->SplitNode(/*bAutoFormat=*/true);
+
+ // Then make sure that the superscript formatting doesn't appear on the next paragraph:
+ aSet.ClearItem(RES_CHRATR_ESCAPEMENT);
+ pWrtShell->GetCurAttr(aSet);
+ // Without the accompanying fix in place, this test would have failed, the unexpected
+ // superscript appeared in the next paragraph.
+ CPPUNIT_ASSERT(!aSet.HasItem(RES_CHRATR_ESCAPEMENT));
+}
+
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 fa29e80ad20e..c4d8cd60bb3f 100644
--- a/sw/source/core/txtnode/ndtxt.cxx
+++ b/sw/source/core/txtnode/ndtxt.cxx
@@ -702,6 +702,37 @@ SwTextNode *SwTextNode::SplitContentNode(const SwPosition & rPos,
}
}
+ // pNode is the previous node, 'this' is the next node from the split.
+ if (nSplitPos == nTextLen && m_pSwpHints)
+ {
+ // We just created an empty next node: avoid unwanted superscript in the new node if it's
+ // there.
+ for (size_t i = 0; i < m_pSwpHints->Count(); ++i)
+ {
+ SwTextAttr* pHt = m_pSwpHints->Get(i);
+ if (pHt->Which() != RES_TXTATR_AUTOFMT)
+ {
+ continue;
+ }
+
+ const sal_Int32* pEnd = pHt->GetEnd();
+ if (!pEnd || pHt->GetStart() != *pEnd)
+ {
+ continue;
+ }
+
+ const std::shared_ptr<SfxItemSet>& pSet = pHt->GetAutoFormat().GetStyleHandle();
+ if (!pSet || pSet->Count() != 1 || !pSet->GetItem(RES_CHRATR_ESCAPEMENT))
+ {
+ continue;
+ }
+
+ m_pSwpHints->DeleteAtPos(i);
+ SwTextAttr::Destroy(pHt, GetDoc().GetAttrPool());
+ --i;
+ }
+ }
+
#ifndef NDEBUG
if (isHide) // otherwise flags won't be set anyway
{