tdf#138605 sw change tracking: fix crash with Undo

Regression from commit 469f472fb31c4ef1a57f8ec54ba750c1332feec2
(tdf#138479 tdf#137769 sw ChangesInMargin: fix Undo in paragraphs)

Change-Id: I7826b7920e51733da98c00bfdcb8636d42655afc
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/107637
Tested-by: Jenkins
Reviewed-by: László Németh <nemeth@numbertext.org>
(cherry picked from commit e57d77cb01d3e76a942c5e2bb896135dd900f807)
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/107620
diff --git a/sw/qa/extras/uiwriter/uiwriter2.cxx b/sw/qa/extras/uiwriter/uiwriter2.cxx
index 4bbaeee..cb33dc0 100644
--- a/sw/qa/extras/uiwriter/uiwriter2.cxx
+++ b/sw/qa/extras/uiwriter/uiwriter2.cxx
@@ -1957,6 +1957,36 @@ CPPUNIT_TEST_FIXTURE(SwUiWriterTest2, testTdf137503)
    CPPUNIT_ASSERT(!pWrtShell->GetViewOptions()->IsShowChangesInMargin());
}

CPPUNIT_TEST_FIXTURE(SwUiWriterTest2, testTdf138605)
{
    SwDoc* const pDoc(createDoc());
    SwWrtShell* const pWrtShell = pDoc->GetDocShell()->GetWrtShell();
    SwXTextDocument* pTextDoc = dynamic_cast<SwXTextDocument*>(mxComponent.get());
    CPPUNIT_ASSERT(pTextDoc);

    // turn on red-lining and show changes
    pDoc->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::On | RedlineFlags::ShowInsert
                                                      | RedlineFlags::ShowDelete);
    CPPUNIT_ASSERT_MESSAGE("redlining should be on",
                           pDoc->getIDocumentRedlineAccess().IsRedlineOn());
    CPPUNIT_ASSERT_MESSAGE(
        "redlines should be visible",
        IDocumentRedlineAccess::IsShowChanges(pDoc->getIDocumentRedlineAccess().GetRedlineFlags()));

    // insert a word, delete it with change tracking and try to undo it
    pWrtShell->Insert("word");
    dispatchCommand(mxComponent, ".uno:SelectAll", {});
    dispatchCommand(mxComponent, ".uno:Delete", {});
    // this crashed due to bad access to the empty redline table
    dispatchCommand(mxComponent, ".uno:Undo", {});

    // more Undo
    CPPUNIT_ASSERT(getParagraph(1)->getString().startsWith("word"));
    dispatchCommand(mxComponent, ".uno:Undo", {});
    CPPUNIT_ASSERT(getParagraph(1)->getString().startsWith(""));
    dispatchCommand(mxComponent, ".uno:Undo", {});
}

CPPUNIT_TEST_FIXTURE(SwUiWriterTest2, testTdf138135)
{
    load(DATA_DIRECTORY, "tdf132160.odt");
diff --git a/sw/source/core/undo/unredln.cxx b/sw/source/core/undo/unredln.cxx
index c385df3..93d0b0d 100644
--- a/sw/source/core/undo/unredln.cxx
+++ b/sw/source/core/undo/unredln.cxx
@@ -92,15 +92,15 @@ void SwUndoRedline::UndoImpl(::sw::UndoRedoContext & rContext)

    // fix PaM for deletions shown in margin
    bool bIsDeletion = dynamic_cast<SwUndoRedlineDelete*>(this);
    const SwRedlineTable& rTable = rDoc.getIDocumentRedlineAccess().GetRedlineTable();
    sal_uInt32 nMaxId = SAL_MAX_UINT32;
    if ( bIsDeletion )
    if ( bIsDeletion && rTable.size() > 0 )
    {
        // Nodes of the deletion range are in the newest invisible redlines.
        // Set all redlines visible and recover the original deletion range.
        for (sal_uInt32 nNodes = 0; nNodes <  m_nEndNode - m_nSttNode + 1; ++ nNodes)
        for (sal_uInt32 nNodes = 0; nNodes <  m_nEndNode - m_nSttNode + 1; ++nNodes)
        {
            SwRedlineTable::size_type nCurRedlinePos = 0;
            const SwRedlineTable& rTable = rDoc.getIDocumentRedlineAccess().GetRedlineTable();
            SwRangeRedline * pRedline(rTable[nCurRedlinePos]);

            // search last but nNodes redline by its nth biggest id