[Libreoffice-commits] core.git: 13 commits - RepositoryExternal.mk sc/inc sc/Library_sc.mk sc/Library_scqahelper.mk sc/source sc/uiconfig

Kohei Yoshida kohei.yoshida at collabora.com
Wed Dec 18 07:12:49 PST 2013


 RepositoryExternal.mk                        |    4 
 sc/Library_sc.mk                             |    7 
 sc/Library_scqahelper.mk                     |    8 
 sc/inc/column.hxx                            |    2 
 sc/inc/document.hxx                          |    6 
 sc/inc/documentstreamaccess.hxx              |   62 ++++
 sc/inc/mtvelements.hxx                       |    2 
 sc/inc/table.hxx                             |    2 
 sc/source/core/data/documen7.cxx             |   27 +
 sc/source/core/data/documen8.cxx             |    4 
 sc/source/core/data/documentstreamaccess.cxx |  143 ++++++++++
 sc/source/core/data/mtvelements.cxx          |    6 
 sc/source/filter/xml/xmlcelli.cxx            |   20 -
 sc/source/filter/xml/xmlexprt.cxx            |    2 
 sc/source/ui/docshell/datastream.cxx         |  375 +++++++++++++++++----------
 sc/source/ui/inc/datastream.hxx              |   68 +++-
 sc/source/ui/inc/datastreamdlg.hxx           |   17 -
 sc/source/ui/miscdlgs/datastreamdlg.cxx      |   93 +++++-
 sc/source/ui/view/cellsh2.cxx                |    6 
 sc/uiconfig/scalc/ui/datastreams.ui          |    3 
 20 files changed, 660 insertions(+), 197 deletions(-)

New commits:
commit 3daf9de8642aeb6e143468bab203af5c6b5b0f41
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 6dc1ea1c67fbe748fc84a0cf0b443545c3b5cbc3
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 9c369f71830099e583946a90158aa3838c056f98
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 ecc884e9b8afbdaaa917774471d71060ff96cc74
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 3d9a4bf..0147876 100644
--- a/RepositoryExternal.mk
+++ b/RepositoryExternal.mk
@@ -2621,6 +2621,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 b60af82..01a4ab9 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;
+
+    SCROW nTopRow = rRange.aStart.Row();
+    SCROW nLastRow = rRange.aEnd.Row();
+
+    for (SCCOL nCol = rRange.aStart.Col(); nCol <= rRange.aEnd.Col(); ++nCol)
+    {
+        ColumnBlockPosition* pBlockPos =
+            mpImpl->maBlockPosSet.getBlockPosition(rRange.aStart.Tab(), nCol);
+
+        if (!pBlockPos)
+            return;
+
+        CellStoreType& rCells = pTab->aCol[nCol].maCells;
+        rCells.erase(nLastRow, nLastRow); // Erase the bottom.
+        pBlockPos->miCellPos = rCells.insert_empty(nTopRow, 1); // insert at the top and shift everything down.
+
+        // Do the same for the text attribute storage.
+        CellTextAttrStoreType& rAttrs = pTab->aCol[nCol].maCellTextAttrs;
+        rAttrs.erase(nLastRow, nLastRow);
+        pBlockPos->miCellTextAttrPos = rAttrs.insert_empty(nTopRow, 1);
+    }
+}
+
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/core/data/mtvelements.cxx b/sc/source/core/data/mtvelements.cxx
index 5a94606..1110ab6 100644
--- a/sc/source/core/data/mtvelements.cxx
+++ b/sc/source/core/data/mtvelements.cxx
@@ -67,6 +67,12 @@ ColumnBlockPosition* ColumnBlockPositionSet::getBlockPosition(SCTAB nTab, SCCOL
     return &it->second;
 }
 
+void ColumnBlockPositionSet::clear()
+{
+    osl::MutexGuard aGuard(&maMtxTables);
+    maTables.clear();
+}
+
 ScRefCellValue toRefCell( const sc::CellStoreType::const_iterator& itPos, size_t nOffset )
 {
     switch (itPos->type)
diff --git a/sc/source/ui/docshell/datastream.cxx b/sc/source/ui/docshell/datastream.cxx
index f053371..a798b84 100644
--- a/sc/source/ui/docshell/datastream.cxx
+++ b/sc/source/ui/docshell/datastream.cxx
@@ -28,6 +28,15 @@
 #include <tabvwsh.hxx>
 #include <viewdata.hxx>
 
+#include <config_orcus.h>
+
+#if ENABLE_ORCUS
+#if defined WNT
+#define __ORCUS_STATIC_LIB
+#endif
+#include <orcus/csv_parser.hpp>
+#endif
+
 #include <queue>
 
 namespace sc {
@@ -316,6 +325,7 @@ void DataStream::StartImport()
 {
     if (mbRunning)
         return;
+
     if (!mxReaderThread.is())
     {
         SvStream *pStream = 0;
@@ -327,6 +337,7 @@ void DataStream::StartImport()
         mxReaderThread->launch();
     }
     mbRunning = true;
+    maDocAccess.reset();
     mxThread->maStart.set();
 }
 
@@ -334,6 +345,7 @@ void DataStream::StopImport()
 {
     if (!mbRunning)
         return;
+
     mbRunning = false;
     Repaint();
 }
@@ -362,23 +374,32 @@ void DataStream::MoveData()
     switch (meMove)
     {
         case RANGE_DOWN:
+        {
             if (mnCurRow == mpEndRange->aStart.Row())
                 meMove = MOVE_UP;
-            break;
+        }
+        break;
         case MOVE_UP:
+        {
             // Remove the top row and shift the remaining rows upward. Then
             // insert a new row at the end row position.
-            mpDoc->DeleteRow(maStartRange);
-            mpDoc->InsertRow(*mpEndRange);
-            break;
+            ScRange aRange = maStartRange;
+            aRange.aEnd = mpEndRange->aEnd;
+            maDocAccess.shiftRangeUp(aRange);
+        }
+        break;
         case MOVE_DOWN:
+        {
             // Remove the end row and shift the remaining rows downward by
             // inserting a new row at the top row.
-            mpDoc->DeleteRow(*mpEndRange);
-            mpDoc->InsertRow(maStartRange);
-            break;
+            ScRange aRange = maStartRange;
+            aRange.aEnd = mpEndRange->aEnd;
+            maDocAccess.shiftRangeDown(aRange);
+        }
+        break;
         case NO_MOVE:
-            break;
+        default:
+            ;
     }
 }
 
@@ -388,77 +409,61 @@ IMPL_LINK_NOARG(DataStream, RefreshHdl)
     return 0;
 }
 
-//  lcl_ScanString and Text2Doc is simplified version
-//  of code from sc/source/ui/docshell/impex.cxx
-const sal_Unicode* lcl_ScanString( const sal_Unicode* p, OUString& rString, sal_Unicode cStr)
+#if ENABLE_ORCUS
+
+namespace {
+
+/**
+ * This handler handles a single line CSV input.
+ */
+class CSVHandler
 {
-    const sal_Unicode* p0 = p;
-    for( ;; )
+    DocumentStreamAccess& mrDoc;
+    ScAddress maPos;
+    SCROW mnRow;
+    SCCOL mnCol;
+    SCCOL mnEndCol;
+    SCTAB mnTab;
+
+public:
+    CSVHandler( DocumentStreamAccess& rDoc, const ScAddress& rPos, SCCOL nEndCol ) :
+        mrDoc(rDoc), maPos(rPos), mnEndCol(nEndCol) {}
+
+    void begin_parse() {}
+    void end_parse() {}
+    void begin_row() {}
+    void end_row() {}
+
+    void cell(const char* p, size_t n)
     {
-        if (!*p)
-            break;
-        if (*p == cStr)
+        if (maPos.Col() <= mnEndCol)
         {
-            if (*++p != cStr)
-                break;
-            p++;
+            mrDoc.setStringCell(maPos, OUString(p, n, RTL_TEXTENCODING_UTF8));
         }
-        else
-            p++;
+        maPos.IncCol();
     }
-    if (p0 < p)
-        if (rString.getLength() + (p - p0) <= STRING_MAXLEN)
-            rString += OUString( p0, sal::static_int_cast<sal_Int32>( p - p0 ) );
-    return p;
+};
+
 }
 
 void DataStream::Text2Doc()
 {
-    sal_Unicode cSep(',');
-    sal_Unicode cStr('"');
-    SCCOL nStartCol = maStartRange.aStart.Col();
-    SCCOL nEndCol = maStartRange.aEnd.Col();
-    OUString aCell;
-    ScDocumentImport aDocImport(*mpDoc);
-
-    SCCOL nCol = nStartCol;
-    OUString sLine( OStringToOUString(ConsumeLine(), RTL_TEXTENCODING_UTF8) );
-    const sal_Unicode* p = sLine.getStr();
-    while (*p)
-    {
-        aCell = "";
-        const sal_Unicode* q = p;
-        while (*p && *p != cSep)
-        {
-            // Always look for a pairing quote and ignore separator in between.
-            while (*p && *p == cStr)
-                q = p = lcl_ScanString(p, aCell, cStr);
-            // All until next separator or quote.
-            while (*p && *p != cSep && *p != cStr)
-                ++p;
-            if (aCell.getLength() + (p - q) <= STRING_MAXLEN)
-                aCell += OUString( q, sal::static_int_cast<sal_Int32>( p - q ) );
-            q = p;
-        }
-        if (*p)
-            ++p;
-        if (nCol <= nEndCol)
-        {
-            ScAddress aAddress(nCol, mnCurRow, maStartRange.aStart.Tab());
-            if (aCell == "0" || ( aCell.indexOf(':') == -1 && aCell.toDouble() ))
-                aDocImport.setNumericCell(aAddress, aCell.toDouble());
-            else
-                aDocImport.setStringCell(aAddress, aCell);
-        }
-        ++nCol;
-    }
+    OString aLine = ConsumeLine();
+    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());
+    orcus::csv_parser<CSVHandler> parser(aLine.getStr(), aLine.getLength(), aHdl, aConfig);
+    parser.parse();
+
     ++mnRepaintCounter;
