summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKohei Yoshida <kohei.yoshida@collabora.com>2014-03-28 20:50:29 -0400
committerEike Rathke <erack@redhat.com>2014-03-31 10:30:49 +0000
commit9ae833b62956a6d86772e2d2bf83a7391f322b00 (patch)
tree622fcc06a00e6d78f56dd50f4ac1b82bca22d01d
parent1a883af91567fd86b966d6fb4d7d33c1110067db (diff)
rhbz#1080196: Delete the destination first then paste.
Deleting in-between pasting was causing the block iterators to become invalid when the deletion took place, which resulted in a segfault. Also cleaned up the bits about handling filtered rows. It was using the old row flag which is empty these days (so it never would have worked). Plus we do bail out earlier if the destination contains a filtered row. Change-Id: I78d3ee8bce1647c1c8685f92a3df3c38cc014811 (cherry picked from commit 2ec45841b97a994ef9dca854e142598a063877fd) Reviewed-on: https://gerrit.libreoffice.org/8786 Reviewed-by: Eike Rathke <erack@redhat.com> Tested-by: Eike Rathke <erack@redhat.com>
-rw-r--r--sc/source/core/data/document.cxx101
1 files changed, 32 insertions, 69 deletions
diff --git a/sc/source/core/data/document.cxx b/sc/source/core/data/document.cxx
index e45bd026c7a9..90128ef50620 100644
--- a/sc/source/core/data/document.cxx
+++ b/sc/source/core/data/document.cxx
@@ -2775,21 +2775,6 @@ void ScDocument::CopyFromClip( const ScRange& rDestRange, const ScMarkData& rMar
SetAutoCalc( bOldAutoCalc );
}
-static SCROW lcl_getLastNonFilteredRow(
- const ScBitMaskCompressedArray<SCROW, sal_uInt8>& rFlags, SCROW nBegRow, SCROW nEndRow,
- SCROW nRowCount)
-{
- SCROW nFilteredRow = rFlags.GetFirstForCondition(
- nBegRow, nEndRow, CR_FILTERED, CR_FILTERED);
-
- SCROW nRow = nFilteredRow - 1;
- if (nRow - nBegRow + 1 > nRowCount)
- // make sure the row range stays within the data size.
- nRow = nBegRow + nRowCount - 1;
-
- return nRow;
-}
-
void ScDocument::CopyMultiRangeFromClip(
const ScAddress& rDestPos, const ScMarkData& rMark, sal_uInt16 nInsFlag, ScDocument* pClipDoc,
bool bResetCut, bool bAsLink, bool /*bIncludeFiltered*/, bool bSkipAttrForEmpty)
@@ -2801,83 +2786,62 @@ void ScDocument::CopyMultiRangeFromClip(
// There is nothing in the clip doc to copy.
return;
- bool bOldAutoCalc = GetAutoCalc();
- SetAutoCalc( false ); // avoid multiple recalculations
+ // Right now, we don't allow pasting into filtered rows, so we don't even handle it here.
+ sc::AutoCalcSwitch aACSwitch(*this, false); // turn of auto calc temporarily.
NumFmtMergeHandler aNumFmtMergeHdl(this, pClipDoc);
+ ScRange aDestRange;
+ rMark.GetMarkArea(aDestRange);
+
+ bInsertingFromOtherDoc = true; // kein Broadcast/Listener aufbauen bei Insert
+
SCCOL nCol1 = rDestPos.Col();
SCROW nRow1 = rDestPos.Row();
ScClipParam& rClipParam = pClipDoc->GetClipParam();
+ if (!bSkipAttrForEmpty)
+ {
+ // Do the deletion first.
+ sal_uInt16 nDelFlag = IDF_CONTENTS;
+ SCCOL nColSize = rClipParam.getPasteColSize();
+ SCROW nRowSize = rClipParam.getPasteRowSize();
+
+ DeleteArea(nCol1, nRow1, nCol1+nColSize-1, nRow1+nRowSize-1, rMark, nDelFlag);
+ }
+
sc::CopyFromClipContext aCxt(*this, NULL, pClipDoc, nInsFlag, bAsLink, bSkipAttrForEmpty);
std::pair<SCTAB,SCTAB> aTabRanges = getMarkedTableRange(maTabs, rMark);
aCxt.setTabRange(aTabRanges.first, aTabRanges.second);
- ScRange aDestRange;
- rMark.GetMarkArea(aDestRange);
- SCROW nLastMarkedRow = aDestRange.aEnd.Row();
-
- bInsertingFromOtherDoc = true; // kein Broadcast/Listener aufbauen bei Insert
-
- SCROW nBegRow = nRow1;
- sal_uInt16 nDelFlag = IDF_CONTENTS;
- const ScBitMaskCompressedArray<SCROW, sal_uInt8>& rFlags = GetRowFlagsArray(aCxt.getTabStart());
-
- for ( size_t i = 0, n = rClipParam.maRanges.size(); i < n; ++i )
+ for (size_t i = 0, n = rClipParam.maRanges.size(); i < n; ++i)
{
- ScRange* p = rClipParam.maRanges[ i ];
- // The begin row must not be filtered.
+ ScRange* p = rClipParam.maRanges[i];
SCROW nRowCount = p->aEnd.Row() - p->aStart.Row() + 1;
-
SCsCOL nDx = static_cast<SCsCOL>(nCol1 - p->aStart.Col());
- SCsROW nDy = static_cast<SCsROW>(nBegRow - p->aStart.Row());
+ SCsROW nDy = static_cast<SCsROW>(nRow1 - p->aStart.Row());
SCCOL nCol2 = nCol1 + p->aEnd.Col() - p->aStart.Col();
+ SCROW nEndRow = nRow1 + nRowCount - 1;
- SCROW nEndRow = lcl_getLastNonFilteredRow(rFlags, nBegRow, nLastMarkedRow, nRowCount);
-
- if (!bSkipAttrForEmpty)
- DeleteArea(nCol1, nBegRow, nCol2, nEndRow, rMark, nDelFlag);
+ CopyBlockFromClip(aCxt, nCol1, nRow1, nCol2, nEndRow, rMark, nDx, nDy);
- CopyBlockFromClip(aCxt, nCol1, nBegRow, nCol2, nEndRow, rMark, nDx, nDy);
- nRowCount -= nEndRow - nBegRow + 1;
-
- while (nRowCount > 0)
+ switch (rClipParam.meDirection)
{
- // Get the first non-filtered row.
- SCROW nNonFilteredRow = rFlags.GetFirstForCondition(nEndRow+1, nLastMarkedRow, CR_FILTERED, 0);
- if (nNonFilteredRow > nLastMarkedRow)
- return;
-
- SCROW nRowsSkipped = nNonFilteredRow - nEndRow - 1;
- nDy += nRowsSkipped;
-
- nBegRow = nNonFilteredRow;
- nEndRow = lcl_getLastNonFilteredRow(rFlags, nBegRow, nLastMarkedRow, nRowCount);
-
- if (!bSkipAttrForEmpty)
- DeleteArea(nCol1, nBegRow, nCol2, nEndRow, rMark, nDelFlag);
-
- CopyBlockFromClip(aCxt, nCol1, nBegRow, nCol2, nEndRow, rMark, nDx, nDy);
- nRowCount -= nEndRow - nBegRow + 1;
+ case ScClipParam::Row:
+ // Begin row for the next range being pasted.
+ nRow1 += nRowCount;
+ break;
+ case ScClipParam::Column:
+ nCol1 += p->aEnd.Col() - p->aStart.Col() + 1;
+ break;
+ default:
+ ;
}
-
- if (rClipParam.meDirection == ScClipParam::Row)
- // Begin row for the next range being pasted.
- nBegRow = rFlags.GetFirstForCondition(nEndRow+1, nLastMarkedRow, CR_FILTERED, 0);
- else
- nBegRow = nRow1;
-
- if (rClipParam.meDirection == ScClipParam::Column)
- nCol1 += p->aEnd.Col() - p->aStart.Col() + 1;
}
bInsertingFromOtherDoc = false;
- ScRangeList aRanges;
- aRanges.Append(aDestRange);
-
// Listener aufbauen nachdem alles inserted wurde
StartListeningFromClip(aDestRange.aStart.Col(), aDestRange.aStart.Row(),
aDestRange.aEnd.Col(), aDestRange.aEnd.Row(), rMark, nInsFlag );
@@ -2887,7 +2851,6 @@ void ScDocument::CopyMultiRangeFromClip(
if (bResetCut)
pClipDoc->GetClipParam().mbCutMode = false;
- SetAutoCalc( bOldAutoCalc );
}
void ScDocument::SetClipArea( const ScRange& rArea, bool bCut )