summaryrefslogtreecommitdiffstats
path: root/sw/source/core/swg
diff options
context:
space:
mode:
Diffstat (limited to 'sw/source/core/swg')
-rw-r--r--sw/source/core/swg/BlockListTokens.txt7
-rw-r--r--sw/source/core/swg/SwXMLBlockExport.cxx138
-rw-r--r--sw/source/core/swg/SwXMLBlockImport.cxx337
-rw-r--r--sw/source/core/swg/SwXMLSectionList.cxx131
-rw-r--r--sw/source/core/swg/SwXMLTextBlocks.cxx572
-rw-r--r--sw/source/core/swg/SwXMLTextBlocks1.cxx583
-rw-r--r--sw/source/core/swg/TextBlockTokens.txt5
-rw-r--r--sw/source/core/swg/swblocks.cxx582
8 files changed, 2355 insertions, 0 deletions
diff --git a/sw/source/core/swg/BlockListTokens.txt b/sw/source/core/swg/BlockListTokens.txt
new file mode 100644
index 0000000000..0b5a64607b
--- /dev/null
+++ b/sw/source/core/swg/BlockListTokens.txt
@@ -0,0 +1,7 @@
+abbreviated-name
+block
+block-list
+list-name
+name
+package-name
+unformatted-text
diff --git a/sw/source/core/swg/SwXMLBlockExport.cxx b/sw/source/core/swg/SwXMLBlockExport.cxx
new file mode 100644
index 0000000000..fe085a4a51
--- /dev/null
+++ b/sw/source/core/swg/SwXMLBlockExport.cxx
@@ -0,0 +1,138 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <SwXMLBlockExport.hxx>
+#include <SwXMLTextBlocks.hxx>
+#include <com/sun/star/util/MeasureUnit.hpp>
+#include <com/sun/star/xml/sax/XDocumentHandler.hpp>
+#include <xmloff/namespacemap.hxx>
+#include <xmloff/xmlnamespace.hxx>
+#include <o3tl/string_view.hxx>
+
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star;
+using namespace ::xmloff::token;
+
+SwXMLBlockListExport::SwXMLBlockListExport(
+ const uno::Reference< uno::XComponentContext >& rContext,
+ SwXMLTextBlocks & rBlocks,
+ const OUString &rFileName,
+ uno::Reference< xml::sax::XDocumentHandler> const &rHandler)
+: SvXMLExport( rContext, "", rFileName, util::MeasureUnit::CM, rHandler ),
+ m_rBlockList(rBlocks)
+{
+ GetNamespaceMap_().Add( GetXMLToken ( XML_NP_BLOCK_LIST ),
+ GetXMLToken ( XML_N_BLOCK_LIST ),
+ XML_NAMESPACE_BLOCKLIST );
+}
+
+ErrCode SwXMLBlockListExport::exportDoc(enum XMLTokenEnum )
+{
+ GetDocHandler()->startDocument();
+
+ addChaffWhenEncryptedStorage();
+
+ AddAttribute ( XML_NAMESPACE_NONE,
+ GetNamespaceMap_().GetAttrNameByKey ( XML_NAMESPACE_BLOCKLIST ),
+ GetNamespaceMap_().GetNameByKey ( XML_NAMESPACE_BLOCKLIST ) );
+ AddAttribute( XML_NAMESPACE_BLOCKLIST,
+ XML_LIST_NAME,
+ m_rBlockList.GetName());
+ {
+ SvXMLElementExport aRoot (*this, XML_NAMESPACE_BLOCKLIST, XML_BLOCK_LIST, true, true);
+ sal_uInt16 nBlocks= m_rBlockList.GetCount();
+ for ( sal_uInt16 i = 0; i < nBlocks; i++)
+ {
+ AddAttribute( XML_NAMESPACE_BLOCKLIST,
+ XML_ABBREVIATED_NAME,
+ m_rBlockList.GetShortName(i));
+ AddAttribute( XML_NAMESPACE_BLOCKLIST,
+ XML_PACKAGE_NAME,
+ m_rBlockList.GetPackageName(i));
+ AddAttribute( XML_NAMESPACE_BLOCKLIST,
+ XML_NAME,
+ m_rBlockList.GetLongName(i));
+ AddAttribute( XML_NAMESPACE_BLOCKLIST,
+ XML_UNFORMATTED_TEXT,
+ m_rBlockList.IsOnlyTextBlock(i) ? XML_TRUE : XML_FALSE );
+
+ SvXMLElementExport aBlock( *this, XML_NAMESPACE_BLOCKLIST, XML_BLOCK, true, true);
+ }
+ }
+ GetDocHandler()->endDocument();
+ return ERRCODE_NONE;
+}
+
+SwXMLTextBlockExport::SwXMLTextBlockExport(
+ const uno::Reference< uno::XComponentContext >& rContext,
+ SwXMLTextBlocks & rBlocks,
+ const OUString &rFileName,
+ uno::Reference< xml::sax::XDocumentHandler> const &rHandler)
+: SvXMLExport( rContext, "", rFileName, util::MeasureUnit::CM, rHandler ),
+ m_rBlockList(rBlocks)
+{
+ GetNamespaceMap_().Add( GetXMLToken ( XML_NP_BLOCK_LIST ),
+ GetXMLToken ( XML_N_BLOCK_LIST ),
+ XML_NAMESPACE_BLOCKLIST );
+ GetNamespaceMap_().Add( GetXMLToken ( XML_NP_OFFICE ),
+ GetXMLToken(XML_N_OFFICE_OOO),
+ XML_NAMESPACE_OFFICE );
+ GetNamespaceMap_().Add( GetXMLToken ( XML_NP_TEXT ),
+ GetXMLToken(XML_N_TEXT_OOO),
+ XML_NAMESPACE_TEXT );
+}
+
+void SwXMLTextBlockExport::exportDoc(std::u16string_view rText)
+{
+ GetDocHandler()->startDocument();
+
+ addChaffWhenEncryptedStorage();
+
+ AddAttribute ( XML_NAMESPACE_NONE,
+ GetNamespaceMap_().GetAttrNameByKey ( XML_NAMESPACE_BLOCKLIST ),
+ GetNamespaceMap_().GetNameByKey ( XML_NAMESPACE_BLOCKLIST ) );
+ AddAttribute ( XML_NAMESPACE_NONE,
+ GetNamespaceMap_().GetAttrNameByKey ( XML_NAMESPACE_TEXT ),
+ GetNamespaceMap_().GetNameByKey ( XML_NAMESPACE_TEXT ) );
+ AddAttribute ( XML_NAMESPACE_NONE,
+ GetNamespaceMap_().GetAttrNameByKey ( XML_NAMESPACE_OFFICE ),
+ GetNamespaceMap_().GetNameByKey ( XML_NAMESPACE_OFFICE ) );
+ AddAttribute( XML_NAMESPACE_BLOCKLIST,
+ XML_LIST_NAME,
+ m_rBlockList.GetName());
+ {
+ SvXMLElementExport aDocument (*this, XML_NAMESPACE_OFFICE, XML_DOCUMENT, true, true);
+ {
+ SvXMLElementExport aBody (*this, XML_NAMESPACE_OFFICE, XML_BODY, true, true);
+ {
+ sal_Int32 nPos = 0;
+ do
+ {
+ OUString sTemp ( o3tl::getToken(rText, 0, '\015', nPos ) );
+ SvXMLElementExport aPara (*this, XML_NAMESPACE_TEXT, XML_P, true, false);
+ GetDocHandler()->characters(sTemp);
+ } while (-1 != nPos );
+ }
+
+ }
+ }
+ GetDocHandler()->endDocument();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/swg/SwXMLBlockImport.cxx b/sw/source/core/swg/SwXMLBlockImport.cxx
new file mode 100644
index 0000000000..b0453a8a5a
--- /dev/null
+++ b/sw/source/core/swg/SwXMLBlockImport.cxx
@@ -0,0 +1,337 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <SwXMLBlockImport.hxx>
+#include <SwXMLTextBlocks.hxx>
+#include <xmloff/xmlictxt.hxx>
+#include <unotools/charclass.hxx>
+#include <swtypes.hxx>
+
+#if defined __clang__
+#if __has_warning("-Wdeprecated-register")
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wdeprecated-register"
+#endif
+#endif
+#include <tokens.cxx>
+#if defined __clang__
+#if __has_warning("-Wdeprecated-register")
+#pragma GCC diagnostic pop
+#endif
+#endif
+
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star;
+using namespace css::xml::sax;
+
+class SwXMLBlockListImport;
+class SwXMLTextBlockImport;
+
+namespace {
+
+class SwXMLBlockListContext : public SvXMLImportContext
+{
+private:
+ SwXMLBlockListImport& m_rLocalRef;
+
+public:
+ SwXMLBlockListContext( SwXMLBlockListImport& rImport,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList > & xAttrList );
+
+ virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(
+ sal_Int32 Element, const css::uno::Reference< css::xml::sax::XFastAttributeList > & xAttrList ) override;
+};
+
+class SwXMLBlockContext : public SvXMLImportContext
+{
+public:
+ SwXMLBlockContext( SwXMLBlockListImport& rImport,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList > & xAttrList );
+};
+
+class SwXMLTextBlockDocumentContext : public SvXMLImportContext
+{
+private:
+ SwXMLTextBlockImport& m_rLocalRef;
+
+public:
+ SwXMLTextBlockDocumentContext( SwXMLTextBlockImport& rImport );
+
+ virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(
+ sal_Int32 Element, const css::uno::Reference< css::xml::sax::XFastAttributeList > & xAttrList ) override;
+};
+
+class SwXMLTextBlockBodyContext : public SvXMLImportContext
+{
+private:
+ SwXMLTextBlockImport& m_rLocalRef;
+
+public:
+ SwXMLTextBlockBodyContext( SwXMLTextBlockImport& rImport );
+
+ virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(
+ sal_Int32, const css::uno::Reference< css::xml::sax::XFastAttributeList > & xAttrList ) override;
+};
+
+class SwXMLTextBlockTextContext : public SvXMLImportContext
+{
+private:
+ SwXMLTextBlockImport& m_rLocalRef;
+
+public:
+ SwXMLTextBlockTextContext( SwXMLTextBlockImport& rImport );
+
+ virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(
+ sal_Int32 Element,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList > & xAttrList ) override;
+};
+
+class SwXMLTextBlockParContext : public SvXMLImportContext
+{
+private:
+ SwXMLTextBlockImport& m_rLocalRef;
+
+public:
+ SwXMLTextBlockParContext( SwXMLTextBlockImport & rImport );
+
+ virtual void SAL_CALL characters( const OUString & aChars ) override;
+
+ virtual ~SwXMLTextBlockParContext() override;
+};
+
+}
+
+SwXMLTextBlockTokenHandler::SwXMLTextBlockTokenHandler()
+{
+}
+
+SwXMLTextBlockTokenHandler::~SwXMLTextBlockTokenHandler()
+{
+}
+
+sal_Int32 SAL_CALL SwXMLTextBlockTokenHandler::getTokenFromUTF8( const Sequence< sal_Int8 >& Identifier )
+{
+ return getTokenDirect( reinterpret_cast< const char* >( Identifier.getConstArray() ), Identifier.getLength() );
+}
+
+Sequence< sal_Int8 > SAL_CALL SwXMLTextBlockTokenHandler::getUTF8Identifier( sal_Int32 )
+{
+ return Sequence< sal_Int8 >();
+}
+
+sal_Int32 SwXMLTextBlockTokenHandler::getTokenDirect( const char *pTag, sal_Int32 nLength ) const
+{
+ if( !nLength )
+ nLength = strlen( pTag );
+ const struct xmltoken* pToken = TextBlockTokens::in_word_set( pTag, nLength );
+ return pToken ? pToken->nToken : XML_TOKEN_INVALID;
+}
+
+SwXMLBlockListTokenHandler::SwXMLBlockListTokenHandler()
+{
+}
+
+SwXMLBlockListTokenHandler::~SwXMLBlockListTokenHandler()
+{
+}
+
+sal_Int32 SAL_CALL SwXMLBlockListTokenHandler::getTokenFromUTF8( const Sequence< sal_Int8 >& Identifier )
+{
+ return getTokenDirect( reinterpret_cast< const char* >( Identifier.getConstArray() ), Identifier.getLength() );
+}
+
+Sequence< sal_Int8 > SAL_CALL SwXMLBlockListTokenHandler::getUTF8Identifier( sal_Int32 )
+{
+ return Sequence< sal_Int8 >();
+}
+
+sal_Int32 SwXMLBlockListTokenHandler::getTokenDirect( const char *pTag, sal_Int32 nLength ) const
+{
+ if( !nLength )
+ nLength = strlen( pTag );
+ const struct xmltoken* pToken = BlockListTokens::in_word_set( pTag, nLength );
+ return pToken ? pToken->nToken : XML_TOKEN_INVALID;
+}
+
+SwXMLBlockListContext::SwXMLBlockListContext(
+ SwXMLBlockListImport& rImport, const uno::Reference<xml::sax::XFastAttributeList>& xAttrList)
+ : SvXMLImportContext(rImport)
+ , m_rLocalRef(rImport)
+{
+ if( xAttrList.is() && xAttrList->hasAttribute( SwXMLBlockListToken::LIST_NAME ) )
+ rImport.getBlockList().SetName( xAttrList->getValue( SwXMLBlockListToken::LIST_NAME ) );
+}
+
+uno::Reference< ::xml::sax::XFastContextHandler > SAL_CALL
+SwXMLBlockListContext::createFastChildContext( sal_Int32 Element,
+ const uno::Reference< xml::sax::XFastAttributeList > & xAttrList )
+{
+ if ( Element == SwXMLBlockListToken::BLOCK )
+ return new SwXMLBlockContext(m_rLocalRef, xAttrList);
+ return nullptr;
+}
+
+SwXMLBlockContext::SwXMLBlockContext(
+ SwXMLBlockListImport& rImport,
+ const uno::Reference< xml::sax::XFastAttributeList > & xAttrList ) :
+ SvXMLImportContext( rImport )
+{
+ static const CharClass & rCC = GetAppCharClass();
+ OUString aShort, aLong, aPackageName;
+ bool bTextOnly = false;
+ if( xAttrList.is() )
+ {
+ if( xAttrList->hasAttribute( SwXMLBlockListToken::ABBREVIATED_NAME ) )
+ aShort = rCC.uppercase( xAttrList->getValue( SwXMLBlockListToken::ABBREVIATED_NAME ) );
+ if( xAttrList->hasAttribute( SwXMLBlockListToken::NAME ) )
+ aLong = xAttrList->getValue( SwXMLBlockListToken::NAME );
+ if( xAttrList->hasAttribute( SwXMLBlockListToken::PACKAGE_NAME ) )
+ aPackageName = xAttrList->getValue( SwXMLBlockListToken::PACKAGE_NAME );
+ if( xAttrList->hasAttribute( SwXMLBlockListToken::UNFORMATTED_TEXT ) )
+ {
+ OUString rAttrValue( xAttrList->getValue( SwXMLBlockListToken::UNFORMATTED_TEXT ) );
+ if( IsXMLToken( rAttrValue, XML_TRUE ) )
+ bTextOnly = true;
+ }
+ }
+ if (aShort.isEmpty() || aLong.isEmpty() || aPackageName.isEmpty())
+ return;
+ rImport.getBlockList().AddName( aShort, aLong, aPackageName, bTextOnly);
+}
+
+SwXMLTextBlockDocumentContext::SwXMLTextBlockDocumentContext(SwXMLTextBlockImport& rImport)
+ : SvXMLImportContext(rImport)
+ , m_rLocalRef(rImport)
+{
+}
+
+uno::Reference< ::xml::sax::XFastContextHandler > SAL_CALL
+SwXMLTextBlockDocumentContext::createFastChildContext( sal_Int32 Element,
+ const uno::Reference< xml::sax::XFastAttributeList > & /*xAttrList*/ )
+{
+ if ( Element == SwXMLTextBlockToken::OFFICE_BODY )
+ return new SwXMLTextBlockBodyContext(m_rLocalRef);
+ return nullptr;
+}
+
+SwXMLTextBlockTextContext::SwXMLTextBlockTextContext(SwXMLTextBlockImport& rImport)
+ : SvXMLImportContext(rImport)
+ , m_rLocalRef(rImport)
+{
+}
+
+uno::Reference< xml::sax::XFastContextHandler > SAL_CALL
+SwXMLTextBlockTextContext::createFastChildContext( sal_Int32 Element,
+ const uno::Reference< xml::sax::XFastAttributeList > & /*xAttrList*/ )
+{
+ if ( Element == SwXMLTextBlockToken::TEXT_P )
+ return new SwXMLTextBlockParContext(m_rLocalRef);
+ return nullptr;
+}
+
+SwXMLTextBlockBodyContext::SwXMLTextBlockBodyContext(SwXMLTextBlockImport& rImport)
+ : SvXMLImportContext(rImport)
+ , m_rLocalRef(rImport)
+{
+}
+
+uno::Reference < xml::sax::XFastContextHandler > SAL_CALL
+SwXMLTextBlockBodyContext::createFastChildContext( sal_Int32 Element,
+ const uno::Reference< xml::sax::XFastAttributeList > & /*xAttrList*/ )
+{
+ if( Element == SwXMLTextBlockToken::OFFICE_TEXT )
+ return new SwXMLTextBlockTextContext(m_rLocalRef);
+ else if( Element == SwXMLTextBlockToken::TEXT_P )
+ return new SwXMLTextBlockParContext(m_rLocalRef);
+ return nullptr;
+}
+
+SwXMLTextBlockParContext::SwXMLTextBlockParContext(SwXMLTextBlockImport& rImport)
+ : SvXMLImportContext(rImport)
+ , m_rLocalRef(rImport)
+{
+}
+
+void SAL_CALL SwXMLTextBlockParContext::characters( const OUString & aChars )
+{
+ m_rLocalRef.m_rText += aChars;
+}
+
+SwXMLTextBlockParContext::~SwXMLTextBlockParContext()
+{
+ if (m_rLocalRef.m_bTextOnly)
+ m_rLocalRef.m_rText += "\015";
+ else
+ {
+ if (!m_rLocalRef.m_rText.endsWith(" "))
+ m_rLocalRef.m_rText += " ";
+ }
+}
+
+// SwXMLBlockListImport //////////////////////////////
+SwXMLBlockListImport::SwXMLBlockListImport(
+ const uno::Reference< uno::XComponentContext >& rContext,
+ SwXMLTextBlocks &rBlocks )
+: SvXMLImport( rContext, "", SvXMLImportFlags::NONE ),
+ m_rBlockList (rBlocks)
+{
+}
+
+SwXMLBlockListImport::~SwXMLBlockListImport()
+ noexcept
+{
+}
+
+SvXMLImportContext* SwXMLBlockListImport::CreateFastContext( sal_Int32 Element,
+ const uno::Reference< xml::sax::XFastAttributeList > & xAttrList )
+{
+ if( Element == SwXMLBlockListToken::BLOCK_LIST )
+ return new SwXMLBlockListContext( *this, xAttrList );
+ return nullptr;
+}
+
+SwXMLTextBlockImport::SwXMLTextBlockImport(
+ const uno::Reference< uno::XComponentContext >& rContext,
+ OUString & rNewText,
+ bool bNewTextOnly )
+: SvXMLImport(rContext, "", SvXMLImportFlags::ALL ),
+ m_bTextOnly ( bNewTextOnly ),
+ m_rText ( rNewText )
+{
+}
+
+SwXMLTextBlockImport::~SwXMLTextBlockImport()
+ noexcept
+{
+}
+
+SvXMLImportContext* SwXMLTextBlockImport::CreateFastContext( sal_Int32 Element,
+ const uno::Reference< xml::sax::XFastAttributeList > & /*xAttrList*/ )
+{
+ if( Element == SwXMLTextBlockToken::OFFICE_DOCUMENT ||
+ Element == SwXMLTextBlockToken::OFFICE_DOCUMENT_CONTENT )
+ return new SwXMLTextBlockDocumentContext( *this );
+ return nullptr;
+}
+
+void SAL_CALL SwXMLTextBlockImport::endDocument()
+{
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/swg/SwXMLSectionList.cxx b/sw/source/core/swg/SwXMLSectionList.cxx
new file mode 100644
index 0000000000..42ed3e7363
--- /dev/null
+++ b/sw/source/core/swg/SwXMLSectionList.cxx
@@ -0,0 +1,131 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <SwXMLSectionList.hxx>
+#include <xmloff/xmlictxt.hxx>
+#include <xmloff/xmlnamespace.hxx>
+#include <xmloff/xmltoken.hxx>
+#include <vector>
+
+using namespace ::com::sun::star;
+using namespace ::xmloff::token;
+
+namespace {
+
+class SvXMLSectionListContext : public SvXMLImportContext
+{
+private:
+ SwXMLSectionList & GetImport() { return static_cast<SwXMLSectionList&>(SvXMLImportContext::GetImport()); }
+
+public:
+ SvXMLSectionListContext(SwXMLSectionList& rImport);
+
+ virtual css::uno::Reference<css::xml::sax::XFastContextHandler> SAL_CALL createFastChildContext(
+ sal_Int32 Element,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList > & xAttrList ) override;
+};
+
+class SwXMLParentContext : public SvXMLImportContext
+{
+private:
+ SwXMLSectionList & GetImport() { return static_cast<SwXMLSectionList&>(SvXMLImportContext::GetImport()); }
+
+public:
+ SwXMLParentContext(SwXMLSectionList& rImport)
+ : SvXMLImportContext(rImport)
+ {
+ }
+
+ virtual css::uno::Reference<XFastContextHandler> SAL_CALL createFastChildContext(
+ sal_Int32 Element, const css::uno::Reference< css::xml::sax::XFastAttributeList > & /*xAttrList*/ ) override
+ {
+ if (Element == XML_ELEMENT(OFFICE, XML_BODY) ||
+ Element == XML_ELEMENT(OFFICE_OOO, XML_BODY))
+ {
+ return new SvXMLSectionListContext(GetImport());
+ }
+ if (IsTokenInNamespace(Element, XML_NAMESPACE_TEXT) ||
+ IsTokenInNamespace(Element, XML_NAMESPACE_TEXT_OOO))
+ {
+ auto nToken = Element & TOKEN_MASK;
+ if (nToken == XML_P ||
+ nToken == XML_H ||
+ nToken == XML_A ||
+ nToken == XML_SPAN ||
+ nToken == XML_SECTION ||
+ nToken == XML_INDEX_BODY ||
+ nToken == XML_INDEX_TITLE ||
+ nToken == XML_INSERTION ||
+ nToken == XML_DELETION)
+ return new SvXMLSectionListContext(GetImport());
+ }
+ return new SwXMLParentContext(GetImport());
+ }
+};
+
+}
+
+SwXMLSectionList::SwXMLSectionList(const css::uno::Reference< css::uno::XComponentContext >& rContext, std::vector<OUString> &rNewSectionList)
+: SvXMLImport(rContext, "")
+, m_rSectionList(rNewSectionList)
+{
+}
+
+SwXMLSectionList::~SwXMLSectionList()
+ noexcept
+{
+}
+
+SvXMLImportContext * SwXMLSectionList::CreateFastContext(
+ sal_Int32 /*Element*/,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList > & /*xAttrList*/ )
+{
+ return new SwXMLParentContext(*this);
+}
+
+SvXMLSectionListContext::SvXMLSectionListContext( SwXMLSectionList& rImport )
+ : SvXMLImportContext ( rImport )
+{
+}
+
+css::uno::Reference<css::xml::sax::XFastContextHandler> SvXMLSectionListContext::createFastChildContext(
+ sal_Int32 Element,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList > & xAttrList )
+{
+ SvXMLImportContext *pContext = nullptr;
+
+ if (Element == XML_ELEMENT(TEXT, XML_SECTION ) ||
+ Element == XML_ELEMENT(TEXT, XML_BOOKMARK) ||
+ Element == XML_ELEMENT(TEXT_OOO, XML_SECTION ) ||
+ Element == XML_ELEMENT(TEXT_OOO, XML_BOOKMARK) )
+ {
+ OUString sName;
+ for (auto &aIter : sax_fastparser::castToFastAttributeList( xAttrList ))
+ if (aIter.getToken() == XML_ELEMENT(TEXT, XML_NAME) ||
+ aIter.getToken() == XML_ELEMENT(TEXT_OOO, XML_NAME))
+ sName = aIter.toString();
+ if ( !sName.isEmpty() )
+ GetImport().m_rSectionList.push_back(sName);
+ }
+
+ pContext = new SvXMLSectionListContext(GetImport());
+ return pContext;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/swg/SwXMLTextBlocks.cxx b/sw/source/core/swg/SwXMLTextBlocks.cxx
new file mode 100644
index 0000000000..efc3e530b0
--- /dev/null
+++ b/sw/source/core/swg/SwXMLTextBlocks.cxx
@@ -0,0 +1,572 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <com/sun/star/embed/ElementModes.hpp>
+#include <com/sun/star/embed/XTransactedObject.hpp>
+#include <com/sun/star/embed/XStorage.hpp>
+#include <com/sun/star/container/ElementExistException.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <osl/file.hxx>
+#include <rtl/ustring.hxx>
+#include <sal/log.hxx>
+#include <sot/exchange.hxx>
+#include <sot/stg.hxx>
+#include <sfx2/docfile.hxx>
+#include <tools/urlobj.hxx>
+#include <comphelper/diagnose_ex.hxx>
+#include <unotools/ucbstreamhelper.hxx>
+#include <o3tl/string_view.hxx>
+
+#include <comphelper/storagehelper.hxx>
+#include <doc.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <IDocumentStylePoolAccess.hxx>
+#include <docsh.hxx>
+#include <pam.hxx>
+#include <swblocks.hxx>
+#include <ndtxt.hxx>
+#include <shellio.hxx>
+#include <poolfmt.hxx>
+#include <SwXMLTextBlocks.hxx>
+#include <swerror.h>
+
+using namespace ::com::sun::star;
+
+void SwXMLTextBlocks::InitBlockMode ( const uno::Reference < embed::XStorage >& rStorage )
+{
+ m_xBlkRoot = rStorage;
+ m_xRoot = nullptr;
+}
+
+void SwXMLTextBlocks::ResetBlockMode ( )
+{
+ m_xBlkRoot = nullptr;
+ m_xRoot = nullptr;
+}
+
+SwXMLTextBlocks::SwXMLTextBlocks( const OUString& rFile )
+ : SwImpBlocks(rFile)
+ , m_nFlags(SwXmlFlags::NONE)
+{
+ SwDocShell* pDocSh = new SwDocShell ( SfxObjectCreateMode::INTERNAL );
+ if( !pDocSh->DoInitNew() )
+ return;
+ m_bReadOnly = true;
+ m_xDoc = pDocSh->GetDoc();
+ m_xDocShellRef = pDocSh;
+ m_xDoc->SetOle2Link( Link<bool,void>() );
+ m_xDoc->GetIDocumentUndoRedo().DoUndo(false);
+ uno::Reference< embed::XStorage > refStg;
+ if( !m_aDateModified.GetDate() || !m_aTimeModified.GetTime() )
+ Touch(); // If it's created anew -> get a new timestamp
+
+ try
+ {
+ refStg = comphelper::OStorageHelper::GetStorageFromURL( rFile, embed::ElementModes::READWRITE );
+ m_bReadOnly = false;
+ }
+ catch(const uno::Exception&)
+ {
+ //FIXME: couldn't open the file - maybe it's readonly
+ }
+ if( !refStg.is())
+ {
+ try
+ {
+ refStg = comphelper::OStorageHelper::GetStorageFromURL( rFile, embed::ElementModes::READ );
+ }
+ catch(const uno::Exception&)
+ {
+ TOOLS_WARN_EXCEPTION( "sw", "exception while creating AutoText storage");
+ }
+ }
+ InitBlockMode ( refStg );
+ ReadInfo();
+ ResetBlockMode ();
+ m_bInfoChanged = false;
+}
+
+SwXMLTextBlocks::SwXMLTextBlocks( const uno::Reference < embed::XStorage >& rStg, const OUString& rName )
+ : SwImpBlocks( rName )
+ , m_nFlags(SwXmlFlags::NONE)
+{
+ SwDocShell* pDocSh = new SwDocShell ( SfxObjectCreateMode::INTERNAL );
+ if( !pDocSh->DoInitNew() )
+ return;
+ m_bReadOnly = false;
+ m_xDoc = pDocSh->GetDoc();
+ m_xDocShellRef = pDocSh;
+ m_xDoc->SetOle2Link( Link<bool,void>() );
+ m_xDoc->GetIDocumentUndoRedo().DoUndo(false);
+
+ InitBlockMode ( rStg );
+ ReadInfo();
+ m_bInfoChanged = false;
+}
+
+SwXMLTextBlocks::~SwXMLTextBlocks()
+{
+ if ( m_bInfoChanged )
+ WriteInfo();
+ ResetBlockMode ();
+ if(m_xDocShellRef.is())
+ m_xDocShellRef->DoClose();
+ m_xDocShellRef = nullptr;
+}
+
+void SwXMLTextBlocks::ClearDoc()
+{
+ SwDocShell * pDocShell = m_xDoc->GetDocShell();
+ pDocShell->InvalidateModel();
+ pDocShell->ReactivateModel();
+
+ m_xDoc->ClearDoc();
+ pDocShell->ClearEmbeddedObjects();
+}
+
+void SwXMLTextBlocks::AddName( const OUString& rShort, const OUString& rLong, bool bOnlyText )
+{
+ m_aPackageName = GeneratePackageName( rShort );
+ AddName(rShort, rLong, m_aPackageName, bOnlyText);
+}
+
+void SwXMLTextBlocks::AddName( const OUString& rShort, const OUString& rLong,
+ const OUString& rPackageName, bool bOnlyText )
+{
+ sal_uInt16 nIdx = GetIndex( rShort );
+ if (nIdx != USHRT_MAX)
+ {
+ m_aNames.erase( m_aNames.begin() + nIdx );
+ }
+ std::unique_ptr<SwBlockName> pNew(new SwBlockName( rShort, rLong, rPackageName ));
+ pNew->m_bIsOnlyTextFlagInit = true;
+ pNew->m_bIsOnlyText = bOnlyText;
+ m_aNames.insert( std::move(pNew) );
+ m_bInfoChanged = true;
+}
+
+ErrCode SwXMLTextBlocks::Delete( sal_uInt16 n )
+{
+ const OUString aPckName (m_aNames[n]->m_aPackageName);
+ if ( m_xBlkRoot.is() &&
+ m_xBlkRoot->hasByName( aPckName ) && m_xBlkRoot->isStreamElement( aPckName ) )
+ {
+ try
+ {
+ m_xBlkRoot->removeElement ( aPckName );
+ uno::Reference < embed::XTransactedObject > xTrans( m_xBlkRoot, uno::UNO_QUERY );
+ if ( xTrans.is() )
+ xTrans->commit();
+ return ERRCODE_NONE;
+ }
+ catch (const uno::Exception&)
+ {
+ return ERR_SWG_WRITE_ERROR;
+ }
+ }
+ return ERRCODE_NONE;
+}
+
+ErrCode SwXMLTextBlocks::Rename( sal_uInt16 nIdx, const OUString& rNewShort )
+{
+ OSL_ENSURE( m_xBlkRoot.is(), "No storage set" );
+ if(!m_xBlkRoot.is())
+ return ERRCODE_NONE;
+ OUString aOldName (m_aNames[nIdx]->m_aPackageName);
+ m_aShort = rNewShort;
+ m_aPackageName = GeneratePackageName( m_aShort );
+
+ if(aOldName != m_aPackageName)
+ {
+ if (IsOnlyTextBlock ( nIdx ) )
+ {
+ OUString sExt(".xml");
+ OUString aOldStreamName = aOldName + sExt;
+ OUString aNewStreamName = m_aPackageName + sExt;
+
+ m_xRoot = m_xBlkRoot->openStorageElement( aOldName, embed::ElementModes::READWRITE );
+ try
+ {
+ m_xRoot->renameElement ( aOldStreamName, aNewStreamName );
+ }
+ catch(const container::ElementExistException&)
+ {
+ SAL_WARN("sw", "Couldn't rename " << aOldStreamName << " to " << aNewStreamName);
+ }
+ uno::Reference < embed::XTransactedObject > xTrans( m_xRoot, uno::UNO_QUERY );
+ if ( xTrans.is() )
+ xTrans->commit();
+ m_xRoot = nullptr;
+ }
+
+ try
+ {
+ m_xBlkRoot->renameElement ( aOldName, m_aPackageName );
+ }
+ catch(const container::ElementExistException&)
+ {
+ SAL_WARN("sw", "Couldn't rename " << aOldName << " to " << m_aPackageName);
+ }
+ }
+ uno::Reference < embed::XTransactedObject > xTrans( m_xBlkRoot, uno::UNO_QUERY );
+ if ( xTrans.is() )
+ xTrans->commit();
+ // No need to commit xBlkRoot here as SwTextBlocks::Rename calls
+ // WriteInfo which does the commit
+ return ERRCODE_NONE;
+}
+
+ErrCode SwXMLTextBlocks::CopyBlock( SwImpBlocks& rDestImp, OUString& rShort,
+ const OUString& rLong)
+{
+ ErrCode nError = ERRCODE_NONE;
+ OpenFile();
+ rDestImp.OpenFile(false);
+ const OUString aGroup( rShort );
+ bool bTextOnly = IsOnlyTextBlock ( rShort ) ;//pImp->pBlkRoot->IsStream( aGroup );
+ sal_uInt16 nIndex = GetIndex ( rShort );
+ OUString sPackageName( GetPackageName (nIndex) );
+ OUString sDestShortName( sPackageName );
+ sal_uInt16 nIdx = 0;
+
+ OSL_ENSURE( m_xBlkRoot.is(), "No storage set" );
+ if(!m_xBlkRoot.is())
+ return ERR_SWG_WRITE_ERROR;
+
+ uno::Reference < container::XNameAccess > xAccess(static_cast<SwXMLTextBlocks&>(rDestImp).m_xBlkRoot);
+ while ( xAccess->hasByName( sDestShortName ) )
+ {
+ ++nIdx;
+ // If someone is that crazy ...
+ if(USHRT_MAX == nIdx)
+ {
+ CloseFile();
+ rDestImp.CloseFile();
+ return ERR_SWG_WRITE_ERROR;
+ }
+ sDestShortName = sPackageName + OUString::number( nIdx );
+ }
+
+ try
+ {
+ uno::Reference < embed::XStorage > rSourceRoot = m_xBlkRoot->openStorageElement( aGroup, embed::ElementModes::READ );
+ uno::Reference < embed::XStorage > rDestRoot = static_cast<SwXMLTextBlocks&>(rDestImp).m_xBlkRoot->openStorageElement( sDestShortName, embed::ElementModes::READWRITE );
+ rSourceRoot->copyToStorage( rDestRoot );
+ }
+ catch (const uno::Exception&)
+ {
+ nError = ERR_SWG_WRITE_ERROR;
+ }
+
+ if(!nError)
+ {
+ rShort = sDestShortName;
+ static_cast<SwXMLTextBlocks&>(rDestImp).AddName( rShort, rLong, bTextOnly );
+ static_cast<SwXMLTextBlocks&>(rDestImp).MakeBlockList();
+ }
+ CloseFile();
+ rDestImp.CloseFile();
+ return nError;
+}
+
+ErrCode SwXMLTextBlocks::StartPutBlock( const OUString& rShort, const OUString& rPackageName )
+{
+ OSL_ENSURE( m_xBlkRoot.is(), "No storage set" );
+ if(!m_xBlkRoot.is())
+ return ERRCODE_NONE;
+ GetIndex ( rShort );
+ try
+ {
+ m_xRoot = m_xBlkRoot->openStorageElement( rPackageName, embed::ElementModes::READWRITE );
+
+ uno::Reference< beans::XPropertySet > xRootProps( m_xRoot, uno::UNO_QUERY_THROW );
+ OUString aMime( SotExchange::GetFormatMimeType( SotClipboardFormatId::STARWRITER_8 ) );
+ xRootProps->setPropertyValue( "MediaType", uno::Any( aMime ) );
+ }
+ catch (const uno::Exception&)
+ {
+ }
+ return ERRCODE_NONE;
+}
+
+ErrCode SwXMLTextBlocks::BeginPutDoc( const OUString& rShort, const OUString& rLong )
+{
+ // Store in base class
+ m_aShort = rShort;
+ m_aLong = rLong;
+ m_aPackageName = GeneratePackageName( rShort );
+ SetIsTextOnly( rShort, false);
+ return StartPutBlock (rShort, m_aPackageName);
+}
+
+ErrCode SwXMLTextBlocks::PutBlock()
+{
+ ErrCodeMsg nRes = ERRCODE_NONE; // dead variable, this always returns 0
+ SwXmlFlags nCommitFlags = m_nFlags;
+
+ WriterRef xWrt;
+ ::GetXMLWriter ( std::u16string_view(), GetBaseURL(), xWrt);
+ SwWriter aWriter (m_xRoot, *m_xDoc );
+
+ xWrt->m_bBlock = true;
+ nRes = aWriter.Write ( xWrt );
+ xWrt->m_bBlock = false;
+ // Save OLE objects if there are some
+ SwDocShell *pDocSh = m_xDoc->GetDocShell();
+
+ bool bHasChildren = pDocSh && pDocSh->GetEmbeddedObjectContainer().HasEmbeddedObjects();
+ if( !nRes && bHasChildren )
+ {
+ // we have to write to the temporary storage first, since the used below functions are optimized
+ // TODO/LATER: it is only a temporary solution, that should be changed soon, the used methods should be
+ // called without optimization
+ bool bOK = false;
+
+ if ( m_xRoot.is() )
+ {
+ std::unique_ptr<SfxMedium> pTmpMedium;
+ try
+ {
+ uno::Reference< embed::XStorage > xTempStorage =
+ ::comphelper::OStorageHelper::GetTemporaryStorage();
+
+ m_xRoot->copyToStorage( xTempStorage );
+
+ // TODO/LATER: no progress bar?!
+ // TODO/MBA: strange construct
+ pTmpMedium.reset(new SfxMedium(xTempStorage, GetBaseURL()));
+ bool bTmpOK = pDocSh->SaveAsChildren( *pTmpMedium );
+ if( bTmpOK )
+ bTmpOK = pDocSh->SaveCompletedChildren();
+
+ xTempStorage->copyToStorage( m_xRoot );
+ bOK = bTmpOK;
+ }
+ catch(const uno::Exception&)
+ {
+ }
+ }
+
+ if( !bOK )
+ nRes = ERR_SWG_WRITE_ERROR;
+ }
+
+ try
+ {
+ uno::Reference < embed::XTransactedObject > xTrans( m_xRoot, uno::UNO_QUERY );
+ if ( xTrans.is() )
+ xTrans->commit();
+ m_xRoot = nullptr;
+ if ( nCommitFlags == SwXmlFlags::NONE )
+ {
+ uno::Reference < embed::XTransactedObject > xTmpTrans( m_xBlkRoot, uno::UNO_QUERY );
+ if ( xTmpTrans.is() )
+ xTmpTrans->commit();
+ }
+ }
+ catch (const uno::Exception&)
+ {
+ }
+
+ //TODO/LATER: error handling
+ return ERRCODE_NONE;
+}
+
+ErrCode SwXMLTextBlocks::PutDoc()
+{
+ std::unique_ptr<SwPaM> pPaM = MakePaM();
+ ErrCode nErr = PutBlock();
+ return nErr;
+}
+
+ErrCode SwXMLTextBlocks::GetText( std::u16string_view rShort, OUString& rText )
+{
+ return GetBlockText( rShort, rText );
+}
+
+ErrCode SwXMLTextBlocks::MakeBlockList()
+{
+ WriteInfo();
+ return ERRCODE_NONE;
+}
+
+bool SwXMLTextBlocks::PutMuchEntries( bool bOn )
+{
+ bool bRet = false;
+ if( bOn )
+ {
+ if( m_bInPutMuchBlocks )
+ {
+ OSL_ENSURE( false, "Nested calls are not allowed");
+ }
+ else if( !IsFileChanged() )
+ {
+ bRet = ERRCODE_NONE == OpenFile( false );
+ if( bRet )
+ {
+ m_nFlags |= SwXmlFlags::NoRootCommit;
+ m_bInPutMuchBlocks = true;
+ }
+ }
+ }
+ else if( m_bInPutMuchBlocks )
+ {
+ m_nFlags &= ~SwXmlFlags::NoRootCommit;
+ if( m_xBlkRoot.is() )
+ {
+ try
+ {
+ uno::Reference < embed::XTransactedObject > xTrans( m_xBlkRoot, uno::UNO_QUERY );
+ if ( xTrans.is() )
+ xTrans->commit();
+ MakeBlockList();
+ CloseFile();
+ Touch();
+ m_bInPutMuchBlocks = false;
+ bRet = true;
+ }
+ catch (const uno::Exception&)
+ {
+ }
+ }
+ }
+ return bRet;
+}
+
+ErrCode SwXMLTextBlocks::OpenFile( bool bRdOnly )
+{
+ ErrCode nRet = ERRCODE_NONE;
+ try
+ {
+ uno::Reference < embed::XStorage > refStg = comphelper::OStorageHelper::GetStorageFromURL( m_aFile,
+ bRdOnly ? embed::ElementModes::READ : embed::ElementModes::READWRITE );
+ InitBlockMode ( refStg );
+ }
+ catch (const uno::Exception&)
+ {
+ //TODO/LATER: error handling
+ nRet = ErrCode(1);
+ }
+
+ return nRet;
+}
+
+void SwXMLTextBlocks::CloseFile()
+{
+ if (m_bInfoChanged)
+ WriteInfo();
+ ResetBlockMode();
+}
+
+void SwXMLTextBlocks::SetIsTextOnly( const OUString& rShort, bool bNewValue )
+{
+ sal_uInt16 nIdx = GetIndex ( rShort );
+ if (nIdx != USHRT_MAX)
+ m_aNames[nIdx]->m_bIsOnlyText = bNewValue;
+}
+
+bool SwXMLTextBlocks::IsOnlyTextBlock( const OUString& rShort ) const
+{
+ sal_uInt16 nIdx = GetIndex ( rShort );
+ bool bRet = false;
+ if (nIdx != USHRT_MAX)
+ {
+ bRet = m_aNames[nIdx]->m_bIsOnlyText;
+ }
+ return bRet;
+}
+bool SwXMLTextBlocks::IsOnlyTextBlock( sal_uInt16 nIdx ) const
+{
+ return m_aNames[nIdx]->m_bIsOnlyText;
+}
+
+bool SwXMLTextBlocks::IsFileUCBStorage( const OUString & rFileName)
+{
+ OUString aName( rFileName );
+ INetURLObject aObj( aName );
+ if ( aObj.GetProtocol() == INetProtocol::NotValid )
+ {
+ OUString aURL;
+ osl::FileBase::getFileURLFromSystemPath( aName, aURL );
+ aObj.SetURL( aURL );
+ aName = aObj.GetMainURL( INetURLObject::DecodeMechanism::NONE );
+ }
+
+ std::unique_ptr<SvStream> pStm = ::utl::UcbStreamHelper::CreateStream( aName, StreamMode::STD_READ );
+ bool bRet = UCBStorage::IsStorageFile( pStm.get() );
+ return bRet;
+}
+
+OUString SwXMLTextBlocks::GeneratePackageName ( std::u16string_view rShort )
+{
+ OString sByte(OUStringToOString(rShort, RTL_TEXTENCODING_UTF7));
+ OUStringBuffer aBuf(OStringToOUString(sByte, RTL_TEXTENCODING_ASCII_US));
+ const sal_Int32 nLen = aBuf.getLength();
+ for (sal_Int32 nPos=0; nPos<nLen; ++nPos)
+ {
+ switch (aBuf[nPos])
+ {
+ case '!':
+ case '/':
+ case ':':
+ case '.':
+ case '\\':
+ aBuf[nPos] = '_';
+ break;
+ default:
+ break;
+ }
+ }
+ return aBuf.makeStringAndClear();
+}
+
+ErrCode SwXMLTextBlocks::PutText( const OUString& rShort, const OUString& rName,
+ const OUString& rText )
+{
+ ErrCode nRes = ERRCODE_NONE;
+ m_aShort = rShort;
+ m_aLong = rName;
+ m_aCurrentText = rText;
+ SetIsTextOnly( m_aShort, true );
+ m_aPackageName = GeneratePackageName( rShort );
+ ClearDoc();
+ nRes = PutBlockText( rShort, rText, m_aPackageName );
+ return nRes;
+}
+
+void SwXMLTextBlocks::MakeBlockText( std::u16string_view rText )
+{
+ SwTextNode* pTextNode = m_xDoc->GetNodes()[ m_xDoc->GetNodes().GetEndOfContent().
+ GetIndex() - 1 ]->GetTextNode();
+ if( pTextNode->GetTextColl() == m_xDoc->GetDfltTextFormatColl() )
+ pTextNode->ChgFormatColl( m_xDoc->getIDocumentStylePoolAccess().GetTextCollFromPool( RES_POOLCOLL_STANDARD ));
+
+ sal_Int32 nPos = 0;
+ do
+ {
+ if ( nPos )
+ {
+ pTextNode = static_cast<SwTextNode*>(pTextNode->AppendNode( SwPosition( *pTextNode ) ));
+ }
+ SwContentIndex aIdx( pTextNode );
+ pTextNode->InsertText( OUString(o3tl::getToken(rText, 0, '\015', nPos )), aIdx );
+ } while ( -1 != nPos );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/swg/SwXMLTextBlocks1.cxx b/sw/source/core/swg/SwXMLTextBlocks1.cxx
new file mode 100644
index 0000000000..989f3ff93e
--- /dev/null
+++ b/sw/source/core/swg/SwXMLTextBlocks1.cxx
@@ -0,0 +1,583 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <com/sun/star/embed/ElementModes.hpp>
+#include <com/sun/star/embed/XTransactedObject.hpp>
+#include <osl/diagnose.h>
+#include <svl/macitem.hxx>
+#include <svtools/unoevent.hxx>
+#include <sfx2/docfile.hxx>
+#include <comphelper/diagnose_ex.hxx>
+#include <comphelper/fileformat.h>
+#include <comphelper/processfactory.hxx>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/xml/sax/InputSource.hpp>
+#include <com/sun/star/io/IOException.hpp>
+#include <com/sun/star/xml/sax/FastParser.hpp>
+#include <com/sun/star/xml/sax/FastToken.hpp>
+#include <com/sun/star/xml/sax/Parser.hpp>
+#include <com/sun/star/xml/sax/Writer.hpp>
+#include <com/sun/star/xml/sax/SAXParseException.hpp>
+#include <com/sun/star/document/XStorageBasedDocument.hpp>
+#include <doc.hxx>
+#include <docsh.hxx>
+#include <shellio.hxx>
+#include <SwXMLTextBlocks.hxx>
+#include <SwXMLBlockImport.hxx>
+#include <SwXMLBlockExport.hxx>
+#include <xmloff/xmlnamespace.hxx>
+#include <sfx2/event.hxx>
+#include <swerror.h>
+
+constexpr OUString XMLN_BLOCKLIST = u"BlockList.xml"_ustr;
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::container;
+using namespace css::xml::sax;
+using namespace xmloff::token;
+
+using ::xmloff::token::XML_BLOCK_LIST;
+using ::xmloff::token::XML_UNFORMATTED_TEXT;
+using ::xmloff::token::GetXMLToken;
+
+ErrCode SwXMLTextBlocks::GetDoc( sal_uInt16 nIdx )
+{
+ OUString aFolderName ( GetPackageName ( nIdx ) );
+
+ if (!IsOnlyTextBlock ( nIdx ) )
+ {
+ try
+ {
+ m_xRoot = m_xBlkRoot->openStorageElement( aFolderName, embed::ElementModes::READ );
+ m_xMedium = new SfxMedium( m_xRoot, GetBaseURL(), "writer8" );
+ SwReader aReader( *m_xMedium, aFolderName, m_xDoc.get() );
+ ReadXML->SetBlockMode( true );
+ aReader.Read( *ReadXML );
+ ReadXML->SetBlockMode( false );
+ // Ole objects fail to display when inserted into the document, as
+ // the ObjectReplacement folder and contents are missing
+ OUString sObjReplacements( "ObjectReplacements" );
+ if ( m_xRoot->hasByName( sObjReplacements ) )
+ {
+ uno::Reference< document::XStorageBasedDocument > xDocStor( m_xDoc->GetDocShell()->GetModel(), uno::UNO_QUERY_THROW );
+ uno::Reference< embed::XStorage > xStr( xDocStor->getDocumentStorage() );
+ if ( xStr.is() )
+ {
+ m_xRoot->copyElementTo( sObjReplacements, xStr, sObjReplacements );
+ uno::Reference< embed::XTransactedObject > xTrans( xStr, uno::UNO_QUERY );
+ if ( xTrans.is() )
+ xTrans->commit();
+ }
+ }
+ }
+ catch( uno::Exception& )
+ {
+ }
+
+ m_xRoot = nullptr;
+ }
+ else
+ {
+ OUString aStreamName = aFolderName + ".xml";
+ try
+ {
+ m_xRoot = m_xBlkRoot->openStorageElement( aFolderName, embed::ElementModes::READ );
+ uno::Reference < io::XStream > xStream = m_xRoot->openStreamElement( aStreamName, embed::ElementModes::READ );
+
+ uno::Reference< uno::XComponentContext > xContext =
+ comphelper::getProcessComponentContext();
+
+ xml::sax::InputSource aParserInput;
+ aParserInput.sSystemId = m_aNames[nIdx]->m_aPackageName;
+
+ aParserInput.aInputStream = xStream->getInputStream();
+
+ // get filter
+ uno::Reference< xml::sax::XFastDocumentHandler > xFilter = new SwXMLTextBlockImport( xContext, m_aCurrentText, true );
+ uno::Reference< xml::sax::XFastTokenHandler > xTokenHandler = new SwXMLTextBlockTokenHandler();
+
+ // connect parser and filter
+ uno::Reference< xml::sax::XFastParser > xParser = xml::sax::FastParser::create(xContext);
+ xParser->setFastDocumentHandler( xFilter );
+ xParser->setTokenHandler( xTokenHandler );
+
+ xParser->registerNamespace( "http://openoffice.org/2000/text", FastToken::NAMESPACE | XML_NAMESPACE_TEXT );
+ xParser->registerNamespace( "http://openoffice.org/2000/office", FastToken::NAMESPACE | XML_NAMESPACE_OFFICE );
+
+ // parse
+ try
+ {
+ xParser->parseStream( aParserInput );
+ }
+ catch( xml::sax::SAXParseException& )
+ {
+ // re throw ?
+ }
+ catch( xml::sax::SAXException& )
+ {
+ // re throw ?
+ }
+ catch( io::IOException& )
+ {
+ // re throw ?
+ }
+
+ m_bInfoChanged = false;
+ MakeBlockText(m_aCurrentText);
+ }
+ catch( uno::Exception& )
+ {
+ }
+
+ m_xRoot = nullptr;
+ }
+ return ERRCODE_NONE;
+}
+
+// event description for autotext events; this constant should really be
+// taken from unocore/unoevents.cxx or ui/unotxt.cxx
+const struct SvEventDescription aAutotextEvents[] =
+{
+ { SvMacroItemId::SwStartInsGlossary, "OnInsertStart" },
+ { SvMacroItemId::SwEndInsGlossary, "OnInsertDone" },
+ { SvMacroItemId::NONE, nullptr }
+};
+
+ErrCode SwXMLTextBlocks::GetMacroTable( sal_uInt16 nIdx,
+ SvxMacroTableDtor& rMacroTable )
+{
+ // set current auto text
+ m_aShort = m_aNames[nIdx]->m_aShort;
+ m_aLong = m_aNames[nIdx]->m_aLong;
+ m_aPackageName = m_aNames[nIdx]->m_aPackageName;
+
+ // open stream in proper sub-storage
+ CloseFile();
+ if ( OpenFile() != ERRCODE_NONE )
+ return ERR_SWG_READ_ERROR;
+
+ try
+ {
+ m_xRoot = m_xBlkRoot->openStorageElement( m_aPackageName, embed::ElementModes::READ );
+ bool bOasis = SotStorage::GetVersion( m_xRoot ) > SOFFICE_FILEFORMAT_60;
+
+ uno::Reference < io::XStream > xDocStream = m_xRoot->openStreamElement(
+ "atevent.xml", embed::ElementModes::READ );
+ OSL_ENSURE(xDocStream.is(), "Can't create stream");
+ if ( !xDocStream.is() )
+ return ERR_SWG_READ_ERROR;
+
+ uno::Reference<io::XInputStream> xInputStream = xDocStream->getInputStream();
+
+ // prepare ParserInputSource
+ xml::sax::InputSource aParserInput;
+ aParserInput.sSystemId = m_aName;
+ aParserInput.aInputStream = xInputStream;
+
+ // get service factory
+ uno::Reference< uno::XComponentContext > xContext =
+ comphelper::getProcessComponentContext();
+
+ // create descriptor and reference to it. Either
+ // both or neither must be kept because of the
+ // reference counting!
+ rtl::Reference<SvMacroTableEventDescriptor> pDescriptor =
+ new SvMacroTableEventDescriptor(aAutotextEvents);
+ Sequence<Any> aFilterArguments{ Any(uno::Reference<XNameReplace>(pDescriptor)) };
+
+ // get filter
+ OUString sFilterComponent = bOasis
+ ? OUString("com.sun.star.comp.Writer.XMLOasisAutotextEventsImporter")
+ : OUString("com.sun.star.comp.Writer.XMLAutotextEventsImporter");
+ uno::Reference< XInterface > xFilterInt =
+ xContext->getServiceManager()->createInstanceWithArgumentsAndContext(
+ sFilterComponent, aFilterArguments, xContext);
+
+
+ // parse the stream
+ try
+ {
+ Reference<css::xml::sax::XFastParser> xFastParser(xFilterInt, UNO_QUERY);
+ Reference<css::xml::sax::XFastDocumentHandler> xFastDocHandler(xFilterInt, UNO_QUERY);
+ if (xFastParser)
+ {
+ xFastParser->parseStream(aParserInput);
+ }
+ else if (xFastDocHandler)
+ {
+ Reference<css::xml::sax::XFastParser> xParser
+ = css::xml::sax::FastParser::create(xContext);
+ xParser->setFastDocumentHandler(xFastDocHandler);
+ xParser->parseStream(aParserInput);
+ }
+ else
+ {
+ Reference<css::xml::sax::XDocumentHandler> xDocHandler(xFilterInt, UNO_QUERY);
+ OSL_ENSURE( xDocHandler.is(), "can't instantiate autotext-events filter");
+ if ( !xDocHandler.is() )
+ return ERR_SWG_READ_ERROR;
+ Reference<css::xml::sax::XParser> xParser = css::xml::sax::Parser::create(xContext);
+ xParser->setDocumentHandler(xDocHandler);
+ xParser->parseStream(aParserInput);
+ }
+ }
+ catch( xml::sax::SAXParseException& )
+ {
+ // workaround for #83452#: SetSize doesn't work
+ // nRet = ERR_SWG_READ_ERROR;
+ }
+ catch( xml::sax::SAXException& )
+ {
+ TOOLS_WARN_EXCEPTION("sw", "");
+ return ERR_SWG_READ_ERROR;
+ }
+ catch( io::IOException& )
+ {
+ TOOLS_WARN_EXCEPTION("sw", "");
+ return ERR_SWG_READ_ERROR;
+ }
+
+ // and finally, copy macro into table
+ pDescriptor->copyMacrosIntoTable(rMacroTable);
+ }
+ catch( uno::Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("sw", "");
+ return ERR_SWG_READ_ERROR;
+ }
+
+ // success!
+ return ERRCODE_NONE;
+}
+
+ErrCode SwXMLTextBlocks::GetBlockText( std::u16string_view rShort, OUString& rText )
+{
+ OUString aFolderName = GeneratePackageName ( rShort );
+ OUString aStreamName = aFolderName + ".xml";
+ rText.clear();
+
+ try
+ {
+ bool bTextOnly = true;
+
+ m_xRoot = m_xBlkRoot->openStorageElement( aFolderName, embed::ElementModes::READ );
+ if ( !m_xRoot->hasByName( aStreamName ) || !m_xRoot->isStreamElement( aStreamName ) )
+ {
+ bTextOnly = false;
+ aStreamName = "content.xml";
+ }
+
+ uno::Reference < io::XStream > xContents = m_xRoot->openStreamElement( aStreamName, embed::ElementModes::READ );
+ uno::Reference< uno::XComponentContext > xContext =
+ comphelper::getProcessComponentContext();
+
+ xml::sax::InputSource aParserInput;
+ aParserInput.sSystemId = m_aName;
+ aParserInput.aInputStream = xContents->getInputStream();
+
+ // get filter
+ uno::Reference< xml::sax::XFastDocumentHandler > xFilter = new SwXMLTextBlockImport( xContext, rText, bTextOnly );
+ uno::Reference< xml::sax::XFastTokenHandler > xTokenHandler = new SwXMLTextBlockTokenHandler();
+
+ // connect parser and filter
+ uno::Reference< xml::sax::XFastParser > xParser = xml::sax::FastParser::create(xContext);
+ xParser->setFastDocumentHandler( xFilter );
+ xParser->setTokenHandler( xTokenHandler );
+
+ xParser->registerNamespace( "urn:oasis:names:tc:opendocument:xmlns:office:1.0", FastToken::NAMESPACE | XML_NAMESPACE_OFFICE );
+ xParser->registerNamespace( "urn:oasis:names:tc:opendocument:xmlns:text:1.0", FastToken::NAMESPACE | XML_NAMESPACE_TEXT );
+
+ // parse
+ try
+ {
+ xParser->parseStream( aParserInput );
+ }
+ catch( xml::sax::SAXParseException& )
+ {
+ // re throw ?
+ }
+ catch( xml::sax::SAXException& )
+ {
+ // re throw ?
+ }
+ catch( io::IOException& )
+ {
+ // re throw ?
+ }
+
+ m_xRoot = nullptr;
+ }
+ catch ( uno::Exception& )
+ {
+ SAL_WARN("sw", "Tried to open non-existent folder or stream: " << aStreamName << " derived from autocorr of: " << OUString(rShort));
+ }
+
+ return ERRCODE_NONE;
+}
+
+ErrCode SwXMLTextBlocks::PutBlockText( const OUString& rShort,
+ std::u16string_view rText, const OUString& rPackageName )
+{
+ GetIndex ( rShort );
+ /*
+ if (xBlkRoot->IsContained ( rPackageName ) )
+ {
+ xBlkRoot->Remove ( rPackageName );
+ xBlkRoot->Commit ( );
+ }
+ */
+ OUString aStreamName = rPackageName + ".xml";
+
+ uno::Reference< uno::XComponentContext > xContext =
+ comphelper::getProcessComponentContext();
+
+ uno::Reference < xml::sax::XWriter > xWriter = xml::sax::Writer::create(xContext);
+ ErrCode nRes = ERRCODE_NONE;
+
+ try
+ {
+ m_xRoot = m_xBlkRoot->openStorageElement( rPackageName, embed::ElementModes::WRITE );
+ uno::Reference < io::XStream > xDocStream = m_xRoot->openStreamElement( aStreamName,
+ embed::ElementModes::WRITE | embed::ElementModes::TRUNCATE );
+
+ uno::Reference < beans::XPropertySet > xSet( xDocStream, uno::UNO_QUERY );
+ xSet->setPropertyValue("MediaType", Any(OUString( "text/xml" )) );
+ uno::Reference < io::XOutputStream > xOut = xDocStream->getOutputStream();
+ xWriter->setOutputStream(xOut);
+
+ rtl::Reference<SwXMLTextBlockExport> xExp( new SwXMLTextBlockExport( xContext, *this, GetXMLToken ( XML_UNFORMATTED_TEXT ), xWriter) );
+
+ xExp->exportDoc( rText );
+
+ uno::Reference < embed::XTransactedObject > xTrans( m_xRoot, uno::UNO_QUERY );
+ if ( xTrans.is() )
+ xTrans->commit();
+
+ if (! (m_nFlags & SwXmlFlags::NoRootCommit) )
+ {
+ uno::Reference < embed::XTransactedObject > xTmpTrans( m_xBlkRoot, uno::UNO_QUERY );
+ if ( xTmpTrans.is() )
+ xTmpTrans->commit();
+ }
+ }
+ catch ( uno::Exception& )
+ {
+ nRes = ERR_SWG_WRITE_ERROR;
+ }
+
+ m_xRoot = nullptr;
+
+ //TODO/LATER: error handling
+ /*
+ sal_uLong nErr = xBlkRoot->GetError();
+ sal_uLong nRes = 0;
+ if( nErr == SVSTREAM_DISK_FULL )
+ nRes = ERR_W4W_WRITE_FULL;
+ else if( nErr != ERRCODE_NONE )
+ nRes = ERR_SWG_WRITE_ERROR;
+ */
+ if( !nRes ) // So that we can access the Doc via GetText & nCur
+ MakeBlockText( rText );
+
+ return nRes;
+}
+
+void SwXMLTextBlocks::ReadInfo()
+{
+ const OUString sDocName( XMLN_BLOCKLIST );
+ try
+ {
+ if ( !m_xBlkRoot.is() || !m_xBlkRoot->hasByName( sDocName ) || !m_xBlkRoot->isStreamElement( sDocName ) )
+ return;
+
+ uno::Reference< uno::XComponentContext > xContext =
+ comphelper::getProcessComponentContext();
+
+ xml::sax::InputSource aParserInput;
+ aParserInput.sSystemId = sDocName;
+
+ uno::Reference < io::XStream > xDocStream = m_xBlkRoot->openStreamElement( sDocName, embed::ElementModes::READ );
+ aParserInput.aInputStream = xDocStream->getInputStream();
+
+ // get filter
+ uno::Reference< xml::sax::XFastDocumentHandler > xFilter = new SwXMLBlockListImport( xContext, *this );
+ uno::Reference< xml::sax::XFastTokenHandler > xTokenHandler = new SwXMLBlockListTokenHandler();
+
+ // connect parser and filter
+ uno::Reference< xml::sax::XFastParser > xParser = xml::sax::FastParser::create(xContext);
+ xParser->setFastDocumentHandler( xFilter );
+ xParser->registerNamespace( "http://openoffice.org/2001/block-list", FastToken::NAMESPACE | XML_NAMESPACE_BLOCKLIST );
+ xParser->setTokenHandler( xTokenHandler );
+
+ // parse
+ xParser->parseStream( aParserInput );
+ }
+ catch ( uno::Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("sw", "when loading " << sDocName);
+ // re throw ?
+ }
+}
+void SwXMLTextBlocks::WriteInfo()
+{
+ if ( !(m_xBlkRoot.is() || ERRCODE_NONE == OpenFile ( false )) )
+ return;
+
+ uno::Reference< uno::XComponentContext > xContext =
+ comphelper::getProcessComponentContext();
+
+ uno::Reference < xml::sax::XWriter > xWriter = xml::sax::Writer::create(xContext);
+
+ /*
+ if ( xBlkRoot->IsContained( sDocName) )
+ {
+ xBlkRoot->Remove ( sDocName );
+ xBlkRoot->Commit();
+ }
+ */
+
+ try
+ {
+ uno::Reference < io::XStream > xDocStream = m_xBlkRoot->openStreamElement( XMLN_BLOCKLIST,
+ embed::ElementModes::WRITE | embed::ElementModes::TRUNCATE );
+
+ uno::Reference < beans::XPropertySet > xSet( xDocStream, uno::UNO_QUERY );
+ xSet->setPropertyValue("MediaType", Any(OUString( "text/xml" )) );
+ uno::Reference < io::XOutputStream > xOut = xDocStream->getOutputStream();
+ xWriter->setOutputStream(xOut);
+
+ rtl::Reference<SwXMLBlockListExport> xExp(new SwXMLBlockListExport( xContext, *this, XMLN_BLOCKLIST, xWriter) );
+
+ xExp->exportDoc( XML_BLOCK_LIST );
+
+ uno::Reference < embed::XTransactedObject > xTrans( m_xBlkRoot, uno::UNO_QUERY );
+ if ( xTrans.is() )
+ xTrans->commit();
+ }
+ catch ( uno::Exception& )
+ {
+ }
+
+ m_bInfoChanged = false;
+ return;
+}
+
+ErrCode SwXMLTextBlocks::SetMacroTable(
+ sal_uInt16 nIdx,
+ const SvxMacroTableDtor& rMacroTable )
+{
+ // set current autotext
+ m_aShort = m_aNames[nIdx]->m_aShort;
+ m_aLong = m_aNames[nIdx]->m_aLong;
+ m_aPackageName = m_aNames[nIdx]->m_aPackageName;
+
+ // start XML autotext event export
+ ErrCode nRes = ERRCODE_NONE;
+
+ uno::Reference< uno::XComponentContext > xContext =
+ comphelper::getProcessComponentContext();
+
+ // Get model
+ uno::Reference< lang::XComponent > xModelComp =
+ m_xDoc->GetDocShell()->GetModel();
+ OSL_ENSURE( xModelComp.is(), "XMLWriter::Write: got no model" );
+ if( !xModelComp.is() )
+ return ERR_SWG_WRITE_ERROR;
+
+ // open stream in proper sub-storage
+ CloseFile(); // close (it may be open in read-only-mode)
+ nRes = OpenFile ( false );
+
+ if ( ERRCODE_NONE == nRes )
+ {
+ try
+ {
+ m_xRoot = m_xBlkRoot->openStorageElement( m_aPackageName, embed::ElementModes::WRITE );
+ bool bOasis = SotStorage::GetVersion( m_xRoot ) > SOFFICE_FILEFORMAT_60;
+
+ uno::Reference < io::XStream > xDocStream = m_xRoot->openStreamElement( "atevent.xml",
+ embed::ElementModes::WRITE | embed::ElementModes::TRUNCATE );
+
+ uno::Reference < beans::XPropertySet > xSet( xDocStream, uno::UNO_QUERY );
+ xSet->setPropertyValue("MediaType", Any(OUString( "text/xml" )) );
+ uno::Reference < io::XOutputStream > xOutputStream = xDocStream->getOutputStream();
+
+ // get XML writer
+ uno::Reference< xml::sax::XWriter > xSaxWriter =
+ xml::sax::Writer::create( xContext );
+
+ // connect XML writer to output stream
+ xSaxWriter->setOutputStream( xOutputStream );
+
+ // construct events object
+ uno::Reference<XNameAccess> xEvents =
+ new SvMacroTableEventDescriptor(rMacroTable,aAutotextEvents);
+
+ // prepare arguments (prepend doc handler to given arguments)
+ Sequence<Any> aParams{ Any(xSaxWriter), Any(xEvents) };
+
+ // get filter component
+ OUString sFilterComponent = bOasis
+ ? OUString("com.sun.star.comp.Writer.XMLOasisAutotextEventsExporter")
+ : OUString("com.sun.star.comp.Writer.XMLAutotextEventsExporter");
+ uno::Reference< document::XExporter > xExporter(
+ xContext->getServiceManager()->createInstanceWithArgumentsAndContext(
+ sFilterComponent, aParams, xContext), UNO_QUERY);
+ OSL_ENSURE( xExporter.is(),
+ "can't instantiate export filter component" );
+ if( xExporter.is() )
+ {
+ // connect model and filter
+ xExporter->setSourceDocument( xModelComp );
+
+ // filter!
+ Sequence<beans::PropertyValue> aFilterProps( 0 );
+ uno::Reference < document::XFilter > xFilter( xExporter,
+ UNO_QUERY );
+ xFilter->filter( aFilterProps );
+ }
+ else
+ nRes = ERR_SWG_WRITE_ERROR;
+
+ // finally, commit stream, sub-storage and storage
+ uno::Reference < embed::XTransactedObject > xTmpTrans( m_xRoot, uno::UNO_QUERY );
+ if ( xTmpTrans.is() )
+ xTmpTrans->commit();
+
+ uno::Reference < embed::XTransactedObject > xTrans( m_xBlkRoot, uno::UNO_QUERY );
+ if ( xTrans.is() )
+ xTrans->commit();
+
+ m_xRoot = nullptr;
+ }
+ catch ( uno::Exception& )
+ {
+ nRes = ERR_SWG_WRITE_ERROR;
+ }
+
+ CloseFile();
+ }
+ else
+ nRes = ERR_SWG_WRITE_ERROR;
+
+ return nRes;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/swg/TextBlockTokens.txt b/sw/source/core/swg/TextBlockTokens.txt
new file mode 100644
index 0000000000..8698704fcb
--- /dev/null
+++ b/sw/source/core/swg/TextBlockTokens.txt
@@ -0,0 +1,5 @@
+body
+text
+document
+document-content
+p
diff --git a/sw/source/core/swg/swblocks.cxx b/sw/source/core/swg/swblocks.cxx
new file mode 100644
index 0000000000..fb47693117
--- /dev/null
+++ b/sw/source/core/swg/swblocks.cxx
@@ -0,0 +1,582 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <algorithm>
+
+#include <osl/diagnose.h>
+#include <tools/urlobj.hxx>
+#include <svl/fstathelper.hxx>
+#include <svl/macitem.hxx>
+#include <unotools/charclass.hxx>
+#include <doc.hxx>
+#include <pam.hxx>
+#include <shellio.hxx>
+#include <swblocks.hxx>
+#include <SwXMLTextBlocks.hxx>
+#include <utility>
+
+#include <swerror.h>
+
+/**
+ * Calculate hash code (is not guaranteed to be unique)
+ */
+sal_uInt16 SwImpBlocks::Hash( std::u16string_view r )
+{
+ sal_uInt16 n = 0;
+ // std::min requires an explicit cast to sal_Int32 on 32bit platforms
+ const sal_Int32 nLen = std::min(sal_Int32(r.size()), static_cast<sal_Int32>(8));
+ for (sal_Int32 i=0; i<nLen; ++i)
+ {
+ n = ( n << 1 ) + r[i];
+ }
+ return n;
+}
+
+SwBlockName::SwBlockName( const OUString& rShort, const OUString& rLong )
+ : m_aShort( rShort ), m_aLong( rLong ), m_aPackageName (rShort),
+ m_bIsOnlyTextFlagInit( false ), m_bIsOnlyText( false )
+{
+ m_nHashS = SwImpBlocks::Hash( rShort );
+ m_nHashL = SwImpBlocks::Hash( rLong );
+}
+
+SwBlockName::SwBlockName( const OUString& rShort, const OUString& rLong, OUString aPackageName)
+ : m_aShort( rShort ), m_aLong( rLong ), m_aPackageName (std::move(aPackageName)),
+ m_bIsOnlyTextFlagInit( false ), m_bIsOnlyText( false )
+{
+ m_nHashS = SwImpBlocks::Hash( rShort );
+ m_nHashL = SwImpBlocks::Hash( rLong );
+}
+
+/**
+ * Is the provided file a storage or doesn't it exist?
+ */
+SwImpBlocks::FileType SwImpBlocks::GetFileType( const OUString& rFile )
+{
+ if( !FStatHelper::IsDocument( rFile ) )
+ return FileType::NoFile;
+ if( SwXMLTextBlocks::IsFileUCBStorage( rFile ) )
+ return FileType::XML;
+ //otherwise return NONE
+ return FileType::None;
+}
+
+SwImpBlocks::SwImpBlocks( const OUString& rFile )
+ : m_aFile( rFile ),
+ m_aDateModified( Date::EMPTY ),
+ m_aTimeModified( tools::Time::EMPTY ),
+ m_nCurrentIndex( USHRT_MAX ),
+ m_bReadOnly( true ), m_bInPutMuchBlocks( false ),
+ m_bInfoChanged(false)
+{
+ FStatHelper::GetModifiedDateTimeOfFile( rFile,
+ &m_aDateModified, &m_aTimeModified );
+ INetURLObject aObj(rFile);
+ aObj.setExtension( u"" );
+ m_aName = aObj.GetBase();
+}
+
+SwImpBlocks::~SwImpBlocks()
+{
+}
+
+/**
+ * Delete the document's content
+ */
+void SwImpBlocks::ClearDoc()
+{
+ m_xDoc->ClearDoc();
+}
+
+/**
+ * Creating a PaM, that spans the whole document
+ */
+std::unique_ptr<SwPaM> SwImpBlocks::MakePaM()
+{
+ std::unique_ptr<SwPaM> pPam(new SwPaM( m_xDoc->GetNodes().GetEndOfContent() ));
+ pPam->Move( fnMoveBackward, GoInDoc );
+ pPam->SetMark();
+ pPam->Move( fnMoveForward, GoInDoc );
+ pPam->Exchange();
+ return pPam;
+}
+
+sal_uInt16 SwImpBlocks::GetCount() const
+{
+ return m_aNames.size();
+}
+
+/**
+ * Case Insensitive
+ */
+sal_uInt16 SwImpBlocks::GetIndex( const OUString& rShort ) const
+{
+ const OUString s( GetAppCharClass().uppercase( rShort ) );
+ const sal_uInt16 nHash = Hash( s );
+ for( size_t i = 0; i < m_aNames.size(); i++ )
+ {
+ const SwBlockName* pName = m_aNames[ i ].get();
+ if( pName->m_nHashS == nHash
+ && pName->m_aShort == s )
+ return i;
+ }
+ return USHRT_MAX;
+}
+
+sal_uInt16 SwImpBlocks::GetLongIndex( std::u16string_view aLong ) const
+{
+ sal_uInt16 nHash = Hash( aLong );
+ for( size_t i = 0; i < m_aNames.size(); i++ )
+ {
+ const SwBlockName* pName = m_aNames[ i ].get();
+ if( pName->m_nHashL == nHash
+ && pName->m_aLong == aLong )
+ return i;
+ }
+ return USHRT_MAX;
+}
+
+OUString SwImpBlocks::GetShortName( sal_uInt16 n ) const
+{
+ if( n < m_aNames.size() )
+ return m_aNames[n]->m_aShort;
+ return OUString();
+}
+
+OUString SwImpBlocks::GetLongName( sal_uInt16 n ) const
+{
+ if( n < m_aNames.size() )
+ return m_aNames[n]->m_aLong;
+ return OUString();
+}
+
+OUString SwImpBlocks::GetPackageName( sal_uInt16 n ) const
+{
+ if( n < m_aNames.size() )
+ return m_aNames[n]->m_aPackageName;
+ return OUString();
+}
+
+void SwImpBlocks::AddName( const OUString& rShort, const OUString& rLong,
+ bool bOnlyText )
+{
+ sal_uInt16 nIdx = GetIndex( rShort );
+ if( nIdx != USHRT_MAX )
+ {
+ m_aNames.erase( m_aNames.begin() + nIdx );
+ }
+ std::unique_ptr<SwBlockName> pNew(new SwBlockName( rShort, rLong ));
+ pNew->m_bIsOnlyTextFlagInit = true;
+ pNew->m_bIsOnlyText = bOnlyText;
+ m_aNames.insert( std::move(pNew) );
+}
+
+bool SwImpBlocks::IsFileChanged() const
+{
+ Date aTempDateModified( m_aDateModified );
+ tools::Time aTempTimeModified( m_aTimeModified );
+ return FStatHelper::GetModifiedDateTimeOfFile( m_aFile, &aTempDateModified, &aTempTimeModified ) &&
+ ( m_aDateModified != aTempDateModified ||
+ m_aTimeModified != aTempTimeModified );
+}
+
+void SwImpBlocks::Touch()
+{
+ FStatHelper::GetModifiedDateTimeOfFile( m_aFile, &m_aDateModified, &m_aTimeModified );
+}
+
+bool SwImpBlocks::IsOnlyTextBlock( const OUString& ) const
+{
+ return false;
+}
+
+ErrCode SwImpBlocks::GetMacroTable( sal_uInt16, SvxMacroTableDtor& )
+{
+ return ERRCODE_NONE;
+}
+
+ErrCode SwImpBlocks::SetMacroTable( sal_uInt16 , const SvxMacroTableDtor& )
+{
+ return ERRCODE_NONE;
+}
+
+bool SwImpBlocks::PutMuchEntries( bool )
+{
+ return false;
+}
+
+SwTextBlocks::SwTextBlocks( const OUString& rFile )
+ : m_nErr( 0 )
+{
+ INetURLObject aObj(rFile);
+ const OUString sFileName = aObj.GetMainURL( INetURLObject::DecodeMechanism::NONE );
+ switch( SwImpBlocks::GetFileType( rFile ) )
+ {
+ case SwImpBlocks::FileType::XML: m_pImp.reset( new SwXMLTextBlocks( sFileName ) ); break;
+ case SwImpBlocks::FileType::NoFile: m_pImp.reset( new SwXMLTextBlocks( sFileName ) ); break;
+ default: break;
+ }
+ if( m_pImp )
+ return;
+
+ m_nErr = ERR_SWG_FILE_FORMAT_ERROR;
+}
+
+SwTextBlocks::~SwTextBlocks()
+{
+}
+
+OUString SwTextBlocks::GetName() const
+{
+ return m_pImp ? m_pImp->m_aName : OUString();
+}
+
+void SwTextBlocks::SetName( const OUString& r )
+{
+ if( m_pImp )
+ m_pImp->SetName( r );
+}
+
+sal_uInt16 SwTextBlocks::GetCount() const
+{
+ return m_pImp ? m_pImp->GetCount() : 0;
+}
+
+sal_uInt16 SwTextBlocks::GetIndex( const OUString& r ) const
+{
+ return m_pImp ? m_pImp->GetIndex( r ) : USHRT_MAX;
+}
+
+sal_uInt16 SwTextBlocks::GetLongIndex( std::u16string_view r ) const
+{
+ return m_pImp ? m_pImp->GetLongIndex( r ) : USHRT_MAX;
+}
+
+OUString SwTextBlocks::GetShortName( sal_uInt16 n ) const
+{
+ if( m_pImp )
+ return m_pImp->GetShortName( n );
+ return OUString();
+}
+
+OUString SwTextBlocks::GetLongName( sal_uInt16 n ) const
+{
+ if( m_pImp )
+ return m_pImp->GetLongName( n );
+ return OUString();
+}
+
+bool SwTextBlocks::Delete( sal_uInt16 n )
+{
+ if( m_pImp && !m_pImp->m_bInPutMuchBlocks )
+ {
+ if( m_pImp->IsFileChanged() )
+ m_nErr = ERR_TXTBLOCK_NEWFILE_ERROR;
+ else if( ERRCODE_NONE == (m_nErr = m_pImp->OpenFile( false ) ))
+ {
+ m_nErr = m_pImp->Delete( n );
+ if( !m_nErr )
+ {
+ m_pImp->m_aNames.erase( m_pImp->m_aNames.begin() + n );
+ }
+ if( n == m_pImp->m_nCurrentIndex )
+ m_pImp->m_nCurrentIndex = USHRT_MAX;
+ if( !m_nErr )
+ m_nErr = m_pImp->MakeBlockList();
+ }
+ m_pImp->CloseFile();
+ m_pImp->Touch();
+
+ return ( m_nErr == ERRCODE_NONE );
+ }
+ return false;
+}
+
+void SwTextBlocks::Rename( sal_uInt16 n, const OUString* s, const OUString* l )
+{
+ if( !m_pImp || m_pImp->m_bInPutMuchBlocks )
+ return;
+
+ m_pImp->m_nCurrentIndex = USHRT_MAX;
+ OUString aNew;
+ OUString aLong;
+ if( s )
+ aNew = aLong = *s;
+ if( l )
+ aLong = *l;
+ if( aNew.isEmpty() )
+ {
+ OSL_ENSURE( false, "No short name provided in the rename" );
+ m_nErr = ERR_SWG_INTERNAL_ERROR;
+ return;
+ }
+
+ if( m_pImp->IsFileChanged() )
+ m_nErr = ERR_TXTBLOCK_NEWFILE_ERROR;
+ else if( ERRCODE_NONE == ( m_nErr = m_pImp->OpenFile( false )))
+ {
+ // Set the new entry in the list before we do that!
+ aNew = GetAppCharClass().uppercase( aNew );
+ m_nErr = m_pImp->Rename( n, aNew );
+ if( !m_nErr )
+ {
+ bool bOnlyText = m_pImp->m_aNames[ n ]->m_bIsOnlyText;
+ m_pImp->m_aNames.erase( m_pImp->m_aNames.begin() + n );
+ m_pImp->AddName( aNew, aLong, bOnlyText );
+ m_nErr = m_pImp->MakeBlockList();
+ }
+ }
+ m_pImp->CloseFile();
+ m_pImp->Touch();
+}
+
+ErrCode const & SwTextBlocks::CopyBlock( SwTextBlocks const & rSource, OUString& rSrcShort,
+ const OUString& rLong )
+{
+ if (m_pImp->m_bInPutMuchBlocks)
+ m_nErr = ERR_SWG_INTERNAL_ERROR;
+ else
+ m_nErr = m_pImp->CopyBlock(*rSource.m_pImp, rSrcShort, rLong);
+ return m_nErr;
+}
+
+bool SwTextBlocks::BeginGetDoc( sal_uInt16 n )
+{
+ if( m_pImp && !m_pImp->m_bInPutMuchBlocks )
+ {
+ if( m_pImp->IsFileChanged() )
+ m_nErr = ERR_TXTBLOCK_NEWFILE_ERROR;
+ else if( ERRCODE_NONE == ( m_nErr = m_pImp->OpenFile()))
+ {
+ m_pImp->ClearDoc();
+ m_nErr = m_pImp->GetDoc( n );
+ if( m_nErr )
+ m_pImp->m_nCurrentIndex = USHRT_MAX;
+ else
+ m_pImp->m_nCurrentIndex = n;
+ }
+ return ( m_nErr == ERRCODE_NONE );
+ }
+ return false;
+}
+
+void SwTextBlocks::EndGetDoc()
+{
+ if( m_pImp && !m_pImp->m_bInPutMuchBlocks )
+ m_pImp->CloseFile();
+}
+
+bool SwTextBlocks::BeginPutDoc( const OUString& s, const OUString& l )
+{
+ if( m_pImp )
+ {
+ bool bOk = m_pImp->m_bInPutMuchBlocks;
+ if( !bOk )
+ {
+ if( m_pImp->IsFileChanged() )
+ m_nErr = ERR_TXTBLOCK_NEWFILE_ERROR;
+ else
+ m_nErr = m_pImp->OpenFile( false );
+ bOk = ERRCODE_NONE == m_nErr;
+ }
+ if( bOk )
+ {
+ const OUString aNew = GetAppCharClass().uppercase(s);
+ m_nErr = m_pImp->BeginPutDoc( aNew, l );
+ }
+ if( m_nErr )
+ m_pImp->CloseFile();
+ }
+ return ERRCODE_NONE == m_nErr;
+}
+
+sal_uInt16 SwTextBlocks::PutDoc()
+{
+ sal_uInt16 nIdx = USHRT_MAX;
+ if( m_pImp )
+ {
+ m_nErr = m_pImp->PutDoc();
+ if( !m_nErr )
+ {
+ m_pImp->m_nCurrentIndex = GetIndex( m_pImp->m_aShort );
+ if( m_pImp->m_nCurrentIndex != USHRT_MAX )
+ m_pImp->m_aNames[ m_pImp->m_nCurrentIndex ]->m_aLong = m_pImp->m_aLong;
+ else
+ {
+ m_pImp->AddName( m_pImp->m_aShort, m_pImp->m_aLong );
+ m_pImp->m_nCurrentIndex = m_pImp->GetIndex( m_pImp->m_aShort );
+ }
+ if( !m_pImp->m_bInPutMuchBlocks )
+ m_nErr = m_pImp->MakeBlockList();
+ }
+ if( !m_pImp->m_bInPutMuchBlocks )
+ {
+ m_pImp->CloseFile();
+ m_pImp->Touch();
+ }
+ nIdx = m_pImp->m_nCurrentIndex;
+ }
+ return nIdx;
+}
+
+sal_uInt16 SwTextBlocks::PutText( const OUString& rShort, const OUString& rName,
+ const OUString& rText )
+{
+ sal_uInt16 nIdx = USHRT_MAX;
+ if( m_pImp )
+ {
+ bool bOk = m_pImp->m_bInPutMuchBlocks;
+ if( !bOk )
+ {
+ if( m_pImp->IsFileChanged() )
+ m_nErr = ERR_TXTBLOCK_NEWFILE_ERROR;
+ else
+ m_nErr = m_pImp->OpenFile( false );
+ bOk = ERRCODE_NONE == m_nErr;
+ }
+ if( bOk )
+ {
+ OUString aNew = GetAppCharClass().uppercase( rShort );
+ m_nErr = m_pImp->PutText( aNew, rName, rText );
+ m_pImp->m_nCurrentIndex = USHRT_MAX;
+ if( !m_nErr )
+ {
+ nIdx = GetIndex( m_pImp->m_aShort );
+ if( nIdx != USHRT_MAX )
+ m_pImp->m_aNames[ nIdx ]->m_aLong = rName;
+ else
+ {
+ m_pImp->AddName( m_pImp->m_aShort, rName, true );
+ nIdx = m_pImp->GetIndex( m_pImp->m_aShort );
+ }
+ if( !m_pImp->m_bInPutMuchBlocks )
+ m_nErr = m_pImp->MakeBlockList();
+ }
+ }
+ if( !m_pImp->m_bInPutMuchBlocks )
+ {
+ m_pImp->CloseFile();
+ m_pImp->Touch();
+ }
+ }
+ return nIdx;
+}
+
+SwDoc* SwTextBlocks::GetDoc()
+{
+ if( m_pImp )
+ return m_pImp->m_xDoc.get();
+ return nullptr;
+}
+
+void SwTextBlocks::ClearDoc()
+{
+ if( m_pImp )
+ {
+ m_pImp->ClearDoc();
+ m_pImp->m_nCurrentIndex = USHRT_MAX;
+ }
+}
+
+OUString const & SwTextBlocks::GetFileName() const
+{
+ return m_pImp->GetFileName();
+}
+
+bool SwTextBlocks::IsReadOnly() const
+{
+ return m_pImp->m_bReadOnly;
+}
+
+bool SwTextBlocks::IsOnlyTextBlock( sal_uInt16 nIdx ) const
+{
+ bool bRet = false;
+ if( m_pImp && !m_pImp->m_bInPutMuchBlocks )
+ {
+ SwBlockName* pBlkNm = m_pImp->m_aNames[ nIdx ].get();
+ if( !pBlkNm->m_bIsOnlyTextFlagInit &&
+ !m_pImp->IsFileChanged() && !m_pImp->OpenFile() )
+ {
+ pBlkNm->m_bIsOnlyText = m_pImp->IsOnlyTextBlock( pBlkNm->m_aShort );
+ pBlkNm->m_bIsOnlyTextFlagInit = true;
+ m_pImp->CloseFile();
+ }
+ bRet = pBlkNm->m_bIsOnlyText;
+ }
+ return bRet;
+}
+
+bool SwTextBlocks::IsOnlyTextBlock( const OUString& rShort ) const
+{
+ sal_uInt16 nIdx = m_pImp->GetIndex( rShort );
+ if( USHRT_MAX != nIdx )
+ {
+ if( m_pImp->m_aNames[ nIdx ]->m_bIsOnlyTextFlagInit )
+ return m_pImp->m_aNames[ nIdx ]->m_bIsOnlyText;
+ return IsOnlyTextBlock( nIdx );
+ }
+
+ OSL_ENSURE( false, "Invalid name" );
+ return false;
+}
+
+bool SwTextBlocks::GetMacroTable( sal_uInt16 nIdx, SvxMacroTableDtor& rMacroTable )
+{
+ bool bRet = true;
+ if ( m_pImp && !m_pImp->m_bInPutMuchBlocks )
+ bRet = ( ERRCODE_NONE == m_pImp->GetMacroTable( nIdx, rMacroTable ) );
+ return bRet;
+}
+
+bool SwTextBlocks::SetMacroTable( sal_uInt16 nIdx, const SvxMacroTableDtor& rMacroTable )
+{
+ bool bRet = true;
+ if ( m_pImp && !m_pImp->m_bInPutMuchBlocks )
+ bRet = ( ERRCODE_NONE == m_pImp->SetMacroTable( nIdx, rMacroTable ) );
+ return bRet;
+}
+
+bool SwTextBlocks::StartPutMuchBlockEntries()
+{
+ bool bRet = false;
+ if( m_pImp )
+ bRet = m_pImp->PutMuchEntries( true );
+ return bRet;
+}
+
+void SwTextBlocks::EndPutMuchBlockEntries()
+{
+ if( m_pImp )
+ m_pImp->PutMuchEntries( false );
+}
+
+OUString SwTextBlocks::GetBaseURL() const
+{
+ if(m_pImp)
+ return m_pImp->GetBaseURL();
+ return OUString();
+}
+
+void SwTextBlocks::SetBaseURL( const OUString& rURL )
+{
+ if(m_pImp)
+ m_pImp->SetBaseURL(rURL);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */