[Libreoffice-commits] core.git: Branch 'private/kohei/4-2-data-stream-staging' - 30 commits - include/xmloff RepositoryExternal.mk sc/inc sc/Library_sc.mk sc/Library_scqahelper.mk sc/source sc/uiconfig xmloff/source

Stephan Bergmann sbergman at redhat.com
Thu Dec 19 13:42:45 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/documen7.cxx             |    1 
 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/miscdlgs/datastreamdlg.cxx      |  124 ++++--
 sc/source/ui/view/cellsh2.cxx                |   58 +--
 sc/uiconfig/scalc/ui/datastreams.ui          |    3 
 xmloff/source/core/xmltoken.cxx              |    3 
 36 files changed, 1177 insertions(+), 359 deletions(-)

New commits:
commit 4ef8915cc62755ce582229e449ad09128ed2ea90
Author: Stephan Bergmann <sbergman at redhat.com>
Date:   Thu Dec 19 22:20:35 2013 +0100

    -Werror,-Wunused-private-field
    
    Change-Id: Ic93497426013b26fece42035272506be55d2d6a4

diff --git a/sc/source/filter/xml/datastreamimport.hxx b/sc/source/filter/xml/datastreamimport.hxx
index a1b675b..c77f235 100644
--- a/sc/source/filter/xml/datastreamimport.hxx
+++ b/sc/source/filter/xml/datastreamimport.hxx
@@ -20,7 +20,6 @@ class ScXMLDataStreamContext : public ScXMLImportContext
     OUString maURL;
     ScRange maRange;
     bool mbRefreshOnEmpty;
-    bool mbInsertBottom;
     sc::ImportPostProcessData::DataStream::InsertPos meInsertPos;
 
 public:
commit 2c2b915d74548149bc7e0ea9ac125669750f317d
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Thu Dec 19 15:47:19 2013 -0500

    I forgot to check in these files.
    
    Change-Id: Ibb0d6c85ba6de2085ce699c1ef1a3b54f8ae66dc

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..a1b675b
--- /dev/null
+++ b/sc/source/filter/xml/datastreamimport.hxx
@@ -0,0 +1,39 @@
+/* -*- 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;
+    bool mbInsertBottom;
+    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: */
commit 6eb8059b24b6ea85ac0d04042b89f5d9b5750995
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Thu Dec 19 15:17:49 2013 -0500

    Properly import data stream data from ods.
    
    Change-Id: Iedae2226ba08c614f1b700a5444715a990899d38

diff --git a/sc/Library_sc.mk b/sc/Library_sc.mk
index ecef4d9..791752f 100644
--- a/sc/Library_sc.mk
+++ b/sc/Library_sc.mk
@@ -269,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 \
@@ -324,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 \
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/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/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/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/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 9092d43..8f6f501 100644
--- a/sc/source/ui/docshell/datastream.cxx
+++ b/sc/source/ui/docshell/datastream.cxx
@@ -288,7 +288,7 @@ void DataStream::Decode(const OUString& rURL, const ScRange& rRange,
     meOrigMove = eMove;
     mnSettings = nSettings;
 
-    mbValuesInLine = mnSettings & VALUES_IN_LINE;
+    mbValuesInLine = true; // always true.
 
     mnCurRow = rRange.aStart.Row();
 
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/miscdlgs/datastreamdlg.cxx b/sc/source/ui/miscdlgs/datastreamdlg.cxx
index cc58195..8a3bee5 100644
--- a/sc/source/ui/miscdlgs/datastreamdlg.cxx
+++ b/sc/source/ui/miscdlgs/datastreamdlg.cxx
@@ -150,6 +150,8 @@ void DataStreamDlg::Init( const DataStream& rStrm )
             ;
     }
 
+    m_pCBRefreshOnEmpty->Check(rStrm.IsRefreshOnEmptyLine());
+
     UpdateEnable();
 }
 
commit 1e2ae1ddc5bf8106c874347f82250fe5881d43a3
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Thu Dec 19 10:54:25 2013 -0500

    Unlimited when the end row is MAXROW.
    
    The top row may not always be row 1, so we can't rely on the total row count.
    
    Change-Id: Ia13bf6931636b15c8b673d3eed91488e6cec0def

diff --git a/sc/source/ui/miscdlgs/datastreamdlg.cxx b/sc/source/ui/miscdlgs/datastreamdlg.cxx
index 17b9e6e..cc58195 100644
--- a/sc/source/ui/miscdlgs/datastreamdlg.cxx
+++ b/sc/source/ui/miscdlgs/datastreamdlg.cxx
@@ -126,7 +126,7 @@ void DataStreamDlg::Init( const DataStream& rStrm )
     m_pEdRange->SetText(aStr);
     SCROW nRows = aRange.aEnd.Row() - aRange.aStart.Row() + 1;
 
-    if (nRows == MAXROWCOUNT)
+    if (aRange.aEnd.Row() == MAXROW)
         m_pRBUnlimited->Check();
     else
     {
commit adad52d0c3e00923f159b455d2d9d3617ee70514
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Thu Dec 19 10:31:41 2013 -0500

    Save the data stream settings to ODS but only for 1.2 extended.
    
    And only when the experimental mode is turned on.
    
    Change-Id: I49dc8a2588cae5ee4a987a47d882672efb93e1c2

diff --git a/sc/source/filter/xml/xmlexprt.cxx b/sc/source/filter/xml/xmlexprt.cxx
index 752d827..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>
@@ -1943,6 +1945,7 @@ void ScXMLExport::_ExportContent()
     }
     WriteExternalRefCaches();
     WriteNamedExpressions();
+    WriteDataStream();
     aExportDatabaseRanges.WriteDatabaseRanges();
     ScXMLExportDataPilot aExportDataPilot(*this);
     aExportDataPilot.WriteDataPilots(xSpreadDoc);
@@ -4039,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/ui/docshell/datastream.cxx b/sc/source/ui/docshell/datastream.cxx
index 10ff739..9092d43 100644
--- a/sc/source/ui/docshell/datastream.cxx
+++ b/sc/source/ui/docshell/datastream.cxx
@@ -208,6 +208,7 @@ DataStream::DataStream(ScDocShell *pShell, const OUString& rURL, const ScRange&
     mpDocShell(pShell),
     mpDoc(mpDocShell->GetDocument()),
     maDocAccess(*mpDoc),
+    meOrigMove(NO_MOVE),
     meMove(NO_MOVE),
     mbRunning(false),
     mbValuesInLine(false),
@@ -268,9 +269,14 @@ ScRange DataStream::GetRange() const
     return aRange;
 }
 
