sc/inc/cellsuno.hxx                      |   11 +++++
 sc/qa/extras/macros-test.cxx             |   57 +++++++++++++++++++++++++++++++
 sc/source/ui/unoobj/cellsuno.cxx         |   48 +++++++++++++++++++-------
 sw/qa/uitest/writer_tests3/pageNumber.py |    9 ++--
 sw/source/uibase/shells/textfld.cxx      |    4 ++
 5 files changed, 113 insertions(+), 16 deletions(-)

New commits:
commit 1f3b872e8c4901ff36e07bb973e008f6849af21c
Author:     Mike Kaganski <mike.kagan...@collabora.com>
AuthorDate: Fri May 2 09:55:27 2025 +0200
Commit:     Xisco Fauli <xiscofa...@libreoffice.org>
CommitDate: Fri May 2 20:18:53 2025 +0200

    tdf#47479: Do not modify range of sheet / column / row in notifications
    
    Change-Id: I2c5afa5397e3a98806908a2f73f8d654e83fb890
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/184889
    Tested-by: Jenkins
    Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com>
    Signed-off-by: Xisco Fauli <xiscofa...@libreoffice.org>
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/184908

diff --git a/sc/inc/cellsuno.hxx b/sc/inc/cellsuno.hxx
index 9f7709631778..259571901721 100644
--- a/sc/inc/cellsuno.hxx
+++ b/sc/inc/cellsuno.hxx
@@ -226,6 +226,9 @@ protected:
     SC_DLLPUBLIC virtual void SetOnePropertyValue( const 
SfxItemPropertyMapEntry* pEntry,
                                                 const css::uno::Any& aValue );
 
+    ScRangeList& AccessRanges() { return aRanges; }
+    SC_DLLPUBLIC virtual void AdjustUpdatedRanges(UpdateRefMode mode);
+
 public:
                             ScCellRangesBase(ScDocShell* pDocSh, const 
ScRange& rR);
                             ScCellRangesBase(ScDocShell* pDocSh, ScRangeList 
aR);
@@ -956,6 +959,9 @@ public:
                             // XTypeProvider
     virtual css::uno::Sequence< css::uno::Type > SAL_CALL getTypes() override;
     virtual css::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId() 
override;
+
+protected:
+    void AdjustUpdatedRanges(UpdateRefMode mode) override;
 };
 
 class ScTableColumnObj final : public ScCellRangeObj,
@@ -995,6 +1001,8 @@ public:
                             // XTypeProvider
     virtual css::uno::Sequence< css::uno::Type > SAL_CALL getTypes() override;
     virtual css::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId() 
override;
+protected:
+    void AdjustUpdatedRanges(UpdateRefMode mode) override;
 };
 
 class ScTableRowObj final : public ScCellRangeObj
@@ -1020,6 +1028,9 @@ public:
     virtual OUString SAL_CALL getImplementationName() override;
     virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) 
override;
     virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() 
override;
+
+protected:
+    void AdjustUpdatedRanges(UpdateRefMode mode) override;
 };
 
 class ScCellsObj final : public cppu::WeakImplHelper<
diff --git a/sc/qa/extras/macros-test.cxx b/sc/qa/extras/macros-test.cxx
index 6e2b81a01ecd..c9148f64854d 100644
--- a/sc/qa/extras/macros-test.cxx
+++ b/sc/qa/extras/macros-test.cxx
@@ -17,8 +17,11 @@
 #include <document.hxx>
 #include <scitems.hxx>
 
+#include <com/sun/star/sheet/XCellRangeAddressable.hpp>
+#include <com/sun/star/sheet/XCellRangeMovement.hpp>
 #include <com/sun/star/sheet/XFunctionAccess.hpp>
 #include <com/sun/star/sheet/XSpreadsheet.hpp>
+#include <com/sun/star/table/XColumnRowRange.hpp>
 
 #include <com/sun/star/script/XLibraryContainerPassword.hpp>
 #include <com/sun/star/drawing/XDrawPageSupplier.hpp>
@@ -919,6 +922,60 @@ CPPUNIT_TEST_FIXTURE(ScMacrosTest, testTdf159412)
     CPPUNIT_ASSERT_EQUAL(u"1 Long/2 Double"_ustr, aReturnValue);
 }
 
