[Libreoffice-commits] core.git: Branch 'feature/formula-core-rework' - editeng/source include/editeng sc/inc sc/Library_sc.mk sc/qa sc/source

Kohei Yoshida kohei.yoshida at gmail.com
Tue Jun 18 11:49:10 PDT 2013


 editeng/source/editeng/editobj.cxx         |    5 
 include/editeng/editobj.hxx                |    1 
 sc/Library_sc.mk                           |    2 
 sc/inc/cellclonehandler.hxx                |   61 
 sc/inc/cellvalue.hxx                       |   27 
 sc/inc/column.hxx                          |  156 -
 sc/inc/columnspanset.hxx                   |   54 
 sc/inc/dociter.hxx                         |  175 -
 sc/inc/document.hxx                        |   12 
 sc/inc/documentimport.hxx                  |    4 
 sc/inc/editutil.hxx                        |    2 
 sc/inc/formulacell.hxx                     |    2 
 sc/inc/markdata.hxx                        |    2 
 sc/inc/mtvcellfunc.hxx                     |  154 +
 sc/inc/mtvelements.hxx                     |   27 
 sc/inc/mtvfunctions.hxx                    |  786 +++++++
 sc/inc/scopetools.hxx                      |   33 
 sc/inc/table.hxx                           |   44 
 sc/inc/types.hxx                           |   16 
 sc/qa/unit/ucalc.cxx                       |   68 
 sc/source/core/data/cell2.cxx              |   43 
 sc/source/core/data/cellclonehandler.cxx   |   89 
 sc/source/core/data/cellvalue.cxx          |  151 +
 sc/source/core/data/column.cxx             | 2871 +++++++++++++++-----------
 sc/source/core/data/column2.cxx            | 2461 ++++++++++++----------
 sc/source/core/data/column3.cxx            | 3108 +++++++++++++++++------------
 sc/source/core/data/columnspanset.cxx      |  117 +
 sc/source/core/data/dociter.cxx            | 1289 +++++-------
 sc/source/core/data/documen2.cxx           |   13 
 sc/source/core/data/documen4.cxx           |   33 
 sc/source/core/data/documen8.cxx           |    9 
 sc/source/core/data/document.cxx           |   22 
 sc/source/core/data/documentimport.cxx     |   47 
 sc/source/core/data/fillinfo.cxx           |   92 
 sc/source/core/data/formulacell.cxx        |  266 +-
 sc/source/core/data/markdata.cxx           |    7 
 sc/source/core/data/mtvelements.cxx        |   16 
 sc/source/core/data/table1.cxx             |  100 
 sc/source/core/data/table2.cxx             |  382 ++-
 sc/source/core/data/table3.cxx             |  297 +-
 sc/source/core/data/table4.cxx             |  182 -
 sc/source/core/data/table5.cxx             |   18 
 sc/source/core/data/table6.cxx             |  305 +-
 sc/source/core/inc/interpre.hxx            |    1 
 sc/source/core/tool/chgtrack.cxx           |   19 
 sc/source/core/tool/editutil.cxx           |   26 
 sc/source/core/tool/scmatrix.cxx           |  178 -
 sc/source/core/tool/scopetools.cxx         |   28 
 sc/source/filter/xml/XMLExportIterator.cxx |    2 
 sc/source/ui/docshell/dbdocimp.cxx         |    3 
 sc/source/ui/docshell/docsh8.cxx           |    3 
 sc/source/ui/docshell/impex.cxx            |    2 
 sc/source/ui/undo/undodat.cxx              |    1 
 53 files changed, 8098 insertions(+), 5714 deletions(-)

New commits:
commit 813dddf5b403b6b5ee1369b589f3e9ee80bb4a1a
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date:   Fri May 24 11:52:18 2013 -0400

    Switch to using multi_type_vector for cell storage.
    
    The old style cell storage is no more.  Currently the code is buildable,
    but crashes during unit test.
    
    Change-Id: Ie688e22e95c7fb02b9e97b23df0fc1883a97945f

diff --git a/editeng/source/editeng/editobj.cxx b/editeng/source/editeng/editobj.cxx
index 2dd86b9..efb5eb1 100644
--- a/editeng/source/editeng/editobj.cxx
+++ b/editeng/source/editeng/editobj.cxx
@@ -303,6 +303,11 @@ editeng::FieldUpdater EditTextObject::GetFieldUpdater()
     return mpImpl->GetFieldUpdater();
 }
 