+bool DataStream::IsRefreshOnEmptyLine() const
+{
+    return mbRefreshOnEmptyLine;
+}
+
 DataStream::MoveType DataStream::GetMove() const
 {
-    return meMove;
+    return meOrigMove;
 }
 
 void DataStream::Decode(const OUString& rURL, const ScRange& rRange,
@@ -279,6 +285,7 @@ void DataStream::Decode(const OUString& rURL, const ScRange& rRange,
     msURL = rURL;
     mnLimit = nLimit;
     meMove = eMove;
+    meOrigMove = eMove;
     mnSettings = nSettings;
 
     mbValuesInLine = mnSettings & VALUES_IN_LINE;
diff --git a/sc/source/ui/inc/datastream.hxx b/sc/source/ui/inc/datastream.hxx
index b7cd712..5a4d8cd 100644
--- a/sc/source/ui/inc/datastream.hxx
+++ b/sc/source/ui/inc/datastream.hxx
@@ -62,6 +62,7 @@ public:
     const sal_Int32& GetLimit() const { return mnLimit; }
     MoveType GetMove() const;
     const sal_uInt32& GetSettings() const { return mnSettings; }
+    bool IsRefreshOnEmptyLine() const;
 
     void Decode(
         const OUString& rURL, const ScRange& rRange, sal_Int32 nLimit,
@@ -83,7 +84,8 @@ private:
     OUString msURL;
     sal_Int32 mnLimit;
     sal_uInt32 mnSettings;
-    MoveType 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;
     bool mbRefreshOnEmptyLine;
commit f0fba73227a19fa5c26a311eee54f0e65b0dc84c
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Thu Dec 19 01:20:13 2013 -0500

    Initialize data stream dialog properly.
    
    Change-Id: I86d4cfe946de896951d5eca2317f6d515113b249

diff --git a/sc/source/filter/xml/xmlexprt.cxx b/sc/source/filter/xml/xmlexprt.cxx
index 9e9c7df..752d827 100644
--- a/sc/source/filter/xml/xmlexprt.cxx
+++ b/sc/source/filter/xml/xmlexprt.cxx
@@ -836,18 +836,6 @@ void ScXMLExport::GetAreaLinks( ScMyAreaLinksContainer& rAreaLinks )
                 aAreaLink.nRefresh = pLink->GetTimeout();
                 rAreaLinks.AddNewAreaLink( aAreaLink );
             }
-            sc::DataStream *pStream = dynamic_cast<sc::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();
diff --git a/sc/source/ui/docshell/datastream.cxx b/sc/source/ui/docshell/datastream.cxx
index 1637aae..10ff739 100644
--- a/sc/source/ui/docshell/datastream.cxx
+++ b/sc/source/ui/docshell/datastream.cxx
@@ -264,27 +264,13 @@ OString DataStream::ConsumeLine()
 ScRange DataStream::GetRange() const
 {
     ScRange aRange = maStartRange;
-    if (mpEndRange)
-        aRange.aEnd = mpEndRange->aEnd;
+    aRange.aEnd = maEndRange.aEnd;
     return aRange;
 }
 
-OUString DataStream::GetMove() const
+DataStream::MoveType DataStream::GetMove() const
 {
-    switch (meMove)
-    {
-        case MOVE_DOWN:
-            return OUString("MOVE_DOWN");
-        case MOVE_UP:
-            return OUString("MOVE_UP");
-        case NO_MOVE:
-            return OUString("NO_MOVE");
-        case RANGE_DOWN:
-            return OUString("RANGE_DOWN");
-        default:
-            ;
-    }
-    return OUString();
+    return meMove;
 }
 
 void DataStream::Decode(const OUString& rURL, const ScRange& rRange,
@@ -294,7 +280,6 @@ void DataStream::Decode(const OUString& rURL, const ScRange& rRange,
     mnLimit = nLimit;
     meMove = eMove;
     mnSettings = nSettings;
-    mpEndRange.reset( NULL );
 
     mbValuesInLine = mnSettings & VALUES_IN_LINE;
 
@@ -306,11 +291,21 @@ void DataStream::Decode(const OUString& rURL, const ScRange& rRange,
         aRange.aEnd.SetRow(aRange.aStart.Row());
 
     maStartRange = aRange;
-    if (nLimit && aRange.aStart.Row() + nLimit - 1 < MAXROW)
+    maEndRange = aRange;
+    if (nLimit == 0)
+    {
+        // Unlimited
+        maEndRange.aStart.SetRow(MAXROW);
+    }
+    else if (nLimit > 0)
     {
-        mpEndRange.reset(new ScRange(aRange));
-        mpEndRange->Move(0, nLimit-1, 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()
@@ -359,14 +354,11 @@ void DataStream::Refresh()
 
 void DataStream::MoveData()
 {
-    if (!mpEndRange)
-        return;
-
     switch (meMove)
     {
         case RANGE_DOWN:
         {
-            if (mnCurRow == mpEndRange->aStart.Row())
+            if (mnCurRow == maEndRange.aStart.Row())
                 meMove = MOVE_UP;
         }
         break;
@@ -375,7 +367,7 @@ void DataStream::MoveData()
             // 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 = mpEndRange->aEnd;
+            aRange.aEnd = maEndRange.aEnd;
             maDocAccess.shiftRangeUp(aRange);
         }
         break;
@@ -384,7 +376,7 @@ void DataStream::MoveData()
             // Remove the end row and shift the remaining rows downward by
             // inserting a new row at the top row.
             ScRange aRange = maStartRange;
-            aRange.aEnd = mpEndRange->aEnd;
+            aRange.aEnd = maEndRange.aEnd;
             maDocAccess.shiftRangeDown(aRange);
         }
         break;
diff --git a/sc/source/ui/inc/datastream.hxx b/sc/source/ui/inc/datastream.hxx
index 935e895..b7cd712 100644
--- a/sc/source/ui/inc/datastream.hxx
+++ b/sc/source/ui/inc/datastream.hxx
@@ -60,7 +60,7 @@ public:
     ScRange GetRange() const;
     const OUString& GetURL() const { return msURL; }
     const sal_Int32& GetLimit() const { return mnLimit; }
-    OUString GetMove() const;
+    MoveType GetMove() const;
     const sal_uInt32& GetSettings() const { return mnSettings; }
 
     void Decode(
@@ -93,7 +93,7 @@ private:
     double mfLastRefreshTime;
     SCROW mnCurRow;
     ScRange maStartRange;
-    boost::scoped_ptr<ScRange> mpEndRange;
+    ScRange maEndRange;
     rtl::Reference<datastreams::CallerThread> mxThread;
     rtl::Reference<datastreams::ReaderThread> mxReaderThread;
 };
diff --git a/sc/source/ui/inc/datastreamdlg.hxx b/sc/source/ui/inc/datastreamdlg.hxx
index c7cff94..851afef 100644
--- a/sc/source/ui/inc/datastreamdlg.hxx
+++ b/sc/source/ui/inc/datastreamdlg.hxx
@@ -36,6 +36,7 @@ class DataStreamDlg : public ModalDialog
     RadioButton*    m_pRBRangeDown;
     RadioButton*    m_pRBNoMove;
     RadioButton*    m_pRBMaxLimit;
+    RadioButton*    m_pRBUnlimited;
     Edit*           m_pEdRange;
     Edit*           m_pEdLimit;
     OKButton*       m_pBtnOk;
@@ -51,11 +52,9 @@ class DataStreamDlg : public ModalDialog
 public:
     DataStreamDlg(ScDocShell *pDocShell, Window* pParent);
 
-    void Init(
-        const OUString& rURL, const ScRange& rRange, const sal_Int32 nLimit,
-        DataStream::MoveType eMove, const sal_uInt32 nSettings);
+    void Init( const DataStream& rStrm );
 
-    void StartStream(DataStream *pStream = 0);
+    void StartStream();
 };
 
 }
diff --git a/sc/source/ui/miscdlgs/datastreamdlg.cxx b/sc/source/ui/miscdlgs/datastreamdlg.cxx
index fbd1389..17b9e6e 100644
--- a/sc/source/ui/miscdlgs/datastreamdlg.cxx
+++ b/sc/source/ui/miscdlgs/datastreamdlg.cxx
@@ -32,6 +32,7 @@ DataStreamDlg::DataStreamDlg(ScDocShell *pDocShell, Window* pParent)
     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");
@@ -114,20 +115,26 @@ ScRange DataStreamDlg::GetStartRange()
     return aRange;
 }
 
-void DataStreamDlg::Init(
-    const OUString& rURL, const ScRange& rRange, const sal_Int32 nLimit,
-    DataStream::MoveType eMove, const sal_uInt32 nSettings)
+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();
-
-    OUString aStr = rRange.Format(SCA_VALID);
+    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 (nRows == MAXROWCOUNT)
+        m_pRBUnlimited->Check();
+    else
+    {
+        m_pRBMaxLimit->Check();
+        m_pEdLimit->SetText(OUString::number(nRows));
+    }
 
+    DataStream::MoveType eMove = rStrm.GetMove();
     switch (eMove)
     {
         case DataStream::MOVE_DOWN:
@@ -146,7 +153,7 @@ void DataStreamDlg::Init(
     UpdateEnable();
 }
 
-void DataStreamDlg::StartStream(DataStream *pStream)
+void DataStreamDlg::StartStream()
 {
     ScRange aStartRange = GetStartRange();
     if (!aStartRange.IsValid())
@@ -166,14 +173,7 @@ void DataStreamDlg::StartStream(DataStream *pStream)
     DataStream::MoveType eMove =
         m_pRBRangeDown->IsChecked() ? DataStream::RANGE_DOWN : DataStream::MOVE_DOWN;
 
-    if (pStream)
-    {
-        pStream->Decode(rURL, aStartRange, nLimit, eMove, nSettings);
-        pStream->SetRefreshOnEmptyLine(m_pCBRefreshOnEmpty->IsChecked());
-        return;
-    }
-
-    pStream = DataStream::Set(mpDocShell, rURL, aStartRange, nLimit, eMove, nSettings);
+    DataStream* pStream = DataStream::Set(mpDocShell, rURL, aStartRange, nLimit, eMove, nSettings);
     pStream->SetRefreshOnEmptyLine(m_pCBRefreshOnEmpty->IsChecked());
     DataStream::MakeToolbarVisible();
     pStream->StartImport();
diff --git a/sc/source/ui/view/cellsh2.cxx b/sc/source/ui/view/cellsh2.cxx
index 246021d..a93761c 100644
--- a/sc/source/ui/view/cellsh2.cxx
+++ b/sc/source/ui/view/cellsh2.cxx
@@ -744,6 +744,12 @@ void ScCellShell::ExecuteDB( SfxRequest& rReq )
         case SID_DATA_STREAMS:
         {
             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();
         }
commit 97a71fb151035066c00605cac2b39647105aac0f
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Wed Dec 18 23:51:27 2013 -0500

    Switch away from using the sfx2 link manager for data stream.
    
    Change-Id: I05ac5a8151135ace7f4e351cfedab0170c8d9a57

diff --git a/sc/Library_sc.mk b/sc/Library_sc.mk
index 0425cea..ecef4d9 100644
--- a/sc/Library_sc.mk
+++ b/sc/Library_sc.mk
@@ -404,6 +404,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/inc/document.hxx b/sc/inc/document.hxx
index d553b84..65d573f 100644
--- a/sc/inc/document.hxx
+++ b/sc/inc/document.hxx
@@ -70,6 +70,7 @@ class EditTextIterator;
 struct NoteEntry;
 struct FormulaGroupContext;
 class DocumentStreamAccess;
+class DocumentLinkManager;
 
 }
 
@@ -258,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
@@ -466,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;
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/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 dfd8a36..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(sc::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(sc::DataStream))
+            if (pBase->ISA(ScAreaLink))
                 pBase->Update();
         }
     }
diff --git a/sc/source/ui/docshell/datastream.cxx b/sc/source/ui/docshell/datastream.cxx
index f292299..1637aae 100644
--- a/sc/source/ui/docshell/datastream.cxx
+++ b/sc/source/ui/docshell/datastream.cxx
@@ -16,18 +16,14 @@
 #include <osl/time.h>
 #include <rtl/strbuf.hxx>
 #include <salhelper/thread.hxx>
-#include <sfx2/linkmgr.hxx>
 #include <sfx2/viewfrm.hxx>
-#include <arealink.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>
 
@@ -189,46 +185,9 @@ 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.
-    ScRange aDestArea;
-    if (rRange.IsValid())
-        aDestArea = rRange;
-
-    sfx2::LinkManager* pLinkManager = pShell->GetDocument()->GetLinkManager();
-    sal_uInt16 nLinkPos = 0;
-    while (nLinkPos < pLinkManager->GetLinks().size())
-    {
-        sfx2::SvBaseLink* pBase = *pLinkManager->GetLinks()[nLinkPos];
-        if (!rRange.IsValid())
-        {
-            if ( (pBase->ISA(ScAreaLink) && static_cast<ScAreaLink*>
-                        (&(*pBase))->GetDestArea().aStart == aDestArea.aStart)
-                || (pBase->ISA(DataStream) && static_cast<DataStream*>
-                        (&(*pBase))->GetRange().aStart == aDestArea.aStart) )
-            {
-                aDestArea.Move(0, 1, 0);
-                nLinkPos = 0;
-                continue;
-            }
-            else
-                ++nLinkPos;
-        }
-        else if ( (pBase->ISA(ScAreaLink) && static_cast<ScAreaLink*>
-                    (&(*pBase))->GetDestArea().aStart == aDestArea.aStart)
-                || (pBase->ISA(DataStream) && static_cast<DataStream*>
-                    (&(*pBase))->GetRange().aStart == aDestArea.aStart) )
-        {
-            pLinkManager->Remove( pBase );
-        }
-        else
-            ++nLinkPos;
-    }
-
-    DataStream* pLink = new DataStream(pShell, rURL, aDestArea, nLimit, eMove, nSettings);
-    pLinkManager->InsertFileLink( *pLink, OBJECT_CLIENT_FILE, rURL, NULL, NULL );
+    DataStream* pLink = new DataStream(pShell, rURL, rRange, nLimit, eMove, nSettings);
+    sc::DocumentLinkManager& rMgr = pShell->GetDocument()->GetDocLinkManager();
+    rMgr.setDataStream(pLink);
     return pLink;
 }
 
@@ -435,12 +394,6 @@ void DataStream::MoveData()
     }
 }
 
