sw/CppunitTest_sw_core_text.mk  |    1 
 sw/qa/core/text/text.cxx        |   44 +++++++++++++++++++++++++++++++++++++++-
 sw/source/core/text/frmform.cxx |   18 ++++++++++++++++
 3 files changed, 62 insertions(+), 1 deletion(-)

New commits:
commit 112309a07b55d5b4a9a4b7395df7612240df5684
Author:     Miklos Vajna <vmik...@collabora.com>
AuthorDate: Fri Apr 29 12:10:13 2022 +0200
Commit:     Miklos Vajna <vmik...@collabora.com>
CommitDate: Mon May 2 13:05:13 2022 +0200

    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)
    
    Change-Id: Iede03e11daceb3c2b614a301e21560b075a60c01
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/133683
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com>
    Reviewed-by: Miklos Vajna <vmik...@collabora.com>

diff --git a/sw/CppunitTest_sw_core_text.mk b/sw/CppunitTest_sw_core_text.mk
index 19d8cd422edc..c3025f007a9a 100644
--- a/sw/CppunitTest_sw_core_text.mk
+++ b/sw/CppunitTest_sw_core_text.mk
@@ -21,6 +21,7 @@ $(eval $(call gb_CppunitTest_use_libraries,sw_core_text, \
     comphelper \
     cppu \
     cppuhelper \
+    editeng \
     sal \
     sfx \
     svl \
diff --git a/sw/qa/core/text/text.cxx b/sw/qa/core/text/text.cxx
index 0cd732c4a4af..f43727ed5f3f 100644
--- a/sw/qa/core/text/text.cxx
+++ b/sw/qa/core/text/text.cxx
@@ -24,13 +24,14 @@
 #include <IDocumentLayoutAccess.hxx>
 #include <rootfrm.hxx>
 #include <txtfrm.hxx>
-
 #include <porlay.hxx>
 #include <pormulti.hxx>
 #include <formatlinebreak.hxx>
 #include <sortedobjs.hxx>
 #include <anchoredobject.hxx>
 #include <fmtcntnt.hxx>
+#include <fmtfsize.hxx>
+#include <IDocumentRedlineAccess.hxx>
 
 constexpr OUStringLiteral DATA_DIRECTORY = u"/sw/qa/core/text/data/";
 
@@ -407,6 +408,47 @@ CPPUNIT_TEST_FIXTURE(SwCoreTextTest, 
testAsCharImageDocModelFromViewPoint)
     CPPUNIT_ASSERT_EQUAL(aGraphicNode, pShellCursor->GetMark()->nNode);
 }
 
+CPPUNIT_TEST_FIXTURE(SwCoreTextTest, testRedlineDelete)
+{
+    // Given a document with A4 paper size, some text, redlining on, but 
hidden:
+    SwDoc* pDoc = createSwDoc();
+    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(SwFrameSize::Fixed);
+        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/text/frmform.cxx b/sw/source/core/text/frmform.cxx
index 2eba32cdef55..9837d3df6c2f 100644
--- a/sw/source/core/text/frmform.cxx
+++ b/sw/source/core/text/frmform.cxx
@@ -1611,8 +1611,26 @@ 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 );

Reply via email to