+const SfxItemPool* EditTextObject::GetPool() const
+{
+    return mpImpl->GetPool();
+}
+
 sal_uInt16 EditTextObject::GetUserType() const
 {
     return mpImpl->GetUserType();
diff --git a/include/editeng/editobj.hxx b/include/editeng/editobj.hxx
index 6713e50..83f6475 100644
--- a/include/editeng/editobj.hxx
+++ b/include/editeng/editobj.hxx
@@ -71,6 +71,7 @@ public:
     EditTextObject( const EditTextObject& r );
     virtual ~EditTextObject();
 
+    const SfxItemPool* GetPool() const;
     sal_uInt16 GetUserType() const;    // For OutlinerMode, it can however not save in compatible format
     void SetUserType( sal_uInt16 n );
 
diff --git a/sc/Library_sc.mk b/sc/Library_sc.mk
index 373ba8a..d7de9aa 100644
--- a/sc/Library_sc.mk
+++ b/sc/Library_sc.mk
@@ -89,6 +89,7 @@ $(eval $(call gb_Library_add_exception_objects,sc,\
 	sc/source/core/data/bigrange \
 	sc/source/core/data/cell \
 	sc/source/core/data/cell2 \
+	sc/source/core/data/cellclonehandler \
 	sc/source/core/data/cellvalue \
 	sc/source/core/data/clipcontext \
 	sc/source/core/data/clipparam \
@@ -235,6 +236,7 @@ $(eval $(call gb_Library_add_exception_objects,sc,\
 	sc/source/core/tool/reftokenhelper \
 	sc/source/core/tool/refupdat \
 	sc/source/core/tool/scmatrix \
+	sc/source/core/tool/scopetools \
 	sc/source/core/tool/simplerangelist \
 	sc/source/core/tool/stringutil \
 	sc/source/core/tool/subtotal \
diff --git a/sc/inc/cellclonehandler.hxx b/sc/inc/cellclonehandler.hxx
new file mode 100644
index 0000000..a08383c
--- /dev/null
+++ b/sc/inc/cellclonehandler.hxx
@@ -0,0 +1,61 @@
+/* -*- 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/.
+ */
+
+#ifndef SC_CELLCLONEHANDLER_HXX
+#define SC_CELLCLONEHANDLER_HXX
+
+#include "rtl/ustring.hxx"
+#include "address.hxx"
+#include "mtvelements.hxx"
+
+class ScDocument;
+class EditTextObject;
+class ScFormulaCell;
+
+namespace sc {
+
+class CellBlockCloneHandler
+{
+    ScDocument& mrSrcDoc;
+    ScDocument& mrDestDoc;
+    CellStoreType& mrDestCellStore;
+
+protected:
+    ScDocument& getSrcDoc();
+    ScDocument& getDestDoc();
+    const ScDocument& getDestDoc() const;
+    CellStoreType& getDestCellStore();
+
+public:
+    CellBlockCloneHandler(
+        ScDocument& rSrcDoc, ScDocument& rDestDoc, CellStoreType& rDestCellStore);
+    virtual ~CellBlockCloneHandler();
+
+    virtual void cloneDoubleBlock(
+        CellStoreType::iterator& itPos, const ScAddress& rSrcPos, const ScAddress& rDestPos,
+        const numeric_block::const_iterator& itBegin, const numeric_block::const_iterator& itEnd);
+
+    virtual void cloneStringBlock(
+        CellStoreType::iterator& itPos, const ScAddress& rSrcPos, const ScAddress& rDestPos,
+        const string_block::const_iterator& itBegin, const string_block::const_iterator& itEnd);
+
+    virtual void cloneEditTextBlock(
+        CellStoreType::iterator& itPos, const ScAddress& rSrcPos, const ScAddress& rDestPos,
+        const edittext_block::const_iterator& itBegin, const edittext_block::const_iterator& itEnd);
+
+    virtual void cloneFormulaBlock(
+        CellStoreType::iterator& itPos, const ScAddress& rSrcPos, const ScAddress& rDestPos,
+        const formula_block::const_iterator& itBegin, const formula_block::const_iterator& itEnd);
+};
+
+}
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/inc/cellvalue.hxx b/sc/inc/cellvalue.hxx
index fb7c175..b1be68d 100644
--- a/sc/inc/cellvalue.hxx
+++ b/sc/inc/cellvalue.hxx
@@ -7,15 +7,16 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
  */
 
-#ifndef __SC_CELLVALUE_HXX__
-#define __SC_CELLVALUE_HXX__
+#ifndef SC_CELLVALUE_HXX
+#define SC_CELLVALUE_HXX
 
 #include "global.hxx"
+#include "mtvelements.hxx"
 
 class ScDocument;
 class ScFormulaCell;
 class EditTextObject;
-class ScBaseCell;
+class ScColumn;
 
 /**
  * Store arbitrary cell value of any kind.  It only stores cell value and
@@ -42,6 +43,12 @@ struct SC_DLLPUBLIC ScCellValue
 
     void clear();
 
+    void set( double fValue );
+    void set( const OUString& rStr );
+    void set( const EditTextObject& rEditText );
+    void set( const ScFormulaCell& rFormula );
+    void set( ScFormulaCell* pFormula );
+
     /**
      * Take cell value from specified position in specified document.
      */
@@ -50,11 +57,6 @@ struct SC_DLLPUBLIC ScCellValue
     void assign( const ScCellValue& rOther, ScDocument& rDestDoc, int nCloneFlags = SC_CLONECELL_DEFAULT );
 
     /**
-     * TODO: Remove this later.
-     */
-    void assign( const ScBaseCell& rCell );
-
-    /**
      * Set cell value at specified position in specified document.
      */
     void commit( ScDocument& rDoc, const ScAddress& rPos ) const;
@@ -66,6 +68,8 @@ struct SC_DLLPUBLIC ScCellValue
      */
     void release( ScDocument& rDoc, const ScAddress& rPos );
 
+    void release( ScColumn& rColumn, SCROW nRow );
+
     bool hasString() const;
 
     bool hasNumeric() const;
@@ -110,16 +114,15 @@ struct SC_DLLPUBLIC ScRefCellValue
      */
     void assign( ScDocument& rDoc, const ScAddress& rPos );
 
-    /**
-     * TODO: Remove this later.
-     */
-    void assign( ScBaseCell& rCell );
+    void assign( const sc::CellStoreType::const_iterator& itPos, size_t nOffset );
 
     /**
      * Set cell value at specified position in specified document.
      */
     void commit( ScDocument& rDoc, const ScAddress& rPos ) const;
 
+    void commit( ScColumn& rColumn, SCROW nRow ) const;
+
     bool hasString() const;
 
     bool hasNumeric() const;
diff --git a/sc/inc/column.hxx b/sc/inc/column.hxx
index e2c6b45..c0b9c35 100644
--- a/sc/inc/column.hxx
+++ b/sc/inc/column.hxx
@@ -32,6 +32,7 @@
 #include <vector>
 
 #include <boost/intrusive_ptr.hpp>
+#include <mdds/flat_segment_tree.hpp>
 
 namespace editeng { class SvxBorderLine; }
 
@@ -44,6 +45,8 @@ namespace sc {
     class CopyToDocContext;
     class MixDocContext;
     struct ColumnBlockPosition;
+    class CellBlockCloneHandler;
+    class SingleColumnSpanSet;
 }
 
 class Fraction;
@@ -58,7 +61,6 @@ class SvxBoxItem;
 class ScAttrIterator;
 class ScAttrArray;
 struct ScAttrEntry;
-class ScBaseCell;
 class ScDocument;
 class ScEditDataArray;
 class ScFormulaCell;
@@ -77,6 +79,7 @@ struct ScColWidthParam;
 class ScColumnTextWidthIterator;
 struct ScFormulaCellGroup;
 struct ScRefCellValue;
+struct ScCellValue;
 class ScDocumentImport;
 
 struct ScNeededSizeOptions
@@ -90,28 +93,6 @@ struct ScNeededSizeOptions
     ScNeededSizeOptions();
 };
 
-struct ColEntry
-{
-    SCROW       nRow;
-    ScBaseCell* pCell;
-
-    struct Less : std::binary_function<ColEntry, ColEntry, bool>
-    {
-        bool operator() (const ColEntry& r1, const ColEntry& r2) const;
-    };
-};
-
-struct ColDoubleEntry
-{
-    SCROW               mnStart;
-    std::vector<double> maData;
-
-    struct LessByPtr : std::binary_function<ColDoubleEntry*, ColDoubleEntry*, bool>
-    {
-        bool operator() (const ColDoubleEntry* p1, const ColDoubleEntry* p2) const;
-    };
-};
-
 class ScColumn
 {
     // Empty values correspond with empty cells. All non-empty cell positions
@@ -130,10 +111,6 @@ class ScColumn
     SCCOL           nCol;
     SCTAB           nTab;
 
-    std::vector<ColEntry> maItems;
-
-    // temporary until we switch to mdds container
-    std::vector<ColDoubleEntry *> maDoubles;
     std::vector<ScFormulaCellGroupRef> maFnGroups;
 
     ScAttrArray*          pAttrArray;
@@ -141,43 +118,39 @@ class ScColumn
     bool mbDirtyGroups;     /// formula groups are dirty.
 
 friend class ScDocument;                    // for FillInfo
+friend class ScTable;
 friend class ScDocumentIterator;
 friend class ScValueIterator;
 friend class ScHorizontalValueIterator;
 friend class ScDBQueryDataIterator;
-friend class ScColumnIterator;
 friend class ScQueryCellIterator;
-friend class ScMarkedDataIter;
 friend class ScCellIterator;
 friend class ScHorizontalCellIterator;
 friend class ScHorizontalAttrIterator;
 friend class ScColumnTextWidthIterator;
 friend class ScDocumentImport;
+friend class sc::SingleColumnSpanSet;
 
     ScColumn(const ScColumn&); // disabled
     ScColumn& operator= (const ScColumn&); // disabled
 
-    std::vector<ColEntry>::iterator Search( SCROW nRow );
-    std::vector<ColEntry>::const_iterator Search( SCROW nRow ) const;
-
 public:
                 ScColumn();
                 ~ScColumn();
 
     void        Init(SCCOL nNewCol, SCTAB nNewTab, ScDocument* pDoc);
 
-    bool    Search( SCROW nRow, SCSIZE& nIndex ) const;
-    ScBaseCell* GetCell( SCROW nRow ) const;
+    ScDocument& GetDoc();
+    const ScDocument& GetDoc() const;
+    SCTAB GetTab() const { return nTab; }
+    SCCOL GetCol() const { return nCol; }
+
     ScRefCellValue GetCellValue( SCROW nRow ) const;
-    void Insert( sc::ColumnBlockPosition& rBlockPos, SCROW nRow, ScBaseCell* pCell );
-    void        Insert( SCROW nRow, ScBaseCell* pCell );
-    void        Insert( SCROW nRow, sal_uInt32 nFormatIndex, ScBaseCell* pCell );
-    void Append( sc::ColumnBlockPosition& rBlockPos, SCROW nRow, ScBaseCell* pCell );
-    void        Append( SCROW nRow, ScBaseCell* pCell );
+    ScRefCellValue GetCellValue( sc::CellStoreType::const_iterator& itPos, SCROW nRow ) const;
+    ScRefCellValue GetCellValue( sc::CellStoreType::const_iterator& itPos, size_t nOffset ) const;
+
     void        Delete( SCROW nRow );
-    void        DeleteAtIndex( SCSIZE nIndex );
     void        FreeAll();
-    void ReserveSize( SCSIZE nSize );
     void        SwapRow( SCROW nRow1, SCROW nRow2 );
     void        SwapCell( SCROW nRow, ScColumn& rCol);
     void        RebuildFormulaGroups();
@@ -188,7 +161,6 @@ public:
                                 SCCOL& rPaintCol, SCROW& rPaintRow,
                                 bool bRefresh );
 
-    bool               IsEmptyVisData() const;              // without Broadcaster
     bool               IsEmptyData() const;
     bool               IsEmptyAttr() const;
     bool               IsEmpty() const;
@@ -200,12 +172,10 @@ public:
     bool               HasVisibleDataAt(SCROW nRow) const;
     SCROW              GetFirstDataPos() const;
     SCROW              GetLastDataPos() const;
-    SCROW              GetLastVisDataPos() const;                           // without Broadcaster
-    SCROW              GetFirstVisDataPos() const;
     bool               GetPrevDataPos(SCROW& rRow) const;
     bool               GetNextDataPos(SCROW& rRow) const;
     void               FindDataAreaPos(SCROW& rRow, bool bDown) const; // (without Broadcaster)
-    void               FindUsed( SCROW nStartRow, SCROW nEndRow, bool* pUsed ) const;
+    void FindUsed( SCROW nStartRow, SCROW nEndRow, mdds::flat_segment_tree<SCROW, bool>& rUsed ) const;
 
     SCSIZE             VisibleCount( SCROW nStartRow, SCROW nEndRow ) const;
     sal_uInt16  GetBlockMatrixEdges( SCROW nRow1, SCROW nRow2, sal_uInt16 nMask ) const;
@@ -219,7 +189,7 @@ public:
     bool    IsAllAttrEqual( const ScColumn& rCol, SCROW nStartRow, SCROW nEndRow ) const;
 
     bool    TestInsertCol( SCROW nStartRow, SCROW nEndRow) const;
-    bool    TestInsertRow( SCSIZE nSize ) const;
+    bool TestInsertRow( SCROW nStartRow, SCSIZE nSize ) const;
     void        InsertRow( SCROW nStartRow, SCSIZE nSize );
     void        DeleteRow( SCROW nStartRow, SCSIZE nSize );
     void        DeleteArea(SCROW nStartRow, SCROW nEndRow, sal_uInt16 nDelFlag );
@@ -228,11 +198,11 @@ public:
     void CopyStaticToDocument(SCROW nRow1, SCROW nRow2, ScColumn& rDestCol);
     void CopyCellToDocument( SCROW nSrcRow, SCROW nDestRow, ScColumn& rDestCol );
     bool InitBlockPosition( sc::ColumnBlockPosition& rBlockPos );
+    bool InitBlockPosition( sc::ColumnBlockConstPosition& rBlockPos ) const;
     void CopyFromClip(
         sc::CopyFromClipContext& rCxt, SCROW nRow1, SCROW nRow2, long nDy, ScColumn& rColumn );
 
     void StartListeningInArea( sc::StartListeningContext& rCxt, SCROW nRow1, SCROW nRow2 );
-    void        BroadcastInArea( SCROW nRow1, SCROW nRow2 );
 
     void        RemoveEditAttribs( SCROW nStartRow, SCROW nEndRow );
 
@@ -244,21 +214,15 @@ public:
         sc::MixDocContext& rCxt, SCROW nRow1, SCROW nRow2, sal_uInt16 nFunction, bool bSkipEmpty,
         const ScColumn& rSrcCol );
 
-    ScFormulaCell*  CreateRefCell( ScDocument* pDestDoc, const ScAddress& rDestPos,
-                                    SCSIZE nIndex, sal_uInt16 nFlags ) const;
-
     ScAttrIterator* CreateAttrIterator( SCROW nStartRow, SCROW nEndRow ) const;
 
-
-    SCCOL              GetCol() const { return nCol; }
-
                 //     UpdateSelectionFunction: multi-select
     void UpdateSelectionFunction(
         const ScMarkData& rMark, ScFunctionData& rData, ScFlatBoolRowSegments& rHiddenRows,
-        bool bDoExclude, SCROW nExStartRow, SCROW nExEndRow ) const;
+        bool bDoExclude, SCROW nExStartRow, SCROW nExEndRow );
 
     void UpdateAreaFunction(
-        ScFunctionData& rData, ScFlatBoolRowSegments& rHiddenRows, SCROW nStartRow, SCROW nEndRow) const;
+        ScFunctionData& rData, ScFlatBoolRowSegments& rHiddenRows, SCROW nStartRow, SCROW nEndRow);
 
     void CopyToColumn(
         sc::CopyToDocContext& rCxt, SCROW nRow1, SCROW nRow2, sal_uInt16 nFlags, bool bMarked,
@@ -286,12 +250,18 @@ public:
         ScSetStringParam* pParam = NULL );
 
     void SetEditText( SCROW nRow, EditTextObject* pEditText );
+    void SetEditText( sc::ColumnBlockPosition& rBlockPos, SCROW nRow, EditTextObject* pEditText );
+    void SetEditText( sc::ColumnBlockPosition& rBlockPos, SCROW nRow, const EditTextObject& rEditText );
     void SetEditText( SCROW nRow, const EditTextObject& rEditText, const SfxItemPool* pEditPool );
     void SetFormula( SCROW nRow, const ScTokenArray& rArray, formula::FormulaGrammar::Grammar eGram );
     void SetFormula( SCROW nRow, const OUString& rFormula, formula::FormulaGrammar::Grammar eGram );
     void SetFormulaCell( SCROW nRow, ScFormulaCell* pCell );
+    void SetFormulaCell( sc::ColumnBlockPosition& rBlockPos, SCROW nRow, ScFormulaCell* pCell );
 
-    void        SetValue( SCROW nRow, const double& rVal);
+    void SetRawString( SCROW nRow, const OUString& rStr, bool bBroadcast = true );
+    void SetRawString( sc::ColumnBlockPosition& rBlockPos, SCROW nRow, const OUString& rStr, bool bBroadcast = true );
+    void SetValue( SCROW nRow, double fVal );
+    void SetValue( sc::ColumnBlockPosition& rBlockPos, SCROW nRow, double fVal, bool bBroadcast = true );
     void        SetError( SCROW nRow, const sal_uInt16 nError);
 
     void        GetString( SCROW nRow, OUString& rString ) const;
@@ -318,7 +288,7 @@ public:
     bool IsFormulaDirty( SCROW nRow ) const;
 
     void        SetDirty();
-    void        SetDirty( const ScRange& );
+    void        SetDirty( SCROW nRow1, SCROW nRow2 );
     void        SetDirtyVar();
     void        SetDirtyAfterLoad();
     void        SetTableOpDirty( const ScRange& );
@@ -428,7 +398,7 @@ public:
     SCsROW      GetNextUnprotected( SCROW nRow, bool bUp ) const;
 
     void GetFilterEntries(SCROW nStartRow, SCROW nEndRow, std::vector<ScTypedStrData>& rStrings, bool& rHasDates);
-    bool GetDataEntries(SCROW nRow, std::set<ScTypedStrData>& rStrings, bool bLimit);
+    bool GetDataEntries( SCROW nRow, std::set<ScTypedStrData>& rStrings, bool bLimit ) const;
 
     void UpdateInsertTabAbs(SCTAB nNewPos);
     bool    TestTabRefAbs(SCTAB nTable) const;
@@ -458,6 +428,11 @@ public:
     void SetTextWidth(SCROW nRow, sal_uInt16 nWidth);
 
     sal_uInt8 GetScriptType( SCROW nRow ) const;
+
+    /**
+     * Get combined script types of the specified range. This method may
+     * update script types on demand if they have not been determined.
+     */
     sal_uInt8 GetRangeScriptType( sc::CellTextAttrStoreType::iterator& itPos, SCROW nRow1, SCROW nRow2 );
 
     void SetScriptType( SCROW nRow, sal_uInt8 nType );
@@ -469,8 +444,6 @@ public:
     bool ResolveStaticReference( ScMatrix& rMat, SCCOL nMatCol, SCROW nRow1, SCROW nRow2 );
     const double* FetchDoubleArray( sc::FormulaGroupContext& rCxt, SCROW nRow1, SCROW nRow2 ) const;
 
-    ScRefCellValue GetRefCellValue( SCROW );
-
     void SetNumberFormat( SCROW nRow, sal_uInt32 nNumberFormat );
 
     SvtBroadcaster* GetBroadcaster( SCROW nRow );
@@ -478,17 +451,25 @@ public:
     void DeleteBroadcasters( sc::ColumnBlockPosition& rBlockPos, SCROW nRow1, SCROW nRow2 );
     bool HasBroadcaster() const;
 
+    void BroadcastCells( const std::vector<SCROW>& rRows );
+    void EndFormulaListening( sc::ColumnBlockPosition& rBlockPos, SCROW nRow1, SCROW nRow2 );
+
 private:
-    void UpdateScriptType( sc::CellTextAttr& rAttr, SCROW nRow );
 
-    void DeleteRange(
-        SCSIZE nStartIndex, SCSIZE nEndIndex, sal_uInt16 nDelFlag, std::vector<SCROW>& rDeletedRows );
+    void CopyCellsInRangeToColumn(
+        sc::ColumnBlockConstPosition* rSrcColPos, sc::ColumnBlockPosition* pDestColPos,
+        sc::CellBlockCloneHandler& Hdl, SCROW nRow1, SCROW nRow2, ScColumn& rColumn ) const;
 
-    const ScFormulaCell* FetchFormulaCell( SCROW nRow ) const;
+    sc::CellStoreType::iterator GetPositionToInsert( SCROW nRow );
+    sc::CellStoreType::iterator GetPositionToInsert( const sc::CellStoreType::iterator& it, SCROW nRow );
+    void ActivateNewFormulaCell( ScFormulaCell* pCell );
+    void BroadcastNewCell( SCROW nRow );
+    void UpdateScriptType( sc::CellTextAttr& rAttr, SCROW nRow );
 
-    ScBaseCell* CloneCell(SCSIZE nIndex, sal_uInt16 nFlags, ScDocument& rDestDoc, const ScAddress& rDestPos) const;
+    const ScFormulaCell* FetchFormulaCell( SCROW nRow ) const;
 
-    SCROW FindNextVisibleRowWithContent(SCROW nRow, bool bForward) const;
+    SCROW FindNextVisibleRowWithContent(
+        sc::CellStoreType::const_iterator& itPos, SCROW nRow, bool bForward) const;
     SCROW FindNextVisibleRow(SCROW nRow, bool bForward) const;
 
     /**
@@ -501,52 +482,21 @@ private:
 
     void CopyCellTextAttrsToDocument(SCROW nRow1, SCROW nRow2, ScColumn& rDestCol) const;
 
-    void SetCell( sc::ColumnBlockPosition& rBlockPos, SCROW nRow, ScBaseCell* pNewCell );
-    void SetCell( SCROW nRow, ScBaseCell* pNewCell );
-    void PostSetCell( SCROW nRow, ScBaseCell* pNewCell );
-
     /**
      * Clear and re-populate the cell text attribute array from the non-empty
      * cells stored in the cell array.
      */
     void ResetCellTextAttrs();
-};
 
+    void SwapCellTextAttrs( SCROW nRow1, SCROW nRow2 );
 
-class ScColumnIterator                                 // walk through all data of a area/range
-{
-    const ScColumn*            pColumn;
-    SCSIZE                             nPos;
-    SCROW               nTop;
-    SCROW               nBottom;
-public:
-                ScColumnIterator( const ScColumn* pCol, SCROW nStart=0, SCROW nEnd=MAXROW );
-                ~ScColumnIterator();
-
-    bool    Next( SCROW& rRow, ScBaseCell*& rpCell );
-    SCSIZE      GetIndex() const;
-};
-
-
-class ScMarkedDataIter                                 // walk through data in a selected area/range
-{
-    const ScColumn*            pColumn;
-    SCSIZE                             nPos;
-    ScMarkArrayIter*    pMarkIter;
-    SCROW               nTop;
-    SCROW               nBottom;
-    bool            bNext;
-    bool            bAll;
-
-public:
-                ScMarkedDataIter( const ScColumn* pCol, const ScMarkData* pMarkData,
-                                    bool bAllIfNone = false );
-                ~ScMarkedDataIter();
-
-    bool    Next( SCSIZE& rIndex );
+    /**
+     * Retrieve the cell value and set that slot empty. The ownership of that
+     * cell value moves to the returned cell value object.
+     */
+    void ReleaseCellValue( sc::CellStoreType::iterator& itPos, SCROW nRow, ScCellValue& rVal );
 };
 
-
 #endif
 
 
diff --git a/sc/inc/columnspanset.hxx b/sc/inc/columnspanset.hxx
index ab24828..55c3f57 100644
--- a/sc/inc/columnspanset.hxx
+++ b/sc/inc/columnspanset.hxx
@@ -16,8 +16,13 @@
 #include <mdds/flat_segment_tree.hpp>
 #include <boost/noncopyable.hpp>
 
