sd/source/ui/func/fuformatpaintbrush.cxx                |   11 -
 svx/source/svdraw/svdedxv.cxx                           |    4 
 sw/qa/extras/uiwriter/uiwriter6.cxx                     |   98 ++++++++++++++++
 sw/source/core/doc/DocumentContentOperationsManager.cxx |   86 +++++++++++---
 sw/source/core/txtnode/txatritr.cxx                     |    9 -
 sw/source/uibase/shells/textsh.cxx                      |   15 ++
 6 files changed, 189 insertions(+), 34 deletions(-)

New commits:
commit 8d5440ff250cc5c9f071f312f5d6d48c91cdb068
Author:     Samuel Mehrbrodt <samuel.mehrbr...@allotropia.de>
AuthorDate: Thu Mar 7 22:51:51 2024 +0100
Commit:     Thorsten Behrens <thorsten.behr...@allotropia.de>
CommitDate: Fri Mar 8 04:33:50 2024 +0100

    tdf#160071 Don't clone formatting to whole boxes
    
    when clicking into an empty area of that box
    
    Change-Id: I383f1584f446e29454eda2177c8bae0f6587e42d
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/164555
    Tested-by: Jenkins
    Reviewed-by: Thorsten Behrens <thorsten.behr...@allotropia.de>

diff --git a/sd/source/ui/func/fuformatpaintbrush.cxx 
b/sd/source/ui/func/fuformatpaintbrush.cxx
index ef1ea258c78f..d4476f4b7ca6 100644
--- a/sd/source/ui/func/fuformatpaintbrush.cxx
+++ b/sd/source/ui/func/fuformatpaintbrush.cxx
@@ -146,13 +146,6 @@ bool FuFormatPaintBrush::MouseButtonDown(const MouseEvent& 
rMEvt)
         }
 
         unmarkimpl( mpView );
-
-        if (aVEvt.mpObj)
-        {
-            sal_uInt16 nHitLog = sal_uInt16 ( 
mpWindow->PixelToLogic(Size(HITPIX,0)).Width() );
-            mpView->MarkObj(mpWindow->PixelToLogic( rMEvt.GetPosPixel() ), 
nHitLog, false/*bToggle*/);
-            return true;
-        }
     }
     return false;
 }
commit 792b099e9de18f7c6e2099199452827a4b8401bf
Author:     Oliver Specht <oliver.spe...@cib.de>
AuthorDate: Thu Mar 7 12:47:22 2024 +0100
Commit:     Thorsten Behrens <thorsten.behr...@allotropia.de>
CommitDate: Fri Mar 8 04:32:52 2024 +0100

    tdf#159726 Improve Clone formatting
    
    Paragraph attributes and lists are copied if there is no source
    selection or the source selection includes at least a full paragraph.
    They are only applied to an empty or a paragraph selection.
    As in tdf#160069 requested the clone formatting function is only enabled
    in text edit mode.
    
    Change-Id: I789402a7928837bb85ec941fd6f958d12585ac40
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/164533
    Tested-by: Thorsten Behrens <thorsten.behr...@allotropia.de>
    Reviewed-by: Thorsten Behrens <thorsten.behr...@allotropia.de>
    (cherry picked from commit 456d0216aae69c39b12a5df749525589871272a7)

