desktop/source/lib/init.cxx                  |    1 
 include/LibreOfficeKit/LibreOfficeKitEnums.h |   10 +
 include/sfx2/lokhelper.hxx                   |    3 
 sc/inc/address.hxx                           |    3 
 sc/inc/markarr.hxx                           |    3 
 sc/inc/markdata.hxx                          |    5 
 sc/inc/markmulti.hxx                         |    2 
 sc/source/core/data/markarr.cxx              |  117 ++++++++++++++++++-
 sc/source/core/data/markdata.cxx             |   27 ++++
 sc/source/core/data/markmulti.cxx            |   74 ++++++++++++
 sc/source/core/tool/address.cxx              |   40 ++++++
 sc/source/ui/view/viewfunc.cxx               |  166 +++++++++++++++++++++++++--
 sfx2/source/view/lokhelper.cxx               |   11 +
 13 files changed, 445 insertions(+), 17 deletions(-)

New commits:
commit 8b929a7124ae42d019ea902a4a54f9911f0b2867
Author: Marco Cecchetti <marco.cecche...@collabora.com>
Date:   Wed Apr 19 22:37:13 2017 +0200

    LOK - Calc: header, cursor and selection misplaced by other view actions
    
    The row header, the cell cursor and the currect cell selection become
    misplaced when another user inserts, deletes or resizes a row.
    
    The same is true for columns.
    
    This patch provides to invalidate cached position values in all views
    when one of the listed action is performed in any view.
    
    It also introduce 2 new LOK callbacks for informing the client that
    the row/col header is no more valid and needs to be updated.
    
    Finally, when a new row/col is inserted or removed in one view, the
    cell cursor position and the current selection (if any) in other views
    may need to be shifted lower by one row/col.
    
    Change-Id: I7002a9adf971929b3e38ff58fa0429e792a1e7c4
    Reviewed-on: https://gerrit.libreoffice.org/36716
    Reviewed-by: Jan Holesovsky <ke...@collabora.com>
    Tested-by: Jan Holesovsky <ke...@collabora.com>

diff --git a/desktop/source/lib/init.cxx b/desktop/source/lib/init.cxx
index 9fcea7a1c5a5..fdedff280e4b 100644
--- a/desktop/source/lib/init.cxx
+++ b/desktop/source/lib/init.cxx
@@ -764,6 +764,7 @@ void CallbackFlushHandler::queue(const int type, const 
char* data)
         case LOK_CALLBACK_VIEW_CURSOR_VISIBLE:
         case LOK_CALLBACK_SET_PART:
         case LOK_CALLBACK_TEXT_VIEW_SELECTION:
+        case LOK_CALLBACK_INVALIDATE_HEADER:
         {
             const auto& pos = std::find_if(m_queue.rbegin(), m_queue.rend(),
                     [type] (const queue_type::value_type& elem) { return 
(elem.first == type); });
diff --git a/include/LibreOfficeKit/LibreOfficeKitEnums.h 
b/include/LibreOfficeKit/LibreOfficeKitEnums.h
index 8a59b4cc8ad1..dffc728eb641 100644
--- a/include/LibreOfficeKit/LibreOfficeKitEnums.h
+++ b/include/LibreOfficeKit/LibreOfficeKitEnums.h
@@ -492,7 +492,15 @@ typedef enum
      * - 'action' can be 'Add', 'Remove' or 'Modify' depending on whether
      *    comment has been added, removed or modified.
      */
-    LOK_CALLBACK_COMMENT = 32
+    LOK_CALLBACK_COMMENT = 32,
+
+    /**
+     * The column/row header is no more valid because of a column/row insertion
+     * or a similar event. Clients must query a new column/row header set.
+     *
+     * The payload says if we are invalidating a row or column header.
+     */
+    LOK_CALLBACK_INVALIDATE_HEADER = 33
 }
 LibreOfficeKitCallbackType;
 