+class ScColumn;
+class ScMarkData;
+
 namespace sc {
 
+struct ColumnBlockConstPosition;
+
 /**
  * Structure that stores segments of boolean flags per column, and perform
  * custom action on those segments.
@@ -49,6 +54,55 @@ public:
     void executeFromTop(Action& ac) const;
 };
 
+/**
+ * Keep track of spans in a single column only.
+ */
+class SingleColumnSpanSet
+{
+public:
+    typedef mdds::flat_segment_tree<SCROW, bool> ColumnSpansType;
+
+    struct Span
+    {
+        SCROW mnRow1;
+        SCROW mnRow2;
+
+        Span(SCROW nRow1, SCROW nRow2) : mnRow1(nRow1), mnRow2(nRow2) {}
+    };
+
+    typedef std::vector<Span> SpansType;
+
+    SingleColumnSpanSet();
+
+    /**
+     * Scan an entire column and tag all non-empty cell positions.
+     */
+    void scan(const ScColumn& rColumn);
+
+    /**
+     * Scan a column between specified range, and tag all non-empty cell
+     * positions.
+     */
+    void scan(const ScColumn& rColumn, SCROW nStart, SCROW nEnd);
+
+    void scan(
+        ColumnBlockConstPosition& rBlockPos, const ScColumn& rColumn, SCROW nStart, SCROW nEnd);
+
+    /**
+     * Scan all marked data and tag all marked segments in specified column.
+     */
+    void scan(const ScMarkData& rMark, SCTAB nTab, SCCOL nCol);
+
+    void set(SCROW nRow1, SCROW nRow2, bool bVal);
+
+    void getRows(std::vector<SCROW> &rRows) const;
+
+    void getSpans(SpansType& rSpans) const;
+
+private:
+    ColumnSpansType maSpans;
+};
+
 }
 
 #endif
diff --git a/sc/inc/dociter.hxx b/sc/inc/dociter.hxx
index cfffb7e..87d17b2 100644
--- a/sc/inc/dociter.hxx
+++ b/sc/inc/dociter.hxx
@@ -25,6 +25,7 @@
 #include "global.hxx"
 #include "scdllapi.h"
 #include "cellvalue.hxx"
+#include "mtvelements.hxx"
 
 #include <memory>
 
@@ -34,7 +35,6 @@
 #include <boost/scoped_ptr.hpp>
 
 class ScDocument;
-class ScBaseCell;
 class ScPatternAttr;
 class ScAttrArray;
 class ScAttrIterator;
@@ -47,84 +47,52 @@ struct ScDBQueryParamInternal;
 struct ScDBQueryParamMatrix;
 class ScFormulaCell;
 
-class ScDocumentIterator                // walk through all non-empty cells
-{
-private:
-    ScDocument*             pDoc;
-    SCTAB                   nStartTab;
-    SCTAB                   nEndTab;
-
-    const ScPatternAttr*    pDefPattern;
-
-    SCCOL                   nCol;
-    SCROW                   nRow;
-    SCTAB                   nTab;
-    ScBaseCell*             pCell;
-    const ScPatternAttr*    pPattern;
-
-
-    SCSIZE                  nColPos;
-    SCSIZE                  nAttrPos;
-
-    bool                    GetThis();
-    bool                    GetThisCol();
-
-public:
-            ScDocumentIterator( ScDocument* pDocument, SCTAB nStartTable, SCTAB nEndTable );
-            ~ScDocumentIterator();
-
-    bool                    GetFirst();
-    bool                    GetNext();
-
-    ScCellValue GetCellValue() const;
-    const ScPatternAttr*    GetPattern();
-    void                    GetPos( SCCOL& rCol, SCROW& rRow, SCTAB& rTab );
-};
-
 class ScValueIterator            // walk through all values in an area
 {
-private:
-    double          fNextValue;
+    typedef std::pair<sc::CellStoreType::const_iterator, size_t> PositionType;
+
     ScDocument*     pDoc;
     const ScAttrArray*  pAttrArray;
     sal_uLong           nNumFormat;     // for CalcAsShown
     sal_uLong           nNumFmtIndex;
-    SCCOL           nStartCol;
-    SCROW           nStartRow;
-    SCTAB           nStartTab;
-    SCCOL           nEndCol;
-    SCROW           nEndRow;
-    SCTAB           nEndTab;
-    SCCOL           nCol;
-    SCROW           nRow;
-    SCTAB           nTab;
-    SCSIZE          nColRow;
-    SCROW           nNextRow;
+    ScAddress maStartPos;
+    ScAddress maEndPos;
+    SCCOL mnCol;
+    SCTAB mnTab;
     SCROW           nAttrEndRow;
     short           nNumFmtType;
-    bool            bNumValid;
-    bool            bSubTotal;
-    bool            bNextValid;
-    bool            bCalcAsShown;
-    bool            bTextAsZero;
+    bool            bNumValid:1;
+    bool            bSubTotal:1;
+    bool            bCalcAsShown:1;
+    bool            bTextAsZero:1;
+
+    const sc::CellStoreType* mpCells;
+    PositionType maCurPos;
+
+    SCROW GetRow() const;
+    void IncBlock();
+    void IncPos();
+    void SetPos(size_t nPos);
+
+    /**
+     * See if the cell at the current position is a non-empty cell. If not,
+     * move to the next non-empty cell position.
+     */
+    bool GetThis( double& rValue, sal_uInt16& rErr );
 
-    bool            GetThis(double& rValue, sal_uInt16& rErr);
 public:
 
-                    ScValueIterator(ScDocument* pDocument,
-                                    const ScRange& rRange, bool bSTotal = false,
-                                    bool bTextAsZero = false );
-    void            GetCurNumFmtInfo( short& nType, sal_uLong& nIndex );
+    ScValueIterator(
+        ScDocument* pDocument, const ScRange& rRange, bool bSTotal = false,
+        bool bTextAsZero = false );
+
+    void GetCurNumFmtInfo( short& nType, sal_uLong& nIndex );
+
     /// Does NOT reset rValue if no value found!
-    bool            GetFirst(double& rValue, sal_uInt16& rErr);
+    bool GetFirst( double& rValue, sal_uInt16& rErr );
+
     /// Does NOT reset rValue if no value found!
-    bool            GetNext(double& rValue, sal_uInt16& rErr)
-                    {
-                        return bNextValid ? ( bNextValid = false, rValue = fNextValue,
-                                                rErr = 0, nRow = nNextRow,
-                                                ++nColRow, bNumValid = false, true )
-                                          : ( ++nRow, GetThis(rValue, rErr) );
-                    }
+    bool GetNext( double& rValue, sal_uInt16& rErr );
 };
 
 class ScDBQueryDataIterator
@@ -141,11 +109,9 @@ public:
     };
 
 private:
-    static SCROW        GetRowByColEntryIndex(ScDocument& rDoc, SCTAB nTab, SCCOL nCol, SCSIZE nColRow);
-    static ScBaseCell*  GetCellByColEntryIndex(ScDocument& rDoc, SCTAB nTab, SCCOL nCol, SCSIZE nColRow);
+    static const sc::CellStoreType* GetColumnCellStore(ScDocument& rDoc, SCTAB nTab, SCCOL nCol);
     static const ScAttrArray* GetAttrArrayByCol(ScDocument& rDoc, SCTAB nTab, SCCOL nCol);
-    static bool         IsQueryValid(ScDocument& rDoc, const ScQueryParam& rParam, SCTAB nTab, SCROW nRow, ScBaseCell* pCell);
-    static SCSIZE       SearchColEntryIndex(ScDocument& rDoc, SCTAB nTab, SCROW nRow, SCCOL nCol);
+    static bool IsQueryValid(ScDocument& rDoc, const ScQueryParam& rParam, SCTAB nTab, SCROW nRow, ScRefCellValue& rCell);
 
     class DataAccess
     {
@@ -161,6 +127,7 @@ private:
 
     class DataAccessInternal : public DataAccess
     {
+        typedef std::pair<sc::CellStoreType::const_iterator,size_t> PositionType;
     public:
         DataAccessInternal(const ScDBQueryDataIterator* pParent, ScDBQueryParamInternal* pParam, ScDocument* pDoc);
         virtual ~DataAccessInternal();
@@ -169,6 +136,12 @@ private:
         virtual bool getNext(Value& rValue);
 
     private:
+        void incBlock();
+        void incPos();
+        void setPos(size_t nPos);
+
+        const sc::CellStoreType* mpCells;
+        PositionType maCurPos;
         ScDBQueryParamInternal* mpParam;
         ScDocument*         mpDoc;
         const ScAttrArray*  pAttrArray;
@@ -176,7 +149,6 @@ private:
         sal_uLong               nNumFmtIndex;
         SCCOL               nCol;
         SCROW               nRow;
-        SCSIZE              nColRow;
         SCROW               nAttrEndRow;
         SCTAB               nTab;
         short               nNumFmtType;
@@ -212,18 +184,31 @@ public:
     bool            GetNext(Value& rValue);
 };
 
-class ScCellIterator            // walk through all cells in an area
-{                               // for SubTotal no hidden and no sub-total lines
-private:
+/**
+ * Walk through all cells in an area. For SubTotal no hidden and no
+ * sub-total lines.
+ **/
+class ScCellIterator
+{
+    typedef std::pair<sc::CellStoreType::const_iterator, size_t> PositionType;
+
     ScDocument* mpDoc;
     ScAddress maStartPos;
     ScAddress maEndPos;
     ScAddress maCurPos;
+
+    PositionType maCurColPos;
     SCSIZE mnIndex;
     bool mbSubTotal;
 
     ScRefCellValue maCurCell;
 
+    void incBlock();
+    void incPos();
+    void setPos(size_t nPos);
+
+    const ScColumn* getColumn() const;
+
     void init();
     bool getCurrent();
 
@@ -269,7 +254,9 @@ class ScQueryCellIterator           // walk through all non-empty cells in an ar
         nTestEqualConditionFulfilled = nTestEqualConditionEnabled | nTestEqualConditionMatched
     };
 
-private:
+    typedef std::pair<sc::CellStoreType::const_iterator, size_t> PositionType;
+    PositionType maCurPos;
+
     boost::scoped_ptr<ScQueryParam> mpParam;
     ScDocument*     pDoc;
     const ScAttrArray*  pAttrArray;
@@ -277,14 +264,17 @@ private:
     SCTAB           nTab;
     SCCOL           nCol;
     SCROW           nRow;
-    SCSIZE          nColRow;
     SCROW           nAttrEndRow;
     sal_uInt8            nStopOnMismatch;
     sal_uInt8            nTestEqualCondition;
     bool            bAdvanceQuery;
     bool            bIgnoreMismatchOnLeadingStrings;
 
-    ScBaseCell*     GetThis();
+    /** Initialize position for new column. */
+    void InitPos();
+    void IncPos();
+    void IncBlock();
+    bool GetThis();
 
                     /* Only works if no regular expression is involved, only
                        searches for rows in one column, and only the first
@@ -295,15 +285,15 @@ private:
                        GetThis() and GetNext() afterwards. Introduced for
                        FindEqualOrSortedLastInRange()
                      */
-    ScBaseCell*     BinarySearch();
+    bool BinarySearch();
 
 public:
                     ScQueryCellIterator(ScDocument* pDocument, SCTAB nTable,
                                         const ScQueryParam& aParam, bool bMod = true);
                                         // for bMod = FALSE the QueryParam has to be filled
                                         // (bIsString)
-    ScBaseCell*     GetFirst();
-    ScBaseCell*     GetNext();
+    bool GetFirst();
+    bool GetNext();
     SCCOL           GetCol() { return nCol; }
     SCROW           GetRow() { return nRow; }
 
@@ -420,27 +410,36 @@ public:
 
 class ScHorizontalCellIterator      // walk through all non empty cells in an area
 {                                   // row by row
-private:
+    typedef std::pair<sc::CellStoreType::const_iterator,size_t> PositionType;
+
+    struct ColParam
+    {
+        sc::CellStoreType::const_iterator maPos;
+        sc::CellStoreType::const_iterator maEnd;
+    };
+
+    std::vector<ColParam> maColPositions;
+
     ScDocument*     pDoc;
-    SCTAB           nTab;
+    SCTAB           mnTab;
     SCCOL           nStartCol;
     SCCOL           nEndCol;
     SCROW           nStartRow;
     SCROW           nEndRow;
     SCROW*          pNextRows;
     SCSIZE*         pNextIndices;
-    SCCOL           nCol;
-    SCROW           nRow;
+    SCCOL           mnCol;
+    SCROW           mnRow;
     ScRefCellValue  maCurCell;
     bool            bMore;
 
 public:
-                    ScHorizontalCellIterator(ScDocument* pDocument, SCTAB nTable,
-                                    SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2);
-                    ~ScHorizontalCellIterator();
+    ScHorizontalCellIterator(ScDocument* pDocument, SCTAB nTable,
+                    SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2);
+    ~ScHorizontalCellIterator();
 
     ScRefCellValue* GetNext( SCCOL& rCol, SCROW& rRow );
-    bool            ReturnNext( SCCOL& rCol, SCROW& rRow );
+    bool            GetPos( SCCOL& rCol, SCROW& rRow );
     /// Set a(nother) sheet and (re)init.
     void            SetTab( SCTAB nTab );
 
diff --git a/sc/inc/document.hxx b/sc/inc/document.hxx
index 427ab2c..59cc997 100644
--- a/sc/inc/document.hxx
+++ b/sc/inc/document.hxx
@@ -83,7 +83,6 @@ class XColorList;
 
 struct ScAttrEntry;
 class ScAutoFormatData;
-class ScBaseCell;
 class ScBroadcastAreaSlotMachine;
 class ScChangeViewSettings;
 class ScChartCollection;
@@ -212,7 +211,6 @@ const sal_uInt8 SC_DDE_IGNOREMODE    = 255;       /// For usage in FindDdeLink()
 
 class ScDocument
 {
-friend class ScDocumentIterator;
 friend class ScValueIterator;
 friend class ScHorizontalValueIterator;
 friend class ScDBQueryDataIterator;
@@ -1624,8 +1622,6 @@ public:
                                  SCCOL nCol, SCROW nRow, SCTAB nTab,
                                  ScMarkData& rMark, bool bIsUndo);
 
-    void            DoColResize( SCTAB nTab, SCCOL nCol1, SCCOL nCol2, SCSIZE nAdd );
-
     void            InvalidateTextWidth( const OUString& rStyleName );
     void            InvalidateTextWidth( SCTAB nTab );
     void            InvalidateTextWidth( const ScAddress* pAdrFrom, const ScAddress* pAdrTo, bool bNumFormatChanged );
@@ -1708,6 +1704,11 @@ public:
 
     SC_DLLPUBLIC ScMacroManager* GetMacroManager();
 
+    /**
+     * See if specified column has any non-empty cells.
+     */
+    bool IsEmptyData( SCTAB nTab, SCCOL nCol ) const;
+
 private:
     ScDocument(const ScDocument& r); // disabled with no definition
 
@@ -2020,9 +2021,6 @@ private: // CLOOK-Impl-methods
 
     bool    HasPartOfMerged( const ScRange& rRange );
 
-    void PutCell( const ScAddress&, ScBaseCell* pCell, bool bForceTab = false );
-    void PutCell(SCCOL nCol, SCROW nRow, SCTAB nTab, ScBaseCell* pCell, sal_uLong nFormatIndex, bool bForceTab = false );
-
     ScRefCellValue GetRefCellValue( const ScAddress& rPos );
 
     std::map< SCTAB, ScSortParam > mSheetSortParams;
diff --git a/sc/inc/documentimport.hxx b/sc/inc/documentimport.hxx
index afd954b..9fddf2b 100644
--- a/sc/inc/documentimport.hxx
+++ b/sc/inc/documentimport.hxx
@@ -20,7 +20,6 @@
 class ScDocument;
 class ScAddress;
 class ScTokenArray;
-class ScBaseCell;
 struct ScDocumentImportImpl;
 
 /**
@@ -62,9 +61,6 @@ public:
     void setFormulaCell(const ScAddress& rPos, const ScTokenArray& rArray);
 
     void finalize();
-
-private:
-    void insertCell(const ScAddress& rPos, ScBaseCell* pCell);
 };
 
 #endif
diff --git a/sc/inc/editutil.hxx b/sc/inc/editutil.hxx
index c033415..eb7fd56 100644
--- a/sc/inc/editutil.hxx
+++ b/sc/inc/editutil.hxx
@@ -66,6 +66,8 @@ public:
 
     static void RemoveCharAttribs( EditTextObject& rEditText, const ScPatternAttr& rAttr );
 
+    static EditTextObject* Clone( const EditTextObject& rSrc, ScDocument& rDestDoc );
+
 public:
                 ScEditUtil( ScDocument* pDocument, SCCOL nX, SCROW nY, SCTAB nZ,
                             const Point& rScrPosPixel,
diff --git a/sc/inc/formulacell.hxx b/sc/inc/formulacell.hxx
index 4760062..af9067e 100644
--- a/sc/inc/formulacell.hxx
+++ b/sc/inc/formulacell.hxx
@@ -211,7 +211,7 @@ public:
     const ScMatrix* GetMatrix();
     bool            GetMatrixOrigin( ScAddress& rPos ) const;
     void            GetResultDimensions( SCSIZE& rCols, SCSIZE& rRows );
-    sal_uInt16      GetMatrixEdge( ScAddress& rOrgPos );
+    sal_uInt16 GetMatrixEdge( ScAddress& rOrgPos ) const;
     sal_uInt16      GetErrCode();   // interpret first if necessary
     sal_uInt16      GetRawError();  // don't interpret, just return code or result error
     short           GetFormatType() const                   { return nFormatType; }
diff --git a/sc/inc/markdata.hxx b/sc/inc/markdata.hxx
index ad7a4b1..75937ed 100644
--- a/sc/inc/markdata.hxx
+++ b/sc/inc/markdata.hxx
@@ -96,6 +96,8 @@ public:
     void        FillRangeListWithMarks( ScRangeList* pList, bool bClear ) const;
     void        ExtendRangeListTables( ScRangeList* pList ) const;
 
+    ScRangeList GetMarkedRanges() const;
+
     void        MarkFromRangeList( const ScRangeList& rList, bool bReset );
 
     SCCOLROW    GetMarkColumnRanges( SCCOLROW* pRanges );
diff --git a/sc/inc/mtvcellfunc.hxx b/sc/inc/mtvcellfunc.hxx
new file mode 100644
index 0000000..9ce3c12
--- /dev/null
+++ b/sc/inc/mtvcellfunc.hxx
@@ -0,0 +1,154 @@
+/* -*- 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/.
+ */
+
+#ifndef SC_MTVCELLFUNC_HXX
+#define SC_MTVCELLFUNC_HXX
+
+#include "mtvelements.hxx"
+#include "mtvfunctions.hxx"
+
+namespace sc {
+
+template<typename _Func>
+void ProcessFormula(CellStoreType& rStore, _Func& rFunc)
+{
+    FuncElseNoOp<size_t> aElse;
+    ProcessElements1<CellStoreType, formula_block, _Func, FuncElseNoOp<size_t> >(rStore, rFunc, aElse);
+}
+
+template<typename _FuncElem>
+typename CellStoreType::iterator
+ProcessFormula(
+    const CellStoreType::iterator& it, CellStoreType& rStore, SCROW nRow1, SCROW nRow2, _FuncElem& rFuncElem)
+{
+    FuncElseNoOp<size_t> aElse;
+    return ProcessElements1<
+        CellStoreType, formula_block, _FuncElem, FuncElseNoOp<size_t> >(it, rStore, nRow1, nRow2, rFuncElem, aElse);
+}
+
+template<typename _FuncElem, typename _FuncElse>
+typename CellStoreType::iterator
+ProcessFormula(
+    const CellStoreType::iterator& it, CellStoreType& rStore, SCROW nRow1, SCROW nRow2, _FuncElem& rFuncElem, _FuncElse& rFuncElse)
+{
+    return ProcessElements1<
+        CellStoreType, formula_block, _FuncElem, _FuncElse>(it, rStore, nRow1, nRow2, rFuncElem, rFuncElse);
+}
+
+template<typename _Func>
+typename CellStoreType::iterator
+ProcessFormulaNumeric(
+    const CellStoreType::iterator& itPos, CellStoreType& rStore, SCROW nRow1, SCROW nRow2, _Func& rFunc)
+{
+    FuncElseNoOp<size_t> aElse;
+    return ProcessElements2<
+        CellStoreType, numeric_block, formula_block, _Func, FuncElseNoOp<size_t> >(
+            itPos, rStore, nRow1, nRow2, rFunc, aElse);
+}
+
+template<typename _Func>
+void ProcessEditText(CellStoreType& rStore, _Func& rFunc)
+{
+    FuncElseNoOp<size_t> aElse;
+    ProcessElements1<CellStoreType, edittext_block, _Func, FuncElseNoOp<size_t> >(rStore, rFunc, aElse);
+}
+
+template<typename _Func>
+CellStoreType::iterator
+ProcessEditText(const CellStoreType::iterator& itPos, CellStoreType& rStore, SCROW nRow1, SCROW nRow2, _Func& rFunc)
+{
+    FuncElseNoOp<size_t> aElse;
+    return ProcessElements1<CellStoreType, edittext_block, _Func, FuncElseNoOp<size_t> >(
+        itPos, rStore, nRow1, nRow2, rFunc, aElse);
+}
+
+template<typename _Func>
+void ParseFormula(
+    const CellStoreType& rStore, _Func& rFunc)
+{
+    FuncElseNoOp<size_t> aElse;
+    ParseElements1<CellStoreType, formula_block, _Func, FuncElseNoOp<size_t> >(rStore, rFunc, aElse);
+}
+
+template<typename _Func>
+typename CellStoreType::const_iterator
+ParseFormula(
+    const CellStoreType::const_iterator& itPos, const CellStoreType& rStore,
+    SCROW nStart, SCROW nEnd, _Func& rFunc)
+{
+    FuncElseNoOp<size_t> aElse;
+    return ParseElements1<CellStoreType, formula_block, _Func, FuncElseNoOp<size_t> >(
+        itPos, rStore, nStart, nEnd, rFunc, aElse);
+}
+
+template<typename _FuncElem, typename _FuncElse>
+typename CellStoreType::const_iterator
+ParseAll(
+    const typename CellStoreType::const_iterator& itPos, const CellStoreType& rCells,
+    SCROW nRow1, SCROW nRow2, _FuncElem& rFuncElem, _FuncElse& rFuncElse)
+{
+    return ParseElements4<CellStoreType,
+        numeric_block, string_block, edittext_block, formula_block,
+        _FuncElem, _FuncElse>(
+            itPos, rCells, nRow1, nRow2, rFuncElem, rFuncElse);
+}
+
+template<typename _Func>
+typename CellStoreType::const_iterator
+ParseAllNonEmpty(
+    const typename CellStoreType::const_iterator& itPos, const CellStoreType& rCells,
+    SCROW nRow1, SCROW nRow2, _Func& rFunc)
+{
+    FuncElseNoOp<size_t> aElse;
+    return ParseElements4<CellStoreType,
+        numeric_block, string_block, edittext_block, formula_block,
+        _Func, FuncElseNoOp<size_t> >(
+            itPos, rCells, nRow1, nRow2, rFunc, aElse);
+}
+
+template<typename _Func>
+typename CellStoreType::const_iterator
+ParseFormulaNumeric(
+    const CellStoreType::const_iterator& itPos, const CellStoreType& rCells,
+    SCROW nRow1, SCROW nRow2, _Func& rFunc)
+{
+    FuncElseNoOp<size_t> aElse;
+    return ParseElements2<CellStoreType,
+        numeric_block, formula_block, _Func, FuncElseNoOp<size_t> >(
+            itPos, rCells, nRow1, nRow2, rFunc, aElse);
+}
+
+template<typename _Func>
+void ProcessFormulaEditText(CellStoreType& rStore, _Func& rFunc)
+{
+    FuncElseNoOp<size_t> aElse;
+    ProcessElements2<CellStoreType, edittext_block, formula_block, _Func, FuncElseNoOp<size_t> >(rStore, rFunc, aElse);
+}
+
+template<typename _Func>
+std::pair<CellStoreType::const_iterator, size_t>
+FindFormula(const CellStoreType& rStore, SCROW nRow1, SCROW nRow2, _Func& rFunc)
+{
+    typedef std::pair<size_t,bool> ElseRetType;
+    FuncElseNoOp<size_t, ElseRetType> aElse;
+    return FindElement1<CellStoreType, formula_block, _Func, FuncElseNoOp<size_t, ElseRetType> >(rStore, nRow1, nRow2, rFunc, aElse);
+}
+
+template<typename _Func>
+std::pair<CellStoreType::const_iterator, size_t>
+FindFormulaEditText(const CellStoreType& rStore, SCROW nRow1, SCROW nRow2, _Func& rFunc)
+{
+    return FindElement2<CellStoreType, edittext_block, formula_block, _Func, _Func>(rStore, nRow1, nRow2, rFunc, rFunc);
+}
+
+}
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/inc/mtvelements.hxx b/sc/inc/mtvelements.hxx
index 941c1a24a..0ebf8be 100644
--- a/sc/inc/mtvelements.hxx
+++ b/sc/inc/mtvelements.hxx
@@ -54,7 +54,9 @@ const mdds::mtv::element_t element_type_string = mdds::mtv::element_type_user_st
 const mdds::mtv::element_t element_type_edittext = mdds::mtv::element_type_user_start + 3;
 const mdds::mtv::element_t element_type_formula = mdds::mtv::element_type_user_start + 4;
 
+// Mapped standard element types (for convenience).
 const mdds::mtv::element_t element_type_numeric = mdds::mtv::element_type_numeric;
+const mdds::mtv::element_t element_type_empty = mdds::mtv::element_type_empty;
 
 // Custom element blocks.
 
@@ -64,6 +66,9 @@ typedef mdds::mtv::default_element_block<element_type_string, rtl::OUString> str
 typedef mdds::mtv::noncopyable_managed_element_block<element_type_edittext, EditTextObject> edittext_block;
 typedef mdds::mtv::noncopyable_managed_element_block<element_type_formula, ScFormulaCell> formula_block;
 
+// Mapped standard element blocks (for convenience).
+typedef mdds::mtv::numeric_element_block numeric_block;
+
 // This needs to be in the same namespace as CellTextAttr.
 MDDS_MTV_DEFINE_ELEMENT_CALLBACKS(CellTextAttr, element_type_celltextattr, CellTextAttr(), celltextattr_block)
 
@@ -83,18 +88,15 @@ MDDS_MTV_DEFINE_ELEMENT_CALLBACKS(OUString, sc::element_type_string, OUString(),
 namespace sc {
 
 // Broadcaster storage container
-typedef mdds::mtv::custom_block_func1<sc::element_type_broadcaster, sc::broadcaster_block> BCBlkFunc;
+typedef mdds::mtv::custom_block_func1<sc::broadcaster_block> BCBlkFunc;
 typedef mdds::multi_type_vector<BCBlkFunc> BroadcasterStoreType;
 
 // Cell text attribute container.
-typedef mdds::mtv::custom_block_func1<sc::element_type_celltextattr, sc::celltextattr_block> CTAttrFunc;
+typedef mdds::mtv::custom_block_func1<sc::celltextattr_block> CTAttrFunc;
 typedef mdds::multi_type_vector<CTAttrFunc> CellTextAttrStoreType;
 
 // Cell container
-typedef mdds::mtv::custom_block_func3<
-    sc::element_type_string, sc::string_block,
-    sc::element_type_edittext, sc::edittext_block,
-    sc::element_type_formula, sc::formula_block> CellFunc;
+typedef mdds::mtv::custom_block_func3<sc::string_block, sc::edittext_block, sc::formula_block> CellFunc;
 typedef mdds::multi_type_vector<CellFunc> CellStoreType;
 
 /**
@@ -104,6 +106,18 @@ struct ColumnBlockPosition
 {
     BroadcasterStoreType::iterator miBroadcasterPos;
     CellTextAttrStoreType::iterator miCellTextAttrPos;
+    CellStoreType::iterator miCellPos;
+
+    ColumnBlockPosition& operator= (const ColumnBlockPosition& r);
+};
+
+struct ColumnBlockConstPosition
+{
+    BroadcasterStoreType::const_iterator miBroadcasterPos;
+    CellTextAttrStoreType::const_iterator miCellTextAttrPos;
+    CellStoreType::const_iterator miCellPos;
+
+    ColumnBlockConstPosition& operator= (const ColumnBlockConstPosition& r);
 };
 
 class ColumnBlockPositionSet
@@ -125,3 +139,4 @@ public:
 #endif
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
+
diff --git a/sc/inc/mtvfunctions.hxx b/sc/inc/mtvfunctions.hxx
new file mode 100644
index 0000000..03cb55a
--- /dev/null
+++ b/sc/inc/mtvfunctions.hxx
@@ -0,0 +1,786 @@
+/* -*- 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/.
+ */
+
+#ifndef SC_MTVFUNCTIONS_HXX
+#define SC_MTVFUNCTIONS_HXX
+
+#include <cstdlib>
+#include <mdds/multi_type_vector_types.hpp>
+
+namespace sc {
+
+template<typename _SizeT, typename _Ret = bool>
+struct FuncElseNoOp
+{
+    _Ret operator() (mdds::mtv::element_t, _SizeT, _SizeT) const
+    {
+        return _Ret();
+    }
+};
+
+/**
+ * Generic algorithm to parse blocks of multi_type_vector either partially
+ * or fully.
+ */
+template<typename _StoreT, typename _Func>
+typename _StoreT::const_iterator
+ParseBlock(
+    const typename _StoreT::const_iterator& itPos, const _StoreT& rStore, _Func& rFunc,
+    typename _StoreT::size_type nStart, typename _StoreT::size_type nEnd)
+{
+    typedef std::pair<typename _StoreT::const_iterator, typename _StoreT::size_type> PositionType;
+
+    PositionType aPos = rStore.position(itPos, nStart);
+    typename _StoreT::const_iterator it = aPos.first;
+    typename _StoreT::size_type nOffset = aPos.second;
+    typename _StoreT::size_type nDataSize = 0;
+    typename _StoreT::size_type nTopRow = nStart;
+
+    for (; it != rStore.end() && nTopRow <= nEnd; ++it, nOffset = 0, nTopRow += nDataSize)
+    {
+        bool bLastBlock = false;
+        nDataSize = it->size - nOffset;
+        if (nTopRow + nDataSize - 1 > nEnd)
+        {
+            // Truncate the block.
+            nDataSize = nEnd - nTopRow + 1;
+            bLastBlock = true;
+        }
+
+        rFunc(*it, nOffset, nDataSize);
+
+        if (bLastBlock)
+            break;
+    }
+
+    return it;
+}
+
+/**
+ * Non-const variant of the above function. TODO: Find a way to merge these
+ * two in an elegant way.
+ */
+template<typename _StoreT, typename _Func>
+typename _StoreT::iterator
+ProcessBlock(const typename _StoreT::iterator& itPos, _StoreT& rStore, _Func& rFunc, typename _StoreT::size_type nStart, typename _StoreT::size_type nEnd)
+{
+    typedef std::pair<typename _StoreT::iterator, typename _StoreT::size_type> PositionType;
+
+    PositionType aPos = rStore.position(itPos, nStart);
+    typename _StoreT::iterator it = aPos.first;
+    typename _StoreT::size_type nOffset = aPos.second;
+    typename _StoreT::size_type nDataSize = 0;
+    typename _StoreT::size_type nCurRow = nStart;
+
+    for (; it != rStore.end() && nCurRow <= nEnd; ++it, nOffset = 0, nCurRow += nDataSize)
+    {
+        bool bLastBlock = false;
+        nDataSize = it->size - nOffset;
+        if (nCurRow + nDataSize - 1 > nEnd)
+        {
+            // Truncate the block.
+            nDataSize = nEnd - nCurRow + 1;
+            bLastBlock = true;
+        }
+
+        rFunc(*it, nOffset, nDataSize);
+
+        if (bLastBlock)
+            break;
+    }
+
+    return it;
+}
+
+template<typename _StoreT, typename _BlkT, typename _FuncElem, typename _FuncElse>
+void ParseElements1(const _StoreT& rStore, _FuncElem& rFuncElem, _FuncElse& rFuncElse)
+{
+    typename _StoreT::size_type nTopRow = 0, nDataSize = 0;
+    typename _StoreT::const_iterator it = rStore.begin(), itEnd = rStore.end();
+    for (; it != itEnd; ++it, nTopRow += nDataSize)
+    {
+        nDataSize = it->size;
+        if (it->type != _BlkT::block_type)
+        {
+            rFuncElse(it->type, nTopRow, nDataSize);
+            continue;
+        }
+
+        typename _BlkT::const_iterator itf    = _BlkT::begin(*it->data);
+        typename _BlkT::const_iterator itfEnd = _BlkT::end(*it->data);
+        typename _StoreT::size_type nRow = nTopRow;
+        for (; itf != itfEnd; ++itf, ++nRow)
+            rFuncElem(nRow, *itf);
+    }
+}
+
+template<typename _StoreT, typename _BlkT, typename _FuncElem, typename _FuncElse>
+typename _StoreT::const_iterator
+ParseElements1(
+    const typename _StoreT::const_iterator& itPos, const _StoreT& rStore,
+    typename _StoreT::size_type nStart, typename _StoreT::size_type nEnd,
+    _FuncElem& rFuncElem, _FuncElse& rFuncElse)
+{
+    typedef std::pair<typename _StoreT::const_iterator, typename _StoreT::size_type> PositionType;
+
+    PositionType aPos = rStore.position(itPos, nStart);
+    typename _StoreT::const_iterator it = aPos.first;
+    typename _StoreT::size_type nOffset = aPos.second;
+    typename _StoreT::size_type nDataSize = 0;
+    typename _StoreT::size_type nTopRow = nStart;
+
+    for (; it != rStore.end() && nTopRow <= nEnd; ++it, nOffset = 0, nTopRow += nDataSize)
+    {
+        bool bLastBlock = false;
+        nDataSize = it->size - nOffset;
+        if (nTopRow + nDataSize - 1 > nEnd)
+        {
+            // Truncate the block.
+            nDataSize = nEnd - nTopRow + 1;
+            bLastBlock = true;
+        }
+
+        if (it->type == _BlkT::block_type)
+        {
+            typename _BlkT::const_iterator itf    = _BlkT::begin(*it->data);
+            std::advance(itf, nOffset);
+            typename _BlkT::const_iterator itfEnd = itf;
+            std::advance(itfEnd, nDataSize);
+            typename _StoreT::size_type nRow = nTopRow;
+            for (; itf != itfEnd; ++itf, ++nRow)
+                rFuncElem(nRow, *itf);
+        }
+        else
+            rFuncElse(it->type, nTopRow, nDataSize);
+
+
+        if (bLastBlock)
+            break;
+    }
+
+    return it;
+};
+
+template<typename _StoreT, typename _Blk1, typename _Blk2, typename _FuncElem, typename _FuncElse>
+typename _StoreT::const_iterator
+ParseElements2(
+    const typename _StoreT::const_iterator& itPos, const _StoreT& rStore, typename _StoreT::size_type nStart, typename _StoreT::size_type nEnd,
+    _FuncElem& rFuncElem, _FuncElse& rFuncElse)
+{
+    typedef std::pair<typename _StoreT::const_iterator, typename _StoreT::size_type> PositionType;
+
+    PositionType aPos = rStore.position(itPos, nStart);
+    typename _StoreT::const_iterator it = aPos.first;
+    typename _StoreT::size_type nOffset = aPos.second;
+    typename _StoreT::size_type nDataSize = 0;
+    typename _StoreT::size_type nTopRow = nStart;
+
+    for (; it != rStore.end() && nTopRow <= nEnd; ++it, nOffset = 0, nTopRow += nDataSize)
+    {
+        bool bLastBlock = false;
+        nDataSize = it->size - nOffset;
+        if (nTopRow + nDataSize - 1 > nEnd)
+        {
+            // Truncate the block.
+            nDataSize = nEnd - nTopRow + 1;
+            bLastBlock = true;
+        }
+
+        switch (it->type)
+        {
+            case _Blk1::block_type:
+            {
+                typename _Blk1::const_iterator itData = _Blk1::begin(*it->data);
+                std::advance(itData, nOffset);
+                typename _Blk1::const_iterator itDataEnd = itData;
+                std::advance(itDataEnd, nDataSize);
+                typename _StoreT::size_type nRow = nTopRow;
+                for (; itData != itDataEnd; ++itData, ++nRow)
+                    rFuncElem(nRow, *itData);
+            }
+            break;
+            case _Blk2::block_type:
+            {
+                typename _Blk2::const_iterator itData = _Blk2::begin(*it->data);
+                std::advance(itData, nOffset);
+                typename _Blk2::const_iterator itDataEnd = itData;
+                std::advance(itDataEnd, nDataSize);
+                typename _StoreT::size_type nRow = nTopRow;
+                for (; itData != itDataEnd; ++itData, ++nRow)
+                    rFuncElem(nRow, *itData);
+            }
+            break;
+            default:
+                rFuncElse(it->type, nTopRow, nDataSize);
+        }
+
+        if (bLastBlock)
+            break;
+    }
+
+    return it;
+}
+
+template<typename _StoreT, typename _Blk1, typename _Blk2, typename _Blk3, typename _Blk4, typename _FuncElem, typename _FuncElse>
+typename _StoreT::const_iterator
+ParseElements4(
+    const typename _StoreT::const_iterator& itPos, const _StoreT& rStore, typename _StoreT::size_type nStart, typename _StoreT::size_type nEnd,
+    _FuncElem& rFuncElem, _FuncElse& rFuncElse)
+{
+    typedef std::pair<typename _StoreT::const_iterator, typename _StoreT::size_type> PositionType;
+
+    PositionType aPos = rStore.position(itPos, nStart);
+    typename _StoreT::const_iterator it = aPos.first;
+    typename _StoreT::size_type nOffset = aPos.second;
+    typename _StoreT::size_type nDataSize = 0;
+    typename _StoreT::size_type nTopRow = nStart;
+
+    for (; it != rStore.end() && nTopRow <= nEnd; ++it, nOffset = 0, nTopRow += nDataSize)
+    {
+        bool bLastBlock = false;
+        nDataSize = it->size - nOffset;
+        if (nTopRow + nDataSize - 1 > nEnd)
+        {
+            // Truncate the block.
+            nDataSize = nEnd - nTopRow + 1;
+            bLastBlock = true;
+        }
+
+        switch (it->type)
+        {
+            case _Blk1::block_type:
+            {
+                typename _Blk1::const_iterator itData = _Blk1::begin(*it->data);
+                std::advance(itData, nOffset);
+                typename _Blk1::const_iterator itDataEnd = itData;
+                std::advance(itDataEnd, nDataSize);
+                typename _StoreT::size_type nRow = nTopRow;
+                for (; itData != itDataEnd; ++itData, ++nRow)
+                    rFuncElem(nRow, *itData);
+            }
+            break;
+            case _Blk2::block_type:
+            {
+                typename _Blk2::const_iterator itData = _Blk2::begin(*it->data);
+                std::advance(itData, nOffset);
+                typename _Blk2::const_iterator itDataEnd = itData;
+                std::advance(itDataEnd, nDataSize);
+                typename _StoreT::size_type nRow = nTopRow;
+                for (; itData != itDataEnd; ++itData, ++nRow)
+                    rFuncElem(nRow, *itData);
+            }
+            break;
+            case _Blk3::block_type:
+            {
+                typename _Blk3::const_iterator itData = _Blk3::begin(*it->data);
+                std::advance(itData, nOffset);
+                typename _Blk3::const_iterator itDataEnd = itData;
+                std::advance(itDataEnd, nDataSize);
+                typename _StoreT::size_type nRow = nTopRow;
+                for (; itData != itDataEnd; ++itData, ++nRow)
+                    rFuncElem(nRow, *itData);
+            }
+            break;
+            case _Blk4::block_type:
+            {
+                typename _Blk4::const_iterator itData = _Blk4::begin(*it->data);
+                std::advance(itData, nOffset);
+                typename _Blk4::const_iterator itDataEnd = itData;
+                std::advance(itDataEnd, nDataSize);
+                typename _StoreT::size_type nRow = nTopRow;
+                for (; itData != itDataEnd; ++itData, ++nRow)
+                    rFuncElem(nRow, *itData);
+            }
+            break;
+            default:
+                rFuncElse(it->type, nTopRow, nDataSize);
+        }
+
+        if (bLastBlock)
+            break;
+    }
+
+    return it;
+}
+
+template<typename _StoreT, typename _BlkT, typename _FuncElem, typename _FuncElse>
+void ProcessElements1(_StoreT& rStore, _FuncElem& rFuncElem, _FuncElse& rFuncElse)
+{
+    typename _StoreT::size_type nTopRow = 0, nDataSize = 0;
+    typename _StoreT::iterator it = rStore.begin(), itEnd = rStore.end();
+    for (; it != itEnd; ++it, nTopRow += nDataSize)
+    {
+        nDataSize = it->size;
+        if (it->type != _BlkT::block_type)
+        {
+            rFuncElse(it->type, nTopRow, nDataSize);
+            continue;
+        }
+
+        typename _BlkT::iterator itf    = _BlkT::begin(*it->data);
+        typename _BlkT::iterator itfEnd = _BlkT::end(*it->data);
+        typename _StoreT::size_type nRow = nTopRow;
+        for (; itf != itfEnd; ++itf, ++nRow)
+            rFuncElem(nRow, *itf);
+    }
+}
+
+/**
+ * This variant specifies start and end positions.
+ */
+template<typename _StoreT, typename _BlkT, typename _FuncElem, typename _FuncElse>
+typename _StoreT::iterator
+ProcessElements1(
+    const typename _StoreT::iterator& itPos, _StoreT& rStore,
+    typename _StoreT::size_type nStart, typename _StoreT::size_type nEnd,
+    _FuncElem& rFuncElem, _FuncElse& rFuncElse)
+{
+    typedef std::pair<typename _StoreT::iterator, typename _StoreT::size_type> PositionType;
+
+    PositionType aPos = rStore.position(itPos, nStart);
+    typename _StoreT::iterator it = aPos.first;
+    typename _StoreT::size_type nOffset = aPos.second;
+    typename _StoreT::size_type nDataSize = 0;
+    typename _StoreT::size_type nTopRow = nStart;
+
+    for (; it != rStore.end() && nTopRow <= nEnd; ++it, nOffset = 0, nTopRow += nDataSize)
+    {
+        bool bLastBlock = false;
+        nDataSize = it->size - nOffset;
+        if (nTopRow + nDataSize - 1 > nEnd)
+        {
+            // Truncate the block.
+            nDataSize = nEnd - nTopRow + 1;
+            bLastBlock = true;
+        }
+
+        if (it->type == _BlkT::block_type)
+        {
+            typename _BlkT::iterator itf    = _BlkT::begin(*it->data);
+            std::advance(itf, nOffset);
+            typename _BlkT::iterator itfEnd = itf;
+            std::advance(itfEnd, nDataSize);
+            typename _StoreT::size_type nRow = nTopRow;
+            for (; itf != itfEnd; ++itf, ++nRow)
+                rFuncElem(nRow, *itf);
+        }
+        else
+            rFuncElse(it->type, nTopRow, nDataSize);
+
+        if (bLastBlock)
+            break;
+    }
+
+    return it;
+};
+
+template<typename _StoreT, typename _Blk1, typename _Blk2, typename _FuncElem, typename _FuncElse>
+void ProcessElements2(_StoreT& rStore, _FuncElem& rFuncElem, _FuncElse& rFuncElse)
+{
+    typename _StoreT::size_type nTopRow = 0, nDataSize = 0;
+    typename _StoreT::iterator it = rStore.begin(), itEnd = rStore.end();
+    for (; it != itEnd; ++it, nTopRow += nDataSize)
+    {
+        nDataSize = it->size;
+        switch (it->type)
+        {
+            case _Blk1::block_type:
+            {
+                typename _Blk1::iterator itData    = _Blk1::begin(*it->data);
+                typename _Blk1::iterator itDataEnd = _Blk1::end(*it->data);
+                typename _StoreT::size_type nRow = nTopRow;
+                for (; itData != itDataEnd; ++itData, ++nRow)
+                    rFuncElem(nRow, *itData);
+            }
+            break;
+            case _Blk2::block_type:
+            {
+                typename _Blk2::iterator itData    = _Blk2::begin(*it->data);
+                typename _Blk2::iterator itDataEnd = _Blk2::end(*it->data);
+                typename _StoreT::size_type nRow = nTopRow;
+                for (; itData != itDataEnd; ++itData, ++nRow)
+                    rFuncElem(nRow, *itData);
+            }
+            break;
+            default:
+                rFuncElse(it->type, nTopRow, nDataSize);
+        }
+    }
+}
+
+template<typename _StoreT, typename _Blk1, typename _Blk2, typename _FuncElem, typename _FuncElse>
+typename _StoreT::iterator
+ProcessElements2(
+    const typename _StoreT::iterator& itPos, _StoreT& rStore,
+    typename _StoreT::size_type nStart, typename _StoreT::size_type nEnd,
+    _FuncElem& rFuncElem, _FuncElse& rFuncElse)
+{
+    typedef std::pair<typename _StoreT::iterator, typename _StoreT::size_type> PositionType;
+
+    PositionType aPos = rStore.position(itPos, nStart);
+    typename _StoreT::iterator it = aPos.first;
+    typename _StoreT::size_type nOffset = aPos.second;
+    typename _StoreT::size_type nDataSize = 0;
+    typename _StoreT::size_type nTopRow = nStart;
+
+    for (; it != rStore.end() && nTopRow <= nEnd; ++it, nOffset = 0, nTopRow += nDataSize)
+    {
+        bool bLastBlock = false;
+        nDataSize = it->size - nOffset;
+        if (nTopRow + nDataSize - 1 > nEnd)
+        {
+            // Truncate the block.
+            nDataSize = nEnd - nTopRow + 1;
+            bLastBlock = true;
+        }
+
+        switch (it->type)
+        {
+            case _Blk1::block_type:
+            {
+                typename _Blk1::iterator itData = _Blk1::begin(*it->data);
+                std::advance(itData, nOffset);
+                typename _Blk1::iterator itDataEnd = itData;
+                std::advance(itDataEnd, nDataSize);
+                typename _StoreT::size_type nRow = nTopRow;
+                for (; itData != itDataEnd; ++itData, ++nRow)
+                    rFuncElem(nRow, *itData);
+            }
+            break;
+            case _Blk2::block_type:
+            {
+                typename _Blk2::iterator itData = _Blk2::begin(*it->data);
+                std::advance(itData, nOffset);
+                typename _Blk2::iterator itDataEnd = itData;
+                std::advance(itDataEnd, nDataSize);
+                typename _StoreT::size_type nRow = nTopRow;
+                for (; itData != itDataEnd; ++itData, ++nRow)
+                    rFuncElem(nRow, *itData);
+            }
+            break;
+            default:
+                rFuncElse(it->type, nTopRow, nDataSize);
+        }
+
+        if (bLastBlock)
+            break;
+    }
+
+    return it;
+}
+
+template<typename _StoreT, typename _Blk1, typename _Blk2, typename _Blk3, typename _FuncElem, typename _FuncElse>
+void ProcessElements3(_StoreT& rStore, _FuncElem& rFuncElem, _FuncElse& rFuncElse)
+{
+    typename _StoreT::size_type nTopRow = 0, nDataSize = 0;
+    typename _StoreT::iterator it = rStore.begin(), itEnd = rStore.end();
+    for (; it != itEnd; ++it, nTopRow += nDataSize)
+    {
+        nDataSize = it->size;
+        switch (it->type)
+        {
+            case _Blk1::block_type:
+            {
+                typename _Blk1::iterator itData    = _Blk1::begin(*it->data);
+                typename _Blk1::iterator itDataEnd = _Blk1::end(*it->data);
+                typename _StoreT::size_type nRow = nTopRow;
+                for (; itData != itDataEnd; ++itData, ++nRow)
+                    rFuncElem(nRow, *itData);
+            }
+            break;
+            case _Blk2::block_type:
+            {
+                typename _Blk2::iterator itData    = _Blk2::begin(*it->data);
+                typename _Blk2::iterator itDataEnd = _Blk2::end(*it->data);
+                typename _StoreT::size_type nRow = nTopRow;
+                for (; itData != itDataEnd; ++itData, ++nRow)
+                    rFuncElem(nRow, *itData);
+            }
+            break;
+            case _Blk3::block_type:
+            {
+                typename _Blk3::iterator itData    = _Blk3::begin(*it->data);
+                typename _Blk3::iterator itDataEnd = _Blk3::end(*it->data);
+                typename _StoreT::size_type nRow = nTopRow;
+                for (; itData != itDataEnd; ++itData, ++nRow)
+                    rFuncElem(nRow, *itData);
+            }
+            break;
+            default:
+                rFuncElse(it->type, nTopRow, nDataSize);
+        }
+    }
+}
+
+template<typename _StoreT, typename _Blk1, typename _Blk2, typename _Blk3, typename _Blk4, typename _FuncElem, typename _FuncElse>
+void ProcessElements4(_StoreT& rStore, _FuncElem& rFuncElem, _FuncElse& rFuncElse)
+{
+    typename _StoreT::size_type nTopRow = 0, nDataSize = 0;
+    typename _StoreT::iterator it = rStore.begin(), itEnd = rStore.end();
+    for (; it != itEnd; ++it, nTopRow += nDataSize)
+    {
+        nDataSize = it->size;
+        switch (it->type)
+        {
+            case _Blk1::block_type:
+            {
+                typename _Blk1::iterator itData    = _Blk1::begin(*it->data);
+                typename _Blk1::iterator itDataEnd = _Blk1::end(*it->data);
+                typename _StoreT::size_type nRow = nTopRow;
+                for (; itData != itDataEnd; ++itData, ++nRow)
+                    rFuncElem(nRow, *itData);
+            }
+            break;
+            case _Blk2::block_type:
+            {
+                typename _Blk2::iterator itData    = _Blk2::begin(*it->data);
+                typename _Blk2::iterator itDataEnd = _Blk2::end(*it->data);
+                typename _StoreT::size_type nRow = nTopRow;
+                for (; itData != itDataEnd; ++itData, ++nRow)
+                    rFuncElem(nRow, *itData);
+            }
+            break;
+            case _Blk3::block_type:
+            {
+                typename _Blk3::iterator itData    = _Blk3::begin(*it->data);
+                typename _Blk3::iterator itDataEnd = _Blk3::end(*it->data);
+                typename _StoreT::size_type nRow = nTopRow;
+                for (; itData != itDataEnd; ++itData, ++nRow)
+                    rFuncElem(nRow, *itData);
+            }
+            break;
+            case _Blk4::block_type:
+            {
+                typename _Blk4::iterator itData    = _Blk4::begin(*it->data);
+                typename _Blk4::iterator itDataEnd = _Blk4::end(*it->data);
+                typename _StoreT::size_type nRow = nTopRow;
+                for (; itData != itDataEnd; ++itData, ++nRow)
+                    rFuncElem(nRow, *itData);
+            }
+            break;
+            default:
+                rFuncElse(it->type, nTopRow, nDataSize);
+        }
+    }
+}
+
+template<typename _StoreT, typename _Blk1, typename _Blk2, typename _Blk3, typename _Blk4, typename _FuncElem, typename _FuncElse>
+typename _StoreT::iterator
+ProcessElements4(
+    const typename _StoreT::iterator& itPos, _StoreT& rStore,
+    typename _StoreT::size_type nStart, typename _StoreT::size_type nEnd,
+    _FuncElem& rFuncElem, _FuncElse& rFuncElse)
+{
+    typedef std::pair<typename _StoreT::iterator, typename _StoreT::size_type> PositionType;
+
+    PositionType aPos = rStore.position(itPos, nStart);
+    typename _StoreT::iterator it = aPos.first;
+    typename _StoreT::size_type nOffset = aPos.second;
+    typename _StoreT::size_type nDataSize = 0;
+    typename _StoreT::size_type nTopRow = nStart;
+
+    for (; it != rStore.end() && nTopRow <= nEnd; ++it, nOffset = 0, nTopRow += nDataSize)
+    {
+        bool bLastBlock = false;
+        nDataSize = it->size - nOffset;
+        if (nTopRow + nDataSize - 1 > nEnd)
+        {
+            // Truncate the block.
+            nDataSize = nEnd - nTopRow + 1;
+            bLastBlock = true;
+        }
+
+        switch (it->type)
+        {
+            case _Blk1::block_type:
+            {
+                typename _Blk1::iterator itData = _Blk1::begin(*it->data);
+                std::advance(itData, nOffset);
+                typename _Blk1::iterator itDataEnd = itData;
+                std::advance(itDataEnd, nDataSize);
+                typename _StoreT::size_type nRow = nTopRow;
+                for (; itData != itDataEnd; ++itData, ++nRow)
+                    rFuncElem(nRow, *itData);
+            }
+            break;
+            case _Blk2::block_type:
+            {
+                typename _Blk2::iterator itData = _Blk2::begin(*it->data);
+                std::advance(itData, nOffset);
+                typename _Blk2::iterator itDataEnd = itData;
+                std::advance(itDataEnd, nDataSize);
+                typename _StoreT::size_type nRow = nTopRow;
+                for (; itData != itDataEnd; ++itData, ++nRow)
+                    rFuncElem(nRow, *itData);
+            }
+            break;
+            case _Blk3::block_type:
+            {
+                typename _Blk3::iterator itData = _Blk3::begin(*it->data);
+                std::advance(itData, nOffset);
+                typename _Blk3::iterator itDataEnd = itData;
+                std::advance(itDataEnd, nDataSize);
+                typename _StoreT::size_type nRow = nTopRow;
+                for (; itData != itDataEnd; ++itData, ++nRow)
+                    rFuncElem(nRow, *itData);
+            }
+            break;
+            case _Blk4::block_type:
+            {
+                typename _Blk4::iterator itData = _Blk4::begin(*it->data);
+                std::advance(itData, nOffset);
+                typename _Blk4::iterator itDataEnd = itData;
+                std::advance(itDataEnd, nDataSize);
+                typename _StoreT::size_type nRow = nTopRow;
+                for (; itData != itDataEnd; ++itData, ++nRow)
+                    rFuncElem(nRow, *itData);
+            }
+            break;
+            default:
+                rFuncElse(it->type, nTopRow, nDataSize);
+        }
+
+        if (bLastBlock)
+            break;
+    }
+
+    return it;
+}
+
+template<typename _StoreT, typename _Blk1, typename _FuncElem, typename _FuncElse>
+std::pair<typename _StoreT::const_iterator, typename _StoreT::size_type>
+FindElement1(
+    const _StoreT& rStore, typename _StoreT::size_type nStart, typename _StoreT::size_type nEnd,
+    _FuncElem& rFuncElem, _FuncElse& rFuncElse)
+{
+    typedef std::pair<typename _StoreT::const_iterator, typename _StoreT::size_type> PositionType;
+    typedef std::pair<typename _StoreT::size_type, bool> ElseRetType;
+
+    PositionType aPos = rStore.position(nStart);
+    typename _StoreT::const_iterator it = aPos.first;
+    typename _StoreT::size_type nOffset = aPos.second;
+    typename _StoreT::size_type nDataSize = 0;
+    typename _StoreT::size_type nTopRow = nStart;
+
+    for (; it != rStore.end() && nTopRow <= nEnd; ++it, nOffset = 0, nTopRow += nDataSize)
+    {
+        bool bLastBlock = false;
+        nDataSize = it->size - nOffset;
+        if (nTopRow + nDataSize - 1 > nEnd)
+        {
+            // Truncate the block.
+            nDataSize = nEnd - nTopRow + 1;
+            bLastBlock = true;
+        }
+
+        switch (it->type)
+        {
+            case _Blk1::block_type:
+            {
+                typename _Blk1::const_iterator itData = _Blk1::begin(*it->data);
+                std::advance(itData, nOffset);
+                typename _Blk1::const_iterator itDataEnd = itData;
+                std::advance(itDataEnd, nDataSize);
+                typename _StoreT::size_type nRow = nTopRow;
+                for (; itData != itDataEnd; ++itData, ++nRow)
+                {
+                    if (rFuncElem(nRow, *itData))
+                        return PositionType(it, nRow-nTopRow);
+                }
+            }
+            break;
+            default:
+            {
+                ElseRetType aRet = rFuncElse(it->type, nTopRow, nDataSize);
+                if (aRet.second)
+                    return PositionType(it, aRet.first);
+            }
+        }
+
+        if (bLastBlock)
+            break;
+    }
+
+    return PositionType(rStore.end(), 0);
+}
+
+template<typename _StoreT, typename _Blk1, typename _Blk2, typename _FuncElem, typename _FuncElse>
+std::pair<typename _StoreT::const_iterator, typename _StoreT::size_type>
+FindElement2(
+    const _StoreT& rStore, typename _StoreT::size_type nStart, typename _StoreT::size_type nEnd,
+    _FuncElem& rFuncElem, _FuncElse& rFuncElse)
+{
+    typedef std::pair<typename _StoreT::const_iterator, typename _StoreT::size_type> PositionType;
+    typedef std::pair<typename _StoreT::size_type, bool> ElseRetType;
+
+    PositionType aPos = rStore.position(nStart);
+    typename _StoreT::const_iterator it = aPos.first;
+    typename _StoreT::size_type nOffset = aPos.second;
+    typename _StoreT::size_type nDataSize = 0;
+    typename _StoreT::size_type nTopRow = nStart;
+
+    for (; it != rStore.end() && nTopRow <= nEnd; ++it, nOffset = 0, nTopRow += nDataSize)
+    {
+        bool bLastBlock = false;
+        nDataSize = it->size - nOffset;
+        if (nTopRow + nDataSize - 1 > nEnd)
+        {
+            // Truncate the block.
+            nDataSize = nEnd - nTopRow + 1;
+            bLastBlock = true;
+        }
+
+        switch (it->type)
+        {
+            case _Blk1::block_type:
+            {
+                typename _Blk1::const_iterator itData = _Blk1::begin(*it->data);
+                std::advance(itData, nOffset);
+                typename _Blk1::const_iterator itDataEnd = itData;
+                std::advance(itDataEnd, nDataSize);
+                typename _StoreT::size_type nRow = nTopRow;
+                for (; itData != itDataEnd; ++itData, ++nRow)
+                {
+                    if (rFuncElem(nRow, *itData))
+                        return PositionType(it, nRow-nTopRow);
+                }
+            }
+            break;
+            case _Blk2::block_type:
+            {
+                typename _Blk2::const_iterator itData = _Blk2::begin(*it->data);
+                std::advance(itData, nOffset);
+                typename _Blk2::const_iterator itDataEnd = itData;
+                std::advance(itDataEnd, nDataSize);
+                typename _StoreT::size_type nRow = nTopRow;
+                for (; itData != itDataEnd; ++itData, ++nRow)
+                    if (rFuncElem(nRow, *itData))
+                        return PositionType(it, nRow-nTopRow);
+            }
+            break;
+            default:
+            {
+                ElseRetType aRet = rFuncElse(it->type, nTopRow, nDataSize);
+                if (aRet.second)
+                    return PositionType(it, aRet.first);
+            }
+        }
+
+        if (bLastBlock)
+            break;
+    }
+
+    return PositionType(rStore.end(), 0);
+}
+
+}
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/inc/scopetools.hxx b/sc/inc/scopetools.hxx
new file mode 100644
index 0000000..590ccbf
--- /dev/null
+++ b/sc/inc/scopetools.hxx
@@ -0,0 +1,33 @@
+/* -*- 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/.
+ */
+
+#ifndef SC_SCOPETOOLS_HXX
+#define SC_SCOPETOOLS_HXX
+
+class ScDocument;
+
+namespace sc {
+
+/**
+ * Temporarily switch on/off auto calculation mode.
+ */
+class AutoCalcSwitch
+{
+    ScDocument& mrDoc;
+    bool mbOldValue;
+public:
+    AutoCalcSwitch(ScDocument& rDoc, bool bAutoCalc);
+    ~AutoCalcSwitch();
+};
+
+}
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/inc/table.hxx b/sc/inc/table.hxx
index b62fa1e..c5c0286 100644
--- a/sc/inc/table.hxx
+++ b/sc/inc/table.hxx
@@ -30,6 +30,7 @@
 #include "compressedarray.hxx"
 #include "postit.hxx"
 #include "types.hxx"
+#include "cellvalue.hxx"
 #include "formula/types.hxx"
 
 #include <set>
@@ -65,7 +66,6 @@ class SvxBoxItem;
 class SvxSearchItem;
 
 class ScAutoFormatData;
-class ScBaseCell;
 class ScDocument;
 class ScEditDataArray;
 class ScFormulaCell;
@@ -191,7 +191,6 @@ private:
     bool            mbPageBreaksValid:1;
 
 friend class ScDocument;                    // for FillInfo
-friend class ScDocumentIterator;
 friend class ScValueIterator;
 friend class ScHorizontalValueIterator;
 friend class ScDBQueryDataIterator;
@@ -209,6 +208,10 @@ public:
                          bool bColInfo = true, bool bRowInfo = true );
                 ~ScTable();
 
+    ScDocument& GetDoc();
+    const ScDocument& GetDoc() const;
+    SCTAB GetTab() const { return nTab; }
+
     ScOutlineTable* GetOutlineTable()               { return pOutlineTable; }
 
     SCSIZE      GetCellCount(SCCOL nCol) const;
@@ -310,10 +313,6 @@ public:
 
     bool        IsBlockEmpty( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, bool bIgnoreNotes = false ) const;
 
-    void        PutCell( const ScAddress&, ScBaseCell* pCell );
-    void        PutCell( SCCOL nCol, SCROW nRow, ScBaseCell* pCell );
-    void        PutCell(SCCOL nCol, SCROW nRow, sal_uLong nFormatIndex, ScBaseCell* pCell);
-
     bool        SetString( SCCOL nCol, SCROW nRow, SCTAB nTab, const String& rString,
                            ScSetStringParam* pParam = NULL );
 
@@ -331,6 +330,7 @@ public:
     void        SetValue( SCCOL nCol, SCROW nRow, const double& rVal );
     void        SetError( SCCOL nCol, SCROW nRow, sal_uInt16 nError);
 
+    void SetRawString( SCCOL nCol, SCROW nRow, const OUString& rStr );
     void        GetString( SCCOL nCol, SCROW nRow, OUString& rString ) const;
     const OUString* GetStringCell( SCCOL nCol, SCROW nRow ) const;
     double* GetValueCell( SCCOL nCol, SCROW nRow );
@@ -356,13 +356,7 @@ public:
                             CELLTYPE_NONE;
                     }
     CellType    GetCellType( SCCOL nCol, SCROW nRow ) const;
-    ScBaseCell* GetCell( const ScAddress& rPos ) const
-                    {
-                        return ValidColRow(rPos.Col(),rPos.Row()) ?
-                            aCol[rPos.Col()].GetCell( rPos.Row() ) :
-                            NULL;
-                    }
-    ScBaseCell* GetCell( SCCOL nCol, SCROW nRow ) const;
+    ScRefCellValue GetCellValue( SCCOL nCol, SCROW nRow ) const;
 
     void        GetFirstDataPos(SCCOL& rCol, SCROW& rRow) const;
     void        GetLastDataPos(SCCOL& rCol, SCROW& rRow) const;
@@ -372,7 +366,7 @@ public:
         @param bForced  True = always create all captions, false = skip when Undo is disabled. */
     void        InitializeNoteCaptions( bool bForced = false );
 
-    bool        TestInsertRow( SCCOL nStartCol, SCCOL nEndCol, SCSIZE nSize ) const;
+    bool TestInsertRow( SCCOL nStartCol, SCCOL nEndCol, SCROW nStartRow, SCSIZE nSize ) const;
     void        InsertRow( SCCOL nStartCol, SCCOL nEndCol, SCROW nStartRow, SCSIZE nSize );
     void        DeleteRow( SCCOL nStartCol, SCCOL nEndCol, SCROW nStartRow, SCSIZE nSize,
                             bool* pUndoOutline = NULL );
@@ -480,6 +474,8 @@ public:
                             0;
                     }
 
+    bool IsEmptyData( SCCOL nCol ) const;
+
     void        ResetChanged( const ScRange& rRange );
 
     void        SetDirty();
@@ -793,8 +789,8 @@ public:
     void        ExtendHidden( SCCOL& rX1, SCROW& rY1, SCCOL& rX2, SCROW& rY2 );
 
     void        Sort(const ScSortParam& rSortParam, bool bKeepQuery, ScProgress* pProgress);
-    bool        ValidQuery(
-        SCROW nRow, const ScQueryParam& rQueryParam, ScBaseCell* pCell = NULL,
+    bool ValidQuery(
+        SCROW nRow, const ScQueryParam& rQueryParam, ScRefCellValue* pCell = NULL,
         bool* pbTestEqualCondition = NULL);
     void        TopTenQuery( ScQueryParam& );
     SCSIZE      Query(ScQueryParam& rQueryParam, bool bKeepSub);
@@ -807,9 +803,6 @@ public:
     bool        HasColHeader( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow ) const;
     bool        HasRowHeader( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow ) const;
 
-    void        DoColResize( SCCOL nCol1, SCCOL nCol2, SCSIZE nAdd );
-
-
     sal_Int32   GetMaxStringLen( SCCOL nCol,
                                     SCROW nRowStart, SCROW nRowEnd, CharSet eCharSet ) const;
     xub_StrLen  GetMaxNumberStringLen( sal_uInt16& nPrecision,
@@ -918,9 +911,10 @@ private:
     void        DecoladeRow( ScSortInfoArray*, SCROW nRow1, SCROW nRow2 );
     void        SwapCol(SCCOL nCol1, SCCOL nCol2);
     void        SwapRow(SCROW nRow1, SCROW nRow2);
-    short       CompareCell( sal_uInt16 nSort,
-                    ScBaseCell* pCell1, SCCOL nCell1Col, SCROW nCell1Row,
-                    ScBaseCell* pCell2, SCCOL nCell2Col, SCROW nCell2Row ) const;
+    short CompareCell(
+        sal_uInt16 nSort,
+        ScRefCellValue& rCell1, SCCOL nCell1Col, SCROW nCell1Row,
+        ScRefCellValue& rCell2, SCCOL nCell2Col, SCROW nCell2Row ) const;
     short       Compare(SCCOLROW nIndex1, SCCOLROW nIndex2) const;
     short       Compare( ScSortInfoArray*, SCCOLROW nIndex1, SCCOLROW nIndex2) const;
     ScSortInfoArray*    CreateSortInfoArray( SCCOLROW nInd1, SCCOLROW nInd2 );
@@ -1000,14 +994,14 @@ private:
          *
          * @return First visible data cell if found, or NULL otherwise.
          */
-        ScBaseCell* reset(SCROW nRow);
+        ScRefCellValue reset(SCROW nRow);
 
         /**
          * Find the next visible data cell position.
          *
          * @return Next visible data cell if found, or NULL otherwise.
          */
-        ScBaseCell* next();
+        ScRefCellValue next();
 
         /**
          * Get the current row position.
@@ -1020,7 +1014,7 @@ private:
     private:
         ScFlatBoolRowSegments& mrRowSegs;
         ScColumn& mrColumn;
-        ScBaseCell* mpCell;
+        ScRefCellValue maCell;
         SCROW mnCurRow;
         SCROW mnUBound;
     };
diff --git a/sc/inc/types.hxx b/sc/inc/types.hxx
index 9654271c4..629ab72 100644
--- a/sc/inc/types.hxx
+++ b/sc/inc/types.hxx
@@ -7,8 +7,8 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
  */
 
-#ifndef __SC_TYPES_HXX__
-#define __SC_TYPES_HXX__
+#ifndef SC_TYPES_HXX
+#define SC_TYPES_HXX
 
 #include <boost/intrusive_ptr.hpp>
 
@@ -36,6 +36,18 @@ enum ScFormulaVectorState
     FormulaVectorUnknown
 };
 
+namespace sc {
+
+const sal_uInt16 MatrixEdgeNothing = 0;
+const sal_uInt16 MatrixEdgeInside  = 1;
+const sal_uInt16 MatrixEdgeBottom  = 2;
+const sal_uInt16 MatrixEdgeLeft    = 4;
+const sal_uInt16 MatrixEdgeTop     = 8;
+const sal_uInt16 MatrixEdgeRight   = 16;
+const sal_uInt16 MatrixEdgeOpen    = 32;
+
+}
+
 #endif
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/qa/unit/ucalc.cxx b/sc/qa/unit/ucalc.cxx
index 12fb593..fde5c16 100644
--- a/sc/qa/unit/ucalc.cxx
+++ b/sc/qa/unit/ucalc.cxx
@@ -52,6 +52,7 @@
 #include "conditio.hxx"
 #include "globstr.hrc"
 #include "tokenarray.hxx"
+#include "scopetools.hxx"
 
 #include "formula/IFunctionDescription.hxx"
 
@@ -397,25 +398,6 @@ ScRange insertRangeData(ScDocument* pDoc, const ScAddress& rPos, const char* aDa
 }
 
 /**
- * Temporarily switch on/off auto calculation mode.
- */
-class AutoCalcSwitch
-{
-    ScDocument* mpDoc;
-    bool mbOldValue;
-public:
-    AutoCalcSwitch(ScDocument* pDoc, bool bAutoCalc) : mpDoc(pDoc), mbOldValue(pDoc->GetAutoCalc())
-    {
-        mpDoc->SetAutoCalc(bAutoCalc);
-    }
-
-    ~AutoCalcSwitch()
-    {
-        mpDoc->SetAutoCalc(mbOldValue);
-    }
-};
-
-/**
  * Temporarily set formula grammar.
  */
 class FormulaGrammarSwitch
@@ -1736,7 +1718,7 @@ void Test::testFormulaDepTracking()
 {
     CPPUNIT_ASSERT_MESSAGE ("failed to insert sheet", m_pDoc->InsertTab (0, "foo"));
 
-    AutoCalcSwitch aACSwitch(m_pDoc, true); // turn on auto calculation.
+    sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); // turn on auto calculation.
 
     // B2 listens on D2.
     m_pDoc->SetString(1, 1, 0, "=D2");
@@ -1844,7 +1826,7 @@ void Test::testFormulaDepTracking2()
 {
     CPPUNIT_ASSERT_MESSAGE ("failed to insert sheet", m_pDoc->InsertTab (0, "foo"));
 
-    AutoCalcSwitch aACSwitch(m_pDoc, true); // turn on auto calculation.
+    sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); // turn on auto calculation.
 
     double val = 2.0;
     m_pDoc->SetValue(0, 0, 0, val);
@@ -1954,7 +1936,7 @@ void Test::testCellBroadcaster()
 {
     CPPUNIT_ASSERT_MESSAGE ("failed to insert sheet", m_pDoc->InsertTab (0, "foo"));
 
-    AutoCalcSwitch aACSwitch(m_pDoc, true); // turn on auto calculation.
+    sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); // turn on auto calculation.
     m_pDoc->SetString(ScAddress(1,0,0), "=A1"); // B1 depends on A1.
     double val = m_pDoc->GetValue(ScAddress(1,0,0)); // A1 is empty, so the result should be 0.
     CPPUNIT_ASSERT_EQUAL(0.0, val);
@@ -2995,7 +2977,7 @@ void Test::testPivotTableFilters()
         CPPUNIT_ASSERT_MESSAGE("Table output check failed", bSuccess);
     }
 
-    AutoCalcSwitch aACSwitch(m_pDoc, true); // turn on auto calculation.
+    sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); // turn on auto calculation.
 
     ScAddress aFormulaAddr = aOutRange.aEnd;
     aFormulaAddr.IncRow(2);
@@ -6879,31 +6861,39 @@ void Test::testFormulaGrouping()
         const char *pFormula[3];
         bool  bGroup[3];
     } aGroupTests[] = {
-        { { "=SUM(B1)",  "=SUM(C1)",    "" },            // single increments
-          { true,        true,          false } },
-        { { "=SUM(B1)",  "=SUM(D1)",    "=SUM(F1)" },    // tripple increments
-          { true,        true,          true } },
-        { { "=SUM(B1)",  "",            "=SUM(C1)" },    // a gap
-          { false,       false,         false } },
-        { { "=SUM(B1)",  "=SUM(C1;3)",  "=SUM(D1;3)" }, // similar foo
-          { false,       true,          true } },
+        { { "=B1", "=B2", "" }, // relative reference
+          { true, true, false } },
+        { { "=B1", "=B2", "=B3" },
+          { true, true, true } },
+        { { "=B1", "", "=B3" }, // a gap
+          { false, false, false } },
+        { { "=$B$1", "=$B$1", "" }, // absolute reference
+          { true, true, false } },
+        { { "=$Z$10", "=$Z$10", "=$Z$10" },
+          { true, true, true } },
+        { { "=C1+$Z$10", "=C2+$Z$10", "=C3+$Z$10" }, // mixture
+          { true, true, true } },
+        { { "=C1+$Z$11", "=C2+$Z$12", "=C3+$Z$12" }, // mixture
+          { false, true, true } },
+        { { "=SUM(B1)",  "", "=SUM(B3)" },    // a gap
+          { false, false, false } },
     };
 
     m_pDoc->InsertTab( 0, "sheet" );
 
