[Libreoffice-commits] core.git: sc/inc sc/source

Marco Cecchetti marco.cecchetti at collabora.com
Mon Oct 2 16:43:36 UTC 2017


 sc/inc/address.hxx                |    3 
 sc/inc/markarr.hxx                |    3 
 sc/inc/markdata.hxx               |    3 
 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/app/inputhdl.cxx     |    4 +
 sc/source/ui/docshell/docfunc.cxx |   33 ++++++++++
 sc/source/ui/inc/viewdata.hxx     |    5 +
 sc/source/ui/inc/viewfunc.hxx     |    4 +
 sc/source/ui/undo/undoblk.cxx     |   44 +++++++++++++-
 sc/source/ui/view/tabvwsh4.cxx    |   13 ++--
 sc/source/ui/view/viewdata.cxx    |   39 +++++++++++-
 sc/source/ui/view/viewfunc.cxx    |   97 +++++++++++++++++++++++++++++++
 16 files changed, 495 insertions(+), 13 deletions(-)

New commits:
commit 6388a50c1e3ef2e25132f63547bb91d08a0f416c
Author: Marco Cecchetti <marco.cecchetti at collabora.com>
Date:   Wed Apr 19 22:37:13 2017 +0200

    lok: sc: overlays and edit view misplaced by other view actions
    
    The edit view, the cell cursor and the cell selection overlays become
    misplaced when another user inserts, deletes or resizes a row.
    
    The same is true for columns.
    
    The solution takes care of the current tab each view is
    displaying and of undo/redo actions.
    
    Change-Id: I24c94f774f3b18028c9356a904e1b14b07c5c61a
    Reviewed-on: https://gerrit.libreoffice.org/40016
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Marco Cecchetti <mrcekets at gmail.com>

diff --git a/sc/inc/address.hxx b/sc/inc/address.hxx
index 8f6ba1f32296..b5b7f1ad689a 100644
--- a/sc/inc/address.hxx
+++ b/sc/inc/address.hxx
@@ -621,6 +621,9 @@ public:
     SC_DLLPUBLIC SAL_WARN_UNUSED_RESULT bool MoveSticky( SCCOL aDeltaX, SCROW aDeltaY, SCTAB aDeltaZ,
             ScRange& rErrorRange );
 
+    SC_DLLPUBLIC void IncColIfNotLessThan(SCCOL nStartCol, SCCOL nOffset);
+    SC_DLLPUBLIC void IncRowIfNotLessThan(SCROW nStartRow, SCROW 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 548d023db4d4..4b538d9131fe 100644
--- a/sc/inc/markarr.hxx
+++ b/sc/inc/markarr.hxx
@@ -60,6 +60,9 @@ public:
     /// Including current row, may return -1 if bUp and not found
     SCROW   GetNextMarked( SCROW 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 51f63a477d67..26387109b833 100644
--- a/sc/inc/markdata.hxx
+++ b/sc/inc/markdata.hxx
@@ -142,6 +142,9 @@ public:
     void        InsertTab( SCTAB nTab );
     void        DeleteTab( SCTAB nTab );
 
+    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 );
diff --git a/sc/inc/markmulti.hxx b/sc/inc/markmulti.hxx
index 6ada78c243e6..cf68a403fb21 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);
 
     // For faster access from within ScMarkData, instead of creating
     // ScMultiSelIter with ScFlatBoolRowSegments bottleneck.
diff --git a/sc/source/core/data/markarr.cxx b/sc/source/core/data/markarr.cxx
index 248ddd0cb4c0..81c8f94fbac4 100644
--- a/sc/source/core/data/markarr.cxx
+++ b/sc/source/core/data/markarr.cxx
@@ -172,10 +172,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 )
@@ -369,6 +369,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 8c94f196f45d..93a66f8cd68a 100644
--- a/sc/source/core/data/markdata.cxx
+++ b/sc/source/core/data/markdata.cxx
@@ -623,6 +623,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 091c91eae9ff..d8ac507dcaa7 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);
+}
+
 const ScMarkArray& ScMultiSel::GetRowSelArray() const
 {
     return aRowSel;
diff --git a/sc/source/core/tool/address.cxx b/sc/source/core/tool/address.cxx
index 9899044e6ef7..e8c5ed4622ef 100644
--- a/sc/source/core/tool/address.cxx
+++ b/sc/source/core/tool/address.cxx
@@ -2382,6 +2382,46 @@ bool ScRange::MoveSticky( SCCOL dx, SCROW dy, SCTAB dz, ScRange& rErrorRange )
     return b1 && b2;
 }
 
