[Libreoffice-commits] core.git: Branch 'feature/formula-core-rework' - helpcontent2 sc/inc sc/source

Kohei Yoshida kohei.yoshida at gmail.com
Mon Mar 25 20:23:16 PDT 2013


 helpcontent2                                           |    2 
 sc/inc/cell.hxx                                        |   21 
 sc/inc/cellvalue.hxx                                   |   21 
 sc/inc/chgtrack.hxx                                    |  123 +--
 sc/inc/dociter.hxx                                     |    3 
 sc/inc/editutil.hxx                                    |    2 
 sc/inc/global.hxx                                      |   17 
 sc/source/core/data/cellvalue.cxx                      |  125 +++
 sc/source/core/data/dociter.cxx                        |   35 
 sc/source/core/data/documen4.cxx                       |   14 
 sc/source/core/tool/chgtrack.cxx                       |  641 ++++++++---------
 sc/source/filter/excel/xehelper.cxx                    |   46 -
 sc/source/filter/excel/xetable.cxx                     |   14 
 sc/source/filter/inc/XclExpChangeTrack.hxx             |    9 
 sc/source/filter/inc/XclImpChangeTrack.hxx             |    9 
 sc/source/filter/inc/xehelper.hxx                      |    4 
 sc/source/filter/xcl97/XclExpChangeTrack.cxx           |   46 -
 sc/source/filter/xcl97/XclImpChangeTrack.cxx           |   48 -
 sc/source/filter/xml/XMLChangeTrackingExportHelper.cxx |  258 +++---
 sc/source/filter/xml/XMLChangeTrackingExportHelper.hxx |   13 
 sc/source/filter/xml/XMLChangeTrackingImportHelper.cxx |  137 +--
 sc/source/filter/xml/XMLChangeTrackingImportHelper.hxx |   13 
 sc/source/filter/xml/XMLTrackedChangesContext.cxx      |   42 -
 sc/source/ui/docshell/docfunc.cxx                      |    5 
 sc/source/ui/docshell/docsh3.cxx                       |    8 
 sc/source/ui/inc/undocell.hxx                          |   13 
 sc/source/ui/undo/undoblk3.cxx                         |    4 
 sc/source/ui/undo/undocell.cxx                         |  116 +--
 sc/source/ui/view/viewfunc.cxx                         |   13 
 29 files changed, 979 insertions(+), 823 deletions(-)

New commits:
commit e0ab365feae9f9bffa67bc2fdf6a1f397ff02c70
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date:   Mon Mar 25 23:22:18 2013 -0400

    Get the whole change tracking code entirely ScBaseCell-free!
    
    This took me a whole day....
    
    Change-Id: Ida757b1efa284fc9d071a225f45666c340ba89ea

diff --git a/helpcontent2 b/helpcontent2
index 7875d6d..f25d6a1 160000
--- a/helpcontent2
+++ b/helpcontent2
@@ -1 +1 @@
-Subproject commit 7875d6df2911a7caa8de1adac9b5b21026c8b9a4
+Subproject commit f25d6a1081dd929a8872fcd9305b5f06355d3337
diff --git a/sc/inc/cell.hxx b/sc/inc/cell.hxx
index 0d34698..236ad43 100644
--- a/sc/inc/cell.hxx
+++ b/sc/inc/cell.hxx
@@ -51,27 +51,6 @@ class SvtBroadcaster;
 class ScProgress;
 class ScPatternAttr;
 
-// ============================================================================
-
-/** Default cell clone flags: do not start listening, do not adjust 3D refs to
-    old position, clone note captions of cell notes. */
-const int SC_CLONECELL_DEFAULT          = 0x0000;
-
-/** If set, cloned formula cells will start to listen to the document. */
-const int SC_CLONECELL_STARTLISTENING   = 0x0001;
-
-/** If set, relative 3D references of cloned formula cells will be adjusted to
-    old position (used while swapping cells for sorting a cell range). */
-const int SC_CLONECELL_ADJUST3DREL      = 0x0002;
-
-/** If set, the caption object of a cell note will not be cloned (used while
-    copying cells to undo document, where captions are handled in drawing undo). */
-const int SC_CLONECELL_NOCAPTION        = 0x0004;
-
-/** If set, absolute refs will not transformed to external references */
-const int SC_CLONECELL_NOMAKEABS_EXTERNAL = 0x0008;
-// ============================================================================
-
 class SC_DLLPUBLIC ScBaseCell
 {
 protected:
diff --git a/sc/inc/cellvalue.hxx b/sc/inc/cellvalue.hxx
index 16af46f..9b7ea19 100644
--- a/sc/inc/cellvalue.hxx
+++ b/sc/inc/cellvalue.hxx
@@ -15,12 +15,13 @@
 class ScDocument;
 class ScFormulaCell;
 class EditTextObject;
+class ScBaseCell;
 
 /**
  * Store arbitrary cell value of any kind.  It only stores cell value and
  * nothing else.
  */
-struct ScCellValue
+struct SC_DLLPUBLIC ScCellValue
 {
     CellType meType;
     union {
@@ -45,10 +46,21 @@ struct ScCellValue
      */
     void assign( const ScDocument& rDoc, const ScAddress& rPos );
 
+    void assign( const ScCellValue& rOther, ScDocument& rDestDoc, int nCloneFlags = SC_CLONECELL_DEFAULT );
+
+    void assign( const ScBaseCell& rCell );
+
     /**
      * Set cell value at specified position in specified document.
      */
-    void commit( ScDocument& rDoc, const ScAddress& rPos );
+    void commit( ScDocument& rDoc, const ScAddress& rPos ) const;
+
+    /**
+     * Set cell value at specified position in specified document. But unlike
+     * commit(), this method sets the original value to the document without
+     * copying.  After this call, the value gets cleared.
+     */
+    void release( ScDocument& rDoc, const ScAddress& rPos );
 
     bool hasString() const;
 
@@ -57,10 +69,13 @@ struct ScCellValue
     bool isEmpty() const;
 
     bool equalsWithoutFormat( const ScCellValue& r ) const;
+
+    ScCellValue& operator= ( const ScCellValue& r );
+
+    void swap( ScCellValue& r );
 };
 
 // TODO: temporary workaround.  To be removed later.
-class ScBaseCell;
 ScBaseCell* getHackedBaseCell( ScDocument* pDoc, const ScCellValue& rVal );
 
 #endif
diff --git a/sc/inc/chgtrack.hxx b/sc/inc/chgtrack.hxx
index 5e5c867..b30cf1b 100644
--- a/sc/inc/chgtrack.hxx
+++ b/sc/inc/chgtrack.hxx
@@ -33,8 +33,8 @@
 #include "bigrange.hxx"
 #include "scdllapi.h"
 #include "refupdat.hxx"
+#include "cellvalue.hxx"
 
-class ScBaseCell;
 class ScDocument;
 class ScFormulaCell;
 class ScCellIterator;
@@ -648,10 +648,11 @@ class ScChangeActionContent : public ScChangeAction
 {
     friend class ScChangeTrack;
 
-    rtl::OUString aOldValue;
-    rtl::OUString aNewValue;
-    ScBaseCell*         pOldCell;
-    ScBaseCell*         pNewCell;
+    ScCellValue maOldCell;
+    ScCellValue maNewCell;
+
+    OUString maOldValue;
+    OUString maNewValue;
     ScChangeActionContent*  pNextContent;   // at the same position
     ScChangeActionContent*  pPrevContent;
     ScChangeActionContent*  pNextInSlot;    // in the same slot
@@ -682,30 +683,27 @@ class ScChangeActionContent : public ScChangeAction
 
     void ClearTrack();
 
-    static void GetStringOfCell( rtl::OUString& rStr, const ScBaseCell* pCell,
-                                 const ScDocument* pDoc, const ScAddress& rPos );
+    static void GetStringOfCell(
+        OUString& rStr, const ScCellValue& rCell, const ScDocument* pDoc, const ScAddress& rPos );
 
-    static void GetStringOfCell( rtl::OUString& rStr, const ScBaseCell* pCell,
-                                 const ScDocument* pDoc, sal_uLong nFormat );
+    static void GetStringOfCell(
+        OUString& rStr, const ScCellValue& rCell, const ScDocument* pDoc, sal_uLong nFormat );
 
-    static void SetValue( rtl::OUString& rStr, ScBaseCell*& pCell, const ScAddress& rPos,
-                          const ScBaseCell* pOrgCell, const ScDocument* pFromDoc,
+    static void SetValue( OUString& rStr, ScCellValue& rCell, const ScAddress& rPos,
+                          const ScCellValue& rOrgCell, const ScDocument* pFromDoc,
                           ScDocument* pToDoc );
 
-    static void SetValue( rtl::OUString& rStr, ScBaseCell*& pCell, sal_uLong nFormat,
-                          const ScBaseCell* pOrgCell, const ScDocument* pFromDoc,
+    static void SetValue( OUString& rStr, ScCellValue& rCell, sal_uLong nFormat,
+                          const ScCellValue& rOrgCell, const ScDocument* pFromDoc,
                           ScDocument* pToDoc );
 
-    static void SetCell( rtl::OUString& rStr, ScBaseCell* pCell,
-                         sal_uLong nFormat, const ScDocument* pDoc );
+    static void SetCell( OUString& rStr, ScCellValue& rCell, sal_uLong nFormat, const ScDocument* pDoc );
 
-    static bool NeedsNumberFormat( const ScBaseCell* );
+    static bool NeedsNumberFormat( const ScCellValue& rVal );
 
-    void SetValueString( rtl::OUString& rValue, ScBaseCell*& pCell,
-                         const rtl::OUString& rStr, ScDocument* pDoc );
+    void SetValueString( OUString& rValue, ScCellValue& rCell, const OUString& rStr, ScDocument* pDoc );
 
-    void GetValueString( rtl::OUString& rStr, const rtl::OUString& rValue,
-                         const ScBaseCell* pCell ) const;
+    void GetValueString( OUString& rStr, const OUString& rValue, const ScCellValue& rCell ) const;
 
     void GetFormulaString( rtl::OUString& rStr, const ScFormulaCell* pCell ) const;
 
@@ -726,8 +724,7 @@ class ScChangeActionContent : public ScChangeAction
                  bool bOldest, ::std::stack<ScChangeActionContent*>* pRejectActions );
 
     void PutValueToDoc(
-        ScBaseCell* pCell, const rtl::OUString& rValue, ScDocument* pDoc,
-        SCsCOL nDx, SCsROW nDy ) const;
+        const ScCellValue& rCell, const OUString& rValue, ScDocument* pDoc, SCsCOL nDx, SCsROW nDy ) const;
 
 protected:
     using ScChangeAction::GetRefString;
@@ -736,26 +733,19 @@ public:
 
     DECL_FIXEDMEMPOOL_NEWDEL( ScChangeActionContent )
 
-    ScChangeActionContent( const ScRange& rRange )
-        : ScChangeAction( SC_CAT_CONTENT, rRange ),
-            pOldCell( NULL ),
-            pNewCell( NULL ),
-            pNextContent( NULL ),
-            pPrevContent( NULL ),
-            pNextInSlot( NULL ),
-            ppPrevInSlot( NULL )
-        {}
+    ScChangeActionContent( const ScRange& rRange );
+
     ScChangeActionContent(
         const sal_uLong nActionNumber,  const ScChangeActionState eState,
         const sal_uLong nRejectingNumber, const ScBigRange& aBigRange,
-        const rtl::OUString& aUser, const DateTime& aDateTime,
-        const rtl::OUString &sComment, ScBaseCell* pOldCell,
-        ScDocument* pDoc, const rtl::OUString& sOldValue); // to use for XML Import
+        const OUString& aUser, const DateTime& aDateTime,
+        const OUString &sComment, const ScCellValue& rOldCell,
+        ScDocument* pDoc, const OUString& sOldValue ); // to use for XML Import
 
     ScChangeActionContent(
-        const sal_uLong nActionNumber, ScBaseCell* pNewCell,
+        const sal_uLong nActionNumber, const ScCellValue& rNewCell,
         const ScBigRange& aBigRange, ScDocument* pDoc,
-        const rtl::OUString& sNewValue); // to use for XML Import of Generated Actions
+        const OUString& sNewValue ); // to use for XML Import of Generated Actions
 
     virtual ~ScChangeActionContent();
 
@@ -772,25 +762,21 @@ public:
     void                PutNewValueToDoc( ScDocument*,
                             SCsCOL nDx, SCsROW nDy ) const;
 
-    void                SetOldValue( const ScBaseCell*,
-                            const ScDocument* pFromDoc,
-                            ScDocument* pToDoc,
-                            sal_uLong nFormat );
-    void                SetOldValue( const ScBaseCell*,
-                            const ScDocument* pFromDoc,
-                            ScDocument* pToDoc );
-    void                SetNewValue( const ScBaseCell*, ScDocument* );
-
-                        // Used in import filter AppendContentOnTheFly,
-                        // takes ownership of cells.
-    void                SetOldNewCells( ScBaseCell* pOldCell,
-                            sal_uLong nOldFormat, ScBaseCell* pNewCell,
-                            sal_uLong nNewFormat, ScDocument* pDoc );
+    void SetOldValue( const ScCellValue& rCell, const ScDocument* pFromDoc, ScDocument* pToDoc, sal_uLong nFormat );
+
+    void SetOldValue( const ScCellValue& rCell, const ScDocument* pFromDoc, ScDocument* pToDoc );
+
+    void SetNewValue( const ScCellValue& rCell, ScDocument* pDoc );
+
+    // Used in import filter AppendContentOnTheFly,
+    void SetOldNewCells(
+        const ScCellValue& rOldCell, sal_uLong nOldFormat,
+        const ScCellValue& rNewCell, sal_uLong nNewFormat, ScDocument* pDoc );
 
     // Use this only in the XML import,
     // takes ownership of cell.
     void SetNewCell(
-        ScBaseCell* pCell, ScDocument* pDoc, const rtl::OUString& rFormatted );
+        const ScCellValue& rCell, ScDocument* pDoc, const OUString& rFormatted );
 
                         // These functions should be protected but for
                         // the XML import they are public.
@@ -801,19 +787,19 @@ public:
 
     // don't use:
     // assigns string / creates forumula cell
-    void SetOldValue( const rtl::OUString& rOld, ScDocument* pDoc );
+    void SetOldValue( const OUString& rOld, ScDocument* pDoc );
 
     void GetOldString( rtl::OUString& rStr ) const;
     void GetNewString( rtl::OUString& rStr ) const;
-    const ScBaseCell*   GetOldCell() const { return pOldCell; }
-    const ScBaseCell*   GetNewCell() const { return pNewCell; }
+    SC_DLLPUBLIC const ScCellValue& GetOldCell() const;
+    SC_DLLPUBLIC const ScCellValue& GetNewCell() const;
     virtual void GetDescription(
         rtl::OUString& rStr, ScDocument* pDoc, bool bSplitRange = false, bool bWarning = true ) const;
 
     virtual void GetRefString(
         rtl::OUString& rStr, ScDocument* pDoc, bool bFlag3D = false ) const;
 
-    static  ScChangeActionContentCellType   GetContentCellType( const ScBaseCell* );
+    static ScChangeActionContentCellType GetContentCellType( const ScCellValue& rCell );
     static ScChangeActionContentCellType GetContentCellType( const ScCellIterator& rIter );
 
     // NewCell
@@ -951,7 +937,7 @@ class ScChangeTrack : public utl::ConfigurationListener
     // true if one is MM_FORMULA and the other is
     // not, or if both are and range differs
     static bool IsMatrixFormulaRangeDifferent(
-        const ScBaseCell* pOldCell, const ScBaseCell* pNewCell );
+        const ScCellValue& rOldCell, const ScCellValue& rNewCell );
 
     void                Init();
     void                DtorClear();
@@ -1004,9 +990,10 @@ class ScChangeTrack : public utl::ConfigurationListener
                                     ScChangeAction* pButNotThis ) const;
     void                DeleteGeneratedDelContent(
                                     ScChangeActionContent* );
-    ScChangeActionContent*  GenerateDelContent( const ScAddress&,
-                                    const ScBaseCell*,
-                                    const ScDocument* pFromDoc );
+
+    ScChangeActionContent* GenerateDelContent(
+        const ScAddress& rPos, const ScCellValue& rCell, const ScDocument* pFromDoc );
+
     void                DeleteCellEntries(
                                     ScChangeActionCellListEntry*&,
                                     ScChangeAction* pDeletor );
@@ -1127,13 +1114,11 @@ public:
                         // after new value was set in the document,
                         // old value from pOldCell, nOldFormat,
                         // RefDoc==NULL => Doc
-    void                AppendContent( const ScAddress& rPos,
-                            const ScBaseCell* pOldCell,
-                            sal_uLong nOldFormat, ScDocument* pRefDoc = NULL );
+    void AppendContent( const ScAddress& rPos, const ScCellValue& rOldCell,
+                        sal_uLong nOldFormat, ScDocument* pRefDoc = NULL );
                         // after new value was set in the document,
                         // old value from pOldCell, format from Doc
-    void                AppendContent( const ScAddress& rPos,
-                            const ScBaseCell* pOldCell );
+    void AppendContent( const ScAddress& rPos, const ScCellValue& rOldCell );
                         // after new values were set in the document,
                         // old values from RefDoc/UndoDoc.
                         // All contents with a cell in RefDoc
@@ -1148,11 +1133,9 @@ public:
                         // The action is returned and may be used to
                         // set user name, description, date/time et al.
                         // Takes ownership of the cells!
-    SC_DLLPUBLIC    ScChangeActionContent*  AppendContentOnTheFly( const ScAddress& rPos,
-                                    ScBaseCell* pOldCell,
-                                    ScBaseCell* pNewCell,
-                                    sal_uLong nOldFormat = 0,
-                                    sal_uLong nNewFormat = 0 );
+    SC_DLLPUBLIC ScChangeActionContent* AppendContentOnTheFly(
+        const ScAddress& rPos, const ScCellValue& rOldCell, const ScCellValue& rNewCell,
+        sal_uLong nOldFormat = 0, sal_uLong nNewFormat = 0 );
 
     // Only use the following two if there is no different solution! (Assign
     // string for NewValue or creation of a formula respectively)
@@ -1240,7 +1223,7 @@ public:
                             sal_uLong nStartAction, sal_uLong nEndAction );
 
     sal_uLong AddLoadedGenerated(
-        ScBaseCell* pOldCell, const ScBigRange& aBigRange, const rtl::OUString& sNewValue ); // only to use in the XML import
+        const ScCellValue& rNewCell, const ScBigRange& aBigRange, const rtl::OUString& sNewValue ); // only to use in the XML import
     void                AppendLoaded( ScChangeAction* pAppend ); // this is only for the XML import public, it should be protected
     void                SetActionMax(sal_uLong nTempActionMax)
                             { nActionMax = nTempActionMax; } // only to use in the XML import
diff --git a/sc/inc/dociter.hxx b/sc/inc/dociter.hxx
index fabbbbe..d24c6ab 100644
--- a/sc/inc/dociter.hxx
+++ b/sc/inc/dociter.hxx
@@ -45,6 +45,7 @@ struct ScQueryParam;
 struct ScDBQueryParamInternal;
 struct ScDBQueryParamMatrix;
 class ScFormulaCell;
+class ScCellValue;
 
 class ScDocumentIterator                // walk through all non-empty cells
 {
@@ -76,6 +77,7 @@ public:
     bool                    GetNext();
 
     ScBaseCell*             GetCell();
+    ScCellValue GetCellValue() const;
     const ScPatternAttr*    GetPattern();
     void                    GetPos( SCCOL& rCol, SCROW& rRow, SCTAB& rTab );
 };
@@ -243,6 +245,7 @@ public:
     ScFormulaCell* getFormulaCell();
     const ScFormulaCell* getFormulaCell() const;
     double getValue() const;
+    ScCellValue getCellValue() const;
 
     bool hasString() const;
     bool hasNumeric() const;
diff --git a/sc/inc/editutil.hxx b/sc/inc/editutil.hxx
index 556e749..ac8fc23 100644
--- a/sc/inc/editutil.hxx
+++ b/sc/inc/editutil.hxx
@@ -59,7 +59,7 @@ public:
     /// Retrieves string with paragraphs delimited by new lines ('\n').
     static String GetMultilineString( const EditEngine& rEngine );
 
-    static OUString GetString( const EditTextObject& rEditText );
+    SC_DLLPUBLIC static OUString GetString( const EditTextObject& rEditText );
 
 public:
                 ScEditUtil( ScDocument* pDocument, SCCOL nX, SCROW nY, SCTAB nZ,
diff --git a/sc/inc/global.hxx b/sc/inc/global.hxx
index d177ada..5b3a5ad 100644
--- a/sc/inc/global.hxx
+++ b/sc/inc/global.hxx
@@ -255,6 +255,23 @@ const sal_uInt16 IDF_AUTOFILL   = IDF_ALL & ~(IDF_NOTE | IDF_OBJECTS);
 #define SC_SCENARIO_VALUE       32
 #define SC_SCENARIO_PROTECT     64
 
+/** Default cell clone flags: do not start listening, do not adjust 3D refs to
+    old position, clone note captions of cell notes. */
+const int SC_CLONECELL_DEFAULT          = 0x0000;
+
+/** If set, cloned formula cells will start to listen to the document. */
+const int SC_CLONECELL_STARTLISTENING   = 0x0001;
+
+/** If set, relative 3D references of cloned formula cells will be adjusted to
+    old position (used while swapping cells for sorting a cell range). */
+const int SC_CLONECELL_ADJUST3DREL      = 0x0002;
+
+/** If set, the caption object of a cell note will not be cloned (used while
+    copying cells to undo document, where captions are handled in drawing undo). */
+const int SC_CLONECELL_NOCAPTION        = 0x0004;
+
+/** If set, absolute refs will not transformed to external references */
+const int SC_CLONECELL_NOMAKEABS_EXTERNAL = 0x0008;
 
 #ifndef DELETEZ
 #define DELETEZ(pPtr) { delete pPtr; pPtr = 0; }
diff --git a/sc/source/core/data/cellvalue.cxx b/sc/source/core/data/cellvalue.cxx
index 3706278..c5006c7 100644
--- a/sc/source/core/data/cellvalue.cxx
+++ b/sc/source/core/data/cellvalue.cxx
@@ -11,7 +11,9 @@
 #include "document.hxx"
 #include "cell.hxx"
 #include "editeng/editobj.hxx"
+#include "editeng/editstat.hxx"
 #include "stringutil.hxx"
+#include "editutil.hxx"
 #include "formula/token.hxx"
 
 ScCellValue::ScCellValue() : meType(CELLTYPE_NONE), mfValue(0.0) {}
@@ -89,7 +91,80 @@ void ScCellValue::assign( const ScDocument& rDoc, const ScAddress& rPos )
     }
 }
 
-void ScCellValue::commit( ScDocument& rDoc, const ScAddress& rPos )
+void ScCellValue::assign( const ScCellValue& rOther, ScDocument& rDestDoc, int nCloneFlags )
+{
+    clear();
+
+    meType = rOther.meType;
+    switch (meType)
+    {
+        case CELLTYPE_STRING:
+            mpString = new OUString(*rOther.mpString);
+        break;
+        case CELLTYPE_EDIT:
+        {
+            // Switch to the pool of the destination document.
+            ScFieldEditEngine& rEngine = rDestDoc.GetEditEngine();
+            if (rOther.mpEditText->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(*rOther.mpEditText);
+                mpEditText = rEngine.CreateTextObject();
+                if (bNewControl)
+                    rEngine.SetControlWord(nControl);
+            }
+            else
+            {
+                rEngine.SetText(*rOther.mpEditText);
+                mpEditText = rEngine.CreateTextObject();
+            }
+        }
+        break;
+        case CELLTYPE_VALUE:
+            mfValue = rOther.mfValue;
+        break;
+        case CELLTYPE_FORMULA:
+            // Switch to the destination document.
+            mpFormula = new ScFormulaCell(*rOther.mpFormula, rDestDoc, rOther.mpFormula->aPos, nCloneFlags);
+        break;
+        default:
+            meType = CELLTYPE_NONE; // reset to empty.
+    }
+}
+
+void ScCellValue::assign( const ScBaseCell& rCell )
+{
+    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();
+        }
+        break;
+        case CELLTYPE_VALUE:
+            mfValue = static_cast<const ScValueCell&>(rCell).GetValue();
+        break;
+        case CELLTYPE_FORMULA:
+            mpFormula = static_cast<const ScFormulaCell&>(rCell).Clone();
+        break;
+        default:
+            meType = CELLTYPE_NONE; // reset to empty.
+    }
+}
+
+void ScCellValue::commit( ScDocument& rDoc, const ScAddress& rPos ) const
 {
     switch (meType)
     {
@@ -114,6 +189,38 @@ void ScCellValue::commit( ScDocument& rDoc, const ScAddress& rPos )
     }
 }
 
+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:
+            // Cell takes the ownership of the text object.
+            rDoc.SetEditText(rPos, mpEditText);
+        break;
+        case CELLTYPE_VALUE:
+            rDoc.SetValue(rPos, mfValue);
+        break;
+        case CELLTYPE_FORMULA:
+            // 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;
+}
+
 bool ScCellValue::hasString() const
 {
     switch (meType)
@@ -229,6 +336,22 @@ bool ScCellValue::equalsWithoutFormat( const ScCellValue& r ) const
     return false;
 }
 
+ScCellValue& ScCellValue::operator= ( const ScCellValue& r )
+{
+    ScCellValue aTmp(r);
+    swap(aTmp);
+    return *this;
+}
+
+void ScCellValue::swap( ScCellValue& r )
+{
+    std::swap(meType, r.meType);
+
+    // double is 8 bytes, whereas a pointer may be 4 or 8 bytes depending on
+    // the platform. Swap by double values.
+    std::swap(mfValue, r.mfValue);
+}
+
 ScBaseCell* getHackedBaseCell( ScDocument* pDoc, const ScCellValue& rVal )
 {
     switch (rVal.meType)
diff --git a/sc/source/core/data/dociter.cxx b/sc/source/core/data/dociter.cxx
index 2b6e568..24fd2b3 100644
--- a/sc/source/core/data/dociter.cxx
+++ b/sc/source/core/data/dociter.cxx
@@ -36,6 +36,7 @@
 #include "queryentry.hxx"
 #include "globstr.hrc"
 #include "editutil.hxx"
+#include "cellvalue.hxx"
 
 #include "tools/fract.hxx"
 #include "editeng/editobj.hxx"
@@ -203,6 +204,14 @@ ScBaseCell* ScDocumentIterator::GetCell()
     return pCell;
 }
 
+ScCellValue ScDocumentIterator::GetCellValue() const
+{
+    ScCellValue aRet;
+    if (pCell)
+        aRet.assign(*pCell);
+    return aRet;
+}
+
 const ScPatternAttr* ScDocumentIterator::GetPattern()
 {
     return pPattern;
@@ -1105,6 +1114,32 @@ double ScCellIterator::getValue() const
     return 0.0;
 }
 
+ScCellValue ScCellIterator::getCellValue() const
+{
+    ScCellValue aRet;
+    aRet.meType = meCurType;
+
+    switch (meCurType)
+    {
+        case CELLTYPE_STRING:
+            aRet.mpString = new OUString(maCurString);
+        break;
+        case CELLTYPE_EDIT:
+            aRet.mpEditText = mpCurEditText->Clone();
+        break;
+        case CELLTYPE_VALUE:
+            aRet.mfValue = mfCurValue;
+        break;
+        case CELLTYPE_FORMULA:
+            aRet.mpFormula = mpCurFormula->Clone();
+        break;
+        default:
+            ;
+    }
+
+    return aRet;
+}
+
 bool ScCellIterator::hasString() const
 {
     switch (meCurType)
diff --git a/sc/source/core/data/documen4.cxx b/sc/source/core/data/documen4.cxx
index b34cc07..aad3f4f 100644
--- a/sc/source/core/data/documen4.cxx
+++ b/sc/source/core/data/documen4.cxx
@@ -1185,19 +1185,21 @@ void ScDocument::CompareDocument( ScDocument& rOtherDoc )
                 {
                     SCCOL nOtherCol = static_cast<SCCOL>(pOtherCols[nThisCol]);
                     ScAddress aThisPos( nThisCol, nThisRow, nThisTab );
-                    const ScBaseCell* pThisCell = GetCell( aThisPos );
-                    const ScBaseCell* pOtherCell = NULL;
+                    ScCellValue aThisCell;
+                    aThisCell.assign(*this, aThisPos);
+                    ScCellValue aOtherCell; // start empty
                     if ( ValidCol(nOtherCol) && ValidRow(nOtherRow) )
                     {
                         ScAddress aOtherPos( nOtherCol, nOtherRow, nOtherTab );
-                        pOtherCell = rOtherDoc.GetCell( aOtherPos );
+                        aOtherCell.assign(*this, aOtherPos);
                     }
-                    if ( !ScBaseCell::CellEqual( pThisCell, pOtherCell ) )
+
+                    if (!aThisCell.equalsWithoutFormat(aOtherCell))
                     {
                         ScRange aRange( aThisPos );
                         ScChangeActionContent* pAction = new ScChangeActionContent( aRange );
-                        pAction->SetOldValue( pOtherCell, &rOtherDoc, this );
-                        pAction->SetNewValue( pThisCell, this );
+                        pAction->SetOldValue(aOtherCell, &rOtherDoc, this);
+                        pAction->SetNewValue(aThisCell, this);
                         pChangeTrack->Append( pAction );
                     }
                 }
diff --git a/sc/source/core/tool/chgtrack.cxx b/sc/source/core/tool/chgtrack.cxx
index 6d98741..8912ffa 100644
--- a/sc/source/core/tool/chgtrack.cxx
+++ b/sc/source/core/tool/chgtrack.cxx
@@ -30,6 +30,7 @@
 #include "hints.hxx"
 #include "markdata.hxx"
 #include "globstr.hrc"
+#include "editutil.hxx"
 
 #include <tools/shl.hxx>        // SHL_CALC
 #include <tools/rtti.hxx>
@@ -1343,44 +1344,50 @@ bool ScChangeActionMove::Reject( ScDocument* pDoc )
 
 IMPL_FIXEDMEMPOOL_NEWDEL( ScChangeActionContent )
 
+ScChangeActionContent::ScChangeActionContent( const ScRange& rRange ) :
+    ScChangeAction(SC_CAT_CONTENT, rRange),
+    pNextContent(NULL),
+    pPrevContent(NULL),
+    pNextInSlot(NULL),
+    ppPrevInSlot(NULL)
+{}
+
 ScChangeActionContent::ScChangeActionContent( const sal_uLong nActionNumber,
             const ScChangeActionState eStateP, const sal_uLong nRejectingNumber,
-            const ScBigRange& aBigRangeP, const rtl::OUString& aUserP,
-            const DateTime& aDateTimeP, const rtl::OUString& sComment,
-            ScBaseCell* pTempOldCell, ScDocument* pDoc, const rtl::OUString& sOldValue )
-        :
-        ScChangeAction(SC_CAT_CONTENT, aBigRangeP, nActionNumber, nRejectingNumber, eStateP, aDateTimeP, aUserP, sComment),
-        aOldValue(sOldValue),
-        pOldCell(pTempOldCell),
-        pNewCell(NULL),
-        pNextContent(NULL),
-        pPrevContent(NULL),
-        pNextInSlot(NULL),
-        ppPrevInSlot(NULL)
-{
-    if (pOldCell)
-        SetCell( aOldValue, pOldCell, 0, pDoc );
+            const ScBigRange& aBigRangeP, const OUString& aUserP,
+            const DateTime& aDateTimeP, const OUString& sComment,
+            const ScCellValue& rOldCell, ScDocument* pDoc, const OUString& sOldValue ) :
+    ScChangeAction(SC_CAT_CONTENT, aBigRangeP, nActionNumber, nRejectingNumber, eStateP, aDateTimeP, aUserP, sComment),
+    maOldCell(rOldCell),
+    maOldValue(sOldValue),
+    pNextContent(NULL),
+    pPrevContent(NULL),
+    pNextInSlot(NULL),
+    ppPrevInSlot(NULL)
+{
+    if (!maOldCell.isEmpty())
+        SetCell(maOldValue, maOldCell, 0, pDoc);
+
     if (!sOldValue.isEmpty())     // #i40704# don't overwrite SetCell result with empty string
-        aOldValue = sOldValue; // set again, because SetCell removes it
+        maOldValue = sOldValue; // set again, because SetCell removes it
 }
 
 ScChangeActionContent::ScChangeActionContent( const sal_uLong nActionNumber,
-            ScBaseCell* pTempNewCell, const ScBigRange& aBigRangeP,
-            ScDocument* pDoc, const rtl::OUString& sNewValue )
-        :
-        ScChangeAction(SC_CAT_CONTENT, aBigRangeP, nActionNumber),
-        aNewValue(sNewValue),
-        pOldCell(NULL),
-        pNewCell(pTempNewCell),
-        pNextContent(NULL),
-        pPrevContent(NULL),
-        pNextInSlot(NULL),
-        ppPrevInSlot(NULL)
-{
-    if (pNewCell)
-        ScChangeActionContent::SetCell( aNewValue, pNewCell, 0, pDoc );
+            const ScCellValue& rNewCell, const ScBigRange& aBigRangeP,
+            ScDocument* pDoc, const OUString& sNewValue ) :
+    ScChangeAction(SC_CAT_CONTENT, aBigRangeP, nActionNumber),
+    maNewCell(rNewCell),
+    maNewValue(sNewValue),
+    pNextContent(NULL),
+    pPrevContent(NULL),
+    pNextInSlot(NULL),
+    ppPrevInSlot(NULL)
+{
+    if (!maNewCell.isEmpty())
+        SetCell(maNewValue, maNewCell, 0, pDoc);
+
     if (!sNewValue.isEmpty())     // #i40704# don't overwrite SetCell result with empty string
-        aNewValue = sNewValue; // set again, because SetCell removes it
+        maNewValue = sNewValue; // set again, because SetCell removes it
 }
 
 ScChangeActionContent::~ScChangeActionContent()
@@ -1428,87 +1435,91 @@ ScChangeActionLinkEntry** ScChangeActionContent::GetDeletedInAddress()
 }
 
 
-void ScChangeActionContent::SetOldValue( const ScBaseCell* pCell,
-        const ScDocument* pFromDoc, ScDocument* pToDoc, sal_uLong nFormat )
+void ScChangeActionContent::SetOldValue(
+    const ScCellValue& rCell, const ScDocument* pFromDoc, ScDocument* pToDoc, sal_uLong nFormat )
 {
-    SetValue( aOldValue, pOldCell, nFormat, pCell, pFromDoc, pToDoc );
+    SetValue(maOldValue, maOldCell, nFormat, rCell, pFromDoc, pToDoc);
 }
 
 
-void ScChangeActionContent::SetOldValue( const ScBaseCell* pCell,
-        const ScDocument* pFromDoc, ScDocument* pToDoc )
+void ScChangeActionContent::SetOldValue(
+    const ScCellValue& rCell, const ScDocument* pFromDoc, ScDocument* pToDoc )
 {
-    SetValue( aOldValue, pOldCell, aBigRange.aStart.MakeAddress(), pCell, pFromDoc, pToDoc );
+    SetValue(maOldValue, maOldCell, aBigRange.aStart.MakeAddress(), rCell, pFromDoc, pToDoc);
 }
 
 
-void ScChangeActionContent::SetNewValue( const ScBaseCell* pCell,
-        ScDocument* pDoc )
+void ScChangeActionContent::SetNewValue( const ScCellValue& rCell, ScDocument* pDoc )
 {
-    SetValue( aNewValue, pNewCell, aBigRange.aStart.MakeAddress(), pCell, pDoc, pDoc );
+    SetValue(maNewValue, maNewCell, aBigRange.aStart.MakeAddress(), rCell, pDoc, pDoc);
 }
 
 
-void ScChangeActionContent::SetOldNewCells( ScBaseCell* pOldCellP,
-                        sal_uLong nOldFormat, ScBaseCell* pNewCellP,
-                        sal_uLong nNewFormat, ScDocument* pDoc )
+void ScChangeActionContent::SetOldNewCells(
+    const ScCellValue& rOldCell, sal_uLong nOldFormat, const ScCellValue& rNewCell,
+    sal_uLong nNewFormat, ScDocument* pDoc )
 {
-    pOldCell = pOldCellP;
-    pNewCell = pNewCellP;
-    SetCell( aOldValue, pOldCell, nOldFormat, pDoc );
-    SetCell( aNewValue, pNewCell, nNewFormat, pDoc );
+    maOldCell = rOldCell;
+    maNewCell = rNewCell;
+    SetCell(maOldValue, maOldCell, nOldFormat, pDoc);
+    SetCell(maNewValue, maNewCell, nNewFormat, pDoc);
 }
 
 void ScChangeActionContent::SetNewCell(
-    ScBaseCell* pCell, ScDocument* pDoc, const rtl::OUString& rFormatted )
+    const ScCellValue& rCell, ScDocument* pDoc, const OUString& rFormatted )
 {
-    OSL_ENSURE( !pNewCell, "ScChangeActionContent::SetNewCell: overwriting existing cell" );
-    pNewCell = pCell;
-    SetCell( aNewValue, pNewCell, 0, pDoc );
+    maNewCell = rCell;
+    SetCell(maNewValue, maNewCell, 0, pDoc);
 
     // #i40704# allow to set formatted text here - don't call SetNewValue with string from XML filter
     if (!rFormatted.isEmpty())
-        aNewValue = rFormatted;
+        maNewValue = rFormatted;
 }
 
 void ScChangeActionContent::SetValueString(
-    rtl::OUString& rValue, ScBaseCell*& pCell, const rtl::OUString& rStr, ScDocument* pDoc )
+    OUString& rValue, ScCellValue& rCell, const OUString& rStr, ScDocument* pDoc )
 {
-    if ( pCell )
-    {
-        pCell->Delete();
-        pCell = NULL;
-    }
+    rCell.clear();
     if ( rStr.getLength() > 1 && rStr.getStr()[0] == '=' )
     {
-        rValue = rtl::OUString();
-        pCell = new ScFormulaCell(
+        rValue = EMPTY_OUSTRING;
+        rCell.meType = CELLTYPE_FORMULA;
+        rCell.mpFormula = new ScFormulaCell(
             pDoc, aBigRange.aStart.MakeAddress(), rStr,
-            formula::FormulaGrammar::GRAM_DEFAULT, formula::FormulaGrammar::CONV_OOO );
-        ((ScFormulaCell*)pCell)->SetInChangeTrack( true );
+            formula::FormulaGrammar::GRAM_DEFAULT, pDoc->GetGrammar() );
+        rCell.mpFormula->SetInChangeTrack(true);
     }
     else
         rValue = rStr;
 }
 
 
-void ScChangeActionContent::SetOldValue( const rtl::OUString& rOld, ScDocument* pDoc )
+void ScChangeActionContent::SetOldValue( const OUString& rOld, ScDocument* pDoc )
 {
-    SetValueString( aOldValue, pOldCell, rOld, pDoc );
+    SetValueString(maOldValue, maOldCell, rOld, pDoc);
 }
 
 
 void ScChangeActionContent::GetOldString( rtl::OUString& rStr ) const
 {
-    GetValueString( rStr, aOldValue, pOldCell );
+    GetValueString(rStr, maOldValue, maOldCell);
 }
 
 
 void ScChangeActionContent::GetNewString( rtl::OUString& rStr ) const
 {
-    GetValueString( rStr, aNewValue, pNewCell );
+    GetValueString(rStr, maNewValue, maNewCell);
+}
+
+const ScCellValue& ScChangeActionContent::GetOldCell() const
+{
+    return maOldCell;
 }
 
+const ScCellValue& ScChangeActionContent::GetNewCell() const
+{
+    return maNewCell;
+}
 
 void ScChangeActionContent::GetDescription(
     rtl::OUString& rStr, ScDocument* pDoc, bool bSplitRange, bool bWarning ) const
@@ -1562,13 +1573,13 @@ void ScChangeActionContent::GetRefString(
     sal_uInt16 nFlags = ( GetBigRange().IsValid( pDoc ) ? SCA_VALID : 0 );
     if ( nFlags )
     {
-        const ScBaseCell* pCell = GetNewCell();
-        if ( GetContentCellType( pCell ) == SC_CACCT_MATORG )
+        const ScCellValue& rCell = GetNewCell();
+        if ( GetContentCellType(rCell) == SC_CACCT_MATORG )
         {
             ScBigRange aLocalBigRange( GetBigRange() );
             SCCOL nC;
             SCROW nR;
-            ((const ScFormulaCell*)pCell)->GetMatColsRows( nC, nR );
+            rCell.mpFormula->GetMatColsRows( nC, nR );
             aLocalBigRange.aEnd.IncCol( nC-1 );
             aLocalBigRange.aEnd.IncRow( nR-1 );
             rStr = ScChangeAction::GetRefString( aLocalBigRange, pDoc, bFlag3D );
@@ -1645,7 +1656,9 @@ bool ScChangeActionContent::Select( ScDocument* pDoc, ScChangeTrack* pTrack,
         const ScAddress& rPos = aRange.aStart;
 
         ScChangeActionContent* pNew = new ScChangeActionContent( aRange );
-        pNew->SetOldValue( pDoc->GetCell( rPos ), pDoc, pDoc );
+        ScCellValue aCell;
+        aCell.assign(*pDoc, rPos);
+        pNew->SetOldValue(aCell, pDoc, pDoc);
 
         if ( bOldest )
             PutOldValueToDoc( pDoc, 0, 0 );
@@ -1658,7 +1671,8 @@ bool ScChangeActionContent::Select( ScDocument* pDoc, ScChangeTrack* pTrack,
             pRejectActions->push( pNew );
         else
         {
-            pNew->SetNewValue( pDoc->GetCell( rPos ), pDoc );
+            aCell.assign(*pDoc, rPos);
+            pNew->SetNewValue(aCell, pDoc);
             pTrack->Append( pNew );
         }
     }
@@ -1672,83 +1686,72 @@ bool ScChangeActionContent::Select( ScDocument* pDoc, ScChangeTrack* pTrack,
 }
 
 
-void ScChangeActionContent::GetStringOfCell( rtl::OUString& rStr,
-    const ScBaseCell* pCell, const ScDocument* pDoc, const ScAddress& rPos )
+void ScChangeActionContent::GetStringOfCell(
+    OUString& rStr, const ScCellValue& rCell, const ScDocument* pDoc, const ScAddress& rPos )
 {
-    if ( pCell )
-    {
-        if ( NeedsNumberFormat( pCell ) )
-            GetStringOfCell( rStr, pCell, pDoc, pDoc->GetNumberFormat( rPos ) );
-        else
-            GetStringOfCell( rStr, pCell, pDoc, 0 );
-    }
+    if (NeedsNumberFormat(rCell))
+        GetStringOfCell(rStr, rCell, pDoc, pDoc->GetNumberFormat(rPos));
     else
-        rStr = rtl::OUString();
+        GetStringOfCell(rStr, rCell, pDoc, 0);
 }
 
 
-void ScChangeActionContent::GetStringOfCell( rtl::OUString& rStr,
-    const ScBaseCell* pCell, const ScDocument* pDoc, sal_uLong nFormat )
+void ScChangeActionContent::GetStringOfCell(
+    OUString& rStr, const ScCellValue& rCell, const ScDocument* pDoc, sal_uLong nFormat )
 {
-    if ( GetContentCellType( pCell ) )
+    rStr = EMPTY_OUSTRING;
+
+    if (!GetContentCellType(rCell))
+        return;
+
+    switch (rCell.meType)
     {
-        switch ( pCell->GetCellType() )
-        {
-            case CELLTYPE_VALUE :
-            {
-                double nValue = ((ScValueCell*)pCell)->GetValue();
-                pDoc->GetFormatTable()->GetInputLineString( nValue, nFormat,
-                    rStr );
-            }
-            break;
-            case CELLTYPE_STRING :
-                rStr = ((ScStringCell*)pCell)->GetString();
-            break;
-            case CELLTYPE_EDIT :
-                rStr = ((ScEditCell*)pCell)->GetString();
-            break;
-            case CELLTYPE_FORMULA :
-                ((ScFormulaCell*)pCell)->GetFormula( rStr );
-            break;
-            default:
-                rStr = rtl::OUString();
-        }
+        case CELLTYPE_VALUE:
+            pDoc->GetFormatTable()->GetInputLineString(rCell.mfValue, nFormat, rStr);
+        break;
+        case CELLTYPE_STRING:
+            rStr = *rCell.mpString;
+        break;
+        case CELLTYPE_EDIT:
+            if (rCell.mpEditText)
+                rStr = ScEditUtil::GetString(*rCell.mpEditText);
+        break;
+        case CELLTYPE_FORMULA:
+            rCell.mpFormula->GetFormula(rStr);
+        break;
+        default:
+            ;
     }
-    else
-        rStr = rtl::OUString();
 }
 
 
-ScChangeActionContentCellType ScChangeActionContent::GetContentCellType( const ScBaseCell* pCell )
+ScChangeActionContentCellType ScChangeActionContent::GetContentCellType( const ScCellValue& rCell )
 {
-    if ( pCell )
+    switch (rCell.meType)
     {
-        switch ( pCell->GetCellType() )
-        {
-            case CELLTYPE_VALUE :
-            case CELLTYPE_STRING :
-            case CELLTYPE_EDIT :
-                return SC_CACCT_NORMAL;
-            //break;
-            case CELLTYPE_FORMULA :
-                switch ( ((const ScFormulaCell*)pCell)->GetMatrixFlag() )
-                {
-                    case MM_NONE :
-                        return SC_CACCT_NORMAL;
-                    //break;
-                    case MM_FORMULA :
-                    case MM_FAKE :
-                        return SC_CACCT_MATORG;
-                    //break;
-                    case MM_REFERENCE :
-                        return SC_CACCT_MATREF;
-                    //break;
-                }
-                return SC_CACCT_NORMAL;
-            //break;
-            default:
-                return SC_CACCT_NONE;
-        }
+        case CELLTYPE_VALUE :
+        case CELLTYPE_STRING :
+        case CELLTYPE_EDIT :
+            return SC_CACCT_NORMAL;
+        //break;
+        case CELLTYPE_FORMULA :
+            switch (rCell.mpFormula->GetMatrixFlag())
+            {
+                case MM_NONE :
+                    return SC_CACCT_NORMAL;
+                //break;
+                case MM_FORMULA :
+                case MM_FAKE :
+                    return SC_CACCT_MATORG;
+                //break;
+                case MM_REFERENCE :
+                    return SC_CACCT_MATREF;
+                //break;
+            }
+            return SC_CACCT_NORMAL;
+        //break;
+        default:
+            return SC_CACCT_NONE;
     }
     return SC_CACCT_NONE;
 }
@@ -1785,41 +1788,38 @@ ScChangeActionContentCellType ScChangeActionContent::GetContentCellType( const S
     return SC_CACCT_NONE;
 }
 
-bool ScChangeActionContent::NeedsNumberFormat( const ScBaseCell* pCell )
+bool ScChangeActionContent::NeedsNumberFormat( const ScCellValue& rVal )
 {
-    return pCell && pCell->GetCellType() == CELLTYPE_VALUE;
+    return rVal.meType == CELLTYPE_VALUE;
 }
 
-
 void ScChangeActionContent::SetValue(
-    rtl::OUString& rStr, ScBaseCell*& pCell, const ScAddress& rPos, const ScBaseCell* pOrgCell,
+    OUString& rStr, ScCellValue& rCell, const ScAddress& rPos, const ScCellValue& rOrgCell,
     const ScDocument* pFromDoc, ScDocument* pToDoc )
 {
-    sal_uLong nFormat = NeedsNumberFormat( pOrgCell ) ? pFromDoc->GetNumberFormat( rPos ) : 0;
-    SetValue( rStr, pCell, nFormat, pOrgCell, pFromDoc, pToDoc );
+    sal_uLong nFormat = NeedsNumberFormat(rOrgCell) ? pFromDoc->GetNumberFormat(rPos) : 0;
+    SetValue(rStr, rCell, nFormat, rOrgCell, pFromDoc, pToDoc);
 }
 
 void ScChangeActionContent::SetValue(
-    rtl::OUString& rStr, ScBaseCell*& pCell, sal_uLong nFormat, const ScBaseCell* pOrgCell,
+    OUString& rStr, ScCellValue& rCell, sal_uLong nFormat, const ScCellValue& rOrgCell,
     const ScDocument* pFromDoc, ScDocument* pToDoc )
 {
-    rStr = rtl::OUString();
-    if ( pCell )
-        pCell->Delete();
-    if ( GetContentCellType( pOrgCell ) )
+    rStr = OUString();
+
+    if (GetContentCellType(rOrgCell))
     {
-        pCell = pOrgCell->Clone( *pToDoc );
-        switch ( pOrgCell->GetCellType() )
+        rCell.assign(rOrgCell, *pToDoc);
+        switch (rOrgCell.meType)
         {
             case CELLTYPE_VALUE :
             {   // z.B. Datum auch als solches merken
-                double nValue = ((ScValueCell*)pOrgCell)->GetValue();
-                pFromDoc->GetFormatTable()->GetInputLineString( nValue,
-                    nFormat, rStr );
+                pFromDoc->GetFormatTable()->GetInputLineString(
+                    rOrgCell.mfValue, nFormat, rStr);
             }
             break;
             case CELLTYPE_FORMULA :
-                ((ScFormulaCell*)pCell)->SetInChangeTrack( true );
+                rCell.mpFormula->SetInChangeTrack(true);
             break;
             default:
             {
@@ -1828,69 +1828,61 @@ void ScChangeActionContent::SetValue(
         }
     }
     else
-        pCell = NULL;
+        rCell.clear();
 }
 
-
-void ScChangeActionContent::SetCell(
-    rtl::OUString& rStr, ScBaseCell* pCell, sal_uLong nFormat, const ScDocument* pDoc )
+void ScChangeActionContent::SetCell( OUString& rStr, ScCellValue& rCell, sal_uLong nFormat, const ScDocument* pDoc )
 {
-    rStr = rtl::OUString();
-    if ( pCell )
+    rStr = OUString();
+    if (rCell.isEmpty())
+        return;
+
+    switch (rCell.meType)
     {
-        switch ( pCell->GetCellType() )
+        case CELLTYPE_VALUE :
+            // e.g. remember date as date string
+            pDoc->GetFormatTable()->GetInputLineString(rCell.mfValue, nFormat, rStr);
+        break;
+        case CELLTYPE_FORMULA :
+            rCell.mpFormula->SetInChangeTrack(true);
+        break;
+        default:
         {
-            case CELLTYPE_VALUE :
-            {   // e.g. remember date as date string
-                double nValue = ((ScValueCell*)pCell)->GetValue();
-                pDoc->GetFormatTable()->GetInputLineString( nValue,
-                    nFormat, rStr );
-            }
-            break;
-            case CELLTYPE_FORMULA :
-                ((ScFormulaCell*)pCell)->SetInChangeTrack( true );
-            break;
-            default:
-            {
-                // added to avoid warnings
-            }
+            // added to avoid warnings
         }
     }
 }
 
 
 void ScChangeActionContent::GetValueString(
-    rtl::OUString& rStr, const rtl::OUString& rValue, const ScBaseCell* pCell ) const
+    OUString& rStr, const OUString& rValue, const ScCellValue& rCell ) const
 {
-    if (rValue.isEmpty())
+    if (!rValue.isEmpty())
+    {
+        rStr = rValue;
+        return;
+    }
+
+    switch (rCell.meType)
     {
-        if ( pCell )
+        case CELLTYPE_STRING :
+            rStr = *rCell.mpString;
+        break;
+        case CELLTYPE_EDIT :
+            if (rCell.mpEditText)
+                rStr = ScEditUtil::GetString(*rCell.mpEditText);
+        break;
+        case CELLTYPE_VALUE :   // ist immer in rValue
+            rStr = rValue;
+        break;
+        case CELLTYPE_FORMULA :
+            GetFormulaString(rStr, rCell.mpFormula);
+        break;
+        default:
         {
-            switch ( pCell->GetCellType() )
-            {
-                case CELLTYPE_STRING :
-                    rStr = ((ScStringCell*)pCell)->GetString();
-                break;
-                case CELLTYPE_EDIT :
-                    rStr = ((ScEditCell*)pCell)->GetString();
-                break;
-                case CELLTYPE_VALUE :   // ist immer in rValue
-                    rStr = rValue;
-                break;
-                case CELLTYPE_FORMULA :
-                    GetFormulaString( rStr, (ScFormulaCell*) pCell );
-                break;
-                default:
-                {
-                    // added to avoid warnings
-                }
-            }
+            // added to avoid warnings
         }
-        else
-            rStr = rtl::OUString();
     }
-    else
-        rStr = rValue;
 }
 
 
@@ -1913,19 +1905,19 @@ void ScChangeActionContent::GetFormulaString(
 void ScChangeActionContent::PutOldValueToDoc( ScDocument* pDoc,
         SCsCOL nDx, SCsROW nDy ) const
 {
-    PutValueToDoc( pOldCell, aOldValue, pDoc, nDx, nDy );
+    PutValueToDoc(maOldCell, maOldValue, pDoc, nDx, nDy);
 }
 
 
 void ScChangeActionContent::PutNewValueToDoc( ScDocument* pDoc,
         SCsCOL nDx, SCsROW nDy ) const
 {
-    PutValueToDoc( pNewCell, aNewValue, pDoc, nDx, nDy );
+    PutValueToDoc(maNewCell, maNewValue, pDoc, nDx, nDy);
 }
 
 
 void ScChangeActionContent::PutValueToDoc(
-    ScBaseCell* pCell, const rtl::OUString& rValue, ScDocument* pDoc,
+    const ScCellValue& rCell, const OUString& rValue, ScDocument* pDoc,
     SCsCOL nDx, SCsROW nDy ) const
 {
     ScAddress aPos( aBigRange.aStart.MakeAddress() );
@@ -1933,51 +1925,52 @@ void ScChangeActionContent::PutValueToDoc(
         aPos.IncCol( nDx );
     if ( nDy )
         aPos.IncRow( nDy );
-    if (rValue.isEmpty())
+
+    if (!rValue.isEmpty())
+    {
+        pDoc->SetString(aPos, rValue);
+        return;
+    }
+
+    if (rCell.isEmpty())
+    {
+        pDoc->SetEmptyCell(aPos);
+        return;
+    }
+
+    if (rCell.meType == CELLTYPE_VALUE)
     {
-        if ( pCell )
+        pDoc->SetString( aPos.Col(), aPos.Row(), aPos.Tab(), rValue );
+        return;
+    }
+
+    switch (GetContentCellType(rCell))
+    {
+        case SC_CACCT_MATORG :
         {
-            switch ( pCell->GetCellType() )
-            {
-                case CELLTYPE_VALUE :   // ist immer in rValue
-                    pDoc->SetString( aPos.Col(), aPos.Row(), aPos.Tab(), rValue );
-                break;
-                default:
-                    switch ( GetContentCellType( pCell ) )
-                    {
-                        case SC_CACCT_MATORG :
-                        {
-                            SCCOL nC;
-                            SCROW nR;
-                            ((const ScFormulaCell*)pCell)->GetMatColsRows( nC, nR );
-                            OSL_ENSURE( nC>0 && nR>0, "ScChangeActionContent::PutValueToDoc: MatColsRows?" );
-                            ScRange aRange( aPos );
-                            if ( nC > 1 )
-                                aRange.aEnd.IncCol( nC-1 );
-                            if ( nR > 1 )
-                                aRange.aEnd.IncRow( nR-1 );
-                            ScMarkData aDestMark;
-                            aDestMark.SelectOneTable( aPos.Tab() );
-                            aDestMark.SetMarkArea( aRange );
-                            pDoc->InsertMatrixFormula( aPos.Col(), aPos.Row(),
-                                aRange.aEnd.Col(), aRange.aEnd.Row(),
-                                aDestMark, EMPTY_OUSTRING,
-                                ((const ScFormulaCell*)pCell)->GetCode() );
-                        }
-                        break;
-                        case SC_CACCT_MATREF :
-                            // nothing
-                        break;
-                        default:
-                            pDoc->PutCell( aPos, pCell->Clone( *pDoc ) );
-                    }
-            }
+            SCCOL nC;
+            SCROW nR;
+            rCell.mpFormula->GetMatColsRows(nC, nR);
+            OSL_ENSURE( nC>0 && nR>0, "ScChangeActionContent::PutValueToDoc: MatColsRows?" );
+            ScRange aRange( aPos );
+            if ( nC > 1 )
+                aRange.aEnd.IncCol( nC-1 );
+            if ( nR > 1 )
+                aRange.aEnd.IncRow( nR-1 );
+            ScMarkData aDestMark;
+            aDestMark.SelectOneTable( aPos.Tab() );
+            aDestMark.SetMarkArea( aRange );
+            pDoc->InsertMatrixFormula( aPos.Col(), aPos.Row(),
+                aRange.aEnd.Col(), aRange.aEnd.Row(),
+                aDestMark, EMPTY_OUSTRING, rCell.mpFormula->GetCode());
         }
-        else
-            pDoc->SetEmptyCell(aPos);
+        break;
+        case SC_CACCT_MATREF :
+            // nothing
+        break;
+        default:
+            rCell.commit(*pDoc, aPos);
     }
-    else
-        pDoc->SetString(aPos, rValue);
 }
 
 
@@ -2043,8 +2036,8 @@ void ScChangeActionContent::UpdateReference( const ScChangeTrack* pTrack,
     if ( pTrack->IsInDelete() && !pTrack->IsInDeleteTop() )
         return ;        // Formeln nur kompletten Bereich updaten
 
-    bool bOldFormula = ( pOldCell && pOldCell->GetCellType() == CELLTYPE_FORMULA );
-    bool bNewFormula = ( pNewCell && pNewCell->GetCellType() == CELLTYPE_FORMULA );
+    bool bOldFormula = maOldCell.meType == CELLTYPE_FORMULA;
+    bool bNewFormula = maNewCell.meType == CELLTYPE_FORMULA;
     if ( bOldFormula || bNewFormula )
     {   // via ScFormulaCell UpdateReference anpassen (dort)
         if ( pTrack->IsInDelete() )
@@ -2082,9 +2075,9 @@ void ScChangeActionContent::UpdateReference( const ScChangeTrack* pTrack,
                 // Move ist hier Quelle, dort Ziel,
                 // Position muss vorher angepasst sein.
                 if ( bOldFormula )
-                    ((ScFormulaCell*)pOldCell)->aPos = aBigRange.aStart.MakeAddress();
+                    maOldCell.mpFormula->aPos = aBigRange.aStart.MakeAddress();
                 if ( bNewFormula )
-                    ((ScFormulaCell*)pNewCell)->aPos = aBigRange.aStart.MakeAddress();
+                    maNewCell.mpFormula->aPos = aBigRange.aStart.MakeAddress();
                 if ( nDx )
                 {
                     aTmpRange.aStart.IncCol( nDx );
@@ -2108,10 +2101,10 @@ void ScChangeActionContent::UpdateReference( const ScChangeTrack* pTrack,
         }
         ScRange aRange( aTmpRange.MakeRange() );
         if ( bOldFormula )
-            ((ScFormulaCell*)pOldCell)->UpdateReference( eMode, aRange,
+            maOldCell.mpFormula->UpdateReference( eMode, aRange,
                 (SCsCOL) nDx, (SCsROW) nDy, (SCsTAB) nDz, NULL );
         if ( bNewFormula )
-            ((ScFormulaCell*)pNewCell)->UpdateReference( eMode, aRange,
+            maNewCell.mpFormula->UpdateReference( eMode, aRange,
                 (SCsCOL) nDx, (SCsROW) nDy, (SCsTAB) nDz, NULL );
         if ( !aBigRange.aStart.IsValid( pTrack->GetDocument() ) )
         {   //! HACK!
@@ -2122,7 +2115,7 @@ void ScChangeActionContent::UpdateReference( const ScChangeTrack* pTrack,
             if ( bOldFormula )
             {
                 ScToken* t;
-                ScTokenArray* pArr = ((ScFormulaCell*)pOldCell)->GetCode();
+                ScTokenArray* pArr = maOldCell.mpFormula->GetCode();
                 pArr->Reset();
                 while ( ( t = static_cast<ScToken*>(pArr->GetNextReference()) ) != NULL )
                     lcl_InvalidateReference( *t, rPos );
@@ -2133,7 +2126,7 @@ void ScChangeActionContent::UpdateReference( const ScChangeTrack* pTrack,
             if ( bNewFormula )
             {
                 ScToken* t;
-                ScTokenArray* pArr = ((ScFormulaCell*)pNewCell)->GetCode();
+                ScTokenArray* pArr = maNewCell.mpFormula->GetCode();
                 pArr->Reset();
                 while ( ( t = static_cast<ScToken*>(pArr->GetNextReference()) ) != NULL )
                     lcl_InvalidateReference( *t, rPos );
@@ -2702,8 +2695,7 @@ void ScChangeTrack::LookUpContents( const ScRange& rOrgRange,
         aPos.Set( aIter.GetPos().Col() + nDx, aIter.GetPos().Row() + nDy,
             aIter.GetPos().Tab() + nDz );
 
-        ScBaseCell* pCell = aIter.getHackedBaseCell();
-        GenerateDelContent( aPos, pCell, pRefDoc );
+        GenerateDelContent(aPos, aIter.getCellValue(), pRefDoc);
         //! der Content wird hier _nicht_ per AddContent hinzugefuegt,
         //! sondern in UpdateReference, um z.B. auch kreuzende Deletes
         //! korrekt zu erfassen
@@ -2721,37 +2713,42 @@ void ScChangeTrack::AppendMove( const ScRange& rFromRange,
 
 
 bool ScChangeTrack::IsMatrixFormulaRangeDifferent(
-    const ScBaseCell* pOldCell, const ScBaseCell* pNewCell )
+    const ScCellValue& rOldCell, const ScCellValue& rNewCell )
 {
     SCCOL nC1, nC2;
     SCROW nR1, nR2;
     nC1 = nC2 = 0;
     nR1 = nR2 = 0;
-    if ( pOldCell && (pOldCell->GetCellType() == CELLTYPE_FORMULA) &&
-            ((const ScFormulaCell*)pOldCell)->GetMatrixFlag() == MM_FORMULA )
-        ((const ScFormulaCell*)pOldCell)->GetMatColsRows( nC1, nR1 );
-    if ( pNewCell && (pNewCell->GetCellType() == CELLTYPE_FORMULA) &&
-            ((const ScFormulaCell*)pNewCell)->GetMatrixFlag() == MM_FORMULA )
-        ((const ScFormulaCell*)pNewCell)->GetMatColsRows( nC1, nR1 );
+
+    if (rOldCell.meType == CELLTYPE_FORMULA && rOldCell.mpFormula->GetMatrixFlag() == MM_FORMULA)
+        rOldCell.mpFormula->GetMatColsRows(nC1, nR1);
+
+    if (rNewCell.meType == CELLTYPE_FORMULA && rNewCell.mpFormula->GetMatrixFlag() == MM_FORMULA)
+        rNewCell.mpFormula->GetMatColsRows(nC1, nR1);
+
     return nC1 != nC2 || nR1 != nR2;
 }
 
-void ScChangeTrack::AppendContent( const ScAddress& rPos,
-        const ScBaseCell* pOldCell, sal_uLong nOldFormat, ScDocument* pRefDoc )
+void ScChangeTrack::AppendContent(
+    const ScAddress& rPos, const ScCellValue& rOldCell, sal_uLong nOldFormat, ScDocument* pRefDoc )
 {
     if ( !pRefDoc )
         pRefDoc = pDoc;
-    rtl::OUString aOldValue;
-    ScChangeActionContent::GetStringOfCell( aOldValue, pOldCell, pRefDoc, nOldFormat );
-    rtl::OUString aNewValue;
-    ScBaseCell* pNewCell = pDoc->GetCell( rPos );
-    ScChangeActionContent::GetStringOfCell( aNewValue, pNewCell, pDoc, rPos );
-    if (!aOldValue.equals(aNewValue) || IsMatrixFormulaRangeDifferent(pOldCell, pNewCell))
+
+    OUString aOldValue;
+    ScChangeActionContent::GetStringOfCell(aOldValue, rOldCell, pRefDoc, nOldFormat);
+
+    OUString aNewValue;
+    ScCellValue aNewCell;
+    aNewCell.assign(*pDoc, rPos);
+    ScChangeActionContent::GetStringOfCell(aNewValue, aNewCell, pDoc, rPos);
+
+    if (!aOldValue.equals(aNewValue) || IsMatrixFormulaRangeDifferent(rOldCell, aNewCell))
     {   // nur wirkliche Aenderung tracken
         ScRange aRange( rPos );
         ScChangeActionContent* pAct = new ScChangeActionContent( aRange );
-        pAct->SetOldValue( pOldCell, pRefDoc, pDoc, nOldFormat );
-        pAct->SetNewValue( pNewCell, pDoc );
+        pAct->SetOldValue(rOldCell, pRefDoc, pDoc, nOldFormat);
+        pAct->SetNewValue(aNewCell, pDoc);
         Append( pAct );
     }
 }
@@ -2760,30 +2757,33 @@ void ScChangeTrack::AppendContent( const ScAddress& rPos,
 void ScChangeTrack::AppendContent( const ScAddress& rPos,
         ScDocument* pRefDoc )
 {
-    rtl::OUString aOldValue;
-    ScBaseCell* pOldCell = pRefDoc->GetCell( rPos );
-    ScChangeActionContent::GetStringOfCell( aOldValue, pOldCell, pRefDoc, rPos );
-    rtl::OUString aNewValue;
-    ScBaseCell* pNewCell = pDoc->GetCell( rPos );
-    ScChangeActionContent::GetStringOfCell( aNewValue, pNewCell, pDoc, rPos );
-    if (!aOldValue.equals(aNewValue) || IsMatrixFormulaRangeDifferent(pOldCell, pNewCell))
+    OUString aOldValue;
+    ScCellValue aOldCell;
+    aOldCell.assign(*pRefDoc, rPos);
+    ScChangeActionContent::GetStringOfCell(aOldValue, aOldCell, pRefDoc, rPos);
+
+    OUString aNewValue;
+    ScCellValue aNewCell;
+    aNewCell.assign(*pDoc, rPos);
+    ScChangeActionContent::GetStringOfCell(aNewValue, aNewCell, pDoc, rPos);
+
+    if (!aOldValue.equals(aNewValue) || IsMatrixFormulaRangeDifferent(aOldCell, aNewCell))
     {   // nur wirkliche Aenderung tracken
         ScRange aRange( rPos );
         ScChangeActionContent* pAct = new ScChangeActionContent( aRange );
-        pAct->SetOldValue( pOldCell, pRefDoc, pDoc );
-        pAct->SetNewValue( pNewCell, pDoc );
+        pAct->SetOldValue(aOldCell, pRefDoc, pDoc);
+        pAct->SetNewValue(aNewCell, pDoc);
         Append( pAct );
     }
 }
 
 
-void ScChangeTrack::AppendContent( const ScAddress& rPos,
-        const ScBaseCell* pOldCell )
+void ScChangeTrack::AppendContent( const ScAddress& rPos, const ScCellValue& rOldCell )
 {
-    if ( ScChangeActionContent::NeedsNumberFormat( pOldCell ) )
-        AppendContent( rPos, pOldCell, pDoc->GetNumberFormat( rPos ), pDoc );
+    if (ScChangeActionContent::NeedsNumberFormat(rOldCell))
+        AppendContent(rPos, rOldCell, pDoc->GetNumberFormat(rPos), pDoc);
     else
-        AppendContent( rPos, pOldCell, 0, pDoc );
+        AppendContent(rPos, rOldCell, 0, pDoc);
 }
 
 
@@ -2917,7 +2917,7 @@ void ScChangeTrack::AppendContentsIfInRefDoc( ScDocument* pRefDoc,
             SCTAB nTab;
             aIter.GetPos( nCol, nRow, nTab );
             ScAddress aPos( nCol, nRow, nTab );
-            AppendContent( aPos, aIter.GetCell(),
+            AppendContent( aPos, aIter.GetCellValue(),
                 aIter.GetPattern()->GetNumberFormat( pFormatter ), pRefDoc );
         } while ( aIter.GetNext() );
         nEndAction = GetActionMax();
@@ -2929,12 +2929,12 @@ void ScChangeTrack::AppendContentsIfInRefDoc( ScDocument* pRefDoc,
 
 
 ScChangeActionContent* ScChangeTrack::AppendContentOnTheFly(
-        const ScAddress& rPos, ScBaseCell* pOldCell, ScBaseCell* pNewCell,
-        sal_uLong nOldFormat, sal_uLong nNewFormat )
+    const ScAddress& rPos, const ScCellValue& rOldCell, const ScCellValue& rNewCell,
+    sal_uLong nOldFormat, sal_uLong nNewFormat )
 {
     ScRange aRange( rPos );
     ScChangeActionContent* pAct = new ScChangeActionContent( aRange );
-    pAct->SetOldNewCells( pOldCell, nOldFormat, pNewCell, nNewFormat, pDoc );
+    pAct->SetOldNewCells(rOldCell, nOldFormat, rNewCell, nNewFormat, pDoc);
     Append( pAct );
     return pAct;
 }
@@ -2966,15 +2966,14 @@ void ScChangeTrack::DeleteCellEntries( ScChangeActionCellListEntry*& pCellList,
 
 
 ScChangeActionContent* ScChangeTrack::GenerateDelContent(
-        const ScAddress& rPos, const ScBaseCell* pCell,
-        const ScDocument* pFromDoc )
+        const ScAddress& rPos, const ScCellValue& rCell, const ScDocument* pFromDoc )
 {
     ScChangeActionContent* pContent = new ScChangeActionContent(
         ScRange( rPos ) );
     pContent->SetActionNumber( --nGeneratedMin );
     // nur NewValue
-    ScChangeActionContent::SetValue( pContent->aNewValue, pContent->pNewCell,
-        rPos, pCell, pFromDoc, pDoc );
+    ScChangeActionContent::SetValue( pContent->maNewValue, pContent->maNewCell,
+        rPos, rCell, pFromDoc, pDoc );
     // pNextContent und pPrevContent werden nicht gesetzt
     if ( pFirstGeneratedDelContent )
     {   // vorne reinhaengen
@@ -3060,11 +3059,11 @@ void ScChangeTrack::Dependencies( ScChangeAction* pAct )
                 ((ScChangeActionContent*)pAct)->SetPrevContent( pContent );
             }
         }
-        const ScBaseCell* pCell = ((ScChangeActionContent*)pAct)->GetNewCell();
-        if ( ScChangeActionContent::GetContentCellType( pCell ) == SC_CACCT_MATREF )
+        const ScCellValue& rCell = static_cast<ScChangeActionContent*>(pAct)->GetNewCell();
+        if ( ScChangeActionContent::GetContentCellType(rCell) == SC_CACCT_MATREF )
         {
             ScAddress aOrg;
-            ((const ScFormulaCell*)pCell)->GetMatrixOrigin( aOrg );
+            rCell.mpFormula->GetMatrixOrigin(aOrg);
             ScChangeActionContent* pContent = SearchContentAt( aOrg, pAct );
             if ( pContent && pContent->IsMatrixOrigin() )
             {
@@ -4212,13 +4211,12 @@ bool ScChangeTrack::SelectContent( ScChangeAction* pAct, bool bOldest )
         return false;
 
     ScBigRange aBigRange( pContent->GetBigRange() );
-    const ScBaseCell* pCell = (bOldest ? pContent->GetOldCell() :
-        pContent->GetNewCell());
-    if ( ScChangeActionContent::GetContentCellType( pCell ) == SC_CACCT_MATORG )
+    const ScCellValue& rCell = (bOldest ? pContent->GetOldCell() : pContent->GetNewCell());
+    if ( ScChangeActionContent::GetContentCellType(rCell) == SC_CACCT_MATORG )
     {
         SCCOL nC;
         SCROW nR;
-        ((const ScFormulaCell*)pCell)->GetMatColsRows( nC, nR );
+        rCell.mpFormula->GetMatColsRows(nC, nR);
         aBigRange.aEnd.IncCol( nC-1 );
         aBigRange.aEnd.IncRow( nR-1 );
     }
@@ -4264,7 +4262,9 @@ bool ScChangeTrack::SelectContent( ScChangeAction* pAct, bool bOldest )
             pNew = aRejectActions.top();
             aRejectActions.pop();
             ScAddress aPos( pNew->GetBigRange().aStart.MakeAddress() );
-            pNew->SetNewValue( pDoc->GetCell( aPos ), pDoc );
+            ScCellValue aCell;
+            aCell.assign(*pDoc, aPos);
+            pNew->SetNewValue(aCell, pDoc);
             Append( pNew );
         }
         return bOk;
@@ -4499,11 +4499,15 @@ bool ScChangeTrack::Reject(
         {
             aRange = pAct->GetBigRange().aStart.MakeAddress();
             pReject = new ScChangeActionContent( aRange );
-            pReject->SetOldValue( pDoc->GetCell( aRange.aStart ), pDoc, pDoc );
+            ScCellValue aCell;
+            aCell.assign(*pDoc, aRange.aStart);
+            pReject->SetOldValue(aCell, pDoc, pDoc);
         }
         if ( (bRejected = pAct->Reject( pDoc )) != false && !bRecursion )
         {
-            pReject->SetNewValue( pDoc->GetCell( aRange.aStart ), pDoc );
+            ScCellValue aCell;
+            aCell.assign(*pDoc, aRange.aStart);
+            pReject->SetNewValue(aCell, pDoc);
             pReject->SetRejectAction( pAct->GetActionNumber() );
             pReject->SetState( SC_CAS_ACCEPTED );
             Append( pReject );
@@ -4521,9 +4525,9 @@ bool ScChangeTrack::Reject(
 
 
 sal_uLong ScChangeTrack::AddLoadedGenerated(
-    ScBaseCell* pNewCell, const ScBigRange& aBigRange, const rtl::OUString& sNewValue )
+    const ScCellValue& rNewCell, const ScBigRange& aBigRange, const rtl::OUString& sNewValue )
 {
-    ScChangeActionContent* pAct = new ScChangeActionContent( --nGeneratedMin, pNewCell, aBigRange, pDoc, sNewValue );
+    ScChangeActionContent* pAct = new ScChangeActionContent( --nGeneratedMin, rNewCell, aBigRange, pDoc, sNewValue );
     if ( pAct )
     {
         if ( pFirstGeneratedDelContent )
@@ -4573,14 +4577,15 @@ ScChangeTrack* ScChangeTrack::Clone( ScDocument* pDocument ) const
         aGeneratedStack.pop();
         const ScChangeActionContent* pContent = dynamic_cast< const ScChangeActionContent* >( pGenerated );
         OSL_ENSURE( pContent, "ScChangeTrack::Clone: pContent is null!" );
-        const ScBaseCell* pNewCell = pContent->GetNewCell();
-        if ( pNewCell )
+        const ScCellValue& rNewCell = pContent->GetNewCell();
+        if (!rNewCell.isEmpty())
         {
-            ScBaseCell* pClonedNewCell = pNewCell->Clone( *pDocument );
-            rtl::OUString aNewValue;
+            ScCellValue aClonedNewCell;
+            aClonedNewCell.assign(rNewCell, *pDocument);
+            OUString aNewValue;
             pContent->GetNewString( aNewValue );
             pClonedTrack->nGeneratedMin = pGenerated->GetActionNumber() + 1;
-            pClonedTrack->AddLoadedGenerated( pClonedNewCell, pGenerated->GetBigRange(), aNewValue );
+            pClonedTrack->AddLoadedGenerated(aClonedNewCell, pGenerated->GetBigRange(), aNewValue);
         }
     }
 
@@ -4659,9 +4664,10 @@ ScChangeTrack* ScChangeTrack::Clone( ScDocument* pDocument ) const
                 {
                     const ScChangeActionContent* pContent = dynamic_cast< const ScChangeActionContent* >( pAction );
                     OSL_ENSURE( pContent, "ScChangeTrack::Clone: pContent is null!" );
-                    const ScBaseCell* pOldCell = pContent->GetOldCell();
-                    ScBaseCell* pClonedOldCell = pOldCell ? pOldCell->Clone( *pDocument ) : 0;
-                    rtl::OUString aOldValue;
+                    const ScCellValue& rOldCell = pContent->GetOldCell();
+                    ScCellValue aClonedOldCell;
+                    aClonedOldCell.assign(rOldCell, *pDocument);
+                    OUString aOldValue;
                     pContent->GetOldString( aOldValue );
 
                     ScChangeActionContent* pClonedContent = new ScChangeActionContent(
@@ -4672,15 +4678,16 @@ ScChangeTrack* ScChangeTrack::Clone( ScDocument* pDocument ) const
                         pAction->GetUser(),
                         pAction->GetDateTimeUTC(),
                         pAction->GetComment(),
-                        pClonedOldCell,
+                        aClonedOldCell,
                         pDocument,
                         aOldValue );
 
-                    const ScBaseCell* pNewCell = pContent->GetNewCell();
-                    if ( pNewCell )
+                    const ScCellValue& rNewCell = pContent->GetNewCell();
+                    if (!rNewCell.isEmpty())
                     {
-                        ScBaseCell* pClonedNewCell = pNewCell->Clone( *pDocument );
-                        pClonedContent->SetNewValue( pClonedNewCell, pDocument );
+                        ScCellValue aClonedNewCell;
+                        aClonedNewCell.assign(rNewCell, *pDocument);
+                        pClonedContent->SetNewValue(aClonedNewCell, pDocument);
                     }
 
                     pClonedAction = pClonedContent;
diff --git a/sc/source/filter/excel/xehelper.cxx b/sc/source/filter/excel/xehelper.cxx
index b69b8e6..ab53c49 100644
--- a/sc/source/filter/excel/xehelper.cxx
+++ b/sc/source/filter/excel/xehelper.cxx
@@ -561,40 +561,34 @@ void XclExpStringHelper::AppendChar( XclExpString& rXclString, const XclExpRoot&
 }
 
 XclExpStringRef XclExpStringHelper::CreateCellString(
-        const XclExpRoot& rRoot, const ScStringCell& rStringCell, const ScPatternAttr* pCellAttr,
+        const XclExpRoot& rRoot, const OUString& rString, const ScPatternAttr* pCellAttr,
         XclStrFlags nFlags, sal_uInt16 nMaxLen )
 {
-    rtl::OUString aCellText = rStringCell.GetString();
-    return lclCreateFormattedString( rRoot, aCellText, pCellAttr, nFlags, nMaxLen );
+    return lclCreateFormattedString(rRoot, rString, pCellAttr, nFlags, nMaxLen);
 }
 
 XclExpStringRef XclExpStringHelper::CreateCellString(
-        const XclExpRoot& rRoot, const ScEditCell& rEditCell, const ScPatternAttr* pCellAttr,
+        const XclExpRoot& rRoot, const EditTextObject& rEditText, const ScPatternAttr* pCellAttr,
         XclExpHyperlinkHelper& rLinkHelper, XclStrFlags nFlags, sal_uInt16 nMaxLen )
 {
     XclExpStringRef xString;
-    if( const EditTextObject* pEditObj = rEditCell.GetData() )
-    {
-        // formatted cell
-        ScEditEngineDefaulter& rEE = rRoot.GetEditEngine();
-        sal_Bool bOldUpdateMode = rEE.GetUpdateMode();
-        rEE.SetUpdateMode( sal_True );
-        // default items
-        const SfxItemSet& rItemSet = pCellAttr ? pCellAttr->GetItemSet() : rRoot.GetDoc().GetDefPattern()->GetItemSet();
-        SfxItemSet* pEEItemSet = new SfxItemSet( rEE.GetEmptyItemSet() );
-        ScPatternAttr::FillToEditItemSet( *pEEItemSet, rItemSet );
-        rEE.SetDefaults( pEEItemSet );      // edit engine takes ownership
-        // create the string
-        rEE.SetText( *pEditObj );
-        xString = lclCreateFormattedString( rRoot, rEE, &rLinkHelper, nFlags, nMaxLen );
-        rEE.SetUpdateMode( bOldUpdateMode );
-    }
-    else
-    {
-        // unformatted cell
-        String aCellText = rEditCell.GetString();
-        xString = lclCreateFormattedString( rRoot, aCellText, pCellAttr, nFlags, nMaxLen );
-    }
+
+    // formatted cell
+    ScEditEngineDefaulter& rEE = rRoot.GetEditEngine();
+    sal_Bool bOldUpdateMode = rEE.GetUpdateMode();
+    rEE.SetUpdateMode( sal_True );
+
+    // default items
+    const SfxItemSet& rItemSet = pCellAttr ? pCellAttr->GetItemSet() : rRoot.GetDoc().GetDefPattern()->GetItemSet();
+    SfxItemSet* pEEItemSet = new SfxItemSet( rEE.GetEmptyItemSet() );
+    ScPatternAttr::FillToEditItemSet( *pEEItemSet, rItemSet );
+    rEE.SetDefaults( pEEItemSet );      // edit engine takes ownership
+
+    // create the string
+    rEE.SetText(rEditText);
+    xString = lclCreateFormattedString( rRoot, rEE, &rLinkHelper, nFlags, nMaxLen );
+    rEE.SetUpdateMode( bOldUpdateMode );
+
     return xString;
 }
 
diff --git a/sc/source/filter/excel/xetable.cxx b/sc/source/filter/excel/xetable.cxx
index 4f5d2e40..e71cfcd 100644
--- a/sc/source/filter/excel/xetable.cxx
+++ b/sc/source/filter/excel/xetable.cxx
@@ -647,7 +647,8 @@ XclExpLabelCell::XclExpLabelCell(
     XclExpSingleCellBase( EXC_ID3_LABEL, 0, rXclPos, nForcedXFId )
 {
     sal_uInt16 nMaxLen = (rRoot.GetBiff() == EXC_BIFF8) ? EXC_STR_MAXLEN : EXC_LABEL_MAXLEN;
-    XclExpStringRef xText = XclExpStringHelper::CreateCellString( rRoot, rCell, pPattern, EXC_STR_DEFAULT, nMaxLen );
+    XclExpStringRef xText = XclExpStringHelper::CreateCellString(
+        rRoot, rCell.GetString(), pPattern, EXC_STR_DEFAULT, nMaxLen );
     Init( rRoot, pPattern, xText );
 }
 
@@ -658,7 +659,16 @@ XclExpLabelCell::XclExpLabelCell(
     XclExpSingleCellBase( EXC_ID3_LABEL, 0, rXclPos, nForcedXFId )
 {
     sal_uInt16 nMaxLen = (rRoot.GetBiff() == EXC_BIFF8) ? EXC_STR_MAXLEN : EXC_LABEL_MAXLEN;
-    XclExpStringRef xText = XclExpStringHelper::CreateCellString( rRoot, rCell, pPattern, rLinkHelper, EXC_STR_DEFAULT, nMaxLen );
+
+    XclExpStringRef xText;
+    const EditTextObject* pEditText = rCell.GetData();
+    if (pEditText)
+        xText = XclExpStringHelper::CreateCellString(
+            rRoot, *pEditText, pPattern, rLinkHelper, EXC_STR_DEFAULT, nMaxLen);
+    else
+        xText = XclExpStringHelper::CreateCellString(
+            rRoot, EMPTY_OUSTRING, pPattern, EXC_STR_DEFAULT, nMaxLen);
+
     Init( rRoot, pPattern, xText );
 }
 
diff --git a/sc/source/filter/inc/XclExpChangeTrack.hxx b/sc/source/filter/inc/XclExpChangeTrack.hxx
index 7874dc2..cf63174 100644
--- a/sc/source/filter/inc/XclExpChangeTrack.hxx
+++ b/sc/source/filter/inc/XclExpChangeTrack.hxx
@@ -471,12 +471,9 @@ private:
 protected:
     ScAddress                   aPosition;
 
-    void                        GetCellData(
-                                    const XclExpRoot& rRoot,
-                                    const ScBaseCell* pScCell,
-                                    XclExpChTrData*& rpData,
-                                    sal_uInt32& rXclLength1,
-                                    sal_uInt16& rXclLength2 );
+    void GetCellData(
+        const XclExpRoot& rRoot, const ScCellValue& rScCell, XclExpChTrData*& rpData,
+        sal_uInt32& rXclLength1, sal_uInt16& rXclLength2 );
 
     virtual void                SaveActionData( XclExpStream& rStrm ) const;
 
diff --git a/sc/source/filter/inc/XclImpChangeTrack.hxx b/sc/source/filter/inc/XclImpChangeTrack.hxx
index ca52acb..f1e18fb 100644
--- a/sc/source/filter/inc/XclImpChangeTrack.hxx
+++ b/sc/source/filter/inc/XclImpChangeTrack.hxx
@@ -29,11 +29,12 @@
 
 //___________________________________________________________________
 
-class ScBaseCell;
+class ScCellValue;
 class ScChangeAction;
 class ScChangeTrack;
 class XclImpChTrFmlConverter;
 
+
 //___________________________________________________________________
 
 struct XclImpChTrRecHeader
@@ -90,11 +91,7 @@ private:
     void                        ReadFormula(
                                     ScTokenArray*& rpTokenArray,
                                     const ScAddress& rPosition );
-    void                        ReadCell(
-                                    ScBaseCell*& rpCell,
-                                    sal_uInt32& rFormat,
-                                    sal_uInt16 nFlags,
-                                    const ScAddress& rPosition );
+    void ReadCell( ScCellValue& rCell, sal_uInt32& rFormat, sal_uInt16 nFlags, const ScAddress& rPosition );
 
     void                        ReadChTrInsert();           // 0x0137
     void                        ReadChTrInfo();             // 0x0138
diff --git a/sc/source/filter/inc/xehelper.hxx b/sc/source/filter/inc/xehelper.hxx
index c6cf72f..b67d264 100644
--- a/sc/source/filter/inc/xehelper.hxx
+++ b/sc/source/filter/inc/xehelper.hxx
@@ -276,7 +276,7 @@ public:
         @return  The new string object (shared pointer). */
     static XclExpStringRef CreateCellString(
                             const XclExpRoot& rRoot,
-                            const ScStringCell& rStringCell,
+                            const OUString& rString,
                             const ScPatternAttr* pCellAttr,
                             XclStrFlags nFlags = EXC_STR_DEFAULT,
                             sal_uInt16 nMaxLen = EXC_STR_MAXLEN );
@@ -292,7 +292,7 @@ public:
         @return  The new string object (shared pointer). */
     static XclExpStringRef CreateCellString(
                             const XclExpRoot& rRoot,
-                            const ScEditCell& rEditCell,
+                            const EditTextObject& rEditText,
                             const ScPatternAttr* pCellAttr,
                             XclExpHyperlinkHelper& rLinkHelper,
                             XclStrFlags nFlags = EXC_STR_DEFAULT,
diff --git a/sc/source/filter/xcl97/XclExpChangeTrack.cxx b/sc/source/filter/xcl97/XclExpChangeTrack.cxx
index 684d5e1..e3a8758 100644
--- a/sc/source/filter/xcl97/XclExpChangeTrack.cxx
+++ b/sc/source/filter/xcl97/XclExpChangeTrack.cxx
@@ -28,6 +28,7 @@
 #include "cell.hxx"
 #include "xcl97rec.hxx"
 #include "document.hxx"
+#include "editutil.hxx"
 
 #include <oox/token/tokens.hxx>
 #include <rtl/strbuf.hxx>
@@ -806,28 +807,25 @@ void XclExpChTrCellContent::MakeEmptyChTrData( XclExpChTrData*& rpData )
 }
 
 void XclExpChTrCellContent::GetCellData(
-        const XclExpRoot& rRoot,
-        const ScBaseCell* pScCell,
-        XclExpChTrData*& rpData,
-        sal_uInt32& rXclLength1,
-        sal_uInt16& rXclLength2 )
+    const XclExpRoot& rRoot, const ScCellValue& rScCell,
+    XclExpChTrData*& rpData, sal_uInt32& rXclLength1, sal_uInt16& rXclLength2 )
 {
     MakeEmptyChTrData( rpData );
     rXclLength1 = 0x0000003A;
     rXclLength2 = 0x0000;
 
-    if( !pScCell )
+    if (rScCell.isEmpty())
     {
         delete rpData;
         rpData = NULL;
         return;
     }
 
-    switch( pScCell->GetCellType() )
+    switch (rScCell.meType)
     {
         case CELLTYPE_VALUE:
         {
-            rpData->fValue = ((const ScValueCell*) pScCell)->GetValue();
+            rpData->fValue = rScCell.mfValue;
             if( XclTools::GetRKFromDouble( rpData->nRKValue, rpData->fValue ) )
             {
                 rpData->nType = EXC_CHTR_TYPE_RK;
@@ -847,32 +845,38 @@ void XclExpChTrCellContent::GetCellData(
         case CELLTYPE_STRING:
         case CELLTYPE_EDIT:
         {
-            String sCellStr;
-            if( pScCell->GetCellType() == CELLTYPE_STRING )
+            OUString sCellStr;
+            if (rScCell.meType == CELLTYPE_STRING)
             {
-                const ScStringCell* pStrCell = static_cast< const ScStringCell* >( pScCell );
-                sCellStr = pStrCell->GetString();
-                rpData->mpFormattedString = XclExpStringHelper::CreateCellString( rRoot,
-                        *pStrCell, NULL );
+                sCellStr = *rScCell.mpString;
+                rpData->mpFormattedString = XclExpStringHelper::CreateCellString(
+                    rRoot, *rScCell.mpString, NULL);
             }
             else
             {
-                const ScEditCell* pEditCell = static_cast< const ScEditCell* >( pScCell );
-                sCellStr = pEditCell->GetString();
                 XclExpHyperlinkHelper aLinkHelper( rRoot, aPosition );
-                rpData->mpFormattedString = XclExpStringHelper::CreateCellString( rRoot,
-                        *pEditCell, NULL, aLinkHelper );
+                if (rScCell.mpEditText)
+                {
+                    sCellStr = ScEditUtil::GetString(*rScCell.mpEditText);
+                    rpData->mpFormattedString = XclExpStringHelper::CreateCellString(
+                        rRoot, *rScCell.mpEditText, NULL, aLinkHelper);
+                }
+                else
+                {
+                    rpData->mpFormattedString = XclExpStringHelper::CreateCellString(
+                        rRoot, EMPTY_OUSTRING, NULL);
+                }
             }
             rpData->pString = new XclExpString( sCellStr, EXC_STR_DEFAULT, 32766 );
             rpData->nType = EXC_CHTR_TYPE_STRING;
             rpData->nSize = 3 + rpData->pString->GetSize();
-            rXclLength1 = 64 + (sCellStr.Len() << 1);
-            rXclLength2 = 6 + (sal_uInt16)(sCellStr.Len() << 1);
+            rXclLength1 = 64 + (sCellStr.getLength() << 1);
+            rXclLength2 = 6 + (sal_uInt16)(sCellStr.getLength() << 1);
         }
         break;
         case CELLTYPE_FORMULA:
         {
-            const ScFormulaCell* pFmlCell = (const ScFormulaCell*) pScCell;
+            const ScFormulaCell* pFmlCell = rScCell.mpFormula;
             rpData->mpFormulaCell = pFmlCell;
 
             const ScTokenArray* pTokenArray = pFmlCell->GetCode();
diff --git a/sc/source/filter/xcl97/XclImpChangeTrack.cxx b/sc/source/filter/xcl97/XclImpChangeTrack.cxx
index e3e31a6..6046dd3 100644
--- a/sc/source/filter/xcl97/XclImpChangeTrack.cxx
+++ b/sc/source/filter/xcl97/XclImpChangeTrack.cxx
@@ -214,12 +214,9 @@ void XclImpChangeTrack::ReadFormula( ScTokenArray*& rpTokenArray, const ScAddres
 }
 
 void XclImpChangeTrack::ReadCell(
-        ScBaseCell*& rpCell,
-        sal_uInt32& rFormat,
-        sal_uInt16 nFlags,
-        const ScAddress& rPosition )
+    ScCellValue& rCell, sal_uInt32& rFormat, sal_uInt16 nFlags, const ScAddress& rPosition )
 {
-    rpCell = NULL;
+    rCell.clear();
     rFormat = 0;
     switch( nFlags & EXC_CHTR_TYPE_MASK )
     {
@@ -229,7 +226,10 @@ void XclImpChangeTrack::ReadCell(
         {
             double fValue = ReadRK();
             if( pStrm->IsValid() )
-                rpCell = new ScValueCell( fValue );
+            {
+                rCell.meType = CELLTYPE_VALUE;
+                rCell.mfValue = fValue;
+            }
         }
         break;
         case EXC_CHTR_TYPE_DOUBLE:
@@ -237,14 +237,20 @@ void XclImpChangeTrack::ReadCell(
             double fValue;
             *pStrm >> fValue;
             if( pStrm->IsValid() )
-                rpCell = new ScValueCell( fValue );
+            {
+                rCell.meType = CELLTYPE_VALUE;
+                rCell.mfValue = fValue;
+            }
         }
         break;
         case EXC_CHTR_TYPE_STRING:
         {
-            String sString( pStrm->ReadUniString() );
+            OUString sString = pStrm->ReadUniString();
             if( pStrm->IsValid() )
-                rpCell = new ScStringCell( sString );
+            {
+                rCell.meType = CELLTYPE_STRING;
+                rCell.mpString = new OUString(sString);
+            }
         }
         break;
         case EXC_CHTR_TYPE_BOOL:
@@ -252,7 +258,8 @@ void XclImpChangeTrack::ReadCell(
             double fValue = (double) ReadBool();
             if( pStrm->IsValid() )
             {
-                rpCell = new ScValueCell( fValue );
+                rCell.meType = CELLTYPE_VALUE;
+                rCell.mfValue = fValue;
                 rFormat = GetFormatter().GetStandardFormat( NUMBERFORMAT_LOGICAL, ScGlobal::eLnge );
             }
         }
@@ -262,7 +269,10 @@ void XclImpChangeTrack::ReadCell(
             ScTokenArray* pTokenArray = NULL;
             ReadFormula( pTokenArray, rPosition );
             if( pStrm->IsValid() && pTokenArray )
-                rpCell = new ScFormulaCell( GetDocPtr(), rPosition, pTokenArray );
+            {
+                rCell.meType = CELLTYPE_FORMULA;
+                rCell.mpFormula = new ScFormulaCell(GetDocPtr(), rPosition, pTokenArray);
+            }
             delete pTokenArray;
         }
         break;
@@ -355,24 +365,22 @@ void XclImpChangeTrack::ReadChTrCellContent()
             default:        OSL_FAIL( "XclImpChangeTrack::ReadChTrCellContent - unknown format info" );
         }
 
-        ScBaseCell* pOldCell;
-        ScBaseCell* pNewCell;
+        ScCellValue aOldCell;
+        ScCellValue aNewCell;
         sal_uInt32 nOldFormat;
         sal_uInt32 nNewFormat;
-        ReadCell( pOldCell, nOldFormat, nOldValueType, aPosition );
-        ReadCell( pNewCell, nNewFormat, nNewValueType, aPosition );
+        ReadCell(aOldCell, nOldFormat, nOldValueType, aPosition);
+        ReadCell(aNewCell, nNewFormat, nNewValueType, aPosition);
         if( !pStrm->IsValid() || (pStrm->GetRecLeft() > 0) )
         {
             OSL_FAIL( "XclImpChangeTrack::ReadChTrCellContent - bytes left, action ignored" );
-            if( pOldCell )
-                pOldCell->Delete();
-            if( pNewCell )
-                pNewCell->Delete();
+            aOldCell.clear();
+            aNewCell.clear();
         }
         else
         {
             ScChangeActionContent* pNewAction =
-                pChangeTrack->AppendContentOnTheFly( aPosition, pOldCell, pNewCell, nOldFormat, nNewFormat );
+                pChangeTrack->AppendContentOnTheFly(aPosition, aOldCell, aNewCell, nOldFormat, nNewFormat);
             DoAcceptRejectAction( pNewAction );
         }
     }
diff --git a/sc/source/filter/xml/XMLChangeTrackingExportHelper.cxx b/sc/source/filter/xml/XMLChangeTrackingExportHelper.cxx
index a1da5bc..223aeed 100644
--- a/sc/source/filter/xml/XMLChangeTrackingExportHelper.cxx
+++ b/sc/source/filter/xml/XMLChangeTrackingExportHelper.cxx
@@ -26,6 +26,9 @@
 #include "cell.hxx"
 #include "textuno.hxx"
 #include "rangeutl.hxx"
+#include "cellvalue.hxx"
+#include "editutil.hxx"
+
 #include <xmloff/xmlnmspe.hxx>
 #include <xmloff/nmspmap.hxx>
 #include <xmloff/xmluconv.hxx>
@@ -276,148 +279,136 @@ void ScChangeTrackingExportHelper::SetValueAttributes(const double& fValue, cons
 }
 
 
-void ScChangeTrackingExportHelper::WriteValueCell(const ScBaseCell* pCell, const String& sValue)
+void ScChangeTrackingExportHelper::WriteValueCell(const ScCellValue& rCell, const OUString& sValue)
 {
-    const ScValueCell* pValueCell = static_cast<const ScValueCell*>(pCell);
-    if (pValueCell)
-    {
-        SetValueAttributes(pValueCell->GetValue(), sValue);
-        SvXMLElementExport aElemC(rExport, XML_NAMESPACE_TABLE, XML_CHANGE_TRACK_TABLE_CELL, true, true);
-    }
+    OSL_ASSERT(rCell.meType == CELLTYPE_VALUE);
+
+    SetValueAttributes(rCell.mfValue, sValue);
+    SvXMLElementExport aElemC(rExport, XML_NAMESPACE_TABLE, XML_CHANGE_TRACK_TABLE_CELL, true, true);
 }
 
-void ScChangeTrackingExportHelper::WriteStringCell(const ScBaseCell* pCell)
+void ScChangeTrackingExportHelper::WriteStringCell(const ScCellValue& rCell)
 {
-    const ScStringCell* pStringCell = static_cast<const ScStringCell*>(pCell);
-    if (pStringCell)
+    OSL_ASSERT(rCell.meType == CELLTYPE_STRING);
+
+    rExport.AddAttribute(XML_NAMESPACE_OFFICE, XML_VALUE_TYPE, XML_STRING);
+    SvXMLElementExport aElemC(rExport, XML_NAMESPACE_TABLE, XML_CHANGE_TRACK_TABLE_CELL, true, true);
+    if (!rCell.mpString->isEmpty())
     {
-        rtl::OUString sOUString = pStringCell->GetString();
-        rExport.AddAttribute(XML_NAMESPACE_OFFICE, XML_VALUE_TYPE, XML_STRING);
-        SvXMLElementExport aElemC(rExport, XML_NAMESPACE_TABLE, XML_CHANGE_TRACK_TABLE_CELL, true, true);
-        if (!sOUString.isEmpty())
-        {
-            SvXMLElementExport aElemP(rExport, XML_NAMESPACE_TEXT, XML_P, true, false);
-            bool bPrevCharWasSpace(true);
-            rExport.GetTextParagraphExport()->exportText(sOUString, bPrevCharWasSpace);
-        }
+        SvXMLElementExport aElemP(rExport, XML_NAMESPACE_TEXT, XML_P, true, false);
+        bool bPrevCharWasSpace(true);
+        rExport.GetTextParagraphExport()->exportText(*rCell.mpString, bPrevCharWasSpace);
     }
 }
 
-void ScChangeTrackingExportHelper::WriteEditCell(const ScBaseCell* pCell)
+void ScChangeTrackingExportHelper::WriteEditCell(const ScCellValue& rCell)
 {
-    const ScEditCell* pEditCell = static_cast<const ScEditCell*>(pCell);
-    if (pEditCell)
+    OSL_ASSERT(rCell.meType == CELLTYPE_EDIT);
+
+    OUString sString;
+    if (rCell.mpEditText)
+        sString = ScEditUtil::GetString(*rCell.mpEditText);
+
+    rExport.AddAttribute(XML_NAMESPACE_OFFICE, XML_VALUE_TYPE, XML_STRING);
+    SvXMLElementExport aElemC(rExport, XML_NAMESPACE_TABLE, XML_CHANGE_TRACK_TABLE_CELL, true, true);
+    if (!sString.isEmpty())
     {
-        String sString = pEditCell->GetString();
-        rExport.AddAttribute(XML_NAMESPACE_OFFICE, XML_VALUE_TYPE, XML_STRING);
-        SvXMLElementExport aElemC(rExport, XML_NAMESPACE_TABLE, XML_CHANGE_TRACK_TABLE_CELL, true, true);
-        if (sString.Len())
+        if (!pEditTextObj)
         {
-            if (!pEditTextObj)
-            {
-                pEditTextObj = new ScEditEngineTextObj();
-                xText.set(pEditTextObj);
-            }
-            pEditTextObj->SetText(*(pEditCell->GetData()));
-            if (xText.is())
-                rExport.GetTextParagraphExport()->exportText(xText, false, false);
+            pEditTextObj = new ScEditEngineTextObj();
+            xText.set(pEditTextObj);
         }
+        pEditTextObj->SetText(*rCell.mpEditText);
+        if (xText.is())
+            rExport.GetTextParagraphExport()->exportText(xText, false, false);
     }
 }
 
-void ScChangeTrackingExportHelper::WriteFormulaCell(const ScBaseCell* pCell, const String& sValue)
+void ScChangeTrackingExportHelper::WriteFormulaCell(const ScCellValue& rCell, const OUString& sValue)
 {
-    ScBaseCell* pBaseCell = const_cast<ScBaseCell*>(pCell);
-    ScFormulaCell* pFormulaCell = static_cast<ScFormulaCell*>(pBaseCell);
-    if (pFormulaCell)
+    OSL_ASSERT(rCell.meType == CELLTYPE_FORMULA);
+
+    ScFormulaCell* pFormulaCell = rCell.mpFormula;
+    OUString sAddress;
+    const ScDocument* pDoc = rExport.GetDocument();
+    ScRangeStringConverter::GetStringFromAddress(sAddress, pFormulaCell->aPos, pDoc, ::formula::FormulaGrammar::CONV_OOO);
+    rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_CELL_ADDRESS, sAddress);
+    const formula::FormulaGrammar::Grammar eGrammar = pDoc->GetStorageGrammar();
+    sal_uInt16 nNamespacePrefix = (eGrammar == formula::FormulaGrammar::GRAM_ODFF ? XML_NAMESPACE_OF : XML_NAMESPACE_OOOC);
+    OUString sFormula;
+    pFormulaCell->GetFormula(sFormula, eGrammar);
+    sal_uInt8 nMatrixFlag(pFormulaCell->GetMatrixFlag());
+    if (nMatrixFlag)
     {
-        rtl::OUString sAddress;
-        const ScDocument* pDoc = rExport.GetDocument();
-        ScRangeStringConverter::GetStringFromAddress(sAddress, pFormulaCell->aPos, pDoc, ::formula::FormulaGrammar::CONV_OOO);
-        rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_CELL_ADDRESS, sAddress);
-        const formula::FormulaGrammar::Grammar eGrammar = pDoc->GetStorageGrammar();
-        sal_uInt16 nNamespacePrefix = (eGrammar == formula::FormulaGrammar::GRAM_ODFF ? XML_NAMESPACE_OF : XML_NAMESPACE_OOOC);
-        rtl::OUString sFormula;
-        pFormulaCell->GetFormula(sFormula, eGrammar);
-        rtl::OUString sOUFormula(sFormula);
-        sal_uInt8 nMatrixFlag(pFormulaCell->GetMatrixFlag());
-        if (nMatrixFlag)
+        if (nMatrixFlag == MM_FORMULA)
         {
-            if (nMatrixFlag == MM_FORMULA)
-            {
-                SCCOL nColumns;
-                SCROW nRows;
-                pFormulaCell->GetMatColsRows(nColumns, nRows);
-                rtl::OUStringBuffer sColumns;
-                rtl::OUStringBuffer sRows;
-                ::sax::Converter::convertNumber(sColumns, static_cast<sal_Int32>(nColumns));
-                ::sax::Converter::convertNumber(sRows, static_cast<sal_Int32>(nRows));
-                rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_NUMBER_MATRIX_COLUMNS_SPANNED, sColumns.makeStringAndClear());
-                rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_NUMBER_MATRIX_ROWS_SPANNED, sRows.makeStringAndClear());
-            }
-            else
-            {
-                rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_MATRIX_COVERED, XML_TRUE);
-            }
-            rtl::OUString sMatrixFormula = sOUFormula.copy(1, sOUFormula.getLength() - 2);
-            rtl::OUString sQValue = rExport.GetNamespaceMap().GetQNameByKey( nNamespacePrefix, sMatrixFormula, false );
-            rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_FORMULA, sQValue);
+            SCCOL nColumns;
+            SCROW nRows;
+            pFormulaCell->GetMatColsRows(nColumns, nRows);
+            OUStringBuffer sColumns;
+            OUStringBuffer sRows;
+            ::sax::Converter::convertNumber(sColumns, static_cast<sal_Int32>(nColumns));
+            ::sax::Converter::convertNumber(sRows, static_cast<sal_Int32>(nRows));
+            rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_NUMBER_MATRIX_COLUMNS_SPANNED, sColumns.makeStringAndClear());
+            rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_NUMBER_MATRIX_ROWS_SPANNED, sRows.makeStringAndClear());
         }
         else
         {
-            rtl::OUString sQValue = rExport.GetNamespaceMap().GetQNameByKey( nNamespacePrefix, sFormula, false );
-            rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_FORMULA, sQValue);
+            rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_MATRIX_COVERED, XML_TRUE);
         }
-        if (pFormulaCell->IsValue())
-        {
-            SetValueAttributes(pFormulaCell->GetValue(), sValue);
-            SvXMLElementExport aElemC(rExport, XML_NAMESPACE_TABLE, XML_CHANGE_TRACK_TABLE_CELL, true, true);
-        }
-        else
+        OUString sMatrixFormula = sFormula.copy(1, sFormula.getLength() - 2);
+        OUString sQValue = rExport.GetNamespaceMap().GetQNameByKey( nNamespacePrefix, sMatrixFormula, false );
+        rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_FORMULA, sQValue);
+    }
+    else
+    {
+        OUString sQValue = rExport.GetNamespaceMap().GetQNameByKey( nNamespacePrefix, sFormula, false );
+        rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_FORMULA, sQValue);
+    }
+    if (pFormulaCell->IsValue())
+    {
+        SetValueAttributes(pFormulaCell->GetValue(), sValue);
+        SvXMLElementExport aElemC(rExport, XML_NAMESPACE_TABLE, XML_CHANGE_TRACK_TABLE_CELL, true, true);
+    }
+    else
+    {
+        rExport.AddAttribute(XML_NAMESPACE_OFFICE, XML_VALUE_TYPE, XML_STRING);
+        OUString sCellValue = pFormulaCell->GetString();
+        SvXMLElementExport aElemC(rExport, XML_NAMESPACE_TABLE, XML_CHANGE_TRACK_TABLE_CELL, true, true);
+        if (!sCellValue.isEmpty())
         {
-            rExport.AddAttribute(XML_NAMESPACE_OFFICE, XML_VALUE_TYPE, XML_STRING);
-            String sCellValue = pFormulaCell->GetString();
-            rtl::OUString sOUValue(sCellValue);
-            SvXMLElementExport aElemC(rExport, XML_NAMESPACE_TABLE, XML_CHANGE_TRACK_TABLE_CELL, true, true);
-            if (!sOUValue.isEmpty())
-            {
-                SvXMLElementExport aElemP(rExport, XML_NAMESPACE_TEXT, XML_P, true, false);
-                bool bPrevCharWasSpace(true);
-                rExport.GetTextParagraphExport()->exportText(sOUValue, bPrevCharWasSpace);
-            }
+            SvXMLElementExport aElemP(rExport, XML_NAMESPACE_TEXT, XML_P, true, false);
+            bool bPrevCharWasSpace(true);
+            rExport.GetTextParagraphExport()->exportText(sCellValue, bPrevCharWasSpace);
         }
     }
 }
 
-void ScChangeTrackingExportHelper::WriteCell(const ScBaseCell* pCell, const String& sValue)
+void ScChangeTrackingExportHelper::WriteCell(const ScCellValue& rCell, const OUString& sValue)
 {
-    if (pCell)
+    if (rCell.isEmpty())
     {
-        switch (pCell->GetCellType())
-        {
-            case CELLTYPE_NONE:
-                WriteEmptyCell();
-                break;
-            case CELLTYPE_VALUE:
-                WriteValueCell(pCell, sValue);
-                break;
-            case CELLTYPE_STRING:
-                WriteStringCell(pCell);
-                break;
-            case CELLTYPE_EDIT:
-                WriteEditCell(pCell);
-                break;
-            case CELLTYPE_FORMULA:
-                WriteFormulaCell(pCell, sValue);
-                break;
-            default:
-            {
-                // added to avoid warnings
-            }
-        }
-    }
-    else
         WriteEmptyCell();
+        return;
+    }
+
+    switch (rCell.meType)
+    {
+        case CELLTYPE_VALUE:
+            WriteValueCell(rCell, sValue);
+            break;
+        case CELLTYPE_STRING:
+            WriteStringCell(rCell);
+            break;
+        case CELLTYPE_EDIT:
+            WriteEditCell(rCell);
+            break;
+        case CELLTYPE_FORMULA:
+            WriteFormulaCell(rCell, sValue);
+            break;
+        default:
+            WriteEmptyCell();
+    }
 }
 
 void ScChangeTrackingExportHelper::WriteContentChange(ScChangeAction* pAction)
@@ -649,37 +640,34 @@ void ScChangeTrackingExportHelper::WriteRejection(ScChangeAction* pAction)
     WriteDependings(pAction);
 }
 
-void ScChangeTrackingExportHelper::CollectCellAutoStyles(const ScBaseCell* pBaseCell)
+void ScChangeTrackingExportHelper::CollectCellAutoStyles(const ScCellValue& rCell)
 {
-    if (pBaseCell && (pBaseCell->GetCellType() == CELLTYPE_EDIT))
+    if (rCell.meType != CELLTYPE_EDIT)
+        return;
+
+    if (!pEditTextObj)
     {
-        const ScEditCell* pEditCell = static_cast<const ScEditCell*>(pBaseCell);
-        if (pEditCell)
-        {
-            if (!pEditTextObj)
-            {
-                pEditTextObj = new ScEditEngineTextObj();
-                xText.set(pEditTextObj);
-            }
-            pEditTextObj->SetText(*(pEditCell->GetData()));
-            if (xText.is())
-                rExport.GetTextParagraphExport()->collectTextAutoStyles(xText, false, false);
-        }
+        pEditTextObj = new ScEditEngineTextObj();
+        xText.set(pEditTextObj);
     }
+
+    pEditTextObj->SetText(*rCell.mpEditText);
+    if (xText.is())
+        rExport.GetTextParagraphExport()->collectTextAutoStyles(xText, false, false);
 }
 
 void ScChangeTrackingExportHelper::CollectActionAutoStyles(ScChangeAction* pAction)
 {
-    if (pAction->GetType() == SC_CAT_CONTENT)
+    if (pAction->GetType() != SC_CAT_CONTENT)
+        return;
+
+    if (pChangeTrack->IsGenerated(pAction->GetActionNumber()))
+        CollectCellAutoStyles(static_cast<ScChangeActionContent*>(pAction)->GetNewCell());
+    else
     {
-        if (pChangeTrack->IsGenerated(pAction->GetActionNumber()))
-             CollectCellAutoStyles(static_cast<ScChangeActionContent*>(pAction)->GetNewCell());
-        else
-        {
-             CollectCellAutoStyles(static_cast<ScChangeActionContent*>(pAction)->GetOldCell());
-            if (static_cast<ScChangeActionContent*>(pAction)->IsTopContent() && pAction->IsDeletedIn())
-                 CollectCellAutoStyles(static_cast<ScChangeActionContent*>(pAction)->GetNewCell());
-        }
+        CollectCellAutoStyles(static_cast<ScChangeActionContent*>(pAction)->GetOldCell());
+        if (static_cast<ScChangeActionContent*>(pAction)->IsTopContent() && pAction->IsDeletedIn())
+            CollectCellAutoStyles(static_cast<ScChangeActionContent*>(pAction)->GetNewCell());
     }
 }
 
diff --git a/sc/source/filter/xml/XMLChangeTrackingExportHelper.hxx b/sc/source/filter/xml/XMLChangeTrackingExportHelper.hxx
index 2e7088c..e810e84 100644
--- a/sc/source/filter/xml/XMLChangeTrackingExportHelper.hxx
+++ b/sc/source/filter/xml/XMLChangeTrackingExportHelper.hxx
@@ -31,6 +31,7 @@ class ScChangeAction;
 class ScChangeTrack;
 class ScXMLExport;
 class ScBaseCell;
+class ScCellValue;
 class ScChangeActionDel;
 class ScBigRange;
 class ScEditEngineTextObj;
@@ -61,11 +62,11 @@ class ScChangeTrackingExportHelper
 
     void WriteEmptyCell();
     void SetValueAttributes(const double& fValue, const String& sValue);
-    void WriteValueCell(const ScBaseCell* pCell, const String& sValue);
-    void WriteStringCell(const ScBaseCell* pCell);
-    void WriteEditCell(const ScBaseCell* pCell);
-    void WriteFormulaCell(const ScBaseCell* pCell, const String& sValue);
-    void WriteCell(const ScBaseCell* pCell, const String& sValue);
+    void WriteValueCell(const ScCellValue& rCell, const OUString& sValue);
+    void WriteStringCell(const ScCellValue& rCell);
+    void WriteEditCell(const ScCellValue& rCell);
+    void WriteFormulaCell(const ScCellValue& rCell, const OUString& sValue);
+    void WriteCell(const ScCellValue& rCell, const OUString& sValue);
 
     void WriteContentChange(ScChangeAction* pAction);
     void AddInsertionAttributes(const ScChangeAction* pAction);
@@ -77,7 +78,7 @@ class ScChangeTrackingExportHelper
     void WriteMovement(ScChangeAction* pAction);
     void WriteRejection(ScChangeAction* pAction);
 
-    void CollectCellAutoStyles(const ScBaseCell* pBaseCell);
+    void CollectCellAutoStyles(const ScCellValue& rCell);
     void CollectActionAutoStyles(ScChangeAction* pAction);
     void WorkWithChangeAction(ScChangeAction* pAction);
 public:
diff --git a/sc/source/filter/xml/XMLChangeTrackingImportHelper.cxx b/sc/source/filter/xml/XMLChangeTrackingImportHelper.cxx
index f5d8ce1..5fb6334 100644
--- a/sc/source/filter/xml/XMLChangeTrackingImportHelper.cxx
+++ b/sc/source/filter/xml/XMLChangeTrackingImportHelper.cxx
@@ -29,11 +29,12 @@
 
 #define SC_CHANGE_ID_PREFIX "ct"
 
-ScMyCellInfo::ScMyCellInfo(ScBaseCell* pTempCell, const rtl::OUString& rFormulaAddress, const rtl::OUString& rFormula,

... etc. - the rest is truncated


More information about the Libreoffice-commits mailing list