-IMPL_LINK_NOARG(DataStream, RefreshHdl)
-{
-    ImportData();
-    return 0;
-}
-
 #if ENABLE_ORCUS
 
 namespace {
@@ -576,39 +529,6 @@ bool DataStream::ImportData()
     return mbRunning;
 }
 
-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;
-}
-
-void DataStream::Edit( Window* pWindow, const Link& )
-{
-    DataStreamDlg aDialog(mpDocShell, pWindow);
-    aDialog.Init(msURL, maStartRange, mnLimit, meMove, mnSettings);
-    if (aDialog.Execute() == RET_OK)
-    {
-        bool bWasRunning = mbRunning;
-        StopImport();
-        aDialog.StartStream(this);
-        if (bWasRunning)
-            StartImport();
-    }
-}
-
 } // namespace sc
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
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 1cde20e..935e895 100644
--- a/sc/source/ui/inc/datastream.hxx
+++ b/sc/source/ui/inc/datastream.hxx
@@ -14,14 +14,12 @@
 
 #include <rtl/ref.hxx>
 #include <rtl/ustring.hxx>
-#include <sfx2/lnkbase.hxx>
 #include <address.hxx>
 
 #include <boost/noncopyable.hpp>
 #include <boost/scoped_ptr.hpp>
 #include <vector>
 
-#include <rangelst.hxx>
 #include <documentstreamaccess.hxx>
 
 class ScDocShell;
