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@libreoffice.org>
Reviewed-by: Marco Cecchetti <mrcekets@gmail.com>
diff --git a/sc/inc/address.hxx b/sc/inc/address.hxx
index 8f6ba1f..b5b7f1a 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 548d023..4b538d9 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 51f63a4..2638710 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 6ada78c..cf68a40 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 248ddd0..81c8f94 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 8c94f19..93a66f8 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 091c91e..d8ac507 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 9899044..e8c5ed4 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 a3df618..5a0436f 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 c9abf98..7a85a36 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 93df48d..bd1288d 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 507d6ad..20ed2bc 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 5ca8efeba..3b7de1a 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 244aec9..5f15c43 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 d978ef8..92647ac 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 3a33dcb..5eae272 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 )