diff --git a/include/sfx2/lokhelper.hxx b/include/sfx2/lokhelper.hxx
index a6de41cb880d..4f7b45065fd5 100644
--- a/include/sfx2/lokhelper.hxx
+++ b/include/sfx2/lokhelper.hxx
@@ -42,7 +42,8 @@ public:
     static void notifyOtherView(SfxViewShell* pThisView, SfxViewShell* 
pOtherView, int nType, const OString& rKey, const OString& rPayload);
     /// Emits a LOK_CALLBACK_INVALIDATE_TILES, but tweaks it according to 
setOptionalFeatures() if needed.
     static void notifyInvalidation(SfxViewShell* pThisView, const OString& 
rPayload);
-
+    /// Emits a LOK_CALLBACK_INVALIDATE_HEADER for all views.
+    static void notifyAllViewsHeaderInvalidation(const OString& rPayload);
     /// A special value to signify 'infinity'.
     /// This value is chosen such that sal_Int32 will not overflow when 
manipulated.
     static const long MaxTwips = 1e9;
diff --git a/sc/inc/address.hxx b/sc/inc/address.hxx
index 43cad11ef409..df2a25020f94 100644
--- a/sc/inc/address.hxx
+++ b/sc/inc/address.hxx
@@ -587,6 +587,9 @@ public:
     SC_DLLPUBLIC SAL_WARN_UNUSED_RESULT bool MoveSticky( SCsCOL aDeltaX, 
SCsROW aDeltaY, SCsTAB aDeltaZ,
             ScRange& rErrorRange );
 
+    SC_DLLPUBLIC void IncColIfNotLessThan(SCCOL nStartCol, SCsCOL nOffset);
+    SC_DLLPUBLIC void IncRowIfNotLessThan(SCROW nStartRow, SCsROW nOffset);
+
     SC_DLLPUBLIC void ExtendTo( const ScRange& rRange );
     SC_DLLPUBLIC bool Intersects( const ScRange& rRange ) const;    // do two 
ranges intersect?
 
diff --git a/sc/inc/markarr.hxx b/sc/inc/markarr.hxx
index 0fd826cad395..2f2e27984486 100644
--- a/sc/inc/markarr.hxx
+++ b/sc/inc/markarr.hxx
@@ -59,6 +59,9 @@ public:
     /// Including current row, may return -1 if bUp and not found
     SCsROW  GetNextMarked( SCsROW nRow, bool bUp ) const;
     SCROW   GetMarkEnd( SCROW nRow, bool bUp ) const;
+
+    void    Shift( SCROW nStartRow, long nOffset );
+    void    Intersect( const ScMarkArray& rOther );
 };
 
 class ScMarkArrayIter                   // iterate over selected range
diff --git a/sc/inc/markdata.hxx b/sc/inc/markdata.hxx
index d11173c301fd..1f5474e73e4e 100644
--- a/sc/inc/markdata.hxx
+++ b/sc/inc/markdata.hxx
@@ -142,7 +142,10 @@ public:
     void        InsertTab( SCTAB nTab );
     void        DeleteTab( SCTAB nTab );
 
-    // Generate envelopes if mutimarked and fills the passed ScRange object 
with
+    void        ShiftCols(SCCOL nStartCol, long nColOffset);
+    void        ShiftRows(SCROW nStartRow, long nRowOffset);
+
+    // Generate envelopes if multimarked and fills the passed ScRange object 
with
     // the smallest range that includes the marked area plus its envelopes.
     void        GetSelectionCover( ScRange& rRange );
     // Get top, bottom, left and right envelopes
diff --git a/sc/inc/markmulti.hxx b/sc/inc/markmulti.hxx
index 22f0ee5d1dad..1abe250bee7d 100644
--- a/sc/inc/markmulti.hxx
+++ b/sc/inc/markmulti.hxx
@@ -63,6 +63,8 @@ public:
     void Clear();
     void MarkAllCols( SCROW nStartRow, SCROW nEndRow );
     bool HasAnyMarks() const;
+    void ShiftCols(SCCOL nStartCol, long nColOffset);
+    void ShiftRows(SCROW nStartRow, long nRowOffset);
 };
 
 class ScMultiSelIter
diff --git a/sc/source/core/data/markarr.cxx b/sc/source/core/data/markarr.cxx
index dc65138ef062..62f087cbab78 100644
--- a/sc/source/core/data/markarr.cxx
+++ b/sc/source/core/data/markarr.cxx
@@ -168,10 +168,10 @@ void ScMarkArray::SetMarkArea( SCROW nStartRow, SCROW 
nEndRow, bool bMarked )
                 }
             }
             else
-        {
+            {
                 nInsert = 0;
                 ni = 0;
-        }
+            }
 
             SCSIZE nj = ni;     // stop position of range to replace
             while ( nj < nCount && pData[nj].nRow <= nEndRow )
@@ -367,6 +367,119 @@ SCROW ScMarkArray::GetMarkEnd( SCROW nRow, bool bUp ) 
const
     return nRet;
 }
 
+void ScMarkArray::Shift(SCROW nStartRow, long nOffset)
+{
+    if (!pData || nOffset == 0 || nStartRow > MAXROW)
+        return;
+
+    for (size_t i=0; i < nCount; ++i)
+    {
+        auto& rEntry = pData[i];
+
+        if (rEntry.nRow < nStartRow)
+            continue;
+        rEntry.nRow += nOffset;
+        if (rEntry.nRow < 0)
+        {
+            rEntry.nRow = 0;
+        }
+        else if (rEntry.nRow > MAXROW)
+        {
+            rEntry.nRow = MAXROW;
+        }
+    }
+}
+
+void ScMarkArray::Intersect(const ScMarkArray& rOther)
+{
+    if (!pData || !rOther.pData)
+        return;
+
+    size_t i = 0;
+    size_t j = 0;
+
+    std::vector<ScMarkEntry> aEntryArray;
+    aEntryArray.reserve(std::max(nCount, rOther.nCount));
+
+    while (i < nCount && j < rOther.nCount)
+    {
+        const auto& rEntry = pData[i];
+        const auto& rOtherEntry = rOther.pData[j];
+
+        if (rEntry.bMarked != rOtherEntry.bMarked)
+        {
+            if (!rOtherEntry.bMarked)
+            {
+                aEntryArray.push_back(rOther.pData[j++]);
+                while (i < nCount && pData[i].nRow <= rOtherEntry.nRow)
+                    ++i;
+            }
+            else // rEntry not marked
+            {
+                aEntryArray.push_back(pData[i++]);
+                while (j < rOther.nCount && rOther.pData[j].nRow <= 
rEntry.nRow)
+                    ++j;
+            }
+        }
+        else // rEntry.bMarked == rOtherEntry.bMarked
+        {
+            if (rEntry.bMarked) // both marked
+            {
+                if (rEntry.nRow <= rOtherEntry.nRow)
+                {
+                    aEntryArray.push_back(pData[i++]); // upper row
+                    if (rEntry.nRow == rOtherEntry.nRow)
+                        ++j;
+                }
+                else
+                {
+                    aEntryArray.push_back(rOther.pData[j++]); // upper row
+                }
+            }
+            else // both not marked
+            {
+                if (rEntry.nRow <= rOtherEntry.nRow)
+                {
+                    aEntryArray.push_back(rOther.pData[j++]); // lower row
+                    while (i < nCount && pData[i].nRow <= rOtherEntry.nRow)
+                        ++i;
+                }
+                else
+                {
+                    aEntryArray.push_back(pData[i++]); // lower row
+                    while (j < rOther.nCount && rOther.pData[j].nRow <= 
rEntry.nRow)
+                        ++j;
+                }
+            }
+        }
+    }
+
+    OSL_ENSURE(i == nCount || j == rOther.nCount, "Unexpected case.");
+
+    if (i == nCount)
+    {
+        for (; j < rOther.nCount; ++j)
+        {
+            aEntryArray.push_back(rOther.pData[j]);
+        }
+    }
+    else // j == rOther.nCount
+    {
+        for (; i < nCount; ++i)
+        {
+            aEntryArray.push_back(pData[i]);
+        }
+    }
+
+    size_t nSize = aEntryArray.size();
+    OSL_ENSURE(nSize > 0, "Unexpected case.");
+
+    pData.reset(new ScMarkEntry[nSize]);
+    memcpy(pData.get(), &(aEntryArray[0]), nSize * sizeof(ScMarkEntry));
+    nCount = nLimit = nSize;
+}
+
+
 //  -------------- Iterator ----------------------------------------------
 
 ScMarkArrayIter::ScMarkArrayIter( const ScMarkArray* pNewArray ) :
diff --git a/sc/source/core/data/markdata.cxx b/sc/source/core/data/markdata.cxx
index 9a490134e7d8..d4e5f3152a7f 100644
--- a/sc/source/core/data/markdata.cxx
+++ b/sc/source/core/data/markdata.cxx
@@ -555,6 +555,33 @@ void ScMarkData::DeleteTab( SCTAB nTab )
     maTabMarked.swap(tabMarked);
 }
 
+void ScMarkData::ShiftCols(SCCOL nStartCol, long nColOffset)
+{
+    if (bMarked)
+    {
+        aMarkRange.IncColIfNotLessThan(nStartCol, nColOffset);
+    }
+    else if (bMultiMarked)
+    {
+        aMultiSel.ShiftCols(nStartCol, nColOffset);
+        aMultiRange.IncColIfNotLessThan(nStartCol, nColOffset);
+    }
+}
+
+void ScMarkData::ShiftRows(SCROW nStartRow, long nRowOffset)
+{
+    if (bMarked)
+    {
+        aMarkRange.IncRowIfNotLessThan(nStartRow, nRowOffset);
+    }
+    else if (bMultiMarked)
+    {
+        aMultiSel.ShiftRows(nStartRow, nRowOffset);
+        aMultiRange.IncRowIfNotLessThan(nStartRow, nRowOffset);
+    }
+
+}
+
 static void lcl_AddRanges(ScRange& rRangeDest, const ScRange& rNewRange )
 {
     SCCOL nStartCol = rNewRange.aStart.Col();
diff --git a/sc/source/core/data/markmulti.cxx 
b/sc/source/core/data/markmulti.cxx
index 04619862b689..1421b8eec8b9 100644
--- a/sc/source/core/data/markmulti.cxx
+++ b/sc/source/core/data/markmulti.cxx
@@ -296,6 +296,80 @@ bool ScMultiSel::HasAnyMarks() const
     return false;
 }
 
+void ScMultiSel::ShiftCols(SCCOL nStartCol, long nColOffset)
+{
+    if (nStartCol > MAXCOL)
+        return;
+
+    ScMultiSel aNewMultiSel(*this);
+    Clear();
+
+    if (nColOffset < 0)
+    {
+        // columns that would be moved on the left of nStartCol must be removed
+        const SCCOL nEndPos = nStartCol - nColOffset;
+        for (SCCOL nSearchPos = nStartCol; nSearchPos < nEndPos; ++nSearchPos)
+        {
+            const auto& aColIt = 
aNewMultiSel.aMultiSelContainer.find(nSearchPos);
+            if (aColIt != aNewMultiSel.aMultiSelContainer.end())
+            {
+                aNewMultiSel.aMultiSelContainer.erase(aColIt);
+            }
+        }
+    }
+
+    MapType::iterator aDestEnd = aMultiSelContainer.end();
+    MapType::iterator aDestIter = aDestEnd;
+    for (const auto& aSourcePair : aNewMultiSel.aMultiSelContainer)
+    {
+        SCCOL nCol = aSourcePair.first;
+        if (aSourcePair.first >= nStartCol)
+        {
+            nCol += nColOffset;
+            if (nCol < 0)
+                nCol = 0;
+            else if (nCol > MAXCOL)
+                nCol = MAXCOL;
+        }
+        // correct hint is always aDestEnd as keys come in ascending order
+        // Amortized constant time operation as we always give the correct hint
+        aDestIter = aMultiSelContainer.emplace_hint( aDestEnd, nCol, 
ScMarkArray() );
+        aSourcePair.second.CopyMarksTo(aDestIter->second);
+    }
+    aNewMultiSel.aRowSel.CopyMarksTo(aRowSel);
+
+    if (nColOffset > 0 && nStartCol > 0)
+    {
+        // insert nColOffset new columns, and select their cells if they are 
selected
+        // both in the old column at nStartPos and in the previous column
+        const auto& aPrevPosIt = 
aNewMultiSel.aMultiSelContainer.find(nStartCol - 1);
+        if (aPrevPosIt != aNewMultiSel.aMultiSelContainer.end())
+        {
+            const auto& aStartPosIt = 
aNewMultiSel.aMultiSelContainer.find(nStartCol);
+            if (aStartPosIt != aNewMultiSel.aMultiSelContainer.end())
+            {
+                MapType::iterator aNewColIt = 
aMultiSelContainer.emplace_hint(aDestEnd, nStartCol, ScMarkArray());
+                aStartPosIt->second.CopyMarksTo(aNewColIt->second);
+                aNewColIt->second.Intersect(aPrevPosIt->second);
+                for (long i = 1; i < nColOffset; ++i)
+                {
+                    aDestIter = aMultiSelContainer.emplace_hint(aDestEnd, 
nStartCol + i, ScMarkArray());
+                    aNewColIt->second.CopyMarksTo(aDestIter->second);
+                }
+            }
+        }
+    }
+}
+
+void ScMultiSel::ShiftRows(SCROW nStartRow, long nRowOffset)
+{
+    for (auto& aPair: aMultiSelContainer)
+    {
+        aPair.second.Shift(nStartRow, nRowOffset);
+    }
+    aRowSel.Shift(nStartRow, nRowOffset);
+}
+
 ScMultiSelIter::ScMultiSelIter( const ScMultiSel& rMultiSel, SCCOL nCol ) :
     aRowSegs(),
     nNextSegmentStart(0)
diff --git a/sc/source/core/tool/address.cxx b/sc/source/core/tool/address.cxx
index 0a7a2a9836a2..1dd85f58fd53 100644
--- a/sc/source/core/tool/address.cxx
+++ b/sc/source/core/tool/address.cxx
@@ -2384,6 +2384,46 @@ bool ScRange::MoveSticky( SCsCOL dx, SCsROW dy, SCsTAB 
dz, ScRange& rErrorRange
     return b1 && b2;
 }
 
+void ScRange::IncColIfNotLessThan(SCCOL nStartCol, SCsCOL nOffset)
+{
+    if (aStart.Col() >= nStartCol)
+    {
+        aStart.IncCol(nOffset);
+        if (aStart.Col() < 0)
+            aStart.SetCol(0);
+        else if(aStart.Col() > MAXCOL)
+            aStart.SetCol(MAXCOL);
+    }
+    if (aEnd.Col() >= nStartCol)
+    {
+        aEnd.IncCol(nOffset);
+        if (aEnd.Col() < 0)
+            aEnd.SetCol(0);
+        else if(aEnd.Col() > MAXCOL)
+            aEnd.SetCol(MAXCOL);
+    }
+}
+
+void ScRange::IncRowIfNotLessThan(SCROW nStartRow, SCsROW nOffset)
+{
+    if (aStart.Row() >= nStartRow)
+    {
+        aStart.IncRow(nOffset);
+        if (aStart.Row() < 0)
+            aStart.SetRow(0);
+        else if(aStart.Row() > MAXROW)
+            aStart.SetRow(MAXROW);
+    }
+    if (aEnd.Row() >= nStartRow)
+    {
+        aEnd.IncRow(nOffset);
+        if (aEnd.Row() < 0)
+            aEnd.SetRow(0);
+        else if(aEnd.Row() > MAXROW)
+            aEnd.SetRow(MAXROW);
+    }
+}
+
 void ScRange::IncEndColSticky( SCsCOL nDelta )
 {
     SCCOL nCol = aEnd.Col();
diff --git a/sc/source/ui/view/viewfunc.cxx b/sc/source/ui/view/viewfunc.cxx
index 6ad62019050b..f02ef2f6732d 100644
--- a/sc/source/ui/view/viewfunc.cxx
+++ b/sc/source/ui/view/viewfunc.cxx
@@ -78,6 +78,7 @@
 #include <rowheightcontext.hxx>
 #include <docfuncutil.hxx>
 #include <comphelper/lok.hxx>
+#include <sfx2/lokhelper.hxx>
 
 #include <memory>
 
@@ -1453,6 +1454,7 @@ bool ScViewFunc::InsertCells( InsCellCmd eCmd, bool 
bRecord, bool bPartOfPaste )
     ScRange aRange;
     if (GetViewData().GetSimpleArea(aRange) == SC_MARK_SIMPLE)
     {
+
         ScDocShell* pDocSh = GetViewData().GetDocShell();
         const ScMarkData& rMark = GetViewData().GetMarkData();
         bool bSuccess = pDocSh->GetDocFunc().InsertCells( aRange, &rMark, 
eCmd, bRecord, false, bPartOfPaste );
@@ -1462,11 +1464,66 @@ bool ScViewFunc::InsertCells( InsCellCmd eCmd, bool 
bRecord, bool bPartOfPaste )
             bool bInsertRows = ( eCmd == INS_INSROWS_BEFORE || eCmd == 
INS_INSROWS_AFTER );
             if (comphelper::LibreOfficeKit::isActive())
             {
-                if (bInsertCols)
-                    
GetViewData().GetLOKWidthHelper().invalidateByIndex(aRange.aStart.Col());
+                SfxViewShell* pViewShell = SfxViewShell::GetFirst();
+                while (pViewShell)
+                {
+                    ScTabViewShell* pTabViewShell = 
dynamic_cast<ScTabViewShell*>(pViewShell);
+                    if (pTabViewShell)
+                    {
+                        if (bInsertCols)
+                        {
+                            
pTabViewShell->GetViewData().GetLOKWidthHelper().invalidateByIndex(aRange.aStart.Col());
+
+                            // if we insert a column the cursor position and 
the current selection
+                            // in other views could need to be moved on the 
right by one column.
+                            if (pTabViewShell != this)
+                            {
+                                SCCOL nX = 
pTabViewShell->GetViewData().GetCurX();
+                                if (nX >= aRange.aStart.Col())
+                                {
+                                    SCROW nY = 
pTabViewShell->GetViewData().GetCurY();
+                                    pTabViewShell->SetCursor(nX+1, nY);
+                                }
+
+                                ScMarkData aMultiMark( 
pTabViewShell->GetViewData().GetMarkData() );
+                                aMultiMark.SetMarking( false );
+                                aMultiMark.MarkToMulti();
+                                if (aMultiMark.IsMultiMarked())
+                                {
+                                    aMultiMark.ShiftCols(aRange.aStart.Col(), 
1);
+                                    pTabViewShell->SetMarkData(aMultiMark);
+                                }
+                            }
+                        }
+
+                        if (bInsertRows)
+                        {
+                            
pTabViewShell->GetViewData().GetLOKHeightHelper().invalidateByIndex(aRange.aStart.Row());
 
-                if (bInsertRows)
-                    
GetViewData().GetLOKHeightHelper().invalidateByIndex(aRange.aStart.Row());
+                            // if we insert a row the cursor position and the 
current selection
+                            // in other views could need to be moved down by 
one row.
+                            if (pTabViewShell != this)
+                            {
+                                SCROW nY = 
pTabViewShell->GetViewData().GetCurY();
+                                if (nY >= aRange.aStart.Row())
+                                {
+                                    SCCOL nX = 
pTabViewShell->GetViewData().GetCurX();
+                                    pTabViewShell->SetCursor(nX, nY+1);
+                                }
+
+                                ScMarkData aMultiMark( 
pTabViewShell->GetViewData().GetMarkData() );
+                                aMultiMark.SetMarking( false );
+                                aMultiMark.MarkToMulti();
+                                if (aMultiMark.IsMultiMarked())
+                                {
+                                    aMultiMark.ShiftRows(aRange.aStart.Row(), 
1);
+                                    pTabViewShell->SetMarkData(aMultiMark);
+                                }
+                            }
+                        }
+                    }
+                    pViewShell = SfxViewShell::GetNext(*pViewShell);
+                }
             }
             pDocSh->UpdateOle(&GetViewData());
             CellContentChanged();
@@ -1479,6 +1536,12 @@ bool ScViewFunc::InsertCells( InsCellCmd eCmd, bool 
bRecord, bool bPartOfPaste )
                     OUString("insert-columns");
                 HelperNotifyChanges::NotifyIfChangesListeners(*pDocSh, aRange, 
aOperation);
             }
+
+            if (bInsertCols)
+                SfxLokHelper::notifyAllViewsHeaderInvalidation("column");
+
+            if (bInsertRows)
+                SfxLokHelper::notifyAllViewsHeaderInvalidation("row");
         }
         return bSuccess;
     }
@@ -1527,11 +1590,66 @@ void ScViewFunc::DeleteCells( DelCellCmd eCmd )
 
         if (comphelper::LibreOfficeKit::isActive())
         {
-            if (eCmd == DEL_DELCOLS)
-                
GetViewData().GetLOKWidthHelper().invalidateByIndex(aRange.aStart.Col());
+            SfxViewShell* pViewShell = SfxViewShell::GetFirst();
+            while (pViewShell)
+            {
+                ScTabViewShell* pTabViewShell = 
dynamic_cast<ScTabViewShell*>(pViewShell);
+                if (pTabViewShell)
+                {
+                    if (eCmd == DEL_DELCOLS)
+                    {
+                        
pTabViewShell->GetViewData().GetLOKWidthHelper().invalidateByIndex(aRange.aStart.Col());
+
+                        // if we remove a column the cursor position  and the 
current selection
+                        // in other views could need to be moved on the left 
by one column.
+                        if (pTabViewShell != this)
+                        {
+                            SCCOL nX = pTabViewShell->GetViewData().GetCurX();
+                            if (nX >= aRange.aStart.Col())
+                            {
+                                SCROW nY = 
pTabViewShell->GetViewData().GetCurY();
+                                pTabViewShell->SetCursor(nX-1, nY);
+                            }
 
-            if (eCmd == DEL_DELROWS)
-                
GetViewData().GetLOKHeightHelper().invalidateByIndex(aRange.aStart.Row());
+                            ScMarkData aMultiMark( 
pTabViewShell->GetViewData().GetMarkData() );
+                            aMultiMark.SetMarking( false );
+                            aMultiMark.MarkToMulti();
+                            if (aMultiMark.IsMultiMarked())
+                            {
+                                aMultiMark.ShiftCols(aRange.aStart.Col(), -1);
+                                pTabViewShell->SetMarkData(aMultiMark);
+                            }
+                        }
+                    }
+
+                    if (eCmd == DEL_DELROWS)
+                    {
+                        
pTabViewShell->GetViewData().GetLOKHeightHelper().invalidateByIndex(aRange.aStart.Row());
+
+                        // if we remove a row the cursor position and the 
current selection
+                        // in other views could need to be moved up by one row.
+                        if (pTabViewShell != this)
+                        {
+                            SCROW nY = pTabViewShell->GetViewData().GetCurY();
+                            if (nY >= aRange.aStart.Row())
+                            {
+                                SCCOL nX = 
pTabViewShell->GetViewData().GetCurX();
+                                pTabViewShell->SetCursor(nX, nY-1);
+                            }
+
+                            ScMarkData aMultiMark( 
pTabViewShell->GetViewData().GetMarkData() );
+                            aMultiMark.SetMarking( false );
+                            aMultiMark.MarkToMulti();
+                            if (aMultiMark.IsMultiMarked())
+                            {
+                                aMultiMark.ShiftRows(aRange.aStart.Row(), -1);
+                                pTabViewShell->SetMarkData(aMultiMark);
+                            }
+                        }
+                    }
+                }
+                pViewShell = SfxViewShell::GetNext(*pViewShell);
+            }
         }
 
         pDocSh->UpdateOle(&GetViewData());
