summaryrefslogtreecommitdiff
path: root/sc/source/core
diff options
context:
space:
mode:
authorKohei Yoshida <kohei.yoshida@collabora.com>2014-11-10 18:45:21 -0500
committerKohei Yoshida <kohei.yoshida@collabora.com>2014-11-18 08:31:53 -0500
commitff5aad0a26aac46a3a540ac6ed2b7eca4a8cd23d (patch)
tree14072cd770393b9734df69e7ec8152d0c1f7da88 /sc/source/core
parent136eed0f538a7b647323773c47a692d65f5b2ae9 (diff)
Speed up pasting of single row onto multiple destination rows.
This is an extension of the earlier paste optimization of a single cell across multiple destination cells. Change-Id: I3a60300d3d0e11420d997bea8f7f540e948f56cc
Diffstat (limited to 'sc/source/core')
-rw-r--r--sc/source/core/data/clipcontext.cxx42
-rw-r--r--sc/source/core/data/column4.cxx8
-rw-r--r--sc/source/core/data/document10.cxx223
-rw-r--r--sc/source/core/data/table7.cxx10
4 files changed, 160 insertions, 123 deletions
diff --git a/sc/source/core/data/clipcontext.cxx b/sc/source/core/data/clipcontext.cxx
index d60a2e2d73b4..a414cfd4fb6f 100644
--- a/sc/source/core/data/clipcontext.cxx
+++ b/sc/source/core/data/clipcontext.cxx
@@ -36,7 +36,7 @@ CopyFromClipContext::CopyFromClipContext(ScDocument& rDoc,
mnTabStart(-1), mnTabEnd(-1),
mpRefUndoDoc(pRefUndoDoc), mpClipDoc(pClipDoc),
mnInsertFlag(nInsertFlag), mnDeleteFlag(IDF_NONE),
- mpCondFormatList(NULL), mpSinglePattern(NULL), mpSingleNote(NULL),
+ mpCondFormatList(NULL),
mbAsLink(bAsLink), mbSkipAttrForEmptyCells(bSkipAttrForEmptyCells),
mbCloneNotes (mnInsertFlag & (IDF_NOTE|IDF_ADDNOTES)),
mbTableProtected(false)
@@ -106,39 +106,51 @@ InsertDeleteFlags CopyFromClipContext::getDeleteFlag() const
return mnDeleteFlag;
}
-ScCellValue& CopyFromClipContext::getSingleCell()
+void CopyFromClipContext::setSingleCellColumnSize( size_t nSize )
{
- return maSingleCell;
+ maSingleCells.resize(nSize);
+ maSinglePatterns.resize(nSize, NULL);
+ maSingleNotes.resize(nSize, NULL);
}
-void CopyFromClipContext::setCondFormatList( ScConditionalFormatList* pCondFormatList )
+ScCellValue& CopyFromClipContext::getSingleCell( size_t nColOffset )
{
- mpCondFormatList = pCondFormatList;
+ assert(nColOffset < maSingleCells.size());
+ return maSingleCells[nColOffset];
}
-ScConditionalFormatList* CopyFromClipContext::getCondFormatList()
+const ScPatternAttr* CopyFromClipContext::getSingleCellPattern( size_t nColOffset ) const
{
- return mpCondFormatList;
+ assert(nColOffset < maSinglePatterns.size());
+ return maSinglePatterns[nColOffset];
}
-const ScPatternAttr* CopyFromClipContext::getSingleCellPattern() const
+void CopyFromClipContext::setSingleCellPattern( size_t nColOffset, const ScPatternAttr* pAttr )
{
- return mpSinglePattern;
+ assert(nColOffset < maSinglePatterns.size());
+ maSinglePatterns[nColOffset] = pAttr;
}
-void CopyFromClipContext::setSingleCellPattern( const ScPatternAttr* pAttr )
+const ScPostIt* CopyFromClipContext::getSingleCellNote( size_t nColOffset ) const
{
- mpSinglePattern = pAttr;
+ assert(nColOffset < maSingleNotes.size());
+ return maSingleNotes[nColOffset];
}
-const ScPostIt* CopyFromClipContext::getSingleCellNote() const
+void CopyFromClipContext::setSingleCellNote( size_t nColOffset, const ScPostIt* pNote )
{
- return mpSingleNote;
+ assert(nColOffset < maSingleNotes.size());
+ maSingleNotes[nColOffset] = pNote;
}
-void CopyFromClipContext::setSingleCellNote( const ScPostIt* pNote )
+void CopyFromClipContext::setCondFormatList( ScConditionalFormatList* pCondFormatList )
{
- mpSingleNote = pNote;
+ mpCondFormatList = pCondFormatList;
+}
+
+ScConditionalFormatList* CopyFromClipContext::getCondFormatList()
+{
+ return mpCondFormatList;
}
void CopyFromClipContext::setTableProtected( bool b )
diff --git a/sc/source/core/data/column4.cxx b/sc/source/core/data/column4.cxx
index 3e93a2d75214..94634dd12769 100644
--- a/sc/source/core/data/column4.cxx
+++ b/sc/source/core/data/column4.cxx
@@ -138,7 +138,7 @@ void ScColumn::DeleteBeforeCopyFromClip( sc::CopyFromClipContext& rCxt, const Sc
BroadcastCells(aDeletedRows, SC_HINT_DATACHANGED);
}
-void ScColumn::CopyOneCellFromClip( sc::CopyFromClipContext& rCxt, SCROW nRow1, SCROW nRow2 )
+void ScColumn::CopyOneCellFromClip( sc::CopyFromClipContext& rCxt, SCROW nRow1, SCROW nRow2, size_t nColOffset )
{
assert(nRow1 <= nRow2);
@@ -147,7 +147,7 @@ void ScColumn::CopyOneCellFromClip( sc::CopyFromClipContext& rCxt, SCROW nRow1,
if (!pBlockPos)
return;
- ScCellValue& rSrcCell = rCxt.getSingleCell();
+ ScCellValue& rSrcCell = rCxt.getSingleCell(nColOffset);
InsertDeleteFlags nFlags = rCxt.getInsertFlag();
@@ -155,7 +155,7 @@ void ScColumn::CopyOneCellFromClip( sc::CopyFromClipContext& rCxt, SCROW nRow1,
{
if (!rCxt.isSkipAttrForEmptyCells() || rSrcCell.meType != CELLTYPE_NONE)
{
- const ScPatternAttr* pAttr = rCxt.getSingleCellPattern();
+ const ScPatternAttr* pAttr = rCxt.getSingleCellPattern(nColOffset);
pAttrArray->SetPatternArea(nRow1, nRow2, pAttr, true);
}
}
@@ -221,7 +221,7 @@ void ScColumn::CopyOneCellFromClip( sc::CopyFromClipContext& rCxt, SCROW nRow1,
}
}
- const ScPostIt* pNote = rCxt.getSingleCellNote();
+ const ScPostIt* pNote = rCxt.getSingleCellNote(nColOffset);
if (pNote && (nFlags & (IDF_NOTE | IDF_ADDNOTES)) != IDF_NONE)
{
// Duplicate the cell note over the whole pasted range.
diff --git a/sc/source/core/data/document10.cxx b/sc/source/core/data/document10.cxx
index 7fcd4daedfef..714bc238f88b 100644
--- a/sc/source/core/data/document10.cxx
+++ b/sc/source/core/data/document10.cxx
@@ -70,142 +70,159 @@ bool ScDocument::CopyOneCellFromClip(
return false;
ScRange aClipRange = pClipDoc->GetClipParam().getWholeRange();
- if (aClipRange.aStart != aClipRange.aEnd)
- // The source is not really a single cell. Bail out.
+ if (aClipRange.aStart.Row() != aClipRange.aEnd.Row())
+ // The source is not really a single row. Bail out.
return false;
- ScAddress aSrcPos = aClipRange.aStart;
- if (pClipDoc->IsMerged(aSrcPos))
- // We don't handle merged source cell for this.
+ SCCOL nSrcColSize = aClipRange.aEnd.Col() - aClipRange.aStart.Col() + 1;
+ SCCOL nDestColSize = nCol2 - nCol1 + 1;
+ if (nDestColSize < nSrcColSize)
return false;
+ ScAddress aSrcPos = aClipRange.aStart;
+
+ for (SCCOL nCol = aClipRange.aStart.Col(); nCol <= aClipRange.aEnd.Col(); ++nCol)
+ {
+ ScAddress aTestPos = aSrcPos;
+ aTestPos.SetCol(nCol);
+ if (pClipDoc->IsMerged(aTestPos))
+ // We don't handle merged source cell for this.
+ return false;
+ }
+
ScTable* pSrcTab = pClipDoc->FetchTable(aSrcPos.Tab());
if (!pSrcTab)
return false;
- ScCellValue& rSrcCell = rCxt.getSingleCell();
- const ScPatternAttr* pAttr = pClipDoc->GetPattern(aSrcPos);
- rCxt.setSingleCellPattern(pAttr);
- if (rCxt.isAsLink())
- {
- ScSingleRefData aRef;
- aRef.InitAddress(aSrcPos);
- aRef.SetFlag3D(true);
+ rCxt.setSingleCellColumnSize(nSrcColSize);
- ScTokenArray aArr;
- aArr.AddSingleReference(aRef);
- rSrcCell.set(new ScFormulaCell(pClipDoc, aSrcPos, aArr));
- }
- else
+ for (SCCOL nColOffset = 0; nColOffset < nSrcColSize; ++nColOffset, aSrcPos.IncCol())
{
- rSrcCell.set(pClipDoc->GetRefCellValue(aSrcPos));
-
- // Check the paste flag to see whether we want to paste this cell. If the
- // flag says we don't want to paste this cell, we'll return with true.
- InsertDeleteFlags nFlags = rCxt.getInsertFlag();
- bool bNumeric = (nFlags & IDF_VALUE) != IDF_NONE;
- bool bDateTime = (nFlags & IDF_DATETIME) != IDF_NONE;
- bool bString = (nFlags & IDF_STRING) != IDF_NONE;
- bool bBoolean = (nFlags & IDF_SPECIAL_BOOLEAN) != IDF_NONE;
- bool bFormula = (nFlags & IDF_FORMULA) != IDF_NONE;
-
- switch (rSrcCell.meType)
+ const ScPatternAttr* pAttr = pClipDoc->GetPattern(aSrcPos);
+ rCxt.setSingleCellPattern(nColOffset, pAttr);
+
+ if ((rCxt.getInsertFlag() & (IDF_NOTE | IDF_ADDNOTES)) != IDF_NONE)
+ rCxt.setSingleCellNote(nColOffset, pClipDoc->GetNote(aSrcPos));
+
+ ScCellValue& rSrcCell = rCxt.getSingleCell(nColOffset);
+ if (rCxt.isAsLink())
{
- case CELLTYPE_VALUE:
- {
- bool bPaste = rCxt.isDateCell(pSrcTab->aCol[aSrcPos.Col()], aSrcPos.Row()) ? bDateTime : bNumeric;
- if (!bPaste)
- // Don't paste this.
- rSrcCell.clear();
- }
- break;
- case CELLTYPE_STRING:
- case CELLTYPE_EDIT:
- {
- if (!bString)
- // Skip pasting.
- rSrcCell.clear();
- }
- break;
- case CELLTYPE_FORMULA:
+ ScSingleRefData aRef;
+ aRef.InitAddress(aSrcPos);
+ aRef.SetFlag3D(true);
+
+ ScTokenArray aArr;
+ aArr.AddSingleReference(aRef);
+ rSrcCell.set(new ScFormulaCell(pClipDoc, aSrcPos, aArr));
+ }
+ else
+ {
+ rSrcCell.assign(*pClipDoc, aSrcPos);
+
+ // Check the paste flag to see whether we want to paste this cell. If the
+ // flag says we don't want to paste this cell, we'll return with true.
+ InsertDeleteFlags nFlags = rCxt.getInsertFlag();
+ bool bNumeric = (nFlags & IDF_VALUE) != IDF_NONE;
+ bool bDateTime = (nFlags & IDF_DATETIME) != IDF_NONE;
+ bool bString = (nFlags & IDF_STRING) != IDF_NONE;
+ bool bBoolean = (nFlags & IDF_SPECIAL_BOOLEAN) != IDF_NONE;
+ bool bFormula = (nFlags & IDF_FORMULA) != IDF_NONE;
+
+ switch (rSrcCell.meType)
{
- if (bBoolean)
+ case CELLTYPE_VALUE:
{
- // Check if this formula cell is a boolean cell, and if so, go ahead and paste it.
- ScTokenArray* pCode = rSrcCell.mpFormula->GetCode();
- if (pCode && pCode->GetLen() == 1)
- {
- const formula::FormulaToken* p = pCode->First();
- if (p->GetOpCode() == ocTrue || p->GetOpCode() == ocFalse)
- // This is a boolean formula. Good.
- break;
- }
+ bool bPaste = rCxt.isDateCell(pSrcTab->aCol[aSrcPos.Col()], aSrcPos.Row()) ? bDateTime : bNumeric;
+ if (!bPaste)
+ // Don't paste this.
+ rSrcCell.clear();
}
-
- if (bFormula)
- // Good.
- break;
-
- sal_uInt16 nErr = rSrcCell.mpFormula->GetErrCode();
- if (nErr)
+ break;
+ case CELLTYPE_STRING:
+ case CELLTYPE_EDIT:
{
- // error codes are cloned with values
- if (!bNumeric)
- // Error code is treated as numeric value. Don't paste it.
+ if (!bString)
+ // Skip pasting.
rSrcCell.clear();
}
- else if (rSrcCell.mpFormula->IsValue())
+ break;
+ case CELLTYPE_FORMULA:
{
- bool bPaste = rCxt.isDateCell(pSrcTab->aCol[aSrcPos.Col()], aSrcPos.Row()) ? bDateTime : bNumeric;
- if (!bPaste)
+ if (bBoolean)
{
- // Don't paste this.
- rSrcCell.clear();
- break;
+ // Check if this formula cell is a boolean cell, and if so, go ahead and paste it.
+ ScTokenArray* pCode = rSrcCell.mpFormula->GetCode();
+ if (pCode && pCode->GetLen() == 1)
+ {
+ const formula::FormulaToken* p = pCode->First();
+ if (p->GetOpCode() == ocTrue || p->GetOpCode() == ocFalse)
+ // This is a boolean formula. Good.
+ break;
+ }
}
- // Turn this into a numeric cell.
- rSrcCell.set(rSrcCell.mpFormula->GetValue());
- }
- else if (bString)
- {
- svl::SharedString aStr = rSrcCell.mpFormula->GetString();
- if (aStr.isEmpty())
- {
- // do not clone empty string
- rSrcCell.clear();
+ if (bFormula)
+ // Good.
break;
+
+ sal_uInt16 nErr = rSrcCell.mpFormula->GetErrCode();
+ if (nErr)
+ {
+ // error codes are cloned with values
+ if (!bNumeric)
+ // Error code is treated as numeric value. Don't paste it.
+ rSrcCell.clear();
}
+ else if (rSrcCell.mpFormula->IsValue())
+ {
+ bool bPaste = rCxt.isDateCell(pSrcTab->aCol[aSrcPos.Col()], aSrcPos.Row()) ? bDateTime : bNumeric;
+ if (!bPaste)
+ {
+ // Don't paste this.
+ rSrcCell.clear();
+ break;
+ }
- // Turn this into a string or edit cell.
- if (rSrcCell.mpFormula->IsMultilineResult())
+ // Turn this into a numeric cell.
+ rSrcCell.set(rSrcCell.mpFormula->GetValue());
+ }
+ else if (bString)
{
- // TODO : Add shared string support to the edit engine to
- // make this process simpler.
- ScFieldEditEngine& rEngine = GetEditEngine();
- rEngine.SetText(rSrcCell.mpFormula->GetString().getString());
- boost::scoped_ptr<EditTextObject> pObj(rEngine.CreateTextObject());
- pObj->NormalizeString(GetSharedStringPool());
- rSrcCell.set(*pObj);
+ svl::SharedString aStr = rSrcCell.mpFormula->GetString();
+ if (aStr.isEmpty())
+ {
+ // do not clone empty string
+ rSrcCell.clear();
+ break;
+ }
+
+ // Turn this into a string or edit cell.
+ if (rSrcCell.mpFormula->IsMultilineResult())
+ {
+ // TODO : Add shared string support to the edit engine to
+ // make this process simpler.
+ ScFieldEditEngine& rEngine = GetEditEngine();
+ rEngine.SetText(rSrcCell.mpFormula->GetString().getString());
+ boost::scoped_ptr<EditTextObject> pObj(rEngine.CreateTextObject());
+ pObj->NormalizeString(GetSharedStringPool());
+ rSrcCell.set(*pObj);
+ }
+ else
+ rSrcCell.set(rSrcCell.mpFormula->GetString());
}
else
- rSrcCell.set(rSrcCell.mpFormula->GetString());
+ // We don't want to paste this.
+ rSrcCell.clear();
}
- else
- // We don't want to paste this.
+ break;
+ case CELLTYPE_NONE:
+ default:
+ // There is nothing to paste.
rSrcCell.clear();
}
- break;
- case CELLTYPE_NONE:
- default:
- // There is nothing to paste.
- rSrcCell.clear();
}
}
- if ((rCxt.getInsertFlag() & (IDF_NOTE | IDF_ADDNOTES)) != IDF_NONE)
- rCxt.setSingleCellNote(pClipDoc->GetNote(aSrcPos));
-
// All good. Proceed with the pasting.
SCTAB nTabEnd = rCxt.getTabEnd();
diff --git a/sc/source/core/data/table7.cxx b/sc/source/core/data/table7.cxx
index 36a22c643a23..568692179170 100644
--- a/sc/source/core/data/table7.cxx
+++ b/sc/source/core/data/table7.cxx
@@ -55,8 +55,16 @@ void ScTable::DeleteBeforeCopyFromClip( sc::CopyFromClipContext& rCxt, const ScT
void ScTable::CopyOneCellFromClip(
sc::CopyFromClipContext& rCxt, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 )
{
+ ScRange aSrcRange = rCxt.getClipDoc()->GetClipParam().getWholeRange();
+ SCCOL nSrcColSize = aSrcRange.aEnd.Col() - aSrcRange.aStart.Col() + 1;
+
for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol)
- aCol[nCol].CopyOneCellFromClip(rCxt, nRow1, nRow2);
+ {
+ SCCOL nColOffset = nCol - nCol1;
+ nColOffset = nColOffset % nSrcColSize;
+ assert(nColOffset >= 0);
+ aCol[nCol].CopyOneCellFromClip(rCxt, nRow1, nRow2, nColOffset);
+ }
}
void ScTable::SetValues( SCCOL nCol, SCROW nRow, const std::vector<double>& rVals )