include/sfx2/lokhelper.hxx       |    2 +
 sc/inc/table.hxx                 |    9 ++++
 sc/qa/unit/ucalc.cxx             |    2 +
 sc/source/core/data/document.cxx |    9 ++++
 sc/source/core/data/table1.cxx   |   19 ++++++++--
 sc/source/ui/docshell/docsh.cxx  |    2 +
 sc/source/ui/inc/docsh.hxx       |   44 ++++++++++++++++++-----
 sc/source/ui/undo/undoblk3.cxx   |    4 +-
 sc/source/ui/undo/undocell.cxx   |   17 ++++++--
 sc/source/ui/unoobj/docuno.cxx   |   74 ++++++++++++++++++++++++++++++++++++---
 sc/source/ui/view/viewfun2.cxx   |   10 +++--
 sc/source/ui/view/viewfun3.cxx   |   10 +++--
 sc/source/ui/view/viewfunc.cxx   |   46 ++++++++++++++++--------
 sfx2/source/view/lokhelper.cxx   |   14 +++++++
 14 files changed, 216 insertions(+), 46 deletions(-)

New commits:
commit 0a55aa8ba38aea56a2bce1504fd687e510f66b9d
Author:     Szymon Kłos <szymon.k...@collabora.com>
AuthorDate: Fri Nov 4 15:19:13 2022 +0100
Commit:     Szymon Kłos <szymon.k...@collabora.com>
CommitDate: Mon Nov 21 12:37:18 2022 +0100

    calc: cache GetCellArea results
    
    This will avoid repeated lookup in the ScTable::GetCellArea.
    Which is used for vcl::ITiledRenderable::getDataArea().
    
    Tested in CppunitTest_sc_ucalc
    
    Change-Id: Ied58cfe447e1b924af9b401e95e127c784b80355
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/142279
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com>
    Reviewed-by: Dennis Francis <dennis.fran...@collabora.com>
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/142995
    Tested-by: Jenkins
    Reviewed-by: Szymon Kłos <szymon.k...@collabora.com>

diff --git a/sc/inc/table.hxx b/sc/inc/table.hxx
index a9d2ad71bd39..f81e3925964e 100644
--- a/sc/inc/table.hxx
+++ b/sc/inc/table.hxx
@@ -178,6 +178,12 @@ private:
     SCROW           nRepeatStartY;
     SCROW           nRepeatEndY;
 
+    // last used col and row
+    bool            mbCellAreaDirty;
+    bool            mbCellAreaEmpty;
+    SCCOL           mnEndCol;
+    SCROW           mnEndRow;
+
     std::unique_ptr<ScTableProtection> pTabProtection;
 
     std::unique_ptr<ScCompressedArray<SCCOL, sal_uInt16>> mpColWidth;
@@ -604,7 +610,8 @@ public:
     void        InvalidateTableArea();
     void        InvalidatePageBreaks();
 
-    bool        GetCellArea( SCCOL& rEndCol, SCROW& rEndRow ) const;           
 // FALSE = empty
+    void        InvalidateCellArea() { mbCellAreaDirty = true; }
+    bool        GetCellArea( SCCOL& rEndCol, SCROW& rEndRow );            // 
FALSE = empty
     bool        GetTableArea( SCCOL& rEndCol, SCROW& rEndRow, bool 
bCalcHiddens = false) const;
     bool        GetPrintArea( SCCOL& rEndCol, SCROW& rEndRow, bool bNotes, 
bool bCalcHiddens = false) const;
     bool        GetPrintAreaHor( SCROW nStartRow, SCROW nEndRow,
diff --git a/sc/qa/unit/ucalc.cxx b/sc/qa/unit/ucalc.cxx
index 321977460cb7..257a80bd4b50 100644
--- a/sc/qa/unit/ucalc.cxx
+++ b/sc/qa/unit/ucalc.cxx
@@ -41,6 +41,7 @@
 #include <columnspanset.hxx>
 
 #include <editable.hxx>
+#include <table.hxx>
 #include <tabprotection.hxx>
 #include <undomanager.hxx>
 
@@ -5387,6 +5388,7 @@ void Test::testAreasWithNotes()
 
     m_pDoc->SetString(0, 3, 0, "Some Text");
     m_pDoc->SetString(3, 3, 0, "Some Text");
+    m_pDoc->FetchTable(0)->InvalidateCellArea();
 
     dataFound = m_pDoc->GetDataStart(0,col,row);
 
diff --git a/sc/source/core/data/document.cxx b/sc/source/core/data/document.cxx
index 19e01a6d06c0..a907c9184754 100644
--- a/sc/source/core/data/document.cxx
+++ b/sc/source/core/data/document.cxx
@@ -41,6 +41,7 @@
 #include <com/sun/star/lang/NotInitializedException.hpp>
 
 #include <document.hxx>
+#include <docsh.hxx>
 #include <docuno.hxx>
 #include <table.hxx>
 #include <column.hxx>
@@ -6748,7 +6749,15 @@ void ScDocument::SetNote(const ScAddress& rPos, 
std::unique_ptr<ScPostIt> pNote)
 void ScDocument::SetNote(SCCOL nCol, SCROW nRow, SCTAB nTab, 
std::unique_ptr<ScPostIt> pNote)
 {
     if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()))