diff --git a/sd/source/ui/func/fuformatpaintbrush.cxx 
b/sd/source/ui/func/fuformatpaintbrush.cxx
index 9bbd30939d53..ef1ea258c78f 100644
--- a/sd/source/ui/func/fuformatpaintbrush.cxx
+++ b/sd/source/ui/func/fuformatpaintbrush.cxx
@@ -290,7 +290,9 @@ void FuFormatPaintBrush::Paste( bool bNoCharacterFormats, 
bool bNoParagraphForma
     if( rMarkList.GetMarkCount() == 1 )
     {
         SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj();
-        if( pObj && 
SdrObjEditView::SupportsFormatPaintbrush(pObj->GetObjInventor(),pObj->GetObjIdentifier())
 )
+        const OutlinerView* pOLV = 
rDrawViewShell.GetDrawView()->GetTextEditOutlinerView();
+        if( pObj && pOLV &&
+            
SdrObjEditView::SupportsFormatPaintbrush(pObj->GetObjInventor(),pObj->GetObjIdentifier())
 )
             return;
     }
     rSet.DisableItem( SID_FORMATPAINTBRUSH );
diff --git a/svx/source/svdraw/svdedxv.cxx b/svx/source/svdraw/svdedxv.cxx
index 6955e52b3fc7..7a8d71e0d34b 100644
--- a/svx/source/svdraw/svdedxv.cxx
+++ b/svx/source/svdraw/svdedxv.cxx
@@ -2814,7 +2814,9 @@ sal_Int32 
SdrObjEditView::TakeFormatPaintBrush(std::shared_ptr<SfxItemSet>& rFor
 
     OutlinerView* pOLV = GetTextEditOutlinerView();
 
-    bool isParaSelection = pOLV ? pOLV->GetEditView().IsSelectionFullPara() : 
false;
+    bool isParaSelection
+        = pOLV ? !pOLV->GetEditView().HasSelection() || 
pOLV->GetEditView().IsSelectionFullPara()
+               : false;
     rFormatSet = std::make_shared<SfxItemSet>(GetModel().GetItemPool(),
                                               GetFormatRangeImpl(pOLV != 
nullptr, isParaSelection));
     if (pOLV)
commit 3c3022ba86cedc083d2f22c2517c6de9a9bef676
Author:     Stephan Bergmann <sberg...@redhat.com>
AuthorDate: Mon Nov 6 15:44:46 2023 +0100
Commit:     Thorsten Behrens <thorsten.behr...@allotropia.de>
CommitDate: Fri Mar 8 04:29:11 2024 +0100

    Fix SwLanguageIterator::Next for RES_TXTATR_AUTOFMT
    
    ...following advice by mstahl, as discussed in the comments starting at
    
<https://gerrit.libreoffice.org/c/core/+/158732/2#message-053bc195667ee3ba396ed12a85f3af8d4b7e5efc>
    "tdf#157667 sw track changes: fix cycle case on multiple words", which had
    started to cause
    
    > /sw/inc/txatritr.hxx:69:18: runtime error: downcast of address 
0x603001b45d90 which does not point to an object of type 'const SvxLanguageItem'
    > 0x603001b45d90: note: object is of type 'SwFormatAutoFormat'
    >  00 00 00 00  f0 0f 53 4e 3b 7f 00 00  02 00 00 00 32 00 90 be  20 31 36 
00 80 60 00 00  c0 5d b4 01
    >               ^~~~~~~~~~~~~~~~~~~~~~~
    >               vptr for 'SwFormatAutoFormat'
    >     #0 0x7f3b45ef75d2 in SwLanguageIterator::GetLanguage() const 
/sw/inc/txatritr.hxx:69:18
    >     #1 0x7f3b45ee2765 in 
SwTextNode::TransliterateText(utl::TransliterationWrapper&, int, int, 
SwUndoTransliterate*, bool) /sw/source/core/txtnode/txtedt.cxx:1980:32
    >     #2 0x7f3b429f1d40 in 
sw::DocumentContentOperationsManager::TransliterateText(SwPaM const&, 
utl::TransliterationWrapper&) 
/sw/source/core/doc/DocumentContentOperationsManager.cxx:3186:15
    >     #3 0x7f3b43a52777 in 
SwEditShell::TransliterateText(TransliterationFlags) 
/sw/source/core/edit/editsh.cxx:1076:51
    >     #4 0x7f3b49118c97 in 
SwTextShell::ExecRotateTransliteration(SfxRequest const&) 
/sw/source/uibase/shells/textsh.cxx:866:20
    >     #5 0x7f3b49118984 in 
SfxStubSwTextShellExecRotateTransliteration(SfxShell*, SfxRequest&) 
/workdir/SdiTarget/sw/sdi/swslots.hxx:3194:1
    >     #6 0x7f3b6529ff75 in SfxDispatcher::Call_Impl(SfxShell&, SfxSlot 
const&, SfxRequest&, bool) /sfx2/source/control/dispatch.cxx:254:9
    >     #7 0x7f3b652b5e85 in SfxDispatcher::Execute_(SfxShell&, SfxSlot 
const&, SfxRequest&, SfxCallMode) /sfx2/source/control/dispatch.cxx:753:9
    >     #8 0x7f3b65240e3b in SfxBindings::Execute_Impl(SfxRequest&, SfxSlot 
const*, SfxShell*) /sfx2/source/control/bindings.cxx:1061:22
    >     #9 0x7f3b656c2760 in 
SfxDispatchController_Impl::dispatch(com::sun::star::util::URL const&, 
com::sun::star::uno::Sequence<com::sun::star::beans::PropertyValue> const&, 
com::sun::star::uno::Reference<com::sun::star::frame::XDispatchResultListener> 
const&) /sfx2/source/control/unoctitm.cxx:688:53
    >     #10 0x7f3b656c4ec1 in 
SfxOfficeDispatch::dispatchWithNotification(com::sun::star::util::URL const&, 
com::sun::star::uno::Sequence<com::sun::star::beans::PropertyValue> const&, 
com::sun::star::uno::Reference<com::sun::star::frame::XDispatchResultListener> 
const&) /sfx2/source/control/unoctitm.cxx:266:16
    >     #11 0x7f3b193705a6 in 
framework::DispatchHelper::executeDispatch(com::sun::star::uno::Reference<com::sun::star::frame::XDispatch>
 const&, com::sun::star::util::URL const&, bool, 
com::sun::star::uno::Sequence<com::sun::star::beans::PropertyValue> const&) 
/framework/source/services/dispatchhelper.cxx:163:30
    >     #12 0x7f3b1936f482 in 
framework::DispatchHelper::executeDispatch(com::sun::star::uno::Reference<com::sun::star::frame::XDispatchProvider>
 const&, rtl::OUString const&, rtl::OUString const&, int, 
com::sun::star::uno::Sequence<com::sun::star::beans::PropertyValue> const&) 
/framework/source/services/dispatchhelper.cxx:120:16
    >     #13 0x7f3b19370e54 in non-virtual thunk to 
framework::DispatchHelper::executeDispatch(com::sun::star::uno::Reference<com::sun::star::frame::XDispatchProvider>
 const&, rtl::OUString const&, rtl::OUString const&, int, 
com::sun::star::uno::Sequence<com::sun::star::beans::PropertyValue> const&) 
/framework/source/services/dispatchhelper.cxx
    >     #14 0x7f3b3810b5e9 in 
unotest::MacrosTest::dispatchCommand(com::sun::star::uno::Reference<com::sun::star::lang::XComponent>
 const&, rtl::OUString const&, 
com::sun::star::uno::Sequence<com::sun::star::beans::PropertyValue> const&) 
/unotest/source/cpp/macros_test.cxx:94:33
    >     #15 0x7f3b7245e5fd in testTdf157667::TestBody() 
/sw/qa/extras/uiwriter/uiwriter6.cxx:793:5
    
    Change-Id: I0e0545a134d86a333b971da83a66f58c5e70f601
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/159002
    Tested-by: Jenkins
    Reviewed-by: Stephan Bergmann <sberg...@redhat.com>

diff --git a/sw/source/core/txtnode/txatritr.cxx 
b/sw/source/core/txtnode/txatritr.cxx
index 883c09760c33..91aed778c157 100644
--- a/sw/source/core/txtnode/txatritr.cxx
+++ b/sw/source/core/txtnode/txatritr.cxx
@@ -126,13 +126,8 @@ bool SwLanguageIterator::Next()
                     m_nChgPos = nEndPos;
                     m_nAttrPos = nSavePos;
 
-                    if( RES_TXTATR_CHARFMT == pHt->Which() )
-                    {
-                        const sal_uInt16 nWId = GetWhichOfScript( 
RES_CHRATR_LANGUAGE, m_aScriptIter.GetCurrScript() );
-                        m_pCurrentItem = 
&pHt->GetCharFormat().GetCharFormat()->GetFormatAttr(nWId);
-                    }
-                    else
-                        m_pCurrentItem = &pHt->GetAttr();
+                    const sal_uInt16 nWId = GetWhichOfScript( 
RES_CHRATR_LANGUAGE, m_aScriptIter.GetCurrScript() );
+                    m_pCurrentItem = CharFormat::GetItem(*pHt, nWId);
 
                     m_aStack.pop_front();
                 }
commit efa3254de9678a3c3fdbb6ab3d06d2c63d5c42cf
Author:     László Németh <nem...@numbertext.org>
AuthorDate: Thu Nov 2 13:15:52 2023 +0100
Commit:     Thorsten Behrens <thorsten.behr...@allotropia.de>
CommitDate: Fri Mar 8 04:28:42 2024 +0100

    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 <nem...@numbertext.org>

