diff options
Diffstat (limited to 'sw/source/core/swg')
-rw-r--r-- | sw/source/core/swg/BlockListTokens.txt | 7 | ||||
-rw-r--r-- | sw/source/core/swg/SwXMLBlockExport.cxx | 138 | ||||
-rw-r--r-- | sw/source/core/swg/SwXMLBlockImport.cxx | 337 | ||||
-rw-r--r-- | sw/source/core/swg/SwXMLSectionList.cxx | 131 | ||||
-rw-r--r-- | sw/source/core/swg/SwXMLTextBlocks.cxx | 572 | ||||
-rw-r--r-- | sw/source/core/swg/SwXMLTextBlocks1.cxx | 583 | ||||
-rw-r--r-- | sw/source/core/swg/TextBlockTokens.txt | 5 | ||||
-rw-r--r-- | sw/source/core/swg/swblocks.cxx | 582 |
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: */ |