+void ScRange::IncColIfNotLessThan(SCCOL nStartCol, SCCOL 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, SCROW 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( SCCOL nDelta )
 {
     SCCOL nCol = aEnd.Col();
diff --git a/sc/source/ui/app/inputhdl.cxx b/sc/source/ui/app/inputhdl.cxx
index a3df618d8cd6..5a0436f6a745 100644
--- a/sc/source/ui/app/inputhdl.cxx
+++ b/sc/source/ui/app/inputhdl.cxx
@@ -2590,6 +2590,10 @@ static void lcl_SelectionToEnd( EditView* pView )
 
 void ScInputHandler::EnterHandler( ScEnterMode nBlockMode )
 {
+    if (!mbDocumentDisposing && comphelper::LibreOfficeKit::isActive()
+        && pActiveViewSh != SfxViewShell::Current())
+        return;
+
     // Macro calls for validity can cause a lot of problems, so inhibit
     // nested calls of EnterHandler().
     if (bInEnterHandler) return;
diff --git a/sc/source/ui/docshell/docfunc.cxx b/sc/source/ui/docshell/docfunc.cxx
index c9abf98d6147..7a85a367d36d 100644
--- a/sc/source/ui/docshell/docfunc.cxx
+++ b/sc/source/ui/docshell/docfunc.cxx
@@ -2132,6 +2132,24 @@ bool ScDocFunc::InsertCells( const ScRange& rRange, const ScMarkData* pTabMark,
             rDocShell.ErrorMessage(STR_INSERT_FULL);        // column/row full
     }
 
+    // The cursor position needs to be modified earlier than updating
+    // any enabled edit view which is triggered by SetDocumentModified below.
+    if (bSuccess)
+    {
+        bool bInsertCols = ( eCmd == INS_INSCOLS_BEFORE || eCmd == INS_INSCOLS_AFTER);
+        bool bInsertRows = ( eCmd == INS_INSROWS_BEFORE || eCmd == INS_INSROWS_AFTER );
+
+        if (bInsertCols)
+        {
+            pViewSh->OnLOKInsertDeleteColumn(rRange.aStart.Col(), 1);
+        }
+
+        if (bInsertRows)
+        {
+            pViewSh->OnLOKInsertDeleteRow(rRange.aStart.Row(), 1);
+        }
+    }
+
     aModificator.SetDocumentModified();
 
     SfxGetpApp()->Broadcast( SfxHint( SfxHintId::ScAreaLinksChanged ) );
@@ -2658,6 +2676,21 @@ bool ScDocFunc::DeleteCells( const ScRange& rRange, const ScMarkData* pTabMark,
         }
     }
 
+    // The cursor position needs to be modified earlier than updating
+    // any enabled edit view which is triggered by SetDocumentModified below.
+    ScTabViewShell* pViewSh = rDocShell.GetBestViewShell();
+    if (pViewSh)
+    {
+        if (eCmd == DEL_DELCOLS)
+        {
+            pViewSh->OnLOKInsertDeleteColumn(rRange.aStart.Col(), -1);
+        }
+        if (eCmd == DEL_DELROWS)
+        {
+            pViewSh->OnLOKInsertDeleteRow(rRange.aStart.Row(), -1);
+        }
+    }
+
     aModificator.SetDocumentModified();
 
     SfxGetpApp()->Broadcast( SfxHint( SfxHintId::ScAreaLinksChanged ) );
diff --git a/sc/source/ui/inc/viewdata.hxx b/sc/source/ui/inc/viewdata.hxx
index 93df48d61dc1..bd1288d6ba9c 100644
--- a/sc/source/ui/inc/viewdata.hxx
+++ b/sc/source/ui/inc/viewdata.hxx
@@ -298,8 +298,11 @@ public:
     SCROW           GetPosY( ScVSplitPos eWhich ) const     { return pThisTab->nPosY[eWhich]; }
     SCCOL           GetCurX() const                         { return pThisTab->nCurX; }
     SCROW           GetCurY() const                         { return pThisTab->nCurY; }
+    SCCOL           GetCurXForTab( SCTAB nTabIndex ) const;
+    SCROW           GetCurYForTab( SCTAB nTabIndex ) const;
     SCCOL           GetOldCurX() const;
     SCROW           GetOldCurY() const;
+
     ScSplitMode     GetHSplitMode() const                   { return pThisTab->eHSplitMode; }
     ScSplitMode     GetVSplitMode() const                   { return pThisTab->eVSplitMode; }
     long            GetHSplitPos() const                    { return pThisTab->nHSplitPos; }
@@ -317,6 +320,8 @@ public:
     void            SetPosY( ScVSplitPos eWhich, SCROW nNewPosY );
     void            SetCurX( SCCOL nNewCurX )                       { pThisTab->nCurX = nNewCurX; }
     void            SetCurY( SCROW nNewCurY )                       { pThisTab->nCurY = nNewCurY; }
+    void            SetCurXForTab( SCCOL nNewCurX, SCTAB nTabIndex );
+    void            SetCurYForTab( SCCOL nNewCurY, SCTAB nTabIndex );
     void            SetOldCursor( SCCOL nNewX, SCROW nNewY );
     void            ResetOldCursor();
     void            SetHSplitMode( ScSplitMode eMode )              { pThisTab->eHSplitMode = eMode; }
diff --git a/sc/source/ui/inc/viewfunc.hxx b/sc/source/ui/inc/viewfunc.hxx
index 507d6adb44d0..20ed2bccb09e 100644
--- a/sc/source/ui/inc/viewfunc.hxx
+++ b/sc/source/ui/inc/viewfunc.hxx
@@ -322,6 +322,10 @@ public:
                                      std::vector<VclPtr<Edit> >& aEdits,
                                      sal_uInt16 aColLength );
     void            UpdateSelectionArea( const ScMarkData& rSel, ScPatternAttr* pAttr = nullptr );
+
+    void            OnLOKInsertDeleteColumn(SCCOL nStartCol, long nOffset);
+    void            OnLOKInsertDeleteRow(SCROW nStartRow, long nOffset);
+
                                                 // Internal helper functions
 protected:
     static void     UpdateLineAttrs( ::editeng::SvxBorderLine&        rLine,
diff --git a/sc/source/ui/undo/undoblk.cxx b/sc/source/ui/undo/undoblk.cxx
index 5ca8efebab7c..3b7de1a31273 100644
--- a/sc/source/ui/undo/undoblk.cxx
+++ b/sc/source/ui/undo/undoblk.cxx
@@ -156,6 +156,7 @@ void ScUndoInsertCells::DoChange( const bool bUndo )
 
     // refresh of merged cells has to be after inserting/deleting
 
+    ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
     switch (eCmd)
     {
         case INS_INSROWS_BEFORE:
@@ -163,12 +164,19 @@ void ScUndoInsertCells::DoChange( const bool bUndo )
         case INS_CELLSDOWN:
             for( i=0; i<nCount; i++ )
             {
+
                 if (bUndo)
                     rDoc.DeleteRow( aEffRange.aStart.Col(), pTabs[i], aEffRange.aEnd.Col(), pTabs[i]+pScenarios[i],
                     aEffRange.aStart.Row(), static_cast<SCSIZE>(aEffRange.aEnd.Row()-aEffRange.aStart.Row()+1));
                 else
                     rDoc.InsertRow( aEffRange.aStart.Col(), pTabs[i], aEffRange.aEnd.Col(), pTabs[i]+pScenarios[i],
                     aEffRange.aStart.Row(), static_cast<SCSIZE>(aEffRange.aEnd.Row()-aEffRange.aStart.Row()+1));
+
+                if (pViewShell)
+                {
+                    const long nSign = bUndo ? -1 : 1;
+                    pViewShell->OnLOKInsertDeleteRow(aEffRange.aStart.Row(), nSign * (aEffRange.aEnd.Row()-aEffRange.aStart.Row()+1));
+                }
             }
             break;
         case INS_INSCOLS_BEFORE:
@@ -182,6 +190,12 @@ void ScUndoInsertCells::DoChange( const bool bUndo )
                 else
                     rDoc.InsertCol( aEffRange.aStart.Row(), pTabs[i], aEffRange.aEnd.Row(), pTabs[i]+pScenarios[i],
                     aEffRange.aStart.Col(), static_cast<SCSIZE>(aEffRange.aEnd.Col()-aEffRange.aStart.Col()+1));
+
+                if (pViewShell)
+                {
+                    const long nSign = bUndo ? -1 : 1;
+                    pViewShell->OnLOKInsertDeleteColumn(aEffRange.aStart.Col(), nSign * (aEffRange.aEnd.Col()-aEffRange.aStart.Col()+1));
+                }
             }
             break;
         default:
@@ -207,7 +221,7 @@ void ScUndoInsertCells::DoChange( const bool bUndo )
     // Undo for displaced attributes?
 
     PaintPartFlags nPaint = PaintPartFlags::Grid;
-    ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
+
     switch (eCmd)
     {
         case INS_INSROWS_BEFORE:
@@ -380,6 +394,8 @@ void ScUndoDeleteCells::DoChange( const bool bUndo )
     else
         SetChangeTrack();
 
+    ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
+
     switch (eCmd)
     {
         case DEL_DELROWS:
@@ -392,6 +408,12 @@ void ScUndoDeleteCells::DoChange( const bool bUndo )
                 else
                     rDoc.DeleteRow( aEffRange.aStart.Col(), pTabs[i], aEffRange.aEnd.Col(), pTabs[i]+pScenarios[i],
                     aEffRange.aStart.Row(), static_cast<SCSIZE>(aEffRange.aEnd.Row()-aEffRange.aStart.Row()+1));
+
+                if (pViewShell)
+                {
+                    const long nSign = bUndo ? 1 : -1;
+                    pViewShell->OnLOKInsertDeleteRow(aEffRange.aStart.Row(), nSign * (aEffRange.aEnd.Row()-aEffRange.aStart.Row()+1));
+                }
             }
             break;
         case DEL_DELCOLS:
@@ -404,6 +426,12 @@ void ScUndoDeleteCells::DoChange( const bool bUndo )
                 else
                     rDoc.DeleteCol( aEffRange.aStart.Row(), pTabs[i], aEffRange.aEnd.Row(), pTabs[i]+pScenarios[i],
                     aEffRange.aStart.Col(), static_cast<SCSIZE>(aEffRange.aEnd.Col()-aEffRange.aStart.Col()+1));
+
+                if (pViewShell)
+                {
+                    const long nSign = bUndo ? 1 : -1;
+                    pViewShell->OnLOKInsertDeleteColumn(aEffRange.aStart.Col(), nSign * (aEffRange.aEnd.Col()-aEffRange.aStart.Col()+1));
+                }
             }
             break;
         default:
@@ -502,6 +530,20 @@ void ScUndoDeleteCells::DoChange( const bool bUndo )
 
     pDocShell->PostDataChanged();
     //  CellContentChanged comes with the selection
+
+    if (pViewShell)
+    {
+        if (comphelper::LibreOfficeKit::isActive())
+        {
+            if (eCmd == DEL_DELCOLS || eCmd == DEL_CELLSLEFT)
+                ScTabViewShell::notifyAllViewsHeaderInvalidation("column",  pViewShell->GetViewData().GetTabNo());
+
+            if (eCmd == DEL_DELROWS || eCmd == DEL_CELLSUP)
+                ScTabViewShell::notifyAllViewsHeaderInvalidation("row",  pViewShell->GetViewData().GetTabNo());
+        }
+
+    }
+
 }
 
 void ScUndoDeleteCells::Undo()
diff --git a/sc/source/ui/view/tabvwsh4.cxx b/sc/source/ui/view/tabvwsh4.cxx
index 244aec9bfc06..5f15c438b891 100644
--- a/sc/source/ui/view/tabvwsh4.cxx
+++ b/sc/source/ui/view/tabvwsh4.cxx
@@ -1746,6 +1746,14 @@ ScTabViewShell::~ScTabViewShell()
     SfxLokHelper::notifyOtherViews(this, LOK_CALLBACK_GRAPHIC_VIEW_SELECTION, "selection", "EMPTY");
     SfxLokHelper::notifyOtherViews(this, LOK_CALLBACK_CELL_VIEW_CURSOR, "rectangle", "EMPTY");
 
+    // all to NULL, in case the TabView-dtor tries to access them
+    //! (should not really! ??!?!)
+    if (mpInputHandler)
+        mpInputHandler->SetDocumentDisposing(true);
+    // We end edit mode, before destroying the input handler and the edit engine
+    // and before end listening (in order to call ScTabViewShell::KillEditView())
+    mpInputHandler->EnterHandler();
+
     ScDocShell* pDocSh = GetViewData().GetDocShell();
     EndListening(*pDocSh);
     EndListening(*GetViewFrame());
@@ -1756,11 +1764,6 @@ ScTabViewShell::~ScTabViewShell()
     RemoveSubShell();           // all
     SetWindow(nullptr);
 
-    // all to NULL, in case the TabView-dtor tries to access them
-    //! (should not really! ??!?!)
-    if (mpInputHandler)
-        mpInputHandler->SetDocumentDisposing(true);
-
     DELETEZ(pFontworkBarShell);
     DELETEZ(pExtrusionBarShell);
     DELETEZ(pCellShell);
diff --git a/sc/source/ui/view/viewdata.cxx b/sc/source/ui/view/viewdata.cxx
index d978ef826292..92647acb5a5e 100644
--- a/sc/source/ui/view/viewdata.cxx
+++ b/sc/source/ui/view/viewdata.cxx
@@ -971,6 +971,38 @@ void ScViewData::ResetOldCursor()
     pThisTab->mbOldCursorValid = false;
 }
 
+SCCOL ScViewData::GetCurXForTab( SCTAB nTabIndex ) const
+{
+    if (!ValidTab(nTabIndex) || !(nTabIndex < static_cast<SCTAB>(maTabData.size())))
+        return -1;
+
+    return maTabData[nTabIndex]->nCurX;
+}
+
+SCROW ScViewData::GetCurYForTab( SCTAB nTabIndex ) const
+{
+    if (!ValidTab(nTabIndex) || !(nTabIndex < static_cast<SCTAB>(maTabData.size())))
+            return -1;
+
+    return maTabData[nTabIndex]->nCurY;
+}
+
+void ScViewData::SetCurXForTab( SCCOL nNewCurX, SCTAB nTabIndex )
+{
+    if (!ValidTab(nTabIndex) || !(nTabIndex < static_cast<SCTAB>(maTabData.size())))
+            return;
+
+    maTabData[nTabIndex]->nCurX = nNewCurX;
+}
+
+void ScViewData::SetCurYForTab( SCCOL nNewCurY, SCTAB nTabIndex )
+{
+    if (!ValidTab(nTabIndex) || !(nTabIndex < static_cast<SCTAB>(maTabData.size())))
+            return;
+
+    maTabData[nTabIndex]->nCurY = nNewCurY;
+}
+
 tools::Rectangle ScViewData::GetEditArea( ScSplitPos eWhich, SCCOL nPosX, SCROW nPosY,
                                     vcl::Window* pWin, const ScPatternAttr* pPattern,
                                     bool bForceToTop )