diff --git a/sw/qa/extras/uiwriter/uiwriter6.cxx 
b/sw/qa/extras/uiwriter/uiwriter6.cxx
index 4b068f63f227..db63836f67cf 100644
--- a/sw/qa/extras/uiwriter/uiwriter6.cxx
+++ b/sw/qa/extras/uiwriter/uiwriter6.cxx
@@ -795,7 +795,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 f89ee513b42b..357c1e67179b 100644
--- a/sw/source/core/doc/DocumentContentOperationsManager.cxx
+++ b/sw/source/core/doc/DocumentContentOperationsManager.cxx
@@ -3049,17 +3049,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 ];
+
+                if ( *pRedline->Start() > *pEnd )
+                    break;
 
-            const SwRangeRedline* pFnd =
-                                rIDRA.GetRedlineTable().FindAtPosition( aPos, 
n );
-            if ( pFnd && RedlineType::Insert == pFnd->GetType() && n > 0 )
+                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() &&
@@ -3089,13 +3099,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);
                 }
             }
@@ -3185,7 +3199,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()) )
commit 2245219f3a341d38417edf46f498dfd3acef15dd
Author:     László Németh <nem...@numbertext.org>
AuthorDate: Tue Oct 31 15:51:09 2023 +0100
Commit:     Thorsten Behrens <thorsten.behr...@allotropia.de>
CommitDate: Fri Mar 8 04:27:59 2024 +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 316181c37cff..4b068f63f227 100644
--- a/sw/qa/extras/uiwriter/uiwriter6.cxx
+++ b/sw/qa/extras/uiwriter/uiwriter6.cxx
@@ -758,6 +758,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 6b1404ecbf0b..f89ee513b42b 100644
--- a/sw/source/core/doc/DocumentContentOperationsManager.cxx
+++ b/sw/source/core/doc/DocumentContentOperationsManager.cxx
@@ -2978,7 +2978,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());
@@ -3055,27 +3056,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;
     }
@@ -3157,6 +3183,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();
 }
 
commit f503a0210cb9d6a46d2241f0b35930667276cce0
Author:     Oliver Specht <oliver.spe...@cib.de>
AuthorDate: Thu Jan 18 15:48:04 2024 +0100
Commit:     Thorsten Behrens <thorsten.behr...@allotropia.de>
CommitDate: Fri Mar 8 03:19:10 2024 +0100

    tdf#63259 rotate case also at start/end of a word
    
    Rotate either rotates the selection or the word the cursor is directly 
before,
    inside or directly after
    
    Change-Id: Ia21e3120d2b00978b9f4ce06738b42e90d2ada62
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/162256
    Tested-by: Jenkins
    Reviewed-by: Michael Stahl <michael.st...@allotropia.de>
    (cherry picked from commit 125fc2ce861c82592b261f2992c893b414396e56)

diff --git a/sw/source/uibase/shells/textsh.cxx 
b/sw/source/uibase/shells/textsh.cxx
index d9bedfdf2a5b..b2d121847736 100644
--- a/sw/source/uibase/shells/textsh.cxx
+++ b/sw/source/uibase/shells/textsh.cxx
@@ -863,7 +863,20 @@ void SwTextShell::ExecTransliteration( SfxRequest const & 
rReq )
 void SwTextShell::ExecRotateTransliteration( SfxRequest const & rReq )
 {
     if( rReq.GetSlot() == SID_TRANSLITERATE_ROTATE_CASE )
-        GetShell().TransliterateText( m_aRotateCase.getNextMode() );
+    {
+        SwWrtShell& rSh = GetShell();
+        if (rSh.HasSelection())
+        {
+            rSh.TransliterateText(m_aRotateCase.getNextMode());
+        }
+        else
+        {
+            rSh.Push(); // save cur cursor
+            if ((rSh.IsEndWrd() || rSh.IsStartWord() || rSh.IsInWord()) && 
rSh.SelWrd())
+                rSh.TransliterateText(m_aRotateCase.getNextMode());
+            rSh.Pop(SwCursorShell::PopMode::DeleteCurrent);
+        }
+    }
 }
 
 SwTextShell::SwTextShell(SwView &_rView) :

Reply via email to