+CPPUNIT_TEST_FIXTURE(ScMacrosTest, testTdf47479)
+{
+    createScDoc();
+    uno::Reference<sheet::XSpreadsheetDocument> xDoc(mxComponent, 
UNO_QUERY_THROW);
+    auto xSheets = xDoc->getSheets().queryThrow<container::XIndexAccess>();
+    auto xSheet = 
xSheets->getByIndex(0).queryThrow<sheet::XCellRangeMovement>();
+    auto xSheetAddressable = xSheet.queryThrow<sheet::XCellRangeAddressable>();
+    auto xColRowRange = xSheet.queryThrow<table::XColumnRowRange>();
+    auto xColAddressable
+        = 
xColRowRange->getColumns()->getByIndex(1).queryThrow<sheet::XCellRangeAddressable>();
+    auto xRowAddressable
+        = 
xColRowRange->getRows()->getByIndex(1).queryThrow<sheet::XCellRangeAddressable>();
+    css::table::CellRangeAddress origSheetRange = 
xSheetAddressable->getRangeAddress();
+    css::table::CellRangeAddress origColRange = 
xColAddressable->getRangeAddress();
+    css::table::CellRangeAddress origRowRange = 
xRowAddressable->getRangeAddress();
+    css::table::CellRangeAddress addressToRemove(origSheetRange.Sheet, 1, 1, 
1, 1);
+
+    xSheet->removeRange(addressToRemove, css::sheet::CellDeleteMode_UP);
+
+    auto currentRange = xSheetAddressable->getRangeAddress();
+    CPPUNIT_ASSERT_EQUAL(origSheetRange.Sheet, currentRange.Sheet);
+    CPPUNIT_ASSERT_EQUAL(origSheetRange.StartColumn, currentRange.StartColumn);
+    CPPUNIT_ASSERT_EQUAL(origSheetRange.StartRow, currentRange.StartRow);
+    CPPUNIT_ASSERT_EQUAL(origSheetRange.EndColumn, currentRange.EndColumn);
+    // Without the fix, this would fail with
+    // - Expected: 1048575
+    // - Actual  : 0
+    CPPUNIT_ASSERT_EQUAL(origSheetRange.EndRow, currentRange.EndRow);
+
+    xSheet->removeRange(addressToRemove, css::sheet::CellDeleteMode_LEFT);
+
+    currentRange = xColAddressable->getRangeAddress();
+    CPPUNIT_ASSERT_EQUAL(origColRange.Sheet, currentRange.Sheet);
+    CPPUNIT_ASSERT_EQUAL(origColRange.StartColumn, currentRange.StartColumn);
+    // Without the fix, this would fail with
+    // - Expected: 0
+    // - Actual  : 2
+    CPPUNIT_ASSERT_EQUAL(origColRange.StartRow, currentRange.StartRow);
+    CPPUNIT_ASSERT_EQUAL(origColRange.EndColumn, currentRange.EndColumn);
+    CPPUNIT_ASSERT_EQUAL(origColRange.EndRow, currentRange.EndRow);
+
+    xSheet->removeRange(origColRange, css::sheet::CellDeleteMode_UP);
+
+    currentRange = xRowAddressable->getRangeAddress();
+    CPPUNIT_ASSERT_EQUAL(origRowRange.Sheet, currentRange.Sheet);
+    // Without the fix, this would fail with
+    // - Expected: 0
+    // - Actual  : 2
+    CPPUNIT_ASSERT_EQUAL(origRowRange.StartColumn, currentRange.StartColumn);
+    CPPUNIT_ASSERT_EQUAL(origRowRange.StartRow, currentRange.StartRow);
+    CPPUNIT_ASSERT_EQUAL(origRowRange.EndColumn, currentRange.EndColumn);
+    CPPUNIT_ASSERT_EQUAL(origRowRange.EndRow, currentRange.EndRow);
+}
+
 ScMacrosTest::ScMacrosTest()
       : ScModelTestBase(u"/sc/qa/extras/testdocuments"_ustr)
 {
diff --git a/sc/source/ui/unoobj/cellsuno.cxx b/sc/source/ui/unoobj/cellsuno.cxx
index 29f437e77529..2e5e6b60be14 100644
--- a/sc/source/ui/unoobj/cellsuno.cxx
+++ b/sc/source/ui/unoobj/cellsuno.cxx
@@ -1475,6 +1475,8 @@ const ScMarkData* ScCellRangesBase::GetMarkData()
     return pMarkData.get();
 }
 