@@ -37,12 +35,11 @@ namespace datastreams {
 
 typedef std::vector<OString> LinesList;
 
-class DataStream : boost::noncopyable, public sfx2::SvBaseLink
+class DataStream : boost::noncopyable
 {
     OString ConsumeLine();
     void MoveData();
     void Text2Doc();
-    DECL_LINK( RefreshHdl, void* );
 
 public:
     enum MoveType { NO_MOVE, RANGE_DOWN, MOVE_DOWN, MOVE_UP };
@@ -58,11 +55,7 @@ public:
         ScDocShell *pShell, const OUString& rURL, const ScRange& rRange,
         sal_Int32 nLimit, MoveType eMove, 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;
+    ~DataStream();
 
     ScRange GetRange() const;
     const OUString& GetURL() const { return msURL; }
diff --git a/sc/source/ui/view/cellsh2.cxx b/sc/source/ui/view/cellsh2.cxx
index 399c36d..246021d 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,30 @@ void ScCellShell::ExecuteDB( SfxRequest& rReq )
             }
             break;
         case SID_DATA_STREAMS:
-            {
-                sc::DataStreamDlg aDialog( GetViewData()->GetDocShell(), pTabViewShell->GetDialogParent() );
-                if (aDialog.Execute() == RET_OK)
-                    aDialog.StartStream();
-            }
-            break;
+        {
+            sc::DataStreamDlg aDialog( GetViewData()->GetDocShell(), pTabViewShell->GetDialogParent() );
+            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 (sc::DataStream *pStream = dynamic_cast<sc::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 (sc::DataStream *pStream = dynamic_cast<sc::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;
commit 8f5a74f0f95b40b5ab794d0b3a274ad3e65df171
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Wed Dec 18 20:56:26 2013 -0500

    Remove the data stream bits from ods import.
    
    Will do this cleanly later.
    
    Change-Id: I1ca44c4522cd0ed7dd9d08bd483fe99a21e2994e

diff --git a/sc/source/filter/xml/xmlcelli.cxx b/sc/source/filter/xml/xmlcelli.cxx
index b1d0de3..e40a527 100644
--- a/sc/source/filter/xml/xmlcelli.cxx
+++ b/sc/source/filter/xml/xmlcelli.cxx
@@ -1000,26 +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")
-            {
-                ScRange aRange;
-                sal_uInt16 nRes = aRange.Parse(sRangeStr, pDoc);
-                if ((nRes & SCA_VALID) == SCA_VALID)
-                {
-                    sc::DataStream::MoveType eMove = sc::DataStream::ToMoveType(sSourceStr);
-                    sc::DataStream::Set( dynamic_cast<ScDocShell*>(pDoc->GetDocumentShell())
-                            , pCellRangeSource->sURL // rURL
-                            , aRange
-                            , sFilterName.toInt32() // nLimit
-                            , eMove
-                            , pCellRangeSource->nRefresh // nSettings
-                            );
-                }
-                return;
-            }
             ScAreaLink* pLink = new ScAreaLink( pDoc->GetDocumentShell(), pCellRangeSource->sURL,
                 sFilterName, pCellRangeSource->sFilterOptions, sSourceStr, aDestRange, pCellRangeSource->nRefresh );
             sfx2::LinkManager* pLinkManager = pDoc->GetLinkManager();
commit 0938544de0f7f0a82ea07f8d48c0399b4203ae18
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Wed Dec 18 20:51:48 2013 -0500

    Add new XML tokens for ODS, for calc data stream import & export.
    
    Change-Id: I3b86a53a3fcbac8eab56a74c5c636e0ce0cb13e5

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/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 ),
commit 820461a9ce4e5cd67334901f7ad5e51a42da22b8
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Wed Dec 18 20:19:24 2013 -0500

    Actually hide these two radio buttons (since there is no choice now).
    
    Change-Id: I8a6080cc724b7ee88ba45d3dce1f8f63b6771f51

diff --git a/sc/source/ui/inc/datastreamdlg.hxx b/sc/source/ui/inc/datastreamdlg.hxx
index 0a7f167..c7cff94 100644
--- a/sc/source/ui/inc/datastreamdlg.hxx
+++ b/sc/source/ui/inc/datastreamdlg.hxx
@@ -27,6 +27,7 @@ class DataStreamDlg : public ModalDialog
 
     SvtURLBox*      m_pCbUrl;
     PushButton*     m_pBtnBrowse;
+    RadioButton*    m_pRBDirectData;
     RadioButton*    m_pRBScriptData;
     RadioButton*    m_pRBValuesInLine;
     RadioButton*    m_pRBAddressValue;
diff --git a/sc/source/ui/miscdlgs/datastreamdlg.cxx b/sc/source/ui/miscdlgs/datastreamdlg.cxx
index 728e74b..fbd1389 100644
--- a/sc/source/ui/miscdlgs/datastreamdlg.cxx
+++ b/sc/source/ui/miscdlgs/datastreamdlg.cxx
@@ -23,6 +23,7 @@ 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");
@@ -41,6 +42,8 @@ DataStreamDlg::DataStreamDlg(ScDocShell *pDocShell, Window* pParent)
     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 ) );
commit 36534892d329a1824f6b58cb7c55c2cb7d2fcd52
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Wed Dec 18 20:15:14 2013 -0500

    Disable script source option.
    
    Change-Id: I6cbfff1d9740e284b05d4737e13794bc2b098167

diff --git a/sc/source/ui/miscdlgs/datastreamdlg.cxx b/sc/source/ui/miscdlgs/datastreamdlg.cxx
index 41a9c7b..728e74b 100644
--- a/sc/source/ui/miscdlgs/datastreamdlg.cxx
+++ b/sc/source/ui/miscdlgs/datastreamdlg.cxx
@@ -40,6 +40,7 @@ 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_pRBNoMove->Hide();
     m_pRBValuesInLine->SetClickHdl( LINK( this, DataStreamDlg, UpdateHdl ) );
     m_pEdRange->SetModifyHdl( LINK( this, DataStreamDlg, UpdateHdl ) );
commit 9e1c133555ff2bcefe64a7a284fa6ea1abe8773e
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Wed Dec 18 19:51:17 2013 -0500

    Hide the "Overwrite existing data" option.
    
    With the address,value mode gone, this option makes no sense.
    
    Change-Id: Iec4925afb03b81d0b4d9fe912c8f20b135ef74d3

diff --git a/sc/source/ui/miscdlgs/datastreamdlg.cxx b/sc/source/ui/miscdlgs/datastreamdlg.cxx
index fa21dd9..41a9c7b 100644
--- a/sc/source/ui/miscdlgs/datastreamdlg.cxx
+++ b/sc/source/ui/miscdlgs/datastreamdlg.cxx
@@ -40,6 +40,7 @@ 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_pRBNoMove->Hide();
     m_pRBValuesInLine->SetClickHdl( LINK( this, DataStreamDlg, UpdateHdl ) );
     m_pEdRange->SetModifyHdl( LINK( this, DataStreamDlg, UpdateHdl ) );
     m_pBtnBrowse->SetClickHdl( LINK( this, DataStreamDlg, BrowseHdl ) );
@@ -68,7 +69,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();
@@ -129,13 +129,12 @@ void DataStreamDlg::Init(
         case DataStream::MOVE_DOWN:
             m_pRBDataDown->Check();
         break;
-        case DataStream::NO_MOVE:
-            m_pRBNoMove->Check();
         break;
         case DataStream::RANGE_DOWN:
             m_pRBRangeDown->Check();
         break;
         case DataStream::MOVE_UP:
+        case DataStream::NO_MOVE:
         default:
             ;
     }
@@ -161,8 +160,7 @@ void DataStreamDlg::StartStream(DataStream *pStream)
        nSettings |= DataStream::VALUES_IN_LINE;
 
     DataStream::MoveType eMove =
-        m_pRBNoMove->IsChecked() ? DataStream::NO_MOVE : m_pRBRangeDown->IsChecked()
-            ? DataStream::RANGE_DOWN : DataStream::MOVE_DOWN;
+        m_pRBRangeDown->IsChecked() ? DataStream::RANGE_DOWN : DataStream::MOVE_DOWN;
 
     if (pStream)
     {
commit 8b9f6ec160551eef99d7f8654efa26b9c8164fa3
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Wed Dec 18 17:48:59 2013 -0500

    We don't need these yet.
    
    Change-Id: Iff875a690f319eb92ccfb8010853714ac60dcc9a

diff --git a/sc/inc/document.hxx b/sc/inc/document.hxx
index 6dbee50..d553b84 100644
--- a/sc/inc/document.hxx
+++ b/sc/inc/document.hxx
@@ -1804,9 +1804,6 @@ public:
                          */
     void                Broadcast( const ScHint& rHint );
 
-    void BroadcastCells( const ScRange& rRange, sal_uLong nHint );
-    void BroadcastCells( const ScRangeList& rRanges, sal_uLong nHint );
-
                         /// only area, no cell broadcast
     void                AreaBroadcast( const ScHint& rHint );
                         /// only areas in range, no cell broadcasts
diff --git a/sc/source/core/data/documen7.cxx b/sc/source/core/data/documen7.cxx
index ec2e1cf..b8f691b 100644
--- a/sc/source/core/data/documen7.cxx
+++ b/sc/source/core/data/documen7.cxx
@@ -104,34 +104,6 @@ void ScDocument::Broadcast( const ScHint& rHint )
     }
 }
 