+    {
         maTabs[nTab]->SetNote(nCol, nRow, std::move(pNote));
+
+        if (ScDocShell* pDocSh = dynamic_cast<ScDocShell*>(GetDocumentShell()))
+        {
+            HelperNotifyChanges::NotifyIfChangesListeners(
+                *pDocSh, ScRange(nCol, nRow, nTab), "note");
+        }
+    }
 }
 
 bool ScDocument::HasNote(const ScAddress& rPos) const
diff --git a/sc/source/core/data/table1.cxx b/sc/source/core/data/table1.cxx
index d0828d04b5d4..78c49912bcc9 100644
--- a/sc/source/core/data/table1.cxx
+++ b/sc/source/core/data/table1.cxx
@@ -244,6 +244,10 @@ ScTable::ScTable( ScDocument& rDoc, SCTAB nNewTab, const 
OUString& rNewName,
     nRepeatEndX( SCCOL_REPEAT_NONE ),
     nRepeatStartY( SCROW_REPEAT_NONE ),
     nRepeatEndY( SCROW_REPEAT_NONE ),
+    mbCellAreaDirty( true ),
+    mbCellAreaEmpty( true ),
+    mnEndCol( -1 ),
+    mnEndRow( -1 ),
     mpRowHeights( static_cast<ScFlatUInt16RowSegments*>(nullptr) ),
     mpHiddenCols(new ScFlatBoolColSegments(rDoc.MaxCol())),
     mpHiddenRows(new ScFlatBoolRowSegments(rDoc.MaxRow())),
@@ -510,8 +514,15 @@ void ScTable::SetOptimalHeightOnly(
         delete pProgress;
 }
 
-bool ScTable::GetCellArea( SCCOL& rEndCol, SCROW& rEndRow ) const
+bool ScTable::GetCellArea( SCCOL& rEndCol, SCROW& rEndRow )
 {
+    if (!mbCellAreaDirty)
+    {
+        rEndCol = mnEndCol;
+        rEndRow = mnEndRow;
+        return !mbCellAreaEmpty;
+    }
+
     bool bFound = false;
     SCCOL nMaxX = 0;
     SCROW nMaxY = 0;
@@ -555,8 +566,10 @@ bool ScTable::GetCellArea( SCCOL& rEndCol, SCROW& rEndRow 
) const
             }
     }
 
-    rEndCol = nMaxX;
-    rEndRow = nMaxY;
+    mnEndCol = rEndCol = nMaxX;
+    mnEndRow = rEndRow = nMaxY;
+    mbCellAreaEmpty = !bFound;
+    mbCellAreaDirty = false;
     return bFound;
 }
 
diff --git a/sc/source/ui/docshell/docsh.cxx b/sc/source/ui/docshell/docsh.cxx
index 40a8311b7bf7..2f2f3521ae4e 100644
--- a/sc/source/ui/docshell/docsh.cxx
+++ b/sc/source/ui/docshell/docsh.cxx
@@ -116,6 +116,7 @@
 #include <warnpassword.hxx>
 #include <optsolver.hxx>
 #include <sheetdata.hxx>
+#include <table.hxx>
 #include <tabprotection.hxx>
 #include <docparam.hxx>
 #include "docshimp.hxx"