+void ScCellRangesBase::AdjustUpdatedRanges(UpdateRefMode) {}
+
 void ScCellRangesBase::Notify( SfxBroadcaster&, const SfxHint& rHint )
 {
     const SfxHintId nId = rHint.GetId();
@@ -1546,18 +1548,7 @@ void ScCellRangesBase::Notify( SfxBroadcaster&, const 
SfxHint& rHint )
         if ( aRanges.UpdateReference( pRefHint->GetMode(), &rDoc, 
pRefHint->GetRange(),
                                     pRefHint->GetDx(), pRefHint->GetDy(), 
pRefHint->GetDz() ) )
         {
-            if (  pRefHint->GetMode() == URM_INSDEL
-               && aRanges.size() == 1
-               && dynamic_cast<ScTableSheetObj*>(this)
-               )
-            {
-                // #101755#; the range size of a sheet does not change
-                ScRange & rR = aRanges.front();
-                rR.aStart.SetCol(0);
-                rR.aStart.SetRow(0);
-                rR.aEnd.SetCol(rDoc.MaxCol());
-                rR.aEnd.SetRow(rDoc.MaxRow());
-            }
+            AdjustUpdatedRanges(pRefHint->GetMode());
             RefChanged();
 
             // any change of the range address is broadcast to value (modify) 
listeners
@@ -6596,6 +6587,17 @@ SCTAB ScTableSheetObj::GetTab_Impl() const
     return 0;
 }
 
+void ScTableSheetObj::AdjustUpdatedRanges(UpdateRefMode mode)
+{
+    if (mode == URM_INSDEL)
+    {
+        ScRangeList& rRanges = AccessRanges();
+        // #101755#, tdf#47479: the range of a sheet does not change
+        rRanges.RemoveAll();
+        rRanges.push_back(GetRange());
+    }
+}
+
 // former XSheet
 
 uno::Reference<table::XTableCharts> SAL_CALL ScTableSheetObj::getCharts()
@@ -8431,6 +8433,17 @@ const SfxItemPropertyMap& 
ScTableColumnObj::GetItemPropertyMap()
     return pColPropSet->getPropertyMap();
 }
 
+void ScTableColumnObj::AdjustUpdatedRanges(UpdateRefMode mode)
+{
+    if (mode == URM_INSDEL)
+    {
+        ScRangeList& rRanges = AccessRanges();
+        // tdf#47479: the range of a column does not change
+        rRanges.RemoveAll();
+        rRanges.push_back(GetRange());
+    }
+}
+
 ScTableRowObj::ScTableRowObj(ScDocShell* pDocSh, SCROW nRow, SCTAB nTab) :
     ScCellRangeObj( pDocSh, ScRange(0,nRow,nTab, 
pDocSh->GetDocument().MaxCol(),nRow,nTab) ),
     pRowPropSet(lcl_GetRowPropertySet())
@@ -8580,6 +8593,17 @@ const SfxItemPropertyMap& 
ScTableRowObj::GetItemPropertyMap()
     return pRowPropSet->getPropertyMap();
 }
 
+void ScTableRowObj::AdjustUpdatedRanges(UpdateRefMode mode)
+{
+    if (mode == URM_INSDEL)
+    {
+        ScRangeList& rRanges = AccessRanges();
+        // tdf#47479: the range of a row does not change
+        rRanges.RemoveAll();
+        rRanges.push_back(GetRange());
+    }
+}
+
 ScCellsObj::ScCellsObj(ScDocShell* pDocSh, ScRangeList aR) :
     pDocShell( pDocSh ),
     aRanges(std::move( aR ))
commit 260a77ad9b04dd53712ebc061dffa4c1b77a88b1
Author:     Justin Luth <jl...@mail.com>
AuthorDate: Fri Jul 19 09:50:11 2024 -0400
Commit:     Xisco Fauli <xiscofa...@libreoffice.org>
CommitDate: Fri May 2 20:18:42 2025 +0200

    tdf#164033 tdf#161741 tdf#161705 pgnum wizard: avoid undo crash 