@@ -1554,6 +1672,12 @@ void ScViewFunc::DeleteCells( DelCellCmd eCmd )
         else
             nCurY = aRange.aStart.Row();
         SetCursor( nCurX, nCurY );
+
+        if (eCmd == DEL_DELCOLS)
+            SfxLokHelper::notifyAllViewsHeaderInvalidation("column");
+
+        if (eCmd == DEL_DELROWS)
+            SfxLokHelper::notifyAllViewsHeaderInvalidation("row");
     }
     else
     {
@@ -1894,10 +2018,22 @@ void ScViewFunc::SetWidthOrHeight(
     SCCOLROW nStart = rRanges.front().mnStart;
     SCCOLROW nEnd = rRanges.back().mnEnd;
 
-    if (bWidth)
-        GetViewData().GetLOKWidthHelper().invalidateByIndex(nStart);
-    else
-        GetViewData().GetLOKHeightHelper().invalidateByIndex(nStart);
+    if (comphelper::LibreOfficeKit::isActive())
+    {
+        SfxViewShell* pViewShell = SfxViewShell::GetFirst();
+        while (pViewShell)
+        {
+            ScTabViewShell* pTabViewShell = 
dynamic_cast<ScTabViewShell*>(pViewShell);
+            if (pTabViewShell)
+            {
+                if (bWidth)
+                    
pTabViewShell->GetViewData().GetLOKWidthHelper().invalidateByIndex(nStart);
+                else
+                    
pTabViewShell->GetViewData().GetLOKHeightHelper().invalidateByIndex(nStart);
+            }
+            pViewShell = SfxViewShell::GetNext(*pViewShell);
+        }
+    }
 
     bool bFormula = false;
     if ( eMode == SC_SIZE_OPTIMAL )
@@ -2152,6 +2288,12 @@ void ScViewFunc::SetWidthOrHeight(
             HelperNotifyChanges::Notify(*pModelObj, aChangeRanges, 
"column-resize");
         }
     }
+
+    if (comphelper::LibreOfficeKit::isActive())
+    {
+        OString aPayload = bWidth ? "column" : "row";
+        SfxLokHelper::notifyAllViewsHeaderInvalidation(aPayload);
+    }
 }
 
 //  column width/row height (via marked range)
diff --git a/sfx2/source/view/lokhelper.cxx b/sfx2/source/view/lokhelper.cxx
index bfcd000eba01..736952757ecb 100644
--- a/sfx2/source/view/lokhelper.cxx
+++ b/sfx2/source/view/lokhelper.cxx
@@ -142,4 +142,15 @@ void SfxLokHelper::notifyInvalidation(SfxViewShell* 
pThisView, const OString& rP
     pThisView->libreOfficeKitViewCallback(LOK_CALLBACK_INVALIDATE_TILES, 
aPayload.getStr());
 }
 
+void SfxLokHelper::notifyAllViewsHeaderInvalidation(const OString& rPayload)
+{
+    SfxViewShell* pViewShell = SfxViewShell::GetFirst();
+    while (pViewShell)
+    {
+        pViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_INVALIDATE_HEADER, 
rPayload.getStr());
+
+        pViewShell = SfxViewShell::GetNext(*pViewShell);
+    }
+}
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
_______________________________________________
Libreoffice-commits mailing list
libreoffice-comm...@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits

Reply via email to