-    for (unsigned i = 0; i < SAL_N_ELEMENTS( aGroupTests ); i++)
+    for (size_t i = 0; i < SAL_N_ELEMENTS(aGroupTests); ++i)
     {
-        for (unsigned j = 0; j < SAL_N_ELEMENTS( aGroupTests[0].pFormula ); j++)
+        for (size_t j = 0; j < SAL_N_ELEMENTS(aGroupTests[0].pFormula); ++j)
         {
             OUString aFormula = OUString::createFromAscii(aGroupTests[i].pFormula[j]);
-            m_pDoc->SetString(0, (SCROW)j, 0, aFormula);
+            m_pDoc->SetString(0, static_cast<SCROW>(j), 0, aFormula);
         }
         m_pDoc->RebuildFormulaGroups();
 
-        for (unsigned j = 0; j < SAL_N_ELEMENTS( aGroupTests[0].pFormula ); j++)
+        for (size_t j = 0; j < SAL_N_ELEMENTS(aGroupTests[0].pFormula); ++j)
         {
             ScRefCellValue aCell;
-            aCell.assign(*m_pDoc, ScAddress(0, (SCROW)j, 0));
+            aCell.assign(*m_pDoc, ScAddress(0, static_cast<SCROW>(j), 0));
             if (aCell.isEmpty())
             {
                 CPPUNIT_ASSERT_MESSAGE("invalid empty cell", !aGroupTests[i].bGroup[j]);
@@ -6916,9 +6906,9 @@ void Test::testFormulaGrouping()
 
             if( !!pCur->GetCellGroup().get() ^ aGroupTests[i].bGroup[j] )
             {
-                printf("expected group test %u at row %u to be %d but is %d\n",
-                       i, j, aGroupTests[i].bGroup[j], !!pCur->GetCellGroup().get());
-                CPPUNIT_ASSERT_MESSAGE("Failed", false);
+                cout << "expected group test " << i << " at row " << j << " to be "
+                    << aGroupTests[i].bGroup[j] << " but is " << !!pCur->GetCellGroup().get() << endl;
+                CPPUNIT_FAIL("Failed");
             }
         }
     }
diff --git a/sc/source/core/data/cell2.cxx b/sc/source/core/data/cell2.cxx
index 8345e48..0d46036 100644
--- a/sc/source/core/data/cell2.cxx
+++ b/sc/source/core/data/cell2.cxx
@@ -135,39 +135,22 @@ void ScEditCell::UpdateFields(SCTAB nTab)
     aUpdater.updateTableFields(nTab);
 }
 
