[Libreoffice-commits] core.git: 2 commits - sc/inc sc/Library_sc.mk sc/source

Kohei Yoshida kohei.yoshida at collabora.com
Fri Jan 24 18:26:17 PST 2014


 sc/Library_sc.mk                    |    3 
 sc/inc/attarray.hxx                 |    1 
 sc/inc/cellvalue.hxx                |    1 
 sc/inc/clipcontext.hxx              |   20 +++-
 sc/inc/column.hxx                   |   10 +-
 sc/inc/document.hxx                 |    4 
 sc/inc/table.hxx                    |    4 
 sc/source/core/data/attarray.cxx    |   10 ++
 sc/source/core/data/cellvalue.cxx   |   24 +++++
 sc/source/core/data/clipcontext.cxx |   29 +++++-
 sc/source/core/data/column2.cxx     |    8 -
 sc/source/core/data/column3.cxx     |   12 --
 sc/source/core/data/column4.cxx     |  124 ++++++++++++++++++++++++++
 sc/source/core/data/document.cxx    |    9 +
 sc/source/core/data/document10.cxx  |  170 ++++++++++++++++++++++++++++++++++++
 sc/source/core/data/table7.cxx      |   27 +++++
 16 files changed, 431 insertions(+), 25 deletions(-)

New commits:
commit 80ea2822c368e6655d216c32904268fc335ef6a4
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Fri Jan 24 11:38:47 2014 -0500

    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

diff --git a/sc/Library_sc.mk b/sc/Library_sc.mk
index d75ce95..1ed89c6 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 2d52279..5b9494d 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 c2606b5..94af146 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 dd63ba6..c693c7f 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 3127cf4..e08226c 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 2f1ecdc..6a980ab 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 f7d3389..00bddb9 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 ec2512f..bcfdb47 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 12ef302..d963fa3 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 8013684..764d66f 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 b891276..22fea46 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 798d544..2301b0f 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 0000000..48c3826
--- /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 27b419c..1f00bd7 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 0000000..1178ce70
--- /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 0000000..ac036aa
--- /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: */
commit f634bc18a0594cc103c1f8a3e0e34fb6024c666d
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Thu Jan 23 22:44:05 2014 -0500

    Use this scope tool instead.
    
    Change-Id: I44d1762bb532fac403963bdebaa98228eebe8f05

diff --git a/sc/source/core/data/document.cxx b/sc/source/core/data/document.cxx
index f1d4ff3..27b419c 100644
--- a/sc/source/core/data/document.cxx
+++ b/sc/source/core/data/document.cxx
@@ -2612,8 +2612,7 @@ void ScDocument::CopyFromClip( const ScRange& rDestRange, const ScMarkData& rMar
     if (!pClipDoc->bIsClip || !pClipDoc->GetTableCount())
         return;
 
-    bool bOldAutoCalc = GetAutoCalc();
-    SetAutoCalc( false );   // avoid multiple recalculations
+    sc::AutoCalcSwitch aACSwitch(*this, false); // temporarily turn off auto calc.
 
     NumFmtMergeHandler aNumFmtMergeHdl(this, pClipDoc);
 
@@ -2789,7 +2788,6 @@ void ScDocument::CopyFromClip( const ScRange& rDestRange, const ScMarkData& rMar
     BroadcastFromClip( nAllCol1, nAllRow1, nAllCol2, nAllRow2, rMark, nInsFlag );
     if (bResetCut)
         pClipDoc->GetClipParam().mbCutMode = false;
-    SetAutoCalc( bOldAutoCalc );
 }
 
 static SCROW lcl_getLastNonFilteredRow(


More information about the Libreoffice-commits mailing list