(sledgehammer)
    
    I have zero knowledge of the many intricate pitfalls of undo/redo,
    so there is no way I could create a "proper" fix.
    
    LO 7.6 introduced the page number wizard which has more prominently
    exposed existing ways to make undo/redo of page style changes
    to crash. So treat this as pre-LO 7.2
    and simply erase the undo stack after running the wizard.
    ------------------------------------------------------------------
    The ability to undo/redo the "Header/footer change" started in
    bibisect-linux-64-7.2 commit 910d9a081daf11ea53235d227c3dc9623942a824
    commit 8d8486f43c1a8a51157bfc3e0b87090b05a9229e
    Author: Daniel Arato (NISZ) on Mon Feb 22 16:59:38 2021 +0100
        tdf#46561 sw: fix lost undo stack setting header/footer
    
    -   if( bHeaderFooterChanged )
    -       GetIDocumentUndoRedo().DelAllUndoObj();
    
    Change-Id: I00c529784bfd7b2cd1230474c05eea8516e6c1e3
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/170771
    Tested-by: Jenkins
    Tested-by: Xisco Fauli <xiscofa...@libreoffice.org>
    Reviewed-by: Xisco Fauli <xiscofa...@libreoffice.org>
    (cherry picked from commit f84369daa125717f3c87fe34abb0b91c6f6ba3d5)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/184903
    Reviewed-by: Justin Luth <jl...@mail.com>

diff --git a/sw/qa/uitest/writer_tests3/pageNumber.py 
b/sw/qa/uitest/writer_tests3/pageNumber.py
index f148d047b33d..30c6ea4781bc 100644
--- a/sw/qa/uitest/writer_tests3/pageNumber.py
+++ b/sw/qa/uitest/writer_tests3/pageNumber.py
@@ -40,7 +40,8 @@ class PageNumberWizard(UITestCase):
             self.xUITest.executeCommand(".uno:Undo")
 
             
self.assertIsNone(document.StyleFamilies.PageStyles.Standard.HeaderText)
-            
self.assertIsNone(document.StyleFamilies.PageStyles.Standard.FooterText)
+            # FIXME: tdf#164033: Undo is disabled to avoid the crash
+            
self.assertIsNotNone(document.StyleFamilies.PageStyles.Standard.FooterText)
 
             with 
self.ui_test.execute_dialog_through_command(".uno:PageNumberWizard") as xDialog:
                 xPositionCombo = xDialog.getChild("positionCombo")
@@ -50,11 +51,11 @@ class PageNumberWizard(UITestCase):
 
             xHeader = 
document.StyleFamilies.PageStyles.Standard.HeaderText.createEnumeration().nextElement()
             self.assertEqual("A", xHeader.String)
-            
self.assertIsNone(document.StyleFamilies.PageStyles.Standard.FooterText)
+            
self.assertIsNotNone(document.StyleFamilies.PageStyles.Standard.FooterText)
 
             self.xUITest.executeCommand(".uno:Undo")
 
-            
self.assertIsNone(document.StyleFamilies.PageStyles.Standard.HeaderText)
-            
self.assertIsNone(document.StyleFamilies.PageStyles.Standard.FooterText)
+            
self.assertIsNotNone(document.StyleFamilies.PageStyles.Standard.HeaderText)
+            
self.assertIsNotNone(document.StyleFamilies.PageStyles.Standard.FooterText)
 
 # vim: set shiftwidth=4 softtabstop=4 expandtab:
diff --git a/sw/source/uibase/shells/textfld.cxx 
b/sw/source/uibase/shells/textfld.cxx
index 42fd111f2684..a3d67d44b073 100644
--- a/sw/source/uibase/shells/textfld.cxx
+++ b/sw/source/uibase/shells/textfld.cxx
@@ -1459,6 +1459,10 @@ FIELD_INSERT:
                 rSh.EndAllAction();
                 rSh.LockView(false);
                 
rDoc.GetIDocumentUndoRedo().EndUndo(SwUndoId::INSERT_PAGE_NUMBER, nullptr);
+
+                // avoid various ways to crash related to undo of SwPageDesc 
(tdf#161741, tdf#161705)
+                if (bChangePageDesc)
+                    rDoc.GetIDocumentUndoRedo().DelAllUndoObj();
             }
             pDlg->disposeOnce();
         });

Reply via email to