@@ -984,10 +1016,6 @@ void ScViewData::SetEditEngine( ScSplitPos eWhich,
                                 ScEditEngineDefaulter* pNewEngine,
                                 vcl::Window* pWin, SCCOL nNewX, SCROW nNewY )
 {
-    if (comphelper::LibreOfficeKit::isActive()
-        && GetViewShell() != SfxViewShell::Current())
-        return;
-
     bool bLayoutRTL = pDoc->IsLayoutRTL( nTabNo );
     ScHSplitPos eHWhich = WhichH(eWhich);
 
@@ -1023,7 +1051,8 @@ void ScViewData::SetEditEngine( ScSplitPos eWhich,
     }
 
     // add windows from other views
-    if (comphelper::LibreOfficeKit::isActive())
+    if (!bWasThere && comphelper::LibreOfficeKit::isActive())
+    //if (comphelper::LibreOfficeKit::isActive())
     {
         ScTabViewShell* pThisViewShell = GetViewShell();
         SCTAB nThisTabNo = GetTabNo();
diff --git a/sc/source/ui/view/viewfunc.cxx b/sc/source/ui/view/viewfunc.cxx
index 3a33dcb514d7..5eae272a9a43 100644
--- a/sc/source/ui/view/viewfunc.cxx
+++ b/sc/source/ui/view/viewfunc.cxx
@@ -1465,6 +1465,103 @@ void ScViewFunc::UpdateStyleSheetInUse( const SfxStyleSheetBase* pStyleSheet )
         pHdl->ForgetLastPattern();
 }
 
+
+void ScViewFunc::OnLOKInsertDeleteColumn(SCCOL nStartCol, long nOffset)
+{
+    if (!comphelper::LibreOfficeKit::isActive() || nOffset == 0)
+        return;
+
+    SCTAB nCurrentTabIndex = GetViewData().GetTabNo();
+    SfxViewShell* pViewShell = SfxViewShell::GetFirst();
+    while (pViewShell)
+    {
+        ScTabViewShell* pTabViewShell = dynamic_cast<ScTabViewShell*>(pViewShell);
+        if (pTabViewShell)
+        {
+            // 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)
+            {
+                if (pTabViewShell->getPart() == nCurrentTabIndex)
+                {
+                    SCCOL nX = pTabViewShell->GetViewData().GetCurX();
+                    if (nX > nStartCol || (nX == nStartCol && nOffset > 0))
+                    {
+                        SCROW nY = pTabViewShell->GetViewData().GetCurY();
+                        pTabViewShell->SetCursor(nX + nOffset, nY);
+                    }
+
+                    ScMarkData aMultiMark( pTabViewShell->GetViewData().GetMarkData() );
+                    aMultiMark.SetMarking( false );
+                    aMultiMark.MarkToMulti();
+                    if (aMultiMark.IsMultiMarked())
+                    {
+                        aMultiMark.ShiftCols(nStartCol, nOffset);
+                        pTabViewShell->SetMarkData(aMultiMark);
+                    }
+                }
+                else
+                {
+                    SCROW nX = pTabViewShell->GetViewData().GetCurXForTab(nCurrentTabIndex);
+                    if (nX > nStartCol || (nX == nStartCol && nOffset > 0))
+                    {
+                        pTabViewShell->GetViewData().SetCurXForTab(nX + nOffset, nCurrentTabIndex);
+                    }
+                }
+            }
+        }
+        pViewShell = SfxViewShell::GetNext(*pViewShell);
+    }
+}
+
+void ScViewFunc::OnLOKInsertDeleteRow(SCROW nStartRow, long nOffset)
+{
+    if (!comphelper::LibreOfficeKit::isActive() || nOffset == 0)
+        return;
+
+    SCTAB nCurrentTabIndex = GetViewData().GetTabNo();
+    SfxViewShell* pViewShell = SfxViewShell::GetFirst();
+    while (pViewShell)
+    {
+        ScTabViewShell* pTabViewShell = dynamic_cast<ScTabViewShell*>(pViewShell);
+        if (pTabViewShell)
+        {
+            // 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)
+            {
+                if (pTabViewShell->getPart() == nCurrentTabIndex)
+                {
+                    SCROW nY = pTabViewShell->GetViewData().GetCurY();
+                    if (nY > nStartRow || (nY == nStartRow && nOffset > 0))
+                    {
+                        SCCOL nX = pTabViewShell->GetViewData().GetCurX();
+                        pTabViewShell->SetCursor(nX, nY + nOffset);
+                    }
+
+                    ScMarkData aMultiMark( pTabViewShell->GetViewData().GetMarkData() );
+                    aMultiMark.SetMarking( false );
+                    aMultiMark.MarkToMulti();
+                    if (aMultiMark.IsMultiMarked())
+                    {
+                        aMultiMark.ShiftRows(nStartRow, nOffset);
+                        pTabViewShell->SetMarkData(aMultiMark);
+                    }
+                }
+                else
+                {
+                    SCROW nY = pTabViewShell->GetViewData().GetCurYForTab(nCurrentTabIndex);
+                    if (nY >= nStartRow || (nY == nStartRow && nOffset > 0))
+                    {
+                        pTabViewShell->GetViewData().SetCurYForTab(nY + nOffset, nCurrentTabIndex);
+                    }
+                }
+            }
+        }
+        pViewShell = SfxViewShell::GetNext(*pViewShell);
+    }
+}
+
 //  insert cells - undo OK
 
 bool ScViewFunc::InsertCells( InsCellCmd eCmd, bool bRecord, bool bPartOfPaste )


More information about the Libreoffice-commits mailing list