-void ScDocument::BroadcastCells( const ScRange& rRange, sal_uLong nHint )
-{
-    // TODO : For now, this simply makes multiple Broadcast() calls one cell
-    // at a time.  In the future, we should add a more efficient way to
-    // make a range of cell broadcasts.
-
-    ScHint aHint(nHint, rRange.aStart);
-
-    for (SCCOL nCol = rRange.aStart.Col(); nCol <= rRange.aEnd.Col(); ++nCol)
-    {
-        for (SCROW nRow = rRange.aStart.Row(); nRow <= rRange.aEnd.Row(); ++nRow)
-        {
-            aHint.GetAddress().SetCol(nCol);
-            aHint.GetAddress().SetRow(nRow);
-            Broadcast(aHint);
-        }
-    }
-}
-
-void ScDocument::BroadcastCells( const ScRangeList& rRanges, sal_uLong nHint )
-{
-    for (size_t i = 0, n = rRanges.size(); i < n; ++i)
-    {
-        const ScRange* p = rRanges[i];
-        BroadcastCells(*p, nHint);
-    }
-}
-
 void ScDocument::AreaBroadcast( const ScHint& rHint )
 {
     if ( !pBASM )
commit cba3005f0ef52d8d5af07e8301fecb1815587bfe
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Wed Dec 18 16:40:36 2013 -0500

    Don't forget to set document modified afterward.
    
    Change-Id: I5b2b9a3dad2aeee6bc5a4a4767b239c92865b2f4

diff --git a/sc/source/ui/docshell/datastream.cxx b/sc/source/ui/docshell/datastream.cxx
index 345f026..f292299 100644
--- a/sc/source/ui/docshell/datastream.cxx
+++ b/sc/source/ui/docshell/datastream.cxx
@@ -392,6 +392,7 @@ void DataStream::Refresh()
 {
     // Hard recalc will repaint the grid area.
     mpDocShell->DoHardRecalc(true);
+    mpDocShell->SetDocumentModified(true);
 
     mfLastRefreshTime = getNow();
     mnLinesSinceRefresh = 0;
commit 4a338044fda27389420e4a9243f52a161dd695ca
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Wed Dec 18 16:19:05 2013 -0500

    Handle "refresh on empty line" setting from the UI.
    
    With this set, when we detect an empty line, we'll trigger refresh and
    discard the line.  If not set, we'll import an empty line.
    
    Change-Id: Ic3ccb1adbd0c7273c3affff82a2d111c378f2af3

diff --git a/sc/source/ui/docshell/datastream.cxx b/sc/source/ui/docshell/datastream.cxx
index 6430ef6..345f026 100644
--- a/sc/source/ui/docshell/datastream.cxx
+++ b/sc/source/ui/docshell/datastream.cxx
@@ -251,6 +251,8 @@ DataStream::DataStream(ScDocShell *pShell, const OUString& rURL, const ScRange&
     maDocAccess(*mpDoc),
     meMove(NO_MOVE),
     mbRunning(false),
+    mbValuesInLine(false),
+    mbRefreshOnEmptyLine(false),
     mpLines(0),
     mnLinesCount(0),
     mnLinesSinceRefresh(0),
@@ -381,6 +383,11 @@ void DataStream::StopImport()
     Refresh();
 }
 
+void DataStream::SetRefreshOnEmptyLine( bool bVal )
+{
+    mbRefreshOnEmptyLine = bVal;
+}
+
 void DataStream::Refresh()
 {
     // Hard recalc will repaint the grid area.
@@ -437,21 +444,41 @@ IMPL_LINK_NOARG(DataStream, RefreshHdl)
 
 namespace {
 
+struct StrVal
+{
+    ScAddress maPos;
+    OUString maStr;
+
+    StrVal( const ScAddress& rPos, const OUString& rStr ) : maPos(rPos), maStr(rStr) {}
+};
+
+struct NumVal
+{
+    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
 {
-    DocumentStreamAccess& mrDoc;
     ScAddress maPos;
     SCROW mnRow;
     SCCOL mnCol;
     SCCOL mnEndCol;
     SCTAB mnTab;
 
+    StrValArray maStrs;
+    NumValArray maNums;
+
 public:
-    CSVHandler( DocumentStreamAccess& rDoc, const ScAddress& rPos, SCCOL nEndCol ) :
-        mrDoc(rDoc), maPos(rPos), mnEndCol(nEndCol) {}
+    CSVHandler( const ScAddress& rPos, SCCOL nEndCol ) : maPos(rPos), mnEndCol(nEndCol) {}
 
     void begin_parse() {}
     void end_parse() {}
@@ -465,12 +492,15 @@ public:
             OUString aStr(p, n, RTL_TEXTENCODING_UTF8);
             double fVal;
             if (ScStringUtil::parseSimpleNumber(aStr, '.', ',', fVal))
-                mrDoc.setNumericCell(maPos, fVal);
+                maNums.push_back(NumVal(maPos, fVal));
             else
-                mrDoc.setStringCell(maPos, aStr);
+                maStrs.push_back(StrVal(maPos, aStr));
         }
         maPos.IncCol();
     }
+
+    const StrValArray& getStrs() const { return maStrs; }
+    const NumValArray& getNums() const { return maNums; }
 };
 
 }
@@ -481,61 +511,34 @@ void DataStream::Text2Doc()
     orcus::csv_parser_config aConfig;
     aConfig.delimiters.push_back(',');
     aConfig.text_qualifier = '"';
-    CSVHandler aHdl(maDocAccess, ScAddress(maStartRange.aStart.Col(), mnCurRow, maStartRange.aStart.Tab()), maStartRange.aEnd.Col());
+    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();
 
-    ++mnLinesSinceRefresh;
-}
-
-#else
-
-void DataStream::Text2Doc() {}
-
-#endif
-
-bool DataStream::ImportData()
-{
-    SolarMutexGuard aGuard;
-    if (ScDocShell::GetViewData()->GetViewShell()->NeedsRepaint())
-        return mbRunning;
+    const StrValArray& rStrs = aHdl.getStrs();
+    const NumValArray& rNums = aHdl.getNums();
+    if (rStrs.empty() && rNums.empty() && mbRefreshOnEmptyLine)
+    {
+        // Empty line detected.  Trigger refresh and discard it.
+        Refresh();
+        return;
+    }
 
     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
-    {
-#if 0 // TODO : temporarily disable this code.
-        ScDocumentImport aDocImport(*mpDoc);
-        // 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, mpDoc);
-            if (!aAddress.IsValid())
-                continue;
 
-            if (sValue == "0" || ( sValue.indexOf(':') == -1 && sValue.toDouble() ))
-                aDocImport.setNumericCell(aAddress, sValue.toDouble());
-            else
-                aDocImport.setStringCell(aAddress, sValue);
-            maBroadcastRanges.Join(aAddress);
-        }
-        aDocImport.finalize();
-#endif
+    {
+        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)
     {
@@ -549,6 +552,26 @@ bool DataStream::ImportData()
         // least we have processed 200 lines.
         Refresh();
 
+    ++mnLinesSinceRefresh;
+}
+
+#else
+
+void DataStream::Text2Doc() {}
+
+#endif
+
+bool DataStream::ImportData()
+{
+    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;
 }
 
diff --git a/sc/source/ui/inc/datastream.hxx b/sc/source/ui/inc/datastream.hxx
index a593aad..1cde20e 100644
--- a/sc/source/ui/inc/datastream.hxx
+++ b/sc/source/ui/inc/datastream.hxx
@@ -78,6 +78,8 @@ public:
     void StartImport();
     void StopImport();
 
+    void SetRefreshOnEmptyLine( bool bVal );
+
 private:
     void Refresh();
 
@@ -91,6 +93,7 @@ private:
     MoveType meMove;
     bool mbRunning;
     bool mbValuesInLine;
+    bool mbRefreshOnEmptyLine;
     LinesList* mpLines;
     size_t mnLinesCount;
     size_t mnLinesSinceRefresh;
diff --git a/sc/source/ui/inc/datastreamdlg.hxx b/sc/source/ui/inc/datastreamdlg.hxx
index d817743..0a7f167 100644
--- a/sc/source/ui/inc/datastreamdlg.hxx
+++ b/sc/source/ui/inc/datastreamdlg.hxx
@@ -30,6 +30,7 @@ class DataStreamDlg : public ModalDialog
     RadioButton*    m_pRBScriptData;
     RadioButton*    m_pRBValuesInLine;
     RadioButton*    m_pRBAddressValue;
+    CheckBox*       m_pCBRefreshOnEmpty;
     RadioButton*    m_pRBDataDown;
     RadioButton*    m_pRBRangeDown;
     RadioButton*    m_pRBNoMove;
diff --git a/sc/source/ui/miscdlgs/datastreamdlg.cxx b/sc/source/ui/miscdlgs/datastreamdlg.cxx
index c004fbc..fa21dd9 100644
--- a/sc/source/ui/miscdlgs/datastreamdlg.cxx
+++ b/sc/source/ui/miscdlgs/datastreamdlg.cxx
@@ -26,6 +26,7 @@ DataStreamDlg::DataStreamDlg(ScDocShell *pDocShell, Window* pParent)
     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");
@@ -166,10 +167,12 @@ void DataStreamDlg::StartStream(DataStream *pStream)
     if (pStream)
     {
         pStream->Decode(rURL, aStartRange, nLimit, eMove, nSettings);
+        pStream->SetRefreshOnEmptyLine(m_pCBRefreshOnEmpty->IsChecked());
         return;
     }
 
     pStream = DataStream::Set(mpDocShell, rURL, aStartRange, nLimit, eMove, nSettings);
+    pStream->SetRefreshOnEmptyLine(m_pCBRefreshOnEmpty->IsChecked());
     DataStream::MakeToolbarVisible();
     pStream->StartImport();
 }
commit 3f4d08a7a4eecf73f6ebdd9d8108201599eb57a0
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Wed Dec 18 14:55:17 2013 -0500

    Fine-tune our refresh policy during streaming.
    
    Change-Id: I9eff0bc0e4087261e2283a55211c8a9daf2a8b24

diff --git a/sc/source/ui/docshell/datastream.cxx b/sc/source/ui/docshell/datastream.cxx
index 1e6cde1..6430ef6 100644
--- a/sc/source/ui/docshell/datastream.cxx
+++ b/sc/source/ui/docshell/datastream.cxx
@@ -13,12 +13,12 @@
 #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>
@@ -42,6 +42,13 @@
 
 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
@@ -246,7 +253,8 @@ DataStream::DataStream(ScDocShell *pShell, const OUString& rURL, const ScRange&
     mbRunning(false),
     mpLines(0),
     mnLinesCount(0),
-    mnRepaintCounter(0),
+    mnLinesSinceRefresh(0),
+    mfLastRefreshTime(0.0),
     mnCurRow(0)
 {
     mxThread = new datastreams::CallerThread( this );
@@ -375,14 +383,11 @@ void DataStream::StopImport()
 
 void DataStream::Refresh()
 {
-    SCROW nEndRow = mpEndRange ? mpEndRange->aEnd.Row() : MAXROW;
-    ScRange aRange(maStartRange.aStart);
-    aRange.aEnd = ScAddress(maStartRange.aEnd.Col(), nEndRow, maStartRange.aStart.Tab());
-
-    mnRepaintCounter = 0;
-
     // Hard recalc will repaint the grid area.
     mpDocShell->DoHardRecalc(true);
+
+    mfLastRefreshTime = getNow();
+    mnLinesSinceRefresh = 0;
 }
 
 void DataStream::MoveData()
@@ -480,7 +485,7 @@ void DataStream::Text2Doc()
     orcus::csv_parser<CSVHandler> parser(aLine.getStr(), aLine.getLength(), aHdl, aConfig);
     parser.parse();
 
-    ++mnRepaintCounter;
+    ++mnLinesSinceRefresh;
 }
 
 #else
@@ -539,7 +544,9 @@ bool DataStream::ImportData()
 //              maStartRange.aStart.Col(), mnCurRow, SC_FOLLOW_JUMP);
     }
 
-    if (mnRepaintCounter > 200)
+    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();
 
     return mbRunning;
diff --git a/sc/source/ui/inc/datastream.hxx b/sc/source/ui/inc/datastream.hxx
index 86be03b..a593aad 100644
--- a/sc/source/ui/inc/datastream.hxx
+++ b/sc/source/ui/inc/datastream.hxx
@@ -93,7 +93,8 @@ private:
     bool mbValuesInLine;
     LinesList* mpLines;
     size_t mnLinesCount;
-    size_t mnRepaintCounter;
+    size_t mnLinesSinceRefresh;
+    double mfLastRefreshTime;
     SCROW mnCurRow;
     ScRange maStartRange;
     boost::scoped_ptr<ScRange> mpEndRange;
commit c9335b5e89d452ec0c0faadfac5fe73586dd7cc4
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Wed Dec 18 14:15:29 2013 -0500

    Just do hard-recalc on stream refresh. That takes care of all our needs.
    
    Change-Id: I9a454089843d1373153988a29843b95db22ee284

diff --git a/sc/source/ui/docshell/datastream.cxx b/sc/source/ui/docshell/datastream.cxx
index 1bb9cd6..1e6cde1 100644
--- a/sc/source/ui/docshell/datastream.cxx
+++ b/sc/source/ui/docshell/datastream.cxx
@@ -370,23 +370,19 @@ void DataStream::StopImport()
         return;
 
     mbRunning = false;
-    Repaint();
+    Refresh();
 }
 
