From 940b4d1848e8c70ab7642901a68594e8016caffc Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sat, 27 Apr 2024 18:51:28 +0200 Subject: Adding upstream version 1:7.0.4. Signed-off-by: Daniel Baumann --- .../source/writer/exp/XMLBase64ImportContext.cxx | 65 +++ .../source/writer/exp/XMLBase64ImportContext.hxx | 48 ++ .../source/writer/exp/XMLFootnoteImportContext.cxx | 126 +++++ .../source/writer/exp/XMLFootnoteImportContext.hxx | 46 ++ .../source/writer/exp/XMLSectionContext.cxx | 44 ++ .../source/writer/exp/XMLSectionContext.hxx | 39 ++ .../source/writer/exp/XMLTextFrameContext.cxx | 171 ++++++ .../source/writer/exp/XMLTextFrameContext.hxx | 44 ++ .../source/writer/exp/XMLTextListContext.cxx | 33 ++ .../source/writer/exp/XMLTextListContext.hxx | 35 ++ .../source/writer/exp/XMLTextListItemContext.cxx | 36 ++ .../source/writer/exp/XMLTextListItemContext.hxx | 35 ++ writerperfect/source/writer/exp/txtparai.cxx | 630 +++++++++++++++++++++ writerperfect/source/writer/exp/txtparai.hxx | 65 +++ writerperfect/source/writer/exp/txtstyli.cxx | 415 ++++++++++++++ writerperfect/source/writer/exp/txtstyli.hxx | 66 +++ writerperfect/source/writer/exp/xmlfmt.cxx | 295 ++++++++++ writerperfect/source/writer/exp/xmlfmt.hxx | 79 +++ writerperfect/source/writer/exp/xmlictxt.cxx | 56 ++ writerperfect/source/writer/exp/xmlictxt.hxx | 57 ++ writerperfect/source/writer/exp/xmlimp.cxx | 617 ++++++++++++++++++++ writerperfect/source/writer/exp/xmlimp.hxx | 161 ++++++ writerperfect/source/writer/exp/xmlmetai.cxx | 285 ++++++++++ writerperfect/source/writer/exp/xmlmetai.hxx | 89 +++ writerperfect/source/writer/exp/xmltbli.cxx | 254 +++++++++ writerperfect/source/writer/exp/xmltbli.hxx | 50 ++ writerperfect/source/writer/exp/xmltext.cxx | 55 ++ writerperfect/source/writer/exp/xmltext.hxx | 40 ++ 28 files changed, 3936 insertions(+) create mode 100644 writerperfect/source/writer/exp/XMLBase64ImportContext.cxx create mode 100644 writerperfect/source/writer/exp/XMLBase64ImportContext.hxx create mode 100644 writerperfect/source/writer/exp/XMLFootnoteImportContext.cxx create mode 100644 writerperfect/source/writer/exp/XMLFootnoteImportContext.hxx create mode 100644 writerperfect/source/writer/exp/XMLSectionContext.cxx create mode 100644 writerperfect/source/writer/exp/XMLSectionContext.hxx create mode 100644 writerperfect/source/writer/exp/XMLTextFrameContext.cxx create mode 100644 writerperfect/source/writer/exp/XMLTextFrameContext.hxx create mode 100644 writerperfect/source/writer/exp/XMLTextListContext.cxx create mode 100644 writerperfect/source/writer/exp/XMLTextListContext.hxx create mode 100644 writerperfect/source/writer/exp/XMLTextListItemContext.cxx create mode 100644 writerperfect/source/writer/exp/XMLTextListItemContext.hxx create mode 100644 writerperfect/source/writer/exp/txtparai.cxx create mode 100644 writerperfect/source/writer/exp/txtparai.hxx create mode 100644 writerperfect/source/writer/exp/txtstyli.cxx create mode 100644 writerperfect/source/writer/exp/txtstyli.hxx create mode 100644 writerperfect/source/writer/exp/xmlfmt.cxx create mode 100644 writerperfect/source/writer/exp/xmlfmt.hxx create mode 100644 writerperfect/source/writer/exp/xmlictxt.cxx create mode 100644 writerperfect/source/writer/exp/xmlictxt.hxx create mode 100644 writerperfect/source/writer/exp/xmlimp.cxx create mode 100644 writerperfect/source/writer/exp/xmlimp.hxx create mode 100644 writerperfect/source/writer/exp/xmlmetai.cxx create mode 100644 writerperfect/source/writer/exp/xmlmetai.hxx create mode 100644 writerperfect/source/writer/exp/xmltbli.cxx create mode 100644 writerperfect/source/writer/exp/xmltbli.hxx create mode 100644 writerperfect/source/writer/exp/xmltext.cxx create mode 100644 writerperfect/source/writer/exp/xmltext.hxx (limited to 'writerperfect/source/writer/exp') diff --git a/writerperfect/source/writer/exp/XMLBase64ImportContext.cxx b/writerperfect/source/writer/exp/XMLBase64ImportContext.cxx new file mode 100644 index 000000000..f281e39a4 --- /dev/null +++ b/writerperfect/source/writer/exp/XMLBase64ImportContext.cxx @@ -0,0 +1,65 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "XMLBase64ImportContext.hxx" + +#include + +using namespace com::sun::star; + +namespace writerperfect::exp +{ +XMLBase64ImportContext::XMLBase64ImportContext(XMLImport& rImport) + : XMLImportContext(rImport) +{ +} + +void XMLBase64ImportContext::startElement( + const OUString& /*rName*/, + const css::uno::Reference& /*xAttribs*/) +{ +} + +void XMLBase64ImportContext::endElement(const OUString& /*rName*/) +{ + m_aBinaryData.append(static_cast(m_aStream.GetData()), + m_aStream.GetSize()); +} + +void XMLBase64ImportContext::characters(const OUString& rChars) +{ + OUString aTrimmedChars(rChars.trim()); + + if (!aTrimmedChars.isEmpty()) + { + OUString aChars; + if (!m_aBase64CharsLeft.isEmpty()) + { + aChars = m_aBase64CharsLeft + aTrimmedChars; + m_aBase64CharsLeft.clear(); + } + else + aChars = aTrimmedChars; + + uno::Sequence aBuffer((aChars.getLength() / 4) * 3); + const sal_Int32 nCharsDecoded = comphelper::Base64::decodeSomeChars(aBuffer, aChars); + m_aStream.WriteBytes(aBuffer.getArray(), aBuffer.getLength()); + if (nCharsDecoded != aChars.getLength()) + m_aBase64CharsLeft = aChars.copy(nCharsDecoded); + } +} + +const librevenge::RVNGBinaryData& XMLBase64ImportContext::getBinaryData() const +{ + return m_aBinaryData; +} + +} // namespace writerperfect::exp + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/writerperfect/source/writer/exp/XMLBase64ImportContext.hxx b/writerperfect/source/writer/exp/XMLBase64ImportContext.hxx new file mode 100644 index 000000000..1fc1325fd --- /dev/null +++ b/writerperfect/source/writer/exp/XMLBase64ImportContext.hxx @@ -0,0 +1,48 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef INCLUDED_WRITERPERFECT_SOURCE_WRITER_EXP_XMLBASE64IMPORTCONTEXT_HXX +#define INCLUDED_WRITERPERFECT_SOURCE_WRITER_EXP_XMLBASE64IMPORTCONTEXT_HXX + +#include + +#include + +#include "xmlictxt.hxx" + +namespace writerperfect +{ +namespace exp +{ +/// Handler for . +class XMLBase64ImportContext : public XMLImportContext +{ +public: + XMLBase64ImportContext(XMLImport& rImport); + + void SAL_CALL + startElement(const OUString& rName, + const css::uno::Reference& xAttribs) override; + void SAL_CALL endElement(const OUString& rName) override; + void SAL_CALL characters(const OUString& rChars) override; + + const librevenge::RVNGBinaryData& getBinaryData() const; + +private: + librevenge::RVNGBinaryData m_aBinaryData; + SvMemoryStream m_aStream; + OUString m_aBase64CharsLeft; +}; + +} // namespace exp +} // namespace writerperfect + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/writerperfect/source/writer/exp/XMLFootnoteImportContext.cxx b/writerperfect/source/writer/exp/XMLFootnoteImportContext.cxx new file mode 100644 index 000000000..cdc08c50b --- /dev/null +++ b/writerperfect/source/writer/exp/XMLFootnoteImportContext.cxx @@ -0,0 +1,126 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "XMLFootnoteImportContext.hxx" + +#include "xmlimp.hxx" +#include "xmltext.hxx" + +#include + +using namespace com::sun::star; + +namespace writerperfect::exp +{ +namespace +{ +/// Handler for . +class XMLTextNoteCitationContext : public XMLImportContext +{ +public: + XMLTextNoteCitationContext(XMLImport& rImport, librevenge::RVNGPropertyList& rProperties); + + void SAL_CALL characters(const OUString& rCharacters) override; + void SAL_CALL endElement(const OUString& rName) override; + +private: + librevenge::RVNGPropertyList& m_rProperties; + OUString m_aCharacters; +}; +} + +XMLTextNoteCitationContext::XMLTextNoteCitationContext(XMLImport& rImport, + librevenge::RVNGPropertyList& rProperties) + : XMLImportContext(rImport) + , m_rProperties(rProperties) +{ +} + +void XMLTextNoteCitationContext::endElement(const OUString& /*rName*/) +{ + m_rProperties.insert("librevenge:number", m_aCharacters.toUtf8().getStr()); +} + +void XMLTextNoteCitationContext::characters(const OUString& rCharacters) +{ + m_aCharacters += rCharacters; +} + +namespace +{ +/// Handler for . +class XMLFootnoteBodyImportContext : public XMLImportContext +{ +public: + XMLFootnoteBodyImportContext(XMLImport& rImport, + const librevenge::RVNGPropertyList& rProperties); + + rtl::Reference + CreateChildContext(const OUString& rName, + const css::uno::Reference& xAttribs) override; + + void SAL_CALL + startElement(const OUString& rName, + const css::uno::Reference& xAttribs) override; + void SAL_CALL endElement(const OUString& rName) override; + +private: + const librevenge::RVNGPropertyList& m_rProperties; +}; +} + +XMLFootnoteBodyImportContext::XMLFootnoteBodyImportContext( + XMLImport& rImport, const librevenge::RVNGPropertyList& rProperties) + : XMLImportContext(rImport) + , m_rProperties(rProperties) +{ +} + +rtl::Reference XMLFootnoteBodyImportContext::CreateChildContext( + const OUString& rName, const css::uno::Reference& /*xAttribs*/) +{ + return CreateTextChildContext(GetImport(), rName); +} + +void XMLFootnoteBodyImportContext::startElement( + const OUString& /*rName*/, + const css::uno::Reference& /*xAttribs*/) +{ + GetImport().GetGenerator().openFootnote(m_rProperties); +} + +void XMLFootnoteBodyImportContext::endElement(const OUString& /*rName*/) +{ + GetImport().GetGenerator().closeFootnote(); +} + +XMLFootnoteImportContext::XMLFootnoteImportContext(XMLImport& rImport) + : XMLImportContext(rImport) +{ +} + +rtl::Reference XMLFootnoteImportContext::CreateChildContext( + const OUString& rName, const css::uno::Reference& /*xAttribs*/) +{ + if (rName == "text:note-citation") + return new XMLTextNoteCitationContext(GetImport(), m_aProperties); + if (rName == "text:note-body") + return new XMLFootnoteBodyImportContext(GetImport(), m_aProperties); + SAL_WARN("writerperfect", "XMLFootnoteImportContext::CreateChildContext: unhandled " << rName); + return nullptr; +} + +void XMLFootnoteImportContext::startElement( + const OUString& /*rName*/, + const css::uno::Reference& /*xAttribs*/) +{ +} +} // namespace writerperfect::exp + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/writerperfect/source/writer/exp/XMLFootnoteImportContext.hxx b/writerperfect/source/writer/exp/XMLFootnoteImportContext.hxx new file mode 100644 index 000000000..22594f2dd --- /dev/null +++ b/writerperfect/source/writer/exp/XMLFootnoteImportContext.hxx @@ -0,0 +1,46 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef INCLUDED_WRITERPERFECT_SOURCE_WRITER_EXP_XMLFOOTNOTEIMPORTCONTEXT_HXX +#define INCLUDED_WRITERPERFECT_SOURCE_WRITER_EXP_XMLFOOTNOTEIMPORTCONTEXT_HXX + +#include + +#include + +#include "xmlictxt.hxx" + +namespace writerperfect +{ +namespace exp +{ +/// Handler for . +class XMLFootnoteImportContext : public XMLImportContext +{ +public: + XMLFootnoteImportContext(XMLImport& rImport); + + rtl::Reference + CreateChildContext(const OUString& rName, + const css::uno::Reference& xAttribs) override; + + void SAL_CALL + startElement(const OUString& rName, + const css::uno::Reference& xAttribs) override; + +private: + librevenge::RVNGPropertyList m_aProperties; +}; + +} // namespace exp +} // namespace writerperfect + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/writerperfect/source/writer/exp/XMLSectionContext.cxx b/writerperfect/source/writer/exp/XMLSectionContext.cxx new file mode 100644 index 000000000..839400e52 --- /dev/null +++ b/writerperfect/source/writer/exp/XMLSectionContext.cxx @@ -0,0 +1,44 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "XMLSectionContext.hxx" + +#include "xmlimp.hxx" +#include "xmltext.hxx" + +using namespace com::sun::star; + +namespace writerperfect::exp +{ +XMLSectionContext::XMLSectionContext(XMLImport& rImport) + : XMLImportContext(rImport) +{ +} + +rtl::Reference XMLSectionContext::CreateChildContext( + const OUString& rName, const css::uno::Reference& /*xAttribs*/) +{ + return CreateTextChildContext(GetImport(), rName); +} + +void XMLSectionContext::startElement( + const OUString& /*rName*/, + const css::uno::Reference& /*xAttribs*/) +{ + GetImport().GetGenerator().openSection(librevenge::RVNGPropertyList()); +} + +void XMLSectionContext::endElement(const OUString& /*rName*/) +{ + GetImport().GetGenerator().closeSection(); +} + +} // namespace writerperfect::exp + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/writerperfect/source/writer/exp/XMLSectionContext.hxx b/writerperfect/source/writer/exp/XMLSectionContext.hxx new file mode 100644 index 000000000..20c4047c0 --- /dev/null +++ b/writerperfect/source/writer/exp/XMLSectionContext.hxx @@ -0,0 +1,39 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef INCLUDED_WRITERPERFECT_SOURCE_WRITER_EXP_XMLSECTIONCONTEXT_HXX +#define INCLUDED_WRITERPERFECT_SOURCE_WRITER_EXP_XMLSECTIONCONTEXT_HXX + +#include "xmlictxt.hxx" + +namespace writerperfect +{ +namespace exp +{ +/// Handler for . +class XMLSectionContext : public XMLImportContext +{ +public: + XMLSectionContext(XMLImport& rImport); + + rtl::Reference + CreateChildContext(const OUString& rName, + const css::uno::Reference& xAttribs) override; + void SAL_CALL + startElement(const OUString& rName, + const css::uno::Reference& xAttribs) override; + void SAL_CALL endElement(const OUString& rName) override; +}; + +} // namespace exp +} // namespace writerperfect + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/writerperfect/source/writer/exp/XMLTextFrameContext.cxx b/writerperfect/source/writer/exp/XMLTextFrameContext.cxx new file mode 100644 index 000000000..60cc3d87f --- /dev/null +++ b/writerperfect/source/writer/exp/XMLTextFrameContext.cxx @@ -0,0 +1,171 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "XMLTextFrameContext.hxx" + +#include "XMLBase64ImportContext.hxx" +#include "txtparai.hxx" +#include "xmlimp.hxx" +#include "xmltext.hxx" + +#include + +using namespace com::sun::star; + +namespace writerperfect::exp +{ +namespace +{ +/// Handler for . +class XMLTextBoxContext : public XMLImportContext +{ +public: + XMLTextBoxContext(XMLImport& rImport); + + rtl::Reference + CreateChildContext(const OUString& rName, + const css::uno::Reference& xAttribs) override; + + void SAL_CALL + startElement(const OUString& rName, + const css::uno::Reference& xAttribs) override; + void SAL_CALL endElement(const OUString& rName) override; +}; +} + +XMLTextBoxContext::XMLTextBoxContext(XMLImport& rImport) + : XMLImportContext(rImport) +{ +} + +rtl::Reference XMLTextBoxContext::CreateChildContext( + const OUString& rName, const css::uno::Reference& /*xAttribs*/) +{ + return CreateTextChildContext(GetImport(), rName); +} + +void XMLTextBoxContext::startElement( + const OUString& /*rName*/, + const css::uno::Reference& /*xAttribs*/) +{ + GetImport().GetGenerator().openTextBox(librevenge::RVNGPropertyList()); +} + +void XMLTextBoxContext::endElement(const OUString& /*rName*/) +{ + GetImport().GetGenerator().closeTextBox(); +} + +namespace +{ +/// Handler for . +class XMLTextImageContext : public XMLImportContext +{ +public: + XMLTextImageContext(XMLImport& rImport); + + rtl::Reference + CreateChildContext(const OUString& rName, + const css::uno::Reference& xAttribs) override; + + void SAL_CALL + startElement(const OUString& rName, + const css::uno::Reference& xAttribs) override; + void SAL_CALL endElement(const OUString& rName) override; + +private: + OString m_aMimeType; + rtl::Reference m_xBinaryData; +}; +} + +XMLTextImageContext::XMLTextImageContext(XMLImport& rImport) + : XMLImportContext(rImport) +{ +} + +rtl::Reference XMLTextImageContext::CreateChildContext( + const OUString& rName, const css::uno::Reference& /*xAttribs*/) +{ + if (rName == "office:binary-data") + { + m_xBinaryData = new XMLBase64ImportContext(GetImport()); + return m_xBinaryData.get(); + } + return nullptr; +} + +void XMLTextImageContext::startElement( + const OUString& /*rName*/, const css::uno::Reference& xAttribs) +{ + for (sal_Int16 i = 0; i < xAttribs->getLength(); ++i) + { + const OUString& rAttributeName = xAttribs->getNameByIndex(i); + if (rAttributeName == "loext:mime-type" || rAttributeName == "draw:mime-type") + m_aMimeType = OUStringToOString(xAttribs->getValueByIndex(i), RTL_TEXTENCODING_UTF8); + } +} + +void XMLTextImageContext::endElement(const OUString& /*rName*/) +{ + librevenge::RVNGPropertyList aPropertyList; + + aPropertyList.insert("librevenge:mime-type", m_aMimeType.getStr()); + if (m_xBinaryData.is()) + aPropertyList.insert("office:binary-data", m_xBinaryData->getBinaryData()); + + GetImport().GetGenerator().insertBinaryObject(aPropertyList); +} + +XMLTextFrameContext::XMLTextFrameContext(XMLImport& rImport) + : XMLImportContext(rImport) +{ +} + +rtl::Reference XMLTextFrameContext::CreateChildContext( + const OUString& rName, const css::uno::Reference& /*xAttribs*/) +{ + if (rName == "draw:image") + return new XMLTextImageContext(GetImport()); + if (rName == "draw:text-box") + return new XMLTextBoxContext(GetImport()); + SAL_WARN("writerperfect", "XMLTextFrameContext::CreateChildContext: unhandled " << rName); + return nullptr; +} + +void XMLTextFrameContext::startElement( + const OUString& /*rName*/, const css::uno::Reference& xAttribs) +{ + librevenge::RVNGPropertyList aPropertyList; + for (sal_Int16 i = 0; i < xAttribs->getLength(); ++i) + { + const OUString& rAttributeName = xAttribs->getNameByIndex(i); + const OUString& rAttributeValue = xAttribs->getValueByIndex(i); + + if (rAttributeName == "draw:style-name") + FillStyles(rAttributeValue, GetImport().GetAutomaticGraphicStyles(), + GetImport().GetGraphicStyles(), aPropertyList); + else + { + OString sName = OUStringToOString(rAttributeName, RTL_TEXTENCODING_UTF8); + OString sValue = OUStringToOString(rAttributeValue, RTL_TEXTENCODING_UTF8); + aPropertyList.insert(sName.getStr(), sValue.getStr()); + } + } + GetImport().GetGenerator().openFrame(aPropertyList); +} + +void XMLTextFrameContext::endElement(const OUString& /*rName*/) +{ + GetImport().GetGenerator().closeFrame(); +} + +} // namespace writerperfect::exp + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/writerperfect/source/writer/exp/XMLTextFrameContext.hxx b/writerperfect/source/writer/exp/XMLTextFrameContext.hxx new file mode 100644 index 000000000..fa8c52123 --- /dev/null +++ b/writerperfect/source/writer/exp/XMLTextFrameContext.hxx @@ -0,0 +1,44 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef INCLUDED_WRITERPERFECT_SOURCE_WRITER_EXP_XMLTEXTFRAMECONTEXT_HXX +#define INCLUDED_WRITERPERFECT_SOURCE_WRITER_EXP_XMLTEXTFRAMECONTEXT_HXX + +#include + +#include "xmlictxt.hxx" + +namespace writerperfect +{ +namespace exp +{ +class XMLBase64ImportContext; + +/// Handler for . +class XMLTextFrameContext : public XMLImportContext +{ +public: + XMLTextFrameContext(XMLImport& rImport); + + rtl::Reference + CreateChildContext(const OUString& rName, + const css::uno::Reference& xAttribs) override; + + void SAL_CALL + startElement(const OUString& rName, + const css::uno::Reference& xAttribs) override; + void SAL_CALL endElement(const OUString& rName) override; +}; + +} // namespace exp +} // namespace writerperfect + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/writerperfect/source/writer/exp/XMLTextListContext.cxx b/writerperfect/source/writer/exp/XMLTextListContext.cxx new file mode 100644 index 000000000..8798c9a39 --- /dev/null +++ b/writerperfect/source/writer/exp/XMLTextListContext.cxx @@ -0,0 +1,33 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "XMLTextListContext.hxx" + +#include "XMLTextListItemContext.hxx" + +using namespace com::sun::star; + +namespace writerperfect::exp +{ +XMLTextListContext::XMLTextListContext(XMLImport& rImport) + : XMLImportContext(rImport) +{ +} + +rtl::Reference XMLTextListContext::CreateChildContext( + const OUString& rName, const css::uno::Reference& /*xAttribs*/) +{ + if (rName == "text:list-item") + return new XMLTextListItemContext(GetImport()); + return nullptr; +} + +} // namespace writerperfect::exp + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/writerperfect/source/writer/exp/XMLTextListContext.hxx b/writerperfect/source/writer/exp/XMLTextListContext.hxx new file mode 100644 index 000000000..d5145465d --- /dev/null +++ b/writerperfect/source/writer/exp/XMLTextListContext.hxx @@ -0,0 +1,35 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef INCLUDED_WRITERPERFECT_SOURCE_WRITER_EXP_XMLTEXTLISTCONTEXT_HXX +#define INCLUDED_WRITERPERFECT_SOURCE_WRITER_EXP_XMLTEXTLISTCONTEXT_HXX + +#include "xmlictxt.hxx" + +namespace writerperfect +{ +namespace exp +{ +/// Handler for . +class XMLTextListContext : public XMLImportContext +{ +public: + XMLTextListContext(XMLImport& rImport); + + rtl::Reference + CreateChildContext(const OUString& rName, + const css::uno::Reference& xAttribs) override; +}; + +} // namespace exp +} // namespace writerperfect + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/writerperfect/source/writer/exp/XMLTextListItemContext.cxx b/writerperfect/source/writer/exp/XMLTextListItemContext.cxx new file mode 100644 index 000000000..36f3f2ce6 --- /dev/null +++ b/writerperfect/source/writer/exp/XMLTextListItemContext.cxx @@ -0,0 +1,36 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "XMLTextListItemContext.hxx" + +#include "XMLTextListContext.hxx" +#include "txtparai.hxx" + +using namespace com::sun::star; + +namespace writerperfect::exp +{ +XMLTextListItemContext::XMLTextListItemContext(XMLImport& rImport) + : XMLImportContext(rImport) +{ +} + +rtl::Reference XMLTextListItemContext::CreateChildContext( + const OUString& rName, const css::uno::Reference& /*xAttribs*/) +{ + if (rName == "text:p" || rName == "text:h") + return new XMLParaContext(GetImport()); + if (rName == "text:list") + return new XMLTextListContext(GetImport()); + return nullptr; +} + +} // namespace writerperfect::exp + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/writerperfect/source/writer/exp/XMLTextListItemContext.hxx b/writerperfect/source/writer/exp/XMLTextListItemContext.hxx new file mode 100644 index 000000000..c66fac6a2 --- /dev/null +++ b/writerperfect/source/writer/exp/XMLTextListItemContext.hxx @@ -0,0 +1,35 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef INCLUDED_WRITERPERFECT_SOURCE_WRITER_EXP_XMLTEXTLISTITEMCONTEXT_HXX +#define INCLUDED_WRITERPERFECT_SOURCE_WRITER_EXP_XMLTEXTLISTITEMCONTEXT_HXX + +#include "xmlictxt.hxx" + +namespace writerperfect +{ +namespace exp +{ +/// Handler for . +class XMLTextListItemContext : public XMLImportContext +{ +public: + XMLTextListItemContext(XMLImport& rImport); + + rtl::Reference + CreateChildContext(const OUString& rName, + const css::uno::Reference& xAttribs) override; +}; + +} // namespace exp +} // namespace writerperfect + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/writerperfect/source/writer/exp/txtparai.cxx b/writerperfect/source/writer/exp/txtparai.cxx new file mode 100644 index 000000000..11dfd8cfe --- /dev/null +++ b/writerperfect/source/writer/exp/txtparai.cxx @@ -0,0 +1,630 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "txtparai.hxx" + +#include "XMLFootnoteImportContext.hxx" +#include "XMLTextFrameContext.hxx" +#include "xmlimp.hxx" + +#include + +using namespace com::sun::star; + +namespace +{ +/// Looks for rName in rStyles and fills rPropertyList based on that +/// (rAutomaticStyles and rNamedStyles are a list of possible parents). +void FillStyle(const OUString& rName, std::map& rStyles, + std::map& rAutomaticStyles, + std::map& rNamedStyles, + librevenge::RVNGPropertyList& rPropertyList) +{ + auto itStyle = rStyles.find(rName); + if (itStyle == rStyles.end()) + return; + + const librevenge::RVNGPropertyList& rStyle = itStyle->second; + if (rStyle["style:parent-style-name"]) + { + // The style has a parent. + OUString aParent = OStringToOUString(rStyle["style:parent-style-name"]->getStr().cstr(), + RTL_TEXTENCODING_UTF8); + if (!aParent.isEmpty()) + writerperfect::exp::FillStyles(aParent, rAutomaticStyles, rNamedStyles, rPropertyList); + } + + // Apply properties from named style. + librevenge::RVNGPropertyList::Iter itProp(rStyle); + for (itProp.rewind(); itProp.next();) + { + if (OString("style:parent-style-name") != itProp.key()) + rPropertyList.insert(itProp.key(), itProp()->clone()); + } +} +} + +namespace writerperfect::exp +{ +namespace +{ +/// Handler for . +class XMLTextSequenceContext : public XMLImportContext +{ +public: + XMLTextSequenceContext(XMLImport& rImport, const librevenge::RVNGPropertyList& rPropertyList); + + void SAL_CALL characters(const OUString& rChars) override; + +private: + librevenge::RVNGPropertyList m_aPropertyList; +}; +} + +XMLTextSequenceContext::XMLTextSequenceContext(XMLImport& rImport, + const librevenge::RVNGPropertyList& rPropertyList) + : XMLImportContext(rImport) +{ + // Inherit properties from parent. + librevenge::RVNGPropertyList::Iter itProp(rPropertyList); + for (itProp.rewind(); itProp.next();) + m_aPropertyList.insert(itProp.key(), itProp()->clone()); +} + +void XMLTextSequenceContext::characters(const OUString& rChars) +{ + GetImport().GetGenerator().openSpan(m_aPropertyList); + + OString sCharU8 = OUStringToOString(rChars, RTL_TEXTENCODING_UTF8); + GetImport().GetGenerator().insertText(librevenge::RVNGString(sCharU8.getStr())); + + GetImport().GetGenerator().closeSpan(); +} + +namespace +{ +/// Handler for . +class XMLSpanContext : public XMLImportContext +{ +public: + XMLSpanContext(XMLImport& rImport, const librevenge::RVNGPropertyList& rPropertyList); + + rtl::Reference + CreateChildContext(const OUString& rName, + const css::uno::Reference& xAttribs) override; + + void SAL_CALL + startElement(const OUString& rName, + const css::uno::Reference& xAttribs) override; + void SAL_CALL characters(const OUString& rChars) override; + +private: + librevenge::RVNGPropertyList m_aPropertyList; +}; +} + +XMLSpanContext::XMLSpanContext(XMLImport& rImport, + const librevenge::RVNGPropertyList& rPropertyList) + : XMLImportContext(rImport) +{ + // Inherit properties from parent. + librevenge::RVNGPropertyList::Iter itProp(rPropertyList); + for (itProp.rewind(); itProp.next();) + m_aPropertyList.insert(itProp.key(), itProp()->clone()); +} + +rtl::Reference XMLSpanContext::CreateChildContext( + const OUString& rName, const css::uno::Reference& /*xAttribs*/) +{ + return CreateParagraphOrSpanChildContext(GetImport(), rName, m_aPropertyList); +} + +void XMLSpanContext::startElement( + const OUString& /*rName*/, const css::uno::Reference& xAttribs) +{ + for (sal_Int16 i = 0; i < xAttribs->getLength(); ++i) + { + const OUString& rAttributeName = xAttribs->getNameByIndex(i); + const OUString& rAttributeValue = xAttribs->getValueByIndex(i); + if (rAttributeName == "text:style-name") + FillStyles(rAttributeValue, GetImport().GetAutomaticTextStyles(), + GetImport().GetTextStyles(), m_aPropertyList); + else + { + OString sName = OUStringToOString(rAttributeName, RTL_TEXTENCODING_UTF8); + OString sValue = OUStringToOString(rAttributeValue, RTL_TEXTENCODING_UTF8); + m_aPropertyList.insert(sName.getStr(), sValue.getStr()); + } + } +} + +void XMLSpanContext::characters(const OUString& rChars) +{ + GetImport().GetGenerator().openSpan(m_aPropertyList); + + OString sCharU8 = OUStringToOString(rChars, RTL_TEXTENCODING_UTF8); + GetImport().GetGenerator().insertText(librevenge::RVNGString(sCharU8.getStr())); + + GetImport().GetGenerator().closeSpan(); +} + +namespace +{ +/// Handler for . +class XMLRubyContext : public XMLImportContext +{ +public: + XMLRubyContext(XMLImport& rImport, const librevenge::RVNGPropertyList& rPropertyList); + + rtl::Reference + CreateChildContext(const OUString& rName, + const css::uno::Reference& xAttribs) override; + + void SAL_CALL endElement(const OUString& rName) override; + + void SetRubyText(const OUString& rRubyText) { m_sRubyText = rRubyText; } + + OUString& GetRubyBase() { return m_sRubyBase; } + +private: + OUString m_sRubyText; + OUString m_sRubyBase; + librevenge::RVNGPropertyList m_aPropertyList; +}; + +/// Handler for . +class XMLRubyTextContext : public XMLImportContext +{ +public: + XMLRubyTextContext(XMLImport& rImport, XMLRubyContext& rParent) + : XMLImportContext(rImport) + , m_rParent(rParent) + { + } + + void SAL_CALL characters(const OUString& rChars) override { m_rParent.SetRubyText(rChars); } + +private: + XMLRubyContext& m_rParent; +}; + +/// Handler for . +class XMLRubyBaseContext : public XMLImportContext +{ +public: + XMLRubyBaseContext(XMLImport& rImport, XMLRubyContext& rParent) + : XMLImportContext(rImport) + , m_rParent(rParent) + { + } + + void SAL_CALL characters(const OUString& rChars) override { m_rParent.GetRubyBase() += rChars; } + +private: + XMLRubyContext& m_rParent; +}; +} + +XMLRubyContext::XMLRubyContext(XMLImport& rImport, + const librevenge::RVNGPropertyList& rPropertyList) + : XMLImportContext(rImport) +{ + // Inherit properties from parent. + librevenge::RVNGPropertyList::Iter itProp(rPropertyList); + for (itProp.rewind(); itProp.next();) + m_aPropertyList.insert(itProp.key(), itProp()->clone()); +} + +rtl::Reference XMLRubyContext::CreateChildContext( + const OUString& rName, const css::uno::Reference& /*xAttribs*/) +{ + if (rName == "text:ruby-base") + return new XMLRubyBaseContext(GetImport(), *this); + if (rName == "text:ruby-text") + return new XMLRubyTextContext(GetImport(), *this); + return nullptr; +} + +void XMLRubyContext::endElement(const OUString& /*rName*/) +{ + OString sRubyText = OUStringToOString(m_sRubyText, RTL_TEXTENCODING_UTF8); + OString sRubyBase = OUStringToOString(m_sRubyBase, RTL_TEXTENCODING_UTF8); + if (sRubyText.getLength()) + m_aPropertyList.insert("text:ruby-text", sRubyText.getStr()); + GetImport().GetGenerator().openSpan(m_aPropertyList); + GetImport().GetGenerator().insertText(sRubyBase.getStr()); + GetImport().GetGenerator().closeSpan(); +} + +namespace +{ +/// Base class for contexts that represent a single character only. +class XMLCharContext : public XMLImportContext +{ +public: + XMLCharContext(XMLImport& rImport, const librevenge::RVNGPropertyList& rPropertyList); + + const librevenge::RVNGPropertyList& GetPropertyList() const { return m_aPropertyList; } + +private: + librevenge::RVNGPropertyList m_aPropertyList; +}; +} + +XMLCharContext::XMLCharContext(XMLImport& rImport, + const librevenge::RVNGPropertyList& rPropertyList) + : XMLImportContext(rImport) +{ + // Inherit properties from parent. + librevenge::RVNGPropertyList::Iter itProp(rPropertyList); + for (itProp.rewind(); itProp.next();) + m_aPropertyList.insert(itProp.key(), itProp()->clone()); +} + +namespace +{ +/// Handler for . +class XMLLineBreakContext : public XMLCharContext +{ +public: + XMLLineBreakContext(XMLImport& rImport, const librevenge::RVNGPropertyList& rPropertyList); + + void SAL_CALL + startElement(const OUString& rName, + const css::uno::Reference& xAttribs) override; +}; +} + +XMLLineBreakContext::XMLLineBreakContext(XMLImport& rImport, + const librevenge::RVNGPropertyList& rPropertyList) + : XMLCharContext(rImport, rPropertyList) +{ +} + +void XMLLineBreakContext::startElement( + const OUString& /*rName*/, + const css::uno::Reference& /*xAttribs*/) +{ + GetImport().GetGenerator().openSpan(GetPropertyList()); + GetImport().GetGenerator().insertLineBreak(); + GetImport().GetGenerator().closeSpan(); +} + +namespace +{ +/// Handler for . +class XMLSpaceContext : public XMLCharContext +{ +public: + XMLSpaceContext(XMLImport& rImport, const librevenge::RVNGPropertyList& rPropertyList); + + void SAL_CALL + startElement(const OUString& rName, + const css::uno::Reference& xAttribs) override; +}; +} + +XMLSpaceContext::XMLSpaceContext(XMLImport& rImport, + const librevenge::RVNGPropertyList& rPropertyList) + : XMLCharContext(rImport, rPropertyList) +{ +} + +void XMLSpaceContext::startElement( + const OUString& /*rName*/, + const css::uno::Reference& /*xAttribs*/) +{ + GetImport().GetGenerator().openSpan(GetPropertyList()); + GetImport().GetGenerator().insertSpace(); + GetImport().GetGenerator().closeSpan(); +} + +namespace +{ +/// Handler for . +class XMLTabContext : public XMLCharContext +{ +public: + XMLTabContext(XMLImport& rImport, const librevenge::RVNGPropertyList& rPropertyList); + + void SAL_CALL + startElement(const OUString& rName, + const css::uno::Reference& xAttribs) override; +}; +} + +XMLTabContext::XMLTabContext(XMLImport& rImport, const librevenge::RVNGPropertyList& rPropertyList) + : XMLCharContext(rImport, rPropertyList) +{ +} + +void XMLTabContext::startElement( + const OUString& /*rName*/, + const css::uno::Reference& /*xAttribs*/) +{ + GetImport().GetGenerator().openSpan(GetPropertyList()); + GetImport().GetGenerator().insertTab(); + GetImport().GetGenerator().closeSpan(); +} + +namespace +{ +/// Handler for . +class XMLTextFrameHyperlinkContext : public XMLImportContext +{ +public: + XMLTextFrameHyperlinkContext(XMLImport& rImport, + const librevenge::RVNGPropertyList& rPropertyList); + rtl::Reference + CreateChildContext(const OUString& rName, + const css::uno::Reference& xAttribs) override; + + void SAL_CALL + startElement(const OUString& rName, + const css::uno::Reference& xAttribs) override; + void SAL_CALL endElement(const OUString& rName) override; + void SAL_CALL characters(const OUString& rChars) override; + +private: + librevenge::RVNGPropertyList m_aPropertyList; + PopupState m_ePopupState = PopupState::NONE; +}; +} + +XMLTextFrameHyperlinkContext::XMLTextFrameHyperlinkContext( + XMLImport& rImport, const librevenge::RVNGPropertyList& rPropertyList) + : XMLImportContext(rImport) +{ + // Inherit properties from parent. + librevenge::RVNGPropertyList::Iter itProp(rPropertyList); + for (itProp.rewind(); itProp.next();) + m_aPropertyList.insert(itProp.key(), itProp()->clone()); +} + +rtl::Reference XMLTextFrameHyperlinkContext::CreateChildContext( + const OUString& rName, const css::uno::Reference& /*xAttribs*/) +{ + return CreateParagraphOrSpanChildContext(GetImport(), rName, m_aPropertyList); +} + +void XMLTextFrameHyperlinkContext::startElement( + const OUString& /*rName*/, const css::uno::Reference& xAttribs) +{ + librevenge::RVNGPropertyList aPropertyList; + for (sal_Int16 i = 0; i < xAttribs->getLength(); ++i) + { + const OUString& rAttributeName = xAttribs->getNameByIndex(i); + const OUString& rAttributeValue = xAttribs->getValueByIndex(i); + if (rAttributeName == "text:style-name") + // This affects the nested span's properties. + FillStyles(rAttributeValue, GetImport().GetAutomaticTextStyles(), + GetImport().GetTextStyles(), m_aPropertyList); + else + { + if (rAttributeName == "xlink:href") + { + m_ePopupState = GetImport().FillPopupData(rAttributeValue, aPropertyList); + if (m_ePopupState != PopupState::NotConsumed) + continue; + } + + // This affects the link's properties. + OString sName = OUStringToOString(rAttributeName, RTL_TEXTENCODING_UTF8); + OString sValue = OUStringToOString(rAttributeValue, RTL_TEXTENCODING_UTF8); + aPropertyList.insert(sName.getStr(), sValue.getStr()); + } + } + + if (m_ePopupState != PopupState::Ignore) + GetImport().GetGenerator().openLink(aPropertyList); +} + +void XMLTextFrameHyperlinkContext::endElement(const OUString& /*rName*/) +{ + if (m_ePopupState != PopupState::Ignore) + GetImport().GetGenerator().closeLink(); +} + +void XMLTextFrameHyperlinkContext::characters(const OUString& rChars) +{ + GetImport().GetGenerator().openSpan(m_aPropertyList); + + OString sCharU8 = OUStringToOString(rChars, RTL_TEXTENCODING_UTF8); + GetImport().GetGenerator().insertText(librevenge::RVNGString(sCharU8.getStr())); + + GetImport().GetGenerator().closeSpan(); +} + +namespace +{ +/// Handler for . +class XMLHyperlinkContext : public XMLImportContext +{ +public: + XMLHyperlinkContext(XMLImport& rImport, const librevenge::RVNGPropertyList& rPropertyList); + rtl::Reference + CreateChildContext(const OUString& rName, + const css::uno::Reference& xAttribs) override; + + void SAL_CALL + startElement(const OUString& rName, + const css::uno::Reference& xAttribs) override; + void SAL_CALL endElement(const OUString& rName) override; + void SAL_CALL characters(const OUString& rChars) override; + +private: + librevenge::RVNGPropertyList m_aPropertyList; + PopupState m_ePopupState = PopupState::NONE; +}; +} + +XMLHyperlinkContext::XMLHyperlinkContext(XMLImport& rImport, + const librevenge::RVNGPropertyList& rPropertyList) + : XMLImportContext(rImport) +{ + // Inherit properties from parent. + librevenge::RVNGPropertyList::Iter itProp(rPropertyList); + for (itProp.rewind(); itProp.next();) + m_aPropertyList.insert(itProp.key(), itProp()->clone()); +} + +rtl::Reference XMLHyperlinkContext::CreateChildContext( + const OUString& rName, const css::uno::Reference& /*xAttribs*/) +{ + return CreateParagraphOrSpanChildContext(GetImport(), rName, m_aPropertyList); +} + +void XMLHyperlinkContext::startElement( + const OUString& /*rName*/, const css::uno::Reference& xAttribs) +{ + librevenge::RVNGPropertyList aPropertyList; + for (sal_Int16 i = 0; i < xAttribs->getLength(); ++i) + { + const OUString& rAttributeName = xAttribs->getNameByIndex(i); + const OUString& rAttributeValue = xAttribs->getValueByIndex(i); + if (rAttributeName == "text:style-name") + // This affects the nested span's properties. + FillStyles(rAttributeValue, GetImport().GetAutomaticTextStyles(), + GetImport().GetTextStyles(), m_aPropertyList); + else + { + if (rAttributeName == "xlink:href") + { + m_ePopupState = GetImport().FillPopupData(rAttributeValue, aPropertyList); + if (m_ePopupState != PopupState::NotConsumed) + continue; + } + + // This affects the link's properties. + OString sName = OUStringToOString(rAttributeName, RTL_TEXTENCODING_UTF8); + OString sValue = OUStringToOString(rAttributeValue, RTL_TEXTENCODING_UTF8); + aPropertyList.insert(sName.getStr(), sValue.getStr()); + } + } + + if (m_ePopupState != PopupState::Ignore) + GetImport().GetGenerator().openLink(aPropertyList); +} + +void XMLHyperlinkContext::endElement(const OUString& /*rName*/) +{ + if (m_ePopupState != PopupState::Ignore) + GetImport().GetGenerator().closeLink(); +} + +void XMLHyperlinkContext::characters(const OUString& rChars) +{ + GetImport().GetGenerator().openSpan(m_aPropertyList); + + OString sCharU8 = OUStringToOString(rChars, RTL_TEXTENCODING_UTF8); + GetImport().GetGenerator().insertText(librevenge::RVNGString(sCharU8.getStr())); + + GetImport().GetGenerator().closeSpan(); +} + +XMLParaContext::XMLParaContext(XMLImport& rImport, bool bTopLevel) + : XMLImportContext(rImport) + , m_bTopLevel(bTopLevel) +{ +} + +rtl::Reference XMLParaContext::CreateChildContext( + const OUString& rName, const css::uno::Reference& /*xAttribs*/) +{ + if (rName == "text:a") + return new XMLHyperlinkContext(GetImport(), m_aTextPropertyList); + if (rName == "draw:a") + return new XMLTextFrameHyperlinkContext(GetImport(), m_aTextPropertyList); + if (rName == "text:ruby") + return new XMLRubyContext(GetImport(), m_aTextPropertyList); + return CreateParagraphOrSpanChildContext(GetImport(), rName, m_aTextPropertyList); +} + +void XMLParaContext::startElement( + const OUString& /*rName*/, const css::uno::Reference& xAttribs) +{ + librevenge::RVNGPropertyList aPropertyList; + for (sal_Int16 i = 0; i < xAttribs->getLength(); ++i) + { + const OUString& rAttributeName = xAttribs->getNameByIndex(i); + const OUString& rAttributeValue = xAttribs->getValueByIndex(i); + if (rAttributeName == "text:style-name") + { + m_aStyleName = rAttributeValue; + FillStyles(m_aStyleName, GetImport().GetAutomaticParagraphStyles(), + GetImport().GetParagraphStyles(), aPropertyList); + FillStyles(m_aStyleName, GetImport().GetAutomaticTextStyles(), + GetImport().GetTextStyles(), m_aTextPropertyList); + if (m_bTopLevel) + GetImport().HandlePageSpan(aPropertyList); + } + else + { + OString sName = OUStringToOString(rAttributeName, RTL_TEXTENCODING_UTF8); + OString sValue = OUStringToOString(rAttributeValue, RTL_TEXTENCODING_UTF8); + aPropertyList.insert(sName.getStr(), sValue.getStr()); + } + } + + GetImport().GetGenerator().openParagraph(aPropertyList); +} + +void XMLParaContext::endElement(const OUString& /*rName*/) +{ + GetImport().GetGenerator().closeParagraph(); +} + +void XMLParaContext::characters(const OUString& rChars) +{ + librevenge::RVNGPropertyList aPropertyList; + if (!m_aStyleName.isEmpty()) + FillStyles(m_aStyleName, GetImport().GetAutomaticTextStyles(), GetImport().GetTextStyles(), + aPropertyList); + GetImport().GetGenerator().openSpan(aPropertyList); + + OString sCharU8 = OUStringToOString(rChars, RTL_TEXTENCODING_UTF8); + GetImport().GetGenerator().insertText(librevenge::RVNGString(sCharU8.getStr())); + + GetImport().GetGenerator().closeSpan(); +} + +rtl::Reference +CreateParagraphOrSpanChildContext(XMLImport& rImport, const OUString& rName, + const librevenge::RVNGPropertyList& rTextPropertyList) +{ + if (rName == "text:span") + return new XMLSpanContext(rImport, rTextPropertyList); + if (rName == "text:line-break") + return new XMLLineBreakContext(rImport, rTextPropertyList); + if (rName == "text:s") + return new XMLSpaceContext(rImport, rTextPropertyList); + if (rName == "text:tab") + return new XMLTabContext(rImport, rTextPropertyList); + if (rName == "draw:frame") + return new XMLTextFrameContext(rImport); + if (rName == "text:sequence") + return new XMLTextSequenceContext(rImport, rTextPropertyList); + if (rName == "text:note") + return new XMLFootnoteImportContext(rImport); + SAL_WARN("writerperfect", "CreateParagraphOrSpanChildContext: unhandled " << rName); + return nullptr; +} + +void FillStyles(const OUString& rName, + std::map& rAutomaticStyles, + std::map& rNamedStyles, + librevenge::RVNGPropertyList& rPropertyList) +{ + FillStyle(rName, rAutomaticStyles, rAutomaticStyles, rNamedStyles, rPropertyList); + FillStyle(rName, rNamedStyles, rAutomaticStyles, rNamedStyles, rPropertyList); +} + +} // namespace writerperfect + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/writerperfect/source/writer/exp/txtparai.hxx b/writerperfect/source/writer/exp/txtparai.hxx new file mode 100644 index 000000000..561be4f0a --- /dev/null +++ b/writerperfect/source/writer/exp/txtparai.hxx @@ -0,0 +1,65 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef INCLUDED_WRITERPERFECT_SOURCE_WRITER_EXP_TXTPARAI_HXX +#define INCLUDED_WRITERPERFECT_SOURCE_WRITER_EXP_TXTPARAI_HXX + +#include + +#include + +#include "xmlictxt.hxx" + +namespace writerperfect +{ +namespace exp +{ +/// Handler for /. +class XMLParaContext : public XMLImportContext +{ +public: + XMLParaContext(XMLImport& rImport, bool bTopLevel = false); + + rtl::Reference CreateChildContext( + const OUString& rName, + const css::uno::Reference& /*xAttribs*/) override; + + void SAL_CALL + startElement(const OUString& rName, + const css::uno::Reference& xAttribs) override; + void SAL_CALL endElement(const OUString& rName) override; + void SAL_CALL characters(const OUString& rChars) override; + +private: + OUString m_aStyleName; + /// List of properties spans should inherit from this paragraph. + librevenge::RVNGPropertyList m_aTextPropertyList; + /// If the context is a direct child of XMLBodyContentContext. + /// Only direct child of XMLBodyContentContext has to handle page span. + bool m_bTopLevel; +}; + +/// Shared child context factory for paragraph and span contexts. +rtl::Reference +CreateParagraphOrSpanChildContext(XMLImport& rImport, const OUString& rName, + const librevenge::RVNGPropertyList& rTextPropertyList); + +/// Looks for rName in rAutomaticStyles (and failing that, in rNamedStyles) and +/// fills rPropertyList based on that. +void FillStyles(const OUString& rName, + std::map& rAutomaticStyles, + std::map& rNamedStyles, + librevenge::RVNGPropertyList& rPropertyList); + +} // namespace exp +} // namespace writerperfect + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/writerperfect/source/writer/exp/txtstyli.cxx b/writerperfect/source/writer/exp/txtstyli.cxx new file mode 100644 index 000000000..53ac4b4e5 --- /dev/null +++ b/writerperfect/source/writer/exp/txtstyli.cxx @@ -0,0 +1,415 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "txtstyli.hxx" + +#include "xmlfmt.hxx" + +using namespace com::sun::star; + +namespace writerperfect::exp +{ +namespace +{ +/// Handler for . +class XMLParagraphPropertiesContext : public XMLImportContext +{ +public: + XMLParagraphPropertiesContext(XMLImport& rImport, XMLStyleContext& rStyle); + + void SAL_CALL + startElement(const OUString& rName, + const css::uno::Reference& xAttribs) override; + +private: + XMLStyleContext& mrStyle; +}; +} + +XMLParagraphPropertiesContext::XMLParagraphPropertiesContext(XMLImport& rImport, + XMLStyleContext& rStyle) + : XMLImportContext(rImport) + , mrStyle(rStyle) +{ +} + +void XMLParagraphPropertiesContext::startElement( + const OUString& /*rName*/, const css::uno::Reference& xAttribs) +{ + for (sal_Int16 i = 0; i < xAttribs->getLength(); ++i) + { + OString sName = OUStringToOString(xAttribs->getNameByIndex(i), RTL_TEXTENCODING_UTF8); + OString sValue = OUStringToOString(xAttribs->getValueByIndex(i), RTL_TEXTENCODING_UTF8); + mrStyle.GetParagraphPropertyList().insert(sName.getStr(), sValue.getStr()); + } +} + +namespace +{ +/// Handler for . +class XMLTextPropertiesContext : public XMLImportContext +{ +public: + XMLTextPropertiesContext(XMLImport& rImport, XMLStyleContext& rStyle); + + void SAL_CALL + startElement(const OUString& rName, + const css::uno::Reference& xAttribs) override; + +private: + XMLStyleContext& mrStyle; +}; +} + +XMLTextPropertiesContext::XMLTextPropertiesContext(XMLImport& rImport, XMLStyleContext& rStyle) + : XMLImportContext(rImport) + , mrStyle(rStyle) +{ +} + +void XMLTextPropertiesContext::startElement( + const OUString& /*rName*/, const css::uno::Reference& xAttribs) +{ + for (sal_Int16 i = 0; i < xAttribs->getLength(); ++i) + { + OString sName = OUStringToOString(xAttribs->getNameByIndex(i), RTL_TEXTENCODING_UTF8); + OString sValue = OUStringToOString(xAttribs->getValueByIndex(i), RTL_TEXTENCODING_UTF8); + mrStyle.GetTextPropertyList().insert(sName.getStr(), sValue.getStr()); + } +} + +namespace +{ +/// Handler for . +class XMLGraphicPropertiesContext : public XMLImportContext +{ +public: + XMLGraphicPropertiesContext(XMLImport& rImport, XMLStyleContext& rStyle); + + void SAL_CALL + startElement(const OUString& rName, + const css::uno::Reference& xAttribs) override; + +private: + XMLStyleContext& mrStyle; +}; +} + +XMLGraphicPropertiesContext::XMLGraphicPropertiesContext(XMLImport& rImport, + XMLStyleContext& rStyle) + : XMLImportContext(rImport) + , mrStyle(rStyle) +{ +} + +void XMLGraphicPropertiesContext::startElement( + const OUString& /*rName*/, const css::uno::Reference& xAttribs) +{ + for (sal_Int16 i = 0; i < xAttribs->getLength(); ++i) + { + OString sName = OUStringToOString(xAttribs->getNameByIndex(i), RTL_TEXTENCODING_UTF8); + OString sValue = OUStringToOString(xAttribs->getValueByIndex(i), RTL_TEXTENCODING_UTF8); + mrStyle.GetGraphicPropertyList().insert(sName.getStr(), sValue.getStr()); + } +} + +namespace +{ +/// Handler for . +class XMLPageLayoutPropertiesContext : public XMLImportContext +{ +public: + XMLPageLayoutPropertiesContext(XMLImport& rImport, XMLStyleContext& rStyle); + + void SAL_CALL + startElement(const OUString& rName, + const css::uno::Reference& xAttribs) override; + +private: + XMLStyleContext& mrStyle; +}; +} + +XMLPageLayoutPropertiesContext::XMLPageLayoutPropertiesContext(XMLImport& rImport, + XMLStyleContext& rStyle) + : XMLImportContext(rImport) + , mrStyle(rStyle) +{ +} + +void XMLPageLayoutPropertiesContext::startElement( + const OUString& /*rName*/, const css::uno::Reference& xAttribs) +{ + for (sal_Int16 i = 0; i < xAttribs->getLength(); ++i) + { + OString sName = OUStringToOString(xAttribs->getNameByIndex(i), RTL_TEXTENCODING_UTF8); + OString sValue = OUStringToOString(xAttribs->getValueByIndex(i), RTL_TEXTENCODING_UTF8); + // We only care about writing-mode for now. + if (sName != "style:writing-mode") + continue; + + mrStyle.GetPageLayoutPropertyList().insert(sName.getStr(), sValue.getStr()); + } +} + +namespace +{ +/// Handler for . +class XMLTablePropertiesContext : public XMLImportContext +{ +public: + XMLTablePropertiesContext(XMLImport& rImport, XMLStyleContext& rStyle); + + void SAL_CALL + startElement(const OUString& rName, + const css::uno::Reference& xAttribs) override; + +private: + XMLStyleContext& mrStyle; +}; +} + +XMLTablePropertiesContext::XMLTablePropertiesContext(XMLImport& rImport, XMLStyleContext& rStyle) + : XMLImportContext(rImport) + , mrStyle(rStyle) +{ +} + +void XMLTablePropertiesContext::startElement( + const OUString& /*rName*/, const css::uno::Reference& xAttribs) +{ + for (sal_Int16 i = 0; i < xAttribs->getLength(); ++i) + { + OString sName = OUStringToOString(xAttribs->getNameByIndex(i), RTL_TEXTENCODING_UTF8); + OString sValue = OUStringToOString(xAttribs->getValueByIndex(i), RTL_TEXTENCODING_UTF8); + if (sName == "style:rel-width") + // Make sure this is passed through as a string, and not parsed as a double. + mrStyle.GetTablePropertyList().insert( + sName.getStr(), librevenge::RVNGPropertyFactory::newStringProp(sValue.getStr())); + else + mrStyle.GetTablePropertyList().insert(sName.getStr(), sValue.getStr()); + } +} + +namespace +{ +/// Handler for . +class XMLTableRowPropertiesContext : public XMLImportContext +{ +public: + XMLTableRowPropertiesContext(XMLImport& rImport, XMLStyleContext& rStyle); + + void SAL_CALL + startElement(const OUString& rName, + const css::uno::Reference& xAttribs) override; + +private: + XMLStyleContext& mrStyle; +}; +} + +XMLTableRowPropertiesContext::XMLTableRowPropertiesContext(XMLImport& rImport, + XMLStyleContext& rStyle) + : XMLImportContext(rImport) + , mrStyle(rStyle) +{ +} + +void XMLTableRowPropertiesContext::startElement( + const OUString& /*rName*/, const css::uno::Reference& xAttribs) +{ + for (sal_Int16 i = 0; i < xAttribs->getLength(); ++i) + { + OString sName = OUStringToOString(xAttribs->getNameByIndex(i), RTL_TEXTENCODING_UTF8); + OString sValue = OUStringToOString(xAttribs->getValueByIndex(i), RTL_TEXTENCODING_UTF8); + mrStyle.GetRowPropertyList().insert(sName.getStr(), sValue.getStr()); + } +} + +namespace +{ +/// Handler for . +class XMLTableColumnPropertiesContext : public XMLImportContext +{ +public: + XMLTableColumnPropertiesContext(XMLImport& rImport, XMLStyleContext& rStyle); + + void SAL_CALL + startElement(const OUString& rName, + const css::uno::Reference& xAttribs) override; + +private: + XMLStyleContext& mrStyle; +}; +} + +XMLTableColumnPropertiesContext::XMLTableColumnPropertiesContext(XMLImport& rImport, + XMLStyleContext& rStyle) + : XMLImportContext(rImport) + , mrStyle(rStyle) +{ +} + +void XMLTableColumnPropertiesContext::startElement( + const OUString& /*rName*/, const css::uno::Reference& xAttribs) +{ + for (sal_Int16 i = 0; i < xAttribs->getLength(); ++i) + { + OString sName = OUStringToOString(xAttribs->getNameByIndex(i), RTL_TEXTENCODING_UTF8); + OString sValue = OUStringToOString(xAttribs->getValueByIndex(i), RTL_TEXTENCODING_UTF8); + mrStyle.GetColumnPropertyList().insert(sName.getStr(), sValue.getStr()); + } +} + +namespace +{ +/// Handler for . +class XMLTableCellPropertiesContext : public XMLImportContext +{ +public: + XMLTableCellPropertiesContext(XMLImport& rImport, XMLStyleContext& rStyle); + + void SAL_CALL + startElement(const OUString& rName, + const css::uno::Reference& xAttribs) override; + +private: + XMLStyleContext& mrStyle; +}; +} + +XMLTableCellPropertiesContext::XMLTableCellPropertiesContext(XMLImport& rImport, + XMLStyleContext& rStyle) + : XMLImportContext(rImport) + , mrStyle(rStyle) +{ +} + +void XMLTableCellPropertiesContext::startElement( + const OUString& /*rName*/, const css::uno::Reference& xAttribs) +{ + for (sal_Int16 i = 0; i < xAttribs->getLength(); ++i) + { + OString sName = OUStringToOString(xAttribs->getNameByIndex(i), RTL_TEXTENCODING_UTF8); + OString sValue = OUStringToOString(xAttribs->getValueByIndex(i), RTL_TEXTENCODING_UTF8); + mrStyle.GetCellPropertyList().insert(sName.getStr(), sValue.getStr()); + } +} + +XMLStyleContext::XMLStyleContext(XMLImport& rImport, XMLStylesContext& rStyles) + : XMLImportContext(rImport) + , m_rStyles(rStyles) +{ +} + +rtl::Reference XMLStyleContext::CreateChildContext( + const OUString& rName, const css::uno::Reference& /*xAttribs*/) +{ + if (rName == "style:paragraph-properties") + return new XMLParagraphPropertiesContext(GetImport(), *this); + if (rName == "style:text-properties") + return new XMLTextPropertiesContext(GetImport(), *this); + if (rName == "style:table-cell-properties") + return new XMLTableCellPropertiesContext(GetImport(), *this); + if (rName == "style:table-column-properties") + return new XMLTableColumnPropertiesContext(GetImport(), *this); + if (rName == "style:table-row-properties") + return new XMLTableRowPropertiesContext(GetImport(), *this); + if (rName == "style:table-properties") + return new XMLTablePropertiesContext(GetImport(), *this); + if (rName == "style:graphic-properties") + return new XMLGraphicPropertiesContext(GetImport(), *this); + if (rName == "style:page-layout-properties") + return new XMLPageLayoutPropertiesContext(GetImport(), *this); + return nullptr; +} + +void XMLStyleContext::startElement( + const OUString& /*rName*/, const css::uno::Reference& xAttribs) +{ + for (sal_Int16 i = 0; i < xAttribs->getLength(); ++i) + { + const OUString& rAttributeName = xAttribs->getNameByIndex(i); + const OUString& rAttributeValue = xAttribs->getValueByIndex(i); + if (rAttributeName == "style:name") + m_aName = rAttributeValue; + else if (rAttributeName == "style:family") + m_aFamily = rAttributeValue; + + // Remember properties of the style itself, e.g. parent name. + OString sName = OUStringToOString(rAttributeName, RTL_TEXTENCODING_UTF8); + OString sValue = OUStringToOString(rAttributeValue, RTL_TEXTENCODING_UTF8); + m_aTextPropertyList.insert(sName.getStr(), sValue.getStr()); + m_aParagraphPropertyList.insert(sName.getStr(), sValue.getStr()); + m_aGraphicPropertyList.insert(sName.getStr(), sValue.getStr()); + m_aPageLayoutPropertyList.insert(sName.getStr(), sValue.getStr()); + m_aMasterPagePropertyList.insert(sName.getStr(), sValue.getStr()); + m_aTablePropertyList.insert(sName.getStr(), sValue.getStr()); + } +} + +void XMLStyleContext::endElement(const OUString& rName) +{ + if (m_aName.isEmpty()) + return; + + if (m_aFamily == "text" || m_aFamily == "paragraph") + m_rStyles.GetCurrentTextStyles()[m_aName] = m_aTextPropertyList; + if (m_aFamily == "paragraph") + m_rStyles.GetCurrentParagraphStyles()[m_aName] = m_aParagraphPropertyList; + else if (m_aFamily == "table-cell") + m_rStyles.GetCurrentCellStyles()[m_aName] = m_aCellPropertyList; + else if (m_aFamily == "table-column") + m_rStyles.GetCurrentColumnStyles()[m_aName] = m_aColumnPropertyList; + else if (m_aFamily == "table-row") + m_rStyles.GetCurrentRowStyles()[m_aName] = m_aRowPropertyList; + else if (m_aFamily == "table") + m_rStyles.GetCurrentTableStyles()[m_aName] = m_aTablePropertyList; + else if (m_aFamily == "graphic") + m_rStyles.GetCurrentGraphicStyles()[m_aName] = m_aGraphicPropertyList; + else if (rName == "style:page-layout") + m_rStyles.GetCurrentPageLayouts()[m_aName] = m_aPageLayoutPropertyList; + else if (rName == "style:master-page") + m_rStyles.GetCurrentMasterStyles()[m_aName] = m_aMasterPagePropertyList; +} + +librevenge::RVNGPropertyList& XMLStyleContext::GetTextPropertyList() { return m_aTextPropertyList; } + +librevenge::RVNGPropertyList& XMLStyleContext::GetParagraphPropertyList() +{ + return m_aParagraphPropertyList; +} + +librevenge::RVNGPropertyList& XMLStyleContext::GetCellPropertyList() { return m_aCellPropertyList; } + +librevenge::RVNGPropertyList& XMLStyleContext::GetColumnPropertyList() +{ + return m_aColumnPropertyList; +} + +librevenge::RVNGPropertyList& XMLStyleContext::GetRowPropertyList() { return m_aRowPropertyList; } + +librevenge::RVNGPropertyList& XMLStyleContext::GetTablePropertyList() +{ + return m_aTablePropertyList; +} + +librevenge::RVNGPropertyList& XMLStyleContext::GetGraphicPropertyList() +{ + return m_aGraphicPropertyList; +} + +librevenge::RVNGPropertyList& XMLStyleContext::GetPageLayoutPropertyList() +{ + return m_aPageLayoutPropertyList; +} + +} // namespace writerperfect::exp + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/writerperfect/source/writer/exp/txtstyli.hxx b/writerperfect/source/writer/exp/txtstyli.hxx new file mode 100644 index 000000000..c4ddc4888 --- /dev/null +++ b/writerperfect/source/writer/exp/txtstyli.hxx @@ -0,0 +1,66 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef INCLUDED_WRITERPERFECT_SOURCE_WRITER_EXP_TXTSTYLI_HXX +#define INCLUDED_WRITERPERFECT_SOURCE_WRITER_EXP_TXTSTYLI_HXX + +#include + +#include "xmlictxt.hxx" + +namespace writerperfect +{ +namespace exp +{ +class XMLStylesContext; + +/// Handler for . +class XMLStyleContext : public XMLImportContext +{ +public: + XMLStyleContext(XMLImport& rImport, XMLStylesContext& rStyles); + + rtl::Reference + CreateChildContext(const OUString& rName, + const css::uno::Reference& xAttribs) override; + void SAL_CALL + startElement(const OUString& rName, + const css::uno::Reference& xAttribs) override; + void SAL_CALL endElement(const OUString& rName) override; + + librevenge::RVNGPropertyList& GetTextPropertyList(); + librevenge::RVNGPropertyList& GetParagraphPropertyList(); + librevenge::RVNGPropertyList& GetCellPropertyList(); + librevenge::RVNGPropertyList& GetColumnPropertyList(); + librevenge::RVNGPropertyList& GetRowPropertyList(); + librevenge::RVNGPropertyList& GetTablePropertyList(); + librevenge::RVNGPropertyList& GetGraphicPropertyList(); + librevenge::RVNGPropertyList& GetPageLayoutPropertyList(); + +private: + OUString m_aName; + OUString m_aFamily; + librevenge::RVNGPropertyList m_aTextPropertyList; + librevenge::RVNGPropertyList m_aParagraphPropertyList; + librevenge::RVNGPropertyList m_aCellPropertyList; + librevenge::RVNGPropertyList m_aColumnPropertyList; + librevenge::RVNGPropertyList m_aRowPropertyList; + librevenge::RVNGPropertyList m_aTablePropertyList; + librevenge::RVNGPropertyList m_aGraphicPropertyList; + librevenge::RVNGPropertyList m_aPageLayoutPropertyList; + librevenge::RVNGPropertyList m_aMasterPagePropertyList; + XMLStylesContext& m_rStyles; +}; + +} // namespace exp +} // namespace writerperfect + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/writerperfect/source/writer/exp/xmlfmt.cxx b/writerperfect/source/writer/exp/xmlfmt.cxx new file mode 100644 index 000000000..f34540ddd --- /dev/null +++ b/writerperfect/source/writer/exp/xmlfmt.cxx @@ -0,0 +1,295 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "xmlfmt.hxx" + +#include "XMLBase64ImportContext.hxx" +#include "txtstyli.hxx" +#include "xmlimp.hxx" + +#include + +using namespace com::sun::star; + +namespace writerperfect::exp +{ +XMLStylesContext::XMLStylesContext(XMLImport& rImport, StyleType eType) + : XMLImportContext(rImport) + , m_rParagraphStyles(eType == StyleType_AUTOMATIC ? GetImport().GetAutomaticParagraphStyles() + : GetImport().GetParagraphStyles()) + , m_rTextStyles(eType == StyleType_AUTOMATIC ? GetImport().GetAutomaticTextStyles() + : GetImport().GetTextStyles()) + , m_rCellStyles(eType == StyleType_AUTOMATIC ? GetImport().GetAutomaticCellStyles() + : GetImport().GetCellStyles()) + , m_rColumnStyles(eType == StyleType_AUTOMATIC ? GetImport().GetAutomaticColumnStyles() + : GetImport().GetColumnStyles()) + , m_rRowStyles(eType == StyleType_AUTOMATIC ? GetImport().GetAutomaticRowStyles() + : GetImport().GetRowStyles()) + , m_rTableStyles(eType == StyleType_AUTOMATIC ? GetImport().GetAutomaticTableStyles() + : GetImport().GetTableStyles()) + , m_rGraphicStyles(eType == StyleType_AUTOMATIC ? GetImport().GetAutomaticGraphicStyles() + : GetImport().GetGraphicStyles()) + , m_rPageLayouts(GetImport().GetPageLayouts()) + , m_rMasterStyles(GetImport().GetMasterStyles()) +{ +} + +rtl::Reference XMLStylesContext::CreateChildContext( + const OUString& rName, const css::uno::Reference& /*xAttribs*/) +{ + if (rName == "style:style" || rName == "style:page-layout" || rName == "style:master-page") + return new XMLStyleContext(GetImport(), *this); + return nullptr; +} + +std::map& XMLStylesContext::GetCurrentParagraphStyles() +{ + return m_rParagraphStyles; +} + +std::map& XMLStylesContext::GetCurrentTextStyles() +{ + return m_rTextStyles; +} + +std::map& XMLStylesContext::GetCurrentCellStyles() +{ + return m_rCellStyles; +} + +std::map& XMLStylesContext::GetCurrentColumnStyles() +{ + return m_rColumnStyles; +} + +std::map& XMLStylesContext::GetCurrentRowStyles() +{ + return m_rRowStyles; +} + +std::map& XMLStylesContext::GetCurrentTableStyles() +{ + return m_rTableStyles; +} + +std::map& XMLStylesContext::GetCurrentGraphicStyles() +{ + return m_rGraphicStyles; +} + +std::map& XMLStylesContext::GetCurrentPageLayouts() +{ + return m_rPageLayouts; +} + +std::map& XMLStylesContext::GetCurrentMasterStyles() +{ + return m_rMasterStyles; +} + +namespace +{ +/// Handler for . +class XMLFontFaceContext : public XMLImportContext +{ +public: + XMLFontFaceContext(XMLImport& rImport); + void SAL_CALL + startElement(const OUString& rName, + const css::uno::Reference& xAttribs) override; + + rtl::Reference + CreateChildContext(const OUString& rName, + const css::uno::Reference& xAttribs) override; + + OUString const& GetName() const { return maName; } + +private: + OUString maName; +}; + +/// Handler for . +class XMLFontFaceSrcContext : public XMLImportContext +{ +public: + XMLFontFaceSrcContext(XMLImport& rImport, XMLFontFaceContext& rFontFace); + + rtl::Reference + CreateChildContext(const OUString& rName, + const css::uno::Reference& xAttribs) override; + +private: + XMLFontFaceContext& mrFontFace; +}; + +/// Handler for . +class XMLFontFaceUriContext : public XMLImportContext +{ +public: + XMLFontFaceUriContext(XMLImport& rImport, XMLFontFaceContext const& rFontFace); + void SAL_CALL + startElement(const OUString& rName, + const css::uno::Reference& xAttribs) override; + void SAL_CALL endElement(const OUString& rName) override; + + rtl::Reference + CreateChildContext(const OUString& rName, + const css::uno::Reference& xAttribs) override; + + librevenge::RVNGPropertyList& GetPropertyList() { return maPropertyList; } + +private: + librevenge::RVNGPropertyList maPropertyList; + rtl::Reference mxBinaryData; +}; + +/// Handler for . +class XMLFontFaceFormatContext : public XMLImportContext +{ +public: + XMLFontFaceFormatContext(XMLImport& rImport, XMLFontFaceUriContext& rFontFaceUri); + void SAL_CALL + startElement(const OUString& rName, + const css::uno::Reference& xAttribs) override; + +private: + XMLFontFaceUriContext& mrFontFaceUri; +}; +} + +XMLFontFaceFormatContext::XMLFontFaceFormatContext(XMLImport& rImport, + XMLFontFaceUriContext& rFontFaceUri) + : XMLImportContext(rImport) + , mrFontFaceUri(rFontFaceUri) +{ +} + +void XMLFontFaceFormatContext::startElement( + const OUString& /*rName*/, const css::uno::Reference& xAttribs) +{ + for (sal_Int16 i = 0; i < xAttribs->getLength(); ++i) + { + const OUString& rAttributeName = xAttribs->getNameByIndex(i); + const OUString& rAttributeValue = xAttribs->getValueByIndex(i); + if (rAttributeName == "svg:string") + { + OString aAttributeValueU8 = OUStringToOString(rAttributeValue, RTL_TEXTENCODING_UTF8); + mrFontFaceUri.GetPropertyList().insert("librevenge:mime-type", + aAttributeValueU8.getStr()); + } + } +} + +XMLFontFaceUriContext::XMLFontFaceUriContext(XMLImport& rImport, + XMLFontFaceContext const& rFontFace) + : XMLImportContext(rImport) +{ + OString aNameU8 = OUStringToOString(rFontFace.GetName(), RTL_TEXTENCODING_UTF8); + maPropertyList.insert("librevenge:name", aNameU8.getStr()); +} + +void XMLFontFaceUriContext::startElement( + const OUString& /*rName*/, const css::uno::Reference& xAttribs) +{ + for (sal_Int16 i = 0; i < xAttribs->getLength(); ++i) + { + const OUString& rAttributeName = xAttribs->getNameByIndex(i); + const OUString& rAttributeValue = xAttribs->getValueByIndex(i); + if (rAttributeName == "loext:font-style") + { + OString aAttributeValueU8 = OUStringToOString(rAttributeValue, RTL_TEXTENCODING_UTF8); + maPropertyList.insert("librevenge:font-style", aAttributeValueU8.getStr()); + } + else if (rAttributeName == "loext:font-weight") + { + OString aAttributeValueU8 = OUStringToOString(rAttributeValue, RTL_TEXTENCODING_UTF8); + maPropertyList.insert("librevenge:font-weight", aAttributeValueU8.getStr()); + } + } +} + +void XMLFontFaceUriContext::endElement(const OUString& /*rName*/) +{ + if (mxBinaryData.is()) + maPropertyList.insert("office:binary-data", mxBinaryData->getBinaryData()); + GetImport().GetGenerator().defineEmbeddedFont(maPropertyList); +} + +rtl::Reference XMLFontFaceUriContext::CreateChildContext( + const OUString& rName, const css::uno::Reference& /*xAttribs*/) +{ + if (rName == "office:binary-data") + { + mxBinaryData = new XMLBase64ImportContext(GetImport()); + return mxBinaryData.get(); + } + if (rName == "svg:font-face-format") + return new XMLFontFaceFormatContext(GetImport(), *this); + + SAL_WARN("writerperfect", "XMLFontFaceUriContext::CreateChildContext: unhandled " << rName); + return nullptr; +} + +XMLFontFaceSrcContext::XMLFontFaceSrcContext(XMLImport& rImport, XMLFontFaceContext& rFontFace) + : XMLImportContext(rImport) + , mrFontFace(rFontFace) +{ +} + +rtl::Reference XMLFontFaceSrcContext::CreateChildContext( + const OUString& rName, const css::uno::Reference& /*xAttribs*/) +{ + if (rName == "svg:font-face-uri") + return new XMLFontFaceUriContext(GetImport(), mrFontFace); + SAL_WARN("writerperfect", "XMLFontFaceSrcContext::CreateChildContext: unhandled " << rName); + return nullptr; +} + +XMLFontFaceContext::XMLFontFaceContext(XMLImport& rImport) + : XMLImportContext(rImport) +{ +} + +void XMLFontFaceContext::startElement( + const OUString& /*rName*/, const css::uno::Reference& xAttribs) +{ + for (sal_Int16 i = 0; i < xAttribs->getLength(); ++i) + { + const OUString& rAttributeName = xAttribs->getNameByIndex(i); + const OUString& rAttributeValue = xAttribs->getValueByIndex(i); + if (rAttributeName == "style:name") + maName = rAttributeValue; + } +} + +rtl::Reference XMLFontFaceContext::CreateChildContext( + const OUString& rName, const css::uno::Reference& /*xAttribs*/) +{ + if (rName == "svg:font-face-src") + return new XMLFontFaceSrcContext(GetImport(), *this); + SAL_WARN("writerperfect", "XMLFontFaceContext::CreateChildContext: unhandled " << rName); + return nullptr; +} + +XMLFontFaceDeclsContext::XMLFontFaceDeclsContext(XMLImport& rImport) + : XMLImportContext(rImport) +{ +} + +rtl::Reference XMLFontFaceDeclsContext::CreateChildContext( + const OUString& rName, const css::uno::Reference& /*xAttribs*/) +{ + if (rName == "style:font-face") + return new XMLFontFaceContext(GetImport()); + return nullptr; +} + +} // namespace writerperfect::exp + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/writerperfect/source/writer/exp/xmlfmt.hxx b/writerperfect/source/writer/exp/xmlfmt.hxx new file mode 100644 index 000000000..6f3211de2 --- /dev/null +++ b/writerperfect/source/writer/exp/xmlfmt.hxx @@ -0,0 +1,79 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef INCLUDED_WRITERPERFECT_SOURCE_WRITER_EXP_XMLFMT_HXX +#define INCLUDED_WRITERPERFECT_SOURCE_WRITER_EXP_XMLFMT_HXX + +#include + +#include "xmlictxt.hxx" + +namespace librevenge +{ +class RVNGPropertyList; +} + +namespace writerperfect +{ +namespace exp +{ +/// Handler for /. +class XMLStylesContext : public XMLImportContext +{ +public: + enum StyleType + { + StyleType_NONE, + StyleType_AUTOMATIC + }; + XMLStylesContext(XMLImport& rImport, StyleType eType); + + rtl::Reference + CreateChildContext(const OUString& rName, + const css::uno::Reference& xAttribs) override; + + std::map& GetCurrentParagraphStyles(); + std::map& GetCurrentTextStyles(); + std::map& GetCurrentCellStyles(); + std::map& GetCurrentColumnStyles(); + std::map& GetCurrentRowStyles(); + std::map& GetCurrentTableStyles(); + std::map& GetCurrentGraphicStyles(); + std::map& GetCurrentPageLayouts(); + std::map& GetCurrentMasterStyles(); + +private: + std::map& m_rParagraphStyles; + std::map& m_rTextStyles; + std::map& m_rCellStyles; + std::map& m_rColumnStyles; + std::map& m_rRowStyles; + std::map& m_rTableStyles; + std::map& m_rGraphicStyles; + std::map& m_rPageLayouts; + std::map& m_rMasterStyles; +}; + +/// Handler for . +class XMLFontFaceDeclsContext : public XMLImportContext +{ +public: + XMLFontFaceDeclsContext(XMLImport& rImport); + + rtl::Reference + CreateChildContext(const OUString& rName, + const css::uno::Reference& xAttribs) override; +}; + +} // namespace exp +} // namespace writerperfect + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/writerperfect/source/writer/exp/xmlictxt.cxx b/writerperfect/source/writer/exp/xmlictxt.cxx new file mode 100644 index 000000000..ebfe58402 --- /dev/null +++ b/writerperfect/source/writer/exp/xmlictxt.cxx @@ -0,0 +1,56 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "xmlictxt.hxx" + +#include "xmlimp.hxx" + +using namespace com::sun::star; + +namespace writerperfect::exp +{ +XMLImportContext::XMLImportContext(XMLImport& rImport) + : mrImport(rImport) +{ +} + +rtl::Reference XMLImportContext::CreateChildContext( + const OUString& rName, const css::uno::Reference& xAttribs) +{ + return mrImport.CreateContext(rName, xAttribs); +} + +void XMLImportContext::startDocument() {} + +void XMLImportContext::endDocument() {} + +void XMLImportContext::startElement( + const OUString& /*rName*/, + const css::uno::Reference& /*xAttribs*/) +{ +} + +void XMLImportContext::endElement(const OUString& /*rName*/) {} + +void XMLImportContext::characters(const OUString& /*rChars*/) {} + +void XMLImportContext::ignorableWhitespace(const OUString& /*rWhitespaces*/) {} + +void XMLImportContext::processingInstruction(const OUString& /*rTarget*/, const OUString& /*rData*/) +{ +} + +void XMLImportContext::setDocumentLocator( + const css::uno::Reference& /*xLocator*/) +{ +} + +} // namespace writerperfect::exp + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/writerperfect/source/writer/exp/xmlictxt.hxx b/writerperfect/source/writer/exp/xmlictxt.hxx new file mode 100644 index 000000000..a0ea42bc6 --- /dev/null +++ b/writerperfect/source/writer/exp/xmlictxt.hxx @@ -0,0 +1,57 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef INCLUDED_WRITERPERFECT_SOURCE_WRITER_EXP_XMLICTXT_HXX +#define INCLUDED_WRITERPERFECT_SOURCE_WRITER_EXP_XMLICTXT_HXX + +#include + +#include +#include + +namespace writerperfect +{ +namespace exp +{ +class XMLImport; + +/// Base class for a handler of a single XML element during ODF -> librevenge conversion. +class XMLImportContext : public cppu::WeakImplHelper +{ +public: + XMLImportContext(XMLImport& rImport); + XMLImport& GetImport() { return mrImport; } + + virtual rtl::Reference + CreateChildContext(const OUString& rName, + const css::uno::Reference& xAttribs); + + // XDocumentHandler + void SAL_CALL startDocument() override; + void SAL_CALL endDocument() override; + void SAL_CALL + startElement(const OUString& rName, + const css::uno::Reference& xAttribs) override; + void SAL_CALL endElement(const OUString& rName) override; + void SAL_CALL characters(const OUString& rChars) override; + void SAL_CALL ignorableWhitespace(const OUString& rWhitespaces) override; + void SAL_CALL processingInstruction(const OUString& rTarget, const OUString& rData) override; + void SAL_CALL + setDocumentLocator(const css::uno::Reference& xLocator) override; + +private: + XMLImport& mrImport; +}; + +} // namespace exp +} // namespace writerperfect + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/writerperfect/source/writer/exp/xmlimp.cxx b/writerperfect/source/writer/exp/xmlimp.cxx new file mode 100644 index 000000000..9ade95990 --- /dev/null +++ b/writerperfect/source/writer/exp/xmlimp.cxx @@ -0,0 +1,617 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "xmlimp.hxx" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "xmlfmt.hxx" +#include "xmlictxt.hxx" +#include "xmlmetai.hxx" +#include "xmltext.hxx" + +using namespace com::sun::star; + +namespace writerperfect::exp +{ +namespace +{ +/// Looks up mime type for a given image extension. +OUString GetMimeType(const OUString& rExtension) +{ + static const std::unordered_map vMimeTypes = { + { "gif", "image/gif" }, + { "jpg", "image/jpeg" }, + { "png", "image/png" }, + { "svg", "image/svg+xml" }, + }; + + auto it = vMimeTypes.find(rExtension); + return it == vMimeTypes.end() ? OUString() : it->second; +} + +/// Determines the base directory for cover images, XMP metadata, popup images. +OUString FindMediaDir(const OUString& rDocumentBaseURL, + const uno::Sequence& rFilterData) +{ + OUString aMediaDir; + + // See if filter data contains a media directory explicitly. + auto pProp = std::find_if( + rFilterData.begin(), rFilterData.end(), + [](const beans::PropertyValue& rProp) { return rProp.Name == "RVNGMediaDir"; }); + if (pProp != rFilterData.end()) + pProp->Value >>= aMediaDir; + + if (!aMediaDir.isEmpty()) + return aMediaDir + "/"; + + // Not set explicitly, try to pick it up from the base directory. + INetURLObject aURL(rDocumentBaseURL); + try + { + aMediaDir = rtl::Uri::convertRelToAbs(rDocumentBaseURL, aURL.GetBase()) + "/"; + } + catch (const rtl::MalformedUriException&) + { + DBG_UNHANDLED_EXCEPTION("writerperfect"); + } + return aMediaDir; +} + +/// Picks up a cover image from the base directory. +OUString FindCoverImage(const OUString& rDocumentBaseURL, OUString& rMimeType, + const uno::Sequence& rFilterData) +{ + OUString aRet; + + // See if filter data contains a cover image explicitly. + auto pProp = std::find_if( + rFilterData.begin(), rFilterData.end(), + [](const beans::PropertyValue& rProp) { return rProp.Name == "RVNGCoverImage"; }); + if (pProp != rFilterData.end()) + pProp->Value >>= aRet; + + if (!aRet.isEmpty()) + { + INetURLObject aRetURL(aRet); + rMimeType = GetMimeType(aRetURL.GetFileExtension()); + return aRet; + } + + // Not set explicitly, try to pick it up from the base directory. + if (rDocumentBaseURL.isEmpty()) + return aRet; + + static const std::initializer_list vExtensions + = { "gif", "jpg", "png", "svg" }; + + OUString aMediaDir = FindMediaDir(rDocumentBaseURL, rFilterData); + for (const auto& rExtension : vExtensions) + { + aRet = aMediaDir + "cover." + rExtension; + if (!aRet.isEmpty()) + { + SvFileStream aStream(aRet, StreamMode::READ); + if (aStream.IsOpen()) + { + rMimeType = GetMimeType(rExtension); + // File exists. + return aRet; + } + + aRet.clear(); + } + } + + return aRet; +} + +/// Picks up XMP metadata from the base directory. +void FindXMPMetadata(const uno::Reference& xContext, + const OUString& rDocumentBaseURL, + const uno::Sequence& rFilterData, + librevenge::RVNGPropertyList& rMetaData) +{ + // See if filter data contains metadata explicitly. + OUString aValue; + for (const auto& rProp : rFilterData) + { + if (rProp.Name == "RVNGIdentifier") + { + rProp.Value >>= aValue; + if (!aValue.isEmpty()) + rMetaData.insert("dc:identifier", aValue.toUtf8().getStr()); + } + else if (rProp.Name == "RVNGTitle") + { + rProp.Value >>= aValue; + if (!aValue.isEmpty()) + rMetaData.insert("dc:title", aValue.toUtf8().getStr()); + } + else if (rProp.Name == "RVNGInitialCreator") + { + rProp.Value >>= aValue; + if (!aValue.isEmpty()) + rMetaData.insert("meta:initial-creator", aValue.toUtf8().getStr()); + } + else if (rProp.Name == "RVNGLanguage") + { + rProp.Value >>= aValue; + if (!aValue.isEmpty()) + rMetaData.insert("dc:language", aValue.toUtf8().getStr()); + } + else if (rProp.Name == "RVNGDate") + { + rProp.Value >>= aValue; + if (!aValue.isEmpty()) + rMetaData.insert("dc:date", aValue.toUtf8().getStr()); + } + } + + // If not set explicitly, try to pick it up from the base directory. + if (rDocumentBaseURL.isEmpty()) + return; + + OUString aMediaDir = FindMediaDir(rDocumentBaseURL, rFilterData); + OUString aURL = aMediaDir + "metadata.xmp"; + SvFileStream aStream(aURL, StreamMode::READ); + if (!aStream.IsOpen()) + return; + + xml::sax::InputSource aInputSource; + uno::Reference xStream(new utl::OStreamWrapper(aStream)); + aInputSource.aInputStream = xStream; + uno::Reference xParser = xml::sax::Parser::create(xContext); + rtl::Reference xXMP(new XMPParser(rMetaData)); + uno::Reference xDocumentHandler(xXMP.get()); + xParser->setDocumentHandler(xDocumentHandler); + try + { + xParser->parseStream(aInputSource); + } + catch (const uno::Exception&) + { + DBG_UNHANDLED_EXCEPTION("writerperfect", "parseStream() failed"); + return; + } +} + +/// Handler for . +class XMLBodyContext : public XMLImportContext +{ +public: + XMLBodyContext(XMLImport& rImport); + + rtl::Reference + CreateChildContext(const OUString& rName, + const uno::Reference& /*xAttribs*/) override; +}; +} + +XMLBodyContext::XMLBodyContext(XMLImport& rImport) + : XMLImportContext(rImport) +{ +} + +rtl::Reference +XMLBodyContext::CreateChildContext(const OUString& rName, + const uno::Reference& /*xAttribs*/) +{ + if (rName == "office:text") + return new XMLBodyContentContext(GetImport()); + return nullptr; +} + +namespace +{ +/// Handler for . +class XMLOfficeDocContext : public XMLImportContext +{ +public: + XMLOfficeDocContext(XMLImport& rImport); + + rtl::Reference + CreateChildContext(const OUString& rName, + const uno::Reference& /*xAttribs*/) override; + + // Handles metafile for a single page. + void HandleFixedLayoutPage(const FixedLayoutPage& rPage, bool bFirst); +}; +} + +XMLOfficeDocContext::XMLOfficeDocContext(XMLImport& rImport) + : XMLImportContext(rImport) +{ +} + +rtl::Reference XMLOfficeDocContext::CreateChildContext( + const OUString& rName, const uno::Reference& /*xAttribs*/) +{ + if (rName == "office:meta") + return new XMLMetaDocumentContext(GetImport()); + if (rName == "office:automatic-styles") + return new XMLStylesContext(GetImport(), XMLStylesContext::StyleType_AUTOMATIC); + if (rName == "office:styles") + return new XMLStylesContext(GetImport(), XMLStylesContext::StyleType_NONE); + if (rName == "office:master-styles") + return new XMLStylesContext(GetImport(), XMLStylesContext::StyleType_NONE); + if (rName == "office:font-face-decls") + return new XMLFontFaceDeclsContext(GetImport()); + if (rName == "office:body") + { + if (GetImport().GetPageMetafiles().empty()) + return new XMLBodyContext(GetImport()); + + // Ignore text from doc model in the fixed layout case, instead + // insert the page metafiles. + bool bFirst = true; + for (const auto& rPage : GetImport().GetPageMetafiles()) + { + HandleFixedLayoutPage(rPage, bFirst); + if (bFirst) + bFirst = false; + } + } + return nullptr; +} + +void XMLOfficeDocContext::HandleFixedLayoutPage(const FixedLayoutPage& rPage, bool bFirst) +{ + uno::Reference xCtx = GetImport().GetComponentContext(); + uno::Reference xSaxWriter = xml::sax::Writer::create(xCtx); + if (!xSaxWriter.is()) + return; + + uno::Sequence aArguments = { uno::makeAny>( + { comphelper::makePropertyValue("DTDString", false) }) }; + uno::Reference xSVGWriter( + xCtx->getServiceManager()->createInstanceWithArgumentsAndContext( + "com.sun.star.svg.SVGWriter", aArguments, xCtx), + uno::UNO_QUERY); + if (!xSVGWriter.is()) + return; + + SvMemoryStream aMemoryStream; + xSaxWriter->setOutputStream(new utl::OStreamWrapper(aMemoryStream)); + + xSVGWriter->write(xSaxWriter, rPage.aMetafile); + + // Have all the info, invoke the generator. + librevenge::RVNGPropertyList aPageProperties; + // Pixel -> inch. + double fWidth = rPage.aCssPixels.getWidth(); + fWidth /= 96; + aPageProperties.insert("fo:page-width", fWidth); + double fHeight = rPage.aCssPixels.getHeight(); + fHeight /= 96; + aPageProperties.insert("fo:page-height", fHeight); + + if (!rPage.aChapterNames.empty()) + { + // Name of chapters starting on this page. + librevenge::RVNGPropertyListVector aChapterNames; + for (const auto& rName : rPage.aChapterNames) + { + librevenge::RVNGPropertyList aChapter; + aChapter.insert("librevenge:name", rName.toUtf8().getStr()); + aChapterNames.append(aChapter); + } + aPageProperties.insert("librevenge:chapter-names", aChapterNames); + } + + GetImport().GetGenerator().openPageSpan(aPageProperties); + librevenge::RVNGPropertyList aParagraphProperties; + if (!bFirst) + // All pages except the first one needs a page break before the page + // metafile. + aParagraphProperties.insert("fo:break-before", "page"); + GetImport().GetGenerator().openParagraph(aParagraphProperties); + librevenge::RVNGPropertyList aImageProperties; + aImageProperties.insert("librevenge:mime-type", "image/svg+xml"); + librevenge::RVNGBinaryData aBinaryData; + aBinaryData.append(static_cast(aMemoryStream.GetData()), + aMemoryStream.GetSize()); + aImageProperties.insert("office:binary-data", aBinaryData); + GetImport().GetGenerator().insertBinaryObject(aImageProperties); + GetImport().GetGenerator().closeParagraph(); + GetImport().GetGenerator().closePageSpan(); +} + +XMLImport::XMLImport(const uno::Reference& xContext, + librevenge::RVNGTextInterface& rGenerator, const OUString& rURL, + const uno::Sequence& rDescriptor, + const std::vector& rPageMetafiles) + : mrGenerator(rGenerator) + , mxContext(xContext) + , mbIsInPageSpan(false) + , mrPageMetafiles(rPageMetafiles) +{ + uno::Sequence aFilterData; + auto pDescriptor = std::find_if( + rDescriptor.begin(), rDescriptor.end(), + [](const beans::PropertyValue& rProp) { return rProp.Name == "FilterData"; }); + if (pDescriptor != rDescriptor.end()) + pDescriptor->Value >>= aFilterData; + + maMediaDir = FindMediaDir(rURL, aFilterData); + + OUString aMimeType; + OUString aCoverImage = FindCoverImage(rURL, aMimeType, aFilterData); + if (!aCoverImage.isEmpty()) + { + librevenge::RVNGBinaryData aBinaryData; + SvFileStream aStream(aCoverImage, StreamMode::READ); + SvMemoryStream aMemoryStream; + aMemoryStream.WriteStream(aStream); + aBinaryData.append(static_cast(aMemoryStream.GetData()), + aMemoryStream.GetSize()); + librevenge::RVNGPropertyList aCoverImageProperties; + aCoverImageProperties.insert("office:binary-data", aBinaryData); + aCoverImageProperties.insert("librevenge:mime-type", aMimeType.toUtf8().getStr()); + maCoverImages.append(aCoverImageProperties); + } + + FindXMPMetadata(mxContext, rURL, aFilterData, maMetaData); + + mxUriReferenceFactory = uri::UriReferenceFactory::create(mxContext); +} + +const librevenge::RVNGPropertyListVector& XMLImport::GetCoverImages() const +{ + return maCoverImages; +} + +const librevenge::RVNGPropertyList& XMLImport::GetMetaData() const { return maMetaData; } + +namespace +{ +/// Finds out if a file URL exists. +bool FileURLExists(const OUString& rURL) +{ + SvFileStream aStream(rURL, StreamMode::READ); + return aStream.IsOpen(); +} +} + +PopupState XMLImport::FillPopupData(const OUString& rURL, librevenge::RVNGPropertyList& rPropList) +{ + uno::Reference xUriRef; + try + { + xUriRef = mxUriReferenceFactory->parse(rURL); + } + catch (const uno::Exception&) + { + DBG_UNHANDLED_EXCEPTION("writerperfect", "XUriReference::parse() failed"); + } + bool bAbsolute = true; + if (xUriRef.is()) + bAbsolute = xUriRef->isAbsolute(); + if (bAbsolute) + return PopupState::NotConsumed; + + // Default case: relative URL, popup data was in the same directory as the + // document at insertion time. + OUString aAbs = maMediaDir + rURL; + if (!FileURLExists(aAbs)) + // Fallback case: relative URL, popup data was in the default media + // directory at insertion time. + aAbs = maMediaDir + "../" + rURL; + + if (!FileURLExists(aAbs)) + // Relative link, but points to non-existing file: don't emit that to + // librevenge, since it will be invalid anyway. + return PopupState::Ignore; + + SvFileStream aStream(aAbs, StreamMode::READ); + librevenge::RVNGBinaryData aBinaryData; + SvMemoryStream aMemoryStream; + aMemoryStream.WriteStream(aStream); + aBinaryData.append(static_cast(aMemoryStream.GetData()), + aMemoryStream.GetSize()); + rPropList.insert("office:binary-data", aBinaryData); + + INetURLObject aAbsURL(aAbs); + OUString aMimeType = GetMimeType(aAbsURL.GetFileExtension()); + rPropList.insert("librevenge:mime-type", aMimeType.toUtf8().getStr()); + + return PopupState::Consumed; +} + +const std::vector& XMLImport::GetPageMetafiles() const { return mrPageMetafiles; } + +const uno::Reference& XMLImport::GetComponentContext() const +{ + return mxContext; +} + +rtl::Reference +XMLImport::CreateContext(const OUString& rName, + const uno::Reference& /*xAttribs*/) +{ + if (rName == "office:document") + return new XMLOfficeDocContext(*this); + return nullptr; +} + +librevenge::RVNGTextInterface& XMLImport::GetGenerator() const { return mrGenerator; } + +std::map& XMLImport::GetAutomaticTextStyles() +{ + return maAutomaticTextStyles; +} + +std::map& XMLImport::GetAutomaticParagraphStyles() +{ + return maAutomaticParagraphStyles; +} + +std::map& XMLImport::GetAutomaticCellStyles() +{ + return maAutomaticCellStyles; +} + +std::map& XMLImport::GetAutomaticColumnStyles() +{ + return maAutomaticColumnStyles; +} + +std::map& XMLImport::GetAutomaticRowStyles() +{ + return maAutomaticRowStyles; +} + +std::map& XMLImport::GetAutomaticTableStyles() +{ + return maAutomaticTableStyles; +} + +std::map& XMLImport::GetAutomaticGraphicStyles() +{ + return maAutomaticGraphicStyles; +} + +std::map& XMLImport::GetTextStyles() +{ + return maTextStyles; +} + +std::map& XMLImport::GetParagraphStyles() +{ + return maParagraphStyles; +} + +std::map& XMLImport::GetCellStyles() +{ + return maCellStyles; +} + +std::map& XMLImport::GetColumnStyles() +{ + return maColumnStyles; +} + +std::map& XMLImport::GetRowStyles() { return maRowStyles; } + +std::map& XMLImport::GetTableStyles() +{ + return maTableStyles; +} + +std::map& XMLImport::GetGraphicStyles() +{ + return maGraphicStyles; +} + +std::map& XMLImport::GetPageLayouts() +{ + return maPageLayouts; +} + +std::map& XMLImport::GetMasterStyles() +{ + return maMasterStyles; +} + +void XMLImport::startDocument() { mrGenerator.startDocument(librevenge::RVNGPropertyList()); } + +void XMLImport::endDocument() { mrGenerator.endDocument(); } + +void XMLImport::startElement(const OUString& rName, + const uno::Reference& xAttribs) +{ + rtl::Reference xContext; + if (!maContexts.empty()) + { + if (maContexts.top().is()) + xContext = maContexts.top()->CreateChildContext(rName, xAttribs); + } + else + xContext = CreateContext(rName, xAttribs); + + if (xContext.is()) + xContext->startElement(rName, xAttribs); + + maContexts.push(xContext); +} + +void XMLImport::endElement(const OUString& rName) +{ + if (maContexts.empty()) + return; + + if (maContexts.top().is()) + maContexts.top()->endElement(rName); + + maContexts.pop(); +} + +void XMLImport::characters(const OUString& rChars) +{ + if (maContexts.top().is()) + maContexts.top()->characters(rChars); +} + +void XMLImport::ignorableWhitespace(const OUString& /*rWhitespaces*/) {} + +void XMLImport::processingInstruction(const OUString& /*rTarget*/, const OUString& /*rData*/) {} + +void XMLImport::setDocumentLocator(const uno::Reference& /*xLocator*/) {} + +void XMLImport::HandlePageSpan(const librevenge::RVNGPropertyList& rPropertyList) +{ + OUString sMasterPageName; + OUString sLayoutName; + + if (rPropertyList["style:master-page-name"]) + sMasterPageName = OStringToOUString( + rPropertyList["style:master-page-name"]->getStr().cstr(), RTL_TEXTENCODING_UTF8); + else if (!GetIsInPageSpan()) + sMasterPageName = "Standard"; + + if (sMasterPageName.getLength()) + { + librevenge::RVNGPropertyList& rMasterPage = GetMasterStyles()[sMasterPageName]; + if (rMasterPage["style:page-layout-name"]) + { + sLayoutName = OStringToOUString(rMasterPage["style:page-layout-name"]->getStr().cstr(), + RTL_TEXTENCODING_UTF8); + } + } + + if (sLayoutName.getLength()) + { + librevenge::RVNGPropertyList& rPageLayout = GetPageLayouts()[sLayoutName]; + + if (GetIsInPageSpan()) + GetGenerator().closePageSpan(); + + GetGenerator().openPageSpan(rPageLayout); + mbIsInPageSpan = true; + } +} + +} // namespace writerperfect + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/writerperfect/source/writer/exp/xmlimp.hxx b/writerperfect/source/writer/exp/xmlimp.hxx new file mode 100644 index 000000000..6994be472 --- /dev/null +++ b/writerperfect/source/writer/exp/xmlimp.hxx @@ -0,0 +1,161 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef INCLUDED_WRITERPERFECT_SOURCE_WRITER_EXP_XMLIMP_HXX +#define INCLUDED_WRITERPERFECT_SOURCE_WRITER_EXP_XMLIMP_HXX + +#include +#include +#include + +#include + +#include + +#include +#include +#include + +#include "xmlictxt.hxx" + +namespace com +{ +namespace sun +{ +namespace star +{ +namespace beans +{ +struct PropertyValue; +} +namespace uno +{ +class XComponentContext; +} +namespace uri +{ +class XUriReferenceFactory; +} +} +} +} + +namespace writerperfect +{ +namespace exp +{ +class XMLImportContext; + +/// Contains info about a fixed-layout page. +struct FixedLayoutPage +{ + css::uno::Sequence aMetafile; + Size aCssPixels; + std::vector aChapterNames; +}; + +/// States describing the result of a link -> popup conversion. +enum class PopupState +{ + /// Conversion did not happen yet. + NONE, + /// The relative link was converted to a popup. + Consumed, + /// The absolute link was not handled. + NotConsumed, + /// The relative link is invalid and should be ignored. + Ignore +}; + +/// ODT export feeds this class to make librevenge calls. +class XMLImport : public cppu::WeakImplHelper +{ + librevenge::RVNGTextInterface& mrGenerator; + std::stack> maContexts; + std::map maAutomaticTextStyles; + std::map maTextStyles; + std::map maAutomaticParagraphStyles; + std::map maParagraphStyles; + std::map maAutomaticCellStyles; + std::map maCellStyles; + std::map maAutomaticColumnStyles; + std::map maColumnStyles; + std::map maAutomaticRowStyles; + std::map maRowStyles; + std::map maAutomaticTableStyles; + std::map maTableStyles; + std::map maAutomaticGraphicStyles; + std::map maGraphicStyles; + std::map maPageLayouts; + std::map maMasterStyles; + librevenge::RVNGPropertyListVector maCoverImages; + /// Author, date, etc -- overwrites what would be from the document out of the box. + librevenge::RVNGPropertyList maMetaData; + const css::uno::Reference& mxContext; + css::uno::Reference mxUriReferenceFactory; + OUString maMediaDir; + bool mbIsInPageSpan; + const std::vector& mrPageMetafiles; + +public: + XMLImport(const css::uno::Reference& xContext, + librevenge::RVNGTextInterface& rGenerator, const OUString& rURL, + const css::uno::Sequence& rDescriptor, + const std::vector& rPageMetafiles); + + rtl::Reference + CreateContext(const OUString& rName, + const css::uno::Reference& xAttribs); + + librevenge::RVNGTextInterface& GetGenerator() const; + std::map& GetAutomaticTextStyles(); + std::map& GetAutomaticParagraphStyles(); + std::map& GetAutomaticCellStyles(); + std::map& GetAutomaticColumnStyles(); + std::map& GetAutomaticRowStyles(); + std::map& GetAutomaticTableStyles(); + std::map& GetAutomaticGraphicStyles(); + std::map& GetTextStyles(); + std::map& GetParagraphStyles(); + std::map& GetCellStyles(); + std::map& GetColumnStyles(); + std::map& GetRowStyles(); + std::map& GetTableStyles(); + std::map& GetGraphicStyles(); + std::map& GetPageLayouts(); + std::map& GetMasterStyles(); + const librevenge::RVNGPropertyListVector& GetCoverImages() const; + const librevenge::RVNGPropertyList& GetMetaData() const; + PopupState FillPopupData(const OUString& rURL, librevenge::RVNGPropertyList& rPropList); + const std::vector& GetPageMetafiles() const; + const css::uno::Reference& GetComponentContext() const; + + bool GetIsInPageSpan() const { return mbIsInPageSpan; } + void HandlePageSpan(const librevenge::RVNGPropertyList& rPropertyList); + + // XDocumentHandler + void SAL_CALL startDocument() override; + void SAL_CALL endDocument() override; + void SAL_CALL + startElement(const OUString& rName, + const css::uno::Reference& xAttribs) override; + void SAL_CALL endElement(const OUString& rName) override; + void SAL_CALL characters(const OUString& rChars) override; + void SAL_CALL ignorableWhitespace(const OUString& rWhitespaces) override; + void SAL_CALL processingInstruction(const OUString& rTarget, const OUString& rData) override; + void SAL_CALL + setDocumentLocator(const css::uno::Reference& xLocator) override; +}; + +} // namespace exp +} // namespace writerperfect + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/writerperfect/source/writer/exp/xmlmetai.cxx b/writerperfect/source/writer/exp/xmlmetai.cxx new file mode 100644 index 000000000..2e42f740f --- /dev/null +++ b/writerperfect/source/writer/exp/xmlmetai.cxx @@ -0,0 +1,285 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "xmlmetai.hxx" + +#include "xmlimp.hxx" + +using namespace com::sun::star; + +namespace writerperfect::exp +{ +namespace +{ +/// Handler for . +class XMLDcTitleContext : public XMLImportContext +{ +public: + XMLDcTitleContext(XMLImport& rImport, XMLMetaDocumentContext& rMeta); + + void SAL_CALL characters(const OUString& rChars) override; + +private: + XMLMetaDocumentContext& mrMeta; +}; +} + +XMLDcTitleContext::XMLDcTitleContext(XMLImport& rImport, XMLMetaDocumentContext& rMeta) + : XMLImportContext(rImport) + , mrMeta(rMeta) +{ +} + +void XMLDcTitleContext::characters(const OUString& rChars) +{ + OString sCharU8 = OUStringToOString(rChars, RTL_TEXTENCODING_UTF8); + if (!mrMeta.GetPropertyList()["dc:title"]) + mrMeta.GetPropertyList().insert("dc:title", librevenge::RVNGString(sCharU8.getStr())); +} + +namespace +{ +/// Handler for . +class XMLDcLanguageContext : public XMLImportContext +{ +public: + XMLDcLanguageContext(XMLImport& rImport, XMLMetaDocumentContext& rMeta); + + void SAL_CALL characters(const OUString& rChars) override; + +private: + XMLMetaDocumentContext& mrMeta; +}; +} + +XMLDcLanguageContext::XMLDcLanguageContext(XMLImport& rImport, XMLMetaDocumentContext& rMeta) + : XMLImportContext(rImport) + , mrMeta(rMeta) +{ +} + +void XMLDcLanguageContext::characters(const OUString& rChars) +{ + OString sCharU8 = OUStringToOString(rChars, RTL_TEXTENCODING_UTF8); + if (!mrMeta.GetPropertyList()["dc:language"]) + mrMeta.GetPropertyList().insert("dc:language", librevenge::RVNGString(sCharU8.getStr())); +} + +namespace +{ +/// Handler for . +class XMLDcDateContext : public XMLImportContext +{ +public: + XMLDcDateContext(XMLImport& rImport, XMLMetaDocumentContext& rMeta); + + void SAL_CALL characters(const OUString& rChars) override; + +private: + XMLMetaDocumentContext& mrMeta; +}; +} + +XMLDcDateContext::XMLDcDateContext(XMLImport& rImport, XMLMetaDocumentContext& rMeta) + : XMLImportContext(rImport) + , mrMeta(rMeta) +{ +} + +void XMLDcDateContext::characters(const OUString& rChars) +{ + OString sCharU8 = OUStringToOString(rChars, RTL_TEXTENCODING_UTF8); + if (!mrMeta.GetPropertyList()["dc:date"]) + mrMeta.GetPropertyList().insert("dc:date", librevenge::RVNGString(sCharU8.getStr())); +} + +namespace +{ +/// Handler for . +class XMLMetaGeneratorContext : public XMLImportContext +{ +public: + XMLMetaGeneratorContext(XMLImport& rImport, XMLMetaDocumentContext& rMeta); + + void SAL_CALL characters(const OUString& rChars) override; + +private: + XMLMetaDocumentContext& mrMeta; +}; +} + +XMLMetaGeneratorContext::XMLMetaGeneratorContext(XMLImport& rImport, XMLMetaDocumentContext& rMeta) + : XMLImportContext(rImport) + , mrMeta(rMeta) +{ +} + +void XMLMetaGeneratorContext::characters(const OUString& rChars) +{ + OString sCharU8 = OUStringToOString(rChars, RTL_TEXTENCODING_UTF8); + mrMeta.GetPropertyList().insert("meta:generator", librevenge::RVNGString(sCharU8.getStr())); +} + +namespace +{ +/// Handler for . +class XMLMetaInitialCreatorContext : public XMLImportContext +{ +public: + XMLMetaInitialCreatorContext(XMLImport& rImport, XMLMetaDocumentContext& rMeta); + + void SAL_CALL characters(const OUString& rChars) override; + +private: + XMLMetaDocumentContext& mrMeta; +}; +} + +XMLMetaInitialCreatorContext::XMLMetaInitialCreatorContext(XMLImport& rImport, + XMLMetaDocumentContext& rMeta) + : XMLImportContext(rImport) + , mrMeta(rMeta) +{ +} + +void XMLMetaInitialCreatorContext::characters(const OUString& rChars) +{ + OString sCharU8 = OUStringToOString(rChars, RTL_TEXTENCODING_UTF8); + if (!mrMeta.GetPropertyList()["meta:initial-creator"]) + mrMeta.GetPropertyList().insert("meta:initial-creator", + librevenge::RVNGString(sCharU8.getStr())); +} + +XMLMetaDocumentContext::XMLMetaDocumentContext(XMLImport& rImport) + : XMLImportContext(rImport) +{ + librevenge::RVNGPropertyList::Iter it(GetImport().GetMetaData()); + for (it.rewind(); it.next();) + m_aPropertyList.insert(it.key(), it()->clone()); + m_aPropertyList.insert("librevenge:cover-images", GetImport().GetCoverImages()); +} + +rtl::Reference XMLMetaDocumentContext::CreateChildContext( + const OUString& rName, const css::uno::Reference& /*xAttribs*/) +{ + if (rName == "dc:title") + return new XMLDcTitleContext(GetImport(), *this); + if (rName == "dc:language") + return new XMLDcLanguageContext(GetImport(), *this); + if (rName == "dc:date") + return new XMLDcDateContext(GetImport(), *this); + if (rName == "meta:generator") + return new XMLMetaGeneratorContext(GetImport(), *this); + if (rName == "meta:initial-creator") + return new XMLMetaInitialCreatorContext(GetImport(), *this); + return nullptr; +} + +void XMLMetaDocumentContext::endElement(const OUString& /*rName*/) +{ + GetImport().GetGenerator().setDocumentMetaData(m_aPropertyList); +} + +XMPParser::XMPParser(librevenge::RVNGPropertyList& rMetaData) + : mrMetaData(rMetaData) +{ +} + +XMPParser::~XMPParser() = default; + +void XMPParser::startDocument() {} + +void XMPParser::endDocument() +{ + if (!mrMetaData["dc:identifier"] && !m_aIdentifier.isEmpty()) + mrMetaData.insert("dc:identifier", m_aIdentifier.toUtf8().getStr()); + if (!mrMetaData["dc:title"] && !m_aTitle.isEmpty()) + mrMetaData.insert("dc:title", m_aTitle.toUtf8().getStr()); + if (!mrMetaData["meta:initial-creator"] && !m_aCreator.isEmpty()) + mrMetaData.insert("meta:initial-creator", m_aCreator.toUtf8().getStr()); + if (!mrMetaData["dc:language"] && !m_aLanguage.isEmpty()) + mrMetaData.insert("dc:language", m_aLanguage.toUtf8().getStr()); + if (!mrMetaData["dc:date"] && !m_aDate.isEmpty()) + mrMetaData.insert("dc:date", m_aDate.toUtf8().getStr()); +} + +void XMPParser::startElement(const OUString& rName, + const uno::Reference& /*xAttribs*/) +{ + if (rName == "dc:identifier") + m_bInIdentifier = true; + else if (rName == "dc:title") + m_bInTitle = true; + else if (rName == "dc:creator") + m_bInCreator = true; + else if (rName == "dc:language") + m_bInLanguage = true; + else if (rName == "dc:date") + m_bInDate = true; + else if (rName == "rdf:li") + { + if (m_bInTitle) + m_bInTitleItem = true; + else if (m_bInCreator) + m_bInCreatorItem = true; + else if (m_bInLanguage) + m_bInLanguageItem = true; + else if (m_bInDate) + m_bInDateItem = true; + } +} + +void XMPParser::endElement(const OUString& rName) +{ + if (rName == "dc:identifier") + m_bInIdentifier = false; + else if (rName == "dc:title") + m_bInTitle = false; + else if (rName == "dc:creator") + m_bInCreator = false; + else if (rName == "dc:language") + m_bInLanguage = false; + else if (rName == "dc:date") + m_bInDate = false; + else if (rName == "rdf:li") + { + if (m_bInTitle) + m_bInTitleItem = false; + else if (m_bInCreator) + m_bInCreatorItem = false; + else if (m_bInLanguage) + m_bInLanguageItem = false; + else if (m_bInDate) + m_bInDateItem = false; + } +} + +void XMPParser::characters(const OUString& rChars) +{ + if (m_bInIdentifier) + m_aIdentifier += rChars; + else if (m_bInTitleItem) + m_aTitle += rChars; + else if (m_bInCreatorItem) + m_aCreator += rChars; + else if (m_bInLanguageItem) + m_aLanguage += rChars; + else if (m_bInDateItem) + m_aDate += rChars; +} + +void XMPParser::ignorableWhitespace(const OUString& /*rWhitespace*/) {} + +void XMPParser::processingInstruction(const OUString& /*rTarget*/, const OUString& /*rData*/) {} + +void XMPParser::setDocumentLocator(const uno::Reference& /*xLocator*/) {} + +} // namespace writerperfect::exp + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/writerperfect/source/writer/exp/xmlmetai.hxx b/writerperfect/source/writer/exp/xmlmetai.hxx new file mode 100644 index 000000000..1f3e0d774 --- /dev/null +++ b/writerperfect/source/writer/exp/xmlmetai.hxx @@ -0,0 +1,89 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef INCLUDED_WRITERPERFECT_SOURCE_WRITER_EXP_XMLMETAI_HXX +#define INCLUDED_WRITERPERFECT_SOURCE_WRITER_EXP_XMLMETAI_HXX + +#include + +#include "xmlictxt.hxx" + +namespace writerperfect +{ +namespace exp +{ +/// Handler for . +class XMLMetaDocumentContext : public XMLImportContext +{ +public: + XMLMetaDocumentContext(XMLImport& rImport); + + librevenge::RVNGPropertyList& GetPropertyList() { return m_aPropertyList; } + + rtl::Reference + CreateChildContext(const OUString& rName, + const css::uno::Reference& xAttribs) override; + + void SAL_CALL endElement(const OUString& rName) override; + +private: + librevenge::RVNGPropertyList m_aPropertyList; +}; + +/// Parses an XMP file. +class XMPParser : public cppu::WeakImplHelper +{ +public: + explicit XMPParser(librevenge::RVNGPropertyList& rMetaData); + ~XMPParser() override; + + // XDocumentHandler + void SAL_CALL startDocument() override; + + void SAL_CALL endDocument() override; + + void SAL_CALL + startElement(const OUString& rName, + const css::uno::Reference& xAttribs) override; + + void SAL_CALL endElement(const OUString& rName) override; + + void SAL_CALL characters(const OUString& rChars) override; + + void SAL_CALL ignorableWhitespace(const OUString& aWhitespaces) override; + + void SAL_CALL processingInstruction(const OUString& aTarget, const OUString& aData) override; + + void SAL_CALL + setDocumentLocator(const css::uno::Reference& xLocator) override; + +private: + librevenge::RVNGPropertyList& mrMetaData; + bool m_bInIdentifier = false; + OUString m_aIdentifier; + bool m_bInTitle = false; + bool m_bInTitleItem = false; + OUString m_aTitle; + bool m_bInCreator = false; + bool m_bInCreatorItem = false; + OUString m_aCreator; + bool m_bInLanguage = false; + bool m_bInLanguageItem = false; + OUString m_aLanguage; + bool m_bInDate = false; + bool m_bInDateItem = false; + OUString m_aDate; +}; + +} // namespace exp +} // namespace writerperfect + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/writerperfect/source/writer/exp/xmltbli.cxx b/writerperfect/source/writer/exp/xmltbli.cxx new file mode 100644 index 000000000..0e5818f0b --- /dev/null +++ b/writerperfect/source/writer/exp/xmltbli.cxx @@ -0,0 +1,254 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "xmltbli.hxx" + +#include "txtparai.hxx" +#include "xmlimp.hxx" +#include "xmltext.hxx" + +#include + +using namespace com::sun::star; + +namespace writerperfect::exp +{ +namespace +{ +/// Handler for . +class XMLTableRowContext : public XMLImportContext +{ +public: + XMLTableRowContext(XMLImport& rImport); + + rtl::Reference + CreateChildContext(const OUString& rName, + const css::uno::Reference& xAttribs) override; + int GetColumn() const; + void SetColumn(int nColumn); + + void SAL_CALL + startElement(const OUString& rName, + const css::uno::Reference& xAttribs) override; + void SAL_CALL endElement(const OUString& rName) override; + +private: + int m_nColumn = 0; +}; + +/// Handler for . +class XMLTableCellContext : public XMLImportContext +{ +public: + XMLTableCellContext(XMLImport& rImport, XMLTableRowContext& rRow); + + rtl::Reference + CreateChildContext(const OUString& rName, + const css::uno::Reference& xAttribs) override; + + void SAL_CALL + startElement(const OUString& rName, + const css::uno::Reference& xAttribs) override; + void SAL_CALL endElement(const OUString& rName) override; + +private: + XMLTableRowContext& m_rRow; +}; +} + +XMLTableCellContext::XMLTableCellContext(XMLImport& rImport, XMLTableRowContext& rRow) + : XMLImportContext(rImport) + , m_rRow(rRow) +{ +} + +rtl::Reference XMLTableCellContext::CreateChildContext( + const OUString& rName, const css::uno::Reference& /*xAttribs*/) +{ + return CreateTextChildContext(GetImport(), rName); +} + +void XMLTableCellContext::startElement( + const OUString& /*rName*/, const css::uno::Reference& xAttribs) +{ + librevenge::RVNGPropertyList aPropertyList; + for (sal_Int16 i = 0; i < xAttribs->getLength(); ++i) + { + const OUString& rAttributeName = xAttribs->getNameByIndex(i); + const OUString& rAttributeValue = xAttribs->getValueByIndex(i); + + if (rAttributeName == "table:style-name") + FillStyles(rAttributeValue, GetImport().GetAutomaticCellStyles(), + GetImport().GetCellStyles(), aPropertyList); + else + { + OString sName = OUStringToOString(rAttributeName, RTL_TEXTENCODING_UTF8); + OString sValue = OUStringToOString(rAttributeValue, RTL_TEXTENCODING_UTF8); + aPropertyList.insert(sName.getStr(), sValue.getStr()); + } + } + aPropertyList.insert("librevenge:column", m_rRow.GetColumn()); + GetImport().GetGenerator().openTableCell(aPropertyList); + m_rRow.SetColumn(m_rRow.GetColumn() + 1); +} + +void XMLTableCellContext::endElement(const OUString& /*rName*/) +{ + GetImport().GetGenerator().closeTableCell(); +} + +namespace +{ +/// Handler for . +class XMLTableColumnContext : public XMLImportContext +{ +public: + XMLTableColumnContext(XMLImport& rImport, librevenge::RVNGPropertyListVector& rColumns); + + void SAL_CALL + startElement(const OUString& rName, + const css::uno::Reference& xAttribs) override; + +private: + librevenge::RVNGPropertyListVector& m_rColumns; +}; +} + +XMLTableColumnContext::XMLTableColumnContext(XMLImport& rImport, + librevenge::RVNGPropertyListVector& rColumns) + : XMLImportContext(rImport) + , m_rColumns(rColumns) +{ +} + +void XMLTableColumnContext::startElement( + const OUString& /*rName*/, const css::uno::Reference& xAttribs) +{ + librevenge::RVNGPropertyList aPropertyList; + for (sal_Int16 i = 0; i < xAttribs->getLength(); ++i) + { + const OUString& rAttributeName = xAttribs->getNameByIndex(i); + const OUString& rAttributeValue = xAttribs->getValueByIndex(i); + + if (rAttributeName == "table:style-name") + FillStyles(rAttributeValue, GetImport().GetAutomaticColumnStyles(), + GetImport().GetColumnStyles(), aPropertyList); + } + m_rColumns.append(aPropertyList); +} + +XMLTableRowContext::XMLTableRowContext(XMLImport& rImport) + : XMLImportContext(rImport) +{ +} + +rtl::Reference XMLTableRowContext::CreateChildContext( + const OUString& rName, const css::uno::Reference& /*xAttribs*/) +{ + if (rName == "table:table-cell") + return new XMLTableCellContext(GetImport(), *this); + if (rName == "table:covered-table-cell") + { + ++m_nColumn; + GetImport().GetGenerator().insertCoveredTableCell(librevenge::RVNGPropertyList()); + } + else + SAL_WARN("writerperfect", "XMLTableRowContext::CreateChildContext: unhandled " << rName); + return nullptr; +} + +void XMLTableRowContext::startElement( + const OUString& /*rName*/, const css::uno::Reference& xAttribs) +{ + librevenge::RVNGPropertyList aPropertyList; + for (sal_Int16 i = 0; i < xAttribs->getLength(); ++i) + { + const OUString& rAttributeName = xAttribs->getNameByIndex(i); + const OUString& rAttributeValue = xAttribs->getValueByIndex(i); + + if (rAttributeName == "table:style-name") + FillStyles(rAttributeValue, GetImport().GetAutomaticRowStyles(), + GetImport().GetRowStyles(), aPropertyList); + } + GetImport().GetGenerator().openTableRow(aPropertyList); +} + +void XMLTableRowContext::endElement(const OUString& /*rName*/) +{ + GetImport().GetGenerator().closeTableRow(); +} + +int XMLTableRowContext::GetColumn() const { return m_nColumn; } + +void XMLTableRowContext::SetColumn(int nColumn) { m_nColumn = nColumn; } + +XMLTableContext::XMLTableContext(XMLImport& rImport, bool bTopLevel) + : XMLImportContext(rImport) + , m_bTopLevel(bTopLevel) +{ +} + +rtl::Reference XMLTableContext::CreateChildContext( + const OUString& rName, const css::uno::Reference& /*xAttribs*/) +{ + if (rName == "table:table-column") + // Make sure columns are parsed before we open the table. + return new XMLTableColumnContext(GetImport(), m_aColumns); + + if (!m_bTableOpened) + { + if (!m_aColumns.empty()) + m_aPropertyList.insert("librevenge:table-columns", m_aColumns); + GetImport().GetGenerator().openTable(m_aPropertyList); + m_bTableOpened = true; + } + + if (rName == "table:table-row") + return new XMLTableRowContext(GetImport()); + + SAL_WARN("writerperfect", "XMLTableContext::CreateChildContext: unhandled " << rName); + + return nullptr; +} + +void XMLTableContext::startElement( + const OUString& /*rName*/, const css::uno::Reference& xAttribs) +{ + for (sal_Int16 i = 0; i < xAttribs->getLength(); ++i) + { + const OUString& rAttributeName = xAttribs->getNameByIndex(i); + const OUString& rAttributeValue = xAttribs->getValueByIndex(i); + + if (rAttributeName == "table:style-name") + { + FillStyles(rAttributeValue, GetImport().GetAutomaticTableStyles(), + GetImport().GetTableStyles(), m_aPropertyList); + if (m_bTopLevel) + GetImport().HandlePageSpan(m_aPropertyList); + } + else + { + OString sName = OUStringToOString(rAttributeName, RTL_TEXTENCODING_UTF8); + OString sValue = OUStringToOString(rAttributeValue, RTL_TEXTENCODING_UTF8); + m_aPropertyList.insert(sName.getStr(), sValue.getStr()); + } + } +} + +void XMLTableContext::endElement(const OUString& /*rName*/) +{ + if (m_bTableOpened) + { + GetImport().GetGenerator().closeTable(); + } +} + +} // namespace writerperfect::exp + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/writerperfect/source/writer/exp/xmltbli.hxx b/writerperfect/source/writer/exp/xmltbli.hxx new file mode 100644 index 000000000..dff4dda2f --- /dev/null +++ b/writerperfect/source/writer/exp/xmltbli.hxx @@ -0,0 +1,50 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef INCLUDED_WRITERPERFECT_SOURCE_WRITER_EXP_XMLTBLI_HXX +#define INCLUDED_WRITERPERFECT_SOURCE_WRITER_EXP_XMLTBLI_HXX + +#include + +#include "xmlictxt.hxx" + +namespace writerperfect +{ +namespace exp +{ +/// Handler for . +class XMLTableContext : public XMLImportContext +{ +public: + XMLTableContext(XMLImport& rImport, bool bTopLevel = false); + + rtl::Reference + CreateChildContext(const OUString& rName, + const css::uno::Reference& xAttribs) override; + + void SAL_CALL + startElement(const OUString& rName, + const css::uno::Reference& xAttribs) override; + void SAL_CALL endElement(const OUString& rName) override; + +private: + bool m_bTableOpened = false; + /// If the context is a direct child of XMLBodyContentContext. + /// Only direct child of XMLBodyContentContext has to handle page span. + bool m_bTopLevel; + librevenge::RVNGPropertyList m_aPropertyList; + librevenge::RVNGPropertyListVector m_aColumns; +}; + +} // namespace exp +} // namespace writerperfect + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/writerperfect/source/writer/exp/xmltext.cxx b/writerperfect/source/writer/exp/xmltext.cxx new file mode 100644 index 000000000..01e185c43 --- /dev/null +++ b/writerperfect/source/writer/exp/xmltext.cxx @@ -0,0 +1,55 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "xmltext.hxx" + +#include "txtparai.hxx" +#include "xmltbli.hxx" +#include "XMLSectionContext.hxx" +#include "XMLTextListContext.hxx" +#include "xmlimp.hxx" + +using namespace com::sun::star; + +namespace writerperfect::exp +{ +XMLBodyContentContext::XMLBodyContentContext(XMLImport& rImport) + : XMLImportContext(rImport) +{ +} + +void XMLBodyContentContext::endElement(const OUString& /*rName*/) +{ + if (GetImport().GetIsInPageSpan()) + GetImport().GetGenerator().closePageSpan(); +} + +rtl::Reference XMLBodyContentContext::CreateChildContext( + const OUString& rName, const css::uno::Reference& /*xAttribs*/) +{ + return CreateTextChildContext(GetImport(), rName, true); +} + +rtl::Reference CreateTextChildContext(XMLImport& rImport, const OUString& rName, + bool bTopLevel) +{ + if (rName == "text:p" || rName == "text:h") + return new XMLParaContext(rImport, bTopLevel); + if (rName == "text:section") + return new XMLSectionContext(rImport); + if (rName == "table:table") + return new XMLTableContext(rImport, bTopLevel); + if (rName == "text:list") + return new XMLTextListContext(rImport); + return nullptr; +} + +} // namespace writerperfect::exp + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/writerperfect/source/writer/exp/xmltext.hxx b/writerperfect/source/writer/exp/xmltext.hxx new file mode 100644 index 000000000..756a7ddbc --- /dev/null +++ b/writerperfect/source/writer/exp/xmltext.hxx @@ -0,0 +1,40 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef INCLUDED_WRITERPERFECT_SOURCE_WRITER_EXP_XMLTEXT_HXX +#define INCLUDED_WRITERPERFECT_SOURCE_WRITER_EXP_XMLTEXT_HXX + +#include "xmlictxt.hxx" + +namespace writerperfect +{ +namespace exp +{ +/// Handler for . +class XMLBodyContentContext : public XMLImportContext +{ +public: + XMLBodyContentContext(XMLImport& rImport); + + rtl::Reference CreateChildContext( + const OUString& rName, + const css::uno::Reference& /*xAttribs*/) override; + void SAL_CALL endElement(const OUString& rName) override; +}; + +/// Context factory for body text, section, table cell, etc. +rtl::Reference CreateTextChildContext(XMLImport& rImport, const OUString& rName, + bool bTopLevel = false); + +} // namespace exp +} // namespace writerperfect + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ -- cgit v1.2.3