summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--RepositoryExternal.mk4
-rw-r--r--include/xmloff/xmltoken.hxx3
-rw-r--r--sc/Library_sc.mk10
-rw-r--r--sc/Library_scqahelper.mk8
-rw-r--r--sc/inc/column.hxx2
-rw-r--r--sc/inc/document.hxx8
-rw-r--r--sc/inc/documentlinkmgr.hxx36
-rw-r--r--sc/inc/documentstreamaccess.hxx62
-rw-r--r--sc/inc/importfilterdata.hxx49
-rw-r--r--sc/inc/mtvelements.hxx2
-rw-r--r--sc/inc/table.hxx2
-rw-r--r--sc/inc/xmlwrap.hxx6
-rw-r--r--sc/source/core/data/documen2.cxx14
-rw-r--r--sc/source/core/data/documen8.cxx5
-rw-r--r--sc/source/core/data/documentstreamaccess.cxx143
-rw-r--r--sc/source/core/data/mtvelements.cxx6
-rw-r--r--sc/source/filter/importfilterdata.cxx19
-rw-r--r--sc/source/filter/xml/datastreamimport.cxx92
-rw-r--r--sc/source/filter/xml/datastreamimport.hxx38
-rw-r--r--sc/source/filter/xml/xmlbodyi.cxx4
-rw-r--r--sc/source/filter/xml/xmlcelli.cxx14
-rw-r--r--sc/source/filter/xml/xmlexprt.cxx58
-rw-r--r--sc/source/filter/xml/xmlexprt.hxx1
-rw-r--r--sc/source/filter/xml/xmlimprt.cxx31
-rw-r--r--sc/source/filter/xml/xmlimprt.hxx27
-rw-r--r--sc/source/filter/xml/xmlwrap.cxx9
-rw-r--r--sc/source/ui/docshell/datastream.cxx511
-rw-r--r--sc/source/ui/docshell/docsh.cxx34
-rw-r--r--sc/source/ui/docshell/documentlinkmgr.cxx44
-rw-r--r--sc/source/ui/inc/datastream.hxx85
-rw-r--r--sc/source/ui/inc/datastreamdlg.hxx20
-rw-r--r--sc/source/ui/inc/gridwin.hxx1
-rw-r--r--sc/source/ui/inc/tabview.hxx1
-rw-r--r--sc/source/ui/miscdlgs/datastreamdlg.cxx124
-rw-r--r--sc/source/ui/view/cellsh2.cxx58
-rw-r--r--sc/source/ui/view/tabview3.cxx10
-rw-r--r--sc/uiconfig/scalc/ui/datastreams.ui3
-rw-r--r--xmloff/source/core/xmltoken.cxx3
38 files changed, 1184 insertions, 363 deletions
diff --git a/RepositoryExternal.mk b/RepositoryExternal.mk
index 3073c565a91d..689b5f595b73 100644
--- a/RepositoryExternal.mk
+++ b/RepositoryExternal.mk
@@ -2624,6 +2624,10 @@ endef
define gb_LinkTarget__use_orcus-parser
$(call gb_LinkTarget_use_external_project,$(1),liborcus)
+$(call gb_LinkTarget_set_include,$(1),\
+ -I$(call gb_UnpackedTarball_get_dir,liborcus/include) \
+ $$(INCLUDE) \
+)
$(call gb_LinkTarget_add_libs,$(1),\
$(call gb_UnpackedTarball_get_dir,liborcus)/src/parser/.libs/liborcus-parser-0.6$(gb_StaticLibrary_PLAINEXT) \
)
diff --git a/include/xmloff/xmltoken.hxx b/include/xmloff/xmltoken.hxx
index f9196afcc54c..d288c8848843 100644
--- a/include/xmloff/xmltoken.hxx
+++ b/include/xmloff/xmltoken.hxx
@@ -550,6 +550,7 @@ namespace xmloff { namespace token {
XML_DATA_PILOT_TABLE,
XML_DATA_PILOT_TABLES,
XML_DATA_POINT,
+ XML_DATA_STREAM_SOURCE,
XML_DATA_STYLE,
XML_DATA_STYLE_NAME,
XML_DATA_TYPE,
@@ -669,6 +670,7 @@ namespace xmloff { namespace token {
XML_EMBOSSED,
XML_EMISSIVE_COLOR,
XML_EMPTY,
+ XML_EMPTY_LINE_REFRESH,
XML_ENABLE_NUMBERING,
XML_ENABLED,
XML_ENCODING,
@@ -1022,6 +1024,7 @@ namespace xmloff { namespace token {
XML_INPROCEEDINGS,
XML_INSERTION,
XML_INSERTION_CUT_OFF,
+ XML_INSERTION_POSITION,
XML_INSET,
XML_INSIDE,
XML_INSTITUTION,
diff --git a/sc/Library_sc.mk b/sc/Library_sc.mk
index fe2ddf89580e..791752f28ce4 100644
--- a/sc/Library_sc.mk
+++ b/sc/Library_sc.mk
@@ -45,6 +45,12 @@ $(eval $(call gb_Library_use_externals,sc,\
mdds_headers \
))
+ifeq ($(SYSTEM_LIBORCUS),YES)
+$(eval $(call gb_Library_use_externals,sc,orcus))
+else
+$(eval $(call gb_Library_use_externals,sc,orcus-parser))
+endif
+
ifeq ($(ENABLE_TELEPATHY),TRUE)
$(eval $(call gb_Library_use_libraries,sc,tubes))
@@ -118,6 +124,7 @@ $(eval $(call gb_Library_add_exception_objects,sc,\
sc/source/core/data/documen9 \
sc/source/core/data/document \
sc/source/core/data/documentimport \
+ sc/source/core/data/documentstreamaccess \
sc/source/core/data/dpdimsave \
sc/source/core/data/dpfilteredcache \
sc/source/core/data/dpglobal \
@@ -262,6 +269,7 @@ $(eval $(call gb_Library_add_exception_objects,sc,\
sc/source/core/tool/userlist \
sc/source/core/tool/viewopti \
sc/source/core/tool/zforauto \
+ sc/source/filter/xml/datastreamimport \
sc/source/filter/xml/XMLCalculationSettingsContext \
sc/source/filter/xml/XMLCellRangeSourceContext \
sc/source/filter/xml/XMLChangeTrackingExportHelper \
@@ -317,6 +325,7 @@ $(eval $(call gb_Library_add_exception_objects,sc,\
sc/source/filter/xml/xmltabi \
sc/source/filter/xml/xmlwrap \
sc/source/filter/chart/chart_imp \
+ sc/source/filter/importfilterdata \
sc/source/ui/Accessibility/AccessibilityHints \
sc/source/ui/Accessibility/AccessibleCell \
sc/source/ui/Accessibility/AccessibleCellBase \
@@ -397,6 +406,7 @@ $(eval $(call gb_Library_add_exception_objects,sc,\
sc/source/ui/docshell/docsh6 \
sc/source/ui/docshell/docsh7 \
sc/source/ui/docshell/docsh8 \
+ sc/source/ui/docshell/documentlinkmgr \
sc/source/ui/docshell/editable \
sc/source/ui/docshell/externalrefmgr \
sc/source/ui/docshell/impex \
diff --git a/sc/Library_scqahelper.mk b/sc/Library_scqahelper.mk
index 37b1d54f3c02..cbdc99df6441 100644
--- a/sc/Library_scqahelper.mk
+++ b/sc/Library_scqahelper.mk
@@ -18,11 +18,15 @@ $(eval $(call gb_Library_set_include,scqahelper,\
$(eval $(call gb_Library_use_externals,scqahelper, \
boost_headers \
mdds_headers \
- orcus \
- orcus-parser \
cppunit \
))
+ifeq ($(SYSTEM_LIBORCUS),YES)
+$(eval $(call gb_Library_use_externals,scqahelper,orcus))
+else
+$(eval $(call gb_Library_use_externals,scqahelper,orcus-parser))
+endif
+
$(eval $(call gb_Library_add_defs,scqahelper,\
-DSCQAHELPER_DLLIMPLEMENTATION \
))
diff --git a/sc/inc/column.hxx b/sc/inc/column.hxx
index ba16644492d4..55b384726470 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 e283b3d2f8c3..65d573f5de24 100644
--- a/sc/inc/document.hxx
+++ b/sc/inc/document.hxx
@@ -69,6 +69,8 @@ struct RefUpdateContext;
class EditTextIterator;
struct NoteEntry;
struct FormulaGroupContext;
+class DocumentStreamAccess;
+class DocumentLinkManager;
}
@@ -246,6 +248,7 @@ friend class ScTable;
friend class ScColumn;
friend struct ScRefCellValue;
friend class ScDocumentImport;
+friend class sc::DocumentStreamAccess;
friend class sc::ColumnSpanSet;
friend class sc::EditTextIterator;
@@ -256,6 +259,7 @@ private:
boost::scoped_ptr<svl::SharedStringPool> mpCellStringPool;
boost::scoped_ptr<sc::FormulaGroupContext> mpFormulaGroupCxt;
+ mutable boost::scoped_ptr<sc::DocumentLinkManager> mpDocLinkMgr;
SfxUndoManager* mpUndoManager;
ScFieldEditEngine* pEditEngine; // uses pEditPool from xPoolHelper
@@ -464,6 +468,9 @@ public:
SC_DLLPUBLIC sfx2::LinkManager* GetLinkManager() const;
+ sc::DocumentLinkManager& GetDocLinkManager();
+ const sc::DocumentLinkManager& GetDocLinkManager() const;
+
SC_DLLPUBLIC const ScDocOptions& GetDocOptions() const;
SC_DLLPUBLIC void SetDocOptions( const ScDocOptions& rOpt );
SC_DLLPUBLIC const ScViewOptions& GetViewOptions() const;
@@ -1801,6 +1808,7 @@ public:
Preferred.
*/
void Broadcast( const ScHint& rHint );
+
/// only area, no cell broadcast
void AreaBroadcast( const ScHint& rHint );
/// only areas in range, no cell broadcasts
diff --git a/sc/inc/documentlinkmgr.hxx b/sc/inc/documentlinkmgr.hxx
new file mode 100644
index 000000000000..ead56985788e
--- /dev/null
+++ b/sc/inc/documentlinkmgr.hxx
@@ -0,0 +1,36 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef SC_DOCUMENTLINKMGR_HXX
+#define SC_DOCUMENTLINKMGR_HXX
+
+#include <boost/noncopyable.hpp>
+
+namespace sc {
+
+class DataStream;
+struct DocumentLinkManagerImpl;
+
+class DocumentLinkManager : boost::noncopyable
+{
+ DocumentLinkManagerImpl* mpImpl;
+
+public:
+ DocumentLinkManager();
+
+ void setDataStream( DataStream* p );
+ DataStream* getDataStream();
+ const DataStream* getDataStream() const;
+};
+
+}
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/inc/documentstreamaccess.hxx b/sc/inc/documentstreamaccess.hxx
new file mode 100644
index 000000000000..9fa2d78a491e
--- /dev/null
+++ b/sc/inc/documentstreamaccess.hxx
@@ -0,0 +1,62 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef SC_DOCUMENTSTREAMACCESS_HXX
+#define SC_DOCUMENTSTREAMACCESS_HXX
+
+#include <rtl/ustring.hxx>
+
+class ScDocument;
+class ScAddress;
+class ScRange;
+
+namespace sc {
+
+struct DocumentStreamAccessImpl;
+
+/**
+ * Provides methods to allow direct shifting of document content without
+ * broadcasting or shifting of broadcaster positions.
+ */
+class DocumentStreamAccess
+{
+ DocumentStreamAccessImpl* mpImpl;
+
+ DocumentStreamAccess();
+
+public:
+ DocumentStreamAccess( ScDocument& rDoc );
+
+ void setNumericCell( const ScAddress& rPos, double fVal );
+ void setStringCell( const ScAddress& rPos, const OUString& rStr );
+
+ /**
+ * Clear its internal state, and more importantly all the block position
+ * hints currently held.
+ */
+ void reset();
+
+ /**
+ * Pop the top row inside specified range, shift all the other rows up by
+ * one, then set the bottom row empty.
+ */
+ void shiftRangeUp( const ScRange& rRange );
+
+ /**
+ * Top the bottom row inside specified range, shift all the other rows
+ * above downward by one by inserting an empty row at the top.
+ */
+ void shiftRangeDown( const ScRange& rRange );
+};
+
+}
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/inc/importfilterdata.hxx b/sc/inc/importfilterdata.hxx
new file mode 100644
index 000000000000..23cef833d202
--- /dev/null
+++ b/sc/inc/importfilterdata.hxx
@@ -0,0 +1,49 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef SC_IMPORTFILTERDATA_HXX
+#define SC_IMPORTFILTERDATA_HXX
+
+#include <address.hxx>
+
+#include <boost/noncopyable.hpp>
+#include <boost/scoped_ptr.hpp>
+
+namespace sc {
+
+/**
+ * Stores data imported from the file that need to be processed at the end
+ * of the import process.
+ */
+struct ImportPostProcessData : boost::noncopyable
+{
+ /**
+ * Data stream data needs to be post-processed because it requires
+ * ScDocShell instance which is not available in the filter code.
+ */
+ struct DataStream
+ {
+ enum InsertPos { InsertTop, InsertBottom };
+
+ OUString maURL;
+ ScRange maRange;
+ bool mbRefreshOnEmpty;
+ InsertPos meInsertPos;
+
+ DataStream();
+ };
+
+ boost::scoped_ptr<DataStream> mpDataStream;
+};
+
+}
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/inc/mtvelements.hxx b/sc/inc/mtvelements.hxx
index e5efbf13f804..0fcafdecce98 100644
--- a/sc/inc/mtvelements.hxx
+++ b/sc/inc/mtvelements.hxx
@@ -145,6 +145,8 @@ public:
ColumnBlockPositionSet(ScDocument& rDoc);
ColumnBlockPosition* getBlockPosition(SCTAB nTab, SCCOL nCol);
+
+ void clear();
};
ScRefCellValue toRefCell( const sc::CellStoreType::const_iterator& itPos, size_t nOffset );
diff --git a/sc/inc/table.hxx b/sc/inc/table.hxx
index e273da83e4c3..86b61f564292 100644
--- a/sc/inc/table.hxx
+++ b/sc/inc/table.hxx
@@ -67,6 +67,7 @@ struct RefUpdateInsertTabContext;
struct RefUpdateDeleteTabContext;
struct RefUpdateMoveTabContext;
struct NoteEntry;
+class DocumentStreamAccess;
}
@@ -208,6 +209,7 @@ friend class ScDocAttrIterator;
friend class ScAttrRectIterator;
friend class ScColumnTextWidthIterator;
friend class ScDocumentImport;
+friend class sc::DocumentStreamAccess;
friend class sc::ColumnSpanSet;
friend class sc::EditTextIterator;
diff --git a/sc/inc/xmlwrap.hxx b/sc/inc/xmlwrap.hxx
index fb7b15681137..107ceb4cfdae 100644
--- a/sc/inc/xmlwrap.hxx
+++ b/sc/inc/xmlwrap.hxx
@@ -25,6 +25,8 @@
#include <com/sun/star/uno/Sequence.hxx>
#include <com/sun/star/frame/XModel.hpp>
+#include <importfilterdata.hxx>
+
class ScDocument;
class SfxMedium;
class ScMySharedData;
@@ -44,6 +46,8 @@ namespace com { namespace sun { namespace star {
class ScXMLImportWrapper
{
+ sc::ImportPostProcessData maPostProcessData;
+
ScDocument& rDoc;
SfxMedium* pMedium;
::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage > xStorage;
@@ -70,6 +74,8 @@ public:
ScXMLImportWrapper(ScDocument& rD, SfxMedium* pM, const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage >&);
sal_Bool Import(sal_Bool bStylesOnly, ErrCode& );
sal_Bool Export(sal_Bool bStylesOnly);
+
+ const sc::ImportPostProcessData& GetImportPostProcessData() const;
};
class ScXMLChartExportWrapper
diff --git a/sc/source/core/data/documen2.cxx b/sc/source/core/data/documen2.cxx
index 6c112d5803c3..ae9cbd9dbcc6 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 09bef923a666..47ad10371eef 100644
--- a/sc/source/core/data/documen8.cxx
+++ b/sc/source/core/data/documen8.cxx
@@ -86,7 +86,6 @@
#include "columniterator.hxx"
#include "globalnames.hxx"
#include "stringutil.hxx"
-#include <datastream.hxx>
#include <memory>
#include <boost/scoped_ptr.hpp>
@@ -1194,7 +1193,7 @@ bool ScDocument::HasAreaLinks() const
const ::sfx2::SvBaseLinks& rLinks = pLinkManager->GetLinks();
sal_uInt16 nCount = rLinks.size();
for (sal_uInt16 i=0; i<nCount; i++)
- if ((*rLinks[i])->ISA(ScAreaLink) || (*rLinks[i])->ISA(DataStream))
+ if ((*rLinks[i])->ISA(ScAreaLink))
return true;
}
@@ -1209,7 +1208,7 @@ void ScDocument::UpdateAreaLinks()
for (sal_uInt16 i=0; i<rLinks.size(); i++)
{
::sfx2::SvBaseLink* pBase = *rLinks[i];
- if (pBase->ISA(ScAreaLink) || (*rLinks[i])->ISA(DataStream))
+ if (pBase->ISA(ScAreaLink))
pBase->Update();
}
}
diff --git a/sc/source/core/data/documentstreamaccess.cxx b/sc/source/core/data/documentstreamaccess.cxx
new file mode 100644
index 000000000000..bf3efe33f4a6
--- /dev/null
+++ b/sc/source/core/data/documentstreamaccess.cxx
@@ -0,0 +1,143 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "documentstreamaccess.hxx"
+#include "document.hxx"
+#include "table.hxx"
+#include "column.hxx"
+#include "mtvelements.hxx"
+
+#include "svl/sharedstringpool.hxx"
+
+namespace sc {
+
+struct DocumentStreamAccessImpl
+{
+ ScDocument& mrDoc;
+ ColumnBlockPositionSet maBlockPosSet;
+
+ DocumentStreamAccessImpl( ScDocument& rDoc ) :
+ mrDoc(rDoc),
+ maBlockPosSet(rDoc)
+ {}
+};
+
+DocumentStreamAccess::DocumentStreamAccess( ScDocument& rDoc ) :
+ mpImpl(new DocumentStreamAccessImpl(rDoc)) {}
+
+void DocumentStreamAccess::setNumericCell( const ScAddress& rPos, double fVal )
+{
+ ScTable* pTab = mpImpl->mrDoc.FetchTable(rPos.Tab());
+ if (!pTab)
+ return;
+
+ ColumnBlockPosition* pBlockPos =
+ mpImpl->maBlockPosSet.getBlockPosition(rPos.Tab(), rPos.Col());
+
+ if (!pBlockPos)
+ return;
+
+ // Set the numeric value.
+ CellStoreType& rCells = pTab->aCol[rPos.Col()].maCells;
+ pBlockPos->miCellPos = rCells.set(pBlockPos->miCellPos, rPos.Row(), fVal);
+
+ // Be sure to set the corresponding text attribute to the default value.
+ CellTextAttrStoreType& rAttrs = pTab->aCol[rPos.Col()].maCellTextAttrs;
+ pBlockPos->miCellTextAttrPos = rAttrs.set(pBlockPos->miCellTextAttrPos, rPos.Row(), CellTextAttr());
+}
+
+void DocumentStreamAccess::setStringCell( const ScAddress& rPos, const OUString& rStr )
+{
+ ScTable* pTab = mpImpl->mrDoc.FetchTable(rPos.Tab());
+ if (!pTab)
+ return;
+
+ ColumnBlockPosition* pBlockPos =
+ mpImpl->maBlockPosSet.getBlockPosition(rPos.Tab(), rPos.Col());
+
+ if (!pBlockPos)
+ return;
+
+ svl::SharedString aSS = mpImpl->mrDoc.GetSharedStringPool().intern(rStr);
+ if (!aSS.getData())
+ return;
+
+ // Set the string.
+ CellStoreType& rCells = pTab->aCol[rPos.Col()].maCells;
+ pBlockPos->miCellPos = rCells.set(pBlockPos->miCellPos, rPos.Row(), aSS);
+
+ // Be sure to set the corresponding text attribute to the default value.
+ CellTextAttrStoreType& rAttrs = pTab->aCol[rPos.Col()].maCellTextAttrs;
+ pBlockPos->miCellTextAttrPos = rAttrs.set(pBlockPos->miCellTextAttrPos, rPos.Row(), CellTextAttr());
+}
+
+void DocumentStreamAccess::reset()
+{
+ mpImpl->maBlockPosSet.clear();
+}
+
+void DocumentStreamAccess::shiftRangeUp( const ScRange& rRange )
+{
+ ScTable* pTab = mpImpl->mrDoc.FetchTable(rRange.aStart.Tab());
+ if (!pTab)
+ return;
+
+ SCROW nTopRow = rRange.aStart.Row();
+ SCROW nLastRow = rRange.aEnd.Row();
+
+ for (SCCOL nCol = rRange.aStart.Col(); nCol <= rRange.aEnd.Col(); ++nCol)
+ {
+ ColumnBlockPosition* pBlockPos =
+ mpImpl->maBlockPosSet.getBlockPosition(rRange.aStart.Tab(), nCol);
+
+ if (!pBlockPos)
+ return;
+
+ CellStoreType& rCells = pTab->aCol[nCol].maCells;
+ rCells.erase(nTopRow, nTopRow); // Erase the top, and shift the rest up.
+ pBlockPos->miCellPos = rCells.insert_empty(nLastRow, 1);
+
+ // Do the same for the text attribute storage.
+ CellTextAttrStoreType& rAttrs = pTab->aCol[nCol].maCellTextAttrs;
+ rAttrs.erase(nTopRow, nTopRow);
+ pBlockPos->miCellTextAttrPos = rAttrs.insert_empty(nLastRow, 1);
+ }
+}
+
+void DocumentStreamAccess::shiftRangeDown( const ScRange& rRange )
+{
+ ScTable* pTab = mpImpl->mrDoc.FetchTable(rRange.aStart.Tab());
+ if (!pTab)
+ return;
+
+ SCROW nTopRow = rRange.aStart.Row();
+ SCROW nLastRow = rRange.aEnd.Row();
+
+ for (SCCOL nCol = rRange.aStart.Col(); nCol <= rRange.aEnd.Col(); ++nCol)
+ {
+ ColumnBlockPosition* pBlockPos =
+ mpImpl->maBlockPosSet.getBlockPosition(rRange.aStart.Tab(), nCol);
+
+ if (!pBlockPos)
+ return;
+
+ CellStoreType& rCells = pTab->aCol[nCol].maCells;
+ rCells.erase(nLastRow, nLastRow); // Erase the bottom.
+ pBlockPos->miCellPos = rCells.insert_empty(nTopRow, 1); // insert at the top and shift everything down.
+
+ // Do the same for the text attribute storage.
+ CellTextAttrStoreType& rAttrs = pTab->aCol[nCol].maCellTextAttrs;
+ rAttrs.erase(nLastRow, nLastRow);
+ pBlockPos->miCellTextAttrPos = rAttrs.insert_empty(nTopRow, 1);
+ }
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/core/data/mtvelements.cxx b/sc/source/core/data/mtvelements.cxx
index 5a946067e032..1110ab6d2a04 100644
--- a/sc/source/core/data/mtvelements.cxx
+++ b/sc/source/core/data/mtvelements.cxx
@@ -67,6 +67,12 @@ ColumnBlockPosition* ColumnBlockPositionSet::getBlockPosition(SCTAB nTab, SCCOL
return &it->second;
}
+void ColumnBlockPositionSet::clear()
+{
+ osl::MutexGuard aGuard(&maMtxTables);
+ maTables.clear();
+}
+
ScRefCellValue toRefCell( const sc::CellStoreType::const_iterator& itPos, size_t nOffset )
{
switch (itPos->type)
diff --git a/sc/source/filter/importfilterdata.cxx b/sc/source/filter/importfilterdata.cxx
new file mode 100644
index 000000000000..100188928a0c
--- /dev/null
+++ b/sc/source/filter/importfilterdata.cxx
@@ -0,0 +1,19 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <importfilterdata.hxx>
+
+namespace sc {
+
+ImportPostProcessData::DataStream::DataStream() :
+ mbRefreshOnEmpty(false), meInsertPos(InsertBottom) {}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/filter/xml/datastreamimport.cxx b/sc/source/filter/xml/datastreamimport.cxx
new file mode 100644
index 000000000000..3c5f17de5a61
--- /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 000000000000..c77f235dc69e
--- /dev/null
+++ b/sc/source/filter/xml/datastreamimport.hxx
@@ -0,0 +1,38 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef SC_XML_DATASTREAMIMPORT_HXX
+#define SC_XML_DATASTREAMIMPORT_HXX
+
+#include "importcontext.hxx"
+
+#include <importfilterdata.hxx>
+#include <address.hxx>
+
+class ScXMLDataStreamContext : public ScXMLImportContext
+{
+ OUString maURL;
+ ScRange maRange;
+ bool mbRefreshOnEmpty;
+ sc::ImportPostProcessData::DataStream::InsertPos meInsertPos;
+
+public:
+ ScXMLDataStreamContext(
+ ScXMLImport& rImport, sal_uInt16 nPrefix, const OUString& rLocalName,
+ const com::sun::star::uno::Reference<
+ com::sun::star::xml::sax::XAttributeList>& xAttrList );
+
+ virtual ~ScXMLDataStreamContext();
+
+ virtual void EndElement();
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/filter/xml/xmlbodyi.cxx b/sc/source/filter/xml/xmlbodyi.cxx
index 10a0a946cc38..2496a94cecfc 100644
--- a/sc/source/filter/xml/xmlbodyi.cxx
+++ b/sc/source/filter/xml/xmlbodyi.cxx
@@ -39,6 +39,7 @@
#include "XMLEmptyContext.hxx"
#include "scerrors.hxx"
#include "tabprotection.hxx"
+#include "datastreamimport.hxx"
#include <xmloff/xmltkmap.hxx>
#include <xmloff/xmltoken.hxx>
@@ -192,6 +193,9 @@ SvXMLImportContext *ScXMLBodyContext::CreateChildContext( sal_uInt16 nPrefix,
pContext = new ScXMLDDELinksContext ( GetScImport(), nPrefix, rLocalName,
xAttrList );
break;
+ case XML_TOK_BODY_DATA_STREAM_SOURCE:
+ pContext = new ScXMLDataStreamContext(GetScImport(), nPrefix, rLocalName, xAttrList);
+ break;
}
if( !pContext )
diff --git a/sc/source/filter/xml/xmlcelli.cxx b/sc/source/filter/xml/xmlcelli.cxx
index 1875afa6e5a6..e40a527b7195 100644
--- a/sc/source/filter/xml/xmlcelli.cxx
+++ b/sc/source/filter/xml/xmlcelli.cxx
@@ -1000,20 +1000,6 @@ void ScXMLTableRowCellContext::SetCellRangeSource( const ScAddress& rPosition )
rPosition.Row() + static_cast<SCROW>(pCellRangeSource->nRows - 1), rPosition.Tab() );
OUString sFilterName( pCellRangeSource->sFilterName );
OUString sSourceStr( pCellRangeSource->sSourceStr );
- OUString sRangeStr;
- ScRangeStringConverter::GetStringFromRange( sRangeStr, aDestRange, pDoc, formula::FormulaGrammar::CONV_OOO );
- SvtMiscOptions aMiscOptions;
- if (aMiscOptions.IsExperimentalMode() && pCellRangeSource->sFilterOptions == "DataStream")
- {
- DataStream::Set( dynamic_cast<ScDocShell*>(pDoc->GetDocumentShell())
- , pCellRangeSource->sURL // rURL
- , sRangeStr // rRange
- , sFilterName.toInt32() // nLimit
- , sSourceStr // rMove
- , pCellRangeSource->nRefresh // nSettings
- );
- return;
- }
ScAreaLink* pLink = new ScAreaLink( pDoc->GetDocumentShell(), pCellRangeSource->sURL,
sFilterName, pCellRangeSource->sFilterOptions, sSourceStr, aDestRange, pCellRangeSource->nRefresh );
sfx2::LinkManager* pLinkManager = pDoc->GetLinkManager();
diff --git a/sc/source/filter/xml/xmlexprt.cxx b/sc/source/filter/xml/xmlexprt.cxx
index eadcd3b97042..3699a61ad226 100644
--- a/sc/source/filter/xml/xmlexprt.cxx
+++ b/sc/source/filter/xml/xmlexprt.cxx
@@ -62,6 +62,7 @@
#include "editattributemap.hxx"
#include <arealink.hxx>
#include <datastream.hxx>
+#include <documentlinkmgr.hxx>
#include <xmloff/xmltoken.hxx>
#include <xmloff/xmlnmspe.hxx>
@@ -109,6 +110,7 @@
#include <editeng/outlobj.hxx>
#include <svx/svditer.hxx>
#include <svx/svdpage.hxx>
+#include <svtools/miscopt.hxx>
#include <comphelper/processfactory.hxx>
#include <com/sun/star/beans/XPropertySet.hpp>
@@ -836,18 +838,6 @@ void ScXMLExport::GetAreaLinks( ScMyAreaLinksContainer& rAreaLinks )
aAreaLink.nRefresh = pLink->GetTimeout();
rAreaLinks.AddNewAreaLink( aAreaLink );
}
- DataStream *pStream = dynamic_cast<DataStream*>(&(*(*rLinks[i])));
- if (pStream)
- {
- ScMyAreaLink aAreaLink;
- ScUnoConversion::FillApiRange( aAreaLink.aDestRange, pStream->GetRange() );
- aAreaLink.sSourceStr = pStream->GetMove();
- aAreaLink.sFilter = OUString::number(pStream->GetLimit());
- aAreaLink.sFilterOptions = "DataStream";
- aAreaLink.sURL = pStream->GetURL();
- aAreaLink.nRefresh = pStream->GetSettings();
- rAreaLinks.AddNewAreaLink( aAreaLink );
- }
}
}
rAreaLinks.Sort();
@@ -1955,6 +1945,7 @@ void ScXMLExport::_ExportContent()
}
WriteExternalRefCaches();
WriteNamedExpressions();
+ WriteDataStream();
aExportDatabaseRanges.WriteDatabaseRanges();
ScXMLExportDataPilot aExportDataPilot(*this);
aExportDataPilot.WriteDataPilots(xSpreadDoc);
@@ -4051,6 +4042,49 @@ void ScXMLExport::WriteNamedExpressions()
WriteNamedRange(pNamedRanges);
}
+void ScXMLExport::WriteDataStream()
+{
+ if (!pDoc)
+ return;
+
+ SvtMiscOptions aMiscOptions;
+ if (!aMiscOptions.IsExperimentalMode())
+ // Export this only in experimental mode.
+ return;
+
+ if (getDefaultVersion() <= SvtSaveOptions::ODFVER_012)
+ // Export this only for 1.2 extended and above.
+ return;
+
+ const sc::DocumentLinkManager& rMgr = pDoc->GetDocLinkManager();
+ const sc::DataStream* pStrm = rMgr.getDataStream();
+ if (!pStrm)
+ // No data stream.
+ return;
+
+ // Source URL
+ AddAttribute(XML_NAMESPACE_XLINK, XML_HREF, GetRelativeReference(pStrm->GetURL()));
+
+ // Streamed range
+ ScRange aRange = pStrm->GetRange();
+ OUString aRangeStr;
+ ScRangeStringConverter::GetStringFromRange(
+ aRangeStr, aRange, pDoc, formula::FormulaGrammar::CONV_OOO);
+ AddAttribute(XML_NAMESPACE_TABLE, XML_TARGET_RANGE_ADDRESS, aRangeStr);
+
+ // Empty line refresh option.
+ AddAttribute(XML_NAMESPACE_CALC_EXT, XML_EMPTY_LINE_REFRESH, pStrm->IsRefreshOnEmptyLine() ? XML_TRUE : XML_FALSE);
+
+ // New data insertion position. Either top of bottom. Default to bottom.
+ xmloff::token::XMLTokenEnum eInsertPosition = XML_BOTTOM;
+ if (pStrm->GetMove() == sc::DataStream::MOVE_DOWN)
+ eInsertPosition = XML_TOP;
+
+ AddAttribute(XML_NAMESPACE_CALC_EXT, XML_INSERTION_POSITION, eInsertPosition);
+
+ SvXMLElementExport aElem(*this, XML_NAMESPACE_CALC_EXT, XML_DATA_STREAM_SOURCE, true, true);
+}
+
void ScXMLExport::WriteNamedRange(ScRangeName* pRangeName)
{
//write a global or local ScRangeName
diff --git a/sc/source/filter/xml/xmlexprt.hxx b/sc/source/filter/xml/xmlexprt.hxx
index 4ece1d5bb9ff..564009d4eb63 100644
--- a/sc/source/filter/xml/xmlexprt.hxx
+++ b/sc/source/filter/xml/xmlexprt.hxx
@@ -198,6 +198,7 @@ class ScXMLExport : public SvXMLExport
void WriteTheLabelRanges(const com::sun::star::uno::Reference< com::sun::star::sheet::XSpreadsheetDocument >& xSpreadDoc);
void WriteLabelRanges( const com::sun::star::uno::Reference< com::sun::star::container::XIndexAccess >& xRangesIAccess, bool bColumn );
void WriteNamedExpressions();
+ void WriteDataStream();
void WriteNamedRange(ScRangeName* pRangeName);
void ExportConditionalFormat(SCTAB nTab);
void WriteExternalRefCaches();
diff --git a/sc/source/filter/xml/xmlimprt.cxx b/sc/source/filter/xml/xmlimprt.cxx
index 0320be55d459..96be8112c40c 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 d4d45a79db1a..f3dba757686d 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 5b99a8cbbe25..c2ad8ec0ed92 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 1d99af24a26b..931395d5615c 100644
--- a/sc/source/ui/docshell/datastream.cxx
+++ b/sc/source/ui/docshell/datastream.cxx
@@ -13,25 +13,71 @@
#include <com/sun/star/ui/XUIElement.hpp>
#include <officecfg/Office/Common.hxx>
#include <osl/conditn.hxx>
+#include <osl/time.h>
#include <rtl/strbuf.hxx>
#include <salhelper/thread.hxx>
-#include <sfx2/linkmgr.hxx>
#include <sfx2/viewfrm.hxx>
-#include <arealink.hxx>
-#include <asciiopt.hxx>
#include <datastreamdlg.hxx>
-#include <dbfunc.hxx>
#include <docsh.hxx>
-#include <documentimport.hxx>
-#include <impex.hxx>
#include <rangelst.hxx>
#include <tabvwsh.hxx>
#include <viewdata.hxx>
+#include <stringutil.hxx>
+#include <documentlinkmgr.hxx>
+
+#include <config_orcus.h>
+
+#if ENABLE_ORCUS
+#if defined WNT
+#define __ORCUS_STATIC_LIB
+#endif
+#include <orcus/csv_parser.hpp>
+#endif
#include <queue>
+namespace sc {
+
+inline double getNow()
+{
+ TimeValue now;
+ osl_getSystemTime(&now);
+ return static_cast<double>(now.Seconds) + static_cast<double>(now.Nanosec) / 1000000000.0;
+}
+
namespace datastreams {
+class CallerThread : public salhelper::Thread
+{
+ DataStream *mpDataStream;
+public:
+ osl::Condition maStart;
+ bool mbTerminate;
+
+ CallerThread(DataStream *pData):
+ Thread("CallerThread")
+ ,mpDataStream(pData)
+ ,mbTerminate(false)
+ {}
+
+private:
+ virtual void execute()
+ {
+ while (!mbTerminate)
+ {
+ // wait for a small amount of time, so that
+ // painting methods have a chance to be called.
+ // And also to make UI more responsive.
+ TimeValue const aTime = {0, 100000};
+ maStart.wait();
+ maStart.reset();
+ if (!mbTerminate)
+ while (mpDataStream->ImportData())
+ wait(aTime);
+ };
+ }
+};
+
class ReaderThread : public salhelper::Thread
{
SvStream *mpStream;
@@ -135,70 +181,57 @@ void DataStream::MakeToolbarVisible()
}
}
-DataStream* DataStream::Set(ScDocShell *pShell, const OUString& rURL, const OUString& rRange,
- sal_Int32 nLimit, const OUString& rMove, sal_uInt32 nSettings)
+DataStream* DataStream::Set(
+ ScDocShell *pShell, const OUString& rURL, const ScRange& rRange,
+ sal_Int32 nLimit, MoveType eMove, sal_uInt32 nSettings)
{
- // Each DataStream needs a destination area in order to be exported.
- // There can be only one ScAreaLink / DataStream per cell.
- // So - if we don't need range (DataStream with mbValuesInLine == false),
- // just find a free cell for now.
- sfx2::LinkManager* pLinkManager = pShell->GetDocument()->GetLinkManager();
- ScRange aDestArea;
- aDestArea.Parse(rRange, pShell->GetDocument());
- sal_uInt16 nLinkPos = 0;
- while (nLinkPos < pLinkManager->GetLinks().size())
- {
- sfx2::SvBaseLink* pBase = *pLinkManager->GetLinks()[nLinkPos];
- if (rRange.isEmpty())
- {
- if ( (pBase->ISA(ScAreaLink) && dynamic_cast<ScAreaLink*>
- (&(*pBase))->GetDestArea().aStart == aDestArea.aStart)
- || (pBase->ISA(DataStream) && dynamic_cast<DataStream*>
- (&(*pBase))->GetRange().aStart == aDestArea.aStart) )
- {
- aDestArea.Move(0, 1, 0);
- nLinkPos = 0;
- continue;
- }
- else
- ++nLinkPos;
- }
- else if ( (pBase->ISA(ScAreaLink) && dynamic_cast<ScAreaLink*>
- (&(*pBase))->GetDestArea().aStart == aDestArea.aStart)
- || (pBase->ISA(DataStream) && dynamic_cast<DataStream*>
- (&(*pBase))->GetRange().aStart == aDestArea.aStart) )
- {
- pLinkManager->Remove( pBase );
- }
- else
- ++nLinkPos;
- }
+ DataStream* pLink = new DataStream(pShell, rURL, rRange, nLimit, eMove, nSettings);
+ sc::DocumentLinkManager& rMgr = pShell->GetDocument()->GetDocLinkManager();
+ rMgr.setDataStream(pLink);
+ return pLink;
+}
- sfx2::SvBaseLink *pLink = 0;
- pLink = new DataStream( pShell, rURL, rRange, nLimit, rMove, nSettings );
- pLinkManager->InsertFileLink( *pLink, OBJECT_CLIENT_FILE, rURL, NULL, NULL );
- return dynamic_cast<DataStream*>(pLink);
+DataStream::MoveType DataStream::ToMoveType( const OUString& rMoveStr )
+{
+ if (rMoveStr == "RANGE_DOWN")
+ return RANGE_DOWN;
+ if (rMoveStr == "MOVE_DOWN")
+ return MOVE_DOWN;
+ if (rMoveStr == "MOVE_UP")
+ return MOVE_UP;
+
+ return NO_MOVE; // default
}
-DataStream::DataStream(ScDocShell *pShell, const OUString& rURL, const OUString& rRange,
- sal_Int32 nLimit, const OUString& rMove, sal_uInt32 nSettings)
- : mpScDocShell(pShell)
- , mpScDocument(mpScDocShell->GetDocument())
- , meMove(NO_MOVE)
- , mbRunning(false)
- , mpLines(0)
- , mnLinesCount(0)
+DataStream::DataStream(ScDocShell *pShell, const OUString& rURL, const ScRange& rRange,
+ sal_Int32 nLimit, MoveType eMove, sal_uInt32 nSettings) :
+ mpDocShell(pShell),
+ mpDoc(mpDocShell->GetDocument()),
+ maDocAccess(*mpDoc),
+ meOrigMove(NO_MOVE),
+ meMove(NO_MOVE),
+ mbRunning(false),
+ mbValuesInLine(false),
+ mbRefreshOnEmptyLine(false),
+ mpLines(0),
+ mnLinesCount(0),
+ mnLinesSinceRefresh(0),
+ mfLastRefreshTime(0.0),
+ mnCurRow(0)
{
- SetRefreshHandler(LINK( this, DataStream, RefreshHdl ));
- SetRefreshControl(mpScDocument->GetRefreshTimerControlAddress());
- SetTimeout( 1 );
- Decode(rURL, rRange, nLimit, rMove, nSettings);
+ mxThread = new datastreams::CallerThread( this );
+ mxThread->launch();
+
+ Decode(rURL, rRange, nLimit, eMove, nSettings);
}
DataStream::~DataStream()
{
if (mbRunning)
StopImport();
+ mxThread->mbTerminate = true;
+ mxThread->maStart.set();
+ mxThread->join();
if (mxReaderThread.is())
mxReaderThread->endThread();
delete mpLines;
@@ -229,40 +262,64 @@ OString DataStream::ConsumeLine()
return mpLines->at(mnLinesCount++);
}
-void DataStream::Decode(const OUString& rURL, const OUString& rRange,
- sal_Int32 nLimit, const OUString& rMove, const sal_uInt32 nSettings)
+ScRange DataStream::GetRange() const
+{
+ ScRange aRange = maStartRange;
+ aRange.aEnd = maEndRange.aEnd;
+ return aRange;
+}
+
+bool DataStream::IsRefreshOnEmptyLine() const
+{
+ return mbRefreshOnEmptyLine;
+}
+
+DataStream::MoveType DataStream::GetMove() const
+{
+ return meOrigMove;
+}
+
+void DataStream::Decode(const OUString& rURL, const ScRange& rRange,
+ sal_Int32 nLimit, MoveType eMove, const sal_uInt32 nSettings)
{
msURL = rURL;
- msRange = rRange;
mnLimit = nLimit;
- msMove = rMove;
+ meMove = eMove;
+ meOrigMove = eMove;
mnSettings = nSettings;
- mpEndRange.reset( NULL );
-
- mbValuesInLine = mnSettings & VALUES_IN_LINE;
-
- if (msMove == "NO_MOVE")
- meMove = NO_MOVE;
- else if (msMove == "RANGE_DOWN")
- meMove = RANGE_DOWN;
- else if (msMove == "MOVE_DOWN")
- meMove = MOVE_DOWN;
-
- maRange.Parse(msRange);
- maStartRange = maRange;
- sal_Int32 nHeight = maRange.aEnd.Row() - maRange.aStart.Row() + 1;
- nLimit = nHeight * (nLimit / nHeight);
- if (nLimit && maRange.aStart.Row() + nLimit - 1 < MAXROW)
+
+ mbValuesInLine = true; // always true.
+
+ mnCurRow = rRange.aStart.Row();
+
+ ScRange aRange = rRange;
+ if (aRange.aStart.Row() != aRange.aEnd.Row())
+ // We only allow this range to be one row tall.
+ aRange.aEnd.SetRow(aRange.aStart.Row());
+
+ maStartRange = aRange;
+ maEndRange = aRange;
+ if (nLimit == 0)
{
- mpEndRange.reset( new ScRange(maRange) );
- mpEndRange->Move(0, nLimit - nHeight, 0);
+ // Unlimited
+ maEndRange.aStart.SetRow(MAXROW);
}
+ else if (nLimit > 0)
+ {
+ // Limited.
+ maEndRange.aStart.IncRow(nLimit-1);
+ if (maEndRange.aStart.Row() > MAXROW)
+ maEndRange.aStart.SetRow(MAXROW);
+ }
+
+ maEndRange.aEnd.SetRow(maEndRange.aStart.Row());
}
void DataStream::StartImport()
{
if (mbRunning)
return;
+
if (!mxReaderThread.is())
{
SvStream *pStream = 0;
@@ -274,15 +331,32 @@ void DataStream::StartImport()
mxReaderThread->launch();
}
mbRunning = true;
- AutoTimer::Start();
+ maDocAccess.reset();
+ mxThread->maStart.set();
}
void DataStream::StopImport()
{
if (!mbRunning)
return;
+
mbRunning = false;
- AutoTimer::Stop();
+ Refresh();
+}
+
+void DataStream::SetRefreshOnEmptyLine( bool bVal )
+{
+ mbRefreshOnEmptyLine = bVal;
+}
+
+void DataStream::Refresh()
+{
+ // Hard recalc will repaint the grid area.
+ mpDocShell->DoHardRecalc(true);
+ mpDocShell->SetDocumentModified(true);
+
+ mfLastRefreshTime = getNow();
+ mnLinesSinceRefresh = 0;
}
void DataStream::MoveData()
@@ -290,185 +364,166 @@ void DataStream::MoveData()
switch (meMove)
{
case RANGE_DOWN:
- if (maRange.aStart == mpEndRange->aStart)
+ {
+ if (mnCurRow == maEndRange.aStart.Row())
meMove = MOVE_UP;
- break;
+ }
+ break;
case MOVE_UP:
- mpScDocument->DeleteRow(maStartRange);
- mpScDocument->InsertRow(*mpEndRange);
- break;
+ {
+ // Remove the top row and shift the remaining rows upward. Then
+ // insert a new row at the end row position.
+ ScRange aRange = maStartRange;
+ aRange.aEnd = maEndRange.aEnd;
+ maDocAccess.shiftRangeUp(aRange);
+ }
+ break;
case MOVE_DOWN:
- if (mpEndRange.get())
- mpScDocument->DeleteRow(*mpEndRange);
- mpScDocument->InsertRow(maRange);
- break;
+ {
+ // Remove the end row and shift the remaining rows downward by
+ // inserting a new row at the top row.
+ ScRange aRange = maStartRange;
+ aRange.aEnd = maEndRange.aEnd;
+ maDocAccess.shiftRangeDown(aRange);
+ }
+ break;
case NO_MOVE:
- break;
+ default:
+ ;
}
}
-IMPL_LINK_NOARG(DataStream, RefreshHdl)
+#if ENABLE_ORCUS
+
+namespace {
+
+struct StrVal
{
- ImportData();
- return 0;
-}
+ ScAddress maPos;
+ OUString maStr;
-// lcl_ScanString and Text2Doc is simplified version
-// of code from sc/source/ui/docshell/impex.cxx
-const sal_Unicode* lcl_ScanString( const sal_Unicode* p, OUString& rString, sal_Unicode cStr)
+ StrVal( const ScAddress& rPos, const OUString& rStr ) : maPos(rPos), maStr(rStr) {}
+};
+
+struct NumVal
{
- const sal_Unicode* p0 = p;
- for( ;; )
+ ScAddress maPos;
+ double mfVal;
+
+ NumVal( const ScAddress& rPos, double fVal ) : maPos(rPos), mfVal(fVal) {}
+};
+
+typedef std::vector<StrVal> StrValArray;
+typedef std::vector<NumVal> NumValArray;
+
+/**
+ * This handler handles a single line CSV input.
+ */
+class CSVHandler
+{
+ ScAddress maPos;
+ SCROW mnRow;
+ SCCOL mnCol;
+ SCCOL mnEndCol;
+ SCTAB mnTab;
+
+ StrValArray maStrs;
+ NumValArray maNums;
+
+public:
+ CSVHandler( const ScAddress& rPos, SCCOL nEndCol ) : maPos(rPos), mnEndCol(nEndCol) {}
+
+ void begin_parse() {}
+ void end_parse() {}
+ void begin_row() {}
+ void end_row() {}
+
+ void cell(const char* p, size_t n)
{
- if (!*p)
- break;
- if (*p == cStr)
+ if (maPos.Col() <= mnEndCol)
{
- if (*++p != cStr)
- break;
- p++;
+ OUString aStr(p, n, RTL_TEXTENCODING_UTF8);
+ double fVal;
+ if (ScStringUtil::parseSimpleNumber(aStr, '.', ',', fVal))
+ maNums.push_back(NumVal(maPos, fVal));
+ else
+ maStrs.push_back(StrVal(maPos, aStr));
}
- else
- p++;
+ maPos.IncCol();
}
- if (p0 < p)
- if (rString.getLength() + (p - p0) <= STRING_MAXLEN)
- rString += OUString( p0, sal::static_int_cast<sal_Int32>( p - p0 ) );
- return p;
+
+ const StrValArray& getStrs() const { return maStrs; }
+ const NumValArray& getNums() const { return maNums; }
+};
+
}
void DataStream::Text2Doc()
{
- sal_Unicode cSep(',');
- sal_Unicode cStr('"');
- SCCOL nStartCol = maRange.aStart.Col();
- SCROW nStartRow = maRange.aStart.Row();
- SCCOL nEndCol = maRange.aEnd.Col();
- SCROW nEndRow = maRange.aEnd.Row();
- OUString aCell;
- SCROW nRow = nStartRow;
- ScDocumentImport aDocImport(*mpScDocument);
- while (nRow <= nEndRow)
+ OString aLine = ConsumeLine();
+ orcus::csv_parser_config aConfig;
+ aConfig.delimiters.push_back(',');
+ aConfig.text_qualifier = '"';
+ CSVHandler aHdl(ScAddress(maStartRange.aStart.Col(), mnCurRow, maStartRange.aStart.Tab()), maStartRange.aEnd.Col());
+ orcus::csv_parser<CSVHandler> parser(aLine.getStr(), aLine.getLength(), aHdl, aConfig);
+ parser.parse();
+
+ const StrValArray& rStrs = aHdl.getStrs();
+ const NumValArray& rNums = aHdl.getNums();
+ if (rStrs.empty() && rNums.empty() && mbRefreshOnEmptyLine)
{
- SCCOL nCol = nStartCol;
- OUString sLine( OStringToOUString(ConsumeLine(), RTL_TEXTENCODING_UTF8) );
- const sal_Unicode* p = sLine.getStr();
- while (*p)
- {
- aCell = "";
- const sal_Unicode* q = p;
- while (*p && *p != cSep)
- {
- // Always look for a pairing quote and ignore separator in between.
- while (*p && *p == cStr)
- q = p = lcl_ScanString(p, aCell, cStr);
- // All until next separator or quote.
- while (*p && *p != cSep && *p != cStr)
- ++p;
- if (aCell.getLength() + (p - q) <= STRING_MAXLEN)
- aCell += OUString( q, sal::static_int_cast<sal_Int32>( p - q ) );
- q = p;
- }
- if (*p)
- ++p;
- if (nCol <= nEndCol && nRow <= nEndRow)
- {
- ScAddress aAddress(nCol, nRow, maRange.aStart.Tab());
- if (aCell == "0" || ( aCell.indexOf(':') == -1 && aCell.toDouble() ))
- aDocImport.setNumericCell(aAddress, aCell.toDouble());
- else
- aDocImport.setStringCell(aAddress, aCell);
- }
- ++nCol;
- }
- ++nRow;
+ // Empty line detected. Trigger refresh and discard it.
+ Refresh();
+ return;
}
- aDocImport.finalize();
- mpScDocShell->PostPaint( maRange, PAINT_GRID );
-}
-bool DataStream::ImportData()
-{
MoveData();
- if (mbValuesInLine)
{
- // do CSV import
- Text2Doc();
+ StrValArray::const_iterator it = rStrs.begin(), itEnd = rStrs.end();
+ for (; it != itEnd; ++it)
+ maDocAccess.setStringCell(it->maPos, it->maStr);
}
- else
+
{
- ScRangeList aRangeList;
- ScDocumentImport aDocImport(*mpScDocument);
- // read more lines at once but not too much
- for (int i = 0; i < 10; ++i)
- {
- OUString sLine( OStringToOUString(ConsumeLine(), RTL_TEXTENCODING_UTF8) );
- if (sLine.indexOf(',') <= 0)
- continue;
-
- OUString sAddress( sLine.copy(0, sLine.indexOf(',')) );
- OUString sValue( sLine.copy(sLine.indexOf(',') + 1) );
- ScAddress aAddress;
- aAddress.Parse(sAddress, mpScDocument);
- if (!aAddress.IsValid())
- continue;
-
- if (sValue == "0" || ( sValue.indexOf(':') == -1 && sValue.toDouble() ))
- aDocImport.setNumericCell(aAddress, sValue.toDouble());
- else
- aDocImport.setStringCell(aAddress, sValue);
- aRangeList.Join(aAddress);
- }
- aDocImport.finalize();
- mpScDocShell->PostPaint( aRangeList, PAINT_GRID );
+ NumValArray::const_iterator it = rNums.begin(), itEnd = rNums.end();
+ for (; it != itEnd; ++it)
+ maDocAccess.setNumericCell(it->maPos, it->mfVal);
}
+
if (meMove == NO_MOVE)
- return mbRunning;
+ return;
if (meMove == RANGE_DOWN)
- {
- maRange.Move(0, maRange.aEnd.Row() - maRange.aStart.Row() + 1, 0);
- mpScDocShell->GetViewData()->GetView()->AlignToCursor(
- maRange.aStart.Col(), maRange.aStart.Row(), SC_FOLLOW_JUMP);
- }
- SCROW aEndRow = mpEndRange.get() ? mpEndRange->aEnd.Row() : MAXROW;
- mpScDocShell->PostPaint( ScRange( maStartRange.aStart, ScAddress( maRange.aEnd.Col(),
- aEndRow, maRange.aStart.Tab()) ), PAINT_GRID );
+ ++mnCurRow;
- return mbRunning;
-}
+ if (getNow() - mfLastRefreshTime > 0.1 && mnLinesSinceRefresh > 200)
+ // Refresh no more frequently than every 0.1 second, and wait until at
+ // least we have processed 200 lines.
+ Refresh();
-sfx2::SvBaseLink::UpdateResult DataStream::DataChanged(
- const OUString& , const css::uno::Any& )
-{
- MakeToolbarVisible();
- StopImport();
- bool bStart = true;
- if (mnSettings & SCRIPT_STREAM && !mxReaderThread.is() &&
- officecfg::Office::Common::Security::Scripting::MacroSecurityLevel::get() >= 1)
- {
- MessageDialog aQBox( NULL, "QueryRunStreamScriptDialog", "modules/scalc/ui/queryrunstreamscriptdialog.ui");
- aQBox.set_primary_text( aQBox.get_primary_text().replaceFirst("%URL", msURL) );
- if (RET_YES != aQBox.Execute())
- bStart = false;
- }
- if (bStart)
- StartImport();
- return SUCCESS;
+ ++mnLinesSinceRefresh;
}
-void DataStream::Edit(Window* pWindow, const Link& )
+#else
+
+void DataStream::Text2Doc() {}
+
+#endif
+
+bool DataStream::ImportData()
{
- DataStreamDlg aDialog(mpScDocShell, pWindow);
- aDialog.Init(msURL, msRange, mnLimit, msMove, mnSettings);
- if (aDialog.Execute() == RET_OK)
- {
- bool bWasRunning = mbRunning;
- StopImport();
- aDialog.StartStream(this);
- if (bWasRunning)
- StartImport();
- }
+ SolarMutexGuard aGuard;
+ if (!mbValuesInLine)
+ // We no longer support this mode. To be deleted later.
+ return false;
+
+ if (ScDocShell::GetViewData()->GetViewShell()->NeedsRepaint())
+ return mbRunning;
+
+ Text2Doc();
+ return mbRunning;
}
+} // namespace sc
+
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/docshell/docsh.cxx b/sc/source/ui/docshell/docsh.cxx
index 1904f1b03d5b..b4cf615ca227 100644
--- a/sc/source/ui/docshell/docsh.cxx
+++ b/sc/source/ui/docshell/docsh.cxx
@@ -119,6 +119,8 @@
#include "dpobject.hxx"
#include "markdata.hxx"
#include "orcusfilters.hxx"
+#include <datastream.hxx>
+#include <documentlinkmgr.hxx>
#include <config_telepathy.h>
@@ -400,6 +402,36 @@ private:
ScDocument* mpDoc;
};
+void processDataStream( ScDocShell& rShell, const sc::ImportPostProcessData& rData )
+{
+ if (!rData.mpDataStream)
+ return;
+
+ const sc::ImportPostProcessData::DataStream& r = *rData.mpDataStream;
+ if (!r.maRange.IsValid())
+ return;
+
+ // Break the streamed range into the top range and the height limit. A
+ // height limit of 0 means unlimited i.e. the streamed data will go all
+ // the way to the last row.
+
+ ScRange aTopRange = r.maRange;
+ aTopRange.aEnd.SetRow(aTopRange.aStart.Row());
+ sal_Int32 nLimit = r.maRange.aEnd.Row() - r.maRange.aStart.Row() + 1;
+ if (r.maRange.aEnd.Row() == MAXROW)
+ // Unlimited range.
+ nLimit = 0;
+
+ sc::DataStream::MoveType eMove =
+ r.meInsertPos == sc::ImportPostProcessData::DataStream::InsertTop ?
+ sc::DataStream::MOVE_DOWN : sc::DataStream::RANGE_DOWN;
+
+ sc::DataStream* pStrm = new sc::DataStream(&rShell, r.maURL, aTopRange, nLimit, eMove, 0);
+ pStrm->SetRefreshOnEmptyLine(r.mbRefreshOnEmpty);
+ sc::DocumentLinkManager& rMgr = rShell.GetDocument()->GetDocLinkManager();
+ rMgr.setDataStream(pStrm);
+}
+
}
sal_Bool ScDocShell::LoadXML( SfxMedium* pLoadMedium, const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage >& xStor )
@@ -430,6 +462,8 @@ sal_Bool ScDocShell::LoadXML( SfxMedium* pLoadMedium, const ::com::sun::star::un
if ( nError )
pLoadMedium->SetError( nError, OUString( OSL_LOG_PREFIX ) );
+ processDataStream(*this, aImport.GetImportPostProcessData());
+
//if the document was not generated by LibreOffice, do hard recalc in case some other document
//generator saved cached formula results that differ from LibreOffice's calculated results or
//did not use cached formula results.
diff --git a/sc/source/ui/docshell/documentlinkmgr.cxx b/sc/source/ui/docshell/documentlinkmgr.cxx
new file mode 100644
index 000000000000..2b9998f96244
--- /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 6eb1e7d8fd85..5a4d8cd444b7 100644
--- a/sc/source/ui/inc/datastream.hxx
+++ b/sc/source/ui/inc/datastream.hxx
@@ -7,78 +7,101 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
+#ifndef SC_DATASTREAM_HXX
+#define SC_DATASTREAM_HXX
+
#include <sal/config.h>
#include <rtl/ref.hxx>
#include <rtl/ustring.hxx>
-#include <sfx2/lnkbase.hxx>
#include <address.hxx>
-#include <refreshtimer.hxx>
#include <boost/noncopyable.hpp>
#include <boost/scoped_ptr.hpp>
#include <vector>
-namespace datastreams {
- class ReaderThread;
-}
+#include <documentstreamaccess.hxx>
+
class ScDocShell;
class ScDocument;
class Window;
+namespace sc {
+
+namespace datastreams {
+ class CallerThread;
+ class ReaderThread;
+}
+
typedef std::vector<OString> LinesList;
-class DataStream : boost::noncopyable, public sfx2::SvBaseLink, ScRefreshTimer
+class DataStream : boost::noncopyable
{
OString ConsumeLine();
void MoveData();
void Text2Doc();
- DECL_LINK( RefreshHdl, void* );
public:
- enum MoveEnum { NO_MOVE, RANGE_DOWN, MOVE_DOWN, MOVE_UP };
+ enum MoveType { NO_MOVE, RANGE_DOWN, MOVE_DOWN, MOVE_UP };
enum { SCRIPT_STREAM = 1, VALUES_IN_LINE = 2 };
static void MakeToolbarVisible();
- static DataStream* Set(ScDocShell *pShell, const OUString& rURL, const OUString& rRange,
- sal_Int32 nLimit, const OUString& rMove, sal_uInt32 nSettings);
-
- DataStream(ScDocShell *pShell, const OUString& rURL, const OUString& rRange,
- sal_Int32 nLimit, const OUString& rMove, sal_uInt32 nSettings);
- virtual ~DataStream();
- // sfx2::SvBaseLink
- virtual sfx2::SvBaseLink::UpdateResult DataChanged(
- const OUString& , const css::uno::Any& ) SAL_OVERRIDE;
- virtual void Edit(Window* , const Link& ) SAL_OVERRIDE;
-
- const ScRange& GetRange() const { return maRange; }
+ static DataStream* Set(ScDocShell *pShell, const OUString& rURL, const ScRange& rRange,
+ sal_Int32 nLimit, MoveType eMove, sal_uInt32 nSettings);
+
+ static MoveType ToMoveType( const OUString& rMoveStr );
+
+ DataStream(
+ ScDocShell *pShell, const OUString& rURL, const ScRange& rRange,
+ sal_Int32 nLimit, MoveType eMove, sal_uInt32 nSettings);
+
+ ~DataStream();
+
+ ScRange GetRange() const;
const OUString& GetURL() const { return msURL; }
const sal_Int32& GetLimit() const { return mnLimit; }
- const OUString& GetMove() const { return msMove; }
+ MoveType GetMove() const;
const sal_uInt32& GetSettings() const { return mnSettings; }
- void Decode(const OUString& rURL, const OUString& rRange, sal_Int32 nLimit,
- const OUString& rMove, const sal_uInt32 nSettings);
+ bool IsRefreshOnEmptyLine() const;
+
+ void Decode(
+ const OUString& rURL, const ScRange& rRange, sal_Int32 nLimit,
+ MoveType eMove, const sal_uInt32 nSettings);
+
bool ImportData();
void StartImport();
void StopImport();
+ void SetRefreshOnEmptyLine( bool bVal );
+
private:
- ScDocShell *mpScDocShell;
- ScDocument *mpScDocument;
+ void Refresh();
+
+private:
+ ScDocShell* mpDocShell;
+ ScDocument* mpDoc;
+ DocumentStreamAccess maDocAccess;
OUString msURL;
- OUString msRange;
- OUString msMove;
sal_Int32 mnLimit;
sal_uInt32 mnSettings;
- MoveEnum meMove;
+ MoveType meOrigMove; // Initial move setting. This one gets saved to file.
+ MoveType meMove; // move setting during streaming, which may change in the middle.
bool mbRunning;
bool mbValuesInLine;
- LinesList *mpLines;
+ bool mbRefreshOnEmptyLine;
+ LinesList* mpLines;
size_t mnLinesCount;
- ScRange maRange;
+ size_t mnLinesSinceRefresh;
+ double mfLastRefreshTime;
+ SCROW mnCurRow;
ScRange maStartRange;
- boost::scoped_ptr<ScRange> mpEndRange;
+ ScRange maEndRange;
+ rtl::Reference<datastreams::CallerThread> mxThread;
rtl::Reference<datastreams::ReaderThread> mxReaderThread;
};
+}
+
+#endif
+
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/inc/datastreamdlg.hxx b/sc/source/ui/inc/datastreamdlg.hxx
index 162a0d6b89d0..851afefe5099 100644
--- a/sc/source/ui/inc/datastreamdlg.hxx
+++ b/sc/source/ui/inc/datastreamdlg.hxx
@@ -13,9 +13,13 @@
#include <vcl/dialog.hxx>
#include <vcl/layout.hxx>
-class DataStream;
+#include <datastream.hxx>
+
class ScDocShell;
class SvtURLBox;
+class ScRange;
+
+namespace sc {
class DataStreamDlg : public ModalDialog
{
@@ -23,13 +27,16 @@ class DataStreamDlg : public ModalDialog
SvtURLBox* m_pCbUrl;
PushButton* m_pBtnBrowse;
+ RadioButton* m_pRBDirectData;
RadioButton* m_pRBScriptData;
RadioButton* m_pRBValuesInLine;
RadioButton* m_pRBAddressValue;
+ CheckBox* m_pCBRefreshOnEmpty;
RadioButton* m_pRBDataDown;
RadioButton* m_pRBRangeDown;
RadioButton* m_pRBNoMove;
RadioButton* m_pRBMaxLimit;
+ RadioButton* m_pRBUnlimited;
Edit* m_pEdRange;
Edit* m_pEdLimit;
OKButton* m_pBtnOk;
@@ -40,13 +47,16 @@ class DataStreamDlg : public ModalDialog
DECL_LINK(BrowseHdl, void *);
void UpdateEnable();
+ ScRange GetStartRange();
public:
DataStreamDlg(ScDocShell *pDocShell, Window* pParent);
- ~DataStreamDlg() {}
- void Init(const OUString& rURL, const OUString& rRange, const sal_Int32 nLimit,
- const OUString& rMove, const sal_uInt32 nSettings);
- void StartStream(DataStream *pStream = 0);
+
+ void Init( const DataStream& rStrm );
+
+ void StartStream();
};
+}
+
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/inc/gridwin.hxx b/sc/source/ui/inc/gridwin.hxx
index 8755da85bc0d..5ac059c739d8 100644
--- a/sc/source/ui/inc/gridwin.hxx
+++ b/sc/source/ui/inc/gridwin.hxx
@@ -373,6 +373,7 @@ public:
void StopMarking();
void UpdateInputContext();
+ bool NeedsRepaint() { return bNeedsRepaint; }
void CheckInverted() { if (nPaintCount) bNeedsRepaint = true; }
diff --git a/sc/source/ui/inc/tabview.hxx b/sc/source/ui/inc/tabview.hxx
index 4964e6d685c1..e13d088f2804 100644
--- a/sc/source/ui/inc/tabview.hxx
+++ b/sc/source/ui/inc/tabview.hxx
@@ -437,6 +437,7 @@ public:
void UpdateFormulas();
void InterpretVisible();
void CheckNeedsRepaint();
+ bool NeedsRepaint();
void PaintRangeFinder( long nNumber = -1 );
void AddHighlightRange( const ScRange& rRange, const Color& rColor );
diff --git a/sc/source/ui/miscdlgs/datastreamdlg.cxx b/sc/source/ui/miscdlgs/datastreamdlg.cxx
index a6d0a9237276..8a3bee5a813a 100644
--- a/sc/source/ui/miscdlgs/datastreamdlg.cxx
+++ b/sc/source/ui/miscdlgs/datastreamdlg.cxx
@@ -12,7 +12,10 @@
#include <sfx2/filedlghelper.hxx>
#include <svtools/inettbc.hxx>
#include <vcl/layout.hxx>
-#include <datastream.hxx>
+#include <address.hxx>
+#include <docsh.hxx>
+
+namespace sc {
DataStreamDlg::DataStreamDlg(ScDocShell *pDocShell, Window* pParent)
: ModalDialog(pParent, "DataStreamDialog", "modules/scalc/ui/datastreams.ui")
@@ -20,13 +23,16 @@ DataStreamDlg::DataStreamDlg(ScDocShell *pDocShell, Window* pParent)
{
get(m_pCbUrl, "url");
get(m_pBtnBrowse, "browse");
+ get(m_pRBDirectData, "directdata");
get(m_pRBScriptData, "scriptdata");
get(m_pRBValuesInLine, "valuesinline");
get(m_pRBAddressValue, "addressvalue");
+ get(m_pCBRefreshOnEmpty, "refresh_ui");
get(m_pRBDataDown, "datadown");
get(m_pRBRangeDown, "rangedown");
get(m_pRBNoMove, "nomove");
get(m_pRBMaxLimit, "maxlimit");
+ get(m_pRBUnlimited, "unlimited");
get(m_pEdRange, "range");
get(m_pEdLimit, "limit");
get(m_pBtnOk, "ok");
@@ -35,6 +41,11 @@ DataStreamDlg::DataStreamDlg(ScDocShell *pDocShell, Window* pParent)
m_pCbUrl->SetSelectHdl( LINK( this, DataStreamDlg, UpdateHdl ) );
m_pRBAddressValue->SetClickHdl( LINK( this, DataStreamDlg, UpdateHdl ) );
+ m_pRBAddressValue->Enable(false);
+ m_pRBScriptData->Enable(false);
+ m_pRBDirectData->Hide();
+ m_pRBScriptData->Hide();
+ m_pRBNoMove->Hide();
m_pRBValuesInLine->SetClickHdl( LINK( this, DataStreamDlg, UpdateHdl ) );
m_pEdRange->SetModifyHdl( LINK( this, DataStreamDlg, UpdateHdl ) );
m_pBtnBrowse->SetClickHdl( LINK( this, DataStreamDlg, BrowseHdl ) );
@@ -63,7 +74,6 @@ void DataStreamDlg::UpdateEnable()
bool bOk = !m_pCbUrl->GetURL().isEmpty();
if (m_pRBAddressValue->IsChecked())
{
- m_pRBNoMove->Check();
m_pVclFrameLimit->Disable();
m_pVclFrameMove->Disable();
m_pEdRange->Disable();
@@ -73,33 +83,85 @@ void DataStreamDlg::UpdateEnable()
m_pVclFrameLimit->Enable();
m_pVclFrameMove->Enable();
m_pEdRange->Enable();
- bOk = bOk && !m_pEdRange->GetText().isEmpty();
+ if (bOk)
+ {
+ // Check the given range to make sure it's valid.
+ ScRange aTest = GetStartRange();
+ if (!aTest.IsValid())
+ bOk = false;
+ }
}
m_pBtnOk->Enable(bOk);
setOptimalLayoutSize();
}
-void DataStreamDlg::Init(const OUString& rURL, const OUString& rRange, const sal_Int32 nLimit,
- const OUString& rMove, const sal_uInt32 nSettings)
+ScRange DataStreamDlg::GetStartRange()
+{
+ OUString aStr = m_pEdRange->GetText();
+ ScDocument* pDoc = mpDocShell->GetDocument();
+ ScRange aRange;
+ sal_uInt16 nRes = aRange.Parse(aStr, pDoc);
+ if ((nRes & SCA_VALID) != SCA_VALID || !aRange.IsValid())
+ {
+ // Invalid range.
+ aRange.SetInvalid();
+ return aRange;
+ }
+
+ // Make sure it's only one row tall.
+ if (aRange.aStart.Row() != aRange.aEnd.Row())
+ aRange.SetInvalid();
+
+ return aRange;
+}
+
+void DataStreamDlg::Init( const DataStream& rStrm )
{
- m_pEdLimit->SetText(OUString::number(nLimit));
- m_pCbUrl->SetText(rURL);
- if (nSettings & DataStream::SCRIPT_STREAM)
- m_pRBScriptData->Check();
- if (!(nSettings & DataStream::VALUES_IN_LINE))
- m_pRBAddressValue->Check();
- m_pEdRange->SetText(rRange);
- if (rMove == "NO_MOVE")
- m_pRBNoMove->Check();
- else if (rMove == "RANGE_DOWN")
- m_pRBRangeDown->Check();
- else if (rMove == "MOVE_DOWN")
- m_pRBDataDown->Check();
+ m_pCbUrl->SetText(rStrm.GetURL());
+
+ ScRange aRange = rStrm.GetRange();
+ ScRange aTopRange = aRange;
+ aTopRange.aEnd.SetRow(aTopRange.aStart.Row());
+ OUString aStr = aTopRange.Format(SCA_VALID);
+ m_pEdRange->SetText(aStr);
+ SCROW nRows = aRange.aEnd.Row() - aRange.aStart.Row() + 1;
+
+ if (aRange.aEnd.Row() == MAXROW)
+ m_pRBUnlimited->Check();
+ else
+ {
+ m_pRBMaxLimit->Check();
+ m_pEdLimit->SetText(OUString::number(nRows));
+ }
+
+ DataStream::MoveType eMove = rStrm.GetMove();
+ switch (eMove)
+ {
+ case DataStream::MOVE_DOWN:
+ m_pRBDataDown->Check();
+ break;
+ break;
+ case DataStream::RANGE_DOWN:
+ m_pRBRangeDown->Check();
+ break;
+ case DataStream::MOVE_UP:
+ case DataStream::NO_MOVE:
+ default:
+ ;
+ }
+
+ m_pCBRefreshOnEmpty->Check(rStrm.IsRefreshOnEmptyLine());
+
UpdateEnable();
}
-void DataStreamDlg::StartStream(DataStream *pStream)
+void DataStreamDlg::StartStream()
{
+ ScRange aStartRange = GetStartRange();
+ if (!aStartRange.IsValid())
+ // Don't start the stream without a valid range.
+ return;
+
sal_Int32 nLimit = 0;
if (m_pRBMaxLimit->IsChecked())
nLimit = m_pEdLimit->GetText().toInt32();
@@ -109,24 +171,16 @@ void DataStreamDlg::StartStream(DataStream *pStream)
nSettings |= DataStream::SCRIPT_STREAM;
if (m_pRBValuesInLine->IsChecked())
nSettings |= DataStream::VALUES_IN_LINE;
- if (pStream)
- {
- pStream->Decode(rURL, m_pEdRange->GetText(), nLimit,
- m_pRBNoMove->IsChecked() ? OUString("NO_MOVE") : m_pRBRangeDown->IsChecked()
- ? OUString("RANGE_DOWN") : OUString("MOVE_DOWN"),
- nSettings);
- return;
- }
- pStream = DataStream::Set( mpDocShell,
- rURL,
- m_pEdRange->GetText(),
- nLimit,
- m_pRBNoMove->IsChecked() ? OUString("NO_MOVE") : m_pRBRangeDown->IsChecked()
- ? OUString("RANGE_DOWN") : OUString("MOVE_DOWN")
- , nSettings
- );
+
+ DataStream::MoveType eMove =
+ m_pRBRangeDown->IsChecked() ? DataStream::RANGE_DOWN : DataStream::MOVE_DOWN;
+
+ DataStream* pStream = DataStream::Set(mpDocShell, rURL, aStartRange, nLimit, eMove, nSettings);
+ pStream->SetRefreshOnEmptyLine(m_pCBRefreshOnEmpty->IsChecked());
DataStream::MakeToolbarVisible();
pStream->StartImport();
}
+}
+
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/view/cellsh2.cxx b/sc/source/ui/view/cellsh2.cxx
index 5a0720c1123c..a93761c10d06 100644
--- a/sc/source/ui/view/cellsh2.cxx
+++ b/sc/source/ui/view/cellsh2.cxx
@@ -20,7 +20,6 @@
#include "scitems.hxx"
#include <sfx2/viewfrm.hxx>
#include <sfx2/app.hxx>
-#include <sfx2/linkmgr.hxx>
#include <sfx2/request.hxx>
#include <svl/aeitem.hxx>
#include <basic/sbxcore.hxx>
@@ -62,6 +61,7 @@
#include "datastreamdlg.hxx"
#include "queryentry.hxx"
#include "markdata.hxx"
+#include <documentlinkmgr.hxx>
#include <config_orcus.h>
@@ -742,36 +742,36 @@ void ScCellShell::ExecuteDB( SfxRequest& rReq )
}
break;
case SID_DATA_STREAMS:
- {
- DataStreamDlg aDialog( GetViewData()->GetDocShell(), pTabViewShell->GetDialogParent() );
- if (aDialog.Execute() == RET_OK)
- aDialog.StartStream();
- }
- break;
+ {
+ sc::DataStreamDlg aDialog( GetViewData()->GetDocShell(), pTabViewShell->GetDialogParent() );
+ ScDocument *pDoc = GetViewData()->GetDocument();
+ sc::DocumentLinkManager& rMgr = pDoc->GetDocLinkManager();
+ sc::DataStream* pStrm = rMgr.getDataStream();
+ if (pStrm)
+ aDialog.Init(*pStrm);
+
+ if (aDialog.Execute() == RET_OK)
+ aDialog.StartStream();
+ }
+ break;
case SID_DATA_STREAMS_PLAY:
- {
- ScDocument *pDoc = GetViewData()->GetDocument();
- if (pDoc->GetLinkManager())
- {
- const sfx2::SvBaseLinks& rLinks = pDoc->GetLinkManager()->GetLinks();
- for (size_t i = 0; i < rLinks.size(); i++)
- if (DataStream *pStream = dynamic_cast<DataStream*>(&(*(*rLinks[i]))))
- pStream->StartImport();
- }
- }
- break;
+ {
+ ScDocument *pDoc = GetViewData()->GetDocument();
+ sc::DocumentLinkManager& rMgr = pDoc->GetDocLinkManager();
+ sc::DataStream* pStrm = rMgr.getDataStream();
+ if (pStrm)
+ pStrm->StartImport();
+ }
+ break;
case SID_DATA_STREAMS_STOP:
- {
- ScDocument *pDoc = GetViewData()->GetDocument();
- if (pDoc->GetLinkManager())
- {
- const sfx2::SvBaseLinks& rLinks = pDoc->GetLinkManager()->GetLinks();
- for (size_t i = 0; i < rLinks.size(); i++)
- if (DataStream *pStream = dynamic_cast<DataStream*>(&(*(*rLinks[i]))))
- pStream->StopImport();
- }
- }
- break;
+ {
+ ScDocument *pDoc = GetViewData()->GetDocument();
+ sc::DocumentLinkManager& rMgr = pDoc->GetDocLinkManager();
+ sc::DataStream* pStrm = rMgr.getDataStream();
+ if (pStrm)
+ pStrm->StopImport();
+ }
+ break;
case SID_MANAGE_XML_SOURCE:
ExecuteXMLSourceDialog();
break;
diff --git a/sc/source/ui/view/tabview3.cxx b/sc/source/ui/view/tabview3.cxx
index e258761fc948..cedb9bab0194 100644
--- a/sc/source/ui/view/tabview3.cxx
+++ b/sc/source/ui/view/tabview3.cxx
@@ -2634,8 +2634,12 @@ void ScTabView::CheckNeedsRepaint()
pGridWin[i]->CheckNeedsRepaint();
}
-
-
-
+bool ScTabView::NeedsRepaint()
+{
+ for (size_t i = 0; i < 4; i++)
+ if (pGridWin[i] && pGridWin[i]->IsVisible() && pGridWin[i]->NeedsRepaint())
+ return true;
+ return false;
+}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/uiconfig/scalc/ui/datastreams.ui b/sc/uiconfig/scalc/ui/datastreams.ui
index 1c2abe78f18b..cd4888661460 100644
--- a/sc/uiconfig/scalc/ui/datastreams.ui
+++ b/sc/uiconfig/scalc/ui/datastreams.ui
@@ -174,6 +174,7 @@
<property name="receives_default">False</property>
<property name="use_underline">True</property>
<property name="xalign">0</property>
+ <property name="active">True</property>
<property name="draw_indicator">True</property>
<property name="group">addressvalue</property>
</object>
@@ -323,6 +324,7 @@
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="use_underline">True</property>
+ <property name="active">True</property>
<property name="xalign">0</property>
<property name="draw_indicator">True</property>
<property name="group">datadown</property>
@@ -401,6 +403,7 @@
<property name="receives_default">False</property>
<property name="use_underline">True</property>
<property name="xalign">0</property>
+ <property name="active">True</property>
<property name="draw_indicator">True</property>
<property name="group">unlimited</property>
</object>
diff --git a/xmloff/source/core/xmltoken.cxx b/xmloff/source/core/xmltoken.cxx
index 431e778ea958..5840f951b746 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 ),