editeng/source/editeng/editeng.cxx             |    4 +-
 editeng/source/editeng/editundo.cxx            |   11 +++++-
 editeng/source/editeng/editundo.hxx            |    3 +
 editeng/source/editeng/impedit.hxx             |    2 -
 editeng/source/editeng/impedit5.cxx            |    3 +
 sd/qa/unit/tiledrendering/data/paste-undo.fodp |   34 ++++++++++++++++++++
 sd/qa/unit/tiledrendering/tiledrendering.cxx   |   41 +++++++++++++++++++++++++
 7 files changed, 93 insertions(+), 5 deletions(-)

New commits:
commit 04f0cd819066229039203fb36848d907146bbba2
Author:     Miklos Vajna <vmik...@collabora.com>
AuthorDate: Mon Aug 9 19:20:53 2021 +0200
Commit:     Michael Stahl <michael.st...@allotropia.de>
CommitDate: Tue Aug 10 20:12:19 2021 +0200

    tdf#142845 editeng: don't update selection when formatting before sd paste
    
    Regression from commit f0c25c751cf8e166a84b289746bce6202a40391d
    (tdf#115783 sd: fix lost char attributes during in-table copy&paste,
    2018-02-16), the problem was that the formatting before paste also
    created an undo action, and executing it alters the selection, which was
    not intended.
    
    So in case the textbox contains "world" and we paste "hello", then the
    undo will set the cursor at the end of "world", while the expected
    result is to just undo the paste and the formatting of "world".
    
    Fix the problem by not altering the selection in the undo of
    Outliner::SetCharAttribs(), which is only called by sd/ in the
    before-paste case, not anywhere else.
    
    (cherry picked from commit fc4c0747e97bb997cc37263b3e86b07dab21fe25)
    
    Change-Id: Ie4a08f57d22cd1862c02987a5f86089fda8a5d9d
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/120254
    Tested-by: Jenkins
    Reviewed-by: Michael Stahl <michael.st...@allotropia.de>

diff --git a/editeng/source/editeng/editeng.cxx 
b/editeng/source/editeng/editeng.cxx
index b90ad3127fee..f9207a937c1f 100644
--- a/editeng/source/editeng/editeng.cxx
+++ b/editeng/source/editeng/editeng.cxx
@@ -1768,7 +1768,9 @@ const SfxPoolItem& EditEngine::GetParaAttrib( sal_Int32 
nPara, sal_uInt16 nWhich
 void EditEngine::SetCharAttribs(sal_Int32 nPara, const SfxItemSet& rSet)
 {
     EditSelection aSel(pImpEditEngine->ConvertSelection(nPara, 0, nPara, 
GetTextLen(nPara)));
-    pImpEditEngine->SetAttribs(aSel, rSet);
+    // This is called by sd::View::OnBeginPasteOrDrop(), updating the cursor 
position on undo is not
+    // wanted.
+    pImpEditEngine->SetAttribs(aSel, rSet, /*nSpecial=*/SetAttribsMode::NONE, 
/*bSetSelection=*/false);
     pImpEditEngine->FormatAndUpdate();
 }
 
diff --git a/editeng/source/editeng/editundo.cxx 
b/editeng/source/editeng/editundo.cxx
index 714dd1b682ed..892183f754af 100644
--- a/editeng/source/editeng/editundo.cxx
+++ b/editeng/source/editeng/editundo.cxx
@@ -501,6 +501,7 @@ EditUndoSetAttribs::EditUndoSetAttribs(EditEngine* pEE, 
const ESelection& rESel,
     aESel(rESel),
     aNewAttribs(rNewItems),
     nSpecial(SetAttribsMode::NONE),
+    m_bSetSelection(true),
     // When EditUndoSetAttribs actually is a RemoveAttribs this could be
     // recognize by the empty itemset, but then it would have to be caught in
     // its own place, which possible a setAttribs does with an empty itemset.
@@ -560,7 +561,10 @@ void EditUndoSetAttribs::Undo()
     }
     if ( bFields )
         pEE->UpdateFieldsOnly();
-    ImpSetSelection();
+    if (m_bSetSelection)
+    {
+        ImpSetSelection();
+    }
 }
 
 void EditUndoSetAttribs::Redo()
@@ -574,7 +578,10 @@ void EditUndoSetAttribs::Redo()
     else
         pEE->RemoveCharAttribs( aSel, bRemoveParaAttribs, nRemoveWhich );
 
-    ImpSetSelection();
+    if (m_bSetSelection)
+    {
+        ImpSetSelection();
+    }
 }
 
 void EditUndoSetAttribs::AppendContentInfo(ContentAttribsInfo* pNew)
diff --git a/editeng/source/editeng/editundo.hxx 
b/editeng/source/editeng/editundo.hxx
index 43d2a0d3b911..f87180ba7dd7 100644
--- a/editeng/source/editeng/editundo.hxx
+++ b/editeng/source/editeng/editundo.hxx
@@ -218,6 +218,8 @@ private:
     InfoArrayType       aPrevAttribs;
 
     SetAttribsMode      nSpecial;
