tdf#158039 sw track changes: fix cycle case of selected sentences

Previous tracked changes of cycle case weren't removed, if
the selection doesn't end in a tracked change, i.e. sentences
with punctuation, or selections end in a capitalized word etc.

Fix also lost selection of multiple selected nodes.

Follow up to commit 4cf8de89bad9143a5b2dd3d6351080bf62b76029
"tdf#157667 sw track changes: fix cycle case on multiple words",
commit dc748d7dbd114fbf663752258dbaf003af2926c3
"tdf#141198 sw: fix cycle case with change tracking" and
commit 79435eb55ef226fb0e3507aabdc2f8af062680f6
"tdf#157988 sw track changes: fix cycle case on a selected word".

Change-Id: I24476c359200a25ca9bcd467c33b0ebeb1afb037
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/158804
Tested-by: Jenkins
Reviewed-by: László Németh <nemeth@numbertext.org>
diff --git a/sw/qa/extras/uiwriter/uiwriter6.cxx b/sw/qa/extras/uiwriter/uiwriter6.cxx
index 8e6b910..30c449a 100644
--- a/sw/qa/extras/uiwriter/uiwriter6.cxx
+++ b/sw/qa/extras/uiwriter/uiwriter6.cxx
@@ -796,7 +796,62 @@ CPPUNIT_TEST_FIXTURE(SwUiWriterTest6, testTdf157667)
        "Integer sodalesINTEGER SODALES tincidunt tristique."));

    dispatchCommand(mxComponent, ".uno:ChangeCaseRotateCase", {});

    CPPUNIT_ASSERT(getParagraph(1)->getString().startsWith("Integer sodales tincidunt tristique."));

    dispatchCommand(mxComponent, ".uno:ChangeCaseRotateCase", {});

    CPPUNIT_ASSERT(getParagraph(1)->getString().startsWith(
        "Integer sodalesSodales tinciduntTincidunt tristique."));

    dispatchCommand(mxComponent, ".uno:ChangeCaseRotateCase", {});

    CPPUNIT_ASSERT(getParagraph(1)->getString().startsWith("Integer sodales tincidunt tristique."));
}