+}
 
-    aDocImport.finalize();
+#else
 
-    ScRange aBCRange(nStartCol, mnCurRow, maStartRange.aStart.Tab(), nEndCol, mnCurRow, maStartRange.aStart.Tab());
-    maBroadcastRanges.Join(aBCRange);
-}
+void DataStream::Text2Doc() {}
+
+#endif
 
 bool DataStream::ImportData()
 {
@@ -474,6 +479,7 @@ bool DataStream::ImportData()
     }
     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)
@@ -496,8 +502,9 @@ bool DataStream::ImportData()
             maBroadcastRanges.Join(aAddress);
         }
         aDocImport.finalize();
+#endif
     }
-    mpDocShell->SetDocumentModified();
+
     if (meMove == NO_MOVE)
         return mbRunning;
 
diff --git a/sc/source/ui/inc/datastream.hxx b/sc/source/ui/inc/datastream.hxx
index 70857dc..5f20bf4 100644
--- a/sc/source/ui/inc/datastream.hxx
+++ b/sc/source/ui/inc/datastream.hxx
@@ -78,8 +78,8 @@ private:
     void Broadcast();
 
 private:
-    ScDocShell *mpDocShell;
-    ScDocument *mpDoc;
+    ScDocShell* mpDocShell;
+    ScDocument* mpDoc;
     DocumentStreamAccess maDocAccess;
     OUString msURL;
     OUString msMove;
@@ -88,7 +88,7 @@ private:
     MoveEnum meMove;
     bool mbRunning;
     bool mbValuesInLine;
-    LinesList *mpLines;
+    LinesList* mpLines;
     size_t mnLinesCount;
     size_t mnRepaintCounter;
     SCROW mnCurRow;
commit df63ec609f361108bc1e531e1454734f6c03258e
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Tue Dec 17 16:11:52 2013 -0500

    Only keep track of current row position, not a whole range.
    
    Change-Id: I8ad56284b9c5422d102c7e8688e5b1e4c37ae877

