summaryrefslogtreecommitdiffstats
path: root/writerperfect/source/writer/exp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--writerperfect/source/writer/exp/XMLBase64ImportContext.cxx65
-rw-r--r--writerperfect/source/writer/exp/XMLBase64ImportContext.hxx42
-rw-r--r--writerperfect/source/writer/exp/XMLFootnoteImportContext.cxx126
-rw-r--r--writerperfect/source/writer/exp/XMLFootnoteImportContext.hxx40
-rw-r--r--writerperfect/source/writer/exp/XMLSectionContext.cxx44
-rw-r--r--writerperfect/source/writer/exp/XMLSectionContext.hxx33
-rw-r--r--writerperfect/source/writer/exp/XMLTextFrameContext.cxx171
-rw-r--r--writerperfect/source/writer/exp/XMLTextFrameContext.hxx38
-rw-r--r--writerperfect/source/writer/exp/XMLTextListContext.cxx33
-rw-r--r--writerperfect/source/writer/exp/XMLTextListContext.hxx29
-rw-r--r--writerperfect/source/writer/exp/XMLTextListItemContext.cxx36
-rw-r--r--writerperfect/source/writer/exp/XMLTextListItemContext.hxx29
-rw-r--r--writerperfect/source/writer/exp/txtparai.cxx634
-rw-r--r--writerperfect/source/writer/exp/txtparai.hxx59
-rw-r--r--writerperfect/source/writer/exp/txtstyli.cxx415
-rw-r--r--writerperfect/source/writer/exp/txtstyli.hxx60
-rw-r--r--writerperfect/source/writer/exp/xmlfmt.cxx295
-rw-r--r--writerperfect/source/writer/exp/xmlfmt.hxx73
-rw-r--r--writerperfect/source/writer/exp/xmlictxt.cxx56
-rw-r--r--writerperfect/source/writer/exp/xmlictxt.hxx51
-rw-r--r--writerperfect/source/writer/exp/xmlimp.cxx621
-rw-r--r--writerperfect/source/writer/exp/xmlimp.hxx149
-rw-r--r--writerperfect/source/writer/exp/xmlmetai.cxx285
-rw-r--r--writerperfect/source/writer/exp/xmlmetai.hxx83
-rw-r--r--writerperfect/source/writer/exp/xmltbli.cxx254
-rw-r--r--writerperfect/source/writer/exp/xmltbli.hxx44
-rw-r--r--writerperfect/source/writer/exp/xmltext.cxx55
-rw-r--r--writerperfect/source/writer/exp/xmltext.hxx34
28 files changed, 3854 insertions, 0 deletions
diff --git a/writerperfect/source/writer/exp/XMLBase64ImportContext.cxx b/writerperfect/source/writer/exp/XMLBase64ImportContext.cxx
new file mode 100644
index 000000000..a7780e2d5
--- /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 <comphelper/base64.hxx>
+
+using namespace com::sun::star;
+
+namespace writerperfect::exp
+{
+XMLBase64ImportContext::XMLBase64ImportContext(XMLImport& rImport)
+ : XMLImportContext(rImport)
+{
+}
+
+void XMLBase64ImportContext::startElement(
+ const OUString& /*rName*/,
+ const css::uno::Reference<css::xml::sax::XAttributeList>& /*xAttribs*/)
+{
+}
+
+void XMLBase64ImportContext::endElement(const OUString& /*rName*/)
+{
+ m_aBinaryData.append(static_cast<const unsigned char*>(m_aStream.GetData()),
+ m_aStream.GetSize());
+}
+
+void XMLBase64ImportContext::characters(const OUString& rChars)
+{
+ OUString aTrimmedChars(rChars.trim());
+
+ if (aTrimmedChars.isEmpty())
+ return;
+
+ OUString aChars;
+ if (!m_aBase64CharsLeft.isEmpty())
+ {
+ aChars = m_aBase64CharsLeft + aTrimmedChars;
+ m_aBase64CharsLeft.clear();
+ }
+ else
+ aChars = aTrimmedChars;
+
+ uno::Sequence<sal_Int8> 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..59558746f
--- /dev/null
+++ b/writerperfect/source/writer/exp/XMLBase64ImportContext.hxx
@@ -0,0 +1,42 @@
+/* -*- 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/.
+ */
+
+#pragma once
+
+#include <librevenge/RVNGBinaryData.h>
+
+#include <tools/stream.hxx>
+
+#include "xmlictxt.hxx"
+
+namespace writerperfect::exp
+{
+/// Handler for <office:binary-data>.
+class XMLBase64ImportContext : public XMLImportContext
+{
+public:
+ XMLBase64ImportContext(XMLImport& rImport);
+
+ void SAL_CALL
+ startElement(const OUString& rName,
+ const css::uno::Reference<css::xml::sax::XAttributeList>& 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 writerperfect::exp
+
+/* 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 <sal/log.hxx>
+
+using namespace com::sun::star;
+
+namespace writerperfect::exp
+{
+namespace
+{
+/// Handler for <text:note-citation>.
+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 <text:note-body>.
+class XMLFootnoteBodyImportContext : public XMLImportContext
+{
+public:
+ XMLFootnoteBodyImportContext(XMLImport& rImport,
+ const librevenge::RVNGPropertyList& rProperties);
+
+ rtl::Reference<XMLImportContext>
+ CreateChildContext(const OUString& rName,
+ const css::uno::Reference<css::xml::sax::XAttributeList>& xAttribs) override;
+
+ void SAL_CALL
+ startElement(const OUString& rName,
+ const css::uno::Reference<css::xml::sax::XAttributeList>& 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<XMLImportContext> XMLFootnoteBodyImportContext::CreateChildContext(
+ const OUString& rName, const css::uno::Reference<css::xml::sax::XAttributeList>& /*xAttribs*/)
+{
+ return CreateTextChildContext(GetImport(), rName);
+}
+
+void XMLFootnoteBodyImportContext::startElement(
+ const OUString& /*rName*/,
+ const css::uno::Reference<css::xml::sax::XAttributeList>& /*xAttribs*/)
+{
+ GetImport().GetGenerator().openFootnote(m_rProperties);
+}
+
+void XMLFootnoteBodyImportContext::endElement(const OUString& /*rName*/)
+{
+ GetImport().GetGenerator().closeFootnote();
+}
+
+XMLFootnoteImportContext::XMLFootnoteImportContext(XMLImport& rImport)
+ : XMLImportContext(rImport)
+{
+}
+
+rtl::Reference<XMLImportContext> XMLFootnoteImportContext::CreateChildContext(
+ const OUString& rName, const css::uno::Reference<css::xml::sax::XAttributeList>& /*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<css::xml::sax::XAttributeList>& /*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..50011d388
--- /dev/null
+++ b/writerperfect/source/writer/exp/XMLFootnoteImportContext.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/.
+ */
+
+#pragma once
+
+#include <librevenge/librevenge.h>
+
+#include <rtl/ref.hxx>
+
+#include "xmlictxt.hxx"
+
+namespace writerperfect::exp
+{
+/// Handler for <text:note>.
+class XMLFootnoteImportContext : public XMLImportContext
+{
+public:
+ XMLFootnoteImportContext(XMLImport& rImport);
+
+ rtl::Reference<XMLImportContext>
+ CreateChildContext(const OUString& rName,
+ const css::uno::Reference<css::xml::sax::XAttributeList>& xAttribs) override;
+
+ void SAL_CALL
+ startElement(const OUString& rName,
+ const css::uno::Reference<css::xml::sax::XAttributeList>& xAttribs) override;
+
+private:
+ librevenge::RVNGPropertyList m_aProperties;
+};
+
+} // namespace writerperfect::exp
+
+/* 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<XMLImportContext> XMLSectionContext::CreateChildContext(
+ const OUString& rName, const css::uno::Reference<css::xml::sax::XAttributeList>& /*xAttribs*/)
+{
+ return CreateTextChildContext(GetImport(), rName);
+}
+
+void XMLSectionContext::startElement(
+ const OUString& /*rName*/,
+ const css::uno::Reference<css::xml::sax::XAttributeList>& /*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..6a1f1e58a
--- /dev/null
+++ b/writerperfect/source/writer/exp/XMLSectionContext.hxx
@@ -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/.
+ */
+
+#pragma once
+
+#include "xmlictxt.hxx"
+
+namespace writerperfect::exp
+{
+/// Handler for <text:section>.
+class XMLSectionContext : public XMLImportContext
+{
+public:
+ XMLSectionContext(XMLImport& rImport);
+
+ rtl::Reference<XMLImportContext>
+ CreateChildContext(const OUString& rName,
+ const css::uno::Reference<css::xml::sax::XAttributeList>& xAttribs) override;
+ void SAL_CALL
+ startElement(const OUString& rName,
+ const css::uno::Reference<css::xml::sax::XAttributeList>& xAttribs) override;
+ void SAL_CALL endElement(const OUString& rName) override;
+};
+
+} // namespace writerperfect::exp
+
+/* 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..4c6ca118e
--- /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 <sal/log.hxx>
+
+using namespace com::sun::star;
+
+namespace writerperfect::exp
+{
+namespace
+{
+/// Handler for <draw:text-box>.
+class XMLTextBoxContext : public XMLImportContext
+{
+public:
+ XMLTextBoxContext(XMLImport& rImport);
+
+ rtl::Reference<XMLImportContext>
+ CreateChildContext(const OUString& rName,
+ const css::uno::Reference<css::xml::sax::XAttributeList>& xAttribs) override;
+
+ void SAL_CALL
+ startElement(const OUString& rName,
+ const css::uno::Reference<css::xml::sax::XAttributeList>& xAttribs) override;
+ void SAL_CALL endElement(const OUString& rName) override;
+};
+}
+
+XMLTextBoxContext::XMLTextBoxContext(XMLImport& rImport)
+ : XMLImportContext(rImport)
+{
+}
+
+rtl::Reference<XMLImportContext> XMLTextBoxContext::CreateChildContext(
+ const OUString& rName, const css::uno::Reference<css::xml::sax::XAttributeList>& /*xAttribs*/)
+{
+ return CreateTextChildContext(GetImport(), rName);
+}
+
+void XMLTextBoxContext::startElement(
+ const OUString& /*rName*/,
+ const css::uno::Reference<css::xml::sax::XAttributeList>& /*xAttribs*/)
+{
+ GetImport().GetGenerator().openTextBox(librevenge::RVNGPropertyList());
+}
+
+void XMLTextBoxContext::endElement(const OUString& /*rName*/)
+{
+ GetImport().GetGenerator().closeTextBox();
+}
+
+namespace
+{
+/// Handler for <draw:image>.
+class XMLTextImageContext : public XMLImportContext
+{
+public:
+ XMLTextImageContext(XMLImport& rImport);
+
+ rtl::Reference<XMLImportContext>
+ CreateChildContext(const OUString& rName,
+ const css::uno::Reference<css::xml::sax::XAttributeList>& xAttribs) override;
+
+ void SAL_CALL
+ startElement(const OUString& rName,
+ const css::uno::Reference<css::xml::sax::XAttributeList>& xAttribs) override;
+ void SAL_CALL endElement(const OUString& rName) override;
+
+private:
+ OString m_aMimeType;
+ rtl::Reference<XMLBase64ImportContext> m_xBinaryData;
+};
+}
+
+XMLTextImageContext::XMLTextImageContext(XMLImport& rImport)
+ : XMLImportContext(rImport)
+{
+}
+
+rtl::Reference<XMLImportContext> XMLTextImageContext::CreateChildContext(
+ const OUString& rName, const css::uno::Reference<css::xml::sax::XAttributeList>& /*xAttribs*/)
+{
+ if (rName == "office:binary-data")
+ {
+ m_xBinaryData = new XMLBase64ImportContext(GetImport());
+ return m_xBinaryData;
+ }
+ return nullptr;
+}
+
+void XMLTextImageContext::startElement(
+ const OUString& /*rName*/, const css::uno::Reference<css::xml::sax::XAttributeList>& 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<XMLImportContext> XMLTextFrameContext::CreateChildContext(
+ const OUString& rName, const css::uno::Reference<css::xml::sax::XAttributeList>& /*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<css::xml::sax::XAttributeList>& 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..9c58849e6
--- /dev/null
+++ b/writerperfect/source/writer/exp/XMLTextFrameContext.hxx
@@ -0,0 +1,38 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#pragma once
+
+#include <rtl/ref.hxx>
+
+#include "xmlictxt.hxx"
+
+namespace writerperfect::exp
+{
+class XMLBase64ImportContext;
+
+/// Handler for <draw:frame>.
+class XMLTextFrameContext : public XMLImportContext
+{
+public:
+ XMLTextFrameContext(XMLImport& rImport);
+
+ rtl::Reference<XMLImportContext>
+ CreateChildContext(const OUString& rName,
+ const css::uno::Reference<css::xml::sax::XAttributeList>& xAttribs) override;
+
+ void SAL_CALL
+ startElement(const OUString& rName,
+ const css::uno::Reference<css::xml::sax::XAttributeList>& xAttribs) override;
+ void SAL_CALL endElement(const OUString& rName) override;
+};
+
+} // namespace writerperfect::exp
+
+/* 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<XMLImportContext> XMLTextListContext::CreateChildContext(
+ const OUString& rName, const css::uno::Reference<css::xml::sax::XAttributeList>& /*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..8a384d7ba
--- /dev/null
+++ b/writerperfect/source/writer/exp/XMLTextListContext.hxx
@@ -0,0 +1,29 @@
+/* -*- 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/.
+ */
+
+#pragma once
+
+#include "xmlictxt.hxx"
+
+namespace writerperfect::exp
+{
+/// Handler for <text:list>.
+class XMLTextListContext : public XMLImportContext
+{
+public:
+ XMLTextListContext(XMLImport& rImport);
+
+ rtl::Reference<XMLImportContext>
+ CreateChildContext(const OUString& rName,
+ const css::uno::Reference<css::xml::sax::XAttributeList>& xAttribs) override;
+};
+
+} // namespace writerperfect::exp
+
+/* 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<XMLImportContext> XMLTextListItemContext::CreateChildContext(
+ const OUString& rName, const css::uno::Reference<css::xml::sax::XAttributeList>& /*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..2f17194d4
--- /dev/null
+++ b/writerperfect/source/writer/exp/XMLTextListItemContext.hxx
@@ -0,0 +1,29 @@
+/* -*- 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/.
+ */
+
+#pragma once
+
+#include "xmlictxt.hxx"
+
+namespace writerperfect::exp
+{
+/// Handler for <text:list-item>.
+class XMLTextListItemContext : public XMLImportContext
+{
+public:
+ XMLTextListItemContext(XMLImport& rImport);
+
+ rtl::Reference<XMLImportContext>
+ CreateChildContext(const OUString& rName,
+ const css::uno::Reference<css::xml::sax::XAttributeList>& xAttribs) override;
+};
+
+} // namespace writerperfect::exp
+
+/* 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..101546c39
--- /dev/null
+++ b/writerperfect/source/writer/exp/txtparai.cxx
@@ -0,0 +1,634 @@
+/* -*- 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 <sal/config.h>
+
+#include "txtparai.hxx"
+
+#include <string_view>
+
+#include "XMLFootnoteImportContext.hxx"
+#include "XMLTextFrameContext.hxx"
+#include "xmlimp.hxx"
+
+#include <sal/log.hxx>
+
+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<OUString, librevenge::RVNGPropertyList>& rStyles,
+ std::map<OUString, librevenge::RVNGPropertyList>& rAutomaticStyles,
+ std::map<OUString, librevenge::RVNGPropertyList>& 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 (std::string_view("style:parent-style-name") != itProp.key())
+ rPropertyList.insert(itProp.key(), itProp()->clone());
+ }
+}
+}
+
+namespace writerperfect::exp
+{
+namespace
+{
+/// Handler for <text:sequence>.
+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 <text:span>.
+class XMLSpanContext : public XMLImportContext
+{
+public:
+ XMLSpanContext(XMLImport& rImport, const librevenge::RVNGPropertyList& rPropertyList);
+
+ rtl::Reference<XMLImportContext>
+ CreateChildContext(const OUString& rName,
+ const css::uno::Reference<css::xml::sax::XAttributeList>& xAttribs) override;
+
+ void SAL_CALL
+ startElement(const OUString& rName,
+ const css::uno::Reference<css::xml::sax::XAttributeList>& 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<XMLImportContext> XMLSpanContext::CreateChildContext(
+ const OUString& rName, const css::uno::Reference<css::xml::sax::XAttributeList>& /*xAttribs*/)
+{
+ return CreateParagraphOrSpanChildContext(GetImport(), rName, m_aPropertyList);
+}
+
+void XMLSpanContext::startElement(
+ const OUString& /*rName*/, const css::uno::Reference<css::xml::sax::XAttributeList>& 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 <text:ruby>.
+class XMLRubyContext : public XMLImportContext
+{
+public:
+ XMLRubyContext(XMLImport& rImport, const librevenge::RVNGPropertyList& rPropertyList);
+
+ rtl::Reference<XMLImportContext>
+ CreateChildContext(const OUString& rName,
+ const css::uno::Reference<css::xml::sax::XAttributeList>& 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 <text:ruby-text>.
+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 <text:ruby-base>.
+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<XMLImportContext> XMLRubyContext::CreateChildContext(
+ const OUString& rName, const css::uno::Reference<css::xml::sax::XAttributeList>& /*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 <text:line-break>.
+class XMLLineBreakContext : public XMLCharContext
+{
+public:
+ XMLLineBreakContext(XMLImport& rImport, const librevenge::RVNGPropertyList& rPropertyList);
+
+ void SAL_CALL
+ startElement(const OUString& rName,
+ const css::uno::Reference<css::xml::sax::XAttributeList>& xAttribs) override;
+};
+}
+
+XMLLineBreakContext::XMLLineBreakContext(XMLImport& rImport,
+ const librevenge::RVNGPropertyList& rPropertyList)
+ : XMLCharContext(rImport, rPropertyList)
+{
+}
+
+void XMLLineBreakContext::startElement(
+ const OUString& /*rName*/,
+ const css::uno::Reference<css::xml::sax::XAttributeList>& /*xAttribs*/)
+{
+ GetImport().GetGenerator().openSpan(GetPropertyList());
+ GetImport().GetGenerator().insertLineBreak();
+ GetImport().GetGenerator().closeSpan();
+}
+
+namespace
+{
+/// Handler for <text:s>.
+class XMLSpaceContext : public XMLCharContext
+{
+public:
+ XMLSpaceContext(XMLImport& rImport, const librevenge::RVNGPropertyList& rPropertyList);
+
+ void SAL_CALL
+ startElement(const OUString& rName,
+ const css::uno::Reference<css::xml::sax::XAttributeList>& xAttribs) override;
+};
+}
+
+XMLSpaceContext::XMLSpaceContext(XMLImport& rImport,
+ const librevenge::RVNGPropertyList& rPropertyList)
+ : XMLCharContext(rImport, rPropertyList)
+{
+}
+
+void XMLSpaceContext::startElement(
+ const OUString& /*rName*/,
+ const css::uno::Reference<css::xml::sax::XAttributeList>& /*xAttribs*/)
+{
+ GetImport().GetGenerator().openSpan(GetPropertyList());
+ GetImport().GetGenerator().insertSpace();
+ GetImport().GetGenerator().closeSpan();
+}
+
+namespace
+{
+/// Handler for <text:tab>.
+class XMLTabContext : public XMLCharContext
+{
+public:
+ XMLTabContext(XMLImport& rImport, const librevenge::RVNGPropertyList& rPropertyList);
+
+ void SAL_CALL
+ startElement(const OUString& rName,
+ const css::uno::Reference<css::xml::sax::XAttributeList>& xAttribs) override;
+};
+}
+
+XMLTabContext::XMLTabContext(XMLImport& rImport, const librevenge::RVNGPropertyList& rPropertyList)
+ : XMLCharContext(rImport, rPropertyList)
+{
+}
+
+void XMLTabContext::startElement(
+ const OUString& /*rName*/,
+ const css::uno::Reference<css::xml::sax::XAttributeList>& /*xAttribs*/)
+{
+ GetImport().GetGenerator().openSpan(GetPropertyList());
+ GetImport().GetGenerator().insertTab();
+ GetImport().GetGenerator().closeSpan();
+}
+
+namespace
+{
+/// Handler for <draw:a>.
+class XMLTextFrameHyperlinkContext : public XMLImportContext
+{
+public:
+ XMLTextFrameHyperlinkContext(XMLImport& rImport,
+ const librevenge::RVNGPropertyList& rPropertyList);
+ rtl::Reference<XMLImportContext>
+ CreateChildContext(const OUString& rName,
+ const css::uno::Reference<css::xml::sax::XAttributeList>& xAttribs) override;
+
+ void SAL_CALL
+ startElement(const OUString& rName,
+ const css::uno::Reference<css::xml::sax::XAttributeList>& 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<XMLImportContext> XMLTextFrameHyperlinkContext::CreateChildContext(
+ const OUString& rName, const css::uno::Reference<css::xml::sax::XAttributeList>& /*xAttribs*/)
+{
+ return CreateParagraphOrSpanChildContext(GetImport(), rName, m_aPropertyList);
+}
+
+void XMLTextFrameHyperlinkContext::startElement(
+ const OUString& /*rName*/, const css::uno::Reference<css::xml::sax::XAttributeList>& 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 <text:a>.
+class XMLHyperlinkContext : public XMLImportContext
+{
+public:
+ XMLHyperlinkContext(XMLImport& rImport, const librevenge::RVNGPropertyList& rPropertyList);
+ rtl::Reference<XMLImportContext>
+ CreateChildContext(const OUString& rName,
+ const css::uno::Reference<css::xml::sax::XAttributeList>& xAttribs) override;
+
+ void SAL_CALL
+ startElement(const OUString& rName,
+ const css::uno::Reference<css::xml::sax::XAttributeList>& 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<XMLImportContext> XMLHyperlinkContext::CreateChildContext(
+ const OUString& rName, const css::uno::Reference<css::xml::sax::XAttributeList>& /*xAttribs*/)
+{
+ return CreateParagraphOrSpanChildContext(GetImport(), rName, m_aPropertyList);
+}
+
+void XMLHyperlinkContext::startElement(
+ const OUString& /*rName*/, const css::uno::Reference<css::xml::sax::XAttributeList>& 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<XMLImportContext> XMLParaContext::CreateChildContext(
+ const OUString& rName, const css::uno::Reference<css::xml::sax::XAttributeList>& /*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<css::xml::sax::XAttributeList>& 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<XMLImportContext>
+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<OUString, librevenge::RVNGPropertyList>& rAutomaticStyles,
+ std::map<OUString, librevenge::RVNGPropertyList>& 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..e759dc8f5
--- /dev/null
+++ b/writerperfect/source/writer/exp/txtparai.hxx
@@ -0,0 +1,59 @@
+/* -*- 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/.
+ */
+
+#pragma once
+
+#include <map>
+
+#include <librevenge/librevenge.h>
+
+#include "xmlictxt.hxx"
+
+namespace writerperfect::exp
+{
+/// Handler for <text:p>/<text:h>.
+class XMLParaContext : public XMLImportContext
+{
+public:
+ XMLParaContext(XMLImport& rImport, bool bTopLevel = false);
+
+ rtl::Reference<XMLImportContext> CreateChildContext(
+ const OUString& rName,
+ const css::uno::Reference<css::xml::sax::XAttributeList>& /*xAttribs*/) override;
+
+ void SAL_CALL
+ startElement(const OUString& rName,
+ const css::uno::Reference<css::xml::sax::XAttributeList>& 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<XMLImportContext>
+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<OUString, librevenge::RVNGPropertyList>& rAutomaticStyles,
+ std::map<OUString, librevenge::RVNGPropertyList>& rNamedStyles,
+ librevenge::RVNGPropertyList& rPropertyList);
+
+} // namespace writerperfect::exp
+
+/* 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 <style:paragraph-properties>.
+class XMLParagraphPropertiesContext : public XMLImportContext
+{
+public:
+ XMLParagraphPropertiesContext(XMLImport& rImport, XMLStyleContext& rStyle);
+
+ void SAL_CALL
+ startElement(const OUString& rName,
+ const css::uno::Reference<css::xml::sax::XAttributeList>& 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<css::xml::sax::XAttributeList>& 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 <style:text-properties>.
+class XMLTextPropertiesContext : public XMLImportContext
+{
+public:
+ XMLTextPropertiesContext(XMLImport& rImport, XMLStyleContext& rStyle);
+
+ void SAL_CALL
+ startElement(const OUString& rName,
+ const css::uno::Reference<css::xml::sax::XAttributeList>& 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<css::xml::sax::XAttributeList>& 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 <style:graphic-properties>.
+class XMLGraphicPropertiesContext : public XMLImportContext
+{
+public:
+ XMLGraphicPropertiesContext(XMLImport& rImport, XMLStyleContext& rStyle);
+
+ void SAL_CALL
+ startElement(const OUString& rName,
+ const css::uno::Reference<css::xml::sax::XAttributeList>& 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<css::xml::sax::XAttributeList>& 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 <style:page-layout-properties>.
+class XMLPageLayoutPropertiesContext : public XMLImportContext
+{
+public:
+ XMLPageLayoutPropertiesContext(XMLImport& rImport, XMLStyleContext& rStyle);
+
+ void SAL_CALL
+ startElement(const OUString& rName,
+ const css::uno::Reference<css::xml::sax::XAttributeList>& 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<css::xml::sax::XAttributeList>& 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 <style:table-properties>.
+class XMLTablePropertiesContext : public XMLImportContext
+{
+public:
+ XMLTablePropertiesContext(XMLImport& rImport, XMLStyleContext& rStyle);
+
+ void SAL_CALL
+ startElement(const OUString& rName,
+ const css::uno::Reference<css::xml::sax::XAttributeList>& 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<css::xml::sax::XAttributeList>& 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 <style:table-row-properties>.
+class XMLTableRowPropertiesContext : public XMLImportContext
+{
+public:
+ XMLTableRowPropertiesContext(XMLImport& rImport, XMLStyleContext& rStyle);
+
+ void SAL_CALL
+ startElement(const OUString& rName,
+ const css::uno::Reference<css::xml::sax::XAttributeList>& 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<css::xml::sax::XAttributeList>& 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 <style:table-column-properties>.
+class XMLTableColumnPropertiesContext : public XMLImportContext
+{
+public:
+ XMLTableColumnPropertiesContext(XMLImport& rImport, XMLStyleContext& rStyle);
+
+ void SAL_CALL
+ startElement(const OUString& rName,
+ const css::uno::Reference<css::xml::sax::XAttributeList>& 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<css::xml::sax::XAttributeList>& 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 <style:table-cell-properties>.
+class XMLTableCellPropertiesContext : public XMLImportContext
+{
+public:
+ XMLTableCellPropertiesContext(XMLImport& rImport, XMLStyleContext& rStyle);
+
+ void SAL_CALL
+ startElement(const OUString& rName,
+ const css::uno::Reference<css::xml::sax::XAttributeList>& 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<css::xml::sax::XAttributeList>& 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<XMLImportContext> XMLStyleContext::CreateChildContext(
+ const OUString& rName, const css::uno::Reference<css::xml::sax::XAttributeList>& /*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<css::xml::sax::XAttributeList>& 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..9247619bc
--- /dev/null
+++ b/writerperfect/source/writer/exp/txtstyli.hxx
@@ -0,0 +1,60 @@
+/* -*- 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/.
+ */
+
+#pragma once
+
+#include <librevenge/librevenge.h>
+
+#include "xmlictxt.hxx"
+
+namespace writerperfect::exp
+{
+class XMLStylesContext;
+
+/// Handler for <style:style>.
+class XMLStyleContext : public XMLImportContext
+{
+public:
+ XMLStyleContext(XMLImport& rImport, XMLStylesContext& rStyles);
+
+ rtl::Reference<XMLImportContext>
+ CreateChildContext(const OUString& rName,
+ const css::uno::Reference<css::xml::sax::XAttributeList>& xAttribs) override;
+ void SAL_CALL
+ startElement(const OUString& rName,
+ const css::uno::Reference<css::xml::sax::XAttributeList>& 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 writerperfect::exp
+
+/* 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..4ac70b85a
--- /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 <sal/log.hxx>
+
+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<XMLImportContext> XMLStylesContext::CreateChildContext(
+ const OUString& rName, const css::uno::Reference<css::xml::sax::XAttributeList>& /*xAttribs*/)
+{
+ if (rName == "style:style" || rName == "style:page-layout" || rName == "style:master-page")
+ return new XMLStyleContext(GetImport(), *this);
+ return nullptr;
+}
+
+std::map<OUString, librevenge::RVNGPropertyList>& XMLStylesContext::GetCurrentParagraphStyles()
+{
+ return m_rParagraphStyles;
+}
+
+std::map<OUString, librevenge::RVNGPropertyList>& XMLStylesContext::GetCurrentTextStyles()
+{
+ return m_rTextStyles;
+}
+
+std::map<OUString, librevenge::RVNGPropertyList>& XMLStylesContext::GetCurrentCellStyles()
+{
+ return m_rCellStyles;
+}
+
+std::map<OUString, librevenge::RVNGPropertyList>& XMLStylesContext::GetCurrentColumnStyles()
+{
+ return m_rColumnStyles;
+}
+
+std::map<OUString, librevenge::RVNGPropertyList>& XMLStylesContext::GetCurrentRowStyles()
+{
+ return m_rRowStyles;
+}
+
+std::map<OUString, librevenge::RVNGPropertyList>& XMLStylesContext::GetCurrentTableStyles()
+{
+ return m_rTableStyles;
+}
+
+std::map<OUString, librevenge::RVNGPropertyList>& XMLStylesContext::GetCurrentGraphicStyles()
+{
+ return m_rGraphicStyles;
+}
+
+std::map<OUString, librevenge::RVNGPropertyList>& XMLStylesContext::GetCurrentPageLayouts()
+{
+ return m_rPageLayouts;
+}
+
+std::map<OUString, librevenge::RVNGPropertyList>& XMLStylesContext::GetCurrentMasterStyles()
+{
+ return m_rMasterStyles;
+}
+
+namespace
+{
+/// Handler for <style:font-face>.
+class XMLFontFaceContext : public XMLImportContext
+{
+public:
+ XMLFontFaceContext(XMLImport& rImport);
+ void SAL_CALL
+ startElement(const OUString& rName,
+ const css::uno::Reference<css::xml::sax::XAttributeList>& xAttribs) override;
+
+ rtl::Reference<XMLImportContext>
+ CreateChildContext(const OUString& rName,
+ const css::uno::Reference<css::xml::sax::XAttributeList>& xAttribs) override;
+
+ OUString const& GetName() const { return maName; }
+
+private:
+ OUString maName;
+};
+
+/// Handler for <svg:font-face-src>.
+class XMLFontFaceSrcContext : public XMLImportContext
+{
+public:
+ XMLFontFaceSrcContext(XMLImport& rImport, XMLFontFaceContext& rFontFace);
+
+ rtl::Reference<XMLImportContext>
+ CreateChildContext(const OUString& rName,
+ const css::uno::Reference<css::xml::sax::XAttributeList>& xAttribs) override;
+
+private:
+ XMLFontFaceContext& mrFontFace;
+};
+
+/// Handler for <svg:font-face-uri>.
+class XMLFontFaceUriContext : public XMLImportContext
+{
+public:
+ XMLFontFaceUriContext(XMLImport& rImport, XMLFontFaceContext const& rFontFace);
+ void SAL_CALL
+ startElement(const OUString& rName,
+ const css::uno::Reference<css::xml::sax::XAttributeList>& xAttribs) override;
+ void SAL_CALL endElement(const OUString& rName) override;
+
+ rtl::Reference<XMLImportContext>
+ CreateChildContext(const OUString& rName,
+ const css::uno::Reference<css::xml::sax::XAttributeList>& xAttribs) override;
+
+ librevenge::RVNGPropertyList& GetPropertyList() { return maPropertyList; }
+
+private:
+ librevenge::RVNGPropertyList maPropertyList;
+ rtl::Reference<XMLBase64ImportContext> mxBinaryData;
+};
+
+/// Handler for <svg:font-face-format>.
+class XMLFontFaceFormatContext : public XMLImportContext
+{
+public:
+ XMLFontFaceFormatContext(XMLImport& rImport, XMLFontFaceUriContext& rFontFaceUri);
+ void SAL_CALL
+ startElement(const OUString& rName,
+ const css::uno::Reference<css::xml::sax::XAttributeList>& 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<css::xml::sax::XAttributeList>& 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<css::xml::sax::XAttributeList>& 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<XMLImportContext> XMLFontFaceUriContext::CreateChildContext(
+ const OUString& rName, const css::uno::Reference<css::xml::sax::XAttributeList>& /*xAttribs*/)
+{
+ if (rName == "office:binary-data")
+ {
+ mxBinaryData = new XMLBase64ImportContext(GetImport());
+ return mxBinaryData;
+ }
+ 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<XMLImportContext> XMLFontFaceSrcContext::CreateChildContext(
+ const OUString& rName, const css::uno::Reference<css::xml::sax::XAttributeList>& /*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<css::xml::sax::XAttributeList>& 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<XMLImportContext> XMLFontFaceContext::CreateChildContext(
+ const OUString& rName, const css::uno::Reference<css::xml::sax::XAttributeList>& /*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<XMLImportContext> XMLFontFaceDeclsContext::CreateChildContext(
+ const OUString& rName, const css::uno::Reference<css::xml::sax::XAttributeList>& /*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..22849be7e
--- /dev/null
+++ b/writerperfect/source/writer/exp/xmlfmt.hxx
@@ -0,0 +1,73 @@
+/* -*- 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/.
+ */
+
+#pragma once
+
+#include <map>
+
+#include "xmlictxt.hxx"
+
+namespace librevenge
+{
+class RVNGPropertyList;
+}
+
+namespace writerperfect::exp
+{
+/// Handler for <office:automatic-styles>/<office:styles>.
+class XMLStylesContext : public XMLImportContext
+{
+public:
+ enum StyleType
+ {
+ StyleType_NONE,
+ StyleType_AUTOMATIC
+ };
+ XMLStylesContext(XMLImport& rImport, StyleType eType);
+
+ rtl::Reference<XMLImportContext>
+ CreateChildContext(const OUString& rName,
+ const css::uno::Reference<css::xml::sax::XAttributeList>& xAttribs) override;
+
+ std::map<OUString, librevenge::RVNGPropertyList>& GetCurrentParagraphStyles();
+ std::map<OUString, librevenge::RVNGPropertyList>& GetCurrentTextStyles();
+ std::map<OUString, librevenge::RVNGPropertyList>& GetCurrentCellStyles();
+ std::map<OUString, librevenge::RVNGPropertyList>& GetCurrentColumnStyles();
+ std::map<OUString, librevenge::RVNGPropertyList>& GetCurrentRowStyles();
+ std::map<OUString, librevenge::RVNGPropertyList>& GetCurrentTableStyles();
+ std::map<OUString, librevenge::RVNGPropertyList>& GetCurrentGraphicStyles();
+ std::map<OUString, librevenge::RVNGPropertyList>& GetCurrentPageLayouts();
+ std::map<OUString, librevenge::RVNGPropertyList>& GetCurrentMasterStyles();
+
+private:
+ std::map<OUString, librevenge::RVNGPropertyList>& m_rParagraphStyles;
+ std::map<OUString, librevenge::RVNGPropertyList>& m_rTextStyles;
+ std::map<OUString, librevenge::RVNGPropertyList>& m_rCellStyles;
+ std::map<OUString, librevenge::RVNGPropertyList>& m_rColumnStyles;
+ std::map<OUString, librevenge::RVNGPropertyList>& m_rRowStyles;
+ std::map<OUString, librevenge::RVNGPropertyList>& m_rTableStyles;
+ std::map<OUString, librevenge::RVNGPropertyList>& m_rGraphicStyles;
+ std::map<OUString, librevenge::RVNGPropertyList>& m_rPageLayouts;
+ std::map<OUString, librevenge::RVNGPropertyList>& m_rMasterStyles;
+};
+
+/// Handler for <office:font-face-decls>.
+class XMLFontFaceDeclsContext : public XMLImportContext
+{
+public:
+ XMLFontFaceDeclsContext(XMLImport& rImport);
+
+ rtl::Reference<XMLImportContext>
+ CreateChildContext(const OUString& rName,
+ const css::uno::Reference<css::xml::sax::XAttributeList>& xAttribs) override;
+};
+
+} // namespace writerperfect::exp
+
+/* 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> XMLImportContext::CreateChildContext(
+ const OUString& rName, const css::uno::Reference<css::xml::sax::XAttributeList>& xAttribs)
+{
+ return mrImport.CreateContext(rName, xAttribs);
+}
+
+void XMLImportContext::startDocument() {}
+
+void XMLImportContext::endDocument() {}
+
+void XMLImportContext::startElement(
+ const OUString& /*rName*/,
+ const css::uno::Reference<css::xml::sax::XAttributeList>& /*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<css::xml::sax::XLocator>& /*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..dc05449d3
--- /dev/null
+++ b/writerperfect/source/writer/exp/xmlictxt.hxx
@@ -0,0 +1,51 @@
+/* -*- 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/.
+ */
+
+#pragma once
+
+#include <com/sun/star/xml/sax/XDocumentHandler.hpp>
+
+#include <cppuhelper/implbase.hxx>
+#include <rtl/ref.hxx>
+
+namespace writerperfect::exp
+{
+class XMLImport;
+
+/// Base class for a handler of a single XML element during ODF -> librevenge conversion.
+class XMLImportContext : public cppu::WeakImplHelper<css::xml::sax::XDocumentHandler>
+{
+public:
+ XMLImportContext(XMLImport& rImport);
+ XMLImport& GetImport() { return mrImport; }
+
+ virtual rtl::Reference<XMLImportContext>
+ CreateChildContext(const OUString& rName,
+ const css::uno::Reference<css::xml::sax::XAttributeList>& xAttribs);
+
+ // XDocumentHandler
+ void SAL_CALL startDocument() override;
+ void SAL_CALL endDocument() override;
+ void SAL_CALL
+ startElement(const OUString& rName,
+ const css::uno::Reference<css::xml::sax::XAttributeList>& 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<css::xml::sax::XLocator>& xLocator) override;
+
+private:
+ XMLImport& mrImport;
+};
+
+} // namespace writerperfect::exp
+
+/* 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..ae7b33518
--- /dev/null
+++ b/writerperfect/source/writer/exp/xmlimp.cxx
@@ -0,0 +1,621 @@
+/* -*- 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 <sal/config.h>
+
+#include "xmlimp.hxx"
+
+#include <string_view>
+
+#include <initializer_list>
+#include <unordered_map>
+
+#include <com/sun/star/svg/XSVGWriter.hpp>
+#include <com/sun/star/uri/UriReferenceFactory.hpp>
+#include <com/sun/star/xml/sax/InputSource.hpp>
+#include <com/sun/star/xml/sax/Parser.hpp>
+#include <com/sun/star/xml/sax/Writer.hpp>
+#include <comphelper/propertyvalue.hxx>
+#include <rtl/uri.hxx>
+#include <tools/gen.hxx>
+#include <tools/stream.hxx>
+#include <tools/urlobj.hxx>
+#include <unotools/streamwrap.hxx>
+#include <tools/diagnose_ex.h>
+
+#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<OUString, OUString> 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<beans::PropertyValue>& 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<beans::PropertyValue>& 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<std::u16string_view> vExtensions
+ = { u"gif", u"jpg", u"png", u"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(OUString(rExtension));
+ // File exists.
+ return aRet;
+ }
+
+ aRet.clear();
+ }
+ }
+
+ return aRet;
+}
+
+/// Picks up XMP metadata from the base directory.
+void FindXMPMetadata(const uno::Reference<uno::XComponentContext>& xContext,
+ const OUString& rDocumentBaseURL,
+ const uno::Sequence<beans::PropertyValue>& 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<io::XInputStream> xStream(new utl::OStreamWrapper(aStream));
+ aInputSource.aInputStream = xStream;
+ uno::Reference<xml::sax::XParser> xParser = xml::sax::Parser::create(xContext);
+ rtl::Reference<XMPParser> xXMP(new XMPParser(rMetaData));
+ xParser->setDocumentHandler(xXMP);
+ try
+ {
+ xParser->parseStream(aInputSource);
+ }
+ catch (const uno::Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("writerperfect", "parseStream() failed");
+ return;
+ }
+}
+
+/// Handler for <office:body>.
+class XMLBodyContext : public XMLImportContext
+{
+public:
+ XMLBodyContext(XMLImport& rImport);
+
+ rtl::Reference<XMLImportContext>
+ CreateChildContext(const OUString& rName,
+ const uno::Reference<xml::sax::XAttributeList>& /*xAttribs*/) override;
+};
+}
+
+XMLBodyContext::XMLBodyContext(XMLImport& rImport)
+ : XMLImportContext(rImport)
+{
+}
+
+rtl::Reference<XMLImportContext>
+XMLBodyContext::CreateChildContext(const OUString& rName,
+ const uno::Reference<xml::sax::XAttributeList>& /*xAttribs*/)
+{
+ if (rName == "office:text")
+ return new XMLBodyContentContext(GetImport());
+ return nullptr;
+}
+
+namespace
+{
+/// Handler for <office:document>.
+class XMLOfficeDocContext : public XMLImportContext
+{
+public:
+ XMLOfficeDocContext(XMLImport& rImport);
+
+ rtl::Reference<XMLImportContext>
+ CreateChildContext(const OUString& rName,
+ const uno::Reference<xml::sax::XAttributeList>& /*xAttribs*/) override;
+
+ // Handles metafile for a single page.
+ void HandleFixedLayoutPage(const FixedLayoutPage& rPage, bool bFirst);
+};
+}
+
+XMLOfficeDocContext::XMLOfficeDocContext(XMLImport& rImport)
+ : XMLImportContext(rImport)
+{
+}
+
+rtl::Reference<XMLImportContext> XMLOfficeDocContext::CreateChildContext(
+ const OUString& rName, const uno::Reference<xml::sax::XAttributeList>& /*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<uno::XComponentContext> xCtx = GetImport().GetComponentContext();
+ uno::Reference<xml::sax::XWriter> xSaxWriter = xml::sax::Writer::create(xCtx);
+ if (!xSaxWriter.is())
+ return;
+
+ // [-loplugin:redundantfcast] false positive:
+ uno::Sequence<uno::Any> aArguments = { uno::Any(uno::Sequence<beans::PropertyValue>(
+ { comphelper::makePropertyValue("DTDString", false) })) };
+ uno::Reference<svg::XSVGWriter> 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<const unsigned char*>(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<uno::XComponentContext>& xContext,
+ librevenge::RVNGTextInterface& rGenerator, const OUString& rURL,
+ const uno::Sequence<beans::PropertyValue>& rDescriptor,
+ const std::vector<FixedLayoutPage>& rPageMetafiles)
+ : mrGenerator(rGenerator)
+ , mxContext(xContext)
+ , mbIsInPageSpan(false)
+ , mrPageMetafiles(rPageMetafiles)
+{
+ uno::Sequence<beans::PropertyValue> 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<const unsigned char*>(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<uri::XUriReference> 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<const unsigned char*>(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<FixedLayoutPage>& XMLImport::GetPageMetafiles() const { return mrPageMetafiles; }
+
+const uno::Reference<uno::XComponentContext>& XMLImport::GetComponentContext() const
+{
+ return mxContext;
+}
+
+rtl::Reference<XMLImportContext>
+XMLImport::CreateContext(std::u16string_view rName,
+ const uno::Reference<xml::sax::XAttributeList>& /*xAttribs*/)
+{
+ if (rName == u"office:document")
+ return new XMLOfficeDocContext(*this);
+ return nullptr;
+}
+
+librevenge::RVNGTextInterface& XMLImport::GetGenerator() const { return mrGenerator; }
+
+std::map<OUString, librevenge::RVNGPropertyList>& XMLImport::GetAutomaticTextStyles()
+{
+ return maAutomaticTextStyles;
+}
+
+std::map<OUString, librevenge::RVNGPropertyList>& XMLImport::GetAutomaticParagraphStyles()
+{
+ return maAutomaticParagraphStyles;
+}
+
+std::map<OUString, librevenge::RVNGPropertyList>& XMLImport::GetAutomaticCellStyles()
+{
+ return maAutomaticCellStyles;
+}
+
+std::map<OUString, librevenge::RVNGPropertyList>& XMLImport::GetAutomaticColumnStyles()
+{
+ return maAutomaticColumnStyles;
+}
+
+std::map<OUString, librevenge::RVNGPropertyList>& XMLImport::GetAutomaticRowStyles()
+{
+ return maAutomaticRowStyles;
+}
+
+std::map<OUString, librevenge::RVNGPropertyList>& XMLImport::GetAutomaticTableStyles()
+{
+ return maAutomaticTableStyles;
+}
+
+std::map<OUString, librevenge::RVNGPropertyList>& XMLImport::GetAutomaticGraphicStyles()
+{
+ return maAutomaticGraphicStyles;
+}
+
+std::map<OUString, librevenge::RVNGPropertyList>& XMLImport::GetTextStyles()
+{
+ return maTextStyles;
+}
+
+std::map<OUString, librevenge::RVNGPropertyList>& XMLImport::GetParagraphStyles()
+{
+ return maParagraphStyles;
+}
+
+std::map<OUString, librevenge::RVNGPropertyList>& XMLImport::GetCellStyles()
+{
+ return maCellStyles;
+}
+
+std::map<OUString, librevenge::RVNGPropertyList>& XMLImport::GetColumnStyles()
+{
+ return maColumnStyles;
+}
+
+std::map<OUString, librevenge::RVNGPropertyList>& XMLImport::GetRowStyles() { return maRowStyles; }
+
+std::map<OUString, librevenge::RVNGPropertyList>& XMLImport::GetTableStyles()
+{
+ return maTableStyles;
+}
+
+std::map<OUString, librevenge::RVNGPropertyList>& XMLImport::GetGraphicStyles()
+{
+ return maGraphicStyles;
+}
+
+std::map<OUString, librevenge::RVNGPropertyList>& XMLImport::GetPageLayouts()
+{
+ return maPageLayouts;
+}
+
+std::map<OUString, librevenge::RVNGPropertyList>& 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<xml::sax::XAttributeList>& xAttribs)
+{
+ rtl::Reference<XMLImportContext> 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<xml::sax::XLocator>& /*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..fd2882371
--- /dev/null
+++ b/writerperfect/source/writer/exp/xmlimp.hxx
@@ -0,0 +1,149 @@
+/* -*- 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/.
+ */
+
+#pragma once
+
+#include <map>
+#include <stack>
+#include <vector>
+
+#include <librevenge/librevenge.h>
+
+#include <com/sun/star/xml/sax/XDocumentHandler.hpp>
+
+#include <cppuhelper/implbase.hxx>
+#include <rtl/ref.hxx>
+#include <tools/gen.hxx>
+
+#include "xmlictxt.hxx"
+
+namespace com::sun::star
+{
+namespace beans
+{
+struct PropertyValue;
+}
+namespace uno
+{
+class XComponentContext;
+}
+namespace uri
+{
+class XUriReferenceFactory;
+}
+}
+
+namespace writerperfect::exp
+{
+class XMLImportContext;
+
+/// Contains info about a fixed-layout page.
+struct FixedLayoutPage
+{
+ css::uno::Sequence<sal_Int8> aMetafile;
+ Size aCssPixels;
+ std::vector<OUString> 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<css::xml::sax::XDocumentHandler>
+{
+ librevenge::RVNGTextInterface& mrGenerator;
+ std::stack<rtl::Reference<XMLImportContext>> maContexts;
+ std::map<OUString, librevenge::RVNGPropertyList> maAutomaticTextStyles;
+ std::map<OUString, librevenge::RVNGPropertyList> maTextStyles;
+ std::map<OUString, librevenge::RVNGPropertyList> maAutomaticParagraphStyles;
+ std::map<OUString, librevenge::RVNGPropertyList> maParagraphStyles;
+ std::map<OUString, librevenge::RVNGPropertyList> maAutomaticCellStyles;
+ std::map<OUString, librevenge::RVNGPropertyList> maCellStyles;
+ std::map<OUString, librevenge::RVNGPropertyList> maAutomaticColumnStyles;
+ std::map<OUString, librevenge::RVNGPropertyList> maColumnStyles;
+ std::map<OUString, librevenge::RVNGPropertyList> maAutomaticRowStyles;
+ std::map<OUString, librevenge::RVNGPropertyList> maRowStyles;
+ std::map<OUString, librevenge::RVNGPropertyList> maAutomaticTableStyles;
+ std::map<OUString, librevenge::RVNGPropertyList> maTableStyles;
+ std::map<OUString, librevenge::RVNGPropertyList> maAutomaticGraphicStyles;
+ std::map<OUString, librevenge::RVNGPropertyList> maGraphicStyles;
+ std::map<OUString, librevenge::RVNGPropertyList> maPageLayouts;
+ std::map<OUString, librevenge::RVNGPropertyList> 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<css::uno::XComponentContext>& mxContext;
+ css::uno::Reference<css::uri::XUriReferenceFactory> mxUriReferenceFactory;
+ OUString maMediaDir;
+ bool mbIsInPageSpan;
+ const std::vector<FixedLayoutPage>& mrPageMetafiles;
+
+public:
+ XMLImport(const css::uno::Reference<css::uno::XComponentContext>& xContext,
+ librevenge::RVNGTextInterface& rGenerator, const OUString& rURL,
+ const css::uno::Sequence<css::beans::PropertyValue>& rDescriptor,
+ const std::vector<FixedLayoutPage>& rPageMetafiles);
+
+ rtl::Reference<XMLImportContext>
+ CreateContext(std::u16string_view rName,
+ const css::uno::Reference<css::xml::sax::XAttributeList>& xAttribs);
+
+ librevenge::RVNGTextInterface& GetGenerator() const;
+ std::map<OUString, librevenge::RVNGPropertyList>& GetAutomaticTextStyles();
+ std::map<OUString, librevenge::RVNGPropertyList>& GetAutomaticParagraphStyles();
+ std::map<OUString, librevenge::RVNGPropertyList>& GetAutomaticCellStyles();
+ std::map<OUString, librevenge::RVNGPropertyList>& GetAutomaticColumnStyles();
+ std::map<OUString, librevenge::RVNGPropertyList>& GetAutomaticRowStyles();
+ std::map<OUString, librevenge::RVNGPropertyList>& GetAutomaticTableStyles();
+ std::map<OUString, librevenge::RVNGPropertyList>& GetAutomaticGraphicStyles();
+ std::map<OUString, librevenge::RVNGPropertyList>& GetTextStyles();
+ std::map<OUString, librevenge::RVNGPropertyList>& GetParagraphStyles();
+ std::map<OUString, librevenge::RVNGPropertyList>& GetCellStyles();
+ std::map<OUString, librevenge::RVNGPropertyList>& GetColumnStyles();
+ std::map<OUString, librevenge::RVNGPropertyList>& GetRowStyles();
+ std::map<OUString, librevenge::RVNGPropertyList>& GetTableStyles();
+ std::map<OUString, librevenge::RVNGPropertyList>& GetGraphicStyles();
+ std::map<OUString, librevenge::RVNGPropertyList>& GetPageLayouts();
+ std::map<OUString, librevenge::RVNGPropertyList>& GetMasterStyles();
+ const librevenge::RVNGPropertyListVector& GetCoverImages() const;
+ const librevenge::RVNGPropertyList& GetMetaData() const;
+ PopupState FillPopupData(const OUString& rURL, librevenge::RVNGPropertyList& rPropList);
+ const std::vector<FixedLayoutPage>& GetPageMetafiles() const;
+ const css::uno::Reference<css::uno::XComponentContext>& 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<css::xml::sax::XAttributeList>& 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<css::xml::sax::XLocator>& xLocator) override;
+};
+
+} // namespace writerperfect::exp
+
+/* 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 <dc:title>.
+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 <dc:language>.
+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 <dc:date>.
+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 <meta:generator>.
+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 <meta:initial-creator>.
+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<XMLImportContext> XMLMetaDocumentContext::CreateChildContext(
+ const OUString& rName, const css::uno::Reference<css::xml::sax::XAttributeList>& /*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<xml::sax::XAttributeList>& /*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<xml::sax::XLocator>& /*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..f87ddff24
--- /dev/null
+++ b/writerperfect/source/writer/exp/xmlmetai.hxx
@@ -0,0 +1,83 @@
+/* -*- 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/.
+ */
+
+#pragma once
+
+#include <librevenge/librevenge.h>
+
+#include "xmlictxt.hxx"
+
+namespace writerperfect::exp
+{
+/// Handler for <office:meta>.
+class XMLMetaDocumentContext : public XMLImportContext
+{
+public:
+ XMLMetaDocumentContext(XMLImport& rImport);
+
+ librevenge::RVNGPropertyList& GetPropertyList() { return m_aPropertyList; }
+
+ rtl::Reference<XMLImportContext>
+ CreateChildContext(const OUString& rName,
+ const css::uno::Reference<css::xml::sax::XAttributeList>& xAttribs) override;
+
+ void SAL_CALL endElement(const OUString& rName) override;
+
+private:
+ librevenge::RVNGPropertyList m_aPropertyList;
+};
+
+/// Parses an XMP file.
+class XMPParser : public cppu::WeakImplHelper<css::xml::sax::XDocumentHandler>
+{
+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<css::xml::sax::XAttributeList>& 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<css::xml::sax::XLocator>& 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 writerperfect::exp
+
+/* 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 <sal/log.hxx>
+
+using namespace com::sun::star;
+
+namespace writerperfect::exp
+{
+namespace
+{
+/// Handler for <table:table-row>.
+class XMLTableRowContext : public XMLImportContext
+{
+public:
+ XMLTableRowContext(XMLImport& rImport);
+
+ rtl::Reference<XMLImportContext>
+ CreateChildContext(const OUString& rName,
+ const css::uno::Reference<css::xml::sax::XAttributeList>& xAttribs) override;
+ int GetColumn() const;
+ void SetColumn(int nColumn);
+
+ void SAL_CALL
+ startElement(const OUString& rName,
+ const css::uno::Reference<css::xml::sax::XAttributeList>& xAttribs) override;
+ void SAL_CALL endElement(const OUString& rName) override;
+
+private:
+ int m_nColumn = 0;
+};
+
+/// Handler for <table:cell>.
+class XMLTableCellContext : public XMLImportContext
+{
+public:
+ XMLTableCellContext(XMLImport& rImport, XMLTableRowContext& rRow);
+
+ rtl::Reference<XMLImportContext>
+ CreateChildContext(const OUString& rName,
+ const css::uno::Reference<css::xml::sax::XAttributeList>& xAttribs) override;
+
+ void SAL_CALL
+ startElement(const OUString& rName,
+ const css::uno::Reference<css::xml::sax::XAttributeList>& 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<XMLImportContext> XMLTableCellContext::CreateChildContext(
+ const OUString& rName, const css::uno::Reference<css::xml::sax::XAttributeList>& /*xAttribs*/)
+{
+ return CreateTextChildContext(GetImport(), rName);
+}
+
+void XMLTableCellContext::startElement(
+ const OUString& /*rName*/, const css::uno::Reference<css::xml::sax::XAttributeList>& 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 <table:table-column>.
+class XMLTableColumnContext : public XMLImportContext
+{
+public:
+ XMLTableColumnContext(XMLImport& rImport, librevenge::RVNGPropertyListVector& rColumns);
+
+ void SAL_CALL
+ startElement(const OUString& rName,
+ const css::uno::Reference<css::xml::sax::XAttributeList>& 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<css::xml::sax::XAttributeList>& 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<XMLImportContext> XMLTableRowContext::CreateChildContext(
+ const OUString& rName, const css::uno::Reference<css::xml::sax::XAttributeList>& /*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<css::xml::sax::XAttributeList>& 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<XMLImportContext> XMLTableContext::CreateChildContext(
+ const OUString& rName, const css::uno::Reference<css::xml::sax::XAttributeList>& /*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<css::xml::sax::XAttributeList>& 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..c1b33f498
--- /dev/null
+++ b/writerperfect/source/writer/exp/xmltbli.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/.
+ */
+
+#pragma once
+
+#include <librevenge/librevenge.h>
+
+#include "xmlictxt.hxx"
+
+namespace writerperfect::exp
+{
+/// Handler for <table:table>.
+class XMLTableContext : public XMLImportContext
+{
+public:
+ XMLTableContext(XMLImport& rImport, bool bTopLevel = false);
+
+ rtl::Reference<XMLImportContext>
+ CreateChildContext(const OUString& rName,
+ const css::uno::Reference<css::xml::sax::XAttributeList>& xAttribs) override;
+
+ void SAL_CALL
+ startElement(const OUString& rName,
+ const css::uno::Reference<css::xml::sax::XAttributeList>& 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 writerperfect::exp
+
+/* 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..933cf43e1
--- /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<XMLImportContext> XMLBodyContentContext::CreateChildContext(
+ const OUString& rName, const css::uno::Reference<css::xml::sax::XAttributeList>& /*xAttribs*/)
+{
+ return CreateTextChildContext(GetImport(), rName, true);
+}
+
+rtl::Reference<XMLImportContext> CreateTextChildContext(XMLImport& rImport,
+ std::u16string_view rName, bool bTopLevel)
+{
+ if (rName == u"text:p" || rName == u"text:h")
+ return new XMLParaContext(rImport, bTopLevel);
+ if (rName == u"text:section")
+ return new XMLSectionContext(rImport);
+ if (rName == u"table:table")
+ return new XMLTableContext(rImport, bTopLevel);
+ if (rName == u"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..50188acfe
--- /dev/null
+++ b/writerperfect/source/writer/exp/xmltext.hxx
@@ -0,0 +1,34 @@
+/* -*- 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/.
+ */
+
+#pragma once
+
+#include "xmlictxt.hxx"
+
+namespace writerperfect::exp
+{
+/// Handler for <office:text>.
+class XMLBodyContentContext : public XMLImportContext
+{
+public:
+ XMLBodyContentContext(XMLImport& rImport);
+
+ rtl::Reference<XMLImportContext> CreateChildContext(
+ const OUString& rName,
+ const css::uno::Reference<css::xml::sax::XAttributeList>& /*xAttribs*/) override;
+ void SAL_CALL endElement(const OUString& rName) override;
+};
+
+/// Context factory for body text, section, table cell, etc.
+rtl::Reference<XMLImportContext>
+CreateTextChildContext(XMLImport& rImport, std::u16string_view rName, bool bTopLevel = false);
+
+} // namespace writerperfect::exp
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */