[Libreoffice-commits] core.git: Branch 'libreoffice-4-2' - include/xmloff RepositoryExternal.mk sc/inc sc/Library_sc.mk sc/Library_scqahelper.mk sc/source sc/uiconfig xmloff/source

Kohei Yoshida kohei.yoshida at collabora.com
Thu Dec 19 18:38:46 PST 2013


 RepositoryExternal.mk                        |    4 
 include/xmloff/xmltoken.hxx                  |    3 
 sc/Library_sc.mk                             |   10 
 sc/Library_scqahelper.mk                     |    8 
 sc/inc/column.hxx                            |    2 
 sc/inc/document.hxx                          |    8 
 sc/inc/documentlinkmgr.hxx                   |   36 +
 sc/inc/documentstreamaccess.hxx              |   62 +++
 sc/inc/importfilterdata.hxx                  |   49 ++
 sc/inc/mtvelements.hxx                       |    2 
 sc/inc/table.hxx                             |    2 
 sc/inc/xmlwrap.hxx                           |    6 
 sc/source/core/data/documen2.cxx             |   14 
 sc/source/core/data/documen8.cxx             |    5 
 sc/source/core/data/documentstreamaccess.cxx |  143 +++++++
 sc/source/core/data/mtvelements.cxx          |    6 
 sc/source/filter/importfilterdata.cxx        |   19 +
 sc/source/filter/xml/datastreamimport.cxx    |   92 ++++
 sc/source/filter/xml/datastreamimport.hxx    |   38 ++
 sc/source/filter/xml/xmlbodyi.cxx            |    4 
 sc/source/filter/xml/xmlcelli.cxx            |   14 
 sc/source/filter/xml/xmlexprt.cxx            |   58 ++-
 sc/source/filter/xml/xmlexprt.hxx            |    1 
 sc/source/filter/xml/xmlimprt.cxx            |   31 +
 sc/source/filter/xml/xmlimprt.hxx            |   27 +
 sc/source/filter/xml/xmlwrap.cxx             |    9 
 sc/source/ui/docshell/datastream.cxx         |  511 ++++++++++++++-------------
 sc/source/ui/docshell/docsh.cxx              |   34 +
 sc/source/ui/docshell/documentlinkmgr.cxx    |   44 ++
 sc/source/ui/inc/datastream.hxx              |   85 ++--
 sc/source/ui/inc/datastreamdlg.hxx           |   20 -
 sc/source/ui/inc/gridwin.hxx                 |    1 
 sc/source/ui/inc/tabview.hxx                 |    1 
 sc/source/ui/miscdlgs/datastreamdlg.cxx      |  124 ++++--
 sc/source/ui/view/cellsh2.cxx                |   58 +--
 sc/source/ui/view/tabview3.cxx               |   10 
 sc/uiconfig/scalc/ui/datastreams.ui          |    3 
 xmloff/source/core/xmltoken.cxx              |    3 
 38 files changed, 1184 insertions(+), 363 deletions(-)

New commits:
commit be7fea04f4c9218dc40bedc95e9496dcac1d1da7
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Thu Dec 12 16:09:11 2013 +0100

    Backport Calc's data stream massive cleanup effort.
    
    Change-Id: Ifbeb7c2d90d87a7cffe9a752f9e8b4910d55fcd9

diff --git a/RepositoryExternal.mk b/RepositoryExternal.mk
index 3073c565..689b5f5 100644
--- a/RepositoryExternal.mk
+++ b/RepositoryExternal.mk
@@ -2624,6 +2624,10 @@ endef
 
 define gb_LinkTarget__use_orcus-parser
 $(call gb_LinkTarget_use_external_project,$(1),liborcus)
+$(call gb_LinkTarget_set_include,$(1),\
+	-I$(call gb_UnpackedTarball_get_dir,liborcus/include) \
+	$$(INCLUDE) \
+)
 $(call gb_LinkTarget_add_libs,$(1),\
 	$(call gb_UnpackedTarball_get_dir,liborcus)/src/parser/.libs/liborcus-parser-0.6$(gb_StaticLibrary_PLAINEXT) \
 )
diff --git a/include/xmloff/xmltoken.hxx b/include/xmloff/xmltoken.hxx
index f9196af..d288c8848 100644
--- a/include/xmloff/xmltoken.hxx
+++ b/include/xmloff/xmltoken.hxx
@@ -550,6 +550,7 @@ namespace xmloff { namespace token {
         XML_DATA_PILOT_TABLE,
         XML_DATA_PILOT_TABLES,
         XML_DATA_POINT,
+        XML_DATA_STREAM_SOURCE,
         XML_DATA_STYLE,
         XML_DATA_STYLE_NAME,
         XML_DATA_TYPE,
@@ -669,6 +670,7 @@ namespace xmloff { namespace token {
         XML_EMBOSSED,
         XML_EMISSIVE_COLOR,
         XML_EMPTY,
+        XML_EMPTY_LINE_REFRESH,
         XML_ENABLE_NUMBERING,
         XML_ENABLED,
         XML_ENCODING,
@@ -1022,6 +1024,7 @@ namespace xmloff { namespace token {
         XML_INPROCEEDINGS,
         XML_INSERTION,
         XML_INSERTION_CUT_OFF,
+        XML_INSERTION_POSITION,
         XML_INSET,
         XML_INSIDE,
         XML_INSTITUTION,
diff --git a/sc/Library_sc.mk b/sc/Library_sc.mk
index fe2ddf8..791752f 100644
--- a/sc/Library_sc.mk
+++ b/sc/Library_sc.mk
@@ -45,6 +45,12 @@ $(eval $(call gb_Library_use_externals,sc,\
     mdds_headers \
 ))
 
+ifeq ($(SYSTEM_LIBORCUS),YES)
+$(eval $(call gb_Library_use_externals,sc,orcus))
+else
+$(eval $(call gb_Library_use_externals,sc,orcus-parser))
+endif
+
 ifeq ($(ENABLE_TELEPATHY),TRUE)
 $(eval $(call gb_Library_use_libraries,sc,tubes))
 
@@ -118,6 +124,7 @@ $(eval $(call gb_Library_add_exception_objects,sc,\
     sc/source/core/data/documen9 \
     sc/source/core/data/document \
     sc/source/core/data/documentimport \
+    sc/source/core/data/documentstreamaccess \
     sc/source/core/data/dpdimsave \
     sc/source/core/data/dpfilteredcache \
     sc/source/core/data/dpglobal \
@@ -262,6 +269,7 @@ $(eval $(call gb_Library_add_exception_objects,sc,\
     sc/source/core/tool/userlist \
     sc/source/core/tool/viewopti \
     sc/source/core/tool/zforauto \
+    sc/source/filter/xml/datastreamimport \
     sc/source/filter/xml/XMLCalculationSettingsContext \
     sc/source/filter/xml/XMLCellRangeSourceContext \
     sc/source/filter/xml/XMLChangeTrackingExportHelper \
@@ -317,6 +325,7 @@ $(eval $(call gb_Library_add_exception_objects,sc,\
     sc/source/filter/xml/xmltabi \
     sc/source/filter/xml/xmlwrap \
     sc/source/filter/chart/chart_imp \
+    sc/source/filter/importfilterdata \
     sc/source/ui/Accessibility/AccessibilityHints \
     sc/source/ui/Accessibility/AccessibleCell \
     sc/source/ui/Accessibility/AccessibleCellBase \
@@ -397,6 +406,7 @@ $(eval $(call gb_Library_add_exception_objects,sc,\
     sc/source/ui/docshell/docsh6 \
     sc/source/ui/docshell/docsh7 \
     sc/source/ui/docshell/docsh8 \
+    sc/source/ui/docshell/documentlinkmgr \
     sc/source/ui/docshell/editable \
     sc/source/ui/docshell/externalrefmgr \
     sc/source/ui/docshell/impex \
diff --git a/sc/Library_scqahelper.mk b/sc/Library_scqahelper.mk
index 37b1d54..cbdc99d 100644
--- a/sc/Library_scqahelper.mk
+++ b/sc/Library_scqahelper.mk
@@ -18,11 +18,15 @@ $(eval $(call gb_Library_set_include,scqahelper,\
 $(eval $(call gb_Library_use_externals,scqahelper, \
 	boost_headers \
 	mdds_headers \
-	orcus \
-	orcus-parser \
 	cppunit \
 ))
 
+ifeq ($(SYSTEM_LIBORCUS),YES)
+$(eval $(call gb_Library_use_externals,scqahelper,orcus))
+else
+$(eval $(call gb_Library_use_externals,scqahelper,orcus-parser))
+endif
+
 $(eval $(call gb_Library_add_defs,scqahelper,\
 	-DSCQAHELPER_DLLIMPLEMENTATION \
 ))
diff --git a/sc/inc/column.hxx b/sc/inc/column.hxx
index ba16644..55b3847 100644
--- a/sc/inc/column.hxx
+++ b/sc/inc/column.hxx
@@ -55,6 +55,7 @@ struct RefUpdateDeleteTabContext;
 struct RefUpdateMoveTabContext;
 class EditTextIterator;
 struct NoteEntry;
+class DocumentStreamAccess;
 
 }
 
@@ -138,6 +139,7 @@ friend class ScHorizontalCellIterator;
 friend class ScHorizontalAttrIterator;
 friend class ScColumnTextWidthIterator;
 friend class ScDocumentImport;
+friend class sc::DocumentStreamAccess;
 friend class sc::SingleColumnSpanSet;
 friend class sc::ColumnSpanSet;
 friend class sc::EditTextIterator;
diff --git a/sc/inc/document.hxx b/sc/inc/document.hxx
index e283b3d..65d573f 100644
--- a/sc/inc/document.hxx
+++ b/sc/inc/document.hxx
@@ -69,6 +69,8 @@ struct RefUpdateContext;
 class EditTextIterator;
 struct NoteEntry;
 struct FormulaGroupContext;
+class DocumentStreamAccess;
+class DocumentLinkManager;
 
 }
 
@@ -246,6 +248,7 @@ friend class ScTable;
 friend class ScColumn;
 friend struct ScRefCellValue;
 friend class ScDocumentImport;
+friend class sc::DocumentStreamAccess;
 friend class sc::ColumnSpanSet;
 friend class sc::EditTextIterator;
 
@@ -256,6 +259,7 @@ private:
 
     boost::scoped_ptr<svl::SharedStringPool> mpCellStringPool;
     boost::scoped_ptr<sc::FormulaGroupContext> mpFormulaGroupCxt;
+    mutable boost::scoped_ptr<sc::DocumentLinkManager> mpDocLinkMgr;
 
     SfxUndoManager*     mpUndoManager;
     ScFieldEditEngine*  pEditEngine;                    // uses pEditPool from xPoolHelper
@@ -464,6 +468,9 @@ public:
 
     SC_DLLPUBLIC sfx2::LinkManager*     GetLinkManager() const;
 
+    sc::DocumentLinkManager& GetDocLinkManager();
+    const sc::DocumentLinkManager& GetDocLinkManager() const;
+
     SC_DLLPUBLIC const ScDocOptions&        GetDocOptions() const;
     SC_DLLPUBLIC void                   SetDocOptions( const ScDocOptions& rOpt );
     SC_DLLPUBLIC const ScViewOptions&   GetViewOptions() const;
@@ -1801,6 +1808,7 @@ public:
                             Preferred.
                          */
     void                Broadcast( const ScHint& rHint );
+
                         /// only area, no cell broadcast
     void                AreaBroadcast( const ScHint& rHint );
                         /// only areas in range, no cell broadcasts
diff --git a/sc/inc/documentlinkmgr.hxx b/sc/inc/documentlinkmgr.hxx
new file mode 100644
index 0000000..ead5698
--- /dev/null
+++ b/sc/inc/documentlinkmgr.hxx
@@ -0,0 +1,36 @@
+/* -*- 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_DOCUMENTLINKMGR_HXX
+#define SC_DOCUMENTLINKMGR_HXX
+
+#include <boost/noncopyable.hpp>
+
+namespace sc {
+
+class DataStream;
+struct DocumentLinkManagerImpl;
+
+class DocumentLinkManager : boost::noncopyable
+{
+    DocumentLinkManagerImpl* mpImpl;
+
+public:
+    DocumentLinkManager();
+
+    void setDataStream( DataStream* p );
+    DataStream* getDataStream();
+    const DataStream* getDataStream() const;
+};
+
+}
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/inc/documentstreamaccess.hxx b/sc/inc/documentstreamaccess.hxx
new file mode 100644
index 0000000..9fa2d78
--- /dev/null
+++ b/sc/inc/documentstreamaccess.hxx
@@ -0,0 +1,62 @@
+/* -*- 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_DOCUMENTSTREAMACCESS_HXX
+#define SC_DOCUMENTSTREAMACCESS_HXX
+
+#include <rtl/ustring.hxx>
+
+class ScDocument;
+class ScAddress;
+class ScRange;
+
+namespace sc {
+
+struct DocumentStreamAccessImpl;
+
+/**
+ * Provides methods to allow direct shifting of document content without
+ * broadcasting or shifting of broadcaster positions.
+ */
+class DocumentStreamAccess
+{
+    DocumentStreamAccessImpl* mpImpl;
+
+    DocumentStreamAccess();
+
+public:
+    DocumentStreamAccess( ScDocument& rDoc );
+
+    void setNumericCell( const ScAddress& rPos, double fVal );
+    void setStringCell( const ScAddress& rPos, const OUString& rStr );
+
+    /**
+     * Clear its internal state, and more importantly all the block position
+     * hints currently held.
+     */
+    void reset();
+
+    /**
+     * Pop the top row inside specified range, shift all the other rows up by
+     * one, then set the bottom row empty.
+     */
+    void shiftRangeUp( const ScRange& rRange );
+
+    /**
+     * Top the bottom row inside specified range, shift all the other rows
+     * above downward by one by inserting an empty row at the top.
+     */
+    void shiftRangeDown( const ScRange& rRange );
+};
+
+}
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/inc/importfilterdata.hxx b/sc/inc/importfilterdata.hxx
new file mode 100644
index 0000000..23cef83
--- /dev/null
+++ b/sc/inc/importfilterdata.hxx
@@ -0,0 +1,49 @@
+/* -*- 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_IMPORTFILTERDATA_HXX
+#define SC_IMPORTFILTERDATA_HXX
+
+#include <address.hxx>
+
+#include <boost/noncopyable.hpp>
+#include <boost/scoped_ptr.hpp>
+
+namespace sc {
+
+/**
+ * Stores data imported from the file that need to be processed at the end
+ * of the import process.
+ */
+struct ImportPostProcessData : boost::noncopyable
+{
+    /**
+     * Data stream data needs to be post-processed because it requires
+     * ScDocShell instance which is not available in the filter code.
+     */
+    struct DataStream
+    {
+        enum InsertPos { InsertTop, InsertBottom };
+
+        OUString maURL;
+        ScRange maRange;
+        bool mbRefreshOnEmpty;
+        InsertPos meInsertPos;
+
+        DataStream();
+    };
+
+    boost::scoped_ptr<DataStream> mpDataStream;
+};
+
+}
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/inc/mtvelements.hxx b/sc/inc/mtvelements.hxx
index e5efbf1..0fcafde 100644
--- a/sc/inc/mtvelements.hxx
+++ b/sc/inc/mtvelements.hxx
@@ -145,6 +145,8 @@ public:
     ColumnBlockPositionSet(ScDocument& rDoc);
 
     ColumnBlockPosition* getBlockPosition(SCTAB nTab, SCCOL nCol);
+
+    void clear();
 };
 
 ScRefCellValue toRefCell( const sc::CellStoreType::const_iterator& itPos, size_t nOffset );
diff --git a/sc/inc/table.hxx b/sc/inc/table.hxx
index e273da8..86b61f5 100644
--- a/sc/inc/table.hxx
+++ b/sc/inc/table.hxx
@@ -67,6 +67,7 @@ struct RefUpdateInsertTabContext;
 struct RefUpdateDeleteTabContext;
 struct RefUpdateMoveTabContext;
 struct NoteEntry;
+class DocumentStreamAccess;
 
 }
 
@@ -208,6 +209,7 @@ friend class ScDocAttrIterator;
 friend class ScAttrRectIterator;
 friend class ScColumnTextWidthIterator;
 friend class ScDocumentImport;
+friend class sc::DocumentStreamAccess;
 friend class sc::ColumnSpanSet;
 friend class sc::EditTextIterator;
 
diff --git a/sc/inc/xmlwrap.hxx b/sc/inc/xmlwrap.hxx
index fb7b156..107ceb4 100644
--- a/sc/inc/xmlwrap.hxx
+++ b/sc/inc/xmlwrap.hxx
@@ -25,6 +25,8 @@
 #include <com/sun/star/uno/Sequence.hxx>
 #include <com/sun/star/frame/XModel.hpp>
 
+#include <importfilterdata.hxx>
+
 class ScDocument;
 class SfxMedium;
 class ScMySharedData;
@@ -44,6 +46,8 @@ namespace com { namespace sun { namespace star {
 
 class ScXMLImportWrapper
 {
+    sc::ImportPostProcessData maPostProcessData;
+
     ScDocument&     rDoc;
     SfxMedium*      pMedium;
     ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage > xStorage;
@@ -70,6 +74,8 @@ public:
     ScXMLImportWrapper(ScDocument& rD, SfxMedium* pM, const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage >&);
     sal_Bool Import(sal_Bool bStylesOnly, ErrCode& );
     sal_Bool Export(sal_Bool bStylesOnly);
+
+    const sc::ImportPostProcessData& GetImportPostProcessData() const;
 };
 
 class ScXMLChartExportWrapper
diff --git a/sc/source/core/data/documen2.cxx b/sc/source/core/data/documen2.cxx
index 6c112d5..ae9cbd9 100644
--- a/sc/source/core/data/documen2.cxx
+++ b/sc/source/core/data/documen2.cxx
@@ -92,6 +92,7 @@
 #include "refreshtimerprotector.hxx"
 #include "scopetools.hxx"
 #include "formulagroup.hxx"
+#include "documentlinkmgr.hxx"
 
 using namespace com::sun::star;
 
@@ -262,6 +263,19 @@ sfx2::LinkManager*  ScDocument::GetLinkManager()  const
     return pLinkManager;
 }
 
+sc::DocumentLinkManager& ScDocument::GetDocLinkManager()
+{
+    if (!mpDocLinkMgr)
+        mpDocLinkMgr.reset(new sc::DocumentLinkManager);
+    return *mpDocLinkMgr;
+}
+
+const sc::DocumentLinkManager& ScDocument::GetDocLinkManager() const
+{
+    if (!mpDocLinkMgr)
+        mpDocLinkMgr.reset(new sc::DocumentLinkManager);
+    return *mpDocLinkMgr;
+}
 
 void ScDocument::SetStorageGrammar( formula::FormulaGrammar::Grammar eGram )
 {
diff --git a/sc/source/core/data/documen8.cxx b/sc/source/core/data/documen8.cxx
index 09bef92..47ad103 100644
--- a/sc/source/core/data/documen8.cxx
+++ b/sc/source/core/data/documen8.cxx
@@ -86,7 +86,6 @@
 #include "columniterator.hxx"
 #include "globalnames.hxx"
 #include "stringutil.hxx"
-#include <datastream.hxx>
 
 #include <memory>
 #include <boost/scoped_ptr.hpp>
@@ -1194,7 +1193,7 @@ bool ScDocument::HasAreaLinks() const
         const ::sfx2::SvBaseLinks& rLinks = pLinkManager->GetLinks();
         sal_uInt16 nCount = rLinks.size();
         for (sal_uInt16 i=0; i<nCount; i++)
-            if ((*rLinks[i])->ISA(ScAreaLink) || (*rLinks[i])->ISA(DataStream))
+            if ((*rLinks[i])->ISA(ScAreaLink))
                 return true;
     }
 
@@ -1209,7 +1208,7 @@ void ScDocument::UpdateAreaLinks()
         for (sal_uInt16 i=0; i<rLinks.size(); i++)
         {
             ::sfx2::SvBaseLink* pBase = *rLinks[i];
-            if (pBase->ISA(ScAreaLink) || (*rLinks[i])->ISA(DataStream))
+            if (pBase->ISA(ScAreaLink))
                 pBase->Update();
         }
     }
diff --git a/sc/source/core/data/documentstreamaccess.cxx b/sc/source/core/data/documentstreamaccess.cxx
new file mode 100644
index 0000000..bf3efe3
--- /dev/null
+++ b/sc/source/core/data/documentstreamaccess.cxx
@@ -0,0 +1,143 @@
+/* -*- 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 "documentstreamaccess.hxx"
+#include "document.hxx"
+#include "table.hxx"
+#include "column.hxx"
+#include "mtvelements.hxx"
+
+#include "svl/sharedstringpool.hxx"
+
+namespace sc {
+
+struct DocumentStreamAccessImpl
+{
+    ScDocument& mrDoc;
+    ColumnBlockPositionSet maBlockPosSet;
+
+    DocumentStreamAccessImpl( ScDocument& rDoc ) :
+        mrDoc(rDoc),
+        maBlockPosSet(rDoc)
+    {}
+};
+
+DocumentStreamAccess::DocumentStreamAccess( ScDocument& rDoc ) :
+    mpImpl(new DocumentStreamAccessImpl(rDoc)) {}
+
+void DocumentStreamAccess::setNumericCell( const ScAddress& rPos, double fVal )
+{
+    ScTable* pTab = mpImpl->mrDoc.FetchTable(rPos.Tab());
+    if (!pTab)
+        return;
+
+    ColumnBlockPosition* pBlockPos =
+        mpImpl->maBlockPosSet.getBlockPosition(rPos.Tab(), rPos.Col());
+
+    if (!pBlockPos)
+        return;
+
+    // Set the numeric value.
+    CellStoreType& rCells = pTab->aCol[rPos.Col()].maCells;
+    pBlockPos->miCellPos = rCells.set(pBlockPos->miCellPos, rPos.Row(), fVal);
+
+    // Be sure to set the corresponding text attribute to the default value.
+    CellTextAttrStoreType& rAttrs = pTab->aCol[rPos.Col()].maCellTextAttrs;
+    pBlockPos->miCellTextAttrPos = rAttrs.set(pBlockPos->miCellTextAttrPos, rPos.Row(), CellTextAttr());
+}
+
+void DocumentStreamAccess::setStringCell( const ScAddress& rPos, const OUString& rStr )
+{
+    ScTable* pTab = mpImpl->mrDoc.FetchTable(rPos.Tab());
+    if (!pTab)
+        return;
+
+    ColumnBlockPosition* pBlockPos =
+        mpImpl->maBlockPosSet.getBlockPosition(rPos.Tab(), rPos.Col());
+
+    if (!pBlockPos)
+        return;
+
+    svl::SharedString aSS = mpImpl->mrDoc.GetSharedStringPool().intern(rStr);
+    if (!aSS.getData())
+        return;
+
+    // Set the string.
+    CellStoreType& rCells = pTab->aCol[rPos.Col()].maCells;
+    pBlockPos->miCellPos = rCells.set(pBlockPos->miCellPos, rPos.Row(), aSS);
+
+    // Be sure to set the corresponding text attribute to the default value.
+    CellTextAttrStoreType& rAttrs = pTab->aCol[rPos.Col()].maCellTextAttrs;
+    pBlockPos->miCellTextAttrPos = rAttrs.set(pBlockPos->miCellTextAttrPos, rPos.Row(), CellTextAttr());
+}
+
+void DocumentStreamAccess::reset()
+{
+    mpImpl->maBlockPosSet.clear();
+}
+
+void DocumentStreamAccess::shiftRangeUp( const ScRange& rRange )
+{
+    ScTable* pTab = mpImpl->mrDoc.FetchTable(rRange.aStart.Tab());
+    if (!pTab)
+        return;
+
+    SCROW nTopRow = rRange.aStart.Row();
+    SCROW nLastRow = rRange.aEnd.Row();
+
+    for (SCCOL nCol = rRange.aStart.Col(); nCol <= rRange.aEnd.Col(); ++nCol)
+    {
+        ColumnBlockPosition* pBlockPos =
+            mpImpl->maBlockPosSet.getBlockPosition(rRange.aStart.Tab(), nCol);
+
+        if (!pBlockPos)
+            return;
+
+        CellStoreType& rCells = pTab->aCol[nCol].maCells;
+        rCells.erase(nTopRow, nTopRow); // Erase the top, and shift the rest up.
+        pBlockPos->miCellPos = rCells.insert_empty(nLastRow, 1);
+
+        // Do the same for the text attribute storage.
+        CellTextAttrStoreType& rAttrs = pTab->aCol[nCol].maCellTextAttrs;
+        rAttrs.erase(nTopRow, nTopRow);
+        pBlockPos->miCellTextAttrPos = rAttrs.insert_empty(nLastRow, 1);
+    }
+}
+
+void DocumentStreamAccess::shiftRangeDown( const ScRange& rRange )
+{
+    ScTable* pTab = mpImpl->mrDoc.FetchTable(rRange.aStart.Tab());
+    if (!pTab)
+        return;
+
+    SCROW nTopRow = rRange.aStart.Row();
+    SCROW nLastRow = rRange.aEnd.Row();
+
+    for (SCCOL nCol = rRange.aStart.Col(); nCol <= rRange.aEnd.Col(); ++nCol)
+    {
+        ColumnBlockPosition* pBlockPos =
+            mpImpl->maBlockPosSet.getBlockPosition(rRange.aStart.Tab(), nCol);
+
+        if (!pBlockPos)
+            return;
+
+        CellStoreType& rCells = pTab->aCol[nCol].maCells;
+        rCells.erase(nLastRow, nLastRow); // Erase the bottom.
+        pBlockPos->miCellPos = rCells.insert_empty(nTopRow, 1); // insert at the top and shift everything down.
+
+        // Do the same for the text attribute storage.
+        CellTextAttrStoreType& rAttrs = pTab->aCol[nCol].maCellTextAttrs;
+        rAttrs.erase(nLastRow, nLastRow);
+        pBlockPos->miCellTextAttrPos = rAttrs.insert_empty(nTopRow, 1);
+    }
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/core/data/mtvelements.cxx b/sc/source/core/data/mtvelements.cxx
index 5a94606..1110ab6 100644
--- a/sc/source/core/data/mtvelements.cxx
+++ b/sc/source/core/data/mtvelements.cxx
@@ -67,6 +67,12 @@ ColumnBlockPosition* ColumnBlockPositionSet::getBlockPosition(SCTAB nTab, SCCOL
     return &it->second;
 }
 
+void ColumnBlockPositionSet::clear()
+{
+    osl::MutexGuard aGuard(&maMtxTables);
+    maTables.clear();
+}
+
 ScRefCellValue toRefCell( const sc::CellStoreType::const_iterator& itPos, size_t nOffset )
 {
     switch (itPos->type)
diff --git a/sc/source/filter/importfilterdata.cxx b/sc/source/filter/importfilterdata.cxx
new file mode 100644
index 0000000..1001889
--- /dev/null
+++ b/sc/source/filter/importfilterdata.cxx
@@ -0,0 +1,19 @@
+/* -*- 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 <importfilterdata.hxx>
+
+namespace sc {
+
+ImportPostProcessData::DataStream::DataStream() :
+    mbRefreshOnEmpty(false), meInsertPos(InsertBottom) {}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/filter/xml/datastreamimport.cxx b/sc/source/filter/xml/datastreamimport.cxx
new file mode 100644
index 0000000..3c5f17d
--- /dev/null
+++ b/sc/source/filter/xml/datastreamimport.cxx
@@ -0,0 +1,92 @@
+/* -*- 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 "datastreamimport.hxx"
+#include "xmlimprt.hxx"
+
+#include <rangeutl.hxx>
+#include <importfilterdata.hxx>
+#include <xmloff/nmspmap.hxx>
+#include <xmloff/xmltoken.hxx>
+#include <formula/grammar.hxx>
+
+using namespace com::sun::star;
+using namespace xmloff::token;
+
+ScXMLDataStreamContext::ScXMLDataStreamContext(
+    ScXMLImport& rImport, sal_uInt16 nPrefix, const OUString& rLocalName,
+    const com::sun::star::uno::Reference<
+        com::sun::star::xml::sax::XAttributeList>& xAttrList ) :
+    ScXMLImportContext(rImport, nPrefix, rLocalName),
+    mbRefreshOnEmpty(false),
+    meInsertPos(sc::ImportPostProcessData::DataStream::InsertBottom)
+{
+    if (!xAttrList.is())
+        return;
+
+    const SvXMLTokenMap& rAttrTokenMap = GetScImport().GetDataStreamAttrTokenMap();
+
+    for (sal_Int32 i = 0; i < xAttrList->getLength(); ++i)
+    {
+        const OUString& rName = xAttrList->getNameByIndex(i);
+        OUString aLocalName;
+        sal_uInt16 nLocalPrefix =
+            GetScImport().GetNamespaceMap().GetKeyByAttrName(rName, &aLocalName);
+
+        const OUString& rVal = xAttrList->getValueByIndex(i);
+        switch (rAttrTokenMap.Get(nLocalPrefix, aLocalName))
+        {
+            case XML_TOK_DATA_STREAM_ATTR_URL:
+                maURL = GetScImport().GetAbsoluteReference(rVal);
+            break;
+            case XML_TOK_DATA_STREAM_ATTR_RANGE:
+            {
+                ScDocument* pDoc = GetScImport().GetDocument();
+                sal_Int32 nOffset = 0;
+                if (!ScRangeStringConverter::GetRangeFromString(
+                    maRange, rVal, pDoc, formula::FormulaGrammar::CONV_OOO, nOffset))
+                    maRange.SetInvalid();
+            }
+            break;
+            case XML_TOK_DATA_STREAM_ATTR_EMPTY_LINE_REFRESH:
+                mbRefreshOnEmpty = IsXMLToken(rVal, XML_TRUE);
+            break;
+            case XML_TOK_DATA_STREAM_ATTR_INSERTION_POSITION:
+                meInsertPos = IsXMLToken(rVal, XML_TOP) ?
+                    sc::ImportPostProcessData::DataStream::InsertTop :
+                    sc::ImportPostProcessData::DataStream::InsertBottom;
+            break;
+            default:
+                ;
+        }
+    }
+}
+
+ScXMLDataStreamContext::~ScXMLDataStreamContext() {}
+
+void ScXMLDataStreamContext::EndElement()
+{
+    if (!maRange.IsValid())
+        // Range must be valid.
+        return;
+
+    sc::ImportPostProcessData* pData = GetScImport().GetPostProcessData();
+    if (!pData)
+        return;
+
+    pData->mpDataStream.reset(new sc::ImportPostProcessData::DataStream);
+    sc::ImportPostProcessData::DataStream& rData = *pData->mpDataStream;
+
+    rData.maURL = maURL;
+    rData.maRange = maRange;
+    rData.mbRefreshOnEmpty = mbRefreshOnEmpty;
+    rData.meInsertPos = meInsertPos;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/filter/xml/datastreamimport.hxx b/sc/source/filter/xml/datastreamimport.hxx
new file mode 100644
index 0000000..c77f235
--- /dev/null
+++ b/sc/source/filter/xml/datastreamimport.hxx
@@ -0,0 +1,38 @@
+/* -*- 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_XML_DATASTREAMIMPORT_HXX
+#define SC_XML_DATASTREAMIMPORT_HXX
+
+#include "importcontext.hxx"
+
+#include <importfilterdata.hxx>
+#include <address.hxx>
+
+class ScXMLDataStreamContext : public ScXMLImportContext
+{
+    OUString maURL;
+    ScRange maRange;
+    bool mbRefreshOnEmpty;
+    sc::ImportPostProcessData::DataStream::InsertPos meInsertPos;
+
+public:
+    ScXMLDataStreamContext(
+        ScXMLImport& rImport, sal_uInt16 nPrefix, const OUString& rLocalName,
+        const com::sun::star::uno::Reference<
+            com::sun::star::xml::sax::XAttributeList>& xAttrList );
+
+    virtual ~ScXMLDataStreamContext();
+
+    virtual void EndElement();
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/filter/xml/xmlbodyi.cxx b/sc/source/filter/xml/xmlbodyi.cxx
index 10a0a94..2496a94 100644
--- a/sc/source/filter/xml/xmlbodyi.cxx
+++ b/sc/source/filter/xml/xmlbodyi.cxx
@@ -39,6 +39,7 @@
 #include "XMLEmptyContext.hxx"
 #include "scerrors.hxx"
 #include "tabprotection.hxx"
+#include "datastreamimport.hxx"
 
 #include <xmloff/xmltkmap.hxx>
 #include <xmloff/xmltoken.hxx>
@@ -192,6 +193,9 @@ SvXMLImportContext *ScXMLBodyContext::CreateChildContext( sal_uInt16 nPrefix,
         pContext = new ScXMLDDELinksContext ( GetScImport(), nPrefix, rLocalName,
                                                         xAttrList );
         break;
+    case XML_TOK_BODY_DATA_STREAM_SOURCE:
+        pContext = new ScXMLDataStreamContext(GetScImport(), nPrefix, rLocalName, xAttrList);
+        break;
     }
 
     if( !pContext )
diff --git a/sc/source/filter/xml/xmlcelli.cxx b/sc/source/filter/xml/xmlcelli.cxx
index 1875afa..e40a527 100644
--- a/sc/source/filter/xml/xmlcelli.cxx
+++ b/sc/source/filter/xml/xmlcelli.cxx
@@ -1000,20 +1000,6 @@ void ScXMLTableRowCellContext::SetCellRangeSource( const ScAddress& rPosition )
                 rPosition.Row() + static_cast<SCROW>(pCellRangeSource->nRows - 1), rPosition.Tab() );
             OUString sFilterName( pCellRangeSource->sFilterName );
             OUString sSourceStr( pCellRangeSource->sSourceStr );
-            OUString sRangeStr;
-            ScRangeStringConverter::GetStringFromRange( sRangeStr, aDestRange, pDoc, formula::FormulaGrammar::CONV_OOO );
-            SvtMiscOptions aMiscOptions;
-            if (aMiscOptions.IsExperimentalMode() && pCellRangeSource->sFilterOptions == "DataStream")
-            {
-                DataStream::Set( dynamic_cast<ScDocShell*>(pDoc->GetDocumentShell())
-                        , pCellRangeSource->sURL // rURL
-                        , sRangeStr // rRange
-                        , sFilterName.toInt32() // nLimit
-                        , sSourceStr // rMove
-                        , pCellRangeSource->nRefresh // nSettings
-                        );
-                return;
-            }
             ScAreaLink* pLink = new ScAreaLink( pDoc->GetDocumentShell(), pCellRangeSource->sURL,
                 sFilterName, pCellRangeSource->sFilterOptions, sSourceStr, aDestRange, pCellRangeSource->nRefresh );
             sfx2::LinkManager* pLinkManager = pDoc->GetLinkManager();
diff --git a/sc/source/filter/xml/xmlexprt.cxx b/sc/source/filter/xml/xmlexprt.cxx
index eadcd3b..3699a61 100644
--- a/sc/source/filter/xml/xmlexprt.cxx
+++ b/sc/source/filter/xml/xmlexprt.cxx
@@ -62,6 +62,7 @@
 #include "editattributemap.hxx"
 #include <arealink.hxx>
 #include <datastream.hxx>
+#include <documentlinkmgr.hxx>
 
 #include <xmloff/xmltoken.hxx>
 #include <xmloff/xmlnmspe.hxx>
@@ -109,6 +110,7 @@
 #include <editeng/outlobj.hxx>
 #include <svx/svditer.hxx>
 #include <svx/svdpage.hxx>
+#include <svtools/miscopt.hxx>
 
 #include <comphelper/processfactory.hxx>
 #include <com/sun/star/beans/XPropertySet.hpp>
@@ -836,18 +838,6 @@ void ScXMLExport::GetAreaLinks( ScMyAreaLinksContainer& rAreaLinks )
                 aAreaLink.nRefresh = pLink->GetTimeout();
                 rAreaLinks.AddNewAreaLink( aAreaLink );
             }
-            DataStream *pStream = dynamic_cast<DataStream*>(&(*(*rLinks[i])));
-            if (pStream)
-            {
-                ScMyAreaLink aAreaLink;
-                ScUnoConversion::FillApiRange( aAreaLink.aDestRange, pStream->GetRange() );
-                aAreaLink.sSourceStr = pStream->GetMove();
-                aAreaLink.sFilter = OUString::number(pStream->GetLimit());
-                aAreaLink.sFilterOptions = "DataStream";
-                aAreaLink.sURL = pStream->GetURL();
-                aAreaLink.nRefresh = pStream->GetSettings();
-                rAreaLinks.AddNewAreaLink( aAreaLink );
-            }
         }
     }
     rAreaLinks.Sort();
@@ -1955,6 +1945,7 @@ void ScXMLExport::_ExportContent()
     }
     WriteExternalRefCaches();
     WriteNamedExpressions();
+    WriteDataStream();
     aExportDatabaseRanges.WriteDatabaseRanges();
     ScXMLExportDataPilot aExportDataPilot(*this);
     aExportDataPilot.WriteDataPilots(xSpreadDoc);
@@ -4051,6 +4042,49 @@ void ScXMLExport::WriteNamedExpressions()
     WriteNamedRange(pNamedRanges);
 }
 
+void ScXMLExport::WriteDataStream()
+{
+    if (!pDoc)
+        return;
+
+    SvtMiscOptions aMiscOptions;
+    if (!aMiscOptions.IsExperimentalMode())
+        // Export this only in experimental mode.
+        return;
+
+    if (getDefaultVersion() <= SvtSaveOptions::ODFVER_012)
+        // Export this only for 1.2 extended and above.
+        return;
+
+    const sc::DocumentLinkManager& rMgr = pDoc->GetDocLinkManager();
+    const sc::DataStream* pStrm = rMgr.getDataStream();
+    if (!pStrm)
+        // No data stream.
+        return;
+
+    // Source URL
+    AddAttribute(XML_NAMESPACE_XLINK, XML_HREF, GetRelativeReference(pStrm->GetURL()));
+
+    // Streamed range
+    ScRange aRange = pStrm->GetRange();
+    OUString aRangeStr;
+    ScRangeStringConverter::GetStringFromRange(
+        aRangeStr, aRange, pDoc, formula::FormulaGrammar::CONV_OOO);
+    AddAttribute(XML_NAMESPACE_TABLE, XML_TARGET_RANGE_ADDRESS, aRangeStr);
+
+    // Empty line refresh option.
+    AddAttribute(XML_NAMESPACE_CALC_EXT, XML_EMPTY_LINE_REFRESH, pStrm->IsRefreshOnEmptyLine() ? XML_TRUE : XML_FALSE);
+
+    // New data insertion position. Either top of bottom. Default to bottom.
+    xmloff::token::XMLTokenEnum eInsertPosition = XML_BOTTOM;
+    if (pStrm->GetMove() == sc::DataStream::MOVE_DOWN)
+        eInsertPosition = XML_TOP;
+
+    AddAttribute(XML_NAMESPACE_CALC_EXT, XML_INSERTION_POSITION, eInsertPosition);
+
+    SvXMLElementExport aElem(*this, XML_NAMESPACE_CALC_EXT, XML_DATA_STREAM_SOURCE, true, true);
+}
+
 void ScXMLExport::WriteNamedRange(ScRangeName* pRangeName)
 {
     //write a global or local ScRangeName
diff --git a/sc/source/filter/xml/xmlexprt.hxx b/sc/source/filter/xml/xmlexprt.hxx
index 4ece1d5..564009d 100644
--- a/sc/source/filter/xml/xmlexprt.hxx
+++ b/sc/source/filter/xml/xmlexprt.hxx
@@ -198,6 +198,7 @@ class ScXMLExport : public SvXMLExport
     void WriteTheLabelRanges(const com::sun::star::uno::Reference< com::sun::star::sheet::XSpreadsheetDocument >& xSpreadDoc);
     void WriteLabelRanges( const com::sun::star::uno::Reference< com::sun::star::container::XIndexAccess >& xRangesIAccess, bool bColumn );
     void WriteNamedExpressions();
+    void WriteDataStream();
     void WriteNamedRange(ScRangeName* pRangeName);
     void ExportConditionalFormat(SCTAB nTab);
     void WriteExternalRefCaches();
diff --git a/sc/source/filter/xml/xmlimprt.cxx b/sc/source/filter/xml/xmlimprt.cxx
index 0320be5..96be811 100644
--- a/sc/source/filter/xml/xmlimprt.cxx
+++ b/sc/source/filter/xml/xmlimprt.cxx
@@ -457,6 +457,7 @@ const SvXMLTokenMap& ScXMLImport::GetBodyElemTokenMap()
             { XML_NAMESPACE_TABLE, XML_DATA_PILOT_TABLES,       XML_TOK_BODY_DATA_PILOT_TABLES      },
             { XML_NAMESPACE_TABLE, XML_CONSOLIDATION,           XML_TOK_BODY_CONSOLIDATION          },
             { XML_NAMESPACE_TABLE, XML_DDE_LINKS,               XML_TOK_BODY_DDE_LINKS              },
+            { XML_NAMESPACE_CALC_EXT, XML_DATA_STREAM_SOURCE,   XML_TOK_BODY_DATA_STREAM_SOURCE     },
             XML_TOKEN_MAP_END
         };
 
@@ -1930,6 +1931,33 @@ const SvXMLTokenMap& ScXMLImport::GetCellTextSAttrTokenMap()
     return *pCellTextSAttrTokenMap;
 }
 
+const SvXMLTokenMap& ScXMLImport::GetDataStreamAttrTokenMap()
+{
+    if (!pDataStreamAttrTokenMap)
+    {
+        static const SvXMLTokenMapEntry aMap[] =
+        {
+            { XML_NAMESPACE_XLINK, XML_HREF, XML_TOK_DATA_STREAM_ATTR_URL },
+            { XML_NAMESPACE_TABLE, XML_TARGET_RANGE_ADDRESS, XML_TOK_DATA_STREAM_ATTR_RANGE },
+            { XML_NAMESPACE_CALC_EXT, XML_EMPTY_LINE_REFRESH, XML_TOK_DATA_STREAM_ATTR_EMPTY_LINE_REFRESH },
+            { XML_NAMESPACE_CALC_EXT, XML_INSERTION_POSITION, XML_TOK_DATA_STREAM_ATTR_INSERTION_POSITION },
+            XML_TOKEN_MAP_END
+        };
+        pDataStreamAttrTokenMap = new SvXMLTokenMap(aMap);
+    }
+    return *pDataStreamAttrTokenMap;
+}
+
+void ScXMLImport::SetPostProcessData( sc::ImportPostProcessData* p )
+{
+    mpPostProcessData = p;
+}
+
+sc::ImportPostProcessData* ScXMLImport::GetPostProcessData()
+{
+    return mpPostProcessData;
+}
+
 SvXMLImportContext *ScXMLImport::CreateContext( sal_uInt16 nPrefix,
                                                const OUString& rLocalName,
                                                const uno::Reference<xml::sax::XAttributeList>& xAttrList )
@@ -2056,6 +2084,8 @@ ScXMLImport::ScXMLImport(
     pCellTextSpanAttrTokenMap(NULL),
     pCellTextURLAttrTokenMap(NULL),
     pCellTextSAttrTokenMap(NULL),
+    pDataStreamAttrTokenMap(NULL),
+    mpPostProcessData(NULL),
     aTables(*this),
     pMyNamedExpressions(NULL),
     pMyLabelRanges(NULL),
@@ -2197,6 +2227,7 @@ ScXMLImport::~ScXMLImport() throw()
     delete pCellTextSpanAttrTokenMap;
     delete pCellTextURLAttrTokenMap;
     delete pCellTextSAttrTokenMap;
+    delete pDataStreamAttrTokenMap;
 
     delete pChangeTrackingImportHelper;
     delete pNumberFormatAttributesExportHelper;
diff --git a/sc/source/filter/xml/xmlimprt.hxx b/sc/source/filter/xml/xmlimprt.hxx
index d4d45a7..f3dba75 100644
--- a/sc/source/filter/xml/xmlimprt.hxx
+++ b/sc/source/filter/xml/xmlimprt.hxx
@@ -55,6 +55,12 @@ class XMLNumberFormatAttributesExportHelper;
 class ScEditEngineDefaulter;
 class ScDocumentImport;
 
+namespace sc {
+
+struct ImportPostProcessData;
+
+}
+
 enum ScXMLDocTokens
 {
     XML_TOK_DOC_FONTDECLS,
@@ -97,7 +103,8 @@ enum ScXMLBodyTokens
     XML_TOK_BODY_DATABASE_RANGE,
     XML_TOK_BODY_DATA_PILOT_TABLES,
     XML_TOK_BODY_CONSOLIDATION,
-    XML_TOK_BODY_DDE_LINKS
+    XML_TOK_BODY_DDE_LINKS,
+    XML_TOK_BODY_DATA_STREAM_SOURCE
 };
 
 enum ScXMLContentValidationsElemTokens
@@ -733,6 +740,17 @@ enum ScXMLCellTextSAttrTokens
     XML_TOK_CELL_TEXT_S_ATTR_C
 };
 
+/**
+ * Attribute tokens for <calcext:data-stream-source>.
+ */
+enum ScXMLDataStreamAttrTokens
+{
+    XML_TOK_DATA_STREAM_ATTR_URL,
+    XML_TOK_DATA_STREAM_ATTR_RANGE,
+    XML_TOK_DATA_STREAM_ATTR_EMPTY_LINE_REFRESH,
+    XML_TOK_DATA_STREAM_ATTR_INSERTION_POSITION
+};
+
 class SvXMLTokenMap;
 class XMLShapeImportHelper;
 class ScXMLChangeTrackingImportHelper;
@@ -907,6 +925,9 @@ class ScXMLImport: public SvXMLImport, boost::noncopyable
     SvXMLTokenMap           *pCellTextSpanAttrTokenMap;
     SvXMLTokenMap           *pCellTextURLAttrTokenMap;
     SvXMLTokenMap           *pCellTextSAttrTokenMap;
+    SvXMLTokenMap           *pDataStreamAttrTokenMap;
+
+    sc::ImportPostProcessData* mpPostProcessData; /// Lift cycle managed elsewhere, no need to delete.
 
     ScMyTables              aTables;
 
@@ -1076,6 +1097,10 @@ public:
     const SvXMLTokenMap& GetCellTextSpanAttrTokenMap();
     const SvXMLTokenMap& GetCellTextURLAttrTokenMap();
     const SvXMLTokenMap& GetCellTextSAttrTokenMap();
+    const SvXMLTokenMap& GetDataStreamAttrTokenMap();
+
+    void SetPostProcessData( sc::ImportPostProcessData* p );
+    sc::ImportPostProcessData* GetPostProcessData();
 
     void AddNamedExpression(ScMyNamedExpression* pMyNamedExpression)
     {
diff --git a/sc/source/filter/xml/xmlwrap.cxx b/sc/source/filter/xml/xmlwrap.cxx
index 5b99a8c..c2ad8ec 100644
--- a/sc/source/filter/xml/xmlwrap.cxx
+++ b/sc/source/filter/xml/xmlwrap.cxx
@@ -176,6 +176,10 @@ sal_uInt32 ScXMLImportWrapper::ImportFromComponent(const uno::Reference<uno::XCo
     if (xImporter.is())
         xImporter->setTargetDocument( xComponent );
 
+    ScXMLImport* pImporterImpl = dynamic_cast<ScXMLImport*>(xImporter.get());
+    if (pImporterImpl)
+        pImporterImpl->SetPostProcessData(&maPostProcessData);
+
     // connect parser and filter
     xParser->setDocumentHandler( xDocHandler );
 
@@ -995,5 +999,10 @@ sal_Bool ScXMLImportWrapper::Export(sal_Bool bStylesOnly)
     return false;
 }
 
+const sc::ImportPostProcessData& ScXMLImportWrapper::GetImportPostProcessData() const
+{
+    return maPostProcessData;
+}
+
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/docshell/datastream.cxx b/sc/source/ui/docshell/datastream.cxx
index 1d99af2..931395d 100644
--- a/sc/source/ui/docshell/datastream.cxx
+++ b/sc/source/ui/docshell/datastream.cxx
@@ -13,25 +13,71 @@
 #include <com/sun/star/ui/XUIElement.hpp>
 #include <officecfg/Office/Common.hxx>
 #include <osl/conditn.hxx>
+#include <osl/time.h>
 #include <rtl/strbuf.hxx>
 #include <salhelper/thread.hxx>
-#include <sfx2/linkmgr.hxx>
 #include <sfx2/viewfrm.hxx>
-#include <arealink.hxx>
-#include <asciiopt.hxx>
 #include <datastreamdlg.hxx>
-#include <dbfunc.hxx>
 #include <docsh.hxx>
-#include <documentimport.hxx>
-#include <impex.hxx>
 #include <rangelst.hxx>
 #include <tabvwsh.hxx>
 #include <viewdata.hxx>
+#include <stringutil.hxx>
+#include <documentlinkmgr.hxx>
+
+#include <config_orcus.h>
+
+#if ENABLE_ORCUS
+#if defined WNT
+#define __ORCUS_STATIC_LIB
+#endif
+#include <orcus/csv_parser.hpp>
+#endif
 
 #include <queue>
 
+namespace sc {
+
+inline double getNow()
+{
+    TimeValue now;
+    osl_getSystemTime(&now);
+    return static_cast<double>(now.Seconds) + static_cast<double>(now.Nanosec) / 1000000000.0;
+}
+
 namespace datastreams {
 
+class CallerThread : public salhelper::Thread
+{
+    DataStream *mpDataStream;
+public:
+    osl::Condition maStart;
+    bool mbTerminate;
+
+    CallerThread(DataStream *pData):
+        Thread("CallerThread")
+        ,mpDataStream(pData)
+        ,mbTerminate(false)
+    {}
+
+private:
+    virtual void execute()
+    {
+        while (!mbTerminate)
+        {
+            // wait for a small amount of time, so that
+            // painting methods have a chance to be called.
+            // And also to make UI more responsive.
+            TimeValue const aTime = {0, 100000};
+            maStart.wait();
+            maStart.reset();
+            if (!mbTerminate)
+                while (mpDataStream->ImportData())
+                    wait(aTime);
+        };
+    }
+};
+
 class ReaderThread : public salhelper::Thread
 {
     SvStream *mpStream;
@@ -135,70 +181,57 @@ void DataStream::MakeToolbarVisible()
     }
 }
 
-DataStream* DataStream::Set(ScDocShell *pShell, const OUString& rURL, const OUString& rRange,
-        sal_Int32 nLimit, const OUString& rMove, sal_uInt32 nSettings)
+DataStream* DataStream::Set(
+    ScDocShell *pShell, const OUString& rURL, const ScRange& rRange,
+    sal_Int32 nLimit, MoveType eMove, sal_uInt32 nSettings)
 {
-    // Each DataStream needs a destination area in order to be exported.
-    // There can be only one ScAreaLink / DataStream per cell.
-    // So - if we don't need range (DataStream with mbValuesInLine == false),
-    // just find a free cell for now.
-    sfx2::LinkManager* pLinkManager = pShell->GetDocument()->GetLinkManager();
-    ScRange aDestArea;
-    aDestArea.Parse(rRange, pShell->GetDocument());
-    sal_uInt16 nLinkPos = 0;
-    while (nLinkPos < pLinkManager->GetLinks().size())
-    {
-        sfx2::SvBaseLink* pBase = *pLinkManager->GetLinks()[nLinkPos];
-        if (rRange.isEmpty())
-        {
-            if ( (pBase->ISA(ScAreaLink) && dynamic_cast<ScAreaLink*>
-                        (&(*pBase))->GetDestArea().aStart == aDestArea.aStart)
-                || (pBase->ISA(DataStream) && dynamic_cast<DataStream*>
-                        (&(*pBase))->GetRange().aStart == aDestArea.aStart) )
-            {
-                aDestArea.Move(0, 1, 0);
-                nLinkPos = 0;
-                continue;
-            }
-            else
-                ++nLinkPos;
-        }
-        else if ( (pBase->ISA(ScAreaLink) && dynamic_cast<ScAreaLink*>
-                    (&(*pBase))->GetDestArea().aStart == aDestArea.aStart)
-                || (pBase->ISA(DataStream) && dynamic_cast<DataStream*>
-                    (&(*pBase))->GetRange().aStart == aDestArea.aStart) )
-        {
-            pLinkManager->Remove( pBase );
-        }
-        else
-            ++nLinkPos;
-    }
+    DataStream* pLink = new DataStream(pShell, rURL, rRange, nLimit, eMove, nSettings);
+    sc::DocumentLinkManager& rMgr = pShell->GetDocument()->GetDocLinkManager();
+    rMgr.setDataStream(pLink);
+    return pLink;
+}
 
-    sfx2::SvBaseLink *pLink = 0;
-    pLink = new DataStream( pShell, rURL, rRange, nLimit, rMove, nSettings );
-    pLinkManager->InsertFileLink( *pLink, OBJECT_CLIENT_FILE, rURL, NULL, NULL );
-    return dynamic_cast<DataStream*>(pLink);
+DataStream::MoveType DataStream::ToMoveType( const OUString& rMoveStr )
+{
+    if (rMoveStr == "RANGE_DOWN")
+        return RANGE_DOWN;
+    if (rMoveStr == "MOVE_DOWN")
+        return MOVE_DOWN;
+    if (rMoveStr == "MOVE_UP")
+        return MOVE_UP;
+
+    return NO_MOVE; // default
 }
 
-DataStream::DataStream(ScDocShell *pShell, const OUString& rURL, const OUString& rRange,
-        sal_Int32 nLimit, const OUString& rMove, sal_uInt32 nSettings)
-    : mpScDocShell(pShell)
-    , mpScDocument(mpScDocShell->GetDocument())
-    , meMove(NO_MOVE)
-    , mbRunning(false)
-    , mpLines(0)
-    , mnLinesCount(0)
+DataStream::DataStream(ScDocShell *pShell, const OUString& rURL, const ScRange& rRange,
+        sal_Int32 nLimit, MoveType eMove, sal_uInt32 nSettings) :
+    mpDocShell(pShell),
+    mpDoc(mpDocShell->GetDocument()),
+    maDocAccess(*mpDoc),
+    meOrigMove(NO_MOVE),
+    meMove(NO_MOVE),
+    mbRunning(false),
+    mbValuesInLine(false),
+    mbRefreshOnEmptyLine(false),
+    mpLines(0),
+    mnLinesCount(0),
+    mnLinesSinceRefresh(0),
+    mfLastRefreshTime(0.0),
+    mnCurRow(0)
 {
-    SetRefreshHandler(LINK( this, DataStream, RefreshHdl ));
-    SetRefreshControl(mpScDocument->GetRefreshTimerControlAddress());
-    SetTimeout( 1 );
-    Decode(rURL, rRange, nLimit, rMove, nSettings);
+    mxThread = new datastreams::CallerThread( this );
+    mxThread->launch();
+
+    Decode(rURL, rRange, nLimit, eMove, nSettings);
 }
 
 DataStream::~DataStream()
 {
     if (mbRunning)
         StopImport();
+    mxThread->mbTerminate = true;
+    mxThread->maStart.set();
+    mxThread->join();
     if (mxReaderThread.is())
         mxReaderThread->endThread();
     delete mpLines;
@@ -229,40 +262,64 @@ OString DataStream::ConsumeLine()
     return mpLines->at(mnLinesCount++);
 }
 
-void DataStream::Decode(const OUString& rURL, const OUString& rRange,
-        sal_Int32 nLimit, const OUString& rMove, const sal_uInt32 nSettings)
+ScRange DataStream::GetRange() const
+{
+    ScRange aRange = maStartRange;
+    aRange.aEnd = maEndRange.aEnd;
+    return aRange;
+}
+
+bool DataStream::IsRefreshOnEmptyLine() const
+{
+    return mbRefreshOnEmptyLine;
+}
+
+DataStream::MoveType DataStream::GetMove() const
+{
+    return meOrigMove;
+}
+
+void DataStream::Decode(const OUString& rURL, const ScRange& rRange,
+        sal_Int32 nLimit, MoveType eMove, const sal_uInt32 nSettings)
 {
     msURL = rURL;
-    msRange = rRange;
     mnLimit = nLimit;
-    msMove = rMove;
+    meMove = eMove;
+    meOrigMove = eMove;
     mnSettings = nSettings;
-    mpEndRange.reset( NULL );
-
-    mbValuesInLine = mnSettings & VALUES_IN_LINE;
-
-    if (msMove == "NO_MOVE")
-        meMove = NO_MOVE;
-    else if (msMove == "RANGE_DOWN")
-        meMove = RANGE_DOWN;
-    else if (msMove == "MOVE_DOWN")
-        meMove = MOVE_DOWN;
-
-    maRange.Parse(msRange);
-    maStartRange = maRange;
-    sal_Int32 nHeight = maRange.aEnd.Row() - maRange.aStart.Row() + 1;
-    nLimit = nHeight * (nLimit / nHeight);
-    if (nLimit && maRange.aStart.Row() + nLimit - 1 < MAXROW)
+
+    mbValuesInLine = true; // always true.
+
+    mnCurRow = rRange.aStart.Row();
+
+    ScRange aRange = rRange;
+    if (aRange.aStart.Row() != aRange.aEnd.Row())
+        // We only allow this range to be one row tall.
+        aRange.aEnd.SetRow(aRange.aStart.Row());
+
+    maStartRange = aRange;
+    maEndRange = aRange;
+    if (nLimit == 0)
     {
-        mpEndRange.reset( new ScRange(maRange) );
-        mpEndRange->Move(0, nLimit - nHeight, 0);
+        // Unlimited
+        maEndRange.aStart.SetRow(MAXROW);
     }
+    else if (nLimit > 0)
+    {
+        // Limited.
+        maEndRange.aStart.IncRow(nLimit-1);
+        if (maEndRange.aStart.Row() > MAXROW)
+            maEndRange.aStart.SetRow(MAXROW);
+    }
+
+    maEndRange.aEnd.SetRow(maEndRange.aStart.Row());
 }
 
 void DataStream::StartImport()
 {
     if (mbRunning)
         return;
+
     if (!mxReaderThread.is())
     {
         SvStream *pStream = 0;
@@ -274,15 +331,32 @@ void DataStream::StartImport()
         mxReaderThread->launch();
     }
     mbRunning = true;
-    AutoTimer::Start();
+    maDocAccess.reset();
+    mxThread->maStart.set();
 }
 
 void DataStream::StopImport()
 {
     if (!mbRunning)
         return;
+
     mbRunning = false;
-    AutoTimer::Stop();
+    Refresh();
+}
+
+void DataStream::SetRefreshOnEmptyLine( bool bVal )
+{
+    mbRefreshOnEmptyLine = bVal;
+}
+
+void DataStream::Refresh()
+{
+    // Hard recalc will repaint the grid area.
+    mpDocShell->DoHardRecalc(true);
+    mpDocShell->SetDocumentModified(true);
+
+    mfLastRefreshTime = getNow();
+    mnLinesSinceRefresh = 0;
 }
 
 void DataStream::MoveData()
@@ -290,185 +364,166 @@ void DataStream::MoveData()
     switch (meMove)
     {
         case RANGE_DOWN:
-            if (maRange.aStart == mpEndRange->aStart)
+        {
+            if (mnCurRow == maEndRange.aStart.Row())
                 meMove = MOVE_UP;
-            break;
+        }
+        break;
         case MOVE_UP:
-            mpScDocument->DeleteRow(maStartRange);
-            mpScDocument->InsertRow(*mpEndRange);
-            break;
+        {
+            // Remove the top row and shift the remaining rows upward. Then
+            // insert a new row at the end row position.
+            ScRange aRange = maStartRange;
+            aRange.aEnd = maEndRange.aEnd;
+            maDocAccess.shiftRangeUp(aRange);
+        }
+        break;
         case MOVE_DOWN:
-            if (mpEndRange.get())
-                mpScDocument->DeleteRow(*mpEndRange);
-            mpScDocument->InsertRow(maRange);
-            break;
+        {
+            // Remove the end row and shift the remaining rows downward by
+            // inserting a new row at the top row.
+            ScRange aRange = maStartRange;
+            aRange.aEnd = maEndRange.aEnd;
+            maDocAccess.shiftRangeDown(aRange);
+        }
+        break;
         case NO_MOVE:
-            break;
+        default:
+            ;
     }
 }
 
-IMPL_LINK_NOARG(DataStream, RefreshHdl)
+#if ENABLE_ORCUS
+
+namespace {
+
+struct StrVal
 {
-    ImportData();
-    return 0;
-}
+    ScAddress maPos;
+    OUString maStr;
 
-//  lcl_ScanString and Text2Doc is simplified version
-//  of code from sc/source/ui/docshell/impex.cxx
-const sal_Unicode* lcl_ScanString( const sal_Unicode* p, OUString& rString, sal_Unicode cStr)
+    StrVal( const ScAddress& rPos, const OUString& rStr ) : maPos(rPos), maStr(rStr) {}
+};
+
+struct NumVal
 {
-    const sal_Unicode* p0 = p;
-    for( ;; )
+    ScAddress maPos;
+    double mfVal;
+
+    NumVal( const ScAddress& rPos, double fVal ) : maPos(rPos), mfVal(fVal) {}
+};
+
+typedef std::vector<StrVal> StrValArray;
+typedef std::vector<NumVal> NumValArray;
+
+/**
+ * This handler handles a single line CSV input.
+ */
+class CSVHandler
+{
+    ScAddress maPos;
+    SCROW mnRow;
+    SCCOL mnCol;
+    SCCOL mnEndCol;
+    SCTAB mnTab;
+
+    StrValArray maStrs;
+    NumValArray maNums;
+
+public:
+    CSVHandler( const ScAddress& rPos, SCCOL nEndCol ) : maPos(rPos), mnEndCol(nEndCol) {}
+
+    void begin_parse() {}
+    void end_parse() {}
+    void begin_row() {}
+    void end_row() {}
+
+    void cell(const char* p, size_t n)
     {
-        if (!*p)
-            break;
-        if (*p == cStr)
+        if (maPos.Col() <= mnEndCol)
         {
-            if (*++p != cStr)
-                break;
-            p++;
+            OUString aStr(p, n, RTL_TEXTENCODING_UTF8);
+            double fVal;
+            if (ScStringUtil::parseSimpleNumber(aStr, '.', ',', fVal))
+                maNums.push_back(NumVal(maPos, fVal));
+            else
+                maStrs.push_back(StrVal(maPos, aStr));
         }
-        else
-            p++;
+        maPos.IncCol();
     }
-    if (p0 < p)
-        if (rString.getLength() + (p - p0) <= STRING_MAXLEN)
-            rString += OUString( p0, sal::static_int_cast<sal_Int32>( p - p0 ) );
-    return p;
+
+    const StrValArray& getStrs() const { return maStrs; }
+    const NumValArray& getNums() const { return maNums; }
+};
+
 }
 
 void DataStream::Text2Doc()
 {
-    sal_Unicode cSep(',');
-    sal_Unicode cStr('"');
-    SCCOL nStartCol = maRange.aStart.Col();
-    SCROW nStartRow = maRange.aStart.Row();
-    SCCOL nEndCol = maRange.aEnd.Col();
-    SCROW nEndRow = maRange.aEnd.Row();
-    OUString aCell;
-    SCROW nRow = nStartRow;
-    ScDocumentImport aDocImport(*mpScDocument);
-    while (nRow <= nEndRow)
+    OString aLine = ConsumeLine();
+    orcus::csv_parser_config aConfig;
+    aConfig.delimiters.push_back(',');
+    aConfig.text_qualifier = '"';
+    CSVHandler aHdl(ScAddress(maStartRange.aStart.Col(), mnCurRow, maStartRange.aStart.Tab()), maStartRange.aEnd.Col());
+    orcus::csv_parser<CSVHandler> parser(aLine.getStr(), aLine.getLength(), aHdl, aConfig);
+    parser.parse();
+
+    const StrValArray& rStrs = aHdl.getStrs();
+    const NumValArray& rNums = aHdl.getNums();
+    if (rStrs.empty() && rNums.empty() && mbRefreshOnEmptyLine)
     {
-        SCCOL nCol = nStartCol;
-        OUString sLine( OStringToOUString(ConsumeLine(), RTL_TEXTENCODING_UTF8) );
-        const sal_Unicode* p = sLine.getStr();
-        while (*p)
-        {
-            aCell = "";
-            const sal_Unicode* q = p;
-            while (*p && *p != cSep)
-            {
-                // Always look for a pairing quote and ignore separator in between.
-                while (*p && *p == cStr)
-                    q = p = lcl_ScanString(p, aCell, cStr);
-                // All until next separator or quote.
-                while (*p && *p != cSep && *p != cStr)
-                    ++p;
-                if (aCell.getLength() + (p - q) <= STRING_MAXLEN)
-                    aCell += OUString( q, sal::static_int_cast<sal_Int32>( p - q ) );
-                q = p;
-            }
-            if (*p)
-                ++p;
-            if (nCol <= nEndCol && nRow <= nEndRow)
-            {
-                ScAddress aAddress(nCol, nRow, maRange.aStart.Tab());
-                if (aCell == "0" || ( aCell.indexOf(':') == -1 && aCell.toDouble() ))
-                    aDocImport.setNumericCell(aAddress, aCell.toDouble());
-                else
-                    aDocImport.setStringCell(aAddress, aCell);
-            }
-            ++nCol;
-        }
-        ++nRow;
+        // Empty line detected.  Trigger refresh and discard it.
+        Refresh();
+        return;
     }
-    aDocImport.finalize();
-    mpScDocShell->PostPaint( maRange, PAINT_GRID );
-}
 
-bool DataStream::ImportData()
-{
     MoveData();
-    if (mbValuesInLine)
     {
-        // do CSV import
-        Text2Doc();
+        StrValArray::const_iterator it = rStrs.begin(), itEnd = rStrs.end();
+        for (; it != itEnd; ++it)
+            maDocAccess.setStringCell(it->maPos, it->maStr);
     }
-    else
+
     {
-        ScRangeList aRangeList;
-        ScDocumentImport aDocImport(*mpScDocument);
-        // read more lines at once but not too much
-        for (int i = 0; i < 10; ++i)
-        {
-            OUString sLine( OStringToOUString(ConsumeLine(), RTL_TEXTENCODING_UTF8) );
-            if (sLine.indexOf(',') <= 0)
-                continue;
-
-            OUString sAddress( sLine.copy(0, sLine.indexOf(',')) );
-            OUString sValue( sLine.copy(sLine.indexOf(',') + 1) );
-            ScAddress aAddress;
-            aAddress.Parse(sAddress, mpScDocument);
-            if (!aAddress.IsValid())
-                continue;
-
-            if (sValue == "0" || ( sValue.indexOf(':') == -1 && sValue.toDouble() ))
-                aDocImport.setNumericCell(aAddress, sValue.toDouble());
-            else
-                aDocImport.setStringCell(aAddress, sValue);
-            aRangeList.Join(aAddress);
-        }
-        aDocImport.finalize();
-        mpScDocShell->PostPaint( aRangeList, PAINT_GRID );
+        NumValArray::const_iterator it = rNums.begin(), itEnd = rNums.end();
+        for (; it != itEnd; ++it)
+            maDocAccess.setNumericCell(it->maPos, it->mfVal);
     }
+
     if (meMove == NO_MOVE)
-        return mbRunning;
+        return;
 
     if (meMove == RANGE_DOWN)
-    {
-        maRange.Move(0, maRange.aEnd.Row() - maRange.aStart.Row() + 1, 0);
-        mpScDocShell->GetViewData()->GetView()->AlignToCursor(
-                maRange.aStart.Col(), maRange.aStart.Row(), SC_FOLLOW_JUMP);
-    }
-    SCROW aEndRow = mpEndRange.get() ? mpEndRange->aEnd.Row() : MAXROW;
-    mpScDocShell->PostPaint( ScRange( maStartRange.aStart, ScAddress( maRange.aEnd.Col(),
-                    aEndRow, maRange.aStart.Tab()) ), PAINT_GRID );
+        ++mnCurRow;
 
-    return mbRunning;
-}
+    if (getNow() - mfLastRefreshTime > 0.1 && mnLinesSinceRefresh > 200)
+        // Refresh no more frequently than every 0.1 second, and wait until at
+        // least we have processed 200 lines.
+        Refresh();
 
-sfx2::SvBaseLink::UpdateResult DataStream::DataChanged(
-        const OUString& , const css::uno::Any& )
-{
-    MakeToolbarVisible();
-    StopImport();
-    bool bStart = true;
-    if (mnSettings & SCRIPT_STREAM && !mxReaderThread.is() &&
-        officecfg::Office::Common::Security::Scripting::MacroSecurityLevel::get() >= 1)
-    {
-        MessageDialog aQBox( NULL, "QueryRunStreamScriptDialog", "modules/scalc/ui/queryrunstreamscriptdialog.ui");
-        aQBox.set_primary_text( aQBox.get_primary_text().replaceFirst("%URL", msURL) );
-        if (RET_YES != aQBox.Execute())
-            bStart = false;
-    }
-    if (bStart)
-        StartImport();
-    return SUCCESS;
+    ++mnLinesSinceRefresh;
 }
 
-void DataStream::Edit(Window* pWindow, const Link& )
+#else
+
+void DataStream::Text2Doc() {}
+
+#endif
+
+bool DataStream::ImportData()
 {
-    DataStreamDlg aDialog(mpScDocShell, pWindow);
-    aDialog.Init(msURL, msRange, mnLimit, msMove, mnSettings);
-    if (aDialog.Execute() == RET_OK)
-    {
-        bool bWasRunning = mbRunning;
-        StopImport();
-        aDialog.StartStream(this);
-        if (bWasRunning)
-            StartImport();
-    }
+    SolarMutexGuard aGuard;
+    if (!mbValuesInLine)
+        // We no longer support this mode. To be deleted later.
+        return false;
+
+    if (ScDocShell::GetViewData()->GetViewShell()->NeedsRepaint())
+        return mbRunning;
+
+    Text2Doc();
+    return mbRunning;
 }
 
+} // namespace sc
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/docshell/docsh.cxx b/sc/source/ui/docshell/docsh.cxx
index 1904f1b..b4cf615 100644
--- a/sc/source/ui/docshell/docsh.cxx
+++ b/sc/source/ui/docshell/docsh.cxx
@@ -119,6 +119,8 @@
 #include "dpobject.hxx"
 #include "markdata.hxx"
 #include "orcusfilters.hxx"
+#include <datastream.hxx>
+#include <documentlinkmgr.hxx>
 
 #include <config_telepathy.h>
 
@@ -400,6 +402,36 @@ private:
     ScDocument* mpDoc;
 };
 
+void processDataStream( ScDocShell& rShell, const sc::ImportPostProcessData& rData )
+{
+    if (!rData.mpDataStream)
+        return;
+
+    const sc::ImportPostProcessData::DataStream& r = *rData.mpDataStream;
+    if (!r.maRange.IsValid())
+        return;
+
+    // Break the streamed range into the top range and the height limit.  A
+    // height limit of 0 means unlimited i.e. the streamed data will go all
+    // the way to the last row.
+
+    ScRange aTopRange = r.maRange;
+    aTopRange.aEnd.SetRow(aTopRange.aStart.Row());
+    sal_Int32 nLimit = r.maRange.aEnd.Row() - r.maRange.aStart.Row() + 1;
+    if (r.maRange.aEnd.Row() == MAXROW)
+        // Unlimited range.
+        nLimit = 0;
+
+    sc::DataStream::MoveType eMove =
+        r.meInsertPos == sc::ImportPostProcessData::DataStream::InsertTop ?
+        sc::DataStream::MOVE_DOWN : sc::DataStream::RANGE_DOWN;
+
+    sc::DataStream* pStrm = new sc::DataStream(&rShell, r.maURL, aTopRange, nLimit, eMove, 0);
+    pStrm->SetRefreshOnEmptyLine(r.mbRefreshOnEmpty);
+    sc::DocumentLinkManager& rMgr = rShell.GetDocument()->GetDocLinkManager();
+    rMgr.setDataStream(pStrm);
+}
+
 }
 
 sal_Bool ScDocShell::LoadXML( SfxMedium* pLoadMedium, const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage >& xStor )
@@ -430,6 +462,8 @@ sal_Bool ScDocShell::LoadXML( SfxMedium* pLoadMedium, const ::com::sun::star::un
     if ( nError )
         pLoadMedium->SetError( nError, OUString( OSL_LOG_PREFIX ) );
 
+    processDataStream(*this, aImport.GetImportPostProcessData());
+
     //if the document was not generated by LibreOffice, do hard recalc in case some other document
     //generator saved cached formula results that differ from LibreOffice's calculated results or
     //did not use cached formula results.
diff --git a/sc/source/ui/docshell/documentlinkmgr.cxx b/sc/source/ui/docshell/documentlinkmgr.cxx
new file mode 100644
index 0000000..2b9998f
--- /dev/null
+++ b/sc/source/ui/docshell/documentlinkmgr.cxx
@@ -0,0 +1,44 @@
+/* -*- 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 <documentlinkmgr.hxx>
+#include <datastream.hxx>
+
+#include <boost/noncopyable.hpp>
+#include <boost/scoped_ptr.hpp>
+
+namespace sc {
+
+struct DocumentLinkManagerImpl : boost::noncopyable
+{
+    boost::scoped_ptr<DataStream> mpDataStream;
+
+    DocumentLinkManagerImpl() : mpDataStream(NULL) {}
+};
+
+DocumentLinkManager::DocumentLinkManager() : mpImpl(new DocumentLinkManagerImpl) {}
+
+void DocumentLinkManager::setDataStream( DataStream* p )
+{
+    mpImpl->mpDataStream.reset(p);
+}
+
+DataStream* DocumentLinkManager::getDataStream()
+{
+    return mpImpl->mpDataStream.get();
+}
+
+const DataStream* DocumentLinkManager::getDataStream() const
+{
+    return mpImpl->mpDataStream.get();
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/inc/datastream.hxx b/sc/source/ui/inc/datastream.hxx
index 6eb1e7d..5a4d8cd 100644
--- a/sc/source/ui/inc/datastream.hxx
+++ b/sc/source/ui/inc/datastream.hxx
@@ -7,78 +7,101 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
  */
 
+#ifndef SC_DATASTREAM_HXX
+#define SC_DATASTREAM_HXX
+
 #include <sal/config.h>
 
 #include <rtl/ref.hxx>
 #include <rtl/ustring.hxx>
-#include <sfx2/lnkbase.hxx>
 #include <address.hxx>
-#include <refreshtimer.hxx>
 
 #include <boost/noncopyable.hpp>
 #include <boost/scoped_ptr.hpp>
 #include <vector>
 
-namespace datastreams {
-    class ReaderThread;
-}
+#include <documentstreamaccess.hxx>
+
 class ScDocShell;
 class ScDocument;
 class Window;
 
+namespace sc {
+
+namespace datastreams {
+    class CallerThread;
+    class ReaderThread;
+}
+
 typedef std::vector<OString> LinesList;
 
-class DataStream : boost::noncopyable, public sfx2::SvBaseLink, ScRefreshTimer
+class DataStream : boost::noncopyable
 {
     OString ConsumeLine();
     void MoveData();
     void Text2Doc();
-    DECL_LINK( RefreshHdl, void* );
 
 public:
-    enum MoveEnum { NO_MOVE, RANGE_DOWN, MOVE_DOWN, MOVE_UP };
+    enum MoveType { NO_MOVE, RANGE_DOWN, MOVE_DOWN, MOVE_UP };
     enum { SCRIPT_STREAM = 1, VALUES_IN_LINE = 2 };
 
     static void MakeToolbarVisible();
-    static DataStream* Set(ScDocShell *pShell, const OUString& rURL, const OUString& rRange,
-            sal_Int32 nLimit, const OUString& rMove, sal_uInt32 nSettings);
-
-    DataStream(ScDocShell *pShell, const OUString& rURL, const OUString& rRange,
-            sal_Int32 nLimit, const OUString& rMove, sal_uInt32 nSettings);
-    virtual ~DataStream();
-    // sfx2::SvBaseLink
-    virtual sfx2::SvBaseLink::UpdateResult DataChanged(
-            const OUString& , const css::uno::Any& ) SAL_OVERRIDE;
-    virtual void Edit(Window* , const Link& ) SAL_OVERRIDE;
-
-    const ScRange& GetRange() const { return maRange; }
+    static DataStream* Set(ScDocShell *pShell, const OUString& rURL, const ScRange& rRange,
+            sal_Int32 nLimit, MoveType eMove, sal_uInt32 nSettings);
+
+    static MoveType ToMoveType( const OUString& rMoveStr );
+
+    DataStream(
+        ScDocShell *pShell, const OUString& rURL, const ScRange& rRange,
+        sal_Int32 nLimit, MoveType eMove, sal_uInt32 nSettings);
+
+    ~DataStream();
+
+    ScRange GetRange() const;
     const OUString& GetURL() const { return msURL; }
     const sal_Int32& GetLimit() const { return mnLimit; }
-    const OUString& GetMove() const { return msMove; }
+    MoveType GetMove() const;
     const sal_uInt32& GetSettings() const { return mnSettings; }
-    void Decode(const OUString& rURL, const OUString& rRange, sal_Int32 nLimit,
-            const OUString& rMove, const sal_uInt32 nSettings);
+    bool IsRefreshOnEmptyLine() const;
+
+    void Decode(
+        const OUString& rURL, const ScRange& rRange, sal_Int32 nLimit,
+        MoveType eMove, const sal_uInt32 nSettings);
+
     bool ImportData();
     void StartImport();
     void StopImport();
 
+    void SetRefreshOnEmptyLine( bool bVal );
+
 private:
-    ScDocShell *mpScDocShell;
-    ScDocument *mpScDocument;
+    void Refresh();
+
+private:
+    ScDocShell* mpDocShell;
+    ScDocument* mpDoc;
+    DocumentStreamAccess maDocAccess;
     OUString msURL;
-    OUString msRange;
-    OUString msMove;
     sal_Int32 mnLimit;
     sal_uInt32 mnSettings;
-    MoveEnum meMove;
+    MoveType meOrigMove; // Initial move setting. This one gets saved to file.
+    MoveType meMove; // move setting during streaming, which may change in the middle.
     bool mbRunning;
     bool mbValuesInLine;
-    LinesList *mpLines;
+    bool mbRefreshOnEmptyLine;
+    LinesList* mpLines;
     size_t mnLinesCount;
-    ScRange maRange;
+    size_t mnLinesSinceRefresh;
+    double mfLastRefreshTime;
+    SCROW mnCurRow;
     ScRange maStartRange;
-    boost::scoped_ptr<ScRange> mpEndRange;
+    ScRange maEndRange;
+    rtl::Reference<datastreams::CallerThread> mxThread;
     rtl::Reference<datastreams::ReaderThread> mxReaderThread;
 };
 
+}
+
+#endif
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/inc/datastreamdlg.hxx b/sc/source/ui/inc/datastreamdlg.hxx
index 162a0d6..851afef 100644
--- a/sc/source/ui/inc/datastreamdlg.hxx
+++ b/sc/source/ui/inc/datastreamdlg.hxx
@@ -13,9 +13,13 @@
 #include <vcl/dialog.hxx>
 #include <vcl/layout.hxx>
 
-class DataStream;
+#include <datastream.hxx>
+
 class ScDocShell;
 class SvtURLBox;
+class ScRange;
+
+namespace sc {
 
 class DataStreamDlg : public ModalDialog
 {
@@ -23,13 +27,16 @@ class DataStreamDlg : public ModalDialog
 
     SvtURLBox*      m_pCbUrl;
     PushButton*     m_pBtnBrowse;
+    RadioButton*    m_pRBDirectData;
     RadioButton*    m_pRBScriptData;
     RadioButton*    m_pRBValuesInLine;
     RadioButton*    m_pRBAddressValue;
+    CheckBox*       m_pCBRefreshOnEmpty;
     RadioButton*    m_pRBDataDown;
     RadioButton*    m_pRBRangeDown;
     RadioButton*    m_pRBNoMove;
     RadioButton*    m_pRBMaxLimit;
+    RadioButton*    m_pRBUnlimited;
     Edit*           m_pEdRange;
     Edit*           m_pEdLimit;
     OKButton*       m_pBtnOk;
@@ -40,13 +47,16 @@ class DataStreamDlg : public ModalDialog
     DECL_LINK(BrowseHdl, void *);
 
     void UpdateEnable();
+    ScRange GetStartRange();
 
 public:
     DataStreamDlg(ScDocShell *pDocShell, Window* pParent);
-    ~DataStreamDlg() {}
-    void Init(const OUString& rURL, const OUString& rRange, const sal_Int32 nLimit,
-            const OUString& rMove, const sal_uInt32 nSettings);
-    void StartStream(DataStream *pStream = 0);
+
+    void Init( const DataStream& rStrm );
+
+    void StartStream();
 };
 
+}
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/inc/gridwin.hxx b/sc/source/ui/inc/gridwin.hxx
index 8755da8..5ac059c 100644
--- a/sc/source/ui/inc/gridwin.hxx
+++ b/sc/source/ui/inc/gridwin.hxx
@@ -373,6 +373,7 @@ public:
 
     void            StopMarking();
     void            UpdateInputContext();
+    bool            NeedsRepaint() { return bNeedsRepaint; }
 
     void            CheckInverted()     { if (nPaintCount) bNeedsRepaint = true; }
 
diff --git a/sc/source/ui/inc/tabview.hxx b/sc/source/ui/inc/tabview.hxx
index 4964e6d..e13d088 100644
--- a/sc/source/ui/inc/tabview.hxx
+++ b/sc/source/ui/inc/tabview.hxx
@@ -437,6 +437,7 @@ public:
     void            UpdateFormulas();
     void            InterpretVisible();
     void            CheckNeedsRepaint();
+    bool            NeedsRepaint();
 
     void            PaintRangeFinder( long nNumber = -1 );
     void            AddHighlightRange( const ScRange& rRange, const Color& rColor );
diff --git a/sc/source/ui/miscdlgs/datastreamdlg.cxx b/sc/source/ui/miscdlgs/datastreamdlg.cxx
index a6d0a92..8a3bee5 100644
--- a/sc/source/ui/miscdlgs/datastreamdlg.cxx
+++ b/sc/source/ui/miscdlgs/datastreamdlg.cxx
@@ -12,7 +12,10 @@
 #include <sfx2/filedlghelper.hxx>
 #include <svtools/inettbc.hxx>
 #include <vcl/layout.hxx>
-#include <datastream.hxx>
+#include <address.hxx>
+#include <docsh.hxx>
+
+namespace sc {
 
 DataStreamDlg::DataStreamDlg(ScDocShell *pDocShell, Window* pParent)
     : ModalDialog(pParent, "DataStreamDialog", "modules/scalc/ui/datastreams.ui")
@@ -20,13 +23,16 @@ DataStreamDlg::DataStreamDlg(ScDocShell *pDocShell, Window* pParent)
 {
     get(m_pCbUrl, "url");
     get(m_pBtnBrowse, "browse");
+    get(m_pRBDirectData, "directdata");
     get(m_pRBScriptData, "scriptdata");
     get(m_pRBValuesInLine, "valuesinline");
     get(m_pRBAddressValue, "addressvalue");
+    get(m_pCBRefreshOnEmpty, "refresh_ui");
     get(m_pRBDataDown, "datadown");
     get(m_pRBRangeDown, "rangedown");
     get(m_pRBNoMove, "nomove");
     get(m_pRBMaxLimit, "maxlimit");
+    get(m_pRBUnlimited, "unlimited");
     get(m_pEdRange, "range");
     get(m_pEdLimit, "limit");
     get(m_pBtnOk, "ok");
@@ -35,6 +41,11 @@ DataStreamDlg::DataStreamDlg(ScDocShell *pDocShell, Window* pParent)
 
     m_pCbUrl->SetSelectHdl( LINK( this, DataStreamDlg, UpdateHdl ) );
     m_pRBAddressValue->SetClickHdl( LINK( this, DataStreamDlg, UpdateHdl ) );
+    m_pRBAddressValue->Enable(false);
+    m_pRBScriptData->Enable(false);
+    m_pRBDirectData->Hide();
+    m_pRBScriptData->Hide();
+    m_pRBNoMove->Hide();
     m_pRBValuesInLine->SetClickHdl( LINK( this, DataStreamDlg, UpdateHdl ) );
     m_pEdRange->SetModifyHdl( LINK( this, DataStreamDlg, UpdateHdl ) );
     m_pBtnBrowse->SetClickHdl( LINK( this, DataStreamDlg, BrowseHdl ) );
@@ -63,7 +74,6 @@ void DataStreamDlg::UpdateEnable()
     bool bOk = !m_pCbUrl->GetURL().isEmpty();
     if (m_pRBAddressValue->IsChecked())
     {
-        m_pRBNoMove->Check();
         m_pVclFrameLimit->Disable();
         m_pVclFrameMove->Disable();
         m_pEdRange->Disable();
@@ -73,33 +83,85 @@ void DataStreamDlg::UpdateEnable()
         m_pVclFrameLimit->Enable();
         m_pVclFrameMove->Enable();
         m_pEdRange->Enable();
-        bOk = bOk && !m_pEdRange->GetText().isEmpty();
+        if (bOk)
+        {
+            // Check the given range to make sure it's valid.
+            ScRange aTest = GetStartRange();
+            if (!aTest.IsValid())
+                bOk = false;
+        }
     }
     m_pBtnOk->Enable(bOk);
     setOptimalLayoutSize();
 }
 
-void DataStreamDlg::Init(const OUString& rURL, const OUString& rRange, const sal_Int32 nLimit,
-        const OUString& rMove, const sal_uInt32 nSettings)
+ScRange DataStreamDlg::GetStartRange()
+{
+    OUString aStr = m_pEdRange->GetText();
+    ScDocument* pDoc = mpDocShell->GetDocument();
+    ScRange aRange;
+    sal_uInt16 nRes = aRange.Parse(aStr, pDoc);
+    if ((nRes & SCA_VALID) != SCA_VALID || !aRange.IsValid())
+    {
+        // Invalid range.
+        aRange.SetInvalid();
+        return aRange;
+    }
+
+    // Make sure it's only one row tall.
+    if (aRange.aStart.Row() != aRange.aEnd.Row())
+        aRange.SetInvalid();
+
+    return aRange;
+}
+
+void DataStreamDlg::Init( const DataStream& rStrm )
 {
-    m_pEdLimit->SetText(OUString::number(nLimit));
-    m_pCbUrl->SetText(rURL);
-    if (nSettings & DataStream::SCRIPT_STREAM)
-        m_pRBScriptData->Check();
-    if (!(nSettings & DataStream::VALUES_IN_LINE))
-        m_pRBAddressValue->Check();
-    m_pEdRange->SetText(rRange);
-    if (rMove == "NO_MOVE")
-        m_pRBNoMove->Check();
-    else if (rMove == "RANGE_DOWN")
-        m_pRBRangeDown->Check();
-    else if (rMove == "MOVE_DOWN")
-        m_pRBDataDown->Check();
+    m_pCbUrl->SetText(rStrm.GetURL());
+
+    ScRange aRange = rStrm.GetRange();
+    ScRange aTopRange = aRange;
+    aTopRange.aEnd.SetRow(aTopRange.aStart.Row());
+    OUString aStr = aTopRange.Format(SCA_VALID);
+    m_pEdRange->SetText(aStr);
+    SCROW nRows = aRange.aEnd.Row() - aRange.aStart.Row() + 1;
+
+    if (aRange.aEnd.Row() == MAXROW)
+        m_pRBUnlimited->Check();
+    else
+    {
+        m_pRBMaxLimit->Check();
+        m_pEdLimit->SetText(OUString::number(nRows));
+    }
+
+    DataStream::MoveType eMove = rStrm.GetMove();
+    switch (eMove)
+    {
+        case DataStream::MOVE_DOWN:
+            m_pRBDataDown->Check();
+        break;
+        break;
+        case DataStream::RANGE_DOWN:
+            m_pRBRangeDown->Check();
+        break;
+        case DataStream::MOVE_UP:
+        case DataStream::NO_MOVE:
+        default:
+            ;
+    }
+
+    m_pCBRefreshOnEmpty->Check(rStrm.IsRefreshOnEmptyLine());
+
     UpdateEnable();
 }
 
-void DataStreamDlg::StartStream(DataStream *pStream)
+void DataStreamDlg::StartStream()
 {
+    ScRange aStartRange = GetStartRange();
+    if (!aStartRange.IsValid())
+        // Don't start the stream without a valid range.
+        return;
+
     sal_Int32 nLimit = 0;
     if (m_pRBMaxLimit->IsChecked())
         nLimit = m_pEdLimit->GetText().toInt32();
@@ -109,24 +171,16 @@ void DataStreamDlg::StartStream(DataStream *pStream)
        nSettings |= DataStream::SCRIPT_STREAM;
     if (m_pRBValuesInLine->IsChecked())
        nSettings |= DataStream::VALUES_IN_LINE;
-    if (pStream)
-    {
-        pStream->Decode(rURL, m_pEdRange->GetText(), nLimit,
-                m_pRBNoMove->IsChecked() ? OUString("NO_MOVE") : m_pRBRangeDown->IsChecked()
-                    ? OUString("RANGE_DOWN") : OUString("MOVE_DOWN"),
-                nSettings);
-        return;
-    }
-    pStream = DataStream::Set( mpDocShell,
-            rURL,
-            m_pEdRange->GetText(),
-            nLimit,
-            m_pRBNoMove->IsChecked() ? OUString("NO_MOVE") : m_pRBRangeDown->IsChecked()
-                ? OUString("RANGE_DOWN") : OUString("MOVE_DOWN")
-            , nSettings
-            );
+
+    DataStream::MoveType eMove =
+        m_pRBRangeDown->IsChecked() ? DataStream::RANGE_DOWN : DataStream::MOVE_DOWN;
+
+    DataStream* pStream = DataStream::Set(mpDocShell, rURL, aStartRange, nLimit, eMove, nSettings);
+    pStream->SetRefreshOnEmptyLine(m_pCBRefreshOnEmpty->IsChecked());
     DataStream::MakeToolbarVisible();
     pStream->StartImport();
 }
 
+}
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/view/cellsh2.cxx b/sc/source/ui/view/cellsh2.cxx
index 5a0720c..a93761c 100644
--- a/sc/source/ui/view/cellsh2.cxx
+++ b/sc/source/ui/view/cellsh2.cxx
@@ -20,7 +20,6 @@
 #include "scitems.hxx"
 #include <sfx2/viewfrm.hxx>
 #include <sfx2/app.hxx>
-#include <sfx2/linkmgr.hxx>
 #include <sfx2/request.hxx>
 #include <svl/aeitem.hxx>
 #include <basic/sbxcore.hxx>
@@ -62,6 +61,7 @@
 #include "datastreamdlg.hxx"
 #include "queryentry.hxx"
 #include "markdata.hxx"
+#include <documentlinkmgr.hxx>
 
 #include <config_orcus.h>
 
@@ -742,36 +742,36 @@ void ScCellShell::ExecuteDB( SfxRequest& rReq )
             }
             break;
         case SID_DATA_STREAMS:
-            {
-                DataStreamDlg aDialog( GetViewData()->GetDocShell(), pTabViewShell->GetDialogParent() );
-                if (aDialog.Execute() == RET_OK)
-                    aDialog.StartStream();
-            }
-            break;
+        {
+            sc::DataStreamDlg aDialog( GetViewData()->GetDocShell(), pTabViewShell->GetDialogParent() );
+            ScDocument *pDoc = GetViewData()->GetDocument();
+            sc::DocumentLinkManager& rMgr = pDoc->GetDocLinkManager();
+            sc::DataStream* pStrm = rMgr.getDataStream();
+            if (pStrm)
+                aDialog.Init(*pStrm);
+
+            if (aDialog.Execute() == RET_OK)
+                aDialog.StartStream();
+        }
+        break;
         case SID_DATA_STREAMS_PLAY:
-            {
-                ScDocument *pDoc = GetViewData()->GetDocument();
-                if (pDoc->GetLinkManager())
-                {
-                    const sfx2::SvBaseLinks& rLinks = pDoc->GetLinkManager()->GetLinks();
-                    for (size_t i = 0; i < rLinks.size(); i++)
-                        if (DataStream *pStream = dynamic_cast<DataStream*>(&(*(*rLinks[i]))))
-                            pStream->StartImport();
-                }
-            }
-            break;
+        {
+            ScDocument *pDoc = GetViewData()->GetDocument();
+            sc::DocumentLinkManager& rMgr = pDoc->GetDocLinkManager();
+            sc::DataStream* pStrm = rMgr.getDataStream();
+            if (pStrm)
+                pStrm->StartImport();
+        }
+        break;
         case SID_DATA_STREAMS_STOP:
-            {
-                ScDocument *pDoc = GetViewData()->GetDocument();
-                if (pDoc->GetLinkManager())
-                {
-                    const sfx2::SvBaseLinks& rLinks = pDoc->GetLinkManager()->GetLinks();
-                    for (size_t i = 0; i < rLinks.size(); i++)
-                        if (DataStream *pStream = dynamic_cast<DataStream*>(&(*(*rLinks[i]))))
-                            pStream->StopImport();
-                }
-            }
-            break;
+        {
+            ScDocument *pDoc = GetViewData()->GetDocument();
+            sc::DocumentLinkManager& rMgr = pDoc->GetDocLinkManager();
+            sc::DataStream* pStrm = rMgr.getDataStream();
+            if (pStrm)
+                pStrm->StopImport();
+        }
+        break;
         case SID_MANAGE_XML_SOURCE:
             ExecuteXMLSourceDialog();
         break;
diff --git a/sc/source/ui/view/tabview3.cxx b/sc/source/ui/view/tabview3.cxx
index e258761..cedb9ba 100644
--- a/sc/source/ui/view/tabview3.cxx
+++ b/sc/source/ui/view/tabview3.cxx
@@ -2634,8 +2634,12 @@ void ScTabView::CheckNeedsRepaint()
             pGridWin[i]->CheckNeedsRepaint();
 }
 
-
-
-
+bool ScTabView::NeedsRepaint()
+{
+    for (size_t i = 0; i < 4; i++)
+        if (pGridWin[i] && pGridWin[i]->IsVisible() && pGridWin[i]->NeedsRepaint())
+            return true;
+    return false;
+}
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/uiconfig/scalc/ui/datastreams.ui b/sc/uiconfig/scalc/ui/datastreams.ui
index 1c2abe7..cd48886 100644
--- a/sc/uiconfig/scalc/ui/datastreams.ui
+++ b/sc/uiconfig/scalc/ui/datastreams.ui
@@ -174,6 +174,7 @@
                                         <property name="receives_default">False</property>
                                         <property name="use_underline">True</property>
                                         <property name="xalign">0</property>
+                                        <property name="active">True</property>
                                         <property name="draw_indicator">True</property>
                                         <property name="group">addressvalue</property>
                                       </object>
@@ -323,6 +324,7 @@
                                 <property name="can_focus">True</property>
                                 <property name="receives_default">False</property>
                                 <property name="use_underline">True</property>
+                                <property name="active">True</property>
                                 <property name="xalign">0</property>
                                 <property name="draw_indicator">True</property>
                                 <property name="group">datadown</property>
@@ -401,6 +403,7 @@
                                 <property name="receives_default">False</property>
                                 <property name="use_underline">True</property>
                                 <property name="xalign">0</property>
+                                <property name="active">True</property>
                                 <property name="draw_indicator">True</property>
                                 <property name="group">unlimited</property>
                               </object>
diff --git a/xmloff/source/core/xmltoken.cxx b/xmloff/source/core/xmltoken.cxx
index 431e778..5840f95 100644
--- a/xmloff/source/core/xmltoken.cxx
+++ b/xmloff/source/core/xmltoken.cxx
@@ -554,6 +554,7 @@ namespace xmloff { namespace token {
         TOKEN( "data-pilot-table",                XML_DATA_PILOT_TABLE ),
         TOKEN( "data-pilot-tables",               XML_DATA_PILOT_TABLES ),
         TOKEN( "data-point",                      XML_DATA_POINT ),
+        TOKEN( "data-stream-source",              XML_DATA_STREAM_SOURCE ),
         TOKEN( "data-style",                      XML_DATA_STYLE ),
         TOKEN( "data-style-name",                 XML_DATA_STYLE_NAME ),
         TOKEN( "data-type",                       XML_DATA_TYPE ),
@@ -673,6 +674,7 @@ namespace xmloff { namespace token {
         TOKEN( "embossed",                        XML_EMBOSSED ),
         TOKEN( "emissive-color",                  XML_EMISSIVE_COLOR ),
         TOKEN( "empty",                           XML_EMPTY ),
+        TOKEN( "empty-line-refresh",              XML_EMPTY_LINE_REFRESH ),
         TOKEN( "enable-numbering",                XML_ENABLE_NUMBERING ),
         TOKEN( "enabled",                         XML_ENABLED ),
         TOKEN( "encoding",                        XML_ENCODING ),
@@ -1027,6 +1029,7 @@ namespace xmloff { namespace token {
         TOKEN( "inproceedings",                   XML_INPROCEEDINGS ),
         TOKEN( "insertion",                       XML_INSERTION ),
         TOKEN( "insertion-cut-off",               XML_INSERTION_CUT_OFF ),
+        TOKEN( "insertion-position",              XML_INSERTION_POSITION ),
         TOKEN( "inset",                           XML_INSET ),
         TOKEN( "inside",                          XML_INSIDE ),
         TOKEN( "institution",                     XML_INSTITUTION ),


More information about the Libreoffice-commits mailing list