-void ScEditCell::SetTextObject( const EditTextObject* pObject,
-            const SfxItemPool* pFromPool )
+void ScEditCell::SetTextObject(
+    const EditTextObject* pObject, const SfxItemPool* pFromPool )
 {
-    if ( pObject )
+    if (!pObject)
     {
-        if ( pFromPool && mpDoc->GetEditPool() == pFromPool )
-            mpData = pObject->Clone();
-        else
-        {   //! another "spool"
-            // Sadly there is no other way to change the Pool than to
-            // "spool" the Object through a corresponding Engine
-            EditEngine& rEngine = mpDoc->GetEditEngine();
-            if ( pObject->HasOnlineSpellErrors() )
-            {
-                sal_uLong nControl = rEngine.GetControlWord();
-                const sal_uLong nSpellControl = EE_CNTRL_ONLINESPELLING | EE_CNTRL_ALLOWBIGOBJS;
-                bool bNewControl = ( (nControl & nSpellControl) != nSpellControl );
-                if ( bNewControl )
-                    rEngine.SetControlWord( nControl | nSpellControl );
-                rEngine.SetText( *pObject );
-                mpData = rEngine.CreateTextObject();
-                if ( bNewControl )
-                    rEngine.SetControlWord( nControl );
-            }
-            else
-            {
-                rEngine.SetText( *pObject );
-                mpData = rEngine.CreateTextObject();
-            }
-        }
-    }
-    else
         mpData = NULL;
+        return;
+    }
+
+    if ( pFromPool && mpDoc->GetEditPool() == pFromPool )
+    {
+        mpData = pObject->Clone();
+        return;
+    }
+
+    mpData = ScEditUtil::Clone(*pObject, *mpDoc);
 }
 
 ScEditDataArray::ScEditDataArray()