diff --git a/sc/source/ui/inc/docsh.hxx b/sc/source/ui/inc/docsh.hxx
index 660f17aee3f4..8fac5cf6ed5a 100644
--- a/sc/source/ui/inc/docsh.hxx
+++ b/sc/source/ui/inc/docsh.hxx
@@ -470,13 +470,34 @@ public:
 //#i97876# Spreadsheet data changes are not notified
 namespace HelperNotifyChanges
 {
-    inline ScModelObj* getMustPropagateChangesModel(const ScDocShell 
&rDocShell)
+    inline bool isDataAreaInvalidateType(std::u16string_view rType)
     {
-        ScModelObj* pModelObj = 
comphelper::getFromUnoTunnel<ScModelObj>(rDocShell.GetModel());
-        const bool isLOK = comphelper::LibreOfficeKit::isActive(); // for 
LOK_CALLBACK_DOCUMENT_SIZE_CHANGED
-        if (pModelObj && (pModelObj->HasChangesListeners() || isLOK))
-            return pModelObj;
-        return nullptr;
+        if (rType == u"delete-content")
+            return true;
+        if (rType == u"delete-rows")
+            return true;
+        if (rType == u"delete-columns")
+            return true;
+        if (rType == u"undo")
+            return true;
+        if (rType == u"redo")
+            return true;
+        if (rType == u"paste")
+            return true;
+        if (rType == u"note")
+            return true;
+
+        return false;
+    }
+
+    inline ScModelObj* getModel(const ScDocShell &rDocShell)
+    {
+        return comphelper::getFromUnoTunnel<ScModelObj>(rDocShell.GetModel());
+    }
+
+    inline bool getMustPropagateChangesModel(ScModelObj* pModelObj)
+    {
+        return pModelObj && pModelObj->HasChangesListeners();
     }
 
     inline void Notify(ScModelObj &rModelObj, const ScRangeList &rChangeRanges,
@@ -490,10 +511,15 @@ namespace HelperNotifyChanges
     inline void NotifyIfChangesListeners(const ScDocShell &rDocShell, const 
ScRange &rRange,
         const OUString &rType = OUString("cell-change"))
     {
-        if (ScModelObj* pModelObj = getMustPropagateChangesModel(rDocShell))
-        {
-            ScRangeList aChangeRanges(rRange);
+        ScModelObj* pModelObj = getModel(rDocShell);
+        ScRangeList aChangeRanges(rRange);
+
+        if (getMustPropagateChangesModel(pModelObj))
             Notify(*pModelObj, aChangeRanges, rType);
+        else if (pModelObj) // possibly need to invalidate getCellArea results
+        {
+            Notify(*pModelObj, aChangeRanges, isDataAreaInvalidateType(rType)
+                ? OUString("data-area-invalidate") : 
OUString("data-area-extend"));
         }
     }
 };
diff --git a/sc/source/ui/undo/undoblk3.cxx b/sc/source/ui/undo/undoblk3.cxx
index da7fa26ff9c1..8e6978659331 100644
--- a/sc/source/ui/undo/undoblk3.cxx
+++ b/sc/source/ui/undo/undoblk3.cxx
@@ -180,7 +180,7 @@ void ScUndoDeleteContents::Undo()
     DoChange( true );
     EndUndo();
 
-    HelperNotifyChanges::NotifyIfChangesListeners(*pDocShell, aRange);
+    HelperNotifyChanges::NotifyIfChangesListeners(*pDocShell, aRange, "undo");
 }
 
 void ScUndoDeleteContents::Redo()
@@ -189,7 +189,7 @@ void ScUndoDeleteContents::Redo()
     DoChange( false );
     EndRedo();
 
-    HelperNotifyChanges::NotifyIfChangesListeners(*pDocShell, aRange);
+    HelperNotifyChanges::NotifyIfChangesListeners(*pDocShell, aRange, "redo");
 }
 
 void ScUndoDeleteContents::Repeat(SfxRepeatTarget& rTarget)
diff --git a/sc/source/ui/undo/undocell.cxx b/sc/source/ui/undo/undocell.cxx
index 5d15ac26a677..c51110402b1e 100644
--- a/sc/source/ui/undo/undocell.cxx
+++ b/sc/source/ui/undo/undocell.cxx
@@ -48,9 +48,10 @@
 namespace HelperNotifyChanges
 {
     static void NotifyIfChangesListeners(const ScDocShell& rDocShell, const 
ScAddress &rPos,
-        const ScUndoEnterData::ValuesType &rOldValues)
+        const ScUndoEnterData::ValuesType &rOldValues, const OUString& rType = 
OUString("cell-change"))
     {
-        if (ScModelObj* pModelObj = getMustPropagateChangesModel(rDocShell))
+        ScModelObj* pModelObj = getModel(rDocShell);
+        if (pModelObj)
         {
             ScRangeList aChangeRanges;
 
@@ -59,7 +60,13 @@ namespace HelperNotifyChanges
                 aChangeRanges.push_back( ScRange(rPos.Col(), rPos.Row(), 
rOldValue.mnTab));
             }
 
-            Notify(*pModelObj, aChangeRanges, "cell-change");
+            if (getMustPropagateChangesModel(pModelObj))
+                Notify(*pModelObj, aChangeRanges, rType);
+            if (pModelObj) // possibly need to invalidate getCellArea results
+            {
+                Notify(*pModelObj, aChangeRanges, 
isDataAreaInvalidateType(rType)
+                    ? OUString("data-area-invalidate") : 
OUString("data-area-extend"));
+            }
         }
     }
 }
