summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKohei Yoshida <kohei.yoshida@collabora.com>2014-01-24 11:38:47 -0500
committerKohei Yoshida <kohei.yoshida@collabora.com>2014-01-24 21:27:10 -0500
commit80ea2822c368e6655d216c32904268fc335ef6a4 (patch)
tree34576d69618b93399fe40395d3005dd3735bc855
parentf634bc18a0594cc103c1f8a3e0e34fb6024c666d (diff)
Optimize copy-n-pasting of single cell replicated over a range.
This is a very common operation. Let's speed it up a bit. TODO : Handle cell comments. Change-Id: I5442bf19008475a9427b889c1eb641cacd8ff161
-rw-r--r--sc/Library_sc.mk3
-rw-r--r--sc/inc/attarray.hxx1
-rw-r--r--sc/inc/cellvalue.hxx1
-rw-r--r--sc/inc/clipcontext.hxx20
-rw-r--r--sc/inc/column.hxx10
-rw-r--r--sc/inc/document.hxx4
-rw-r--r--sc/inc/table.hxx4
-rw-r--r--sc/source/core/data/attarray.cxx10
-rw-r--r--sc/source/core/data/cellvalue.cxx24
-rw-r--r--sc/source/core/data/clipcontext.cxx29
-rw-r--r--sc/source/core/data/column2.cxx8
-rw-r--r--sc/source/core/data/column3.cxx12
-rw-r--r--sc/source/core/data/column4.cxx124
-rw-r--r--sc/source/core/data/document.cxx5
-rw-r--r--sc/source/core/data/document10.cxx170
-rw-r--r--sc/source/core/data/table7.cxx27
16 files changed, 430 insertions, 22 deletions
diff --git a/sc/Library_sc.mk b/sc/Library_sc.mk
index d75ce95730b5..1ed89c6d4abb 100644
--- a/sc/Library_sc.mk
+++ b/sc/Library_sc.mk
@@ -105,6 +105,7 @@ $(eval $(call gb_Library_add_exception_objects,sc,\
sc/source/core/data/column \
sc/source/core/data/column2 \
sc/source/core/data/column3 \
+ sc/source/core/data/column4 \
sc/source/core/data/columniterator \
sc/source/core/data/columnset \
sc/source/core/data/columnspanset \
@@ -124,6 +125,7 @@ $(eval $(call gb_Library_add_exception_objects,sc,\
sc/source/core/data/documen8 \
sc/source/core/data/documen9 \
sc/source/core/data/document \
+ sc/source/core/data/document10 \
sc/source/core/data/documentimport \
sc/source/core/data/documentstreamaccess \
sc/source/core/data/dpdimsave \
@@ -180,6 +182,7 @@ $(eval $(call gb_Library_add_exception_objects,sc,\
sc/source/core/data/table4 \
sc/source/core/data/table5 \
sc/source/core/data/table6 \
+ sc/source/core/data/table7 \
sc/source/core/data/tabprotection \
sc/source/core/data/types \
sc/source/core/data/userdat \
diff --git a/sc/inc/attarray.hxx b/sc/inc/attarray.hxx
index 2d52279d13c7..5b9494d9a9eb 100644
--- a/sc/inc/attarray.hxx
+++ b/sc/inc/attarray.hxx
@@ -154,6 +154,7 @@ public:
bool Search( SCROW nRow, SCSIZE& nIndex ) const;
bool HasAttrib( SCROW nRow1, SCROW nRow2, sal_uInt16 nMask ) const;
+ bool IsMerged( SCROW nRow ) const;
bool ExtendMerge( SCCOL nThisCol, SCROW nStartRow, SCROW nEndRow,
SCCOL& rPaintCol, SCROW& rPaintRow,
bool bRefresh );
diff --git a/sc/inc/cellvalue.hxx b/sc/inc/cellvalue.hxx
index c2606b511e72..94af1469e570 100644
--- a/sc/inc/cellvalue.hxx
+++ b/sc/inc/cellvalue.hxx
@@ -50,6 +50,7 @@ struct SC_DLLPUBLIC ScCellValue
void clear();
+ void set( const ScRefCellValue& rCell );
void set( double fValue );
void set( const svl::SharedString& rStr );
void set( const EditTextObject& rEditText );
diff --git a/sc/inc/clipcontext.hxx b/sc/inc/clipcontext.hxx
index dd63ba6c36c6..c693c7f533a7 100644
--- a/sc/inc/clipcontext.hxx
+++ b/sc/inc/clipcontext.hxx
@@ -11,6 +11,7 @@
#define SC_CLIPCONTEXT_HXX
#include "address.hxx"
+#include <cellvalue.hxx>
#include <vector>
#include <boost/unordered_map.hpp>
@@ -18,6 +19,8 @@
#include <boost/scoped_ptr.hpp>
class ScDocument;
+class ScColumn;
+class ScPatternAttr;
namespace sc {
@@ -44,9 +47,11 @@ class CopyFromClipContext : public ClipContextBase
ScDocument* mpRefUndoDoc;
ScDocument* mpClipDoc;
sal_uInt16 mnInsertFlag;
- bool mbAsLink:1;
- bool mbSkipAttrForEmptyCells:1;
- bool mbCloneNotes;
+ ScCellValue maSingleCell;
+ const ScPatternAttr* mpSinglePattern;
+ bool mbAsLink:1;
+ bool mbSkipAttrForEmptyCells:1;
+ bool mbCloneNotes:1;
CopyFromClipContext(); // disabled
@@ -65,9 +70,16 @@ public:
ScDocument* getUndoDoc();
ScDocument* getClipDoc();
sal_uInt16 getInsertFlag() const;
+
+ ScCellValue& getSingleCell();
+
+ const ScPatternAttr* getSingleCellPattern() const;
+ void setSingleCellPattern( const ScPatternAttr* pAttr );
+
bool isAsLink() const;
bool isSkipAttrForEmptyCells() const;
- bool isCloneNotes() const;
+ bool isCloneNotes() const;
+ bool isDateCell( const ScColumn& rCol, SCROW nRow ) const;
};
class CopyToClipContext : public ClipContextBase
diff --git a/sc/inc/column.hxx b/sc/inc/column.hxx
index 3127cf49334c..e08226cd3917 100644
--- a/sc/inc/column.hxx
+++ b/sc/inc/column.hxx
@@ -177,6 +177,7 @@ public:
bool HasAttrib( SCROW nRow1, SCROW nRow2, sal_uInt16 nMask ) const;
bool HasAttribSelection( const ScMarkData& rMark, sal_uInt16 nMask ) const;
+ bool IsMerged( SCROW nRow ) const;
bool ExtendMerge( SCCOL nThisCol, SCROW nStartRow, SCROW nEndRow,
SCCOL& rPaintCol, SCROW& rPaintRow,
bool bRefresh );
@@ -220,6 +221,9 @@ public:
void CopyCellToDocument( SCROW nSrcRow, SCROW nDestRow, ScColumn& rDestCol );
bool InitBlockPosition( sc::ColumnBlockPosition& rBlockPos );
bool InitBlockPosition( sc::ColumnBlockConstPosition& rBlockPos ) const;
+
+ void CopyOneCellFromClip( sc::CopyFromClipContext& rCxt, SCROW nRow1, SCROW nRow2 );
+
void CopyFromClip(
sc::CopyFromClipContext& rCxt, SCROW nRow1, SCROW nRow2, long nDy, ScColumn& rColumn );
@@ -509,8 +513,10 @@ public:
SCROW GetCellNotesMaxRow() const;
SCROW GetCellNotesMinRow() const;
- void CopyCellNotesToDocument(SCROW nRow1, SCROW nRow2, ScColumn& rDestCol, bool bCloneCaption = true,
- SCROW nRowOffsetDest=0) const;
+ void CopyCellNotesToDocument(
+ SCROW nRow1, SCROW nRow2, ScColumn& rDestCol, bool bCloneCaption = true,
+ SCROW nRowOffsetDest = 0) const;
+
void DuplicateNotes(SCROW nStartRow, size_t nDataSize, ScColumn& rDestCol,
sc::ColumnBlockPosition& maDestBlockPos, bool bCloneCaption = true, SCROW nRowOffsetDest=0 ) const;
void UpdateNoteCaptions();
diff --git a/sc/inc/document.hxx b/sc/inc/document.hxx
index 2f1ecdc160b0..6a980ab298f2 100644
--- a/sc/inc/document.hxx
+++ b/sc/inc/document.hxx
@@ -917,6 +917,8 @@ public:
SC_DLLPUBLIC void SetDrawPageSize(SCTAB nTab);
+ bool IsMerged( const ScAddress& rPos ) const;
+
bool ExtendMergeSel( SCCOL nStartCol, SCROW nStartRow,
SCCOL& rEndCol, SCROW& rEndRow, const ScMarkData& rMark,
bool bRefresh = false );
@@ -1192,6 +1194,8 @@ public:
bool InitColumnBlockPosition( sc::ColumnBlockPosition& rBlokPos, SCTAB nTab, SCCOL nCol );
+ bool CopyOneCellFromClip(
+ sc::CopyFromClipContext& rCxt, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 );
void CopyBlockFromClip(
sc::CopyFromClipContext& rCxt, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
const ScMarkData& rMark, SCsCOL nDx, SCsROW nDy );
diff --git a/sc/inc/table.hxx b/sc/inc/table.hxx
index f7d338953e6a..00bddb975f0d 100644
--- a/sc/inc/table.hxx
+++ b/sc/inc/table.hxx
@@ -409,6 +409,9 @@ public:
bool InitColumnBlockPosition( sc::ColumnBlockPosition& rBlockPos, SCCOL nCol );
+ void CopyOneCellFromClip(
+ sc::CopyFromClipContext& rCxt, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 );
+
void CopyFromClip(
sc::CopyFromClipContext& rCxt, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
SCsCOL nDx, SCsROW nDy, ScTable* pTable );
@@ -560,6 +563,7 @@ public:
bool HasAttrib( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, sal_uInt16 nMask ) const;
bool HasAttribSelection( const ScMarkData& rMark, sal_uInt16 nMask ) const;
+ bool IsMerged( SCCOL nCol, SCROW nRow ) const;
bool ExtendMerge( SCCOL nStartCol, SCROW nStartRow,
SCCOL& rEndCol, SCROW& rEndRow,
bool bRefresh );
diff --git a/sc/source/core/data/attarray.cxx b/sc/source/core/data/attarray.cxx
index ec2512f96ba1..bcfdb477f059 100644
--- a/sc/source/core/data/attarray.cxx
+++ b/sc/source/core/data/attarray.cxx
@@ -1374,6 +1374,16 @@ bool ScAttrArray::HasAttrib( SCROW nRow1, SCROW nRow2, sal_uInt16 nMask ) const
return bFound;
}
+bool ScAttrArray::IsMerged( SCROW nRow ) const
+{
+ SCSIZE nIndex;
+ Search(nRow, nIndex);
+ const ScMergeAttr& rItem =
+ static_cast<const ScMergeAttr&>(pData[nIndex].pPattern->GetItem(ATTR_MERGE));
+
+ return rItem.IsMerged();
+}
+
// Area around any given summaries expand and adapt any MergeFlag (bRefresh)
bool ScAttrArray::ExtendMerge( SCCOL nThisCol, SCROW nStartRow, SCROW nEndRow,
SCCOL& rPaintCol, SCROW& rPaintRow,
diff --git a/sc/source/core/data/cellvalue.cxx b/sc/source/core/data/cellvalue.cxx
index 12ef30272e62..d963fa31bc5a 100644
--- a/sc/source/core/data/cellvalue.cxx
+++ b/sc/source/core/data/cellvalue.cxx
@@ -227,6 +227,30 @@ void ScCellValue::clear()
mfValue = 0.0;
}
+void ScCellValue::set( const ScRefCellValue& rCell )
+{
+ clear();
+
+ meType = rCell.meType;
+ switch (meType)
+ {
+ case CELLTYPE_VALUE:
+ mfValue = rCell.mfValue;
+ break;
+ case CELLTYPE_STRING:
+ mpString = new svl::SharedString(*rCell.mpString);
+ break;
+ case CELLTYPE_EDIT:
+ mpEditText = rCell.mpEditText->Clone();
+ break;
+ case CELLTYPE_FORMULA:
+ mpFormula = rCell.mpFormula->Clone();
+ break;
+ default:
+ ;
+ }
+}
+
void ScCellValue::set( double fValue )
{
clear();
diff --git a/sc/source/core/data/clipcontext.cxx b/sc/source/core/data/clipcontext.cxx
index 8013684867ee..764d66f6ccb0 100644
--- a/sc/source/core/data/clipcontext.cxx
+++ b/sc/source/core/data/clipcontext.cxx
@@ -10,6 +10,10 @@
#include "clipcontext.hxx"
#include "document.hxx"
#include "mtvelements.hxx"
+#include <column.hxx>
+#include <scitems.hxx>
+
+#include <svl/intitem.hxx>
namespace sc {
@@ -29,8 +33,9 @@ CopyFromClipContext::CopyFromClipContext(ScDocument& rDoc,
ClipContextBase(rDoc),
mnTabStart(-1), mnTabEnd(-1),
mpRefUndoDoc(pRefUndoDoc), mpClipDoc(pClipDoc), mnInsertFlag(nInsertFlag),
+ mpSinglePattern(NULL),
mbAsLink(bAsLink), mbSkipAttrForEmptyCells(bSkipAttrForEmptyCells),
- mbCloneNotes (mnInsertFlag & (IDF_NOTE|IDF_ADDNOTES) )
+ mbCloneNotes (mnInsertFlag & (IDF_NOTE|IDF_ADDNOTES))
{
}
@@ -69,6 +74,21 @@ sal_uInt16 CopyFromClipContext::getInsertFlag() const
return mnInsertFlag;
}
+ScCellValue& CopyFromClipContext::getSingleCell()
+{
+ return maSingleCell;
+}
+
+const ScPatternAttr* CopyFromClipContext::getSingleCellPattern() const
+{
+ return mpSinglePattern;
+}
+
+void CopyFromClipContext::setSingleCellPattern( const ScPatternAttr* pAttr )
+{
+ mpSinglePattern = pAttr;
+}
+
bool CopyFromClipContext::isAsLink() const
{
return mbAsLink;
@@ -84,6 +104,13 @@ bool CopyFromClipContext::isCloneNotes() const
return mbCloneNotes;
}
+bool CopyFromClipContext::isDateCell( const ScColumn& rCol, SCROW nRow ) const
+{
+ sal_uLong nNumIndex = static_cast<const SfxUInt32Item*>(rCol.GetAttr(nRow, ATTR_VALUE_FORMAT))->GetValue();
+ short nType = mpClipDoc->GetFormatTable()->GetType(nNumIndex);
+ return (nType == NUMBERFORMAT_DATE) || (nType == NUMBERFORMAT_TIME) || (nType == NUMBERFORMAT_DATETIME);
+}
+
CopyToClipContext::CopyToClipContext(
ScDocument& rDoc, bool bKeepScenarioFlags, bool bCloneNotes) :
ClipContextBase(rDoc), mbKeepScenarioFlags(bKeepScenarioFlags), mbCloneNotes(bCloneNotes) {}
diff --git a/sc/source/core/data/column2.cxx b/sc/source/core/data/column2.cxx
index b891276aef32..22fea460b4a1 100644
--- a/sc/source/core/data/column2.cxx
+++ b/sc/source/core/data/column2.cxx
@@ -1749,7 +1749,8 @@ void ScColumn::CopyCellTextAttrsToDocument(SCROW nRow1, SCROW nRow2, ScColumn& r
}
}
-void ScColumn::CopyCellNotesToDocument(SCROW nRow1, SCROW nRow2, ScColumn& rDestCol, bool bCloneCaption, SCROW nRowOffsetDest) const
+void ScColumn::CopyCellNotesToDocument(
+ SCROW nRow1, SCROW nRow2, ScColumn& rDestCol, bool bCloneCaption, SCROW nRowOffsetDest ) const
{
SCCOL nDestCol = rDestCol.GetCol();
SCTAB nDestTab = rDestCol.GetTab();
@@ -1825,7 +1826,6 @@ void ScColumn::CopyCellNotesToDocument(SCROW nRow1, SCROW nRow2, ScColumn& rDest
vCloned.push_back(pClonedNote);
}
rDestCol.maCellNotes.set(rDestCol.maCellNotes.begin(), nBlockStart + nOffsetInBlock + nRowOffsetDest, vCloned.begin(), vCloned.end());
-
}
}
}
@@ -1833,8 +1833,8 @@ void ScColumn::CopyCellNotesToDocument(SCROW nRow1, SCROW nRow2, ScColumn& rDest
void ScColumn::DuplicateNotes(SCROW nStartRow, size_t nDataSize, ScColumn& rDestCol, sc::ColumnBlockPosition& maDestBlockPos,
bool bCloneCaption, SCROW nRowOffsetDest ) const
{
- CopyCellNotesToDocument(nStartRow, nStartRow + nDataSize -1, rDestCol, bCloneCaption, nRowOffsetDest);
- maDestBlockPos.miCellNotePos = rDestCol.maCellNotes.begin();
+ CopyCellNotesToDocument(nStartRow, nStartRow + nDataSize -1, rDestCol, bCloneCaption, nRowOffsetDest);
+ maDestBlockPos.miCellNotePos = rDestCol.maCellNotes.begin();
}
void ScColumn::SwapCellTextAttrs( SCROW nRow1, SCROW nRow2 )
diff --git a/sc/source/core/data/column3.cxx b/sc/source/core/data/column3.cxx
index 798d5444a570..2301b0f8590f 100644
--- a/sc/source/core/data/column3.cxx
+++ b/sc/source/core/data/column3.cxx
@@ -680,14 +680,6 @@ class CopyCellsFromClipHandler
sc::ColumnBlockPosition maDestBlockPos;
sc::ColumnBlockPosition* mpDestBlockPos; // to save it for next iteration.
- bool isDateCell(SCROW nSrcRow) const
- {
- ScDocument* pSrcDoc = mrCxt.getClipDoc(); // clip document is the source.
- sal_uLong nNumIndex = static_cast<const SfxUInt32Item*>(mrSrcCol.GetAttr(nSrcRow, ATTR_VALUE_FORMAT))->GetValue();
- short nType = pSrcDoc->GetFormatTable()->GetType(nNumIndex);
- return (nType == NUMBERFORMAT_DATE) || (nType == NUMBERFORMAT_TIME) || (nType == NUMBERFORMAT_DATETIME);
- }
-
void insertRefCell(SCROW nSrcRow, SCROW nDestRow)
{
ScAddress aSrcPos(mnSrcCol, nSrcRow, mnSrcTab);
@@ -770,7 +762,7 @@ public:
std::advance(itEnd, nDataSize);
for (SCROW nSrcRow = nSrcRow1; it != itEnd; ++it, ++nSrcRow)
{
- bool bCopy = isDateCell(nSrcRow) ? bDateTime : bNumeric;
+ bool bCopy = mrCxt.isDateCell(mrSrcCol, nSrcRow) ? bDateTime : bNumeric;
if (!bCopy)
continue;
@@ -877,7 +869,7 @@ public:
}
else if (rSrcCell.IsValue())
{
- bool bCopy = isDateCell(nSrcRow) ? bDateTime : bNumeric;
+ bool bCopy = mrCxt.isDateCell(mrSrcCol, nSrcRow) ? bDateTime : bNumeric;
if (!bCopy)
continue;
diff --git a/sc/source/core/data/column4.cxx b/sc/source/core/data/column4.cxx
new file mode 100644
index 000000000000..48c38267f0d0
--- /dev/null
+++ b/sc/source/core/data/column4.cxx
@@ -0,0 +1,124 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <column.hxx>
+#include <clipcontext.hxx>
+#include <cellvalue.hxx>
+#include <attarray.hxx>
+#include <document.hxx>
+
+#include <svl/sharedstring.hxx>
+
+#include <vector>
+#include <cassert>
+
+bool ScColumn::IsMerged( SCROW nRow ) const
+{
+ return pAttrArray->IsMerged(nRow);
+}
+
+void ScColumn::CopyOneCellFromClip( sc::CopyFromClipContext& rCxt, SCROW nRow1, SCROW nRow2 )
+{
+ assert(nRow1 <= nRow2);
+
+ size_t nDestSize = nRow2 - nRow1 + 1;
+ sc::ColumnBlockPosition* pBlockPos = rCxt.getBlockPosition(nTab, nCol);
+ if (!pBlockPos)
+ return;
+
+ ScCellValue& rSrcCell = rCxt.getSingleCell();
+
+ sal_uInt16 nFlags = rCxt.getInsertFlag();
+
+ if ((nFlags & IDF_ATTRIB) != 0)
+ {
+ if (!rCxt.isSkipAttrForEmptyCells() || rSrcCell.meType != CELLTYPE_NONE)
+ {
+ const ScPatternAttr* pAttr = rCxt.getSingleCellPattern();
+ pAttrArray->SetPatternArea(nRow1, nRow2, pAttr, true);
+ }
+ }
+
+ if ((nFlags & IDF_CONTENTS) != 0)
+ {
+ switch (rSrcCell.meType)
+ {
+ case CELLTYPE_VALUE:
+ {
+ std::vector<double> aVals(nDestSize, rSrcCell.mfValue);
+ pBlockPos->miCellPos =
+ maCells.set(pBlockPos->miCellPos, nRow1, aVals.begin(), aVals.end());
+ CellStorageModified();
+ }
+ break;
+ case CELLTYPE_STRING:
+ {
+ std::vector<svl::SharedString> aStrs(nDestSize, *rSrcCell.mpString);
+ maCells.set(pBlockPos->miCellPos, nRow1, aStrs.begin(), aStrs.end());
+ CellStorageModified();
+ }
+ break;
+ case CELLTYPE_EDIT:
+ {
+ std::vector<EditTextObject*> aStrs;
+ aStrs.reserve(nDestSize);
+ for (size_t i = 0; i < nDestSize; ++i)
+ aStrs.push_back(rSrcCell.mpEditText->Clone());
+
+ pBlockPos->miCellPos =
+ maCells.set(pBlockPos->miCellPos, nRow1, aStrs.begin(), aStrs.end());
+ CellStorageModified();
+ }
+ break;
+ case CELLTYPE_FORMULA:
+ {
+ std::vector<ScFormulaCell*> aFormulas;
+ ScAddress aPos(nCol, nRow1, nTab);
+ aFormulas.reserve(nDestSize);
+ ScFormulaCellGroupRef xGroup(new ScFormulaCellGroup);
+ xGroup->setCode(*rSrcCell.mpFormula->GetCode());
+ xGroup->compileCode(*pDocument, aPos, pDocument->GetGrammar());
+ for (size_t i = 0; i < nDestSize; ++i)
+ {
+ ScFormulaCell* pCell = new ScFormulaCell(pDocument, aPos, xGroup);
+ if (i == 0)
+ {
+ xGroup->mpTopCell = pCell;
+ xGroup->mnLength = nDestSize;
+ }
+ aFormulas.push_back(pCell);
+ aPos.IncRow();
+ }
+
+ pBlockPos->miCellPos =
+ maCells.set(pBlockPos->miCellPos, nRow1, aFormulas.begin(), aFormulas.end());
+
+ // Join the top and bottom of the pasted formula cells as needed.
+ sc::CellStoreType::position_type aPosObj =
+ maCells.position(pBlockPos->miCellPos, nRow1);
+
+ assert(aPosObj.first->type == sc::element_type_formula);
+ ScFormulaCell* pCell = sc::formula_block::at(*aPosObj.first->data, aPosObj.second);
+ JoinNewFormulaCell(aPosObj, *pCell);
+
+ aPosObj = maCells.position(aPosObj.first, nRow2);
+ assert(aPosObj.first->type == sc::element_type_formula);
+ pCell = sc::formula_block::at(*aPosObj.first->data, aPosObj.second);
+ JoinNewFormulaCell(aPosObj, *pCell);
+
+ CellStorageModified();
+ }
+ break;
+ default:
+ ;
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/core/data/document.cxx b/sc/source/core/data/document.cxx
index 27b419c20781..1f00bd7ccb13 100644
--- a/sc/source/core/data/document.cxx
+++ b/sc/source/core/data/document.cxx
@@ -95,6 +95,7 @@
#include "scopetools.hxx"
#include "refupdatecontext.hxx"
#include "formulagroup.hxx"
+#include <tokenarray.hxx>
#include "formula/vectortoken.hxx"
@@ -2690,6 +2691,9 @@ void ScDocument::CopyFromClip( const ScRange& rDestRange, const ScMarkData& rMar
DeleteArea(nCol1, nRow1, nCol2, nRow2, rMark, nDelFlag);
+ if (CopyOneCellFromClip(aCxt, nCol1, nRow1, nCol2, nRow2))
+ continue;
+
SCCOL nC1 = nCol1;
SCROW nR1 = nRow1;
SCCOL nC2 = nC1 + nXw;
@@ -5290,7 +5294,6 @@ bool ScDocument::ExtendOverlapped( SCCOL& rStartCol, SCROW& rStartRow,
return bFound;
}
-
bool ScDocument::ExtendMergeSel( SCCOL nStartCol, SCROW nStartRow,
SCCOL& rEndCol, SCROW& rEndRow,
const ScMarkData& rMark, bool bRefresh )
diff --git a/sc/source/core/data/document10.cxx b/sc/source/core/data/document10.cxx
new file mode 100644
index 000000000000..1178ce703155
--- /dev/null
+++ b/sc/source/core/data/document10.cxx
@@ -0,0 +1,170 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <document.hxx>
+#include <clipcontext.hxx>
+#include <formulacell.hxx>
+#include <clipparam.hxx>
+#include <table.hxx>
+#include <tokenarray.hxx>
+#include <editutil.hxx>
+
+// Add totally brand-new methods to this source file.
+
+bool ScDocument::IsMerged( const ScAddress& rPos ) const
+{
+ const ScTable* pTab = FetchTable(rPos.Tab());
+ if (!pTab)
+ return false;
+
+ return pTab->IsMerged(rPos.Col(), rPos.Row());
+}
+
+bool ScDocument::CopyOneCellFromClip(
+ sc::CopyFromClipContext& rCxt, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 )
+{
+ ScDocument* pClipDoc = rCxt.getClipDoc();
+ ScRange aClipRange = pClipDoc->GetClipParam().getWholeRange();
+ if (aClipRange.aStart != aClipRange.aEnd)
+ // The source is not really a single cell. Bail out.
+ return false;
+
+ ScAddress aSrcPos = aClipRange.aStart;
+ if (pClipDoc->IsMerged(aSrcPos))
+ // 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();
+ if (rCxt.isAsLink())
+ {
+ ScSingleRefData aRef;
+ aRef.InitAddress(aSrcPos);
+ aRef.SetFlag3D(true);
+
+ ScTokenArray aArr;
+ aArr.AddSingleReference(aRef);
+ rSrcCell.set(new ScFormulaCell(pClipDoc, aSrcPos, aArr));
+ }
+ else
+ {
+ rSrcCell.set(pClipDoc->GetRefCellValue(aSrcPos));
+ const ScPatternAttr* pAttr = pClipDoc->GetPattern(aSrcPos);
+ rCxt.setSingleCellPattern(pAttr);
+
+ // 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.
+ sal_uInt16 nFlags = rCxt.getInsertFlag();
+ bool bNumeric = (nFlags & IDF_VALUE) != 0;
+ bool bDateTime = (nFlags & IDF_DATETIME) != 0;
+ bool bString = (nFlags & IDF_STRING) != 0;
+ bool bBoolean = (nFlags & IDF_SPECIAL_BOOLEAN) != 0;
+ bool bFormula = (nFlags & IDF_FORMULA) != 0;
+
+ switch (rSrcCell.meType)
+ {
+ case CELLTYPE_VALUE:
+ {
+ bool bPaste = rCxt.isDateCell(pSrcTab->aCol[aSrcPos.Col()], aSrcPos.Row()) ? bDateTime : bNumeric;
+ if (!bPaste)
+ // Don't paste this.
+ return true;
+ }
+ break;
+ case CELLTYPE_STRING:
+ case CELLTYPE_EDIT:
+ {
+ if (!bString)
+ // Skip pasting.
+ return true;
+ }
+ break;
+ case CELLTYPE_FORMULA:
+ {
+ if (bBoolean)
+ {
+ // 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;
+ }
+ }
+
+ 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.
+ return true;
+ }
+ else if (rSrcCell.mpFormula->IsValue())
+ {
+ bool bPaste = rCxt.isDateCell(pSrcTab->aCol[aSrcPos.Col()], aSrcPos.Row()) ? bDateTime : bNumeric;
+ if (!bPaste)
+ // Don't paste this.
+ return true;
+
+ // 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
+ return true;
+
+ // 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
+ // We don't want to paste this. Bail out.
+ return true;
+ }
+ break;
+ case CELLTYPE_NONE:
+ default:
+ // There is nothing to paste.
+ return true;
+ }
+ }
+
+ // All good. Proceed with the pasting.
+
+ SCTAB nTabEnd = rCxt.getTabEnd();
+ for (SCTAB i = rCxt.getTabStart(); i <= nTabEnd && i < static_cast<SCTAB>(maTabs.size()); ++i)
+ maTabs[i]->CopyOneCellFromClip(rCxt, nCol1, nRow1, nCol2, nRow2);
+
+ return true;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/core/data/table7.cxx b/sc/source/core/data/table7.cxx
new file mode 100644
index 000000000000..ac036aac2baf
--- /dev/null
+++ b/sc/source/core/data/table7.cxx
@@ -0,0 +1,27 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <table.hxx>
+
+bool ScTable::IsMerged( SCCOL nCol, SCROW nRow ) const
+{
+ if (!ValidCol(nCol))
+ return false;
+
+ return aCol[nCol].IsMerged(nRow);
+}
+
+void ScTable::CopyOneCellFromClip(
+ sc::CopyFromClipContext& rCxt, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 )
+{
+ for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol)
+ aCol[nCol].CopyOneCellFromClip(rCxt, nRow1, nRow2);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */