[Libreoffice-commits] core.git: Branch 'libreoffice-4-2' - 5 commits - embeddedobj/source include/svl include/svx offapi/com offapi/UnoApi_offapi.mk sc/inc sc/Library_scfilt.mk sc/Library_sc.mk sc/qa sc/source svl/source svx/source

Kohei Yoshida kohei.yoshida at collabora.com
Mon Jul 21 09:48:55 PDT 2014


 embeddedobj/source/commonembedding/miscobj.cxx     |    8 
 embeddedobj/source/commonembedding/persistence.cxx |   10 
 embeddedobj/source/inc/commonembobj.hxx            |    8 
 include/svl/listener.hxx                           |   12 
 include/svx/svdoole2.hxx                           |    7 
 offapi/UnoApi_offapi.mk                            |    1 
 offapi/com/sun/star/embed/XEmbedPersist2.idl       |   30 +
 sc/Library_sc.mk                                   |    2 
 sc/Library_scfilt.mk                               |    1 
 sc/inc/cellvalue.hxx                               |    1 
 sc/inc/chgtrack.hxx                                |   28 -
 sc/inc/document.hxx                                |   35 -
 sc/inc/formulacell.hxx                             |    2 
 sc/inc/listenerquery.hxx                           |   50 ++
 sc/inc/listenerqueryids.hxx                        |   17 
 sc/inc/refhint.hxx                                 |   30 +
 sc/inc/sharedformula.hxx                           |    9 
 sc/inc/sortparam.hxx                               |   27 +
 sc/inc/table.hxx                                   |   16 
 sc/inc/tokenarray.hxx                              |    8 
 sc/inc/types.hxx                                   |    2 
 sc/inc/undosort.hxx                                |   37 +
 sc/qa/unit/filters-test.cxx                        |    4 
 sc/qa/unit/ucalc.cxx                               |   11 
 sc/source/core/data/cellvalue.cxx                  |    7 
 sc/source/core/data/documen3.cxx                   |   27 +
 sc/source/core/data/document10.cxx                 |   18 
 sc/source/core/data/formulacell.cxx                |   38 +
 sc/source/core/data/sortparam.cxx                  |   51 ++
 sc/source/core/data/table3.cxx                     |  467 +++++++++++++++------
 sc/source/core/data/table7.cxx                     |   17 
 sc/source/core/tool/chgtrack.cxx                   |   46 +-
 sc/source/core/tool/listenerquery.cxx              |   72 +++
 sc/source/core/tool/refhint.cxx                    |   29 +
 sc/source/core/tool/sharedformula.cxx              |   29 +
 sc/source/core/tool/token.cxx                      |   71 +++
 sc/source/filter/excel/xestream.cxx                |    7 
 sc/source/filter/inc/XclExpChangeTrack.hxx         |   89 ++--
 sc/source/filter/inc/XclImpChangeTrack.hxx         |    2 
 sc/source/filter/inc/revisionfragment.hxx          |   79 +++
 sc/source/filter/inc/xestream.hxx                  |   10 
 sc/source/filter/oox/revisionfragment.cxx          |  462 ++++++++++++++++++++
 sc/source/filter/oox/workbookfragment.cxx          |   11 
 sc/source/filter/xcl97/XclExpChangeTrack.cxx       |  363 ++++++++++------
 sc/source/filter/xcl97/XclImpChangeTrack.cxx       |   11 
 sc/source/filter/xml/XMLExportDatabaseRanges.cxx   |    1 
 sc/source/filter/xml/xmldrani.cxx                  |    1 
 sc/source/ui/docshell/dbdocfun.cxx                 |  163 -------
 sc/source/ui/undo/undobase.cxx                     |    1 
 sc/source/ui/undo/undosort.cxx                     |   55 ++
 sc/source/ui/unoobj/cellsuno.cxx                   |    1 
 sc/source/ui/unoobj/datauno.cxx                    |    1 
 svl/source/notify/listener.cxx                     |   24 +
 svx/source/svdraw/svdetc.cxx                       |    4 
 svx/source/svdraw/svdoole2.cxx                     |   16 
 55 files changed, 2000 insertions(+), 529 deletions(-)

New commits:
commit d4aed409279d3b9b8b95d84418fb7f279367cc30
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Mon Jun 2 18:29:27 2014 -0400

    fdo#81309: Adjust references during sort.
    
    (cherry picked from commit 5c6ee09126631342939ae8766fe36083d8c011e3)
    Signed-off-by: Andras Timar <andras.timar at collabora.com>
    
    Conflicts:
    	sc/inc/sortparam.hxx
    	sc/source/ui/docshell/dbdocfun.cxx
    	sc/source/ui/undo/undodat.cxx
    	sc/inc/formulacell.hxx
    	sc/qa/unit/filters-test.cxx
    	sc/qa/unit/ucalc.cxx
    	sc/source/core/data/documen3.cxx
    	sc/source/ui/docshell/dbdocfun.cxx
    
    Change-Id: I2b98610f6b774400ecfaffe2905201c27fcab33f
    (cherry picked from commit e31300e8749ac7de07bbcb91c6ae28559238e60c)
    Signed-off-by: Andras Timar <andras.timar at collabora.com>

diff --git a/include/svl/listener.hxx b/include/svl/listener.hxx
index 1c98458..8b47fda 100644
--- a/include/svl/listener.hxx
+++ b/include/svl/listener.hxx
@@ -34,6 +34,16 @@ class SVL_DLLPUBLIC SvtListener
     const SvtListener&  operator=(const SvtListener &); // n.i., ist verboten
 
 public:
+    class SVL_DLLPUBLIC QueryBase
+    {
+        sal_uInt16 mnId;
+    public:
+        QueryBase( sal_uInt16 nId );
+        virtual ~QueryBase();
+
+        sal_uInt16 getId() const;
+    };
+
     SvtListener();
     SvtListener( const SvtListener &r );
     virtual ~SvtListener();
@@ -43,9 +53,11 @@ public:
     void EndListeningAll();
     bool IsListening( SvtBroadcaster& rBroadcaster ) const;
 
+    void CopyAllBroadcasters( const SvtListener& r );
     bool HasBroadcaster() const;
 
     virtual void Notify( const SfxHint& rHint );
+    virtual void Query( QueryBase& rQuery ) const;
 };
 
 
diff --git a/sc/Library_sc.mk b/sc/Library_sc.mk
index b7041b8..33c6652 100644
--- a/sc/Library_sc.mk
+++ b/sc/Library_sc.mk
@@ -234,6 +234,7 @@ $(eval $(call gb_Library_add_exception_objects,sc,\
     sc/source/core/tool/interpr6 \
     sc/source/core/tool/interpr7 \
     sc/source/core/tool/jumpmatrix \
+    sc/source/core/tool/listenerquery \
     sc/source/core/tool/lookupcache \
     sc/source/core/tool/navicfg \
     sc/source/core/tool/odffmap \
@@ -515,6 +516,7 @@ $(eval $(call gb_Library_add_exception_objects,sc,\
     sc/source/ui/undo/undodraw \
     sc/source/ui/undo/undoolk \
     sc/source/ui/undo/undorangename \
+    sc/source/ui/undo/undosort \
     sc/source/ui/undo/undostyl \
     sc/source/ui/undo/undotab \
     sc/source/ui/undo/undoutil \
diff --git a/sc/inc/document.hxx b/sc/inc/document.hxx
index a2aea94..c901af5 100644
--- a/sc/inc/document.hxx
+++ b/sc/inc/document.hxx
@@ -29,7 +29,6 @@
 #include "rangenam.hxx"
 #include "brdcst.hxx"
 #include "tabopparams.hxx"
-#include "sortparam.hxx"
 #include "types.hxx"
 #include "formula/grammar.hxx"
 #include "formula/types.hxx"
@@ -76,6 +75,8 @@ class DocumentStreamAccess;
 class DocumentLinkManager;
 struct SetFormulaDirtyContext;
 class RefMovedHint;
+struct SortUndoParam;
+struct ReorderParam;
 
 }
 
@@ -178,6 +179,8 @@ class EditTextObject;
 struct ScRefCellValue;
 class ScDocumentImport;
 class ScPostIt;
+struct ScSubTotalParam;
+struct ScQueryParam;
 
 namespace com { namespace sun { namespace star {
     namespace lang {
@@ -1664,7 +1667,9 @@ public:
     SC_DLLPUBLIC SvNumberFormatter* GetFormatTable() const;
     SC_DLLPUBLIC SvNumberFormatter* CreateFormatTable() const;
 
-    void            Sort( SCTAB nTab, const ScSortParam& rSortParam, bool bKeepQuery, ScProgress* pProgress );
+    void Sort( SCTAB nTab, const ScSortParam& rSortParam, bool bKeepQuery, ScProgress* pProgress, sc::ReorderParam* pUndo );
+    void Reorder( const sc::ReorderParam& rParam, ScProgress* pProgress );
+
     SCSIZE          Query( SCTAB nTab, const ScQueryParam& rQueryParam, bool bKeepSub );
     SC_DLLPUBLIC bool           CreateQueryParam( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
                                         SCTAB nTab, ScQueryParam& rQueryParam );
@@ -2022,8 +2027,8 @@ public:
 
     void            InvalidateStyleSheetUsage()
                         { bStyleSheetUsageInvalid = true; }
-    void GetSortParam( ScSortParam& rParam, SCTAB nTab );
-    void SetSortParam( ScSortParam& rParam, SCTAB nTab );
+    void SC_DLLPUBLIC GetSortParam( ScSortParam& rParam, SCTAB nTab );
+    void SC_DLLPUBLIC SetSortParam( ScSortParam& rParam, SCTAB nTab );
 
     inline void     SetVbaEventProcessor( const com::sun::star::uno::Reference< com::sun::star::script::vba::XVBAEventProcessor >& rxVbaEvents )
                         { mxVbaEvents = rxVbaEvents; }
@@ -2052,6 +2057,19 @@ public:
 
     size_t GetFormulaHash( const ScAddress& rPos ) const;
 
+    /**
+     * Make specified formula cells non-grouped.
+     *
+     * @param nTab sheet index
+     * @param nCol column index
+     * @param rRows list of row indices at which formula cells are to be
+     *              unshared. This call sorts the passed row indices and
+     *              removes duplicates, which is why the caller must pass it
+     *              as reference.
+     */
+    void UnshareFormulaCells( SCTAB nTab, SCCOL nCol, std::vector<SCROW>& rRows );
+    void RegroupFormulaCells( SCTAB nTab, SCCOL nCol );
+
     ScFormulaVectorState GetFormulaVectorState( const ScAddress& rPos ) const;
 
     formula::FormulaTokenRef ResolveStaticReference( const ScAddress& rPos );
@@ -2130,15 +2148,6 @@ private: // CLOOK-Impl-methods
 
     void SharePooledResources( ScDocument* pSrcDoc );
 };
-inline void ScDocument::GetSortParam( ScSortParam& rParam, SCTAB nTab )
-{
-    rParam = mSheetSortParams[ nTab ];
-}
-
-inline void ScDocument::SetSortParam( ScSortParam& rParam, SCTAB nTab )
-{
-    mSheetSortParams[ nTab ] = rParam;
-}
 
 #endif
 
diff --git a/sc/inc/formulacell.hxx b/sc/inc/formulacell.hxx
index 2d25c9b..9c7cd10 100644
--- a/sc/inc/formulacell.hxx
+++ b/sc/inc/formulacell.hxx
@@ -322,6 +322,8 @@ public:
     void            SetNextTrack( ScFormulaCell* pF );
 
     virtual void Notify( const SfxHint& rHint );
+    virtual void Query( SvtListener::QueryBase& rQuery ) const;
+
     void SetCompile( bool bVal );
     ScDocument* GetDocument() const;
     void            SetMatColsRows( SCCOL nCols, SCROW nRows, bool bDirtyFlag=true );
diff --git a/sc/inc/listenerquery.hxx b/sc/inc/listenerquery.hxx
new file mode 100644
index 0000000..2cbc957
--- /dev/null
+++ b/sc/inc/listenerquery.hxx
@@ -0,0 +1,50 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef SC_LISTENERQUERY_HXX
+#define SC_LISTENERQUERY_HXX
+
+#include <address.hxx>
+#include <svl/listener.hxx>
+
+namespace sc {
+
+/**
+ * Used to collect positions of formula cells that belong to a formula
+ * group.
+ */
+class RefQueryFormulaGroup : public SvtListener::QueryBase
+{
+public:
+    typedef std::vector<SCROW> ColType;
+    typedef boost::unordered_map<SCCOL,ColType> ColsType;
+    typedef boost::unordered_map<SCTAB,ColsType> TabsType;
+
+    RefQueryFormulaGroup();
+    virtual ~RefQueryFormulaGroup();
+
+    void setSkipRange( const ScRange& rRange );
+    void add( const ScAddress& rPos );
+
+    /**
+     * Row positions in each column may contain duplicates.  Caller must
+     * remove duplicates if necessary.
+     */
+    const TabsType& getAllPositions() const;
+
+private:
+    ScRange maSkipRange;
+    TabsType maTabs;
+};
+
+}
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/inc/listenerqueryids.hxx b/sc/inc/listenerqueryids.hxx
new file mode 100644
index 0000000..48f240b
--- /dev/null
+++ b/sc/inc/listenerqueryids.hxx
@@ -0,0 +1,17 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef SC_LISTENERQUERYIDS_HXX
+#define SC_LISTENERQUERYIDS_HXX
+
+#define SC_LISTENER_QUERY_FORMULA_GROUP_POS 0
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/inc/refhint.hxx b/sc/inc/refhint.hxx
index 3ffe861..6ccda8b 100644
--- a/sc/inc/refhint.hxx
+++ b/sc/inc/refhint.hxx
@@ -18,7 +18,11 @@ namespace sc {
 class RefHint : public SfxSimpleHint
 {
 public:
-    enum Type { Moved, ColumnReordered };
+    enum Type {
+        Moved,
+        ColumnReordered,
+        RowReordered
+    };
 
 private:
     Type meType;
@@ -57,22 +61,40 @@ public:
 
 class RefColReorderHint : public RefHint
 {
-    const sc::ColReorderMapType& mrColMap;
+    const sc::ColRowReorderMapType& mrColMap;
     SCTAB mnTab;
     SCROW mnRow1;
     SCROW mnRow2;
 
 public:
-    RefColReorderHint( const sc::ColReorderMapType& rColMap, SCTAB nTab, SCROW nRow1, SCROW nRow2 );
+    RefColReorderHint( const sc::ColRowReorderMapType& rColMap, SCTAB nTab, SCROW nRow1, SCROW nRow2 );
     virtual ~RefColReorderHint();
 
-    const sc::ColReorderMapType& getColMap() const;
+    const sc::ColRowReorderMapType& getColMap() const;
 
     SCTAB getTab() const;
     SCROW getStartRow() const;
     SCROW getEndRow() const;
 };
 
+class RefRowReorderHint : public RefHint
+{
+    const sc::ColRowReorderMapType& mrRowMap;
+    SCTAB mnTab;
+    SCCOL mnCol1;
+    SCCOL mnCol2;
+
+public:
+    RefRowReorderHint( const sc::ColRowReorderMapType& rRowMap, SCTAB nTab, SCCOL nCol1, SCCOL nCol2 );
+    virtual ~RefRowReorderHint();
+
+    const sc::ColRowReorderMapType& getRowMap() const;
+
+    SCTAB getTab() const;
+    SCCOL getStartColumn() const;
+    SCCOL getEndColumn() const;
+};
+
 }
 
 #endif
diff --git a/sc/inc/sharedformula.hxx b/sc/inc/sharedformula.hxx
index 571d73c..453b14f 100644
--- a/sc/inc/sharedformula.hxx
+++ b/sc/inc/sharedformula.hxx
@@ -100,6 +100,15 @@ public:
      * @param rCell formula cell instance
      */
     static void unshareFormulaCell(const CellStoreType::position_type& aPos, ScFormulaCell& rCell);
+
+    /**
+     * Make specified formula cells non-shared ones, and split them off from
+     * their respective adjacent formula cell groups.
+     *
+     * @param rCells cell storage container
+     * @param rRows row positions at which to unshare formula cells.
+     */
+    static void unshareFormulaCells(CellStoreType& rCells, std::vector<SCROW>& rRows);
 };
 
 }
diff --git a/sc/inc/sortparam.hxx b/sc/inc/sortparam.hxx
index b6f1427..4c3ef1b 100644
--- a/sc/inc/sortparam.hxx
+++ b/sc/inc/sortparam.hxx
@@ -80,6 +80,33 @@ struct SC_DLLPUBLIC ScSortParam
     inline sal_uInt16 GetSortKeyCount() const { return maKeyState.size(); }
 };
 
+namespace sc {
+
+struct SC_DLLPUBLIC ReorderParam
+{
+    /**
+     * This sort range already takes into account the presence or absence of
+     * header row / column i.e. if a header row / column is present, it
+     * excludes that row / column.
+     */
+    ScRange maSortRange;
+
+    /**
+     * List of original column / row positions after reordering.
+     */
+    std::vector<SCCOLROW> maOrderIndices;
+    bool mbByRow;
+    bool mbPattern;
+    bool mbHiddenFiltered;
+
+    /**
+     * Reorder the position indices such that it can be used to undo the
+     * original reordering.
+     */
+    void reverse();
+};
+
+}
 
 #endif // SC_SORTPARAM_HXX
 
diff --git a/sc/inc/table.hxx b/sc/inc/table.hxx
index fe8adb6..97ee720 100644
--- a/sc/inc/table.hxx
+++ b/sc/inc/table.hxx
@@ -71,6 +71,7 @@ class DocumentStreamAccess;
 class CompileFormulaContext;
 struct SetFormulaDirtyContext;
 class RefMovedHint;
+struct ReorderParam;
 
 }
 
@@ -828,7 +829,10 @@ public:
     void        StripHidden( SCCOL& rX1, SCROW& rY1, SCCOL& rX2, SCROW& rY2 );
     void        ExtendHidden( SCCOL& rX1, SCROW& rY1, SCCOL& rX2, SCROW& rY2 );
 
-    void        Sort(const ScSortParam& rSortParam, bool bKeepQuery, ScProgress* pProgress);
+    void Sort(
+        const ScSortParam& rSortParam, bool bKeepQuery, ScProgress* pProgress, sc::ReorderParam* pUndo );
+    void Reorder( const sc::ReorderParam& rParam, ScProgress* pProgress );
+
     bool ValidQuery(
         SCROW nRow, const ScQueryParam& rQueryParam, ScRefCellValue* pCell = NULL,
         bool* pbTestEqualCondition = NULL);
@@ -884,6 +888,9 @@ public:
     formula::FormulaTokenRef ResolveStaticReference( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 );
     formula::VectorRefArray FetchVectorRefArray( SCCOL nCol, SCROW nRow1, SCROW nRow2 );
 
+    void UnshareFormulaCells( SCCOL nCol, std::vector<SCROW>& rRows );
+    void RegroupFormulaCells( SCCOL nCol );
+
     ScRefCellValue GetRefCellValue( SCCOL nCol, SCROW nRow );
 
     SvtBroadcaster* GetBroadcaster( SCCOL nCol, SCROW nRow );
@@ -998,10 +1005,11 @@ private:
         ScRefCellValue& rCell2, SCCOL nCell2Col, SCROW nCell2Row ) const;
     short       Compare(SCCOLROW nIndex1, SCCOLROW nIndex2) const;
     short       Compare( ScSortInfoArray*, SCCOLROW nIndex1, SCCOLROW nIndex2) const;
-    ScSortInfoArray* CreateSortInfoArray( SCCOLROW nInd1, SCCOLROW nInd2, bool bKeepQuery );
+    ScSortInfoArray* CreateSortInfoArray( const sc::ReorderParam& rParam );
+    ScSortInfoArray* CreateSortInfoArray( const ScSortParam& rSortParam, SCCOLROW nInd1, SCCOLROW nInd2, bool bKeepQuery );
     void        QuickSort( ScSortInfoArray*, SCsCOLROW nLo, SCsCOLROW nHi);
-    void SortReorder( ScSortInfoArray* pArray, ScProgress* pProgress );
-    void SortReorderByRow( ScSortInfoArray* pArray, ScProgress* pProgress );
+    void SortReorderByColumn( ScSortInfoArray* pArray, SCROW nRow1, SCROW nRow2, bool bPattern, ScProgress* pProgress );
+    void SortReorderByRow( ScSortInfoArray* pArray, SCCOL nCol1, SCCOL nCol2, ScProgress* pProgress );
 
     bool        CreateExcelQuery(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, ScQueryParam& rQueryParam);
     bool        CreateStarQuery(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, ScQueryParam& rQueryParam);
diff --git a/sc/inc/tokenarray.hxx b/sc/inc/tokenarray.hxx
index 8715e9c..fbb613c 100644
--- a/sc/inc/tokenarray.hxx
+++ b/sc/inc/tokenarray.hxx
@@ -167,7 +167,13 @@ public:
      * @param nRow2 bottom row of reordered range.
      * @param rColMap old-to-new column mapping.
      */
-    void MoveReference( const ScAddress& rPos, SCTAB nTab, SCROW nRow1, SCROW nRow2, const sc::ColReorderMapType& rColMap );
+    void MoveReferenceColReorder(
+        const ScAddress& rPos, SCTAB nTab, SCROW nRow1, SCROW nRow2,
+        const sc::ColRowReorderMapType& rColMap );
+
+    void MoveReferenceRowReorder(
+        const ScAddress& rPos, SCTAB nTab, SCCOL nCol1, SCCOL nCol2,
+        const sc::ColRowReorderMapType& rRowMap );
 
     /**
      * Adjust all references in named expression. In named expression, we only
diff --git a/sc/inc/types.hxx b/sc/inc/types.hxx
index e0163aa..732ff19 100644
--- a/sc/inc/types.hxx
+++ b/sc/inc/types.hxx
@@ -98,7 +98,7 @@ struct RangeMatrix
     bool isRangeValid() const;
 };
 
-typedef boost::unordered_map<SCCOL,SCCOL> ColReorderMapType;
+typedef boost::unordered_map<SCCOLROW,SCCOLROW> ColRowReorderMapType;
 
 }
 
diff --git a/sc/inc/undosort.hxx b/sc/inc/undosort.hxx
new file mode 100644
index 0000000..388fcfa
--- /dev/null
+++ b/sc/inc/undosort.hxx
@@ -0,0 +1,37 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDED_SC_UNDOSORT_HXX
+#define INCLUDED_SC_UNDOSORT_HXX
+
+#include <undobase.hxx>
+#include <sortparam.hxx>
+
+namespace sc {
+
+class UndoSort : public ScSimpleUndo
+{
+    ReorderParam maParam;
+
+public:
+    UndoSort( ScDocShell* pDocSh, const ReorderParam& rParam );
+
+    virtual OUString GetComment() const;
+    virtual void Undo();
+    virtual void Redo();
+
+private:
+    void Execute( bool bUndo );
+};
+
+}
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/qa/unit/filters-test.cxx b/sc/qa/unit/filters-test.cxx
index e7dcae2..dab2b9e 100644
--- a/sc/qa/unit/filters-test.cxx
+++ b/sc/qa/unit/filters-test.cxx
@@ -33,6 +33,10 @@
 #include "drwlayer.hxx"
 #include "userdat.hxx"
 #include "formulacell.hxx"
+#include <dbdocfun.hxx>
+#include <globalnames.hxx>
+#include <dbdata.hxx>
+#include <sortparam.hxx>
 
 #include <svx/svdpage.hxx>
 
diff --git a/sc/qa/unit/ucalc.cxx b/sc/qa/unit/ucalc.cxx
index e993a9b..fbc2919 100644
--- a/sc/qa/unit/ucalc.cxx
+++ b/sc/qa/unit/ucalc.cxx
@@ -51,6 +51,7 @@
 #include "queryparam.hxx"
 #include "edittextiterator.hxx"
 #include "editutil.hxx"
+#include <sortparam.hxx>
 
 #include "formula/IFunctionDescription.hxx"
 
@@ -4276,7 +4277,7 @@ void Test::testSortWithFormulaRefs()
     aSortData.maKeyState[0].bDoSort = true;
     aSortData.maKeyState[0].nField = 0;
 
-    pDoc->Sort(0, aSortData, false, NULL);
+    pDoc->Sort(0, aSortData, false, NULL, NULL);
 
     nEnd = SAL_N_ELEMENTS( aResults );
     for ( SCROW i = nStart; i < nEnd; ++i )
@@ -4312,7 +4313,7 @@ void Test::testSortWithStrings()
     aParam.maKeyState[0].bAscending = true;
     aParam.maKeyState[0].nField = 1;
 
-    m_pDoc->Sort(0, aParam, false, NULL);
+    m_pDoc->Sort(0, aParam, false, NULL, NULL);
 
     CPPUNIT_ASSERT_EQUAL(OUString("Header"), m_pDoc->GetString(ScAddress(1,1,0)));
     CPPUNIT_ASSERT_EQUAL(OUString("Val1"), m_pDoc->GetString(ScAddress(1,2,0)));
@@ -4320,7 +4321,7 @@ void Test::testSortWithStrings()
 
     aParam.maKeyState[0].bAscending = false;
 
-    m_pDoc->Sort(0, aParam, false, NULL);
+    m_pDoc->Sort(0, aParam, false, NULL, NULL);
 
     CPPUNIT_ASSERT_EQUAL(OUString("Header"), m_pDoc->GetString(ScAddress(1,1,0)));
     CPPUNIT_ASSERT_EQUAL(OUString("Val2"), m_pDoc->GetString(ScAddress(1,2,0)));
@@ -4366,7 +4367,7 @@ void Test::testSort()
     aSortData.maKeyState[0].nField = 1;
     aSortData.maKeyState[0].bAscending = true;
 
-    m_pDoc->Sort(0, aSortData, false, NULL);
+    m_pDoc->Sort(0, aSortData, false, NULL, NULL);
 
     double nVal = m_pDoc->GetValue(1,0,0);
     ASSERT_DOUBLES_EQUAL(nVal, 1.0);
@@ -4399,7 +4400,7 @@ void Test::testSort()
     aSortData.nRow2 = aDataRange.aEnd.Row();
     aSortData.bHasHeader = true;
     aSortData.maKeyState[0].nField = 0;
-    m_pDoc->Sort(0, aSortData, false, NULL);
+    m_pDoc->Sort(0, aSortData, false, NULL, NULL);
 
     // Title should stay at the top, numbers should be sorted numerically,
     // numbers always come before strings, and empty cells always occur at the
diff --git a/sc/source/core/data/documen3.cxx b/sc/source/core/data/documen3.cxx
index b2efbdf..75514fd 100644
--- a/sc/source/core/data/documen3.cxx
+++ b/sc/source/core/data/documen3.cxx
@@ -1354,17 +1354,30 @@ bool ScDocument::UpdateOutlineRow( SCROW nStartRow, SCROW nEndRow, SCTAB nTab, b
     return false;
 }
 
-void ScDocument::Sort(SCTAB nTab, const ScSortParam& rSortParam, bool bKeepQuery, ScProgress* pProgress)
+void ScDocument::Sort(
+    SCTAB nTab, const ScSortParam& rSortParam, bool bKeepQuery, ScProgress* pProgress, sc::ReorderParam* pUndo )
 {
     if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
     {
         bool bOldEnableIdle = IsIdleEnabled();
         EnableIdle(false);
-        maTabs[nTab]->Sort(rSortParam, bKeepQuery, pProgress);
+        maTabs[nTab]->Sort(rSortParam, bKeepQuery, pProgress, pUndo);
         EnableIdle(bOldEnableIdle);
     }
 }
 
+void ScDocument::Reorder( const sc::ReorderParam& rParam, ScProgress* pProgress )
+{
+    ScTable* pTab = FetchTable(rParam.maSortRange.aStart.Tab());
+    if (!pTab)
+        return;
+
+    bool bOldEnableIdle = IsIdleEnabled();
+    EnableIdle(false);
+    pTab->Reorder(rParam, pProgress);
+    EnableIdle(bOldEnableIdle);
+}
+
 SCSIZE ScDocument::Query(SCTAB nTab, const ScQueryParam& rQueryParam, bool bKeepSub)
 {
     if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
@@ -2016,4 +2029,14 @@ void ScDocument::ExtendPrintArea( OutputDevice* pDev, SCTAB nTab,
         maTabs[nTab]->ExtendPrintArea( pDev, nStartCol, nStartRow, rEndCol, nEndRow );
 }
 
+void ScDocument::GetSortParam( ScSortParam& rParam, SCTAB nTab )
+{
+    rParam = mSheetSortParams[ nTab ];
+}
+
+void ScDocument::SetSortParam( ScSortParam& rParam, SCTAB nTab )
+{
+    mSheetSortParams[ nTab ] = rParam;
+}
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/core/data/document10.cxx b/sc/source/core/data/document10.cxx
index a4ede21..cb64221 100644
--- a/sc/source/core/data/document10.cxx
+++ b/sc/source/core/data/document10.cxx
@@ -93,4 +93,22 @@ bool ScDocument::HasUniformRowHeight( SCTAB nTab, SCROW nRow1, SCROW nRow2 ) con
     return pTab->HasUniformRowHeight(nRow1, nRow2);
 }
 
+void ScDocument::UnshareFormulaCells( SCTAB nTab, SCCOL nCol, std::vector<SCROW>& rRows )
+{
+    ScTable* pTab = FetchTable(nTab);
+    if (!pTab)
+        return;
+
+    pTab->UnshareFormulaCells(nCol, rRows);
+}
+
+void ScDocument::RegroupFormulaCells( SCTAB nTab, SCCOL nCol )
+{
+    ScTable* pTab = FetchTable(nTab);
+    if (!pTab)
+        return;
+
+    pTab->RegroupFormulaCells(nCol);
+}
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/core/data/formulacell.cxx b/sc/source/core/data/formulacell.cxx
index 1397372..18194e1 100644
--- a/sc/source/core/data/formulacell.cxx
+++ b/sc/source/core/data/formulacell.cxx
@@ -52,6 +52,8 @@
 #include "refupdatecontext.hxx"
 #include <tokenstringcontext.hxx>
 #include <refhint.hxx>
+#include <listenerquery.hxx>
+#include <listenerqueryids.hxx>
 
 #include <boost/scoped_ptr.hpp>
 
@@ -1915,8 +1917,23 @@ void ScFormulaCell::Notify( const SfxHint& rHint )
                 const sc::RefColReorderHint& rRefColReorder =
                     static_cast<const sc::RefColReorderHint&>(rRefHint);
                 if (!IsShared() || IsSharedTop())
-                    pCode->MoveReference(
-                        aPos, rRefColReorder.getTab(), rRefColReorder.getStartRow(), rRefColReorder.getEndRow(), rRefColReorder.getColMap());
+                    pCode->MoveReferenceColReorder(
+                        aPos, rRefColReorder.getTab(),
+                        rRefColReorder.getStartRow(),
+                        rRefColReorder.getEndRow(),
+                        rRefColReorder.getColMap());
+            }
+            break;
+            case sc::RefHint::RowReordered:
+            {
+                const sc::RefRowReorderHint& rRefRowReorder =
+                    static_cast<const sc::RefRowReorderHint&>(rRefHint);
+                if (!IsShared() || IsSharedTop())
+                    pCode->MoveReferenceRowReorder(
+                        aPos, rRefRowReorder.getTab(),
+                        rRefRowReorder.getStartColumn(),
+                        rRefRowReorder.getEndColumn(),
+                        rRefRowReorder.getRowMap());
             }
             break;
             default:
@@ -1961,6 +1978,23 @@ void ScFormulaCell::Notify( const SfxHint& rHint )
     }
 }
 
+void ScFormulaCell::Query( SvtListener::QueryBase& rQuery ) const
+{
+    switch (rQuery.getId())
+    {
+        case SC_LISTENER_QUERY_FORMULA_GROUP_POS:
+        {
+            sc::RefQueryFormulaGroup& rRefQuery =
+                static_cast<sc::RefQueryFormulaGroup&>(rQuery);
+            if (IsShared())
+                rRefQuery.add(aPos);
+        }
+        break;
+        default:
+            ;
+    }
+}
+
 void ScFormulaCell::SetDirty( bool bDirtyFlag )
 {
     if ( !IsInChangeTrack() )
diff --git a/sc/source/core/data/sortparam.cxx b/sc/source/core/data/sortparam.cxx
index d416f32..e4aee16 100644
--- a/sc/source/core/data/sortparam.cxx
+++ b/sc/source/core/data/sortparam.cxx
@@ -252,4 +252,55 @@ void ScSortParam::MoveToDest()
     }
 }
 
+namespace sc {
+
+namespace {
+
+struct ReorderIndex
+{
+    struct LessByPos2 : std::binary_function<ReorderIndex, ReorderIndex, bool>
+    {
+        bool operator() ( const ReorderIndex& r1, const ReorderIndex& r2 ) const
+        {
+            return r1.mnPos2 < r2.mnPos2;
+        }
+    };
+
+    SCCOLROW mnPos1;
+    SCCOLROW mnPos2;
+
+    ReorderIndex( SCCOLROW nPos1, SCCOLROW nPos2 ) : mnPos1(nPos1), mnPos2(nPos2) {}
+};
+
+}
+
+void ReorderParam::reverse()
+{
+    SCCOLROW nStart;
+    if (mbByRow)
+        nStart = maSortRange.aStart.Row();
+    else
+        nStart = maSortRange.aStart.Col();
+
+    size_t n = maOrderIndices.size();
+    std::vector<ReorderIndex> aBucket;
+    aBucket.reserve(n);
+    for (size_t i = 0; i < n; ++i)
+    {
+        SCCOLROW nPos1 = i + nStart;
+        SCCOLROW nPos2 = maOrderIndices[i];
+        aBucket.push_back(ReorderIndex(nPos1, nPos2));
+    }
+
+    std::sort(aBucket.begin(), aBucket.end(), ReorderIndex::LessByPos2());
+    std::vector<SCCOLROW> aNew;
+    aNew.reserve(n);
+    for (size_t i = 0; i < n; ++i)
+        aNew.push_back(aBucket[i].mnPos1);
+
+    maOrderIndices.swap(aNew);
+}
+
+}
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/core/data/table3.cxx b/sc/source/core/data/table3.cxx
index 6a169ef..31cfe2e 100644
--- a/sc/source/core/data/table3.cxx
+++ b/sc/source/core/data/table3.cxx
@@ -61,6 +61,7 @@
 #include <listenercontext.hxx>
 #include <sharedformula.hxx>
 #include <refhint.hxx>
+#include <listenerquery.hxx>
 
 #include "svl/sharedstringpool.hxx"
 
@@ -257,39 +258,46 @@ private:
     SCCOLROW        mnLastIndex; /// index of last non-empty cell position.
     sal_uInt16      nUsedSorts;
 
-    std::vector<SCCOLROW> maOldIndices;
+    std::vector<SCCOLROW> maOrderIndices;
     bool mbKeepQuery;
 
 public:
     ScSortInfoArray( sal_uInt16 nSorts, SCCOLROW nInd1, SCCOLROW nInd2 ) :
-        pppInfo( new ScSortInfo**[nSorts]),
+        pppInfo(NULL),
         nCount( nInd2 - nInd1 + 1 ), nStart( nInd1 ),
         mnLastIndex(nInd2),
         nUsedSorts(nSorts),
         mbKeepQuery(false)
     {
-        for ( sal_uInt16 nSort = 0; nSort < nUsedSorts; nSort++ )
+        if (nUsedSorts)
         {
-            ScSortInfo** ppInfo = new ScSortInfo* [nCount];
-            for ( SCSIZE j = 0; j < nCount; j++ )
-                ppInfo[j] = new ScSortInfo;
-            pppInfo[nSort] = ppInfo;
+            pppInfo = new ScSortInfo**[nUsedSorts];
+            for ( sal_uInt16 nSort = 0; nSort < nUsedSorts; nSort++ )
+            {
+                ScSortInfo** ppInfo = new ScSortInfo* [nCount];
+                for ( SCSIZE j = 0; j < nCount; j++ )
+                    ppInfo[j] = new ScSortInfo;
+                pppInfo[nSort] = ppInfo;
+            }
         }
 
         for (size_t i = 0; i < nCount; ++i)
-            maOldIndices.push_back(i+nStart);
+            maOrderIndices.push_back(i+nStart);
     }
 
     ~ScSortInfoArray()
     {
-        for ( sal_uInt16 nSort = 0; nSort < nUsedSorts; nSort++ )
+        if (pppInfo)
         {
-            ScSortInfo** ppInfo = pppInfo[nSort];
-            for ( SCSIZE j = 0; j < nCount; j++ )
-                delete ppInfo[j];
-            delete [] ppInfo;
+            for ( sal_uInt16 nSort = 0; nSort < nUsedSorts; nSort++ )
+            {
+                ScSortInfo** ppInfo = pppInfo[nSort];
+                for ( SCSIZE j = 0; j < nCount; j++ )
+                    delete ppInfo[j];
+                delete [] ppInfo;
+            }
+            delete[] pppInfo;
         }
-        delete[] pppInfo;
 
         if (mpRows)
             std::for_each(mpRows->begin(), mpRows->end(), ScDeleteObjectByPtr<Row>());
@@ -299,11 +307,30 @@ public:
 
     bool IsKeepQuery() const { return mbKeepQuery; }
 
+    /**
+     * Call this only during normal sorting, not from reordering.
+     */
+    ScSortInfo** GetFirstArray() const
+    {
+        OSL_ASSERT(pppInfo);
+        return pppInfo[0];
+    }
+
+    /**
+     * Call this only during normal sorting, not from reordering.
+     */
     ScSortInfo* Get( sal_uInt16 nSort, SCCOLROW nInd )
-                    { return (pppInfo[nSort])[ nInd - nStart ]; }
+    {
+        OSL_ASSERT(pppInfo);
+        return (pppInfo[nSort])[ nInd - nStart ];
+    }
 
+    /**
+     * Call this only during normal sorting, not from reordering.
+     */
     void Swap( SCCOLROW nInd1, SCCOLROW nInd2 )
     {
+        OSL_ASSERT(pppInfo);
         SCSIZE n1 = static_cast<SCSIZE>(nInd1 - nStart);
         SCSIZE n2 = static_cast<SCSIZE>(nInd2 - nStart);
         for ( sal_uInt16 nSort = 0; nSort < nUsedSorts; nSort++ )
@@ -314,7 +341,7 @@ public:
             ppInfo[n2] = pTmp;
         }
 
-        std::swap(maOldIndices[n1], maOldIndices[n2]);
+        std::swap(maOrderIndices[n1], maOrderIndices[n2]);
 
         if (mpRows)
         {
@@ -324,13 +351,47 @@ public:
         }
     }
 
+    void SetOrderIndices( const std::vector<SCCOLROW>& rIndices )
+    {
+        maOrderIndices = rIndices;
+    }
+
+    /**
+     * @param rIndices indices are actual row positions on the sheet, not an
+     *                 offset from the top row.
+     */
+    void ReorderByRow( const std::vector<SCCOLROW>& rIndices )
+    {
+        if (!mpRows)
+            return;
+
+        RowsType& rRows = *mpRows;
+
+        std::vector<SCCOLROW> aOrderIndices2;
+        aOrderIndices2.reserve(rIndices.size());
+
+        RowsType aRows2;
+        aRows2.reserve(rRows.size());
+
+        std::vector<SCCOLROW>::const_iterator it = rIndices.begin(), itEnd = rIndices.end();
+        for (; it != itEnd; ++it)
+        {
+            size_t nPos = *it - nStart; // switch to an offset to top row.
+            aRows2.push_back(rRows[nPos]);
+            aOrderIndices2.push_back(maOrderIndices[nPos]);
+        }
+
+        rRows.swap(aRows2);
+        maOrderIndices.swap(aOrderIndices2);
+    }
+
     sal_uInt16      GetUsedSorts() const { return nUsedSorts; }
-    ScSortInfo**    GetFirstArray() const { return pppInfo[0]; }
+
     SCCOLROW    GetStart() const { return nStart; }
     SCCOLROW GetLast() const { return mnLastIndex; }
     SCSIZE      GetCount() const { return nCount; }
 
-    const std::vector<SCCOLROW>& GetOldIndices() const { return maOldIndices; }
+    const std::vector<SCCOLROW>& GetOrderIndices() const { return maOrderIndices; }
 
     RowsType& InitDataRows( size_t nRowSize, size_t nColSize )
     {
@@ -348,19 +409,98 @@ public:
     }
 };
 
-ScSortInfoArray* ScTable::CreateSortInfoArray( SCCOLROW nInd1, SCCOLROW nInd2, bool bKeepQuery )
+namespace {
+
+void initDataRows(
+    ScSortInfoArray& rArray, ScTable& rTab, ScColumn* pCols,
+    SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
+    bool bPattern, bool bHiddenFiltered )
+{
+    // Fill row-wise data table.
+    ScSortInfoArray::RowsType& rRows = rArray.InitDataRows(nRow2-nRow1+1, nCol2-nCol1+1);
+
+    for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol)
+    {
+        ScColumn& rCol = pCols[nCol];
+
+        // Skip reordering of cell formats if the whole span is on the same pattern entry.
+        bool bUniformPattern = rCol.GetPatternCount(nRow1, nRow2) < 2u;
+
+        sc::ColumnBlockConstPosition aBlockPos;
+        rCol.InitBlockPosition(aBlockPos);
+        for (SCROW nRow = nRow1; nRow <= nRow2; ++nRow)
+        {
+            ScSortInfoArray::Row& rRow = *rRows[nRow-nRow1];
+            ScSortInfoArray::Cell& rCell = rRow.maCells[nCol-nCol1];
+
+            rCell.maCell = rCol.GetCellValue(aBlockPos, nRow);
+            rCell.mpAttr = rCol.GetCellTextAttr(aBlockPos, nRow);
+            rCell.mpBroadcaster = rCol.GetBroadcaster(aBlockPos, nRow);
+            rCell.mpNote = rCol.GetCellNote(aBlockPos, nRow);
+
+            if (!bUniformPattern && bPattern)
+                rCell.mpPattern = rCol.GetPattern(nRow);
+        }
+    }
+
+    if (bHiddenFiltered)
+    {
+        for (SCROW nRow = nRow1; nRow <= nRow2; ++nRow)
+        {
+            ScSortInfoArray::Row& rRow = *rRows[nRow-nRow1];
+            rRow.mbHidden = rTab.RowHidden(nRow);
+            rRow.mbFiltered = rTab.RowFiltered(nRow);
+        }
+    }
+}
+
+}
+
+ScSortInfoArray* ScTable::CreateSortInfoArray( const sc::ReorderParam& rParam )
+{
+    ScSortInfoArray* pArray = NULL;
+
+    if (rParam.mbByRow)
+    {
+        // Create a sort info array with just the data table.
+        SCROW nRow1 = rParam.maSortRange.aStart.Row();
+        SCROW nRow2 = rParam.maSortRange.aEnd.Row();
+        SCCOL nCol1 = rParam.maSortRange.aStart.Col();
+        SCCOL nCol2 = rParam.maSortRange.aEnd.Col();
+
+        pArray = new ScSortInfoArray(0, nRow1, nRow2);
+        pArray->SetKeepQuery(rParam.mbHiddenFiltered);
+
+        initDataRows(
+            *pArray, *this, aCol, nCol1, nRow1, nCol2, nRow2,
+            rParam.mbPattern, rParam.mbHiddenFiltered);
+    }
+    else
+    {
+        SCCOLROW nCol1 = rParam.maSortRange.aStart.Col();
+        SCCOLROW nCol2 = rParam.maSortRange.aEnd.Col();
+
+        pArray = new ScSortInfoArray(0, nCol1, nCol2);
+        pArray->SetKeepQuery(rParam.mbHiddenFiltered);
+    }
+
+    return pArray;
+}
+
+ScSortInfoArray* ScTable::CreateSortInfoArray(
+    const ScSortParam& rSortParam, SCCOLROW nInd1, SCCOLROW nInd2, bool bKeepQuery )
 {
     sal_uInt16 nUsedSorts = 1;
-    while ( nUsedSorts < aSortParam.GetSortKeyCount() && aSortParam.maKeyState[nUsedSorts].bDoSort )
+    while ( nUsedSorts < rSortParam.GetSortKeyCount() && rSortParam.maKeyState[nUsedSorts].bDoSort )
         nUsedSorts++;
     ScSortInfoArray* pArray = new ScSortInfoArray( nUsedSorts, nInd1, nInd2 );
     pArray->SetKeepQuery(bKeepQuery);
 
-    if ( aSortParam.bByRow )
+    if ( rSortParam.bByRow )
     {
         for ( sal_uInt16 nSort = 0; nSort < nUsedSorts; nSort++ )
         {
-            SCCOL nCol = static_cast<SCCOL>(aSortParam.maKeyState[nSort].nField);
+            SCCOL nCol = static_cast<SCCOL>(rSortParam.maKeyState[nSort].nField);
             ScColumn* pCol = &aCol[nCol];
             sc::ColumnBlockConstPosition aBlockPos;
             pCol->InitBlockPosition(aBlockPos);
@@ -372,49 +512,15 @@ ScSortInfoArray* ScTable::CreateSortInfoArray( SCCOLROW nInd1, SCCOLROW nInd2, b
             }
         }
 
-        // Fill row-wise data table.
-        ScSortInfoArray::RowsType& rRows = pArray->InitDataRows(
-            nInd2 - nInd1 + 1, aSortParam.nCol2 - aSortParam.nCol1 + 1);
-
-        for (SCCOL nCol = aSortParam.nCol1; nCol <= aSortParam.nCol2; ++nCol)
-        {
-            ScColumn& rCol = aCol[nCol];
-
-            // Skip reordering of cell formats if the whole span is on the same pattern entry.
-            bool bUniformPattern = rCol.GetPatternCount(nInd1, nInd2) < 2u;
-
-            sc::ColumnBlockConstPosition aBlockPos;
-            rCol.InitBlockPosition(aBlockPos);
-            for (SCROW nRow = nInd1; nRow <= nInd2; ++nRow)
-            {
-                ScSortInfoArray::Row& rRow = *rRows[nRow-nInd1];
-                ScSortInfoArray::Cell& rCell = rRow.maCells[nCol-aSortParam.nCol1];
-
-                rCell.maCell = rCol.GetCellValue(aBlockPos, nRow);
-                rCell.mpAttr = rCol.GetCellTextAttr(aBlockPos, nRow);
-                rCell.mpBroadcaster = rCol.GetBroadcaster(aBlockPos, nRow);
-                rCell.mpNote = rCol.GetCellNote(aBlockPos, nRow);
-
-                if (!bUniformPattern && aSortParam.bIncludePattern)
-                    rCell.mpPattern = rCol.GetPattern(nRow);
-            }
-        }
-
-        if (bKeepQuery)
-        {
-            for (SCROW nRow = nInd1; nRow <= nInd2; ++nRow)
-            {
-                ScSortInfoArray::Row& rRow = *rRows[nRow-nInd1];
-                rRow.mbHidden = RowHidden(nRow);
-                rRow.mbFiltered = RowFiltered(nRow);
-            }
-        }
+        initDataRows(
+            *pArray, *this, aCol, rSortParam.nCol1, nInd1, rSortParam.nCol2, nInd2,
+            rSortParam.bIncludePattern, bKeepQuery);
     }
     else
     {
         for ( sal_uInt16 nSort = 0; nSort < nUsedSorts; nSort++ )
         {
-            SCROW nRow = aSortParam.maKeyState[nSort].nField;
+            SCROW nRow = rSortParam.maKeyState[nSort].nField;
             for ( SCCOL nCol = static_cast<SCCOL>(nInd1);
                     nCol <= static_cast<SCCOL>(nInd2); nCol++ )
             {
@@ -530,12 +636,13 @@ void ScTable::DestroySortCollator()
 
 namespace {
 
-class ColReorderNotifier : std::unary_function<SvtListener*, void>
+template<typename _Hint, typename _ReorderMap, typename _Index>
+class ReorderNotifier : std::unary_function<SvtListener*, void>
 {
-    sc::RefColReorderHint maHint;
+    _Hint maHint;
 public:
-    ColReorderNotifier( const sc::ColReorderMapType& rColMap, SCTAB nTab, SCROW nRow1, SCROW nRow2 ) :
-        maHint(rColMap, nTab, nRow1, nRow2) {}
+    ReorderNotifier( const _ReorderMap& rMap, SCTAB nTab, _Index nPos1, _Index nPos2 ) :
+        maHint(rMap, nTab, nPos1, nPos2) {}
 
     void operator() ( SvtListener* p )
     {
@@ -543,77 +650,86 @@ public:
     }
 };
 
-}
+typedef ReorderNotifier<sc::RefColReorderHint, sc::ColRowReorderMapType, SCCOL> ColReorderNotifier;
+typedef ReorderNotifier<sc::RefRowReorderHint, sc::ColRowReorderMapType, SCROW> RowReorderNotifier;
 
-void ScTable::SortReorder( ScSortInfoArray* pArray, ScProgress* pProgress )
+class FormulaGroupPosCollector : std::unary_function<SvtListener*, void>
 {
-    if (aSortParam.bByRow)
+    sc::RefQueryFormulaGroup& mrQuery;
+
+public:
+    FormulaGroupPosCollector( sc::RefQueryFormulaGroup& rQuery ) : mrQuery(rQuery) {}
+
+    void operator() ( SvtListener* p )
     {
-        SortReorderByRow(pArray, pProgress);
-        return;
+        p->Query(mrQuery);
     }
+};
 
-    size_t nCount = pArray->GetCount();
+}
+
+void ScTable::SortReorderByColumn(
+    ScSortInfoArray* pArray, SCROW nRow1, SCROW nRow2, bool bPattern, ScProgress* pProgress )
+{
     SCCOLROW nStart = pArray->GetStart();
     SCCOLROW nLast = pArray->GetLast();
-    ScSortInfo** ppInfo = pArray->GetFirstArray();
-
-    std::vector<ScSortInfo*> aTable(nCount);
 
-    SCSIZE nPos;
-    for ( nPos = 0; nPos < nCount; nPos++ )
-        aTable[ppInfo[nPos]->nOrg - nStart] = ppInfo[nPos];
+    std::vector<SCCOLROW> aIndices = pArray->GetOrderIndices();
+    size_t nCount = aIndices.size();
 
     // Cut formula grouping at row and reference boundaries before the reordering.
-    ScRange aSortRange(nStart, aSortParam.nRow1, nTab, nLast, aSortParam.nRow2, nTab);
+    ScRange aSortRange(nStart, nRow1, nTab, nLast, nRow2, nTab);
     for (SCCOL nCol = nStart; nCol <= nLast; ++nCol)
         aCol[nCol].SplitFormulaGroupByRelativeRef(aSortRange);
 
+    // table to keep track of column index to position in the index table.
+    std::vector<SCCOLROW> aPosTable(nCount);
+    for (size_t i = 0; i < nCount; ++i)
+        aPosTable[aIndices[i]-nStart] = i;
+
     SCCOLROW nDest = nStart;
-    for ( nPos = 0; nPos < nCount; nPos++, nDest++ )
+    for (size_t i = 0; i < nCount; ++i, ++nDest)
     {
-        SCCOLROW nOrg = ppInfo[nPos]->nOrg;
-        if ( nDest != nOrg )
+        SCCOLROW nSrc = aIndices[i];
+        if (nDest != nSrc)
         {
-            aCol[nDest].Swap(aCol[nOrg], aSortParam.nRow1, aSortParam.nRow2, aSortParam.bIncludePattern);
+            aCol[nDest].Swap(aCol[nSrc], nRow1, nRow2, bPattern);
 
-            // neue Position des weggeswapten eintragen
-            ScSortInfo* p = ppInfo[nPos];
-            p->nOrg = nDest;
-            ::std::swap(p, aTable[nDest-nStart]);
-            p->nOrg = nOrg;
-            ::std::swap(p, aTable[nOrg-nStart]);
-            OSL_ENSURE( p == ppInfo[nPos], "SortReorder: nOrg MisMatch" );
+            // Update the position of the index that was originally equal to nDest.
+            size_t nPos = aPosTable[nDest-nStart];
+            aIndices[nPos] = nSrc;
+            aPosTable[nSrc-nStart] = nPos;
         }
-        if(pProgress)
-            pProgress->SetStateOnPercent( nPos );
+
+        if (pProgress)
+            pProgress->SetStateOnPercent(i);
     }
 
     // Reset formula cell positions which became out-of-sync after column reordering.
     for (SCCOL nCol = nStart; nCol <= nLast; ++nCol)
-        aCol[nCol].ResetFormulaCellPositions(aSortParam.nRow1, aSortParam.nRow2);
+        aCol[nCol].ResetFormulaCellPositions(nRow1, nRow2);
 
     // Set up column reorder map (for later broadcasting of reference updates).
-    sc::ColReorderMapType aColMap;
-    const std::vector<SCCOLROW>& rOldIndices = pArray->GetOldIndices();
+    sc::ColRowReorderMapType aColMap;
+    const std::vector<SCCOLROW>& rOldIndices = pArray->GetOrderIndices();
     for (size_t i = 0, n = rOldIndices.size(); i < n; ++i)
     {
         SCCOL nNew = i + nStart;
-        SCROW nOld = rOldIndices[i];
-        aColMap.insert(sc::ColReorderMapType::value_type(nOld, nNew));
+        SCCOL nOld = rOldIndices[i];
+        aColMap.insert(sc::ColRowReorderMapType::value_type(nOld, nNew));
     }
 
     // Collect all listeners within sorted range ahead of time.
     std::vector<SvtListener*> aListeners;
     for (SCCOL nCol = nStart; nCol <= nLast; ++nCol)
-        aCol[nCol].CollectListeners(aListeners, aSortParam.nRow1, aSortParam.nRow2);
+        aCol[nCol].CollectListeners(aListeners, nRow1, nRow2);
 
     // Remove any duplicate listener entries and notify all listeners
     // afterward.  We must ensure that we notify each unique listener only
     // once.
     std::sort(aListeners.begin(), aListeners.end());
     aListeners.erase(std::unique(aListeners.begin(), aListeners.end()), aListeners.end());
-    ColReorderNotifier aFunc(aColMap, nTab, aSortParam.nRow1, aSortParam.nRow2);
+    ColReorderNotifier aFunc(aColMap, nTab, nRow1, nRow2);
     std::for_each(aListeners.begin(), aListeners.end(), aFunc);
 
     // Re-join formulas at row boundaries now that all the references have
@@ -621,28 +737,28 @@ void ScTable::SortReorder( ScSortInfoArray* pArray, ScProgress* pProgress )
     for (SCCOL nCol = nStart; nCol <= nLast; ++nCol)
     {
         sc::CellStoreType& rCells = aCol[nCol].maCells;
-        sc::CellStoreType::position_type aPos = rCells.position(aSortParam.nRow1);
+        sc::CellStoreType::position_type aPos = rCells.position(nRow1);
         sc::SharedFormulaUtil::joinFormulaCellAbove(aPos);
-        aPos = rCells.position(aPos.first, aSortParam.nRow2+1);
+        aPos = rCells.position(aPos.first, nRow2+1);
         sc::SharedFormulaUtil::joinFormulaCellAbove(aPos);
     }
 }
 
-void ScTable::SortReorderByRow( ScSortInfoArray* pArray, ScProgress* pProgress )
+void ScTable::SortReorderByRow(
+    ScSortInfoArray* pArray, SCCOL nCol1, SCCOL nCol2, ScProgress* pProgress )
 {
+    if (nCol2 < nCol1)
+        return;
+
     SCROW nRow1 = pArray->GetStart();
     SCROW nRow2 = pArray->GetLast();
     ScSortInfoArray::RowsType* pRows = pArray->GetDataRows();
     assert(pRows); // In sort-by-row mode we must have data rows already populated.
 
-    // Detach all formula cells within the sorted range first.
-    sc::EndListeningContext aCxt(*pDocument);
-    DetachFormulaCells(aCxt, aSortParam.nCol1, nRow1, aSortParam.nCol2, nRow2);
-
     // Cells in the data rows only reference values in the document. Make
     // a copy before updating the document.
 
-    size_t nColCount = aSortParam.nCol2 - aSortParam.nCol1 + 1;
+    size_t nColCount = nCol2 - nCol1 + 1;
     boost::ptr_vector<SortedColumn> aSortedCols; // storage for copied cells.
     SortedRowFlags aRowFlags;
     aSortedCols.reserve(nColCount);
@@ -659,7 +775,7 @@ void ScTable::SortReorderByRow( ScSortInfoArray* pArray, ScProgress* pProgress )
         ScSortInfoArray::Row* pRow = (*pRows)[i];
         for (size_t j = 0; j < pRow->maCells.size(); ++j)
         {
-            ScAddress aCellPos(aSortParam.nCol1 + j, nRow1 + i, nTab);
+            ScAddress aCellPos(nCol1 + j, nRow1 + i, nTab);
 
             ScSortInfoArray::Cell& rCell = pRow->maCells[j];
 
@@ -681,14 +797,14 @@ void ScTable::SortReorderByRow( ScSortInfoArray* pArray, ScProgress* pProgress )
                 case CELLTYPE_FORMULA:
                 {
                     assert(rCell.mpAttr);
-                    size_t n = rCellStore.size();
-                    sc::CellStoreType::iterator itBlk = rCellStore.push_back( rCell.maCell.mpFormula->Clone(
-                                aCellPos, SC_CLONECELL_DEFAULT | SC_CLONECELL_ADJUST3DREL));
-
-                    // Join the formula cells as we fill the container.
-                    size_t nOffset = n - itBlk->position;
-                    sc::CellStoreType::position_type aPos(itBlk, nOffset);
-                    sc::SharedFormulaUtil::joinFormulaCellAbove(aPos);
+                    ScAddress aOldPos = rCell.maCell.mpFormula->aPos;
+
+                    ScFormulaCell* pNew = rCell.maCell.mpFormula->Clone(
+                        aCellPos, SC_CLONECELL_DEFAULT | SC_CLONECELL_ADJUST3DREL);
+                    pNew->CopyAllBroadcasters(*rCell.maCell.mpFormula);
+                    pNew->GetCode()->AdjustReferenceOnMovedOrigin(aOldPos, aCellPos);
+
+                    sc::CellStoreType::iterator itBlk = rCellStore.push_back(pNew);
                 }
                 break;
                 default:
@@ -737,7 +853,7 @@ void ScTable::SortReorderByRow( ScSortInfoArray* pArray, ScProgress* pProgress )
 
     for (size_t i = 0, n = aSortedCols.size(); i < n; ++i)
     {
-        SCCOL nThisCol = i + aSortParam.nCol1;
+        SCCOL nThisCol = i + nCol1;
 
         {
             sc::CellStoreType& rDest = aCol[nThisCol].maCells;
@@ -812,10 +928,62 @@ void ScTable::SortReorderByRow( ScSortInfoArray* pArray, ScProgress* pProgress )
             SetRowFiltered(it->mnRow1, it->mnRow2, true);
     }
 
-    // Attach all formula cells within sorted range, to have them start listening again.
-    sc::StartListeningContext aStartListenCxt(*pDocument);
-    AttachFormulaCells(
-        aStartListenCxt, aSortParam.nCol1, nRow1, aSortParam.nCol2, nRow2);
+    // Set up row reorder map (for later broadcasting of reference updates).
+    sc::ColRowReorderMapType aRowMap;
+    const std::vector<SCCOLROW>& rOldIndices = pArray->GetOrderIndices();
+    for (size_t i = 0, n = rOldIndices.size(); i < n; ++i)
+    {
+        SCROW nNew = i + nRow1;
+        SCROW nOld = rOldIndices[i];
+        aRowMap.insert(sc::ColRowReorderMapType::value_type(nOld, nNew));
+    }
+
+    // Collect all listeners within sorted range ahead of time.
+    std::vector<SvtListener*> aListeners;
+    for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol)
+        aCol[nCol].CollectListeners(aListeners, nRow1, nRow2);
+
+    // Remove any duplicate listener entries.  We must ensure that we notify
+    // each unique listener only once.
+    std::sort(aListeners.begin(), aListeners.end());
+    aListeners.erase(std::unique(aListeners.begin(), aListeners.end()), aListeners.end());
+
+    // Collect positions of all shared formula cells outside the sorted range,
+    // and make them unshared before notifying them.
+    sc::RefQueryFormulaGroup aFormulaGroupPos;
+    aFormulaGroupPos.setSkipRange(ScRange(nCol1, nRow1, nTab, nCol2, nRow2, nTab));
+
+    std::for_each(aListeners.begin(), aListeners.end(), FormulaGroupPosCollector(aFormulaGroupPos));
+    const sc::RefQueryFormulaGroup::TabsType& rGroupTabs = aFormulaGroupPos.getAllPositions();
+    sc::RefQueryFormulaGroup::TabsType::const_iterator itGroupTab = rGroupTabs.begin(), itGroupTabEnd = rGroupTabs.end();
+    for (; itGroupTab != itGroupTabEnd; ++itGroupTab)
+    {
+        const sc::RefQueryFormulaGroup::ColsType& rCols = itGroupTab->second;
+        sc::RefQueryFormulaGroup::ColsType::const_iterator itCol = rCols.begin(), itColEnd = rCols.end();
+        for (; itCol != itColEnd; ++itCol)
+        {
+            const sc::RefQueryFormulaGroup::ColType& rCol = itCol->second;
+            std::vector<SCROW> aBounds(rCol);
+            pDocument->UnshareFormulaCells(itGroupTab->first, itCol->first, aBounds);
+        }
+    }
+
+    // Notify the listeners.
+    RowReorderNotifier aFunc(aRowMap, nTab, nCol1, nCol2);
+    std::for_each(aListeners.begin(), aListeners.end(), aFunc);
+
+    // Re-group formulas in affected columns.
+    for (itGroupTab = rGroupTabs.begin(); itGroupTab != itGroupTabEnd; ++itGroupTab)
+    {
+        const sc::RefQueryFormulaGroup::ColsType& rCols = itGroupTab->second;
+        sc::RefQueryFormulaGroup::ColsType::const_iterator itCol = rCols.begin(), itColEnd = rCols.end();
+        for (; itCol != itColEnd; ++itCol)
+            pDocument->RegroupFormulaCells(itGroupTab->first, itCol->first);
+    }
+
+    // Re-group columns in the sorted range too.
+    for (SCCOL i = nCol1; i <= nCol2; ++i)
+        aCol[i].RegroupFormulaCells();
 }
 
 short ScTable::CompareCell(
@@ -1034,11 +1202,21 @@ void ScTable::DecoladeRow( ScSortInfoArray* pArray, SCROW nRow1, SCROW nRow2 )
     }
 }
 
-void ScTable::Sort(const ScSortParam& rSortParam, bool bKeepQuery, ScProgress* pProgress)
+void ScTable::Sort(
+    const ScSortParam& rSortParam, bool bKeepQuery, ScProgress* pProgress, sc::ReorderParam* pUndo )
 {
     aSortParam = rSortParam;
     InitSortCollator( rSortParam );
     bGlobalKeepQuery = bKeepQuery;
+
+    if (pUndo)
+    {
+        // Copy over the basic sort parameters.
+        pUndo->mbByRow = rSortParam.bByRow;
+        pUndo->mbPattern = rSortParam.bIncludePattern;
+        pUndo->mbHiddenFiltered = bKeepQuery;
+    }
+
     if (rSortParam.bByRow)
     {
         SCROW nLastRow = 0;
@@ -1052,15 +1230,19 @@ void ScTable::Sort(const ScSortParam& rSortParam, bool bKeepQuery, ScProgress* p
             if(pProgress)
                 pProgress->SetState( 0, nLastRow-nRow1 );
 
-            boost::scoped_ptr<ScSortInfoArray> pArray(CreateSortInfoArray(nRow1, nLastRow, bKeepQuery));
+            boost::scoped_ptr<ScSortInfoArray> pArray(CreateSortInfoArray(aSortParam, nRow1, nLastRow, bKeepQuery));
 
             if ( nLastRow - nRow1 > 255 )
                 DecoladeRow(pArray.get(), nRow1, nLastRow);
 
             QuickSort(pArray.get(), nRow1, nLastRow);
-            SortReorder(pArray.get(), pProgress);
+            SortReorderByRow(pArray.get(), aSortParam.nCol1, aSortParam.nCol2, pProgress);
 
-            // #i59745# update position of caption objects of cell notes --> reported at (SortReorder) ScColumn::SwapCellNotes level
+            if (pUndo)
+            {
+                pUndo->maSortRange = ScRange(rSortParam.nCol1, nRow1, nTab, rSortParam.nCol2, nLastRow, nTab);
+                pUndo->maOrderIndices = pArray->GetOrderIndices();
+            }
         }
     }
     else
@@ -1077,17 +1259,48 @@ void ScTable::Sort(const ScSortParam& rSortParam, bool bKeepQuery, ScProgress* p
             if(pProgress)
                 pProgress->SetState( 0, nLastCol-nCol1 );
 
-            boost::scoped_ptr<ScSortInfoArray> pArray(CreateSortInfoArray(nCol1, nLastCol, bKeepQuery));
+            boost::scoped_ptr<ScSortInfoArray> pArray(CreateSortInfoArray(aSortParam, nCol1, nLastCol, bKeepQuery));
 
             QuickSort(pArray.get(), nCol1, nLastCol);
-            SortReorder(pArray.get(), pProgress);
+            SortReorderByColumn(pArray.get(), aSortParam.nRow1, aSortParam.nRow2, aSortParam.bIncludePattern, pProgress);
 
-            // #i59745# update position of caption objects of cell notes --> reported at (SortReorder) ScColumn::SwapCellNotes level
+            if (pUndo)
+            {
+                pUndo->maSortRange = ScRange(nCol1, aSortParam.nRow1, nTab, nLastCol, aSortParam.nRow2, nTab);
+                pUndo->maOrderIndices = pArray->GetOrderIndices();
+            }
         }
     }
     DestroySortCollator();
 }
 
+void ScTable::Reorder( const sc::ReorderParam& rParam, ScProgress* pProgress )
+{
+    if (rParam.maOrderIndices.empty())
+        return;
+
+    boost::scoped_ptr<ScSortInfoArray> pArray(CreateSortInfoArray(rParam));
+    if (!pArray)
+        return;
+
+    if (rParam.mbByRow)
+    {
+        // Re-play sorting from the known sort indices.
+        pArray->ReorderByRow(rParam.maOrderIndices);
+
+        SortReorderByRow(
+            pArray.get(), rParam.maSortRange.aStart.Col(), rParam.maSortRange.aEnd.Col(), pProgress);
+    }
+    else
+    {
+        // Ordering by column is much simpler.  Just set the order indices and we are done.
+        pArray->SetOrderIndices(rParam.maOrderIndices);
+        SortReorderByColumn(
+            pArray.get(), rParam.maSortRange.aStart.Row(), rParam.maSortRange.aEnd.Row(),
+            rParam.mbPattern, pProgress);
+    }
+}
+
 namespace {
 
 class SubTotalRowFinder
@@ -2078,7 +2291,7 @@ void ScTable::TopTenQuery( ScQueryParam& rParam )
                     bSortCollatorInitialized = true;
                     InitSortCollator( aLocalSortParam );
                 }
-                boost::scoped_ptr<ScSortInfoArray> pArray(CreateSortInfoArray(nRow1, rParam.nRow2, bGlobalKeepQuery));
+                boost::scoped_ptr<ScSortInfoArray> pArray(CreateSortInfoArray(aSortParam, nRow1, rParam.nRow2, bGlobalKeepQuery));
                 DecoladeRow( pArray.get(), nRow1, rParam.nRow2 );
                 QuickSort( pArray.get(), nRow1, rParam.nRow2 );
                 ScSortInfo** ppInfo = pArray->GetFirstArray();
diff --git a/sc/source/core/data/table7.cxx b/sc/source/core/data/table7.cxx
index 2e6aad1..f3528dd 100644
--- a/sc/source/core/data/table7.cxx
+++ b/sc/source/core/data/table7.cxx
@@ -13,6 +13,7 @@
 #include <clipparam.hxx>
 #include <bcaslot.hxx>
 #include <segmenttree.hxx>
+#include <sharedformula.hxx>
 
 void ScTable::DeleteBeforeCopyFromClip( sc::CopyFromClipContext& rCxt, const ScTable& rClipTab )
 {
@@ -78,4 +79,20 @@ bool ScTable::HasUniformRowHeight( SCROW nRow1, SCROW nRow2 ) const
     return nRow2 <= aData.mnRow2;
 }
 
+void ScTable::UnshareFormulaCells( SCCOL nCol, std::vector<SCROW>& rRows )
+{
+    if (!ValidCol(nCol))
+        return;
+
+    sc::SharedFormulaUtil::unshareFormulaCells(aCol[nCol].maCells, rRows);
+}
+
+void ScTable::RegroupFormulaCells( SCCOL nCol )
+{
+    if (!ValidCol(nCol))
+        return;
+
+    aCol[nCol].RegroupFormulaCells();
+}
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/core/tool/listenerquery.cxx b/sc/source/core/tool/listenerquery.cxx
new file mode 100644
index 0000000..bf9d38f
--- /dev/null
+++ b/sc/source/core/tool/listenerquery.cxx
@@ -0,0 +1,72 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <listenerquery.hxx>
+#include <listenerqueryids.hxx>
+#include <address.hxx>
+
+namespace sc {
+
+RefQueryFormulaGroup::RefQueryFormulaGroup() :
+    SvtListener::QueryBase(SC_LISTENER_QUERY_FORMULA_GROUP_POS),
+    maSkipRange(ScAddress::INITIALIZE_INVALID) {}
+
+RefQueryFormulaGroup::~RefQueryFormulaGroup() {}
+
+void RefQueryFormulaGroup::setSkipRange( const ScRange& rRange )
+{
+    maSkipRange = rRange;
+}
+
+void RefQueryFormulaGroup::add( const ScAddress& rPos )
+{
+    if (!rPos.IsValid())
+        return;
+
+    if (maSkipRange.IsValid() && maSkipRange.In(rPos))
+        // This is within the skip range.  Skip it.
+        return;
+
+    TabsType::iterator itTab = maTabs.find(rPos.Tab());
+    if (itTab == maTabs.end())
+    {
+        std::pair<TabsType::iterator,bool> r =
+            maTabs.insert(TabsType::value_type(rPos.Tab(), ColsType()));
+        if (!r.second)
+            // Insertion failed.
+            return;
+
+        itTab = r.first;
+    }
+
+    ColsType& rCols = itTab->second;
+    ColsType::iterator itCol = rCols.find(rPos.Col());
+    if (itCol == rCols.end())
+    {
+        std::pair<ColsType::iterator,bool> r =
+            rCols.insert(ColsType::value_type(rPos.Col(), ColType()));
+        if (!r.second)
+            // Insertion failed.
+            return;
+
+        itCol = r.first;
+    }
+
+    ColType& rCol = itCol->second;
+    rCol.push_back(rPos.Row());
+}
+
+const RefQueryFormulaGroup::TabsType& RefQueryFormulaGroup::getAllPositions() const
+{
+    return maTabs;
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/core/tool/refhint.cxx b/sc/source/core/tool/refhint.cxx
index 0e70b4f..29a9166 100644
--- a/sc/source/core/tool/refhint.cxx
+++ b/sc/source/core/tool/refhint.cxx
@@ -31,12 +31,12 @@ const ScAddress& RefMovedHint::getDelta() const
     return maMoveDelta;
 }
 
-RefColReorderHint::RefColReorderHint( const sc::ColReorderMapType& rColMap, SCTAB nTab, SCROW nRow1, SCROW nRow2 ) :
+RefColReorderHint::RefColReorderHint( const sc::ColRowReorderMapType& rColMap, SCTAB nTab, SCROW nRow1, SCROW nRow2 ) :
     RefHint(ColumnReordered), mrColMap(rColMap), mnTab(nTab), mnRow1(nRow1), mnRow2(nRow2) {}
 
 RefColReorderHint::~RefColReorderHint() {}
 
-const sc::ColReorderMapType& RefColReorderHint::getColMap() const
+const sc::ColRowReorderMapType& RefColReorderHint::getColMap() const
 {
     return mrColMap;
 }
@@ -56,6 +56,31 @@ SCROW RefColReorderHint::getEndRow() const
     return mnRow2;
 }
 
+RefRowReorderHint::RefRowReorderHint( const sc::ColRowReorderMapType& rRowMap, SCTAB nTab, SCCOL nCol1, SCCOL nCol2 ) :
+    RefHint(RowReordered), mrRowMap(rRowMap), mnTab(nTab), mnCol1(nCol1), mnCol2(nCol2) {}
+
+RefRowReorderHint::~RefRowReorderHint() {}
+
+const sc::ColRowReorderMapType& RefRowReorderHint::getRowMap() const
+{
+    return mrRowMap;
+}
+
+SCTAB RefRowReorderHint::getTab() const
+{
+    return mnTab;
+}
+
+SCCOL RefRowReorderHint::getStartColumn() const
+{
+    return mnCol1;
+}
+
+SCCOL RefRowReorderHint::getEndColumn() const
+{
+    return mnCol2;
+}
+
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/core/tool/sharedformula.cxx b/sc/source/core/tool/sharedformula.cxx
index ed35690..6f66365 100644
--- a/sc/source/core/tool/sharedformula.cxx
+++ b/sc/source/core/tool/sharedformula.cxx
@@ -297,6 +297,35 @@ void SharedFormulaUtil::unshareFormulaCell(const CellStoreType::position_type& a
     rCell.SetCellGroup(xNone);
 }
 
+void SharedFormulaUtil::unshareFormulaCells(CellStoreType& rCells, std::vector<SCROW>& rRows)
+{
+    if (rRows.empty())
+        return;
+
+    // Sort and remove duplicates.
+    std::sort(rRows.begin(), rRows.end());
+    rRows.erase(std::unique(rRows.begin(), rRows.end()), rRows.end());
+
+    // Add next cell positions to the list (to ensure that each position becomes a single cell).
+    std::vector<SCROW> aRows2;
+    std::vector<SCROW>::const_iterator it = rRows.begin(), itEnd = rRows.end();
+    for (; it != itEnd; ++it)
+    {
+        if (*it > MAXROW)
+            break;
+
+        aRows2.push_back(*it);
+
+        if (*it < MAXROW)
+            aRows2.push_back(*it+1);
+    }
+
+    // Remove duplicates again (the vector should still be sorted).
+    aRows2.erase(std::unique(aRows2.begin(), aRows2.end()), aRows2.end());
+
+    splitFormulaCellGroups(rCells, aRows2);
+}
+
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/core/tool/token.cxx b/sc/source/core/tool/token.cxx
index ab47bee..c289960 100644
--- a/sc/source/core/tool/token.cxx
+++ b/sc/source/core/tool/token.cxx
@@ -2914,8 +2914,8 @@ void ScTokenArray::MoveReference(
     }
 }
 
-void ScTokenArray::MoveReference(
-    const ScAddress& rPos, SCTAB nTab, SCROW nRow1, SCROW nRow2, const sc::ColReorderMapType& rColMap )
+void ScTokenArray::MoveReferenceColReorder(
+    const ScAddress& rPos, SCTAB nTab, SCROW nRow1, SCROW nRow2, const sc::ColRowReorderMapType& rColMap )
 {
     FormulaToken** p = pCode;
     FormulaToken** pEnd = p + static_cast<size_t>(nLen);
@@ -2932,7 +2932,7 @@ void ScTokenArray::MoveReference(
                 if (aAbs.Tab() == nTab && nRow1 <= aAbs.Row() && aAbs.Row() <= nRow2)
                 {
                     // Inside reordered row range.
-                    sc::ColReorderMapType::const_iterator it = rColMap.find(aAbs.Col());
+                    sc::ColRowReorderMapType::const_iterator it = rColMap.find(aAbs.Col());
                     if (it != rColMap.end())
                     {
                         // This column is reordered.
@@ -2960,7 +2960,7 @@ void ScTokenArray::MoveReference(
                 if (aAbs.aStart.Tab() == nTab && nRow1 <= aAbs.aStart.Row() && aAbs.aEnd.Row() <= nRow2)
                 {
                     // Inside reordered row range.
-                    sc::ColReorderMapType::const_iterator it = rColMap.find(aAbs.aStart.Col());
+                    sc::ColRowReorderMapType::const_iterator it = rColMap.find(aAbs.aStart.Col());
                     if (it != rColMap.end())
                     {
                         // This column is reordered.
@@ -2978,6 +2978,69 @@ void ScTokenArray::MoveReference(
     }
 }
 
+void ScTokenArray::MoveReferenceRowReorder( const ScAddress& rPos, SCTAB nTab, SCCOL nCol1, SCCOL nCol2, const sc::ColRowReorderMapType& rRowMap )
+{
+    FormulaToken** p = pCode;
+    FormulaToken** pEnd = p + static_cast<size_t>(nLen);
+    for (; p != pEnd; ++p)
+    {
+        switch ((*p)->GetType())
+        {
+            case svSingleRef:
+            {
+                ScToken* pToken = static_cast<ScToken*>(*p);
+                ScSingleRefData& rRef = pToken->GetSingleRef();
+                ScAddress aAbs = rRef.toAbs(rPos);
+
+                if (aAbs.Tab() == nTab && nCol1 <= aAbs.Col() && aAbs.Col() <= nCol2)
+                {
+                    // Inside reordered column range.
+                    sc::ColRowReorderMapType::const_iterator it = rRowMap.find(aAbs.Row());
+                    if (it != rRowMap.end())
+                    {
+                        // This column is reordered.
+                        SCROW nNewRow = it->second;
+                        aAbs.SetRow(nNewRow);
+                        rRef.SetAddress(aAbs, rPos);
+                    }
+                }
+            }
+            break;
+            case svDoubleRef:
+            {
+                ScToken* pToken = static_cast<ScToken*>(*p);
+                ScComplexRefData& rRef = pToken->GetDoubleRef();
+                ScRange aAbs = rRef.toAbs(rPos);
+
+                if (aAbs.aStart.Tab() != aAbs.aEnd.Tab())
+                    // Must be a single-sheet reference.
+                    break;
+
+                if (aAbs.aStart.Row() != aAbs.aEnd.Row())
+                    // Whole range must fit in a single row.
+                    break;
+
+                if (aAbs.aStart.Tab() == nTab && nCol1 <= aAbs.aStart.Col() && aAbs.aEnd.Col() <= nCol2)
+                {
+                    // Inside reordered column range.
+                    sc::ColRowReorderMapType::const_iterator it = rRowMap.find(aAbs.aStart.Row());
+                    if (it != rRowMap.end())
+                    {
+                        // This row is reordered.
+                        SCCOL nNewRow = it->second;
+                        aAbs.aStart.SetRow(nNewRow);
+                        aAbs.aEnd.SetRow(nNewRow);
+                        rRef.SetRange(aAbs, rPos);
+                    }
+                }
+            }
+            break;
+            default:
+                ;
+        }
+    }
+}
+
 namespace {
 
 bool adjustSingleRefInName(
diff --git a/sc/source/filter/xml/XMLExportDatabaseRanges.cxx b/sc/source/filter/xml/XMLExportDatabaseRanges.cxx
index ea2b31c..8e954ad 100644
--- a/sc/source/filter/xml/XMLExportDatabaseRanges.cxx
+++ b/sc/source/filter/xml/XMLExportDatabaseRanges.cxx
@@ -35,6 +35,7 @@
 #include "subtotalparam.hxx"
 #include "queryparam.hxx"
 #include "queryentry.hxx"
+#include <sortparam.hxx>
 
 #include "svx/dataaccessdescriptor.hxx"
 
diff --git a/sc/source/filter/xml/xmldrani.cxx b/sc/source/filter/xml/xmldrani.cxx
index 9478b0c..c6a8727 100644
--- a/sc/source/filter/xml/xmldrani.cxx
+++ b/sc/source/filter/xml/xmldrani.cxx
@@ -34,6 +34,7 @@
 #include "rangeutl.hxx"
 #include "queryentry.hxx"
 #include "dputil.hxx"
+#include <sortparam.hxx>
 
 #include <xmloff/xmltkmap.hxx>
 #include <xmloff/nmspmap.hxx>
diff --git a/sc/source/ui/docshell/dbdocfun.cxx b/sc/source/ui/docshell/dbdocfun.cxx
index d9d5550..900bf3e 100644
--- a/sc/source/ui/docshell/dbdocfun.cxx
+++ b/sc/source/ui/docshell/dbdocfun.cxx
@@ -47,6 +47,7 @@
 #include "queryentry.hxx"
 #include "markdata.hxx"
 #include "progress.hxx"
+#include <undosort.hxx>
 
 #include <set>
 #include <memory>
@@ -433,8 +434,6 @@ sal_Bool ScDBDocFunc::Sort( SCTAB nTab, const ScSortParam& rSortParam,
     ScDocument* pDoc = rDocShell.GetDocument();
     if (bRecord && !pDoc->IsUndoEnabled())
         bRecord = false;
-    SCTAB nSrcTab = nTab;
-    ScDrawLayer* pDrawLayer = pDoc->GetDrawLayer();
 
     ScDBData* pDBData = pDoc->GetDBAtArea( nTab, rSortParam.nCol1, rSortParam.nRow1,
                                                     rSortParam.nCol2, rSortParam.nRow2 );
@@ -444,28 +443,25 @@ sal_Bool ScDBDocFunc::Sort( SCTAB nTab, const ScSortParam& rSortParam,
         return false;
     }
 
-    ScDBData* pDestData = NULL;
-    ScRange aOldDest;
-    sal_Bool bCopy = !rSortParam.bInplace;
+    bool bCopy = !rSortParam.bInplace;
     if ( bCopy && rSortParam.nDestCol == rSortParam.nCol1 &&
                   rSortParam.nDestRow == rSortParam.nRow1 && rSortParam.nDestTab == nTab )
         bCopy = false;
+
     ScSortParam aLocalParam( rSortParam );
     if ( bCopy )
     {
-        aLocalParam.MoveToDest();
-        if ( !ValidColRow( aLocalParam.nCol2, aLocalParam.nRow2 ) )
-        {
-            if (!bApi)
-                rDocShell.ErrorMessage(STR_PASTE_FULL);
+        // Copy the data range to the destination then move the sort range to it.
+        ScRange aSrcRange(rSortParam.nCol1, rSortParam.nRow1, nTab, rSortParam.nCol2, rSortParam.nRow2, nTab);
+        ScAddress aDestPos(rSortParam.nDestCol,rSortParam.nDestRow,rSortParam.nDestTab);
+
+        ScDocFunc& rDocFunc = rDocShell.GetDocFunc();
+        bool bRet = rDocFunc.MoveBlock(aSrcRange, aDestPos, false, bRecord, bPaint, bApi);
+
+        if (!bRet)
             return false;
-        }
 
-        nTab = rSortParam.nDestTab;
-        pDestData = pDoc->GetDBAtCursor( rSortParam.nDestCol, rSortParam.nDestRow,
-                                            rSortParam.nDestTab, sal_True );
-        if (pDestData)
-            pDestData->GetArea(aOldDest);
+        aLocalParam.MoveToDest();
     }
 
     ScEditableTester aTester( pDoc, nTab, aLocalParam.nCol1,aLocalParam.nRow1,
@@ -515,133 +511,23 @@ sal_Bool ScDBDocFunc::Sort( SCTAB nTab, const ScSortParam& rSortParam,
     if ( aQueryParam.GetEntry(0).bDoQuery )
         bRepeatQuery = sal_True;
 
-    if (bRepeatQuery && bCopy)
-    {
-        if ( aQueryParam.bInplace ||
-                aQueryParam.nDestCol != rSortParam.nDestCol ||
-                aQueryParam.nDestRow != rSortParam.nDestRow ||
-                aQueryParam.nDestTab != rSortParam.nDestTab )       // Query auf selben Zielbereich?
-            bRepeatQuery = false;
-    }
-
-    ScUndoSort* pUndoAction = 0;
-    if ( bRecord )
-    {
-        //  Referenzen ausserhalb des Bereichs werden nicht veraendert !
-
-        ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
-        //  Zeilenhoehen immer (wegen automatischer Anpassung)
-        //! auf ScBlockUndo umstellen
-        pUndoDoc->InitUndo( pDoc, nTab, nTab, false, sal_True );
-
-        /*  #i59745# Do not copy note captions to undo document. All existing
-            caption objects will be repositioned while sorting which is tracked
-            in drawing undo. When undo is executed, the old positions will be
-            restored, and the cells with the old notes (which still refer to the
-            existing captions) will be copied back into the source document. */
-        pDoc->CopyToDocument( aLocalParam.nCol1, aLocalParam.nRow1, nTab,
-                                aLocalParam.nCol2, aLocalParam.nRow2, nTab,
-                                IDF_ALL|IDF_NOCAPTIONS, false, pUndoDoc );
-
-        const ScRange* pR = 0;
-        if (pDestData)
-        {
-            /*  #i59745# Do not copy note captions from destination range to
-                undo document. All existing caption objects will be removed
-                which is tracked in drawing undo. When undo is executed, the
-                caption objects are reinserted with drawing undo, and the cells
-                with the old notes (which still refer to the existing captions)
-                will be copied back into the source document. */
-            pDoc->CopyToDocument( aOldDest, IDF_ALL|IDF_NOCAPTIONS, false, pUndoDoc );
-            pR = &aOldDest;
-        }
-
-        //  Zeilenhoehen immer (wegen automatischer Anpassung)
-        //! auf ScBlockUndo umstellen
-//        if (bRepeatQuery)
-            pDoc->CopyToDocument( 0, aLocalParam.nRow1, nTab, MAXCOL, aLocalParam.nRow2, nTab,
-                                    IDF_NONE, false, pUndoDoc );
-
-        ScDBCollection* pUndoDB = NULL;
-        ScDBCollection* pDocDB = pDoc->GetDBCollection();
-        if (!pDocDB->empty())
-            pUndoDB = new ScDBCollection( *pDocDB );
-
-        pUndoAction = new ScUndoSort( &rDocShell, nTab, rSortParam, pUndoDoc, pUndoDB, pR );
-        rDocShell.GetUndoManager()->AddUndoAction( pUndoAction );
-
-        // #i59745# collect all drawing undo actions affecting cell note captions
-        if( pDrawLayer )
-            pDrawLayer->BeginCalcUndo(false);
-    }
-
-    if ( bCopy )
-    {
-        if (pDestData)
-            pDoc->DeleteAreaTab(aOldDest, IDF_CONTENTS);            // Zielbereich vorher loeschen
-
-        ScRange aSource( rSortParam.nCol1,rSortParam.nRow1,nSrcTab,
-                            rSortParam.nCol2,rSortParam.nRow2,nSrcTab );
-        ScAddress aDest( rSortParam.nDestCol, rSortParam.nDestRow, rSortParam.nDestTab );
-
-        rDocShell.GetDocFunc().MoveBlock( aSource, aDest, false, false, false, sal_True );
-    }
+    sc::ReorderParam aUndoParam;
 
     // don't call ScDocument::Sort with an empty SortParam (may be empty here if bCopy is set)
     if (aLocalParam.GetSortKeyCount() && aLocalParam.maKeyState[0].bDoSort)
     {
         ScProgress aProgress(&rDocShell, ScGlobal::GetRscString(STR_PROGRESS_SORTING), 0);
-        pDoc->Sort( nTab, aLocalParam, bRepeatQuery, &aProgress );
+        pDoc->Sort(nTab, aLocalParam, bRepeatQuery, &aProgress, &aUndoParam);
     }
 
-    sal_Bool bSave = sal_True;
-    if (bCopy)
-    {
-        ScSortParam aOldSortParam;
-        pDBData->GetSortParam( aOldSortParam );
-        if (aOldSortParam.GetSortKeyCount() &&
-            aOldSortParam.maKeyState[0].bDoSort && aOldSortParam.bInplace)
-        {
-            bSave = false;
-            aOldSortParam.nDestCol = rSortParam.nDestCol;
-            aOldSortParam.nDestRow = rSortParam.nDestRow;
-            aOldSortParam.nDestTab = rSortParam.nDestTab;
-            pDBData->SetSortParam( aOldSortParam );                 // dann nur DestPos merken
-        }
-    }
-    if (bSave)                                              // Parameter merken
+    if (bRecord)
     {
-        pDBData->SetSortParam( rSortParam );
-        pDBData->SetHeader( rSortParam.bHasHeader );        //! ???
-        pDBData->SetByRow( rSortParam.bByRow );             //! ???
+        // Set up an undo object.
+        sc::UndoSort* pUndoAction = new sc::UndoSort(&rDocShell, aUndoParam);
+        rDocShell.GetUndoManager()->AddUndoAction(pUndoAction);
     }
 
-    if (bCopy)                                          // neuen DB-Bereich merken
-    {
-        //  Tabelle umschalten von aussen (View)
-        //! SetCursor ??!?!
-
-        ScRange aDestPos( aLocalParam.nCol1, aLocalParam.nRow1, nTab,
-                            aLocalParam.nCol2, aLocalParam.nRow2, nTab );
-        ScDBData* pNewData;
-        if (pDestData)
-            pNewData = pDestData;               // Bereich vorhanden -> anpassen
-        else                                    // Bereich ab Cursor/Markierung wird angelegt
-            pNewData = rDocShell.GetDBData(aDestPos, SC_DB_MAKE, SC_DBSEL_FORCE_MARK );
-        if (pNewData)
-        {
-            pNewData->SetArea( nTab,
-                                aLocalParam.nCol1,aLocalParam.nRow1,
-                                aLocalParam.nCol2,aLocalParam.nRow2 );
-            pNewData->SetSortParam( aLocalParam );
-            pNewData->SetHeader( aLocalParam.bHasHeader );      //! ???
-            pNewData->SetByRow( aLocalParam.bByRow );
-        }
-        else
-        {
-            OSL_FAIL("Zielbereich nicht da");
-        }
-    }
+    pDBData->SetSortParam(rSortParam);
 
     ScRange aDirtyRange(
         aLocalParam.nCol1, nStartRow, nTab,
@@ -661,23 +547,12 @@ sal_Bool ScDBDocFunc::Sort( SCTAB nTab, const ScSortParam& rSortParam,
             nStartX = 0;
             nEndX = MAXCOL;
         }
-        if (pDestData)
-        {
-            if ( nEndX < aOldDest.aEnd.Col() )
-                nEndX = aOldDest.aEnd.Col();
-            if ( nEndY < aOldDest.aEnd.Row() )
-                nEndY = aOldDest.aEnd.Row();
-        }
         rDocShell.PostPaint(ScRange(nStartX, nStartY, nTab, nEndX, nEndY, nTab), nPaint);
     }
 
     if (!bUniformRowHeight)
         rDocShell.AdjustRowHeight(nStartRow, aLocalParam.nRow2, nTab);
 
-    // #i59745# set collected drawing undo actions at sorting undo action
-    if( pUndoAction && pDrawLayer )
-        pUndoAction->SetDrawUndoAction( pDrawLayer->GetCalcUndo() );
-
     aModificator.SetDocumentModified();
 
     return sal_True;
diff --git a/sc/source/ui/undo/undobase.cxx b/sc/source/ui/undo/undobase.cxx
index 609b6fe..6342910 100644
--- a/sc/source/ui/undo/undobase.cxx
+++ b/sc/source/ui/undo/undobase.cxx
@@ -31,6 +31,7 @@
 #include "subtotalparam.hxx"
 #include "globstr.hrc"
 #include <column.hxx>
+#include <sortparam.hxx>
 
 TYPEINIT1(ScSimpleUndo,     SfxUndoAction);
 TYPEINIT1(ScBlockUndo,      ScSimpleUndo);
diff --git a/sc/source/ui/undo/undosort.cxx b/sc/source/ui/undo/undosort.cxx
new file mode 100644
index 0000000..4ff0960
--- /dev/null
+++ b/sc/source/ui/undo/undosort.cxx
@@ -0,0 +1,55 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <undosort.hxx>
+#include <globstr.hrc>
+#include <global.hxx>
+#include <undoutil.hxx>
+
+namespace sc {
+
+UndoSort::UndoSort( ScDocShell* pDocSh, const ReorderParam& rParam ) :
+    ScSimpleUndo(pDocSh), maParam(rParam) {}
+
+OUString UndoSort::GetComment() const
+{
+    return ScGlobal::GetRscString(STR_UNDO_SORT);
+}
+
+void UndoSort::Undo()
+{
+    BeginUndo();
+    Execute(true);
+    EndUndo();
+}
+
+void UndoSort::Redo()
+{
+    BeginRedo();
+    Execute(false);
+    EndRedo();
+}
+
+void UndoSort::Execute( bool bUndo )
+{
+    ScDocument& rDoc = *pDocShell->GetDocument();
+    sc::ReorderParam aParam = maParam;
+    if (bUndo)
+        aParam.reverse();
+    rDoc.Reorder(aParam, NULL);
+
+    ScUndoUtil::MarkSimpleBlock(pDocShell, maParam.maSortRange);
+
+    pDocShell->PostPaint(maParam.maSortRange, PAINT_GRID);
+    pDocShell->PostDataChanged();
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/unoobj/cellsuno.cxx b/sc/source/ui/unoobj/cellsuno.cxx
index a9cf2eb..c1963e0 100644
--- a/sc/source/ui/unoobj/cellsuno.cxx
+++ b/sc/source/ui/unoobj/cellsuno.cxx
@@ -124,6 +124,7 @@
 #include "tokenarray.hxx"
 #include "stylehelper.hxx"
 #include "dputil.hxx"
+#include <sortparam.hxx>
 
 #include <list>
 #include <boost/scoped_ptr.hpp>
diff --git a/sc/source/ui/unoobj/datauno.cxx b/sc/source/ui/unoobj/datauno.cxx
index 8886776..26838e1 100644
--- a/sc/source/ui/unoobj/datauno.cxx
+++ b/sc/source/ui/unoobj/datauno.cxx
@@ -51,6 +51,7 @@
 #include "dpshttab.hxx"
 #include "queryentry.hxx"
 #include "dputil.hxx"
+#include <sortparam.hxx>
 
 #include <comphelper/extract.hxx>
 #include <comphelper/servicehelper.hxx>
diff --git a/svl/source/notify/listener.cxx b/svl/source/notify/listener.cxx
index 66207bf..f905090 100644
--- a/svl/source/notify/listener.cxx
+++ b/svl/source/notify/listener.cxx
@@ -21,6 +21,14 @@
 #include <svl/broadcast.hxx>
 #include <tools/debug.hxx>
 
+SvtListener::QueryBase::QueryBase( sal_uInt16 nId ) : mnId(nId) {}
+SvtListener::QueryBase::~QueryBase() {}
+
+sal_uInt16 SvtListener::QueryBase::getId() const
+{
+    return mnId;
+}
+
 SvtListener::SvtListener() {}
 
 SvtListener::SvtListener( const SvtListener &r ) :
@@ -75,12 +83,26 @@ bool SvtListener::IsListening( SvtBroadcaster& rBroadcaster ) const
     return maBroadcasters.count(&rBroadcaster) > 0;
 }
 
+void SvtListener::CopyAllBroadcasters( const SvtListener& r )
+{
+    BroadcastersType aCopy(r.maBroadcasters);
+    maBroadcasters.swap(aCopy);
+    BroadcastersType::iterator it = maBroadcasters.begin(), itEnd = maBroadcasters.end();
+    for (; it != itEnd; ++it)
+    {
+        SvtBroadcaster* p = *it;
+        p->Add(this);
+    }
+}
+
 bool SvtListener::HasBroadcaster() const
 {
     return !maBroadcasters.empty();
 }
 
-void SvtListener::Notify( const SfxHint& ) {}
+void SvtListener::Notify( const SfxHint& /*rHint*/ ) {}
+
+void SvtListener::Query( QueryBase& /*rQuery*/ ) const {}
 
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
commit 9ba9d810d9e17a7e3a3e0885235924f4c480c3b0
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Fri Jul 11 10:50:29 2014 -0400

    bnc#883684: Better fix for this.
    
    Instead of making all chart objects exempt from unloading, check each OLE
    object on whether or not it already has its persistent storage created.
    If not, don't unload it else it would have nothing to load back from once
    unloaded.
    
    (cherry picked from commit a0bd5587a5ac62974bdb10731d3fd21584521a72)
    
    Conflicts:
    	svx/source/svdraw/svdetc.cxx
    	embeddedobj/source/commonembedding/miscobj.cxx
    	embeddedobj/source/commonembedding/persistence.cxx
    	include/svx/svdoole2.hxx
    	svx/source/svdraw/svdoole2.cxx
    
    Change-Id: I2312e86c9376d3699ef4aa1e0cf2f4c04f706c1e

diff --git a/embeddedobj/source/commonembedding/miscobj.cxx b/embeddedobj/source/commonembedding/miscobj.cxx
index 70b8696..8ce2f84 100644
--- a/embeddedobj/source/commonembedding/miscobj.cxx
+++ b/embeddedobj/source/commonembedding/miscobj.cxx
@@ -363,6 +363,11 @@ uno::Any SAL_CALL OCommonEmbeddedObject::queryInterface( const uno::Type& rType
         void * p = static_cast< embed::XEmbeddedObject * >( this );
         return uno::Any( &p, rType );
     }
+    else if (rType == ::getCppuType( (uno::Reference<embed::XEmbedPersist2> const *)0 ))
+    {
+        void* p = static_cast<embed::XEmbedPersist2*>(this);
+        return uno::Any(&p, rType);
+    }
     else
         aReturn <<= ::cppu::queryInterface(
                     rType,
@@ -431,7 +436,8 @@ uno::Sequence< uno::Type > SAL_CALL OCommonEmbeddedObject::getTypes()
                                             ::getCppuType( (const uno::Reference< embed::XInplaceObject >*)NULL ),
                                             ::getCppuType( (const uno::Reference< embed::XCommonEmbedPersist >*)NULL ),
                                             ::getCppuType( (const uno::Reference< container::XChild >*)NULL ),
-                                            ::getCppuType( (const uno::Reference< embed::XEmbedPersist >*)NULL ) );
+                                            ::getCppuType( (const uno::Reference< embed::XEmbedPersist >*)NULL ),
+                                            ::getCppuType( (const uno::Reference< embed::XEmbedPersist2 >*)NULL ) );
 
                 pTypeCollection = &aTypeCollection ;
             }
diff --git a/embeddedobj/source/commonembedding/persistence.cxx b/embeddedobj/source/commonembedding/persistence.cxx
index 4891656..44b4e30 100644
--- a/embeddedobj/source/commonembedding/persistence.cxx
+++ b/embeddedobj/source/commonembedding/persistence.cxx
@@ -1799,7 +1799,15 @@ void SAL_CALL OCommonEmbeddedObject::reload(
     }
 }
 
-//------------------------------------------------------
+sal_Bool SAL_CALL OCommonEmbeddedObject::isStored() throw (css::uno::RuntimeException, std::exception)
+{
+    uno::Reference<container::XNameAccess> xNA(m_xObjectStorage, uno::UNO_QUERY);
+    if (!xNA.is())
+        return false;
+
+    return xNA->getElementNames().getLength() > 0;
+}
+
 void SAL_CALL OCommonEmbeddedObject::breakLink( const uno::Reference< embed::XStorage >& xStorage,
                                                 const OUString& sEntName )
         throw ( lang::IllegalArgumentException,
diff --git a/embeddedobj/source/inc/commonembobj.hxx b/embeddedobj/source/inc/commonembobj.hxx
index 83e4445..4c23325 100644
--- a/embeddedobj/source/inc/commonembobj.hxx
+++ b/embeddedobj/source/inc/commonembobj.hxx
@@ -27,7 +27,7 @@
 #include <com/sun/star/document/XStorageBasedDocument.hpp>
 #include <com/sun/star/embed/XEmbeddedObject.hpp>
 #include <com/sun/star/embed/XVisualObject.hpp>
-#include <com/sun/star/embed/XEmbedPersist.hpp>
+#include <com/sun/star/embed/XEmbedPersist2.hpp>
 #include <com/sun/star/embed/XLinkageSupport.hpp>
 #include <com/sun/star/embed/XClassifiedObject.hpp>
 #include <com/sun/star/embed/XComponentSupplier.hpp>
@@ -72,7 +72,7 @@ namespace comphelper {
 class Interceptor;
 
 class OCommonEmbeddedObject : public ::com::sun::star::embed::XEmbeddedObject
-                            , public ::com::sun::star::embed::XEmbedPersist
+                            , public ::com::sun::star::embed::XEmbedPersist2
                             , public ::com::sun::star::embed::XLinkageSupport
                             , public ::com::sun::star::embed::XInplaceObject
                             , public ::com::sun::star::container::XChild
@@ -431,6 +431,10 @@ public:
                 ::com::sun::star::uno::Exception,
                 ::com::sun::star::uno::RuntimeException );
 
+// XEmbedPersist2
+
+    virtual sal_Bool SAL_CALL isStored()
+        throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
 
 // XInplaceObject
 
diff --git a/include/svx/svdoole2.hxx b/include/svx/svdoole2.hxx
index 149dc61..c2cad4b 100644
--- a/include/svx/svdoole2.hxx
+++ b/include/svx/svdoole2.hxx
@@ -170,13 +170,6 @@ public:
     sal_Bool IsChart() const;
     sal_Bool IsCalc() const;
 
-    /**
-     * Unloadable OLE objects are subject to automatic unloading per memory
-     * setting.  The "Number of objects" setting in the Memory option controls
-     * how many OLE objects can be loaded at any given moment.
-     */
-    bool IsUnloadable() const;
-
     sal_Bool UpdateLinkURL_Impl();
     void BreakFileLink_Impl();
     void DisconnectFileLink_Impl();
diff --git a/offapi/UnoApi_offapi.mk b/offapi/UnoApi_offapi.mk
index 3c1d92e..22d84d2 100755
--- a/offapi/UnoApi_offapi.mk
+++ b/offapi/UnoApi_offapi.mk
@@ -2411,6 +2411,7 @@ $(eval $(call gb_UnoApi_add_idlfiles,offapi,com/sun/star/embed,\
     XEmbeddedObjectCreator \
 	XEmbedObjectFactory \
 	XEmbedPersist \
+	XEmbedPersist2 \
 	XEmbeddedClient \
 	XEmbeddedObject \
 	XEncryptionProtectedSource \
diff --git a/offapi/com/sun/star/embed/XEmbedPersist2.idl b/offapi/com/sun/star/embed/XEmbedPersist2.idl
new file mode 100644
index 0000000..205b902
--- /dev/null
+++ b/offapi/com/sun/star/embed/XEmbedPersist2.idl
@@ -0,0 +1,30 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef __com_sun_star_XEmbedPersist2_idl__
+#define __com_sun_star_XEmbedPersist2_idl__
+
+#include <com/sun/star/embed/XEmbedPersist.idl>
+
+module com {  module sun {  module star { module embed {
+
+interface XEmbedPersist2 : XEmbedPersist
+{
+    /**
+     * Checks whether or not the object has created its persistent
+     * representation counterpart of its in-memory model.
+     */
+    boolean isStored();
+};
+
+}; }; }; };
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svx/source/svdraw/svdetc.cxx b/svx/source/svdraw/svdetc.cxx
index afcc792..4caca94 100644
--- a/svx/source/svdraw/svdetc.cxx
+++ b/svx/source/svdraw/svdetc.cxx
@@ -165,10 +165,6 @@ void OLEObjCache::UnloadOnDemand()
 
 void OLEObjCache::InsertObj(SdrOle2Obj* pObj)
 {
-    if (!pObj->IsUnloadable())
-        // This OLE object is exempt from automatic unloading.
-        return;
-
     if ( !empty() )
     {
         SdrOle2Obj* pExistingObj = front();
diff --git a/svx/source/svdraw/svdoole2.cxx b/svx/source/svdraw/svdoole2.cxx
index f68f5d7..f1f27a83 100644
--- a/svx/source/svdraw/svdoole2.cxx
+++ b/svx/source/svdraw/svdoole2.cxx
@@ -25,6 +25,7 @@
 #include <com/sun/star/embed/ElementModes.hpp>
 #include <com/sun/star/embed/EmbedMisc.hpp>
 #include <com/sun/star/embed/Aspects.hpp>
+#include <com/sun/star/embed/XEmbedPersist2.hpp>
 #include <com/sun/star/embed/XInplaceClient.hpp>
 #include <com/sun/star/embed/XInplaceObject.hpp>
 #include <com/sun/star/embed/XLinkageSupport.hpp>
@@ -1926,6 +1927,14 @@ void SdrOle2Obj::NbcMove(const Size& rSize)
 
 sal_Bool SdrOle2Obj::CanUnloadRunningObj( const uno::Reference< embed::XEmbeddedObject >& xObj, sal_Int64 nAspect )
 {
+    uno::Reference<embed::XEmbedPersist2> xPersist(xObj, uno::UNO_QUERY);
+    if (xPersist.is())
+    {
+        if (!xPersist->isStored())
+            // It doesn't have persistent storage.  We can't unload this.
+            return false;
+    }
+
     sal_Bool bResult = sal_False;
 
     sal_Int32 nState = xObj->getCurrentState();
@@ -2159,13 +2168,6 @@ sal_Bool SdrOle2Obj::IsCalc() const
     return sal_False;
 }
 
-bool SdrOle2Obj::IsUnloadable() const
-{
-    // Right now, chart OLE objects are the only ones exempt from automatic
-    // unloading.
-    return !IsChart();
-}
-
 uno::Reference< frame::XModel > SdrOle2Obj::GetParentXModel() const
 {
     uno::Reference< frame::XModel > xDoc;
commit b7bd1b66287d9d337234ac1b9b50a1fafba7dd1e
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Mon Jul 14 15:24:19 2014 -0400

    Preserve the "end of list" flag for xls round-tripping.
    
    This "end of list" flag determines whether the row insertion was an
    automatic insertion at the bottom.  Calc doesn't use this at the moment
    but Excel uses it to differentiate a normal row insertion from an
    automatic one.
    
    (cherry picked from commit adf0d7b1fb8eed88f4fcd6d31662ae6f59d00812)
    Signed-off-by: Andras Timar <andras.timar at collabora.com>
    
    Conflicts:
    	sc/inc/chgtrack.hxx
    	sc/source/filter/xcl97/XclExpChangeTrack.cxx
    
    Change-Id: I6b28669d816c54d1dc1e4c106918ba688415788d
    (cherry picked from commit 8fd0951429bfa00a054ebbc195a480f89af9f912)
    Signed-off-by: Andras Timar <andras.timar at collabora.com>

diff --git a/sc/inc/chgtrack.hxx b/sc/inc/chgtrack.hxx
index 1f6ddcd..2e57437 100644
--- a/sc/inc/chgtrack.hxx
+++ b/sc/inc/chgtrack.hxx
@@ -402,7 +402,9 @@ class ScChangeActionIns : public ScChangeAction
 {
     friend class ScChangeTrack;
 
-                                ScChangeActionIns( const ScRange& rRange );
+    bool mbEndOfList; /// whether or not a row was auto-inserted at the bottom.
+
+    ScChangeActionIns( const ScRange& rRange, bool bEndOfList = false );
     virtual                     ~ScChangeActionIns();
 
     virtual void                AddContent( ScChangeActionContent* ) {}
@@ -413,17 +415,21 @@ class ScChangeActionIns : public ScChangeAction
     virtual const ScChangeTrack*    GetChangeTrack() const { return 0; }
 
 public:
-    ScChangeActionIns(const sal_uLong nActionNumber,
-            const ScChangeActionState eState,
-            const sal_uLong nRejectingNumber,
-            const ScBigRange& aBigRange,
-            const OUString& aUser,
-            const DateTime& aDateTime,
-            const OUString &sComment,
-            const ScChangeActionType eType); // only to use in the XML import
+    ScChangeActionIns(
+        const sal_uLong nActionNumber,
+        const ScChangeActionState eState,
+        const sal_uLong nRejectingNumber,
+        const ScBigRange& aBigRange,
+        const OUString& aUser,
+        const DateTime& aDateTime,
+        const OUString &sComment,
+        const ScChangeActionType eType,
+        bool bEndOfList = false );
 
     virtual void GetDescription(
         OUString& rStr, ScDocument* pDoc, bool bSplitRange = false, bool bWarning = true) const;
+
+    SC_DLLPUBLIC bool IsEndOfList() const;
 };
 
 //  ScChangeActionDel
@@ -1123,7 +1129,7 @@ public:
     // Only use the following two if there is no different solution! (Assign
     // string for NewValue or creation of a formula respectively)
 
-    SC_DLLPUBLIC void AppendInsert( const ScRange& );
+    SC_DLLPUBLIC void AppendInsert( const ScRange& rRange, bool bEndOfList = false );
 
                                 // pRefDoc may be NULL => no lookup of contents
                                 // => no generation of deleted contents
diff --git a/sc/source/core/tool/chgtrack.cxx b/sc/source/core/tool/chgtrack.cxx
index 1ebb30d..ff261ca 100644
--- a/sc/source/core/tool/chgtrack.cxx
+++ b/sc/source/core/tool/chgtrack.cxx
@@ -660,8 +660,9 @@ void ScChangeAction::AddDependent( sal_uLong nActionNumber,
 }
 
 //  ScChangeActionIns
-ScChangeActionIns::ScChangeActionIns( const ScRange& rRange )
-        : ScChangeAction( SC_CAT_NONE, rRange )
+ScChangeActionIns::ScChangeActionIns( const ScRange& rRange, bool bEndOfList ) :
+    ScChangeAction(SC_CAT_NONE, rRange),
+    mbEndOfList(bEndOfList)
 {
     if ( rRange.aStart.Col() == 0 && rRange.aEnd.Col() == MAXCOL )
     {
@@ -692,8 +693,10 @@ ScChangeActionIns::ScChangeActionIns(
     const sal_uLong nActionNumber, const ScChangeActionState eStateP,
     const sal_uLong nRejectingNumber, const ScBigRange& aBigRangeP,
     const OUString& aUserP, const DateTime& aDateTimeP,
-    const OUString& sComment, const ScChangeActionType eTypeP) :
-    ScChangeAction(eTypeP, aBigRangeP, nActionNumber, nRejectingNumber, eStateP, aDateTimeP, aUserP, sComment)
+    const OUString& sComment, const ScChangeActionType eTypeP,
+    bool bEndOfList ) :
+    ScChangeAction(eTypeP, aBigRangeP, nActionNumber, nRejectingNumber, eStateP, aDateTimeP, aUserP, sComment),
+    mbEndOfList(bEndOfList)
 {
 }
 
@@ -736,6 +739,11 @@ void ScChangeActionIns::GetDescription(
     }
 }
 
+bool ScChangeActionIns::IsEndOfList() const
+{
+    return mbEndOfList;
+}
+
 bool ScChangeActionIns::Reject( ScDocument* pDoc )
 {
     if ( !aBigRange.IsValid( pDoc ) )
@@ -2826,9 +2834,9 @@ ScChangeActionContent* ScChangeTrack::AppendContentOnTheFly(
     return pAct;
 }
 
-void ScChangeTrack::AppendInsert( const ScRange& rRange )
+void ScChangeTrack::AppendInsert( const ScRange& rRange, bool bEndOfList )
 {
-    ScChangeActionIns* pAct = new ScChangeActionIns( rRange );
+    ScChangeActionIns* pAct = new ScChangeActionIns(rRange, bEndOfList);
     Append( pAct );
 }
 
@@ -4458,18 +4466,20 @@ ScChangeTrack* ScChangeTrack::Clone( ScDocument* pDocument ) const
             case SC_CAT_INSERT_COLS:
             case SC_CAT_INSERT_ROWS:
             case SC_CAT_INSERT_TABS:
-                {
-                    pClonedAction = new ScChangeActionIns(
-                        pAction->GetActionNumber(),
-                        pAction->GetState(),
-                        pAction->GetRejectAction(),
-                        pAction->GetBigRange(),
-                        pAction->GetUser(),
-                        pAction->GetDateTimeUTC(),
-                        pAction->GetComment(),
-                        pAction->GetType() );
-                }
-                break;
+            {
+                bool bEndOfList = static_cast<const ScChangeActionIns*>(pAction)->IsEndOfList();
+                pClonedAction = new ScChangeActionIns(
+                    pAction->GetActionNumber(),
+                    pAction->GetState(),
+                    pAction->GetRejectAction(),
+                    pAction->GetBigRange(),
+                    pAction->GetUser(),
+                    pAction->GetDateTimeUTC(),
+                    pAction->GetComment(),
+                    pAction->GetType(),
+                    bEndOfList );
+            }
+            break;
             case SC_CAT_DELETE_COLS:
             case SC_CAT_DELETE_ROWS:
             case SC_CAT_DELETE_TABS:
diff --git a/sc/source/filter/inc/XclExpChangeTrack.hxx b/sc/source/filter/inc/XclExpChangeTrack.hxx
index 72b7066..c7ee389 100644
--- a/sc/source/filter/inc/XclExpChangeTrack.hxx
+++ b/sc/source/filter/inc/XclExpChangeTrack.hxx
@@ -516,11 +516,12 @@ public:
 
 class XclExpChTrInsert : public XclExpChTrAction
 {
+    bool mbEndOfList;
+
 protected:
     ScRange                     aRange;
 
-                                XclExpChTrInsert( const XclExpChTrInsert& rCopy ) :
-                                    XclExpChTrAction( rCopy ), aRange( rCopy.aRange ) {}
+    XclExpChTrInsert( const XclExpChTrInsert& rCopy );
 
     virtual void                SaveActionData( XclExpStream& rStrm ) const;
     virtual void                PrepareSaveAction( XclExpStream& rStrm ) const;
diff --git a/sc/source/filter/inc/XclImpChangeTrack.hxx b/sc/source/filter/inc/XclImpChangeTrack.hxx
index ffce967..c1b06d6 100644
--- a/sc/source/filter/inc/XclImpChangeTrack.hxx
+++ b/sc/source/filter/inc/XclImpChangeTrack.hxx
@@ -73,7 +73,7 @@ private:
     void                        DoAcceptRejectAction( ScChangeAction* pAction );
     void                        DoAcceptRejectAction( sal_uInt32 nFirst, sal_uInt32 nLast );
 
-    void                        DoInsertRange( const ScRange& rRange );
+    void DoInsertRange( const ScRange& rRange, bool bEndOfList );
     void                        DoDeleteRange( const ScRange& rRange );
 
     inline sal_uInt8            LookAtuInt8();
diff --git a/sc/source/filter/xcl97/XclExpChangeTrack.cxx b/sc/source/filter/xcl97/XclExpChangeTrack.cxx
index aed0322..fe27e92 100644
--- a/sc/source/filter/xcl97/XclExpChangeTrack.cxx
+++ b/sc/source/filter/xcl97/XclExpChangeTrack.cxx
@@ -1118,7 +1118,10 @@ void XclExpChTrCellContent::SaveXml( XclExpXmlStream& rRevisionLogStrm )
     pStream->endElement( XML_rcc );
 }
 
-//___________________________________________________________________
+XclExpChTrInsert::XclExpChTrInsert( const XclExpChTrInsert& rCopy ) :
+    XclExpChTrAction(rCopy),
+    mbEndOfList(rCopy.mbEndOfList),
+    aRange(rCopy.aRange) {}
 
 XclExpChTrInsert::XclExpChTrInsert(
         const ScChangeAction& rAction,
@@ -1126,13 +1129,20 @@ XclExpChTrInsert::XclExpChTrInsert(
         const XclExpChTrTabIdBuffer& rTabIdBuffer,
         ScChangeTrack& rChangeTrack ) :
     XclExpChTrAction( rAction, rRoot, rTabIdBuffer ),
+    mbEndOfList(false),
     aRange( rAction.GetBigRange().MakeRange() )
 {
     nLength = 0x00000030;
     switch( rAction.GetType() )
     {
         case SC_CAT_INSERT_COLS:    nOpCode = EXC_CHTR_OP_INSCOL;   break;
-        case SC_CAT_INSERT_ROWS:    nOpCode = EXC_CHTR_OP_INSROW;   break;
+        case SC_CAT_INSERT_ROWS:
+        {
+            const ScChangeActionIns& rIns = static_cast<const ScChangeActionIns&>(rAction);
+            mbEndOfList = rIns.IsEndOfList();
+            nOpCode = EXC_CHTR_OP_INSROW;
+        }
+        break;
         case SC_CAT_DELETE_COLS:    nOpCode = EXC_CHTR_OP_DELCOL;   break;
         case SC_CAT_DELETE_ROWS:    nOpCode = EXC_CHTR_OP_DELROW;   break;
         default:
@@ -1164,7 +1174,8 @@ XclExpChTrInsert::~XclExpChTrInsert()
 void XclExpChTrInsert::SaveActionData( XclExpStream& rStrm ) const
 {
     WriteTabId( rStrm, aRange.aStart.Tab() );
-    rStrm   << (sal_uInt16) 0x0000;
+    sal_uInt16 nFlagVal = mbEndOfList ? 0x0001 : 0x0000;
+    rStrm << nFlagVal;
     Write2DRange( rStrm, aRange );
     rStrm   << (sal_uInt32) 0x00000000;
 }
diff --git a/sc/source/filter/xcl97/XclImpChangeTrack.cxx b/sc/source/filter/xcl97/XclImpChangeTrack.cxx
index 58c2540..cf1babc 100644
--- a/sc/source/filter/xcl97/XclImpChangeTrack.cxx
+++ b/sc/source/filter/xcl97/XclImpChangeTrack.cxx
@@ -95,10 +95,10 @@ void XclImpChangeTrack::DoAcceptRejectAction( sal_uInt32 nFirst, sal_uInt32 nLas
         DoAcceptRejectAction( pChangeTrack->GetAction( nIndex ) );
 }
 
-void XclImpChangeTrack::DoInsertRange( const ScRange& rRange )
+void XclImpChangeTrack::DoInsertRange( const ScRange& rRange, bool bEndOfList )
 {
     sal_uInt32 nFirst = pChangeTrack->GetActionMax() + 1;
-    pChangeTrack->AppendInsert( rRange );
+    pChangeTrack->AppendInsert(rRange, bEndOfList);
     sal_uInt32 nLast = pChangeTrack->GetActionMax();
     DoAcceptRejectAction( nFirst, nLast );
 }
@@ -299,7 +299,8 @@ void XclImpChangeTrack::ReadChTrInsert()
         ScRange aRange;
         aRange.aStart.SetTab( ReadTabNum() );
         aRange.aEnd.SetTab( aRange.aStart.Tab() );
-        pStrm->Ignore( 2 );
+        sal_uInt16 nFlags = pStrm->ReaduInt16();
+        bool bEndOfList = (nFlags & 0x0001); // row auto-inserted at the bottom.
         Read2DRange( aRange );
 
         if( aRecHeader.nOpCode & EXC_CHTR_OP_COLFLAG )
@@ -316,7 +317,7 @@ void XclImpChangeTrack::ReadChTrInsert()
             if( aRecHeader.nOpCode & EXC_CHTR_OP_DELFLAG )
                 DoDeleteRange( aRange );
             else
-                DoInsertRange( aRange );
+                DoInsertRange(aRange, bEndOfList);
         }
     }
 }
@@ -428,7 +429,7 @@ void XclImpChangeTrack::ReadChTrInsertTab()
         if( pStrm->IsValid() )
         {
             nTabIdCount++;
-            DoInsertRange( ScRange( 0, 0, nTab, MAXCOL, MAXROW, nTab ) );
+            DoInsertRange(ScRange(0, 0, nTab, MAXCOL, MAXROW, nTab), false);
         }
     }
 }
commit 766d54154f5225c9dc91ed8e4863d3fca1bd2b90
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Thu Jul 17 20:20:16 2014 -0400

    bnc#885548: Adjust xlsx export of revisions to get it to work in Excel.
    
    (cherry picked from commit fa44673e154ed4fb0b518b8850e2f6e4b9069531)
    Signed-off-by: Andras Timar <andras.timar at collabora.com>
    
    Conflicts:
    	sc/source/filter/inc/XclExpChangeTrack.hxx
    	sc/source/filter/xcl97/XclExpChangeTrack.cxx
    	sc/inc/cellvalue.hxx
    	sc/source/core/data/cellvalue.cxx
    
    Change-Id: I0058d9ddfea545390e615a3030171a366e333c85
    (cherry picked from commit ca20a53315eaea218c693e0de2026eb6f957331f)
    Signed-off-by: Andras Timar <andras.timar at collabora.com>

diff --git a/sc/inc/cellvalue.hxx b/sc/inc/cellvalue.hxx
index c2606b5..8e2e64a 100644
--- a/sc/inc/cellvalue.hxx
+++ b/sc/inc/cellvalue.hxx
@@ -53,6 +53,7 @@ struct SC_DLLPUBLIC ScCellValue
     void set( double fValue );
     void set( const svl::SharedString& rStr );
     void set( const EditTextObject& rEditText );
+    void set( EditTextObject* pEditText );
     void set( const ScFormulaCell& rFormula );
     void set( ScFormulaCell* pFormula );
 

... etc. - the rest is truncated


More information about the Libreoffice-commits mailing list