summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMiklos Vajna <vmiklos@collabora.com>2022-04-29 12:10:13 +0200
committerMichael Stahl <michael.stahl@allotropia.de>2022-06-20 11:20:33 +0200
commit8fe5abd87de8eb4df3c6c2f311f130ad00ff5815 (patch)
tree170f5e5f4594c9ab1f683dd3539dd2d78444b334
parenttdf#135978 sw_redlinehide: recreate fly frames anchored to subsequent nodes (diff)
downloadcore-8fe5abd87de8eb4df3c6c2f311f130ad00ff5815.tar.gz
core-8fe5abd87de8eb4df3c6c2f311f130ad00ff5815.zip
tdf#148683 sw: fix crash on deleting text with redlining enabled, but hidden
Regression from commit 32902f66e7749b2d06d13f50416be5323a0c0ea9 (sw_redlinehide: make layout based Show/Hide mode the default, 2018-11-30), deleting some text in the middle of the paragraph with the bugdoc results in an assertion failure in the SwDrawTextInfo ctor. Normally this doesn't happen on text deletion as we already have a mechanism for truncating no longer needed lines in SwTextFrame::Format_(), though that only checks the length of the current line. Fix the problem by extending this mechanism to also check the remaining lines: if change tracking is on and the total of all line lengths is more than the string length of the text frame, then time to re-calculate. It seems this is not needed in practice when redlining is disabled, though we might want to enable this for the non-redline case as well in the future. (cherry picked from commit 515bf5d4afa3a8ed413fd6f17f66fa98b6dbf29e) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/133684 Reviewed-by: Michael Stahl <michael.stahl@allotropia.de> Tested-by: Jenkins Signed-off-by: Xisco Fauli <xiscofauli@libreoffice.org> Reviewed-on: https://gerrit.libreoffice.org/c/core/+/133693 (cherry picked from commit 3b539b30c3a6559d6b4cf32c2b02fc5d81a0b794) Change-Id: Iede03e11daceb3c2b614a301e21560b075a60c01 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/133888 Tested-by: Michael Stahl <michael.stahl@allotropia.de> Reviewed-by: Michael Stahl <michael.stahl@allotropia.de>
-rw-r--r--sw/CppunitTest_sw_core_text.mk2
-rw-r--r--sw/qa/core/text/text.cxx51
-rw-r--r--sw/source/core/inc/rootfrm.hxx2
-rwxr-xr-xsw/source/core/text/frmform.cxx18
4 files changed, 71 insertions, 2 deletions
diff --git a/sw/CppunitTest_sw_core_text.mk b/sw/CppunitTest_sw_core_text.mk
index 9fe4fadbf357..6f8e7e46c0fc 100644
--- a/sw/CppunitTest_sw_core_text.mk
+++ b/sw/CppunitTest_sw_core_text.mk
@@ -21,9 +21,11 @@ $(eval $(call gb_CppunitTest_use_libraries,sw_core_text, \
comphelper \
cppu \
cppuhelper \
+ editeng \
sal \
sfx \
sw \
+ svl \
test \
unotest \
utl \
diff --git a/sw/qa/core/text/text.cxx b/sw/qa/core/text/text.cxx
index 8074cbc9f45e..e6fe75d6c4ad 100644
--- a/sw/qa/core/text/text.cxx
+++ b/sw/qa/core/text/text.cxx
@@ -8,7 +8,12 @@
*/
#include <swmodeltestbase.hxx>
+
+#include <rootfrm.hxx>
+#include <unotxdoc.hxx>
#include <wrtsh.hxx>
+#include <fmtfsize.hxx>
+#include <IDocumentRedlineAccess.hxx>
static char const DATA_DIRECTORY[] = "/sw/qa/core/text/data/";
@@ -21,7 +26,10 @@ public:
SwDoc* SwCoreTextTest::createDoc(const char* pName)
{
- load(DATA_DIRECTORY, pName);
+ if (!pName)
+ loadURL("private:factory/swriter", nullptr);
+ else
+ load(DATA_DIRECTORY, pName);
SwXTextDocument* pTextDoc = dynamic_cast<SwXTextDocument*>(mxComponent.get());
CPPUNIT_ASSERT(pTextDoc);
@@ -46,6 +54,47 @@ CPPUNIT_TEST_FIXTURE(SwCoreTextTest, testFootnoteConnect)
pWrtShell->DelLeft();
}
+CPPUNIT_TEST_FIXTURE(SwCoreTextTest, testRedlineDelete)
+{
+ // Given a document with A4 paper size, some text, redlining on, but hidden:
+ SwDoc* pDoc = createDoc();
+ SwDocShell* pDocShell = pDoc->GetDocShell();
+ SwWrtShell* pWrtShell = pDocShell->GetWrtShell();
+ {
+ // Set page size to A4.
+ size_t nCurIdx = pWrtShell->GetCurPageDesc();
+ SwPageDesc aPageDesc(pWrtShell->GetPageDesc(nCurIdx));
+ SwFrameFormat& rMaster = aPageDesc.GetMaster();
+ SwFormatFrameSize aSize(ATT_FIX_SIZE);
+ aSize.SetSize(Size(11906, 16838));
+ rMaster.SetFormatAttr(aSize);
+ pWrtShell->ChgPageDesc(nCurIdx, aPageDesc);
+ }
+ OUString aBefore("aaaaaaaaa aaaaaaaaaa aa aa aa ");
+ OUString aDelete("delete eeeeeeeeeee ee eeeeeeeeeee ee eeeeee");
+ pWrtShell->Insert(aBefore + " " + aDelete
+ + " zz zzz zzzzzzzzz zzz zzzz zzzz zzzzzzzzz zzzzzz zzz zzzzzzzzzzz zzz");
+ // Enable redlining.
+ pDocShell->SetChangeRecording(/*bActivate=*/true);
+ // Hide redlining.
+ pWrtShell->StartAllAction();
+ pWrtShell->GetLayout()->SetHideRedlines(true);
+ pWrtShell->EndAllAction();
+
+ // When deleting content in the middle of the paragraph:
+ pWrtShell->SttEndDoc(/*bStt=*/true);
+ pWrtShell->Right(CRSR_SKIP_CHARS, /*bSelect=*/false, /*nCount=*/aBefore.getLength(),
+ /*bBasicCall=*/false);
+ pWrtShell->Right(CRSR_SKIP_CHARS, /*bSelect=*/true, /*nCount=*/aDelete.getLength(),
+ /*bBasicCall=*/false);
+ // Without the accompanying fix in place, this test would have crashed:
+ pWrtShell->Delete();
+
+ // Then make sure that the redline is created:
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1),
+ pDoc->getIDocumentRedlineAccess().GetRedlineTable().size());
+}
+
CPPUNIT_PLUGIN_IMPLEMENT();
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/inc/rootfrm.hxx b/sw/source/core/inc/rootfrm.hxx
index 484ff172e25d..44d7a5800032 100644
--- a/sw/source/core/inc/rootfrm.hxx
+++ b/sw/source/core/inc/rootfrm.hxx
@@ -76,7 +76,7 @@ using SwDestroyList = std::set<SwSectionFrame*>;
/// The root element of a Writer document layout. Lower frames are expected to
/// be SwPageFrame instances.
-class SAL_DLLPUBLIC_RTTI SwRootFrame: public SwLayoutFrame
+class SW_DLLPUBLIC SwRootFrame: public SwLayoutFrame
{
// Needs to disable the Superfluous temporarily
friend void AdjustSizeChgNotify( SwRootFrame *pRoot );
diff --git a/sw/source/core/text/frmform.cxx b/sw/source/core/text/frmform.cxx
index 69db90b6502d..3720c3117f9b 100755
--- a/sw/source/core/text/frmform.cxx
+++ b/sw/source/core/text/frmform.cxx
@@ -1599,9 +1599,27 @@ void SwTextFrame::Format_( SwTextFormatter &rLine, SwTextFormatInfo &rInf,
// If we're finished formatting the text and we still
// have other line objects left, these are superfluous
// now because the text has gotten shorter.
+ bool bTruncLines = false;
if( rLine.GetStart() + rLine.GetLength() >= nStrLen &&
rLine.GetCurr()->GetNext() )
{
+ bTruncLines = true;
+ }
+ else if (GetMergedPara() && rLine.GetCurr()->GetNext())
+ {
+ // We can also have superfluous lines with redlining in case the current line is shorter
+ // than the text length, but the total length of lines is still more than expected.
+ // Truncate in this case as well.
+ TextFrameIndex nLen(0);
+ for (const SwLineLayout* pLine = pPara; pLine; pLine = pLine->GetNext())
+ {
+ nLen += pLine->GetLen();
+ }
+ bTruncLines = nLen > nStrLen;
+ }
+
+ if (bTruncLines)
+ {
rLine.TruncLines();
rLine.SetTruncLines( true );
}