-void DataStream::Repaint()
+void DataStream::Refresh()
 {
     SCROW nEndRow = mpEndRange ? mpEndRange->aEnd.Row() : MAXROW;
     ScRange aRange(maStartRange.aStart);
     aRange.aEnd = ScAddress(maStartRange.aEnd.Col(), nEndRow, maStartRange.aStart.Tab());
 
-    mpDocShell->PostPaint(aRange, PAINT_GRID);
     mnRepaintCounter = 0;
-}
 
-void DataStream::Broadcast()
-{
-    mpDoc->BroadcastCells(maBroadcastRanges, SC_HINT_DATACHANGED);
-    maBroadcastRanges.RemoveAll();
+    // Hard recalc will repaint the grid area.
+    mpDocShell->DoHardRecalc(true);
 }
 
 void DataStream::MoveData()
@@ -544,7 +540,7 @@ bool DataStream::ImportData()
     }
 
     if (mnRepaintCounter > 200)
-        Repaint();
+        Refresh();
 
     return mbRunning;
 }
diff --git a/sc/source/ui/inc/datastream.hxx b/sc/source/ui/inc/datastream.hxx
index 494a73e..86be03b 100644
--- a/sc/source/ui/inc/datastream.hxx
+++ b/sc/source/ui/inc/datastream.hxx
@@ -79,8 +79,7 @@ public:
     void StopImport();
 
 private:
-    void Repaint();
-    void Broadcast();
+    void Refresh();
 
 private:
     ScDocShell* mpDocShell;
@@ -97,7 +96,6 @@ private:
     size_t mnRepaintCounter;
     SCROW mnCurRow;
     ScRange maStartRange;
-    ScRangeList maBroadcastRanges;
     boost::scoped_ptr<ScRange> mpEndRange;
     rtl::Reference<datastreams::CallerThread> mxThread;
     rtl::Reference<datastreams::ReaderThread> mxReaderThread;
commit 41f9dd54912412869efd23f3e12fc4fecf741cca
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Wed Dec 18 10:10:57 2013 -0500

    Disable this mode for now.
    
    Change-Id: I3206de5e379fb7091498f5e3d83ccc5d28071ae5

diff --git a/sc/source/ui/miscdlgs/datastreamdlg.cxx b/sc/source/ui/miscdlgs/datastreamdlg.cxx
index bc1bf3d..c004fbc 100644
--- a/sc/source/ui/miscdlgs/datastreamdlg.cxx
+++ b/sc/source/ui/miscdlgs/datastreamdlg.cxx
@@ -38,6 +38,7 @@ 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_pRBValuesInLine->SetClickHdl( LINK( this, DataStreamDlg, UpdateHdl ) );
     m_pEdRange->SetModifyHdl( LINK( this, DataStreamDlg, UpdateHdl ) );
     m_pBtnBrowse->SetClickHdl( LINK( this, DataStreamDlg, BrowseHdl ) );
commit ff6beaabaac07bcbc8dd4f3c0467a742056fd435
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Tue Dec 17 22:38:37 2013 -0500

    Pass enum values around rather than OUString ones.
    
    Ditto with the range type.
    
    Change-Id: Iab37d50b6d58d76c60872f49f13d77ff0c918974

diff --git a/sc/source/filter/xml/xmlcelli.cxx b/sc/source/filter/xml/xmlcelli.cxx
index 1223d3c5..b1d0de3 100644
--- a/sc/source/filter/xml/xmlcelli.cxx
+++ b/sc/source/filter/xml/xmlcelli.cxx
@@ -1005,13 +1005,19 @@ void ScXMLTableRowCellContext::SetCellRangeSource( const ScAddress& rPosition )
             SvtMiscOptions aMiscOptions;
             if (aMiscOptions.IsExperimentalMode() && pCellRangeSource->sFilterOptions == "DataStream")
             {
-                sc::DataStream::Set( dynamic_cast<ScDocShell*>(pDoc->GetDocumentShell())
-                        , pCellRangeSource->sURL // rURL
-                        , sRangeStr // rRange
-                        , sFilterName.toInt32() // nLimit
-                        , sSourceStr // rMove
-                        , pCellRangeSource->nRefresh // nSettings
-                        );
+                ScRange aRange;
+                sal_uInt16 nRes = aRange.Parse(sRangeStr, pDoc);
+                if ((nRes & SCA_VALID) == SCA_VALID)
+                {
+                    sc::DataStream::MoveType eMove = sc::DataStream::ToMoveType(sSourceStr);
+                    sc::DataStream::Set( dynamic_cast<ScDocShell*>(pDoc->GetDocumentShell())
+                            , pCellRangeSource->sURL // rURL
+                            , aRange
+                            , sFilterName.toInt32() // nLimit
+                            , eMove
+                            , pCellRangeSource->nRefresh // nSettings
+                            );
+                }
                 return;
             }
             ScAreaLink* pLink = new ScAreaLink( pDoc->GetDocumentShell(), pCellRangeSource->sURL,
diff --git a/sc/source/ui/docshell/datastream.cxx b/sc/source/ui/docshell/datastream.cxx
index af60412e..1bb9cd6 100644
--- a/sc/source/ui/docshell/datastream.cxx
+++ b/sc/source/ui/docshell/datastream.cxx
@@ -178,25 +178,24 @@ 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.
     ScRange aDestArea;
-    sal_uInt16 nRes = aDestArea.Parse(rRange, pShell->GetDocument());
-    if ((nRes & SCA_VALID) != SCA_VALID)
-        // Invalid range string.
-        return NULL;
+    if (rRange.IsValid())
+        aDestArea = rRange;
 
     sfx2::LinkManager* pLinkManager = pShell->GetDocument()->GetLinkManager();
     sal_uInt16 nLinkPos = 0;
     while (nLinkPos < pLinkManager->GetLinks().size())
     {
         sfx2::SvBaseLink* pBase = *pLinkManager->GetLinks()[nLinkPos];
-        if (rRange.isEmpty())
+        if (!rRange.IsValid())
         {
             if ( (pBase->ISA(ScAreaLink) && static_cast<ScAreaLink*>
                         (&(*pBase))->GetDestArea().aStart == aDestArea.aStart)
@@ -221,13 +220,25 @@ DataStream* DataStream::Set(ScDocShell *pShell, const OUString& rURL, const OUSt
             ++nLinkPos;
     }
 
-    DataStream* pLink = new DataStream(pShell, rURL, aDestArea, nLimit, rMove, nSettings);
+    DataStream* pLink = new DataStream(pShell, rURL, aDestArea, nLimit, eMove, nSettings);
     pLinkManager->InsertFileLink( *pLink, OBJECT_CLIENT_FILE, rURL, NULL, NULL );
     return 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 ScRange& rRange,
-        sal_Int32 nLimit, const OUString& rMove, sal_uInt32 nSettings) :
+        sal_Int32 nLimit, MoveType eMove, sal_uInt32 nSettings) :
     mpDocShell(pShell),
     mpDoc(mpDocShell->GetDocument()),
     maDocAccess(*mpDoc),
@@ -241,7 +252,7 @@ DataStream::DataStream(ScDocShell *pShell, const OUString& rURL, const ScRange&
     mxThread = new datastreams::CallerThread( this );
     mxThread->launch();
 
-    Decode(rURL, rRange, nLimit, rMove, nSettings);
+    Decode(rURL, rRange, nLimit, eMove, nSettings);
 }
 
 DataStream::~DataStream()
@@ -289,24 +300,35 @@ ScRange DataStream::GetRange() const
     return aRange;
 }
 
+OUString DataStream::GetMove() const
+{
+    switch (meMove)
+    {
+        case MOVE_DOWN:
+            return OUString("MOVE_DOWN");
+        case MOVE_UP:
+            return OUString("MOVE_UP");
+        case NO_MOVE:
+            return OUString("NO_MOVE");
+        case RANGE_DOWN:
+            return OUString("RANGE_DOWN");
+        default:
+            ;
+    }
+    return OUString();
+}
+
 void DataStream::Decode(const OUString& rURL, const ScRange& rRange,
-        sal_Int32 nLimit, const OUString& rMove, const sal_uInt32 nSettings)
+        sal_Int32 nLimit, MoveType eMove, const sal_uInt32 nSettings)
 {
     msURL = rURL;
     mnLimit = nLimit;
-    msMove = rMove;
+    meMove = 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;
-
     mnCurRow = rRange.aStart.Row();
 
     ScRange aRange = rRange;
@@ -549,7 +571,7 @@ sfx2::SvBaseLink::UpdateResult DataStream::DataChanged(
 void DataStream::Edit( Window* pWindow, const Link& )
 {
     DataStreamDlg aDialog(mpDocShell, pWindow);
-    aDialog.Init(msURL, maStartRange, mnLimit, msMove, mnSettings);
+    aDialog.Init(msURL, maStartRange, mnLimit, meMove, mnSettings);
     if (aDialog.Execute() == RET_OK)
     {
         bool bWasRunning = mbRunning;
diff --git a/sc/source/ui/inc/datastream.hxx b/sc/source/ui/inc/datastream.hxx
index 5f20bf4..494a73e 100644
--- a/sc/source/ui/inc/datastream.hxx
+++ b/sc/source/ui/inc/datastream.hxx
@@ -7,6 +7,9 @@
  * 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>
@@ -42,16 +45,18 @@ class DataStream : boost::noncopyable, public sfx2::SvBaseLink
     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);
+    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, const OUString& rMove, sal_uInt32 nSettings);
+        sal_Int32 nLimit, MoveType eMove, sal_uInt32 nSettings);
 
     virtual ~DataStream();
     // sfx2::SvBaseLink
@@ -62,12 +67,12 @@ public:
     ScRange GetRange() const;
     const OUString& GetURL() const { return msURL; }
     const sal_Int32& GetLimit() const { return mnLimit; }
-    const OUString& GetMove() const { return msMove; }
+    OUString GetMove() const;
     const sal_uInt32& GetSettings() const { return mnSettings; }
 
     void Decode(
         const OUString& rURL, const ScRange& rRange, sal_Int32 nLimit,
-        const OUString& rMove, const sal_uInt32 nSettings);
+        MoveType eMove, const sal_uInt32 nSettings);
 
     bool ImportData();
     void StartImport();
@@ -82,10 +87,9 @@ private:
     ScDocument* mpDoc;
     DocumentStreamAccess maDocAccess;
     OUString msURL;
-    OUString msMove;
     sal_Int32 mnLimit;
     sal_uInt32 mnSettings;
-    MoveEnum meMove;
+    MoveType meMove;
     bool mbRunning;
     bool mbValuesInLine;
     LinesList* mpLines;
@@ -101,4 +105,6 @@ private:
 
 }
 
+#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 e3308f8..d817743 100644
--- a/sc/source/ui/inc/datastreamdlg.hxx
+++ b/sc/source/ui/inc/datastreamdlg.hxx
@@ -13,14 +13,14 @@
 #include <vcl/dialog.hxx>
 #include <vcl/layout.hxx>
 
+#include <datastream.hxx>
+
 class ScDocShell;
 class SvtURLBox;
 class ScRange;
 
 namespace sc {
 
-class DataStream;
-
 class DataStreamDlg : public ModalDialog
 {
     ScDocShell *mpDocShell;
@@ -51,7 +51,7 @@ public:
 
     void Init(
         const OUString& rURL, const ScRange& rRange, const sal_Int32 nLimit,
-        const OUString& rMove, const sal_uInt32 nSettings);
+        DataStream::MoveType eMove, const sal_uInt32 nSettings);
 
     void StartStream(DataStream *pStream = 0);
 };