CPPUNIT_TEST_FIXTURE(SwUiWriterTest6, testTdf158039)
{
    createSwDoc("tdf130088.docx");
    SwDoc* pDoc = getSwDoc();
    SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();

    // select the first sentence
    pWrtShell->Right(SwCursorSkipMode::Chars, /*bSelect=*/true, 26, /*bBasicCall=*/false);

    // enable redlining
    dispatchCommand(mxComponent, ".uno:TrackChanges", {});
    CPPUNIT_ASSERT_MESSAGE("redlining should be on",
                           pDoc->getIDocumentRedlineAccess().IsRedlineOn());

    // show changes
    CPPUNIT_ASSERT_MESSAGE(
        "redlines should be visible",
        IDocumentRedlineAccess::IsShowChanges(pDoc->getIDocumentRedlineAccess().GetRedlineFlags()));

    // cycle case with change tracking

    dispatchCommand(mxComponent, ".uno:ChangeCaseRotateCase", {});

    CPPUNIT_ASSERT(getParagraph(1)->getString().startsWith(
        "Integer sodalesSodales tinciduntTincidunt tristique."));

    dispatchCommand(mxComponent, ".uno:ChangeCaseRotateCase", {});

    // This was false (missing revert of the tracked change)
    CPPUNIT_ASSERT(getParagraph(1)->getString().startsWith("Integer sodales tincidunt tristique."));

    dispatchCommand(mxComponent, ".uno:ChangeCaseRotateCase", {});

    CPPUNIT_ASSERT(getParagraph(1)->getString().startsWith(
        "Integer sodalesINTEGER SODALES tincidunt tristique."));

    dispatchCommand(mxComponent, ".uno:ChangeCaseRotateCase", {});

    dispatchCommand(mxComponent, ".uno:ChangeCaseRotateCase", {});

    CPPUNIT_ASSERT(getParagraph(1)->getString().startsWith(
        "Integer sodalesSodales tinciduntTincidunt tristique."));

    dispatchCommand(mxComponent, ".uno:ChangeCaseRotateCase", {});

    CPPUNIT_ASSERT(getParagraph(1)->getString().startsWith("Integer sodales tincidunt tristique."));
diff --git a/sw/source/core/doc/DocumentContentOperationsManager.cxx b/sw/source/core/doc/DocumentContentOperationsManager.cxx
index d51565c..d36ee7a 100644
--- a/sw/source/core/doc/DocumentContentOperationsManager.cxx
+++ b/sw/source/core/doc/DocumentContentOperationsManager.cxx
@@ -3055,17 +3055,27 @@ void DocumentContentOperationsManager::TransliterateText(
        if ( IDocumentRedlineAccess::IsShowChanges( rIDRA.GetRedlineFlags() ) &&
                        pEnd->GetContentIndex() > 0 )
        {
            SwPosition aPos(*pEnd->GetContentNode(), pEnd->GetContentIndex() - 1);
            SwRedlineTable::size_type n = 0;
            // search all own redlines within the selected area
            SwRedlineTable::size_type n = SwRedlineTable::npos;
            const SwRedlineTable& aRedlineTable = rIDRA.GetRedlineTable();
            for( SwRedlineTable::size_type m = 0; m < aRedlineTable.size(); ++m )
            {
                const SwRangeRedline* pRedline = aRedlineTable[ m ];

            const SwRangeRedline* pFnd =
                                rIDRA.GetRedlineTable().FindAtPosition( aPos, n );
            if ( pFnd && RedlineType::Insert == pFnd->GetType() && n > 0 )
                if ( *pRedline->Start() > *pEnd )
                    break;

                if ( *pRedline->Start() >= *pStt )
                    n = m;
            }

            if ( n != SwRedlineTable::npos && n > 0 )
            {
                SwWrtShell *pWrtShell = dynamic_cast<SwWrtShell*>(
                            m_rDoc.getIDocumentLayoutAccess().GetCurrentViewShell());

                sal_Int32 nRejectedCharacters = 0;
                SwRangeRedline* pFnd = rIDRA.GetRedlineTable()[n];
                SwRangeRedline* pFnd2 = rIDRA.GetRedlineTable()[--n];
                // loop on all redlines of a case changing, and reject them
                while ( ( ( RedlineType::Insert == pFnd->GetType() &&
@@ -3095,13 +3105,17 @@ void DocumentContentOperationsManager::TransliterateText(
                    pFnd2 = rIDRA.GetRedlineTable()[--n];
                }

                // remove the last item and restore the original selection
                // remove the last item and restore the original selection within the node
                if ( bHasTrackedChange )
                {
                    pWrtShell->GetCursor()->GetPoint()->
                        Assign(*rPaM.Start()->GetContentNode(), nSttCnt);
                    pWrtShell->GetCursor()->GetMark()->
                        Assign(*rPaM.End()->GetContentNode(), nEndCnt - nRejectedCharacters);
                    if ( nSttNd == nEndNd )
                    {
                        pWrtShell->GetCursor()->GetPoint()->
                            Assign(*rPaM.Start()->GetContentNode(), nSttCnt);
                        if ( nEndCnt >= nRejectedCharacters )
                            pWrtShell->GetCursor()->GetMark()->
                                Assign(*rPaM.End()->GetContentNode(), nEndCnt - nRejectedCharacters);
                    }
                    rIDRA.RejectRedline(*pFnd, true);
                }
            }
@@ -3191,7 +3205,7 @@ void DocumentContentOperationsManager::TransliterateText(
    }

    // restore selection after tracked changes
    if ( !bNoSelection && bUseRedlining )
    if ( !bNoSelection && bUseRedlining && nSttNd == nEndNd )
    {
        if ( SwWrtShell *pWrtShell = dynamic_cast<SwWrtShell*>(
                        m_rDoc.getIDocumentLayoutAccess().GetCurrentViewShell()) )