@@ -260,7 +267,7 @@ void ScUndoEnterData::Undo()
     DoChange();
     EndUndo();
 
-    HelperNotifyChanges::NotifyIfChangesListeners(*pDocShell, maPos, 
maOldValues);
+    HelperNotifyChanges::NotifyIfChangesListeners(*pDocShell, maPos, 
maOldValues, "undo");
 }
 
 void ScUndoEnterData::Redo()
@@ -289,7 +296,7 @@ void ScUndoEnterData::Redo()
     DoChange();
     EndRedo();
 
-    HelperNotifyChanges::NotifyIfChangesListeners(*pDocShell, maPos, 
maOldValues);
+    HelperNotifyChanges::NotifyIfChangesListeners(*pDocShell, maPos, 
maOldValues, "redo");
 }
 
 void ScUndoEnterData::Repeat(SfxRepeatTarget& rTarget)
diff --git a/sc/source/ui/unoobj/docuno.cxx b/sc/source/ui/unoobj/docuno.cxx
index 0701cae0d9ca..d6d8f1ae0583 100644
--- a/sc/source/ui/unoobj/docuno.cxx
+++ b/sc/source/ui/unoobj/docuno.cxx
@@ -695,9 +695,9 @@ Size ScModelObj::getDataArea(long nPart)
     SCTAB nTab = nPart;
     SCCOL nEndCol = 0;
     SCROW nEndRow = 0;
-    const ScDocument& rDoc = pDocShell->GetDocument();
+    ScDocument& rDoc = pDocShell->GetDocument();
 
-    const ScTable* pTab = rDoc.FetchTable(nTab);
+    ScTable* pTab = rDoc.FetchTable(nTab);
     if (!pTab)
         return aSize;
 
@@ -3173,9 +3173,75 @@ bool ScModelObj::HasChangesListeners() const
     return pDocShell && 
pDocShell->GetDocument().HasAnySheetEventScript(ScSheetEventId::CHANGE);
 }
 
+namespace
+{
+
+void lcl_dataAreaInvalidation(ScDocument& rDocument, ScModelObj* pModel,
+                              const ScRangeList& rRanges,
+                              bool bInvalidateDataArea, bool bExtendDataArea)
+{
+    size_t nRangeCount = rRanges.size();
+
+    for ( size_t nIndex = 0; nIndex < nRangeCount; ++nIndex )
+    {
+        ScRange const & rRange = rRanges[ nIndex ];
+        ScAddress const & rEnd = rRange.aEnd;
+        SCTAB nTab = rEnd.Tab();
+
+        bool bAreaExtended = false;
+
+        if (bExtendDataArea)
+        {
+            const Size aCurrentDataArea = pModel->getDataArea( nTab );
+
+            SCCOL nLastCol = aCurrentDataArea.Width();
+            SCROW nLastRow = aCurrentDataArea.Height();
+
+            bAreaExtended = rEnd.Col() > nLastCol || rEnd.Row() > nLastRow;
+        }
+
+        bool bInvalidate = bAreaExtended || bInvalidateDataArea;
+        if ( bInvalidate )
+        {
+            ScTable* pTab = rDocument.FetchTable( nTab );
+            if ( pTab )
+                pTab->InvalidateCellArea();
+
+            if ( comphelper::LibreOfficeKit::isActive() )
+                SfxLokHelper::notifyPartSizeChangedAllViews( pModel, nTab );
+        }
+    }
+}
+
+};
+
 void ScModelObj::NotifyChanges( const OUString& rOperation, const ScRangeList& 
rRanges,
     const uno::Sequence< beans::PropertyValue >& rProperties )
 {
+    OUString aOperation = rOperation;
+    bool bIsDataAreaInvalidateType = aOperation == "data-area-invalidate";
+    bool bIsDataAreaExtendType = aOperation == "data-area-extend";
+
+    bool bInvalidateDataArea = bIsDataAreaInvalidateType
+        || HelperNotifyChanges::isDataAreaInvalidateType(aOperation);
+    bool bExtendDataArea = bIsDataAreaExtendType || aOperation == 
"cell-change";
+
+    if ( pDocShell )
+    {
+        ScDocument& rDocument = pDocShell->GetDocument();
+        lcl_dataAreaInvalidation(rDocument, this, rRanges, 
bInvalidateDataArea, bExtendDataArea);
+
+        // check if we were called only to update data area
+        if (bIsDataAreaInvalidateType || bIsDataAreaExtendType)
+            return;
+
+        // backward-compatibility Operation conversion
+        // FIXME: make sure it can be passed
+        if (rOperation == "delete-content" || rOperation == "undo"
+            || rOperation == "redo" || rOperation == "paste")
+            aOperation = "cell-change";
+    }
+
     if ( pDocShell && HasChangesListeners() )
     {
         util::ChangesEvent aEvent;
@@ -3200,7 +3266,7 @@ void ScModelObj::NotifyChanges( const OUString& 
rOperation, const ScRangeList& r
             }
 
             util::ElementChange& rChange = pChanges[ static_cast< sal_Int32 >( 
nIndex ) ];
-            rChange.Accessor <<= rOperation;
+            rChange.Accessor <<= aOperation;
             rChange.Element <<= rProperties;
             rChange.ReplacedElement <<= xRangeObj;
         }
@@ -3218,27 +3284,9 @@ void ScModelObj::NotifyChanges( const OUString& 
rOperation, const ScRangeList& r
         }
     }
 
-    if (comphelper::LibreOfficeKit::isActive())
-    {
-        size_t nRangeCount = rRanges.size();
-        for ( size_t nIndex = 0; nIndex < nRangeCount; ++nIndex )
-        {
-            ScRange const & rRange = rRanges[ nIndex ];
-            ScAddress const & rEnd = rRange.aEnd;
-            const Size aCurrentDataArea = getDataArea(rEnd.Tab());
-
-            SCCOL nLastCol = aCurrentDataArea.Width();
-            SCROW nLastRow = aCurrentDataArea.Height();
-
-            // is equal -> probably we just edited last col/row
-            if (rEnd.Col() >= nLastCol || rEnd.Row() >= nLastRow)
-                SfxLokHelper::notifyPartSizeChangedAllViews(this, rEnd.Tab());
-        }
-    }
-
     // handle sheet events
     //! separate method with ScMarkData? Then change HasChangesListeners back.
-    if ( !(rOperation == "cell-change" && pDocShell) )
+    if ( !(aOperation == "cell-change" && pDocShell) )
         return;
 
     ScMarkData aMarkData(pDocShell->GetDocument().GetSheetLimits());
diff --git a/sc/source/ui/view/viewfun2.cxx b/sc/source/ui/view/viewfun2.cxx
index 44c84b8ebcd7..884722204f0a 100644
--- a/sc/source/ui/view/viewfun2.cxx
+++ b/sc/source/ui/view/viewfun2.cxx
@@ -1487,9 +1487,7 @@ void ScViewFunc::FillAuto( FillDir eDir, SCCOL nStartCol, 
SCROW nStartRow,
     if ( bDoAutoSpell )
         CopyAutoSpellData(eDir, nStartCol, nStartRow, nEndCol, nEndRow, 
nCount);
 
-    ScModelObj* pModelObj = 
HelperNotifyChanges::getMustPropagateChangesModel(*pDocSh);
-    if (!pModelObj)
-        return;
+    ScModelObj* pModelObj = HelperNotifyChanges::getModel(*pDocSh);
 
     ScRangeList aChangeRanges;
     ScRange aChangeRange( aRange );
@@ -1511,7 +1509,11 @@ void ScViewFunc::FillAuto( FillDir eDir, SCCOL 
nStartCol, SCROW nStartRow,
             break;
     }
     aChangeRanges.push_back( aChangeRange );
-    HelperNotifyChanges::Notify(*pModelObj, aChangeRanges);
+
+    if (HelperNotifyChanges::getMustPropagateChangesModel(pModelObj))
+        HelperNotifyChanges::Notify(*pModelObj, aChangeRanges);
+    else if (pModelObj)
+        HelperNotifyChanges::Notify(*pModelObj, aChangeRanges, 
"data-area-invalidate");
 }
 
 void ScViewFunc::CopyAutoSpellData( FillDir eDir, SCCOL nStartCol, SCROW 
nStartRow,
diff --git a/sc/source/ui/view/viewfun3.cxx b/sc/source/ui/view/viewfun3.cxx
index 215fde010694..9dd9b810273a 100644
--- a/sc/source/ui/view/viewfun3.cxx
+++ b/sc/source/ui/view/viewfun3.cxx
@@ -1803,9 +1803,7 @@ void ScViewFunc::PostPasteFromClip(const ScRangeList& 
rPasteRanges, const ScMark
 
     SelectionChanged(true);
 
-    ScModelObj* pModelObj = 
HelperNotifyChanges::getMustPropagateChangesModel(*pDocSh);
-    if (!pModelObj)
-        return;
+    ScModelObj* pModelObj = HelperNotifyChanges::getModel(*pDocSh);
 
     ScRangeList aChangeRanges;
     for (size_t i = 0, n = rPasteRanges.size(); i < n; ++i)
@@ -1819,7 +1817,11 @@ void ScViewFunc::PostPasteFromClip(const ScRangeList& 
rPasteRanges, const ScMark
             aChangeRanges.push_back(aChangeRange);
         }
     }
-    HelperNotifyChanges::Notify(*pModelObj, aChangeRanges);
+
+    if (HelperNotifyChanges::getMustPropagateChangesModel(pModelObj))
+        HelperNotifyChanges::Notify(*pModelObj, aChangeRanges, "paste");
+    else if (pModelObj)
+        HelperNotifyChanges::Notify(*pModelObj, aChangeRanges, 
"data-area-invalidate");
 }
 
 //      D R A G   A N D   D R O P