diff --git a/sc/source/ui/docshell/datastream.cxx b/sc/source/ui/docshell/datastream.cxx
index 423ce07..f053371 100644
--- a/sc/source/ui/docshell/datastream.cxx
+++ b/sc/source/ui/docshell/datastream.cxx
@@ -188,9 +188,9 @@ DataStream* DataStream::Set(ScDocShell *pShell, const OUString& rURL, const OUSt
         sfx2::SvBaseLink* pBase = *pLinkManager->GetLinks()[nLinkPos];
         if (rRange.isEmpty())
         {
-            if ( (pBase->ISA(ScAreaLink) && dynamic_cast<ScAreaLink*>
+            if ( (pBase->ISA(ScAreaLink) && static_cast<ScAreaLink*>
                         (&(*pBase))->GetDestArea().aStart == aDestArea.aStart)
-                || (pBase->ISA(DataStream) && dynamic_cast<DataStream*>
+                || (pBase->ISA(DataStream) && static_cast<DataStream*>
                         (&(*pBase))->GetRange().aStart == aDestArea.aStart) )
             {
                 aDestArea.Move(0, 1, 0);
@@ -200,9 +200,9 @@ DataStream* DataStream::Set(ScDocShell *pShell, const OUString& rURL, const OUSt
             else
                 ++nLinkPos;
         }
-        else if ( (pBase->ISA(ScAreaLink) && dynamic_cast<ScAreaLink*>
+        else if ( (pBase->ISA(ScAreaLink) && static_cast<ScAreaLink*>
                     (&(*pBase))->GetDestArea().aStart == aDestArea.aStart)
-                || (pBase->ISA(DataStream) && dynamic_cast<DataStream*>
+                || (pBase->ISA(DataStream) && static_cast<DataStream*>
                     (&(*pBase))->GetRange().aStart == aDestArea.aStart) )
         {
             pLinkManager->Remove( pBase );
@@ -225,7 +225,8 @@ DataStream::DataStream(ScDocShell *pShell, const OUString& rURL, const ScRange&
     mbRunning(false),
     mpLines(0),
     mnLinesCount(0),
-    mnRepaintCounter(0)
+    mnRepaintCounter(0),
+    mnCurRow(0)
 {
     mxThread = new datastreams::CallerThread( this );
     mxThread->launch();
@@ -270,6 +271,14 @@ OString DataStream::ConsumeLine()
     return mpLines->at(mnLinesCount++);
 }
 
+ScRange DataStream::GetRange() const
+{
+    ScRange aRange = maStartRange;
+    if (mpEndRange)
+        aRange.aEnd = mpEndRange->aEnd;
+    return aRange;
+}
+
 void DataStream::Decode(const OUString& rURL, const ScRange& rRange,
         sal_Int32 nLimit, const OUString& rMove, const sal_uInt32 nSettings)
 {
@@ -288,15 +297,17 @@ void DataStream::Decode(const OUString& rURL, const ScRange& rRange,
     else if (msMove == "MOVE_DOWN")
         meMove = MOVE_DOWN;
 
-    maRange = rRange;
-    if (maRange.aStart.Row() != maRange.aEnd.Row())
+    mnCurRow = rRange.aStart.Row();
+
+    ScRange aRange = rRange;
+    if (aRange.aStart.Row() != aRange.aEnd.Row())
         // We only allow this range to be one row tall.
-        maRange.aEnd.SetRow(maRange.aStart.Row());
+        aRange.aEnd.SetRow(aRange.aStart.Row());
 
-    maStartRange = maRange;
-    if (nLimit && maRange.aStart.Row() + nLimit - 1 < MAXROW)
+    maStartRange = aRange;
+    if (nLimit && aRange.aStart.Row() + nLimit - 1 < MAXROW)
     {
-        mpEndRange.reset( new ScRange(maRange) );
+        mpEndRange.reset(new ScRange(aRange));
         mpEndRange->Move(0, nLimit-1, 0);
     }
 }
@@ -331,7 +342,7 @@ void DataStream::Repaint()
 {
     SCROW nEndRow = mpEndRange ? mpEndRange->aEnd.Row() : MAXROW;
     ScRange aRange(maStartRange.aStart);
-    aRange.aEnd = ScAddress(maRange.aEnd.Col(), nEndRow, maRange.aStart.Tab());
+    aRange.aEnd = ScAddress(maStartRange.aEnd.Col(), nEndRow, maStartRange.aStart.Tab());
 
     mpDocShell->PostPaint(aRange, PAINT_GRID);
     mnRepaintCounter = 0;
@@ -345,25 +356,22 @@ void DataStream::Broadcast()
 
 void DataStream::MoveData()
 {
+    if (!mpEndRange)
+        return;
+
     switch (meMove)
     {
         case RANGE_DOWN:
-            if (maRange.aStart == mpEndRange->aStart)
+            if (mnCurRow == mpEndRange->aStart.Row())
                 meMove = MOVE_UP;
             break;
         case MOVE_UP:
-            if (!mpEndRange)
-                break;
-
             // Remove the top row and shift the remaining rows upward. Then
             // insert a new row at the end row position.
             mpDoc->DeleteRow(maStartRange);
             mpDoc->InsertRow(*mpEndRange);
             break;
         case MOVE_DOWN:
-            if (!mpEndRange)
-                break;
-
             // Remove the end row and shift the remaining rows downward by
             // inserting a new row at the top row.
             mpDoc->DeleteRow(*mpEndRange);
@@ -408,53 +416,47 @@ void DataStream::Text2Doc()
 {
     sal_Unicode cSep(',');
     sal_Unicode cStr('"');
-    SCCOL nStartCol = maRange.aStart.Col();
-    SCROW nStartRow = maRange.aStart.Row();
-    SCCOL nEndCol = maRange.aEnd.Col();
-    SCROW nEndRow = maRange.aEnd.Row();
+    SCCOL nStartCol = maStartRange.aStart.Col();
+    SCCOL nEndCol = maStartRange.aEnd.Col();
     OUString aCell;
-    SCROW nRow = nStartRow;
     ScDocumentImport aDocImport(*mpDoc);
-    while (nRow <= nEndRow)
+
+    SCCOL nCol = nStartCol;
+    OUString sLine( OStringToOUString(ConsumeLine(), RTL_TEXTENCODING_UTF8) );
+    const sal_Unicode* p = sLine.getStr();
+    while (*p)
     {
-        SCCOL nCol = nStartCol;
-        OUString sLine( OStringToOUString(ConsumeLine(), RTL_TEXTENCODING_UTF8) );
-        const sal_Unicode* p = sLine.getStr();
-        while (*p)
+        aCell = "";
+        const sal_Unicode* q = p;
+        while (*p && *p != cSep)
         {
-            aCell = "";
-            const sal_Unicode* q = p;
-            while (*p && *p != cSep)
-            {
-                // Always look for a pairing quote and ignore separator in between.
-                while (*p && *p == cStr)
-                    q = p = lcl_ScanString(p, aCell, cStr);
-                // All until next separator or quote.
-                while (*p && *p != cSep && *p != cStr)
-                    ++p;
-                if (aCell.getLength() + (p - q) <= STRING_MAXLEN)
-                    aCell += OUString( q, sal::static_int_cast<sal_Int32>( p - q ) );
-                q = p;
-            }
-            if (*p)
+            // Always look for a pairing quote and ignore separator in between.
+            while (*p && *p == cStr)
+                q = p = lcl_ScanString(p, aCell, cStr);
+            // All until next separator or quote.
+            while (*p && *p != cSep && *p != cStr)
                 ++p;
-            if (nCol <= nEndCol && nRow <= nEndRow)
-            {
-                ScAddress aAddress(nCol, nRow, maRange.aStart.Tab());
-                if (aCell == "0" || ( aCell.indexOf(':') == -1 && aCell.toDouble() ))
-                    aDocImport.setNumericCell(aAddress, aCell.toDouble());
-                else
-                    aDocImport.setStringCell(aAddress, aCell);
-            }
-            ++nCol;
+            if (aCell.getLength() + (p - q) <= STRING_MAXLEN)
+                aCell += OUString( q, sal::static_int_cast<sal_Int32>( p - q ) );
+            q = p;
+        }
+        if (*p)
+            ++p;
+        if (nCol <= nEndCol)
+        {
+            ScAddress aAddress(nCol, mnCurRow, maStartRange.aStart.Tab());
+            if (aCell == "0" || ( aCell.indexOf(':') == -1 && aCell.toDouble() ))
+                aDocImport.setNumericCell(aAddress, aCell.toDouble());
+            else
+                aDocImport.setStringCell(aAddress, aCell);
         }
-        ++nRow;
-        ++mnRepaintCounter;
+        ++nCol;
     }
+    ++mnRepaintCounter;
 
     aDocImport.finalize();
 
-    ScRange aBCRange(nStartCol, nStartRow, maRange.aStart.Tab(), nEndCol, nEndRow, maRange.aStart.Tab());
+    ScRange aBCRange(nStartCol, mnCurRow, maStartRange.aStart.Tab(), nEndCol, mnCurRow, maStartRange.aStart.Tab());
     maBroadcastRanges.Join(aBCRange);
 }
 
@@ -501,9 +503,9 @@ bool DataStream::ImportData()
 
     if (meMove == RANGE_DOWN)
     {
-        maRange.Move(0, maRange.aEnd.Row() - maRange.aStart.Row() + 1, 0);
+        ++mnCurRow;
         mpDocShell->GetViewData()->GetView()->AlignToCursor(
-                maRange.aStart.Col(), maRange.aStart.Row(), SC_FOLLOW_JUMP);
+                maStartRange.aStart.Col(), mnCurRow, SC_FOLLOW_JUMP);
     }
 
     if (mnRepaintCounter > 100)
diff --git a/sc/source/ui/inc/datastream.hxx b/sc/source/ui/inc/datastream.hxx
index 8b7a510..70857dc 100644
--- a/sc/source/ui/inc/datastream.hxx
+++ b/sc/source/ui/inc/datastream.hxx
@@ -59,7 +59,7 @@ public:
             const OUString& , const css::uno::Any& ) SAL_OVERRIDE;
     virtual void Edit(Window* , const Link& ) SAL_OVERRIDE;
 
-    const ScRange& GetRange() const { return maRange; }
+    ScRange GetRange() const;
     const OUString& GetURL() const { return msURL; }
     const sal_Int32& GetLimit() const { return mnLimit; }
     const OUString& GetMove() const { return msMove; }
@@ -91,7 +91,7 @@ private:
     LinesList *mpLines;
     size_t mnLinesCount;
     size_t mnRepaintCounter;
-    ScRange maRange;
+    SCROW mnCurRow;
     ScRange maStartRange;
     ScRangeList maBroadcastRanges;
     boost::scoped_ptr<ScRange> mpEndRange;
commit d76bc6b5c719e525cd262ade54c3e99a7644acf2
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Tue Dec 17 15:14:08 2013 -0500

    Re-organize it a bit.
    
    Change-Id: Idbd8c62a51e2de9df0396c2f18b8b25f0ad8ebf2

diff --git a/sc/source/ui/docshell/datastream.cxx b/sc/source/ui/docshell/datastream.cxx
index 42858dd..423ce07 100644
--- a/sc/source/ui/docshell/datastream.cxx
+++ b/sc/source/ui/docshell/datastream.cxx
@@ -352,14 +352,22 @@ void DataStream::MoveData()
                 meMove = MOVE_UP;
             break;
         case MOVE_UP:
-            // Remove the top row and shift the remaining rows upward.
+            if (!mpEndRange)
+                break;
+
+            // Remove the top row and shift the remaining rows upward. Then
+            // insert a new row at the end row position.
             mpDoc->DeleteRow(maStartRange);
             mpDoc->InsertRow(*mpEndRange);
             break;
         case MOVE_DOWN:
-            if (mpEndRange)
-                mpDoc->DeleteRow(*mpEndRange);
-            mpDoc->InsertRow(maRange);
+            if (!mpEndRange)
+                break;
+
+            // Remove the end row and shift the remaining rows downward by
+            // inserting a new row at the top row.
+            mpDoc->DeleteRow(*mpEndRange);
+            mpDoc->InsertRow(maStartRange);
             break;
         case NO_MOVE:
             break;
commit 49c2c79286344cdbaf30999d2e6262b032db97df
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Tue Dec 17 14:21:07 2013 -0500

    Check the parse result and handle an error case.
    
    Change-Id: Ie61f8c274754669a15e12a6f1517dacb7645c752

diff --git a/sc/source/ui/docshell/datastream.cxx b/sc/source/ui/docshell/datastream.cxx
index cde296b..42858dd 100644
--- a/sc/source/ui/docshell/datastream.cxx
+++ b/sc/source/ui/docshell/datastream.cxx
@@ -175,9 +175,13 @@ DataStream* DataStream::Set(ScDocShell *pShell, const OUString& rURL, const OUSt
     // There can be only one ScAreaLink / DataStream per cell.
     // So - if we don't need range (DataStream with mbValuesInLine == false),
     // just find a free cell for now.
-    sfx2::LinkManager* pLinkManager = pShell->GetDocument()->GetLinkManager();
     ScRange aDestArea;
-    aDestArea.Parse(rRange, pShell->GetDocument());
+    sal_uInt16 nRes = aDestArea.Parse(rRange, pShell->GetDocument());
+    if ((nRes & SCA_VALID) != SCA_VALID)
+        // Invalid range string.
+        return NULL;
+
+    sfx2::LinkManager* pLinkManager = pShell->GetDocument()->GetLinkManager();
     sal_uInt16 nLinkPos = 0;
     while (nLinkPos < pLinkManager->GetLinks().size())
     {
@@ -207,10 +211,9 @@ DataStream* DataStream::Set(ScDocShell *pShell, const OUString& rURL, const OUSt
             ++nLinkPos;
     }
 
-    sfx2::SvBaseLink *pLink = 0;
-    pLink = new DataStream( pShell, rURL, aDestArea, nLimit, rMove, nSettings );
+    DataStream* pLink = new DataStream(pShell, rURL, aDestArea, nLimit, rMove, nSettings);
     pLinkManager->InsertFileLink( *pLink, OBJECT_CLIENT_FILE, rURL, NULL, NULL );
-    return dynamic_cast<DataStream*>(pLink);
+    return pLink;
 }
 
 DataStream::DataStream(ScDocShell *pShell, const OUString& rURL, const ScRange& rRange,
commit 507c0a0fe7ec3087adfee36547ebba16d788ae92
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Tue Dec 17 14:09:25 2013 -0500

    Ensure that the initial data range has only one row.
    
    Change-Id: I97731ba02bab0ab44f19ab9cae2563ee0f71fef2

diff --git a/sc/source/ui/docshell/datastream.cxx b/sc/source/ui/docshell/datastream.cxx
index dd2d817..cde296b 100644
--- a/sc/source/ui/docshell/datastream.cxx
+++ b/sc/source/ui/docshell/datastream.cxx
@@ -208,12 +208,12 @@ DataStream* DataStream::Set(ScDocShell *pShell, const OUString& rURL, const OUSt
     }
 
     sfx2::SvBaseLink *pLink = 0;
-    pLink = new DataStream( pShell, rURL, rRange, nLimit, rMove, nSettings );
+    pLink = new DataStream( pShell, rURL, aDestArea, nLimit, rMove, nSettings );
     pLinkManager->InsertFileLink( *pLink, OBJECT_CLIENT_FILE, rURL, NULL, NULL );
     return dynamic_cast<DataStream*>(pLink);
 }
 
-DataStream::DataStream(ScDocShell *pShell, const OUString& rURL, const OUString& rRange,
+DataStream::DataStream(ScDocShell *pShell, const OUString& rURL, const ScRange& rRange,
         sal_Int32 nLimit, const OUString& rMove, sal_uInt32 nSettings) :
     mpDocShell(pShell),
     mpDoc(mpDocShell->GetDocument()),
@@ -267,11 +267,10 @@ OString DataStream::ConsumeLine()
     return mpLines->at(mnLinesCount++);
 }
 
-void DataStream::Decode(const OUString& rURL, const OUString& rRange,
+void DataStream::Decode(const OUString& rURL, const ScRange& rRange,
         sal_Int32 nLimit, const OUString& rMove, const sal_uInt32 nSettings)
 {
     msURL = rURL;
-    msRange = rRange;
     mnLimit = nLimit;
     msMove = rMove;
     mnSettings = nSettings;
@@ -286,14 +285,16 @@ void DataStream::Decode(const OUString& rURL, const OUString& rRange,
     else if (msMove == "MOVE_DOWN")
         meMove = MOVE_DOWN;
 
-    maRange.Parse(msRange);
+    maRange = rRange;
+    if (maRange.aStart.Row() != maRange.aEnd.Row())
+        // We only allow this range to be one row tall.
+        maRange.aEnd.SetRow(maRange.aStart.Row());
+
     maStartRange = maRange;
-    sal_Int32 nHeight = maRange.aEnd.Row() - maRange.aStart.Row() + 1;
-    nLimit = nHeight * (nLimit / nHeight);
     if (nLimit && maRange.aStart.Row() + nLimit - 1 < MAXROW)
     {
         mpEndRange.reset( new ScRange(maRange) );
-        mpEndRange->Move(0, nLimit - nHeight, 0);
+        mpEndRange->Move(0, nLimit-1, 0);
     }
 }
 
@@ -519,10 +520,10 @@ sfx2::SvBaseLink::UpdateResult DataStream::DataChanged(
     return SUCCESS;
 }
 
-void DataStream::Edit(Window* pWindow, const Link& )
+void DataStream::Edit( Window* pWindow, const Link& )
 {
     DataStreamDlg aDialog(mpDocShell, pWindow);
-    aDialog.Init(msURL, msRange, mnLimit, msMove, mnSettings);
+    aDialog.Init(msURL, maStartRange, mnLimit, msMove, 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 5c468a2..8b7a510 100644
--- a/sc/source/ui/inc/datastream.hxx
+++ b/sc/source/ui/inc/datastream.hxx
@@ -49,8 +49,10 @@ public:
     static DataStream* Set(ScDocShell *pShell, const OUString& rURL, const OUString& rRange,
             sal_Int32 nLimit, const OUString& rMove, sal_uInt32 nSettings);
 
-    DataStream(ScDocShell *pShell, const OUString& rURL, const OUString& rRange,
-            sal_Int32 nLimit, const OUString& rMove, sal_uInt32 nSettings);
+    DataStream(
+        ScDocShell *pShell, const OUString& rURL, const ScRange& rRange,
+        sal_Int32 nLimit, const OUString& rMove, sal_uInt32 nSettings);
+
     virtual ~DataStream();
     // sfx2::SvBaseLink
     virtual sfx2::SvBaseLink::UpdateResult DataChanged(
@@ -62,8 +64,11 @@ public:
     const sal_Int32& GetLimit() const { return mnLimit; }
     const OUString& GetMove() const { return msMove; }
     const sal_uInt32& GetSettings() const { return mnSettings; }
-    void Decode(const OUString& rURL, const OUString& rRange, sal_Int32 nLimit,
-            const OUString& rMove, const sal_uInt32 nSettings);
+
+    void Decode(
+        const OUString& rURL, const ScRange& rRange, sal_Int32 nLimit,
+        const OUString& rMove, const sal_uInt32 nSettings);
+
     bool ImportData();
     void StartImport();
     void StopImport();
@@ -77,7 +82,6 @@ private:
     ScDocument *mpDoc;
     DocumentStreamAccess maDocAccess;
     OUString msURL;
-    OUString msRange;
     OUString msMove;
     sal_Int32 mnLimit;
     sal_uInt32 mnSettings;
diff --git a/sc/source/ui/inc/datastreamdlg.hxx b/sc/source/ui/inc/datastreamdlg.hxx
index e401c66..e3308f8 100644
--- a/sc/source/ui/inc/datastreamdlg.hxx
+++ b/sc/source/ui/inc/datastreamdlg.hxx
@@ -15,6 +15,7 @@
 
 class ScDocShell;
 class SvtURLBox;
+class ScRange;
 
 namespace sc {
 
@@ -43,12 +44,15 @@ class DataStreamDlg : public ModalDialog
     DECL_LINK(BrowseHdl, void *);
 
     void UpdateEnable();
+    ScRange GetStartRange();
 
 public:
     DataStreamDlg(ScDocShell *pDocShell, Window* pParent);
-    ~DataStreamDlg() {}
-    void Init(const OUString& rURL, const OUString& rRange, const sal_Int32 nLimit,
-            const OUString& rMove, const sal_uInt32 nSettings);
+
+    void Init(
+        const OUString& rURL, const ScRange& rRange, const sal_Int32 nLimit,
+        const OUString& rMove, 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 9836d0a..06980b9 100644
--- a/sc/source/ui/miscdlgs/datastreamdlg.cxx
+++ b/sc/source/ui/miscdlgs/datastreamdlg.cxx
@@ -13,6 +13,8 @@
 #include <svtools/inettbc.hxx>
 #include <vcl/layout.hxx>
 #include <datastream.hxx>
+#include <address.hxx>
+#include <docsh.hxx>
 
 namespace sc {
 
@@ -75,14 +77,41 @@ void DataStreamDlg::UpdateEnable()
         m_pVclFrameLimit->Enable();
         m_pVclFrameMove->Enable();
         m_pEdRange->Enable();
-        bOk = bOk && !m_pEdRange->GetText().isEmpty();
+        if (bOk)
+        {
+            // Check the given range to make sure it's valid.
+            ScRange aTest = GetStartRange();
+            if (!aTest.IsValid())
+                bOk = false;
+        }
     }
     m_pBtnOk->Enable(bOk);
     setOptimalLayoutSize();
 }
 
-void DataStreamDlg::Init(const OUString& rURL, const OUString& rRange, const sal_Int32 nLimit,
-        const OUString& rMove, const sal_uInt32 nSettings)
+ScRange DataStreamDlg::GetStartRange()
+{
+    OUString aStr = m_pEdRange->GetText();
+    ScDocument* pDoc = mpDocShell->GetDocument();
+    ScRange aRange;
+    sal_uInt16 nRes = aRange.Parse(aStr, pDoc);
+    if ((nRes & SCA_VALID) != SCA_VALID || !aRange.IsValid())
+    {
+        // Invalid range.
+        aRange.SetInvalid();
+        return aRange;
+    }
+
+    // Make sure it's only one row tall.
+    if (aRange.aStart.Row() != aRange.aEnd.Row())
+        aRange.SetInvalid();
+
+    return aRange;
+}
+
+void DataStreamDlg::Init(
+    const OUString& rURL, const ScRange& rRange, const sal_Int32 nLimit,
+    const OUString& rMove, const sal_uInt32 nSettings)
 {
     m_pEdLimit->SetText(OUString::number(nLimit));
     m_pCbUrl->SetText(rURL);
@@ -90,7 +119,10 @@ void DataStreamDlg::Init(const OUString& rURL, const OUString& rRange, const sal
         m_pRBScriptData->Check();
     if (!(nSettings & DataStream::VALUES_IN_LINE))
         m_pRBAddressValue->Check();
-    m_pEdRange->SetText(rRange);
+
+    OUString aStr = rRange.Format(SCA_VALID);
+    m_pEdRange->SetText(aStr);
+
     if (rMove == "NO_MOVE")
         m_pRBNoMove->Check();
     else if (rMove == "RANGE_DOWN")
@@ -102,6 +134,11 @@ void DataStreamDlg::Init(const OUString& rURL, const OUString& rRange, const sal
 
 void DataStreamDlg::StartStream(DataStream *pStream)
 {
+    ScRange aStartRange = GetStartRange();
+    if (!aStartRange.IsValid())
+        // Don't start the stream without a valid range.
+        return;
+
     sal_Int32 nLimit = 0;
     if (m_pRBMaxLimit->IsChecked())
         nLimit = m_pEdLimit->GetText().toInt32();
@@ -113,7 +150,7 @@ void DataStreamDlg::StartStream(DataStream *pStream)
        nSettings |= DataStream::VALUES_IN_LINE;
     if (pStream)
     {
-        pStream->Decode(rURL, m_pEdRange->GetText(), nLimit,
+        pStream->Decode(rURL, aStartRange, nLimit,
                 m_pRBNoMove->IsChecked() ? OUString("NO_MOVE") : m_pRBRangeDown->IsChecked()
                     ? OUString("RANGE_DOWN") : OUString("MOVE_DOWN"),
                 nSettings);
commit 374b3df291cd8af05833e7b9acd6ec2efb19b468
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Tue Dec 17 11:41:10 2013 -0500

    Set sensible default values in the UI.
    
    Change-Id: Ibafbeae0becaca4f0b217b6a5a78bee048fceea0

diff --git a/sc/uiconfig/scalc/ui/datastreams.ui b/sc/uiconfig/scalc/ui/datastreams.ui
index 1c2abe7..cd48886 100644
--- a/sc/uiconfig/scalc/ui/datastreams.ui
+++ b/sc/uiconfig/scalc/ui/datastreams.ui
@@ -174,6 +174,7 @@
                                         <property name="receives_default">False</property>
                                         <property name="use_underline">True</property>
                                         <property name="xalign">0</property>
+                                        <property name="active">True</property>
                                         <property name="draw_indicator">True</property>
                                         <property name="group">addressvalue</property>
                                       </object>
@@ -323,6 +324,7 @@
                                 <property name="can_focus">True</property>
                                 <property name="receives_default">False</property>
                                 <property name="use_underline">True</property>
+                                <property name="active">True</property>
                                 <property name="xalign">0</property>
                                 <property name="draw_indicator">True</property>
                                 <property name="group">datadown</property>
@@ -401,6 +403,7 @@
                                 <property name="receives_default">False</property>
                                 <property name="use_underline">True</property>
                                 <property name="xalign">0</property>
+                                <property name="active">True</property>
                                 <property name="draw_indicator">True</property>
                                 <property name="group">unlimited</property>
                               </object>
commit 8538722a494c190aa432356111ffc87c87ce4e76
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Tue Dec 17 11:36:18 2013 -0500

    Add sc::DocumentStreamAccess class.
    
    To provide the DataStream class with a fast way to manipulate document
    content without altering broadcaster positions or unnecessary broadcasting.
    
    Change-Id: Ib329313b8668c9a1698ea05372de6269d089859c

diff --git a/sc/Library_sc.mk b/sc/Library_sc.mk
index 23d5040..b60af82 100644
--- a/sc/Library_sc.mk
+++ b/sc/Library_sc.mk
@@ -118,6 +118,7 @@ $(eval $(call gb_Library_add_exception_objects,sc,\
     sc/source/core/data/documen9 \
     sc/source/core/data/document \
     sc/source/core/data/documentimport \
+    sc/source/core/data/documentstreamaccess \
     sc/source/core/data/dpdimsave \
     sc/source/core/data/dpfilteredcache \
     sc/source/core/data/dpglobal \
diff --git a/sc/inc/column.hxx b/sc/inc/column.hxx
index ba16644..55b3847 100644
--- a/sc/inc/column.hxx
+++ b/sc/inc/column.hxx
@@ -55,6 +55,7 @@ struct RefUpdateDeleteTabContext;
 struct RefUpdateMoveTabContext;
 class EditTextIterator;
 struct NoteEntry;
+class DocumentStreamAccess;
 
 }
 
@@ -138,6 +139,7 @@ friend class ScHorizontalCellIterator;
 friend class ScHorizontalAttrIterator;
 friend class ScColumnTextWidthIterator;
 friend class ScDocumentImport;
+friend class sc::DocumentStreamAccess;
 friend class sc::SingleColumnSpanSet;
 friend class sc::ColumnSpanSet;
 friend class sc::EditTextIterator;
diff --git a/sc/inc/document.hxx b/sc/inc/document.hxx
index c560d20..61dd1bd 100644
--- a/sc/inc/document.hxx
+++ b/sc/inc/document.hxx
@@ -69,6 +69,7 @@ struct RefUpdateContext;
 class EditTextIterator;
 struct NoteEntry;
 struct FormulaGroupContext;
+class DocumentStreamAccess;
 
 }
 
@@ -247,6 +248,7 @@ friend class ScTable;
 friend class ScColumn;
 friend struct ScRefCellValue;
 friend class ScDocumentImport;
+friend class sc::DocumentStreamAccess;
 friend class sc::ColumnSpanSet;
 friend class sc::EditTextIterator;
 
diff --git a/sc/inc/documentstreamaccess.hxx b/sc/inc/documentstreamaccess.hxx
new file mode 100644
index 0000000..1450f21
--- /dev/null
+++ b/sc/inc/documentstreamaccess.hxx
@@ -0,0 +1,37 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef SC_DOCUMENTSTREAMACCESS_HXX
+#define SC_DOCUMENTSTREAMACCESS_HXX
+
+class ScDocument;
+
+namespace sc {
+
+struct DocumentStreamAccessImpl;
+
+/**
+ * Provides methods to allow direct shifting of document content without
+ * broadcasting or shifting of broadcaster positions.
+ */
+class DocumentStreamAccess
+{
+    DocumentStreamAccessImpl* mpImpl;
+
+    DocumentStreamAccess();
+
+public:
+    DocumentStreamAccess( ScDocument& rDoc );
+};
+
+}
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/inc/table.hxx b/sc/inc/table.hxx
index f07e8d4..1a80f90 100644
--- a/sc/inc/table.hxx
+++ b/sc/inc/table.hxx
@@ -67,6 +67,7 @@ struct RefUpdateInsertTabContext;
 struct RefUpdateDeleteTabContext;
 struct RefUpdateMoveTabContext;
 struct NoteEntry;
+class DocumentStreamAccess;
 
 }
 
@@ -208,6 +209,7 @@ friend class ScDocAttrIterator;
 friend class ScAttrRectIterator;
 friend class ScColumnTextWidthIterator;
 friend class ScDocumentImport;
+friend class sc::DocumentStreamAccess;
 friend class sc::ColumnSpanSet;
 friend class sc::EditTextIterator;
 
diff --git a/sc/source/core/data/documentstreamaccess.cxx b/sc/source/core/data/documentstreamaccess.cxx
new file mode 100644
index 0000000..2d427af
--- /dev/null
+++ b/sc/source/core/data/documentstreamaccess.cxx
@@ -0,0 +1,27 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "documentstreamaccess.hxx"
+#include "document.hxx"
+
+namespace sc {
+
+struct DocumentStreamAccessImpl
+{
+    ScDocument& mrDoc;
+
+    DocumentStreamAccessImpl( ScDocument& rDoc ) : mrDoc(rDoc) {}
+};
+
+DocumentStreamAccess::DocumentStreamAccess( ScDocument& rDoc ) :
+    mpImpl(new DocumentStreamAccessImpl(rDoc)) {}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/docshell/datastream.cxx b/sc/source/ui/docshell/datastream.cxx
index 0097311..dd2d817 100644
--- a/sc/source/ui/docshell/datastream.cxx
+++ b/sc/source/ui/docshell/datastream.cxx
@@ -214,14 +214,15 @@ DataStream* DataStream::Set(ScDocShell *pShell, const OUString& rURL, const OUSt
 }
 
 DataStream::DataStream(ScDocShell *pShell, const OUString& rURL, const OUString& rRange,
-        sal_Int32 nLimit, const OUString& rMove, sal_uInt32 nSettings)
-    : mpScDocShell(pShell)
-    , mpScDocument(mpScDocShell->GetDocument())
-    , meMove(NO_MOVE)
-    , mbRunning(false)
-    , mpLines(0)
-    , mnLinesCount(0)
-    , mnRepaintCounter(0)
+        sal_Int32 nLimit, const OUString& rMove, sal_uInt32 nSettings) :
+    mpDocShell(pShell),
+    mpDoc(mpDocShell->GetDocument()),
+    maDocAccess(*mpDoc),
+    meMove(NO_MOVE),
+    mbRunning(false),
+    mpLines(0),
+    mnLinesCount(0),
+    mnRepaintCounter(0)
 {
     mxThread = new datastreams::CallerThread( this );
     mxThread->launch();
@@ -328,13 +329,13 @@ void DataStream::Repaint()
     ScRange aRange(maStartRange.aStart);
     aRange.aEnd = ScAddress(maRange.aEnd.Col(), nEndRow, maRange.aStart.Tab());
 
-    mpScDocShell->PostPaint(aRange, PAINT_GRID);
+    mpDocShell->PostPaint(aRange, PAINT_GRID);
     mnRepaintCounter = 0;
 }
 
 void DataStream::Broadcast()
 {
-    mpScDocument->BroadcastCells(maBroadcastRanges, SC_HINT_DATACHANGED);
+    mpDoc->BroadcastCells(maBroadcastRanges, SC_HINT_DATACHANGED);
     maBroadcastRanges.RemoveAll();
 }
 
@@ -347,13 +348,14 @@ void DataStream::MoveData()
                 meMove = MOVE_UP;
             break;
         case MOVE_UP:
-            mpScDocument->DeleteRow(maStartRange);
-            mpScDocument->InsertRow(*mpEndRange);
+            // Remove the top row and shift the remaining rows upward.
+            mpDoc->DeleteRow(maStartRange);
+            mpDoc->InsertRow(*mpEndRange);
             break;
         case MOVE_DOWN:
             if (mpEndRange)
-                mpScDocument->DeleteRow(*mpEndRange);
-            mpScDocument->InsertRow(maRange);
+                mpDoc->DeleteRow(*mpEndRange);
+            mpDoc->InsertRow(maRange);
             break;
         case NO_MOVE:
             break;
@@ -400,7 +402,7 @@ void DataStream::Text2Doc()
     SCROW nEndRow = maRange.aEnd.Row();
     OUString aCell;
     SCROW nRow = nStartRow;
-    ScDocumentImport aDocImport(*mpScDocument);
+    ScDocumentImport aDocImport(*mpDoc);
     while (nRow <= nEndRow)
     {
         SCCOL nCol = nStartCol;
@@ -458,7 +460,7 @@ bool DataStream::ImportData()
     }
     else
     {
-        ScDocumentImport aDocImport(*mpScDocument);
+        ScDocumentImport aDocImport(*mpDoc);
         // read more lines at once but not too much
         for (int i = 0; i < 10; ++i)
         {
@@ -469,7 +471,7 @@ bool DataStream::ImportData()
             OUString sAddress( sLine.copy(0, sLine.indexOf(',')) );
             OUString sValue( sLine.copy(sLine.indexOf(',') + 1) );
             ScAddress aAddress;
-            aAddress.Parse(sAddress, mpScDocument);
+            aAddress.Parse(sAddress, mpDoc);
             if (!aAddress.IsValid())
                 continue;
 
@@ -481,14 +483,14 @@ bool DataStream::ImportData()
         }
         aDocImport.finalize();
     }
-    mpScDocShell->SetDocumentModified();
+    mpDocShell->SetDocumentModified();
     if (meMove == NO_MOVE)
         return mbRunning;
 
     if (meMove == RANGE_DOWN)
     {
         maRange.Move(0, maRange.aEnd.Row() - maRange.aStart.Row() + 1, 0);
-        mpScDocShell->GetViewData()->GetView()->AlignToCursor(
+        mpDocShell->GetViewData()->GetView()->AlignToCursor(
                 maRange.aStart.Col(), maRange.aStart.Row(), SC_FOLLOW_JUMP);
     }
 
@@ -519,7 +521,7 @@ sfx2::SvBaseLink::UpdateResult DataStream::DataChanged(
 
 void DataStream::Edit(Window* pWindow, const Link& )
 {
-    DataStreamDlg aDialog(mpScDocShell, pWindow);
+    DataStreamDlg aDialog(mpDocShell, pWindow);
     aDialog.Init(msURL, msRange, mnLimit, msMove, mnSettings);
     if (aDialog.Execute() == RET_OK)
     {
diff --git a/sc/source/ui/inc/datastream.hxx b/sc/source/ui/inc/datastream.hxx
index 42a8ab1..5c468a2 100644
--- a/sc/source/ui/inc/datastream.hxx
+++ b/sc/source/ui/inc/datastream.hxx
@@ -19,6 +19,7 @@
 #include <vector>
 
 #include <rangelst.hxx>
+#include <documentstreamaccess.hxx>
 
 class ScDocShell;
 class ScDocument;
@@ -72,8 +73,9 @@ private:
     void Broadcast();
 
 private:
-    ScDocShell *mpScDocShell;
-    ScDocument *mpScDocument;
+    ScDocShell *mpDocShell;
+    ScDocument *mpDoc;
+    DocumentStreamAccess maDocAccess;
     OUString msURL;
     OUString msRange;
     OUString msMove;
commit 2fe4112c5b6c48e4ab39335854406ff8255d7280
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Tue Dec 17 10:19:57 2013 -0500

    Put these new classes in sc namespace.
    
    Change-Id: Id75c63521def501a4c8c55d4cd45b66a010a9580

diff --git a/sc/source/core/data/documen8.cxx b/sc/source/core/data/documen8.cxx
index 09bef92..dfd8a36 100644
--- a/sc/source/core/data/documen8.cxx
+++ b/sc/source/core/data/documen8.cxx
@@ -1194,7 +1194,7 @@ bool ScDocument::HasAreaLinks() const
         const ::sfx2::SvBaseLinks& rLinks = pLinkManager->GetLinks();
         sal_uInt16 nCount = rLinks.size();
         for (sal_uInt16 i=0; i<nCount; i++)
-            if ((*rLinks[i])->ISA(ScAreaLink) || (*rLinks[i])->ISA(DataStream))
+            if ((*rLinks[i])->ISA(ScAreaLink) || (*rLinks[i])->ISA(sc::DataStream))
                 return true;
     }
 
@@ -1209,7 +1209,7 @@ void ScDocument::UpdateAreaLinks()
         for (sal_uInt16 i=0; i<rLinks.size(); i++)
         {
             ::sfx2::SvBaseLink* pBase = *rLinks[i];
-            if (pBase->ISA(ScAreaLink) || (*rLinks[i])->ISA(DataStream))
+            if (pBase->ISA(ScAreaLink) || (*rLinks[i])->ISA(sc::DataStream))
                 pBase->Update();
         }
     }
diff --git a/sc/source/filter/xml/xmlcelli.cxx b/sc/source/filter/xml/xmlcelli.cxx
index 1875afa..1223d3c5 100644
--- a/sc/source/filter/xml/xmlcelli.cxx
+++ b/sc/source/filter/xml/xmlcelli.cxx
@@ -1005,7 +1005,7 @@ void ScXMLTableRowCellContext::SetCellRangeSource( const ScAddress& rPosition )
             SvtMiscOptions aMiscOptions;
             if (aMiscOptions.IsExperimentalMode() && pCellRangeSource->sFilterOptions == "DataStream")
             {
-                DataStream::Set( dynamic_cast<ScDocShell*>(pDoc->GetDocumentShell())
+                sc::DataStream::Set( dynamic_cast<ScDocShell*>(pDoc->GetDocumentShell())
                         , pCellRangeSource->sURL // rURL
                         , sRangeStr // rRange
                         , sFilterName.toInt32() // nLimit
diff --git a/sc/source/filter/xml/xmlexprt.cxx b/sc/source/filter/xml/xmlexprt.cxx
index d1b5af3..51f2175 100644
--- a/sc/source/filter/xml/xmlexprt.cxx
+++ b/sc/source/filter/xml/xmlexprt.cxx
@@ -836,7 +836,7 @@ void ScXMLExport::GetAreaLinks( ScMyAreaLinksContainer& rAreaLinks )
                 aAreaLink.nRefresh = pLink->GetTimeout();
                 rAreaLinks.AddNewAreaLink( aAreaLink );
             }
-            DataStream *pStream = dynamic_cast<DataStream*>(&(*(*rLinks[i])));
+            sc::DataStream *pStream = dynamic_cast<sc::DataStream*>(&(*(*rLinks[i])));
             if (pStream)
             {
                 ScMyAreaLink aAreaLink;
diff --git a/sc/source/ui/docshell/datastream.cxx b/sc/source/ui/docshell/datastream.cxx
index e4fb6b0..0097311 100644
--- a/sc/source/ui/docshell/datastream.cxx
+++ b/sc/source/ui/docshell/datastream.cxx
@@ -30,6 +30,8 @@
 
 #include <queue>
 
+namespace sc {
+
 namespace datastreams {
 
 class CallerThread : public salhelper::Thread
@@ -529,4 +531,6 @@ void DataStream::Edit(Window* pWindow, const Link& )
     }
 }
 
+} // namespace sc
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/inc/datastream.hxx b/sc/source/ui/inc/datastream.hxx
index bb04604..42a8ab1 100644
--- a/sc/source/ui/inc/datastream.hxx
+++ b/sc/source/ui/inc/datastream.hxx
@@ -20,13 +20,16 @@
 
 #include <rangelst.hxx>
 
+class ScDocShell;
+class ScDocument;
+class Window;
+
+namespace sc {
+
 namespace datastreams {
     class CallerThread;
     class ReaderThread;
 }
-class ScDocShell;
-class ScDocument;
-class Window;
 
 typedef std::vector<OString> LinesList;
 
@@ -90,4 +93,6 @@ private:
     rtl::Reference<datastreams::ReaderThread> mxReaderThread;
 };
 
+}
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/inc/datastreamdlg.hxx b/sc/source/ui/inc/datastreamdlg.hxx
index 162a0d6..e401c66 100644
--- a/sc/source/ui/inc/datastreamdlg.hxx
+++ b/sc/source/ui/inc/datastreamdlg.hxx
@@ -13,10 +13,13 @@
 #include <vcl/dialog.hxx>
 #include <vcl/layout.hxx>
 
-class DataStream;
 class ScDocShell;
 class SvtURLBox;
 
+namespace sc {
+
+class DataStream;
+
 class DataStreamDlg : public ModalDialog
 {
     ScDocShell *mpDocShell;
@@ -49,4 +52,6 @@ public:
     void StartStream(DataStream *pStream = 0);
 };
 
+}
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/miscdlgs/datastreamdlg.cxx b/sc/source/ui/miscdlgs/datastreamdlg.cxx
index a6d0a92..9836d0a 100644
--- a/sc/source/ui/miscdlgs/datastreamdlg.cxx
+++ b/sc/source/ui/miscdlgs/datastreamdlg.cxx
@@ -14,6 +14,8 @@
 #include <vcl/layout.hxx>
 #include <datastream.hxx>
 
+namespace sc {
+
 DataStreamDlg::DataStreamDlg(ScDocShell *pDocShell, Window* pParent)
     : ModalDialog(pParent, "DataStreamDialog", "modules/scalc/ui/datastreams.ui")
     , mpDocShell(pDocShell)
@@ -129,4 +131,6 @@ void DataStreamDlg::StartStream(DataStream *pStream)
     pStream->StartImport();
 }
 
+}
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/view/cellsh2.cxx b/sc/source/ui/view/cellsh2.cxx
index 71c9282..1b5aa69 100644
--- a/sc/source/ui/view/cellsh2.cxx
+++ b/sc/source/ui/view/cellsh2.cxx
@@ -738,7 +738,7 @@ void ScCellShell::ExecuteDB( SfxRequest& rReq )
             break;
         case SID_DATA_STREAMS:
             {
-                DataStreamDlg aDialog( GetViewData()->GetDocShell(), pTabViewShell->GetDialogParent() );
+                sc::DataStreamDlg aDialog( GetViewData()->GetDocShell(), pTabViewShell->GetDialogParent() );
                 if (aDialog.Execute() == RET_OK)
                     aDialog.StartStream();
             }
@@ -750,7 +750,7 @@ void ScCellShell::ExecuteDB( SfxRequest& rReq )
                 {
                     const sfx2::SvBaseLinks& rLinks = pDoc->GetLinkManager()->GetLinks();
                     for (size_t i = 0; i < rLinks.size(); i++)
-                        if (DataStream *pStream = dynamic_cast<DataStream*>(&(*(*rLinks[i]))))
+                        if (sc::DataStream *pStream = dynamic_cast<sc::DataStream*>(&(*(*rLinks[i]))))
                             pStream->StartImport();
                 }
             }
@@ -762,7 +762,7 @@ void ScCellShell::ExecuteDB( SfxRequest& rReq )
                 {
                     const sfx2::SvBaseLinks& rLinks = pDoc->GetLinkManager()->GetLinks();
                     for (size_t i = 0; i < rLinks.size(); i++)
-                        if (DataStream *pStream = dynamic_cast<DataStream*>(&(*(*rLinks[i]))))
+                        if (sc::DataStream *pStream = dynamic_cast<sc::DataStream*>(&(*(*rLinks[i]))))
                             pStream->StopImport();
                 }
             }
commit 5945b187a5b5a01783b2a7e934dc5c4b9ace41ed
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Tue Dec 17 00:05:22 2013 -0500

    Try to consolidate all broadcast calls into one place. Still WIP.
    
    Change-Id: I7b75307de3ae91726facb67ea8d3fb6999e1f9c7

diff --git a/sc/inc/document.hxx b/sc/inc/document.hxx
index 47ff391..c560d20 100644
--- a/sc/inc/document.hxx
+++ b/sc/inc/document.hxx
@@ -1815,6 +1815,10 @@ public:
                             Preferred.
                          */
     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 7dd9821..ec2e1cf 100644
--- a/sc/source/core/data/documen7.cxx
+++ b/sc/source/core/data/documen7.cxx
@@ -104,6 +104,33 @@ 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 )
 {
diff --git a/sc/source/ui/docshell/datastream.cxx b/sc/source/ui/docshell/datastream.cxx
index d03a01e..e4fb6b0 100644
--- a/sc/source/ui/docshell/datastream.cxx
+++ b/sc/source/ui/docshell/datastream.cxx
@@ -327,6 +327,13 @@ void DataStream::Repaint()
     aRange.aEnd = ScAddress(maRange.aEnd.Col(), nEndRow, maRange.aStart.Tab());
 
     mpScDocShell->PostPaint(aRange, PAINT_GRID);
+    mnRepaintCounter = 0;
+}
+
+void DataStream::Broadcast()
+{
+    mpScDocument->BroadcastCells(maBroadcastRanges, SC_HINT_DATACHANGED);
+    maBroadcastRanges.RemoveAll();
 }
 
 void DataStream::MoveData()
@@ -342,7 +349,7 @@ void DataStream::MoveData()
             mpScDocument->InsertRow(*mpEndRange);
             break;
         case MOVE_DOWN:
-            if (mpEndRange.get())
+            if (mpEndRange)
                 mpScDocument->DeleteRow(*mpEndRange);
             mpScDocument->InsertRow(maRange);
             break;
@@ -422,14 +429,17 @@ void DataStream::Text2Doc()
                     aDocImport.setNumericCell(aAddress, aCell.toDouble());
                 else
                     aDocImport.setStringCell(aAddress, aCell);
-                mpScDocument->Broadcast(ScHint(SC_HINT_DATACHANGED, aAddress));
             }
             ++nCol;
         }
         ++nRow;
         ++mnRepaintCounter;
     }
+
     aDocImport.finalize();
+
+    ScRange aBCRange(nStartCol, nStartRow, maRange.aStart.Tab(), nEndCol, nEndRow, maRange.aStart.Tab());
+    maBroadcastRanges.Join(aBCRange);
 }
 
 bool DataStream::ImportData()
@@ -446,7 +456,6 @@ bool DataStream::ImportData()
     }
     else
     {
-        ScRangeList aRangeList;
         ScDocumentImport aDocImport(*mpScDocument);
         // read more lines at once but not too much
         for (int i = 0; i < 10; ++i)
@@ -466,8 +475,7 @@ bool DataStream::ImportData()
                 aDocImport.setNumericCell(aAddress, sValue.toDouble());
             else
                 aDocImport.setStringCell(aAddress, sValue);
-            aRangeList.Join(aAddress);
-            mpScDocument->Broadcast(ScHint(SC_HINT_DATACHANGED, aAddress));
+            maBroadcastRanges.Join(aAddress);
         }
         aDocImport.finalize();
     }
@@ -483,10 +491,7 @@ bool DataStream::ImportData()
     }
 
     if (mnRepaintCounter > 100)
-    {
         Repaint();
-        mnRepaintCounter = 0;
-    }
 
     return mbRunning;
 }
diff --git a/sc/source/ui/inc/datastream.hxx b/sc/source/ui/inc/datastream.hxx
index 3a80646..bb04604 100644
--- a/sc/source/ui/inc/datastream.hxx
+++ b/sc/source/ui/inc/datastream.hxx
@@ -18,6 +18,8 @@
 #include <boost/scoped_ptr.hpp>
 #include <vector>
 
+#include <rangelst.hxx>
+
 namespace datastreams {
     class CallerThread;
     class ReaderThread;
@@ -64,6 +66,7 @@ public:
 
 private:
     void Repaint();
+    void Broadcast();
 
 private:
     ScDocShell *mpScDocShell;
@@ -81,6 +84,7 @@ private:
     size_t mnRepaintCounter;
     ScRange maRange;
     ScRange maStartRange;
+    ScRangeList maBroadcastRanges;
     boost::scoped_ptr<ScRange> mpEndRange;
     rtl::Reference<datastreams::CallerThread> mxThread;
     rtl::Reference<datastreams::ReaderThread> mxReaderThread;
commit 1d6e5dbaff0fadd8ffbb689e318be466eef9d451
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Thu Dec 12 16:09:11 2013 +0100

    Try to reduce the amount of repainting during streaming.

diff --git a/sc/source/ui/docshell/datastream.cxx b/sc/source/ui/docshell/datastream.cxx
index 7f529dd..d03a01e 100644
--- a/sc/source/ui/docshell/datastream.cxx
+++ b/sc/source/ui/docshell/datastream.cxx
@@ -32,6 +32,37 @@
 
 namespace datastreams {
 
+class CallerThread : public salhelper::Thread
+{
+    DataStream *mpDataStream;
+public:
+    osl::Condition maStart;
+    bool mbTerminate;
+
+    CallerThread(DataStream *pData):
+        Thread("CallerThread")
+        ,mpDataStream(pData)
+        ,mbTerminate(false)
+    {}
+
+private:
+    virtual void execute()
+    {
+        while (!mbTerminate)
+        {
+            // wait for a small amount of time, so that
+            // painting methods have a chance to be called.
+            // And also to make UI more responsive.
+            TimeValue const aTime = {0, 100000};
+            maStart.wait();
+            maStart.reset();
+            if (!mbTerminate)
+                while (mpDataStream->ImportData())
+                    wait(aTime);
+        };
+    }
+};
+
 class ReaderThread : public salhelper::Thread
 {
     SvStream *mpStream;
@@ -188,10 +219,11 @@ DataStream::DataStream(ScDocShell *pShell, const OUString& rURL, const OUString&
     , mbRunning(false)
     , mpLines(0)
     , mnLinesCount(0)
+    , mnRepaintCounter(0)
 {
-    SetRefreshHandler(LINK( this, DataStream, RefreshHdl ));
-    SetRefreshControl(mpScDocument->GetRefreshTimerControlAddress());
-    SetTimeout( 1 );
+    mxThread = new datastreams::CallerThread( this );
+    mxThread->launch();
+
     Decode(rURL, rRange, nLimit, rMove, nSettings);
 }
 
@@ -199,6 +231,9 @@ DataStream::~DataStream()
 {
     if (mbRunning)
         StopImport();
+    mxThread->mbTerminate = true;
+    mxThread->maStart.set();
+    mxThread->join();
     if (mxReaderThread.is())
         mxReaderThread->endThread();
     delete mpLines;
@@ -274,7 +309,7 @@ void DataStream::StartImport()
         mxReaderThread->launch();
     }
     mbRunning = true;
-    AutoTimer::Start();
+    mxThread->maStart.set();
 }
 
 void DataStream::StopImport()
@@ -282,7 +317,16 @@ void DataStream::StopImport()
     if (!mbRunning)
         return;
     mbRunning = false;
-    AutoTimer::Stop();
+    Repaint();
+}
+
+void DataStream::Repaint()
+{
+    SCROW nEndRow = mpEndRange ? mpEndRange->aEnd.Row() : MAXROW;
+    ScRange aRange(maStartRange.aStart);
+    aRange.aEnd = ScAddress(maRange.aEnd.Col(), nEndRow, maRange.aStart.Tab());
+
+    mpScDocShell->PostPaint(aRange, PAINT_GRID);
 }
 
 void DataStream::MoveData()
@@ -383,13 +427,14 @@ void DataStream::Text2Doc()
             ++nCol;
         }
         ++nRow;
+        ++mnRepaintCounter;
     }
     aDocImport.finalize();
-    mpScDocShell->PostPaint( maRange, PAINT_GRID );
 }
 
 bool DataStream::ImportData()
 {
+    SolarMutexGuard aGuard;
     if (ScDocShell::GetViewData()->GetViewShell()->NeedsRepaint())
         return mbRunning;
 
@@ -425,7 +470,6 @@ bool DataStream::ImportData()
             mpScDocument->Broadcast(ScHint(SC_HINT_DATACHANGED, aAddress));
         }
         aDocImport.finalize();
-        mpScDocShell->PostPaint( aRangeList, PAINT_GRID );
     }
     mpScDocShell->SetDocumentModified();
     if (meMove == NO_MOVE)
@@ -437,9 +481,12 @@ bool DataStream::ImportData()
         mpScDocShell->GetViewData()->GetView()->AlignToCursor(
                 maRange.aStart.Col(), maRange.aStart.Row(), SC_FOLLOW_JUMP);
     }
-    SCROW aEndRow = mpEndRange.get() ? mpEndRange->aEnd.Row() : MAXROW;
-    mpScDocShell->PostPaint( ScRange( maStartRange.aStart, ScAddress( maRange.aEnd.Col(),
-                    aEndRow, maRange.aStart.Tab()) ), PAINT_GRID );
+
+    if (mnRepaintCounter > 100)
+    {
+        Repaint();
+        mnRepaintCounter = 0;
+    }
 
     return mbRunning;
 }
diff --git a/sc/source/ui/inc/datastream.hxx b/sc/source/ui/inc/datastream.hxx
index 6eb1e7d..3a80646 100644
--- a/sc/source/ui/inc/datastream.hxx
+++ b/sc/source/ui/inc/datastream.hxx
@@ -13,13 +13,13 @@
 #include <rtl/ustring.hxx>
 #include <sfx2/lnkbase.hxx>
 #include <address.hxx>
-#include <refreshtimer.hxx>
 
 #include <boost/noncopyable.hpp>
 #include <boost/scoped_ptr.hpp>
 #include <vector>
 
 namespace datastreams {
+    class CallerThread;
     class ReaderThread;
 }
 class ScDocShell;
@@ -28,7 +28,7 @@ class Window;
 
 typedef std::vector<OString> LinesList;
 
-class DataStream : boost::noncopyable, public sfx2::SvBaseLink, ScRefreshTimer
+class DataStream : boost::noncopyable, public sfx2::SvBaseLink
 {
     OString ConsumeLine();
     void MoveData();
@@ -63,6 +63,9 @@ public:
     void StopImport();
 
 private:
+    void Repaint();
+
+private:
     ScDocShell *mpScDocShell;
     ScDocument *mpScDocument;
     OUString msURL;
@@ -75,9 +78,11 @@ private:
     bool mbValuesInLine;
     LinesList *mpLines;
     size_t mnLinesCount;
+    size_t mnRepaintCounter;
     ScRange maRange;
     ScRange maStartRange;
     boost::scoped_ptr<ScRange> mpEndRange;
+    rtl::Reference<datastreams::CallerThread> mxThread;
     rtl::Reference<datastreams::ReaderThread> mxReaderThread;
 };
 


More information about the Libreoffice-commits mailing list