+    /// Once the attributes are set / unset, set the selection to the end of 
the formatted range?
+    bool m_bSetSelection;
     bool                bSetIsRemove;
     bool                bRemoveParaAttribs;
     sal_uInt16          nRemoveWhich;
@@ -232,6 +234,7 @@ public:
     SfxItemSet&         GetNewAttribs()     { return aNewAttribs; }
 
     void                SetSpecial( SetAttribsMode n )  { nSpecial = n; }
+    void                SetUpdateSelection( bool bSetSelection )  { 
m_bSetSelection = bSetSelection; }
     void                SetRemoveAttribs( bool b )      { bSetIsRemove = b; }
     void                SetRemoveParaAttribs( bool b )  { bRemoveParaAttribs = 
b; }
     void                SetRemoveWhich( sal_uInt16 n )  { nRemoveWhich = n; }
diff --git a/editeng/source/editeng/impedit.hxx 
b/editeng/source/editeng/impedit.hxx
index c56b6b284f1a..3855f38da45c 100644
--- a/editeng/source/editeng/impedit.hxx
+++ b/editeng/source/editeng/impedit.hxx
@@ -910,7 +910,7 @@ public:
 
     SfxItemSet      GetAttribs( sal_Int32 nPara, sal_Int32 nStart, sal_Int32 
nEnd, GetAttribsFlags nFlags = GetAttribsFlags::ALL ) const;
     SfxItemSet      GetAttribs( EditSelection aSel, EditEngineAttribs 
nOnlyHardAttrib = EditEngineAttribs::All  );
-    void            SetAttribs( EditSelection aSel, const SfxItemSet& rSet, 
SetAttribsMode nSpecial = SetAttribsMode::NONE );
+    void            SetAttribs( EditSelection aSel, const SfxItemSet& rSet, 
SetAttribsMode nSpecial = SetAttribsMode::NONE, bool bSetSelection = true );
     void            RemoveCharAttribs( EditSelection aSel, 
EERemoveParaAttribsMode eMode, sal_uInt16 nWhich );
     void            RemoveCharAttribs( sal_Int32 nPara, sal_uInt16 nWhich = 0, 
bool bRemoveFeatures = false );
     void            SetFlatMode( bool bFlat );
diff --git a/editeng/source/editeng/impedit5.cxx 
b/editeng/source/editeng/impedit5.cxx
index 02133496bb6b..d1846f1df880 100644
--- a/editeng/source/editeng/impedit5.cxx
+++ b/editeng/source/editeng/impedit5.cxx
@@ -483,7 +483,7 @@ SfxItemSet ImpEditEngine::GetAttribs( sal_Int32 nPara, 
sal_Int32 nStart, sal_Int
 }
 
 