diff --git a/sc/source/core/data/cellclonehandler.cxx b/sc/source/core/data/cellclonehandler.cxx
new file mode 100644
index 0000000..1f1d75c
--- /dev/null
+++ b/sc/source/core/data/cellclonehandler.cxx
@@ -0,0 +1,89 @@
+/* -*- 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 "cellclonehandler.hxx"
+#include "editutil.hxx"
+#include "document.hxx"
+
+namespace sc {
+
+CellBlockCloneHandler::CellBlockCloneHandler(
+    ScDocument& rSrcDoc, ScDocument& rDestDoc, CellStoreType& rDestCellStore) :
+    mrSrcDoc(rSrcDoc), mrDestDoc(rDestDoc), mrDestCellStore(rDestCellStore) {}
+
+CellBlockCloneHandler::~CellBlockCloneHandler() {}
+
+ScDocument& CellBlockCloneHandler::getSrcDoc()
+{
+    return mrSrcDoc;
+}
+
+ScDocument& CellBlockCloneHandler::getDestDoc()
+{
+    return mrDestDoc;
+}
+
+const ScDocument& CellBlockCloneHandler::getDestDoc() const
+{
+    return mrDestDoc;
+}
+
+CellStoreType& CellBlockCloneHandler::getDestCellStore()
+{
+    return mrDestCellStore;
+}
+
+void CellBlockCloneHandler::cloneDoubleBlock(
+    CellStoreType::iterator& itPos, const ScAddress& /*rSrcPos*/, const ScAddress& rDestPos,
+    const numeric_block::const_iterator& itBegin, const numeric_block::const_iterator& itEnd)
+{
+    itPos = mrDestCellStore.set(itPos, rDestPos.Row(), itBegin, itEnd);
+}
+
+void CellBlockCloneHandler::cloneStringBlock(
+    CellStoreType::iterator& itPos, const ScAddress& /*rSrcPos*/, const ScAddress& rDestPos,
+    const string_block::const_iterator& itBegin, const string_block::const_iterator& itEnd)
+{
+    itPos = mrDestCellStore.set(itPos, rDestPos.Row(), itBegin, itEnd);
+}
+
+void CellBlockCloneHandler::cloneEditTextBlock(
+    CellStoreType::iterator& itPos, const ScAddress& /*rSrcPos*/, const ScAddress& rDestPos,
+    const edittext_block::const_iterator& itBegin, const edittext_block::const_iterator& itEnd)
+{
+    std::vector<EditTextObject*> aCloned;
+    aCloned.reserve(std::distance(itBegin, itEnd));
+    for (edittext_block::const_iterator it = itBegin; it != itEnd; ++it)
+        aCloned.push_back(ScEditUtil::Clone(**it, getDestDoc()));
+
+    itPos = getDestCellStore().set(itPos, rDestPos.Row(), aCloned.begin(), aCloned.end());
+}
+
+void CellBlockCloneHandler::cloneFormulaBlock(
+    CellStoreType::iterator& itPos, const ScAddress& /*rSrcPos*/, const ScAddress& rDestPos,
+    const formula_block::const_iterator& itBegin, const formula_block::const_iterator& itEnd)
+{
+    std::vector<ScFormulaCell*> aCloned;
+    aCloned.reserve(std::distance(itBegin, itEnd));
+    ScAddress aDestPos = rDestPos;
+    for (formula_block::const_iterator it = itBegin; it != itEnd; ++it, aDestPos.IncRow())
+    {
+        const ScFormulaCell& rOld = **it;
+        if (rOld.GetDirty() && getSrcDoc().GetAutoCalc())
+            const_cast<ScFormulaCell&>(rOld).Interpret();
+
+        aCloned.push_back(new ScFormulaCell(rOld, getDestDoc(), aDestPos));
+    }
+
+    itPos = getDestCellStore().set(itPos, rDestPos.Row(), aCloned.begin(), aCloned.end());
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/core/data/cellvalue.cxx b/sc/source/core/data/cellvalue.cxx
index 75362ba..169d2f7 100644
--- a/sc/source/core/data/cellvalue.cxx
+++ b/sc/source/core/data/cellvalue.cxx
@@ -9,6 +9,7 @@
 
 #include "cellvalue.hxx"
 #include "document.hxx"
+#include "column.hxx"
 #include "cell.hxx"
 #include "formulacell.hxx"
 #include "editeng/editobj.hxx"
@@ -182,6 +183,41 @@ void ScCellValue::clear()
     mfValue = 0.0;
 }
 