diff --git a/sc/source/ui/view/viewfunc.cxx b/sc/source/ui/view/viewfunc.cxx
index 8b7adf0c0f19..6e15f9b3e0f8 100644
--- a/sc/source/ui/view/viewfunc.cxx
+++ b/sc/source/ui/view/viewfunc.cxx
@@ -337,15 +337,21 @@ static bool lcl_AddFunction( ScAppOptions& rAppOpt, 
sal_uInt16 nOpCode )
 
 namespace HelperNotifyChanges
 {
-    static void NotifyIfChangesListeners(const ScDocShell &rDocShell, 
ScMarkData& rMark, SCCOL nCol, SCROW nRow)
+    static void NotifyIfChangesListeners(const ScDocShell &rDocShell, 
ScMarkData& rMark,
+                                         SCCOL nCol, SCROW nRow, const 
OUString& rType = "cell-change")
     {
-        if (ScModelObj *pModelObj = getMustPropagateChangesModel(rDocShell))
-        {
-            ScRangeList aChangeRanges;
-            for (const auto& rTab : rMark)
-                aChangeRanges.push_back( ScRange( nCol, nRow, rTab ) );
+        ScModelObj* pModelObj = getModel(rDocShell);
+
+        ScRangeList aChangeRanges;
+        for (const auto& rTab : rMark)
+            aChangeRanges.push_back( ScRange( nCol, nRow, rTab ) );
 
-            HelperNotifyChanges::Notify(*pModelObj, aChangeRanges, 
"cell-change");
+        if (getMustPropagateChangesModel(pModelObj))
+            Notify(*pModelObj, aChangeRanges, rType);
+        else
+        {
+            Notify(*pModelObj, aChangeRanges, isDataAreaInvalidateType(rType)
+                    ? OUString("data-area-invalidate") : 
OUString("data-area-extend"));
         }
     }
 }
@@ -648,7 +654,8 @@ void ScViewFunc::EnterData( SCCOL nCol, SCROW nRow, SCTAB 
nTab,
 
     pDocSh->UpdateOle(GetViewData());
 
-    HelperNotifyChanges::NotifyIfChangesListeners(*pDocSh, rMark, nCol, nRow);
+    const OUString aType(rString.isEmpty() ? u"delete-content" : 
u"cell-change");
+    HelperNotifyChanges::NotifyIfChangesListeners(*pDocSh, rMark, nCol, nRow, 
aType);
 
     if ( bRecord )
         rFunc.EndListAction();
@@ -802,7 +809,10 @@ void ScViewFunc::EnterData( SCCOL nCol, SCROW nRow, SCTAB 
nTab,
 
             pDocSh->UpdateOle(GetViewData());
 
-            HelperNotifyChanges::NotifyIfChangesListeners(*pDocSh, rMark, 
nCol, nRow);
+            bool bIsEmpty = rData.GetParagraphCount() == 0
+                || (rData.GetParagraphCount() == 1 && 
rData.GetText(0).isEmpty());
+            const OUString aType(bIsEmpty ? u"delete-content" : 
u"cell-change");
+            HelperNotifyChanges::NotifyIfChangesListeners(*pDocSh, rMark, 
nCol, nRow, aType);
 
             aModificator.SetDocumentModified();
         }
@@ -1337,8 +1347,9 @@ void ScViewFunc::ApplySelectionPattern( const 
ScPatternAttr& rAttr, bool bCursor
         CellContentChanged();
     }
 
-    ScModelObj* pModelObj = 
HelperNotifyChanges::getMustPropagateChangesModel(*pDocSh);
-    if (pModelObj)
+    ScModelObj* pModelObj = HelperNotifyChanges::getModel(*pDocSh);
+
+    if (HelperNotifyChanges::getMustPropagateChangesModel(pModelObj))
     {
         css::uno::Sequence< css::beans::PropertyValue > aProperties;
         sal_Int32 nCount = 0;
@@ -2097,7 +2108,7 @@ void ScViewFunc::DeleteContents( InsertDeleteFlags nFlags 
)
 
     pDocSh->UpdateOle(GetViewData());
 
-    if (ScModelObj *pModelObj = 
HelperNotifyChanges::getMustPropagateChangesModel(*pDocSh))
+    if (ScModelObj* pModelObj = HelperNotifyChanges::getModel(*pDocSh))
     {
         ScRangeList aChangeRanges;
         if ( bSimple )
@@ -2108,7 +2119,11 @@ void ScViewFunc::DeleteContents( InsertDeleteFlags 
nFlags )
         {
             aFuncMark.FillRangeListWithMarks( &aChangeRanges, false );
         }
-        HelperNotifyChanges::Notify(*pModelObj, aChangeRanges);
+
+        if (HelperNotifyChanges::getMustPropagateChangesModel(pModelObj))
+            HelperNotifyChanges::Notify(*pModelObj, aChangeRanges, 
"delete-content");
+        else if (pModelObj)
+            HelperNotifyChanges::Notify(*pModelObj, aChangeRanges, 
"data-area-invalidate");
     }
 
     CellContentChanged();
@@ -2428,8 +2443,9 @@ void ScViewFunc::SetWidthOrHeight(
     if ( !bWidth )
         return;
 
-    ScModelObj* pModelObj = 
HelperNotifyChanges::getMustPropagateChangesModel(*pDocSh);
-    if (!pModelObj)
+    ScModelObj* pModelObj = HelperNotifyChanges::getModel(*pDocSh);
+
+    if (!HelperNotifyChanges::getMustPropagateChangesModel(pModelObj))
         return;
 
     ScRangeList aChangeRanges;
commit d29349a3f8808e650a9432bd087e352845e8b0d3
Author:     Szymon Kłos <szymon.k...@collabora.com>
AuthorDate: Mon Sep 5 15:01:34 2022 +0200
Commit:     Szymon Kłos <szymon.k...@collabora.com>
CommitDate: Mon Nov 21 12:37:03 2022 +0100

    lok: Notify about last used row and column in Calc
    
    We use HelperNotifyChanges::NotifyIfChangesListeners
    notifier so we know which cell was modified and we
    can correctly target only affected users.
    
    Change-Id: Iaeb68e350e85e4ed1492a7d350a790e68f2d63af
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/139473
    Reviewed-by: Dennis Francis <dennis.fran...@collabora.com>
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com>
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/142994
    Tested-by: Jenkins
    Reviewed-by: Szymon Kłos <szymon.k...@collabora.com>

diff --git a/include/sfx2/lokhelper.hxx b/include/sfx2/lokhelper.hxx
index fb2d767b7b66..c3b05b7927e5 100644
--- a/include/sfx2/lokhelper.hxx
+++ b/include/sfx2/lokhelper.hxx
@@ -119,6 +119,8 @@ public:
     static void notifyDocumentSizeChanged(SfxViewShell const* pThisView, const 
OString& rPayload, vcl::ITiledRenderable* pDoc, bool bInvalidateAll = true);
     /// Emits a LOK_CALLBACK_DOCUMENT_SIZE_CHANGED for all views of the same 
document - if @bInvalidateAll - first invalidates all parts
     static void notifyDocumentSizeChangedAllViews(vcl::ITiledRenderable* pDoc, 
bool bInvalidateAll = true);
+    /// Emits a LOK_CALLBACK_DOCUMENT_SIZE_CHANGED for all views of the same 
document with the same part
+    static void notifyPartSizeChangedAllViews(vcl::ITiledRenderable* pDoc, int 
nPart);
     /// Emits a LOK_CALLBACK_INVALIDATE_TILES, but tweaks it according to 
setOptionalFeatures() if needed.
     static void notifyInvalidation(SfxViewShell const* pThisView, 
tools::Rectangle const *);
     /// Notifies all views with the given type and payload.
diff --git a/sc/source/ui/docshell/docsh.cxx b/sc/source/ui/docshell/docsh.cxx
index df55d056f7f2..40a8311b7bf7 100644
--- a/sc/source/ui/docshell/docsh.cxx
+++ b/sc/source/ui/docshell/docsh.cxx
@@ -45,6 +45,7 @@
 #include <sfx2/docfile.hxx>
 #include <sfx2/event.hxx>
 #include <sfx2/docfilt.hxx>
+#include <sfx2/lokhelper.hxx>
 #include <sfx2/objface.hxx>
 #include <sfx2/viewfrm.hxx>
 #include <svl/documentlockfile.hxx>
diff --git a/sc/source/ui/inc/docsh.hxx b/sc/source/ui/inc/docsh.hxx
index 7830984145c9..660f17aee3f4 100644
--- a/sc/source/ui/inc/docsh.hxx
+++ b/sc/source/ui/inc/docsh.hxx
@@ -24,6 +24,7 @@
 #include <sfx2/sfxmodelfactory.hxx>
 #include <sfx2/viewsh.hxx>
 #include <o3tl/deleter.hxx>
+#include <comphelper/lok.hxx>
 #include <comphelper/servicehelper.hxx>
 
 #include <scdllapi.h>
@@ -472,7 +473,8 @@ namespace HelperNotifyChanges
     inline ScModelObj* getMustPropagateChangesModel(const ScDocShell 
&rDocShell)
     {
         ScModelObj* pModelObj = 
comphelper::getFromUnoTunnel<ScModelObj>(rDocShell.GetModel());
-        if (pModelObj && pModelObj->HasChangesListeners())
+        const bool isLOK = comphelper::LibreOfficeKit::isActive(); // for 
LOK_CALLBACK_DOCUMENT_SIZE_CHANGED
+        if (pModelObj && (pModelObj->HasChangesListeners() || isLOK))
             return pModelObj;
         return nullptr;
     }
diff --git a/sc/source/ui/unoobj/docuno.cxx b/sc/source/ui/unoobj/docuno.cxx
index bb8a1ce81e7b..0701cae0d9ca 100644
--- a/sc/source/ui/unoobj/docuno.cxx
+++ b/sc/source/ui/unoobj/docuno.cxx
@@ -3218,6 +3218,24 @@ void ScModelObj::NotifyChanges( const OUString& 
rOperation, const ScRangeList& r
         }
     }
 
+    if (comphelper::LibreOfficeKit::isActive())
+    {
+        size_t nRangeCount = rRanges.size();
+        for ( size_t nIndex = 0; nIndex < nRangeCount; ++nIndex )
+        {
+            ScRange const & rRange = rRanges[ nIndex ];
+            ScAddress const & rEnd = rRange.aEnd;
+            const Size aCurrentDataArea = getDataArea(rEnd.Tab());
+
+            SCCOL nLastCol = aCurrentDataArea.Width();
+            SCROW nLastRow = aCurrentDataArea.Height();
+
+            // is equal -> probably we just edited last col/row
+            if (rEnd.Col() >= nLastCol || rEnd.Row() >= nLastRow)
+                SfxLokHelper::notifyPartSizeChangedAllViews(this, rEnd.Tab());
+        }
+    }
+
     // handle sheet events
     //! separate method with ScMarkData? Then change HasChangesListeners back.
     if ( !(rOperation == "cell-change" && pDocShell) )
diff --git a/sfx2/source/view/lokhelper.cxx b/sfx2/source/view/lokhelper.cxx
index 5f7bef16a843..794dcc00b300 100644
--- a/sfx2/source/view/lokhelper.cxx
+++ b/sfx2/source/view/lokhelper.cxx
@@ -596,6 +596,20 @@ void 
SfxLokHelper::notifyDocumentSizeChangedAllViews(vcl::ITiledRenderable* pDoc
     }
 }
 
+void SfxLokHelper::notifyPartSizeChangedAllViews(vcl::ITiledRenderable* pDoc, 
int nPart)
+{
+    if (DisableCallbacks::disabled())
+        return;
+
+    SfxViewShell* pViewShell = SfxViewShell::GetFirst();
+    while (pViewShell)
+    {
+        if (pViewShell->getPart() == nPart)
+            SfxLokHelper::notifyDocumentSizeChanged(pViewShell, "", pDoc, 
false);
+        pViewShell = SfxViewShell::GetNext(*pViewShell);
+    }
+}
+
 OString SfxLokHelper::makeVisCursorInvalidation(int nViewId, const OString& 
rRectangle,
     bool bMispelledWord, const OString& rHyperlink)
 {

Reply via email to