diff --git a/sc/source/ui/miscdlgs/datastreamdlg.cxx b/sc/source/ui/miscdlgs/datastreamdlg.cxx
index 06980b9..bc1bf3d 100644
--- a/sc/source/ui/miscdlgs/datastreamdlg.cxx
+++ b/sc/source/ui/miscdlgs/datastreamdlg.cxx
@@ -12,7 +12,6 @@
 #include <sfx2/filedlghelper.hxx>
 #include <svtools/inettbc.hxx>
 #include <vcl/layout.hxx>
-#include <datastream.hxx>
 #include <address.hxx>
 #include <docsh.hxx>
 
@@ -111,7 +110,7 @@ ScRange DataStreamDlg::GetStartRange()
 
 void DataStreamDlg::Init(
     const OUString& rURL, const ScRange& rRange, const sal_Int32 nLimit,
-    const OUString& rMove, const sal_uInt32 nSettings)
+    DataStream::MoveType eMove, const sal_uInt32 nSettings)
 {
     m_pEdLimit->SetText(OUString::number(nLimit));
     m_pCbUrl->SetText(rURL);
@@ -123,12 +122,22 @@ void DataStreamDlg::Init(
     OUString aStr = rRange.Format(SCA_VALID);
     m_pEdRange->SetText(aStr);
 
-    if (rMove == "NO_MOVE")
-        m_pRBNoMove->Check();
-    else if (rMove == "RANGE_DOWN")
-        m_pRBRangeDown->Check();
-    else if (rMove == "MOVE_DOWN")
-        m_pRBDataDown->Check();
+    switch (eMove)
+    {
+        case DataStream::MOVE_DOWN:
+            m_pRBDataDown->Check();
+        break;
+        case DataStream::NO_MOVE:
+            m_pRBNoMove->Check();
+        break;
+        case DataStream::RANGE_DOWN:
+            m_pRBRangeDown->Check();
+        break;
+        case DataStream::MOVE_UP:
+        default:
+            ;
+    }
+
     UpdateEnable();
 }
 
@@ -148,22 +157,18 @@ void DataStreamDlg::StartStream(DataStream *pStream)
        nSettings |= DataStream::SCRIPT_STREAM;
     if (m_pRBValuesInLine->IsChecked())
        nSettings |= DataStream::VALUES_IN_LINE;
+
+    DataStream::MoveType eMove =
+        m_pRBNoMove->IsChecked() ? DataStream::NO_MOVE : m_pRBRangeDown->IsChecked()
+            ? DataStream::RANGE_DOWN : DataStream::MOVE_DOWN;
+
     if (pStream)
     {
-        pStream->Decode(rURL, aStartRange, nLimit,
-                m_pRBNoMove->IsChecked() ? OUString("NO_MOVE") : m_pRBRangeDown->IsChecked()
-                    ? OUString("RANGE_DOWN") : OUString("MOVE_DOWN"),
-                nSettings);
+        pStream->Decode(rURL, aStartRange, nLimit, eMove, 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
-            );
+
+    pStream = DataStream::Set(mpDocShell, rURL, aStartRange, nLimit, eMove, nSettings);
     DataStream::MakeToolbarVisible();
     pStream->StartImport();
 }
commit f1000801bcf8ea414261e296c4cd43f603adec64
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Tue Dec 17 21:51:43 2013 -0500

    Detect numbers which are to be inserted as numeric cells.
    
    Also, disable automatic scrolling.
    
    Change-Id: I2f3facfd91b9b4e3f86b9685a546a094180bf1ee

diff --git a/sc/inc/documentstreamaccess.hxx b/sc/inc/documentstreamaccess.hxx
index 74f8914..9fa2d78 100644
--- a/sc/inc/documentstreamaccess.hxx
+++ b/sc/inc/documentstreamaccess.hxx
@@ -33,6 +33,7 @@ class DocumentStreamAccess
 public:
     DocumentStreamAccess( ScDocument& rDoc );
 
+    void setNumericCell( const ScAddress& rPos, double fVal );
     void setStringCell( const ScAddress& rPos, const OUString& rStr );
 
     /**
diff --git a/sc/source/core/data/documentstreamaccess.cxx b/sc/source/core/data/documentstreamaccess.cxx
index 81ca160..bf3efe3 100644
--- a/sc/source/core/data/documentstreamaccess.cxx
+++ b/sc/source/core/data/documentstreamaccess.cxx
@@ -31,6 +31,27 @@ struct DocumentStreamAccessImpl
 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());
diff --git a/sc/source/ui/docshell/datastream.cxx b/sc/source/ui/docshell/datastream.cxx
index a798b84..af60412e 100644
--- a/sc/source/ui/docshell/datastream.cxx
+++ b/sc/source/ui/docshell/datastream.cxx
@@ -27,6 +27,7 @@
 #include <rangelst.hxx>
 #include <tabvwsh.hxx>
 #include <viewdata.hxx>
+#include <stringutil.hxx>
 
 #include <config_orcus.h>
 
@@ -438,7 +439,12 @@ public:
     {
         if (maPos.Col() <= mnEndCol)
         {
-            mrDoc.setStringCell(maPos, OUString(p, n, RTL_TEXTENCODING_UTF8));
+            OUString aStr(p, n, RTL_TEXTENCODING_UTF8);
+            double fVal;
+            if (ScStringUtil::parseSimpleNumber(aStr, '.', ',', fVal))
+                mrDoc.setNumericCell(maPos, fVal);
+            else
+                mrDoc.setStringCell(maPos, aStr);
         }
         maPos.IncCol();
     }
@@ -511,11 +517,11 @@ bool DataStream::ImportData()
     if (meMove == RANGE_DOWN)
     {
         ++mnCurRow;
-        mpDocShell->GetViewData()->GetView()->AlignToCursor(
-                maStartRange.aStart.Col(), mnCurRow, SC_FOLLOW_JUMP);
+//      mpDocShell->GetViewData()->GetView()->AlignToCursor(
+//              maStartRange.aStart.Col(), mnCurRow, SC_FOLLOW_JUMP);
     }
 
-    if (mnRepaintCounter > 100)
+    if (mnRepaintCounter > 200)
         Repaint();
 
     return mbRunning;
commit 21f03a3e5d58d501fff9de207765299c3d2c132d
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Tue Dec 17 21:18:46 2013 -0500

    Use orcus csv parser to streamd data which has much less overhead.
    
    Also, use DocumentStreamAccess to modify ScDocument's content.
    
    Change-Id: I516260cff1f2315267afcff05e36e620798a1aed

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/sc/Library_sc.mk b/sc/Library_sc.mk
index 2c8fd68..0425cea 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))
 
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/documentstreamaccess.hxx b/sc/inc/documentstreamaccess.hxx
index 1450f21..74f8914 100644
--- a/sc/inc/documentstreamaccess.hxx
+++ b/sc/inc/documentstreamaccess.hxx
@@ -10,7 +10,11 @@
 #ifndef SC_DOCUMENTSTREAMACCESS_HXX
 #define SC_DOCUMENTSTREAMACCESS_HXX
 
+#include <rtl/ustring.hxx>
+
 class ScDocument;
+class ScAddress;
+class ScRange;
 
 namespace sc {
 
@@ -28,6 +32,26 @@ class DocumentStreamAccess
 
 public:
     DocumentStreamAccess( ScDocument& rDoc );
+
+    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 );
 };
 
 }
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/source/core/data/documentstreamaccess.cxx b/sc/source/core/data/documentstreamaccess.cxx
index 2d427af..81ca160 100644
--- a/sc/source/core/data/documentstreamaccess.cxx
+++ b/sc/source/core/data/documentstreamaccess.cxx
@@ -9,19 +9,114 @@
 
 #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) {}
+    DocumentStreamAccessImpl( ScDocument& rDoc ) :
+        mrDoc(rDoc),
+        maBlockPosSet(rDoc)
+    {}
 };
 
 DocumentStreamAccess::DocumentStreamAccess( ScDocument& rDoc ) :
     mpImpl(new DocumentStreamAccessImpl(rDoc)) {}
 
+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;
+

... etc. - the rest is truncated


More information about the Libreoffice-commits mailing list