+void ScCellValue::set( double fValue )
+{
+    clear();
+    meType = CELLTYPE_VALUE;
+    mfValue = fValue;
+}
+
+void ScCellValue::set( const OUString& rStr )
+{
+    clear();
+    meType = CELLTYPE_STRING;
+    mpString = new OUString(rStr);
+}
+
+void ScCellValue::set( const EditTextObject& rEditText )
+{
+    clear();
+    meType = CELLTYPE_EDIT;
+    mpEditText = rEditText.Clone();
+}
+
+void ScCellValue::set( const ScFormulaCell& rFormula )
+{
+    clear();
+    meType = CELLTYPE_FORMULA;
+    mpFormula = rFormula.Clone();
+}
+
+void ScCellValue::set( ScFormulaCell* pFormula )
+{
+    clear();
+    meType = CELLTYPE_FORMULA;
+    mpFormula = pFormula;
+}
+
 void ScCellValue::assign( const ScDocument& rDoc, const ScAddress& rPos )
 {
     clear();
@@ -255,85 +291,87 @@ void ScCellValue::assign( const ScCellValue& rOther, ScDocument& rDestDoc, int n
     }
 }
 
-void ScCellValue::assign( const ScBaseCell& rCell )
+void ScCellValue::commit( ScDocument& rDoc, const ScAddress& rPos ) const
 {
-    clear();
-
-    meType = rCell.GetCellType();
     switch (meType)
     {
         case CELLTYPE_STRING:
-            mpString = new OUString(static_cast<const ScStringCell&>(rCell).GetString());
-        break;
-        case CELLTYPE_EDIT:
         {
-            const EditTextObject* p = static_cast<const ScEditCell&>(rCell).GetData();
-            if (p)
-                mpEditText = p->Clone();
+            ScSetStringParam aParam;
+            aParam.setTextInput();
+            rDoc.SetString(rPos, *mpString, &aParam);
         }
         break;
+        case CELLTYPE_EDIT:
+            rDoc.SetEditText(rPos, mpEditText->Clone());
+        break;
         case CELLTYPE_VALUE:
-            mfValue = static_cast<const ScValueCell&>(rCell).GetValue();
+            rDoc.SetValue(rPos, mfValue);
         break;
         case CELLTYPE_FORMULA:
-            mpFormula = static_cast<const ScFormulaCell&>(rCell).Clone();
+            rDoc.SetFormulaCell(rPos, mpFormula->Clone());
         break;
         default:
-            meType = CELLTYPE_NONE; // reset to empty.
+            rDoc.SetEmptyCell(rPos);
     }
 }
 
-void ScCellValue::commit( ScDocument& rDoc, const ScAddress& rPos ) const
+void ScCellValue::release( ScDocument& rDoc, const ScAddress& rPos )
 {
     switch (meType)
     {
         case CELLTYPE_STRING:
         {
+            // Currently, string cannot be placed without copying.
             ScSetStringParam aParam;
             aParam.setTextInput();
             rDoc.SetString(rPos, *mpString, &aParam);
+            delete mpString;
         }
         break;
         case CELLTYPE_EDIT:
-            rDoc.SetEditText(rPos, mpEditText->Clone());
+            // Cell takes the ownership of the text object.
+            rDoc.SetEditText(rPos, mpEditText);
         break;
         case CELLTYPE_VALUE:
             rDoc.SetValue(rPos, mfValue);
         break;
         case CELLTYPE_FORMULA:
-            rDoc.SetFormulaCell(rPos, mpFormula->Clone());
+            // This formula cell instance is directly placed in the document without copying.
+            rDoc.SetFormulaCell(rPos, mpFormula);
         break;
         default:
             rDoc.SetEmptyCell(rPos);
     }
+
+    meType = CELLTYPE_NONE;
+    mfValue = 0.0;
 }
 
-void ScCellValue::release( ScDocument& rDoc, const ScAddress& rPos )
+void ScCellValue::release( ScColumn& rColumn, SCROW nRow )
 {
     switch (meType)
     {
         case CELLTYPE_STRING:
         {
             // Currently, string cannot be placed without copying.
-            ScSetStringParam aParam;
-            aParam.setTextInput();
-            rDoc.SetString(rPos, *mpString, &aParam);
+            rColumn.SetRawString(nRow, *mpString);
             delete mpString;
         }
         break;
         case CELLTYPE_EDIT:
             // Cell takes the ownership of the text object.
-            rDoc.SetEditText(rPos, mpEditText);
+            rColumn.SetEditText(nRow, mpEditText);
         break;
         case CELLTYPE_VALUE:
-            rDoc.SetValue(rPos, mfValue);
+            rColumn.SetValue(nRow, mfValue);
         break;
         case CELLTYPE_FORMULA:
             // This formula cell instance is directly placed in the document without copying.
-            rDoc.SetFormulaCell(rPos, mpFormula);
+            rColumn.SetFormulaCell(nRow, mpFormula);
         break;
         default:
-            rDoc.SetEmptyCell(rPos);
+            rColumn.Delete(nRow);
     }
 
     meType = CELLTYPE_NONE;
@@ -403,52 +441,81 @@ void ScRefCellValue::assign( ScDocument& rDoc, const ScAddress& rPos )
     *this = rDoc.GetRefCellValue(rPos);
 }
 
-void ScRefCellValue::assign( ScBaseCell& rCell )
+void ScRefCellValue::assign( const sc::CellStoreType::const_iterator& itPos, size_t nOffset )
 {
-    clear();
+    switch (itPos->type)
+    {
+        case sc::element_type_numeric:
+            // Numeric cell
+            mfValue = sc::numeric_block::at(*itPos->data, nOffset);
+            meType = CELLTYPE_VALUE;
+        break;
+        case sc::element_type_string:
+            // String cell

... etc. - the rest is truncated


More information about the Libreoffice-commits mailing list