sw/qa/extras/uiwriter/uiwriter6.cxx                     |   43 ++++++++++
 sw/source/core/doc/DocumentContentOperationsManager.cxx |   68 ++++++++++++----
 2 files changed, 96 insertions(+), 15 deletions(-)

New commits:
commit 4cf8de89bad9143a5b2dd3d6351080bf62b76029
Author:     László Németh <nem...@numbertext.org>
AuthorDate: Tue Oct 31 15:51:09 2023 +0100
Commit:     László Németh <nem...@numbertext.org>
CommitDate: Tue Oct 31 23:07:01 2023 +0100

    tdf#157667 sw track changes: fix cycle case on multiple words
    
    Fix tracked cycle case on multiple selected words.
    
    Follow up to 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: I81566f8be0cf6f4af6ed4af031116bd19e3884d7
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/158732
    Tested-by: Jenkins
    Reviewed-by: László Németh <nem...@numbertext.org>

diff --git a/sw/qa/extras/uiwriter/uiwriter6.cxx 
b/sw/qa/extras/uiwriter/uiwriter6.cxx
index 83bc43f6d866..8e6b91043b0b 100644
--- a/sw/qa/extras/uiwriter/uiwriter6.cxx
+++ b/sw/qa/extras/uiwriter/uiwriter6.cxx
@@ -759,6 +759,49 @@ CPPUNIT_TEST_FIXTURE(SwUiWriterTest6, testTdf157988)
     CPPUNIT_ASSERT(getParagraph(1)->getString().startsWith("Integer sodales 
tincidunt"));
 }
 
+CPPUNIT_TEST_FIXTURE(SwUiWriterTest6, testTdf157667)
+{
+    createSwDoc("tdf130088.docx");
+    SwDoc* pDoc = getSwDoc();
+    SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+
+    // select the first three words
+    pWrtShell->Right(SwCursorSkipMode::Chars, /*bSelect=*/true, 25, 
/*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", {});
+    dispatchCommand(mxComponent, ".uno:ChangeCaseRotateCase", {});
+
+    CPPUNIT_ASSERT(getParagraph(1)->getString().startsWith("Integer sodales 
tincidunt tristique."));
+}
+
 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6, testTdf108048)
 {
     createSwDoc();
diff --git a/sw/source/core/doc/DocumentContentOperationsManager.cxx 
b/sw/source/core/doc/DocumentContentOperationsManager.cxx
index 54b29b9b766c..d51565c5eaee 100644
--- a/sw/source/core/doc/DocumentContentOperationsManager.cxx
+++ b/sw/source/core/doc/DocumentContentOperationsManager.cxx
@@ -2984,7 +2984,8 @@ void DocumentContentOperationsManager::TransliterateText(
     sal_Int32 nEndCnt = pEnd->GetContentIndex();
 
     SwTextNode* pTNd = pStt->GetNode().GetTextNode();
-    if( (pStt == pEnd) && pTNd )  // no selection?
+    bool bNoSelection = (pStt == pEnd) && pTNd;  // no selection?
+    if ( bNoSelection )
     {
         /* Check if cursor is inside of a word */
         assert(g_pBreakIt && g_pBreakIt->GetBreakIter().is());
@@ -3061,27 +3062,52 @@ void 
DocumentContentOperationsManager::TransliterateText(
                                 rIDRA.GetRedlineTable().FindAtPosition( aPos, 
n );
             if ( pFnd && RedlineType::Insert == pFnd->GetType() && n > 0 )
             {
-                const SwRangeRedline* pFnd2 = rIDRA.GetRedlineTable()[n-1];
-                if ( RedlineType::Delete == pFnd2->GetType() &&
-                      m_rDoc.getIDocumentLayoutAccess().GetCurrentViewShell() 
&&
-                      *pFnd2->End() == *pFnd->Start() &&
-                      pFnd->GetAuthor() == pFnd2->GetAuthor() )
+                SwWrtShell *pWrtShell = dynamic_cast<SwWrtShell*>(
+                            
m_rDoc.getIDocumentLayoutAccess().GetCurrentViewShell());
+
+                sal_Int32 nRejectedCharacters = 0;
+                SwRangeRedline* pFnd2 = rIDRA.GetRedlineTable()[--n];
+                // loop on all redlines of a case changing, and reject them
+                while ( ( ( RedlineType::Insert == pFnd->GetType() &&
+                            RedlineType::Delete == pFnd2->GetType() ) ||
+                          ( RedlineType::Delete == pFnd->GetType() &&
+                            RedlineType::Insert == pFnd2->GetType() ) ) &&
+                            pWrtShell &&
+                      // use time stamp to recognize the multiple selections 
in the text,
+                      // not only the changes from the same author within the 
(sometimes
+                      // incomplete) selection
+                      ( pFnd2->GetTimeStamp() == pFnd->GetTimeStamp() ||
+                        ( pStt->GetContentNode() < 
pFnd2->Start()->GetContentNode() ||
+                            ( pStt->GetContentNode() == 
pFnd2->Start()->GetContentNode() &&
+                              nSttCnt <= pFnd2->Start()->GetContentIndex() ) ) 
) &&
+                        pFnd->GetAuthor() == pFnd2->GetAuthor() )
                 {
                     bHasTrackedChange = true;
-                    SwPosition aPos2(*pFnd2->Start());
+
+                    if ( RedlineType::Insert == pFnd->GetType() )
+                        nRejectedCharacters += pFnd->GetText().getLength();
+
                     rIDRA.RejectRedline(*pFnd, true);
 
-                    rIDRA.RejectRedline(*pFnd2, true);
-                    // positionate the text cursor before the changed word to 
select it
-                    if ( SwWrtShell *pWrtShell = dynamic_cast<SwWrtShell*>(
-                            
m_rDoc.getIDocumentLayoutAccess().GetCurrentViewShell()) )
-                    {
-                        pWrtShell->GetCursor()->GetPoint()->
-                                Assign(*aPos2.GetContentNode(), 
aPos2.GetContentIndex());
-                    }
+                    pFnd = pFnd2;
+                    if ( n == 0 )
+                        break;
+                    pFnd2 = rIDRA.GetRedlineTable()[--n];
+                }
+
+                // remove the last item and restore the original selection
+                if ( bHasTrackedChange )
+                {
+                    pWrtShell->GetCursor()->GetPoint()->
+                        Assign(*rPaM.Start()->GetContentNode(), nSttCnt);
+                    pWrtShell->GetCursor()->GetMark()->
+                        Assign(*rPaM.End()->GetContentNode(), nEndCnt - 
nRejectedCharacters);
+                    rIDRA.RejectRedline(*pFnd, true);
                 }
             }
         }
+
+        // TODO handle title case to lowercase
         if ( bHasTrackedChange )
             return;
     }
@@ -3163,6 +3189,18 @@ void DocumentContentOperationsManager::TransliterateText(
     {
         m_rDoc.GetIDocumentUndoRedo().AppendUndo(std::move(pUndo));
     }
+
+    // restore selection after tracked changes
+    if ( !bNoSelection && bUseRedlining )
+    {
+        if ( SwWrtShell *pWrtShell = dynamic_cast<SwWrtShell*>(
+                        
m_rDoc.getIDocumentLayoutAccess().GetCurrentViewShell()) )
+        {
+            *pWrtShell->GetCursor()->GetMark() = 
*pWrtShell->GetCursor()->End();
+            
pWrtShell->GetCursor()->GetPoint()->Assign(*pStt->GetContentNode(), nSttCnt);
+        }
+    }
+
     m_rDoc.getIDocumentState().SetModified();
 }
 

Reply via email to