-void ImpEditEngine::SetAttribs( EditSelection aSel, const SfxItemSet& rSet, 
SetAttribsMode nSpecial )
+void ImpEditEngine::SetAttribs( EditSelection aSel, const SfxItemSet& rSet, 
SetAttribsMode nSpecial, bool bSetSelection )
 {
     aSel.Adjust( aEditDoc );
 
@@ -499,6 +499,7 @@ void ImpEditEngine::SetAttribs( EditSelection aSel, const 
SfxItemSet& rSet, SetA
     {
         std::unique_ptr<EditUndoSetAttribs> pUndo = CreateAttribUndo( aSel, 
rSet );
         pUndo->SetSpecial( nSpecial );
+        pUndo->SetUpdateSelection(bSetSelection);
         InsertUndo( std::move(pUndo) );
     }
 
diff --git a/sd/qa/unit/tiledrendering/data/paste-undo.fodp 
b/sd/qa/unit/tiledrendering/data/paste-undo.fodp
new file mode 100644
index 000000000000..2615d1e11445
--- /dev/null
+++ b/sd/qa/unit/tiledrendering/data/paste-undo.fodp
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<office:document 
xmlns:presentation="urn:oasis:names:tc:opendocument:xmlns:presentation:1.0" 
xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" 
xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" 
xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" 
xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" 
xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" 
xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" 
office:version="1.3" 
office:mimetype="application/vnd.oasis.opendocument.presentation">
+  <office:styles>
+    <style:presentation-page-layout style:name="AL1T0">
+      <presentation:placeholder presentation:object="title" svg:x="2.058cm" 
svg:y="1.743cm" svg:width="23.912cm" svg:height="3.507cm"/>
+      <presentation:placeholder presentation:object="subtitle" svg:x="2.058cm" 
svg:y="5.838cm" svg:width="23.912cm" svg:height="13.23cm"/>
+    </style:presentation-page-layout>
+  </office:styles>
+  <office:automatic-styles>
+    <style:page-layout style:name="PM0">
+      <style:page-layout-properties fo:margin-top="0cm" fo:margin-bottom="0cm" 
fo:margin-left="0cm" fo:margin-right="0cm" fo:page-width="21cm" 
fo:page-height="29.7cm" style:print-orientation="portrait"/>
+    </style:page-layout>
+    <style:page-layout style:name="PM1">
+      <style:page-layout-properties fo:margin-top="0cm" fo:margin-bottom="0cm" 
fo:margin-left="0cm" fo:margin-right="0cm" fo:page-width="28cm" 
fo:page-height="15.75cm" style:print-orientation="landscape"/>
+    </style:page-layout>
+    <style:style style:name="dp3" style:family="drawing-page">
+    </style:style>
+    <style:style style:name="gr3" style:family="graphic" 
style:parent-style-name="standard">
+      <style:graphic-properties draw:stroke="none" svg:stroke-color="#000000" 
draw:fill="none" draw:fill-color="#ffffff" draw:auto-grow-height="true" 
draw:auto-grow-width="false" fo:max-height="0cm" fo:min-height="0.712cm"/>
+      <style:paragraph-properties style:writing-mode="lr-tb"/>
+    </style:style>
+  </office:automatic-styles>
+  <office:body>
+    <office:presentation>
+      <draw:page draw:name="page1" draw:style-name="dp3" 
draw:master-page-name="Default" 
presentation:presentation-page-layout-name="AL1T0">
+        <draw:frame draw:style-name="gr3" draw:text-style-name="P7" 
draw:layer="layout" svg:width="7.5cm" svg:height="0.962cm" svg:x="3.5cm" 
svg:y="3.5cm">
+          <draw:text-box>
+            <text:p>world</text:p>
+          </draw:text-box>
+        </draw:frame>
+      </draw:page>
+    </office:presentation>
+  </office:body>
+</office:document>
diff --git a/sd/qa/unit/tiledrendering/tiledrendering.cxx 
b/sd/qa/unit/tiledrendering/tiledrendering.cxx
index 02856dd0043e..1bdd4c30386a 100644
--- a/sd/qa/unit/tiledrendering/tiledrendering.cxx
+++ b/sd/qa/unit/tiledrendering/tiledrendering.cxx
@@ -8,6 +8,9 @@
  */
 
 #include "../sdmodeltestbase.hxx"
+
+#include <com/sun/star/datatransfer/clipboard/SystemClipboard.hpp>
+
 #include <app.hrc>
 #include <test/bootstrapfixture.hxx>
 #include <test/helper/transferable.hxx>
@@ -53,6 +56,7 @@
 #include <vcl/cursor.hxx>
 #include <vcl/scheduler.hxx>
 #include <vcl/vclevent.hxx>
+#include <vcl/unohelp2.hxx>
 
 #include <chrono>
 #include <cstdlib>
@@ -133,6 +137,7 @@ public:
     void testSlideDuplicateUndo();
     void testMoveShapeHandle();
     void testDeleteTable();
+    void testPasteUndo();
 
     CPPUNIT_TEST_SUITE(SdTiledRenderingTest);
     CPPUNIT_TEST(testCreateDestroy);
@@ -190,6 +195,7 @@ public:
     CPPUNIT_TEST(testSlideDuplicateUndo);
     CPPUNIT_TEST(testMoveShapeHandle);
     CPPUNIT_TEST(testDeleteTable);
+    CPPUNIT_TEST(testPasteUndo);
 
     CPPUNIT_TEST_SUITE_END();
 
@@ -2679,6 +2685,41 @@ void SdTiledRenderingTest::testMoveShapeHandle()
     }
 
 }
+
+void SdTiledRenderingTest::testPasteUndo()
+{
+    // Given a document with a textbox, containing "world":
+    SdXImpressDocument* pXImpressDocument = createDoc("paste-undo.fodp");
+    sd::ViewShell* pViewShell = 
pXImpressDocument->GetDocShell()->GetViewShell();
+    SdPage* pActualPage = pViewShell->GetActualPage();
+    SdrObject* pObject = pActualPage->GetObj(0);
+    SdrView* pView = pViewShell->GetView();
+    pView->MarkObj(pObject, pView->GetSdrPageView());
+    pView->SdrBeginTextEdit(pObject);
+    pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_HOME);
+    pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, KEY_HOME);
+    EditView& rEditView = pView->GetTextEditOutlinerView()->GetEditView();
+    ESelection aWordSelection(0, 0, 0, 1); // "w" of "world"
+    rEditView.SetSelection(aWordSelection);
+    comphelper::dispatchCommand(".uno:Cut", {});
+    Scheduler::ProcessEventsToIdle();
+
+    // When undoing a paste:
+    comphelper::dispatchCommand(".uno:Paste", {});
+    Scheduler::ProcessEventsToIdle();
+    comphelper::dispatchCommand(".uno:Undo", {});
+    Scheduler::ProcessEventsToIdle();
+
+    // Then make sure the cursor position is still at the beginning:
+    ESelection aSelection = rEditView.GetSelection();
+    // Without the accompanying fix in place, this test would have failed with:
+    // - Expected: 0
+    // - Actual  : 4
+    // i.e. the cursor position after undo was at the end of the line, not at 
the start, as
+    // expected.
+    CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(0), aSelection.nStartPos);
+}
+
 CPPUNIT_TEST_SUITE_REGISTRATION(SdTiledRenderingTest);
 
 CPPUNIT_PLUGIN_IMPLEMENT();

Reply via email to