Resolves: tdf#134675 Allow unrestricted pastes of same size in one dimension
So copy-paste of for example one entire column onto more than 23
columns is possible as that does not create multiple repetitions.
Change-Id: I2b035afa1c04522db55569396a36b1bac57c590c
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/116031
Reviewed-by: Eike Rathke <erack@redhat.com>
Tested-by: Jenkins
diff --git a/sc/source/ui/inc/viewdata.hxx b/sc/source/ui/inc/viewdata.hxx
index 957fd47..b63b10f 100644
--- a/sc/source/ui/inc/viewdata.hxx
+++ b/sc/source/ui/inc/viewdata.hxx
@@ -479,7 +479,15 @@ public:
bool IsMultiMarked() const;
/** Disallow cell fill (Paste,Fill,...) on Ctrl+A all
/** Disallow Paste on Ctrl+A all selected or another high
amount of selected cells that is not the same size in
one direction as the clipboard source.
To prevent DOOM.
*/
bool SelectionForbidsPaste( ScDocument* pClipDoc = nullptr );
bool SelectionForbidsPaste( SCCOL nSrcCols, SCROW nSrcRows );
/** Disallow cell fill (Fill,Enter,...) on Ctrl+A all
selected or another high amount of selected cells.
We'd go DOOM.
*/
diff --git a/sc/source/ui/view/cellsh.cxx b/sc/source/ui/view/cellsh.cxx
index 9bf5286..233e59b 100644
--- a/sc/source/ui/view/cellsh.cxx
+++ b/sc/source/ui/view/cellsh.cxx
@@ -225,7 +225,7 @@ void ScCellShell::GetBlockState( SfxItemSet& rSet )
case SID_PASTE_TRANSPOSED:
case SID_PASTE_AS_LINK:
case SID_PASTE_TEXTIMPORT_DIALOG:
bDisable = GetViewData().SelectionForbidsCellFill();
bDisable = GetViewData().SelectionForbidsPaste();
break;
case FID_INS_ROW:
@@ -548,12 +548,11 @@ bool checkDestRanges(ScViewData& rViewData)
return false;
}
if (rViewData.SelectionForbidsCellFill())
return false;
// Multiple destination ranges.
ScDocument& rDoc = rViewData.GetDocument();
// Same as ScViewData::SelectionForbidsPaste() in
// sc/source/ui/view/viewdata.cxx but different return details.
vcl::Window* pWin = rViewData.GetActiveWin();
if (!pWin)
return false;
@@ -571,12 +570,15 @@ bool checkDestRanges(ScViewData& rViewData)
SCROW nRowSize = aSrcRange.aEnd.Row() - aSrcRange.aStart.Row() + 1;
SCCOL nColSize = aSrcRange.aEnd.Col() - aSrcRange.aStart.Col() + 1;
if (rViewData.SelectionForbidsPaste( nColSize, nRowSize))
return false;
ScMarkData aMark = rViewData.GetMarkData();
ScRangeList aRanges;
aMark.MarkToSimple();
aMark.FillRangeListWithMarks(&aRanges, false);
return ScClipUtil::CheckDestRanges(rDoc, nColSize, nRowSize, aMark, aRanges);
return ScClipUtil::CheckDestRanges(rViewData.GetDocument(), nColSize, nRowSize, aMark, aRanges);
}
}
diff --git a/sc/source/ui/view/viewdata.cxx b/sc/source/ui/view/viewdata.cxx
index 233ea92..5c66b48 100644
--- a/sc/source/ui/view/viewdata.cxx
+++ b/sc/source/ui/view/viewdata.cxx
@@ -56,6 +56,8 @@
#include <markdata.hxx>
#include <ViewSettingsSequenceDefines.hxx>
#include <gridwin.hxx>
#include <transobj.hxx>
#include <clipparam.hxx>
#include <comphelper/flagguard.hxx>
#include <comphelper/lok.hxx>
#include <comphelper/processfactory.hxx>
@@ -1256,6 +1258,56 @@ bool ScViewData::IsMultiMarked() const
return (eType & SC_MARK_SIMPLE) != SC_MARK_SIMPLE;
}
bool ScViewData::SelectionForbidsPaste( ScDocument* pClipDoc )
{
if (!pClipDoc)
{
// Same as checkDestRanges() in sc/source/ui/view/cellsh.cxx but
// different return details.
vcl::Window* pWin = GetActiveWin();
if (!pWin)
// No window doesn't mean paste would be forbidden.
return false;
const ScTransferObj* pOwnClip = ScTransferObj::GetOwnClipboard(ScTabViewShell::GetClipData(pWin));
if (!pOwnClip)
// Foreign content does not get repeatedly replicated.
return false;
pClipDoc = pOwnClip->GetDocument();
if (!pClipDoc)
// No clipdoc doesn't mean paste would be forbidden.
return false;
}
const ScRange aSrcRange = pClipDoc->GetClipParam().getWholeRange();
const SCROW nRowSize = aSrcRange.aEnd.Row() - aSrcRange.aStart.Row() + 1;
const SCCOL nColSize = aSrcRange.aEnd.Col() - aSrcRange.aStart.Col() + 1;
return SelectionForbidsPaste( nColSize, nRowSize);
}
bool ScViewData::SelectionForbidsPaste( SCCOL nSrcCols, SCROW nSrcRows )
{
ScRange aSelRange( ScAddress::UNINITIALIZED );
ScMarkType eMarkType = GetSimpleArea( aSelRange);
if (eMarkType == SC_MARK_MULTI)
// Not because of DOOM.
return false;
if (aSelRange.aEnd.Row() - aSelRange.aStart.Row() + 1 == nSrcRows)
// This also covers entire col(s) copied to be pasted on entire cols.
return false;
if (aSelRange.aEnd.Col() - aSelRange.aStart.Col() + 1 == nSrcCols)
// This also covers entire row(s) copied to be pasted on entire rows.
return false;
return SelectionFillDOOM( aSelRange);
}
bool ScViewData::SelectionForbidsCellFill()
{
ScRange aSelRange( ScAddress::UNINITIALIZED );
diff --git a/sc/source/ui/view/viewfun3.cxx b/sc/source/ui/view/viewfun3.cxx
index 476e92c..5f5cb8a 100644
--- a/sc/source/ui/view/viewfun3.cxx
+++ b/sc/source/ui/view/viewfun3.cxx
@@ -885,7 +885,7 @@ bool ScViewFunc::PasteFromClip( InsertDeleteFlags nFlags, ScDocument* pClipDoc,
return false;
}
if (GetViewData().SelectionForbidsCellFill())
if (GetViewData().SelectionForbidsPaste(pClipDoc))
return false;
// undo: save all or no content