summaryrefslogtreecommitdiffstats
path: root/writerperfect/source
diff options
context:
space:
mode:
Diffstat (limited to 'writerperfect/source')
-rw-r--r--writerperfect/source/calc/MSWorksCalcImportFilter.cxx474
-rw-r--r--writerperfect/source/calc/MSWorksCalcImportFilter.hxx45
-rw-r--r--writerperfect/source/calc/MWAWCalcImportFilter.cxx124
-rw-r--r--writerperfect/source/calc/MWAWCalcImportFilter.hxx40
-rw-r--r--writerperfect/source/calc/NumbersImportFilter.cxx65
-rw-r--r--writerperfect/source/calc/NumbersImportFilter.hxx40
-rw-r--r--writerperfect/source/calc/StarOfficeCalcImportFilter.cxx99
-rw-r--r--writerperfect/source/calc/StarOfficeCalcImportFilter.hxx41
-rw-r--r--writerperfect/source/calc/wpftcalc.component32
-rw-r--r--writerperfect/source/common/DirectoryStream.cxx221
-rw-r--r--writerperfect/source/common/DocumentHandler.cxx181
-rw-r--r--writerperfect/source/common/WPFTEncodingDialog.cxx122
-rw-r--r--writerperfect/source/common/WPXSvInputStream.cxx960
-rw-r--r--writerperfect/source/draw/CDRImportFilter.cxx60
-rw-r--r--writerperfect/source/draw/CDRImportFilter.hxx39
-rw-r--r--writerperfect/source/draw/CMXImportFilter.cxx60
-rw-r--r--writerperfect/source/draw/CMXImportFilter.hxx39
-rw-r--r--writerperfect/source/draw/FreehandImportFilter.cxx56
-rw-r--r--writerperfect/source/draw/FreehandImportFilter.hxx36
-rw-r--r--writerperfect/source/draw/MSPUBImportFilter.cxx56
-rw-r--r--writerperfect/source/draw/MSPUBImportFilter.hxx36
-rw-r--r--writerperfect/source/draw/MWAWDrawImportFilter.cxx116
-rw-r--r--writerperfect/source/draw/MWAWDrawImportFilter.hxx41
-rw-r--r--writerperfect/source/draw/PageMakerImportFilter.cxx56
-rw-r--r--writerperfect/source/draw/PageMakerImportFilter.hxx37
-rw-r--r--writerperfect/source/draw/QXPImportFilter.cxx60
-rw-r--r--writerperfect/source/draw/QXPImportFilter.hxx36
-rw-r--r--writerperfect/source/draw/StarOfficeDrawImportFilter.cxx101
-rw-r--r--writerperfect/source/draw/StarOfficeDrawImportFilter.hxx42
-rw-r--r--writerperfect/source/draw/VisioImportFilter.cxx56
-rw-r--r--writerperfect/source/draw/VisioImportFilter.hxx36
-rw-r--r--writerperfect/source/draw/WPGImportFilter.cxx62
-rw-r--r--writerperfect/source/draw/WPGImportFilter.hxx41
-rw-r--r--writerperfect/source/draw/ZMFImportFilter.cxx60
-rw-r--r--writerperfect/source/draw/ZMFImportFilter.hxx36
-rw-r--r--writerperfect/source/draw/wpftdraw.component67
-rw-r--r--writerperfect/source/impress/KeynoteImportFilter.cxx247
-rw-r--r--writerperfect/source/impress/KeynoteImportFilter.hxx41
-rw-r--r--writerperfect/source/impress/MWAWPresentationImportFilter.cxx104
-rw-r--r--writerperfect/source/impress/MWAWPresentationImportFilter.hxx42
-rw-r--r--writerperfect/source/impress/StarOfficePresentationImportFilter.cxx102
-rw-r--r--writerperfect/source/impress/StarOfficePresentationImportFilter.hxx42
-rw-r--r--writerperfect/source/impress/wpftimpress.component27
-rw-r--r--writerperfect/source/writer/AbiWordImportFilter.cxx58
-rw-r--r--writerperfect/source/writer/AbiWordImportFilter.hxx40
-rw-r--r--writerperfect/source/writer/EBookImportFilter.cxx114
-rw-r--r--writerperfect/source/writer/EBookImportFilter.hxx44
-rw-r--r--writerperfect/source/writer/EPUBExportDialog.cxx224
-rw-r--r--writerperfect/source/writer/EPUBExportDialog.hxx61
-rw-r--r--writerperfect/source/writer/EPUBExportFilter.cxx206
-rw-r--r--writerperfect/source/writer/EPUBExportFilter.hxx71
-rw-r--r--writerperfect/source/writer/EPUBExportUIComponent.cxx102
-rw-r--r--writerperfect/source/writer/EPUBExportUIComponent.hxx72
-rw-r--r--writerperfect/source/writer/EPUBPackage.cxx215
-rw-r--r--writerperfect/source/writer/EPUBPackage.hxx90
-rw-r--r--writerperfect/source/writer/MSWorksImportFilter.cxx157
-rw-r--r--writerperfect/source/writer/MSWorksImportFilter.hxx41
-rw-r--r--writerperfect/source/writer/MWAWImportFilter.cxx117
-rw-r--r--writerperfect/source/writer/MWAWImportFilter.hxx41
-rw-r--r--writerperfect/source/writer/PagesImportFilter.cxx63
-rw-r--r--writerperfect/source/writer/PagesImportFilter.hxx40
-rw-r--r--writerperfect/source/writer/StarOfficeWriterImportFilter.cxx128
-rw-r--r--writerperfect/source/writer/StarOfficeWriterImportFilter.hxx42
-rw-r--r--writerperfect/source/writer/WordPerfectImportFilter.cxx238
-rw-r--r--writerperfect/source/writer/WordPerfectImportFilter.hxx63
-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
-rw-r--r--writerperfect/source/writer/wpftwriter.component72
-rw-r--r--writerperfect/source/writer/wpftwriter.component.extended8
-rw-r--r--writerperfect/source/writer/wpftwriter.component.extended212
96 files changed, 10451 insertions, 0 deletions
diff --git a/writerperfect/source/calc/MSWorksCalcImportFilter.cxx b/writerperfect/source/calc/MSWorksCalcImportFilter.cxx
new file mode 100644
index 000000000..b0118eaad
--- /dev/null
+++ b/writerperfect/source/calc/MSWorksCalcImportFilter.cxx
@@ -0,0 +1,474 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* MSWorksCalcImportFilter: Sets up the filter, and calls DocumentCollector
+ * to do the actual filtering
+ *
+ * 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 <com/sun/star/awt/XWindow.hpp>
+#include <com/sun/star/container/XChild.hpp>
+#include <com/sun/star/sdbc/XResultSet.hpp>
+#include <com/sun/star/sdbc/XRow.hpp>
+#include <com/sun/star/ucb/XContent.hpp>
+#include <com/sun/star/ucb/XContentAccess.hpp>
+#include <sal/log.hxx>
+#include <comphelper/processfactory.hxx>
+#include <cppuhelper/supportsservice.hxx>
+#include <sfx2/passwd.hxx>
+#include <tools/urlobj.hxx>
+#include <ucbhelper/content.hxx>
+
+#include <libwps/libwps.h>
+
+#include <DocumentHandlerForOds.hxx>
+#include <WPFTEncodingDialog.hxx>
+#include <WPFTResMgr.hxx>
+#include "MSWorksCalcImportFilter.hxx"
+#include <strings.hrc>
+
+#include <iostream>
+#include <map>
+
+using namespace ::com::sun::star;
+
+namespace MSWorksCalcImportFilterInternal
+{
+/// returns the list of stream name present in a folder
+static uno::Reference<sdbc::XResultSet>
+getResultSet(const css::uno::Reference<css::ucb::XContent>& xPackageContent)
+{
+ try
+ {
+ if (xPackageContent.is())
+ {
+ ucbhelper::Content packageContent(xPackageContent,
+ uno::Reference<ucb::XCommandEnvironment>(),
+ comphelper::getProcessComponentContext());
+ uno::Sequence<OUString> lPropNames{ "Title" };
+ uno::Reference<sdbc::XResultSet> xResultSet(
+ packageContent.createCursor(lPropNames, ucbhelper::INCLUDE_DOCUMENTS_ONLY));
+ return xResultSet;
+ }
+ return uno::Reference<sdbc::XResultSet>();
+ }
+ catch (...)
+ {
+ SAL_WARN("writerperfect",
+ "ignoring Exception in MSWorksCalcImportFilterInternal:getResultSet");
+ return uno::Reference<sdbc::XResultSet>();
+ }
+}
+
+namespace
+{
+/** internal class used to create a structured RVNGInputStream from a list of path and their short names
+ */
+class FolderStream : public librevenge::RVNGInputStream
+{
+public:
+ //! constructor
+ explicit FolderStream(const css::uno::Reference<css::ucb::XContent>& xContent)
+ : m_xContent(xContent)
+ {
+ }
+
+ //! add a file
+ void addFile(OUString const& path, std::string const& shortName)
+ {
+ m_nameToPathMap[shortName] = path;
+ }
+ /**! reads numbytes data.
+
+ * \return a pointer to the read elements
+ */
+ const unsigned char* read(unsigned long, unsigned long&) override { return nullptr; }
+ //! returns actual offset position
+ long tell() override { return 0; }
+ /*! \brief seeks to an offset position, from actual, beginning or ending position
+ * \return 0 if ok
+ */
+ int seek(long, librevenge::RVNG_SEEK_TYPE) override { return 1; }
+ //! returns true if we are at the end of the section/file
+ bool isEnd() override { return true; }
+
+ /** returns true if the stream is ole
+
+ \sa returns always false*/
+ bool isStructured() override { return true; }
+ /** returns the number of sub streams.
+
+ \sa returns always 2*/
+ unsigned subStreamCount() override { return unsigned(m_nameToPathMap.size()); }
+ /** returns the ith sub streams name */
+ const char* subStreamName(unsigned id) override
+ {
+ if (m_nameToPathMap.size() < id)
+ return nullptr;
+
+ std::map<std::string, OUString>::const_iterator it = m_nameToPathMap.begin();
+ std::advance(it, id);
+ return it->first.c_str();
+ }
+ /** returns true if a substream with name exists */
+ bool existsSubStream(const char* name) override
+ {
+ return name && m_nameToPathMap.find(name) != m_nameToPathMap.end();
+ }
+ /** return a new stream for an OLE zone */
+ librevenge::RVNGInputStream* getSubStreamByName(const char* name) override
+ {
+ if (m_nameToPathMap.find(name) == m_nameToPathMap.end() || !m_xContent.is())
+ return nullptr;
+
+ try
+ {
+ const uno::Reference<sdbc::XResultSet> xResultSet = getResultSet(m_xContent);
+ if (xResultSet.is() && xResultSet->first())
+ {
+ const uno::Reference<ucb::XContentAccess> xContentAccess(xResultSet,
+ uno::UNO_QUERY_THROW);
+ const uno::Reference<sdbc::XRow> xRow(xResultSet, uno::UNO_QUERY_THROW);
+ OUString lPath = m_nameToPathMap.find(name)->second;
+ do
+ {
+ const OUString aTitle(xRow->getString(1));
+ if (aTitle != lPath)
+ continue;
+
+ const uno::Reference<ucb::XContent> xSubContent(xContentAccess->queryContent());
+ ucbhelper::Content aSubContent(xSubContent,
+ uno::Reference<ucb::XCommandEnvironment>(),
+ comphelper::getProcessComponentContext());
+ uno::Reference<io::XInputStream> xInputStream = aSubContent.openStream();
+ if (xInputStream.is())
+ return new writerperfect::WPXSvInputStream(xInputStream);
+ break;
+ } while (xResultSet->next());
+ }
+ }
+ catch (...)
+ {
+ SAL_WARN("writerperfect", "ignoring Exception in "
+ "MSWorksCalcImportFilterInternal::FolderStream::"
+ "getSubStreamByName");
+ }
+
+ return nullptr;
+ }
+ /** return a new stream for an OLE zone */
+ librevenge::RVNGInputStream* getSubStreamById(unsigned id) override
+ {
+ char const* name = subStreamName(id);
+ return name ? getSubStreamByName(name) : nullptr;
+ }
+
+private:
+ /// the main container
+ uno::Reference<ucb::XContent> m_xContent;
+ /// the map short name to path
+ std::map<std::string, OUString> m_nameToPathMap;
+ FolderStream(const FolderStream&) = delete;
+ FolderStream& operator=(const FolderStream&) = delete;
+};
+}
+}
+
+////////////////////////////////////////////////////////////
+bool MSWorksCalcImportFilter::doImportDocument(weld::Window* pParent,
+ librevenge::RVNGInputStream& rInput,
+ OdsGenerator& rGenerator,
+ utl::MediaDescriptor& mediaDescriptor)
+{
+ libwps::WPSKind kind = libwps::WPS_TEXT;
+ libwps::WPSCreator creator;
+ bool needEncoding;
+ const libwps::WPSConfidence confidence
+ = libwps::WPSDocument::isFileFormatSupported(&rInput, kind, creator, needEncoding);
+
+ if ((kind != libwps::WPS_SPREADSHEET && kind != libwps::WPS_DATABASE)
+ || (confidence == libwps::WPS_CONFIDENCE_NONE))
+ return false;
+ std::string fileEncoding;
+ if (needEncoding)
+ {
+ OUString encoding;
+ // first check if we can find the encoding in the filter options (headless mode)
+ mediaDescriptor[utl::MediaDescriptor::PROP_FILTEROPTIONS] >>= encoding;
+ if (!encoding.isEmpty()) // TODO: check if the encoding string is valid
+ fileEncoding = encoding.toUtf8().getStr();
+ else
+ {
+ OUString title;
+ switch (creator)
+ {
+ case libwps::WPS_MSWORKS:
+ title = WpResId(STR_ENCODING_DIALOG_TITLE_MSWORKS);
+ encoding = "CP850";
+ break;
+ case libwps::WPS_LOTUS:
+ title = WpResId(STR_ENCODING_DIALOG_TITLE_LOTUS);
+ encoding = "CP437";
+ break;
+ case libwps::WPS_SYMPHONY:
+ title = WpResId(STR_ENCODING_DIALOG_TITLE_SYMPHONY);
+ encoding = "CP437";
+ break;
+ case libwps::WPS_QUATTRO_PRO:
+ title = WpResId(STR_ENCODING_DIALOG_TITLE_QUATTROPRO);
+ encoding = "CP437";
+ break;
+ case libwps::WPS_RESERVED_2:
+ title = WpResId(STR_ENCODING_DIALOG_TITLE_MSMULTIPLAN);
+ encoding = "CP437";
+ break;
+ default:
+ SAL_INFO("writerperfect", "unexpected creator: " << creator);
+ title = WpResId(STR_ENCODING_DIALOG_TITLE);
+ encoding = "CP437";
+ break;
+ }
+
+ fileEncoding = encoding.toUtf8().getStr(); // set default to the proposed encoding
+ try
+ {
+ writerperfect::WPFTEncodingDialog aDlg(pParent, title, encoding);
+ if (aDlg.run() == RET_OK)
+ {
+ if (!aDlg.GetEncoding().isEmpty())
+ fileEncoding = aDlg.GetEncoding().toUtf8().getStr();
+ }
+ // we can fail because we are in headless mode, the user has cancelled conversion, ...
+ else if (aDlg.hasUserCalledCancel())
+ return false;
+ }
+ catch (...)
+ {
+ SAL_WARN("writerperfect",
+ "ignoring Exception in MSWorksCalcImportFilter::doImportDocument");
+ }
+ }
+ }
+ OString aUtf8Passwd;
+ if (confidence == libwps::WPS_CONFIDENCE_SUPPORTED_ENCRYPTION)
+ {
+ OUString sPassword;
+ // now check if we can find the password in the properties
+ // (just in case, "soffice --headless" adds an option to send password)
+ mediaDescriptor[utl::MediaDescriptor::PROP_PASSWORD] >>= sPassword;
+ if (!sPassword.isEmpty())
+ aUtf8Passwd = OUStringToOString(sPassword, RTL_TEXTENCODING_UTF8);
+ else
+ {
+ // ok, ask the user for a password
+ try
+ {
+ SfxPasswordDialog aPasswdDlg(pParent);
+ aPasswdDlg.SetMinLen(1);
+ if (!aPasswdDlg.run())
+ return false;
+ OUString aPasswd = aPasswdDlg.GetPassword();
+ aUtf8Passwd = OUStringToOString(aPasswd, RTL_TEXTENCODING_UTF8);
+ }
+ catch (...)
+ {
+ return false;
+ }
+ }
+ }
+ return libwps::WPS_OK
+ == libwps::WPSDocument::parse(&rInput, &rGenerator,
+ confidence == libwps::WPS_CONFIDENCE_SUPPORTED_ENCRYPTION
+ ? aUtf8Passwd.getStr()
+ : nullptr,
+ fileEncoding.c_str());
+}
+
+//XExtendedFilterDetection
+sal_Bool
+MSWorksCalcImportFilter::filter(const css::uno::Sequence<css::beans::PropertyValue>& rDescriptor)
+{
+ OUString sUrl;
+ css::uno::Reference<css::io::XInputStream> xInputStream;
+ css::uno::Reference<ucb::XContent> xContent;
+ css::uno::Reference<css::awt::XWindow> xDialogParent;
+
+ for (const auto& rValue : rDescriptor)
+ {
+ if (rValue.Name == "InputStream")
+ rValue.Value >>= xInputStream;
+ else if (rValue.Name == "UCBContent")
+ rValue.Value >>= xContent;
+ else if (rValue.Name == "FileName" || rValue.Name == "URL")
+ rValue.Value >>= sUrl;
+ else if (rValue.Name == "ParentWindow")
+ rValue.Value >>= xDialogParent;
+ }
+
+ if (!getXContext().is() || !xInputStream.is())
+ {
+ OSL_ASSERT(false);
+ return false;
+ }
+
+ // An XML import service: what we push sax messages to...
+ css::uno::Reference<XInterface> xInternalFilter
+ = getXContext()->getServiceManager()->createInstanceWithContext(
+ writerperfect::DocumentHandlerFor<OdsGenerator>::name(), getXContext());
+ assert(xInternalFilter);
+ css::uno::Reference<css::xml::sax::XFastDocumentHandler> xInternalHandler(xInternalFilter,
+ css::uno::UNO_QUERY);
+ assert(xInternalHandler);
+
+ // The XImporter sets up an empty target document for XDocumentHandler to write to...
+ css::uno::Reference<css::document::XImporter> xImporter(xInternalHandler, css::uno::UNO_QUERY);
+ assert(xImporter);
+ xImporter->setTargetDocument(getTargetDocument());
+
+ // OO Graphics Handler: abstract class to handle document SAX messages, concrete implementation here
+ // writes to in-memory target doc
+ writerperfect::DocumentHandler aHandler(
+ new SvXMLLegacyToFastDocHandler(static_cast<SvXMLImport*>(xInternalHandler.get())));
+
+ writerperfect::WPXSvInputStream input(xInputStream);
+ OdsGenerator exporter;
+ exporter.addDocumentHandler(&aHandler, ODF_FLAT_XML);
+ doRegisterHandlers(exporter);
+
+ utl::MediaDescriptor aDescriptor(rDescriptor);
+ try
+ {
+ // time to check if the file is a WK3 file and a FM3 file is
+ // present
+ bool checkForFM3 = false;
+ if (input.seek(0, librevenge::RVNG_SEEK_SET) == 0 && xContent.is()
+ && INetURLObject(sUrl).getExtension().equalsIgnoreAsciiCase("WK3"))
+ {
+ // check if the file header corresponds to a .wk3 file
+ unsigned long numBytesRead;
+ const unsigned char* data = input.read(6, numBytesRead);
+ if (data && numBytesRead == 6 && data[0] == 0 && data[1] == 0 && data[2] == 0x1a
+ && data[3] == 0 && data[4] < 2 && data[5] == 0x10)
+ checkForFM3 = true;
+ }
+ if (checkForFM3)
+ {
+ // check if the format file exists
+ const css::uno::Reference<container::XChild> xChild(xContent, uno::UNO_QUERY);
+ if (xChild.is())
+ {
+ OUString sWM3Name;
+ OUString sFM3Name;
+ const css::uno::Reference<ucb::XContent> xPackageContent(xChild->getParent(),
+ uno::UNO_QUERY);
+ uno::Reference<sdbc::XResultSet> xResultSet
+ = MSWorksCalcImportFilterInternal::getResultSet(xPackageContent);
+ if (xResultSet.is() && xResultSet->first())
+ {
+ const uno::Reference<ucb::XContentAccess> xContentAccess(xResultSet,
+ uno::UNO_QUERY_THROW);
+ const uno::Reference<sdbc::XRow> xRow(xResultSet, uno::UNO_QUERY_THROW);
+ INetURLObject aTmpUrl(sUrl);
+ sWM3Name = aTmpUrl.getName(INetURLObject::LAST_SEGMENT, true,
+ INetURLObject::DecodeMechanism::WithCharset);
+ aTmpUrl.setExtension(u"FM3");
+ const OUString& sTestFM3Name
+ = aTmpUrl.getName(INetURLObject::LAST_SEGMENT, true,
+ INetURLObject::DecodeMechanism::WithCharset);
+ do
+ {
+ const OUString& aTitle(xRow->getString(1));
+ if (aTitle.equalsIgnoreAsciiCase(sTestFM3Name))
+ sFM3Name = aTitle;
+ } while (xResultSet->next() && sFM3Name.isEmpty());
+ }
+ if (!sFM3Name.isEmpty())
+ {
+ MSWorksCalcImportFilterInternal::FolderStream structuredInput(xPackageContent);
+ structuredInput.addFile(sWM3Name, "WK3");
+ structuredInput.addFile(sFM3Name, "FM3");
+
+ libwps::WPSKind kind = libwps::WPS_TEXT;
+ libwps::WPSCreator creator;
+ bool needEncoding;
+ const libwps::WPSConfidence confidence
+ = libwps::WPSDocument::isFileFormatSupported(&structuredInput, kind,
+ creator, needEncoding);
+ if (confidence != libwps::WPS_CONFIDENCE_NONE)
+ return doImportDocument(Application::GetFrameWeld(xDialogParent),
+ structuredInput, exporter, aDescriptor);
+ }
+ }
+ }
+ }
+ catch (...)
+ {
+ }
+
+ return doImportDocument(Application::GetFrameWeld(xDialogParent), input, exporter, aDescriptor);
+}
+
+bool MSWorksCalcImportFilter::doDetectFormat(librevenge::RVNGInputStream& rInput,
+ OUString& rTypeName)
+{
+ libwps::WPSKind kind = libwps::WPS_TEXT;
+ libwps::WPSCreator creator;
+ bool needEncoding;
+ const libwps::WPSConfidence confidence
+ = libwps::WPSDocument::isFileFormatSupported(&rInput, kind, creator, needEncoding);
+
+ if ((kind == libwps::WPS_SPREADSHEET || kind == libwps::WPS_DATABASE)
+ && confidence != libwps::WPS_CONFIDENCE_NONE)
+ {
+ switch (creator)
+ {
+ case libwps::WPS_MSWORKS:
+ rTypeName = "calc_MS_Works_Document";
+ break;
+ case libwps::WPS_LOTUS:
+ case libwps::WPS_SYMPHONY:
+ rTypeName = "calc_WPS_Lotus_Document";
+ break;
+ case libwps::WPS_QUATTRO_PRO:
+ rTypeName = "calc_WPS_QPro_Document";
+ break;
+ case libwps::WPS_RESERVED_2:
+ rTypeName = "calc_MS_Multiplan";
+ break;
+ default:
+ break;
+ }
+ }
+
+ return !rTypeName.isEmpty();
+}
+
+void MSWorksCalcImportFilter::doRegisterHandlers(OdsGenerator&) {}
+
+// XServiceInfo
+OUString SAL_CALL MSWorksCalcImportFilter::getImplementationName()
+{
+ return "com.sun.star.comp.Calc.MSWorksCalcImportFilter";
+}
+
+sal_Bool SAL_CALL MSWorksCalcImportFilter::supportsService(const OUString& rServiceName)
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+css::uno::Sequence<OUString> SAL_CALL MSWorksCalcImportFilter::getSupportedServiceNames()
+{
+ return { "com.sun.star.document.ImportFilter", "com.sun.star.document.ExtendedTypeDetection" };
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+com_sun_star_comp_Calc_MSWorksCalcImportFilter_get_implementation(
+ css::uno::XComponentContext* const context, const css::uno::Sequence<css::uno::Any>&)
+{
+ return cppu::acquire(new MSWorksCalcImportFilter(context));
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/writerperfect/source/calc/MSWorksCalcImportFilter.hxx b/writerperfect/source/calc/MSWorksCalcImportFilter.hxx
new file mode 100644
index 000000000..d0ce3e1fc
--- /dev/null
+++ b/writerperfect/source/calc/MSWorksCalcImportFilter.hxx
@@ -0,0 +1,45 @@
+/* -*- 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/uno/XComponentContext.hpp>
+
+#include <DocumentHandlerForOds.hxx>
+#include <ImportFilter.hxx>
+
+/* This component will be instantiated for both import or export. Whether it calls
+ * setSourceDocument or setTargetDocument determines which Impl function the filter
+ * member calls */
+class MSWorksCalcImportFilter : public writerperfect::ImportFilter<OdsGenerator>
+{
+public:
+ explicit MSWorksCalcImportFilter(
+ const css::uno::Reference<css::uno::XComponentContext>& rxContext)
+ : writerperfect::ImportFilter<OdsGenerator>(rxContext)
+ {
+ }
+
+ // XServiceInfo
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override;
+ virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override;
+
+ //XFilter
+ virtual sal_Bool SAL_CALL
+ filter(const css::uno::Sequence<css::beans::PropertyValue>& rDescriptor) override;
+
+private:
+ virtual bool doDetectFormat(librevenge::RVNGInputStream& rInput, OUString& rTypeName) override;
+ virtual bool doImportDocument(weld::Window* pParent, librevenge::RVNGInputStream& rInput,
+ OdsGenerator& rGenerator, utl::MediaDescriptor&) override;
+ virtual void doRegisterHandlers(OdsGenerator& rGenerator) override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/writerperfect/source/calc/MWAWCalcImportFilter.cxx b/writerperfect/source/calc/MWAWCalcImportFilter.cxx
new file mode 100644
index 000000000..186084b17
--- /dev/null
+++ b/writerperfect/source/calc/MWAWCalcImportFilter.cxx
@@ -0,0 +1,124 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* MWAWCalcImportFilter: Sets up the filter, and calls DocumentCollector
+ * to do the actual filtering
+ *
+ * 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 <cppuhelper/supportsservice.hxx>
+
+#include <libmwaw/libmwaw.hxx>
+
+#include "MWAWCalcImportFilter.hxx"
+
+static bool handleEmbeddedMWAWGraphicObject(const librevenge::RVNGBinaryData& data,
+ OdfDocumentHandler* pHandler,
+ const OdfStreamType streamType)
+{
+ OdgGenerator exporter;
+ exporter.addDocumentHandler(pHandler, streamType);
+ return MWAWDocument::decodeGraphic(data, &exporter);
+}
+
+static bool handleEmbeddedMWAWSpreadsheetObject(const librevenge::RVNGBinaryData& data,
+ OdfDocumentHandler* pHandler,
+ const OdfStreamType streamType)
+{
+ OdsGenerator exporter;
+ exporter.addDocumentHandler(pHandler, streamType);
+ return MWAWDocument::decodeSpreadsheet(data, &exporter);
+}
+
+bool MWAWCalcImportFilter::doImportDocument(weld::Window*, librevenge::RVNGInputStream& rInput,
+ OdsGenerator& rGenerator, utl::MediaDescriptor&)
+{
+ return MWAWDocument::MWAW_R_OK == MWAWDocument::parse(&rInput, &rGenerator);
+}
+
+bool MWAWCalcImportFilter::doDetectFormat(librevenge::RVNGInputStream& rInput, OUString& rTypeName)
+{
+ rTypeName.clear();
+
+ MWAWDocument::Type docType = MWAWDocument::MWAW_T_UNKNOWN;
+ MWAWDocument::Kind docKind = MWAWDocument::MWAW_K_UNKNOWN;
+ const MWAWDocument::Confidence confidence
+ = MWAWDocument::isFileFormatSupported(&rInput, docType, docKind);
+
+ if (confidence == MWAWDocument::MWAW_C_EXCELLENT)
+ {
+ switch (docKind)
+ {
+ case MWAWDocument::MWAW_K_DATABASE:
+ switch (docType)
+ {
+ case MWAWDocument::MWAW_T_CLARISWORKS:
+ rTypeName = "calc_ClarisWorks";
+ break;
+ case MWAWDocument::MWAW_T_MICROSOFTWORKS:
+ rTypeName = "calc_Mac_Works";
+ break;
+ default:
+ rTypeName = "MWAW_Database";
+ break;
+ }
+ break;
+ case MWAWDocument::MWAW_K_SPREADSHEET:
+ switch (docType)
+ {
+ case MWAWDocument::MWAW_T_CLARISRESOLVE:
+ rTypeName = "calc_Claris_Resolve";
+ break;
+ case MWAWDocument::MWAW_T_CLARISWORKS:
+ rTypeName = "calc_ClarisWorks";
+ break;
+ case MWAWDocument::MWAW_T_MICROSOFTWORKS:
+ rTypeName = "calc_Mac_Works";
+ break;
+ default:
+ rTypeName = "MWAW_Spreadsheet";
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ return !rTypeName.isEmpty();
+}
+
+void MWAWCalcImportFilter::doRegisterHandlers(OdsGenerator& rGenerator)
+{
+ rGenerator.registerEmbeddedObjectHandler("image/mwaw-odg", &handleEmbeddedMWAWGraphicObject);
+ rGenerator.registerEmbeddedObjectHandler("image/mwaw-ods",
+ &handleEmbeddedMWAWSpreadsheetObject);
+}
+
+// XServiceInfo
+OUString SAL_CALL MWAWCalcImportFilter::getImplementationName()
+{
+ return "com.sun.star.comp.Calc.MWAWCalcImportFilter";
+}
+
+sal_Bool SAL_CALL MWAWCalcImportFilter::supportsService(const OUString& rServiceName)
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+css::uno::Sequence<OUString> SAL_CALL MWAWCalcImportFilter::getSupportedServiceNames()
+{
+ return { "com.sun.star.document.ImportFilter", "com.sun.star.document.ExtendedTypeDetection" };
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+com_sun_star_comp_Calc_MWAWCalcImportFilter_get_implementation(
+ css::uno::XComponentContext* const context, const css::uno::Sequence<css::uno::Any>&)
+{
+ return cppu::acquire(new MWAWCalcImportFilter(context));
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/writerperfect/source/calc/MWAWCalcImportFilter.hxx b/writerperfect/source/calc/MWAWCalcImportFilter.hxx
new file mode 100644
index 000000000..aa574315d
--- /dev/null
+++ b/writerperfect/source/calc/MWAWCalcImportFilter.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 <com/sun/star/uno/XComponentContext.hpp>
+
+#include <DocumentHandlerForOds.hxx>
+#include <ImportFilter.hxx>
+
+/* This component will be instantiated for both import or export. Whether it calls
+ * setSourceDocument or setTargetDocument determines which Impl function the filter
+ * member calls */
+class MWAWCalcImportFilter : public writerperfect::ImportFilter<OdsGenerator>
+{
+public:
+ explicit MWAWCalcImportFilter(const css::uno::Reference<css::uno::XComponentContext>& rxContext)
+ : writerperfect::ImportFilter<OdsGenerator>(rxContext)
+ {
+ }
+
+ // XServiceInfo
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override;
+ virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override;
+
+private:
+ virtual bool doDetectFormat(librevenge::RVNGInputStream& rInput, OUString& rTypeName) override;
+ virtual bool doImportDocument(weld::Window* pParent, librevenge::RVNGInputStream& rInput,
+ OdsGenerator& rGenerator, utl::MediaDescriptor&) override;
+ virtual void doRegisterHandlers(OdsGenerator& rGenerator) override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/writerperfect/source/calc/NumbersImportFilter.cxx b/writerperfect/source/calc/NumbersImportFilter.cxx
new file mode 100644
index 000000000..813684361
--- /dev/null
+++ b/writerperfect/source/calc/NumbersImportFilter.cxx
@@ -0,0 +1,65 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* NumbersImportFilter: Sets up the filter, and calls DocumentCollector
+ * to do the actual filtering
+ *
+ * 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 <libetonyek/libetonyek.h>
+
+#include <cppuhelper/supportsservice.hxx>
+
+#include "NumbersImportFilter.hxx"
+
+using libetonyek::EtonyekDocument;
+
+bool NumbersImportFilter::doImportDocument(weld::Window*, librevenge::RVNGInputStream& rInput,
+ OdsGenerator& rGenerator, utl::MediaDescriptor&)
+{
+ return EtonyekDocument::parse(&rInput, &rGenerator);
+}
+
+bool NumbersImportFilter::doDetectFormat(librevenge::RVNGInputStream& rInput, OUString& rTypeName)
+{
+ EtonyekDocument::Type type = EtonyekDocument::TYPE_UNKNOWN;
+ const EtonyekDocument::Confidence confidence = EtonyekDocument::isSupported(&rInput, &type);
+ if ((confidence == EtonyekDocument::CONFIDENCE_EXCELLENT)
+ && (type == EtonyekDocument::TYPE_NUMBERS))
+ {
+ rTypeName = "calc_AppleNumbers";
+ return true;
+ }
+
+ return false;
+}
+
+void NumbersImportFilter::doRegisterHandlers(OdsGenerator&) {}
+
+// XServiceInfo
+OUString SAL_CALL NumbersImportFilter::getImplementationName()
+{
+ return "org.libreoffice.comp.Calc.NumbersImportFilter";
+}
+
+sal_Bool SAL_CALL NumbersImportFilter::supportsService(const OUString& rServiceName)
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+css::uno::Sequence<OUString> SAL_CALL NumbersImportFilter::getSupportedServiceNames()
+{
+ return { "com.sun.star.document.ImportFilter", "com.sun.star.document.ExtendedTypeDetection" };
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+org_libreoffice_comp_Calc_NumbersImportFilter_get_implementation(
+ css::uno::XComponentContext* const context, const css::uno::Sequence<css::uno::Any>&)
+{
+ return cppu::acquire(new NumbersImportFilter(context));
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/writerperfect/source/calc/NumbersImportFilter.hxx b/writerperfect/source/calc/NumbersImportFilter.hxx
new file mode 100644
index 000000000..96db0b689
--- /dev/null
+++ b/writerperfect/source/calc/NumbersImportFilter.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 <com/sun/star/uno/XComponentContext.hpp>
+
+#include <DocumentHandlerForOds.hxx>
+#include <ImportFilter.hxx>
+
+/* This component will be instantiated for both import or export. Whether it calls
+ * setSourceDocument or setTargetDocument determines which Impl function the filter
+ * member calls */
+class NumbersImportFilter : public writerperfect::ImportFilter<OdsGenerator>
+{
+public:
+ explicit NumbersImportFilter(const css::uno::Reference<css::uno::XComponentContext>& rxContext)
+ : writerperfect::ImportFilter<OdsGenerator>(rxContext)
+ {
+ }
+
+ // XServiceInfo
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override;
+ virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override;
+
+private:
+ virtual bool doDetectFormat(librevenge::RVNGInputStream& rInput, OUString& rTypeName) override;
+ virtual bool doImportDocument(weld::Window* pParent, librevenge::RVNGInputStream& rInput,
+ OdsGenerator& rGenerator, utl::MediaDescriptor&) override;
+ virtual void doRegisterHandlers(OdsGenerator& rGenerator) override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/writerperfect/source/calc/StarOfficeCalcImportFilter.cxx b/writerperfect/source/calc/StarOfficeCalcImportFilter.cxx
new file mode 100644
index 000000000..de7e30e44
--- /dev/null
+++ b/writerperfect/source/calc/StarOfficeCalcImportFilter.cxx
@@ -0,0 +1,99 @@
+/* -*- 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 <cppuhelper/supportsservice.hxx>
+
+#include <libstaroffice/libstaroffice.hxx>
+
+#include "StarOfficeCalcImportFilter.hxx"
+
+using com::sun::star::uno::Sequence;
+using com::sun::star::uno::XComponentContext;
+using com::sun::star::uno::XInterface;
+
+static bool handleEmbeddedSTOFFGraphicObject(const librevenge::RVNGBinaryData& data,
+ OdfDocumentHandler* pHandler,
+ const OdfStreamType streamType)
+{
+ OdgGenerator exporter;
+ exporter.addDocumentHandler(pHandler, streamType);
+ return STOFFDocument::decodeGraphic(data, &exporter);
+}
+
+static bool handleEmbeddedSTOFFSpreadsheetObject(const librevenge::RVNGBinaryData& data,
+ OdfDocumentHandler* pHandler,
+ const OdfStreamType streamType)
+{
+ OdsGenerator exporter;
+ exporter.addDocumentHandler(pHandler, streamType);
+ return STOFFDocument::decodeSpreadsheet(data, &exporter);
+}
+
+bool StarOfficeCalcImportFilter::doImportDocument(weld::Window*,
+ librevenge::RVNGInputStream& rInput,
+ OdsGenerator& rGenerator, utl::MediaDescriptor&)
+{
+ return STOFFDocument::STOFF_R_OK == STOFFDocument::parse(&rInput, &rGenerator);
+}
+
+bool StarOfficeCalcImportFilter::doDetectFormat(librevenge::RVNGInputStream& rInput,
+ OUString& rTypeName)
+{
+ rTypeName.clear();
+ STOFFDocument::Kind docKind = STOFFDocument::STOFF_K_UNKNOWN;
+ const STOFFDocument::Confidence confidence
+ = STOFFDocument::isFileFormatSupported(&rInput, docKind);
+ if (confidence == STOFFDocument::STOFF_C_EXCELLENT
+ || confidence == STOFFDocument::STOFF_C_SUPPORTED_ENCRYPTION)
+ {
+ switch (docKind)
+ {
+ case STOFFDocument::STOFF_K_DATABASE:
+ case STOFFDocument::STOFF_K_SPREADSHEET:
+ rTypeName = "StarOffice_Spreadsheet";
+ break;
+ default:
+ break;
+ }
+ }
+
+ return !rTypeName.isEmpty();
+}
+
+void StarOfficeCalcImportFilter::doRegisterHandlers(OdsGenerator& rGenerator)
+{
+ rGenerator.registerEmbeddedObjectHandler("image/stoff-odg", &handleEmbeddedSTOFFGraphicObject);
+ rGenerator.registerEmbeddedObjectHandler("image/stoff-ods",
+ &handleEmbeddedSTOFFSpreadsheetObject);
+}
+
+// XServiceInfo
+OUString SAL_CALL StarOfficeCalcImportFilter::getImplementationName()
+{
+ return "org.libreoffice.comp.Calc.StarOfficeCalcImportFilter";
+}
+
+sal_Bool SAL_CALL StarOfficeCalcImportFilter::supportsService(const OUString& rServiceName)
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+Sequence<OUString> SAL_CALL StarOfficeCalcImportFilter::getSupportedServiceNames()
+{
+ return { "com.sun.star.document.ImportFilter", "com.sun.star.document.ExtendedTypeDetection" };
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+org_libreoffice_comp_Calc_StarOfficeCalcImportFilter_get_implementation(
+ css::uno::XComponentContext* const context, const css::uno::Sequence<css::uno::Any>&)
+{
+ return cppu::acquire(new StarOfficeCalcImportFilter(context));
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/writerperfect/source/calc/StarOfficeCalcImportFilter.hxx b/writerperfect/source/calc/StarOfficeCalcImportFilter.hxx
new file mode 100644
index 000000000..0b11e5166
--- /dev/null
+++ b/writerperfect/source/calc/StarOfficeCalcImportFilter.hxx
@@ -0,0 +1,41 @@
+/* -*- 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/uno/XComponentContext.hpp>
+
+#include <DocumentHandlerForOds.hxx>
+#include <ImportFilter.hxx>
+
+/* This component will be instantiated for both import or export. Whether it calls
+ * setSourceDocument or setTargetDocument determines which Impl function the filter
+ * member calls */
+class StarOfficeCalcImportFilter : public writerperfect::ImportFilter<OdsGenerator>
+{
+public:
+ explicit StarOfficeCalcImportFilter(
+ const css::uno::Reference<css::uno::XComponentContext>& rxContext)
+ : writerperfect::ImportFilter<OdsGenerator>(rxContext)
+ {
+ }
+
+ // XServiceInfo
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override;
+ virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override;
+
+private:
+ virtual bool doDetectFormat(librevenge::RVNGInputStream& rInput, OUString& rTypeName) override;
+ virtual bool doImportDocument(weld::Window* pParent, librevenge::RVNGInputStream& rInput,
+ OdsGenerator& rGenerator, utl::MediaDescriptor&) override;
+ virtual void doRegisterHandlers(OdsGenerator& rGenerator) override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/writerperfect/source/calc/wpftcalc.component b/writerperfect/source/calc/wpftcalc.component
new file mode 100644
index 000000000..404d09b6c
--- /dev/null
+++ b/writerperfect/source/calc/wpftcalc.component
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * 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/.
+ *
+-->
+<component loader="com.sun.star.loader.SharedLibrary" environment="@CPPU_ENV@"
+ xmlns="http://openoffice.org/2010/uno-components">
+ <implementation name="com.sun.star.comp.Calc.MSWorksCalcImportFilter"
+ constructor="com_sun_star_comp_Calc_MSWorksCalcImportFilter_get_implementation">
+ <service name="com.sun.star.document.ImportFilter"/>
+ <service name="com.sun.star.document.ExtendedTypeDetection"/>
+ </implementation>
+ <implementation name="com.sun.star.comp.Calc.MWAWCalcImportFilter"
+ constructor="com_sun_star_comp_Calc_MWAWCalcImportFilter_get_implementation">
+ <service name="com.sun.star.document.ImportFilter"/>
+ <service name="com.sun.star.document.ExtendedTypeDetection"/>
+ </implementation>
+ <implementation name="org.libreoffice.comp.Calc.NumbersImportFilter"
+ constructor="org_libreoffice_comp_Calc_NumbersImportFilter_get_implementation">
+ <service name="com.sun.star.document.ImportFilter"/>
+ <service name="com.sun.star.document.ExtendedTypeDetection"/>
+ </implementation>
+ <implementation name="org.libreoffice.comp.Calc.StarOfficeCalcImportFilter"
+ constructor="org_libreoffice_comp_Calc_StarOfficeCalcImportFilter_get_implementation">
+ <service name="com.sun.star.document.ImportFilter"/>
+ <service name="com.sun.star.document.ExtendedTypeDetection"/>
+ </implementation>
+</component>
diff --git a/writerperfect/source/common/DirectoryStream.cxx b/writerperfect/source/common/DirectoryStream.cxx
new file mode 100644
index 000000000..28c38daa6
--- /dev/null
+++ b/writerperfect/source/common/DirectoryStream.cxx
@@ -0,0 +1,221 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* writerperfect
+ * Version: MPL 2.0 / LGPLv2.1+
+ *
+ * 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/.
+ *
+ * Major Contributor(s):
+ * Copyright (C) 2007 Fridrich Strba (fridrich.strba@bluewin.ch)
+ *
+ * For minor contributions see the git repository.
+ *
+ * Alternatively, the contents of this file may be used under the terms
+ * of the GNU Lesser General Public License Version 2.1 or later
+ * (LGPLv2.1+), in which case the provisions of the LGPLv2.1+ are
+ * applicable instead of those above.
+ *
+ * For further information visit http://libwpd.sourceforge.net
+ */
+
+#include <memory>
+#include <com/sun/star/container/XChild.hpp>
+#include <com/sun/star/io/XInputStream.hpp>
+#include <com/sun/star/sdbc/XResultSet.hpp>
+#include <com/sun/star/sdbc/XRow.hpp>
+#include <com/sun/star/ucb/XContent.hpp>
+#include <com/sun/star/ucb/XContentAccess.hpp>
+#include <com/sun/star/ucb/XCommandEnvironment.hpp>
+
+#include <com/sun/star/uno/Reference.hxx>
+#include <com/sun/star/uno/Sequence.hxx>
+
+#include <comphelper/processfactory.hxx>
+
+#include <rtl/ustring.hxx>
+
+#include <ucbhelper/content.hxx>
+
+#include <DirectoryStream.hxx>
+#include <WPXSvInputStream.hxx>
+
+namespace io = com::sun::star::io;
+namespace sdbc = com::sun::star::sdbc;
+namespace ucb = com::sun::star::ucb;
+namespace uno = com::sun::star::uno;
+
+namespace writerperfect
+{
+namespace
+{
+uno::Reference<io::XInputStream> findStream(ucbhelper::Content& rContent, std::u16string_view rName)
+{
+ uno::Reference<io::XInputStream> xInputStream;
+
+ uno::Sequence<OUString> lPropNames{ "Title" };
+ try
+ {
+ const uno::Reference<sdbc::XResultSet> xResultSet(
+ rContent.createCursor(lPropNames, ucbhelper::INCLUDE_DOCUMENTS_ONLY));
+ if (xResultSet->first())
+ {
+ const uno::Reference<ucb::XContentAccess> xContentAccess(xResultSet,
+ uno::UNO_QUERY_THROW);
+ const uno::Reference<sdbc::XRow> xRow(xResultSet, uno::UNO_QUERY_THROW);
+ do
+ {
+ const OUString aTitle(xRow->getString(1));
+ if (aTitle == rName)
+ {
+ const uno::Reference<ucb::XContent> xSubContent(xContentAccess->queryContent());
+ ucbhelper::Content aSubContent(xSubContent,
+ uno::Reference<ucb::XCommandEnvironment>(),
+ comphelper::getProcessComponentContext());
+ xInputStream = aSubContent.openStream();
+ break;
+ }
+ } while (xResultSet->next());
+ }
+ }
+ catch (const uno::RuntimeException&)
+ {
+ // ignore
+ }
+ catch (const uno::Exception&)
+ {
+ // ignore
+ }
+
+ return xInputStream;
+}
+}
+
+struct DirectoryStream::Impl
+{
+ explicit Impl(const uno::Reference<ucb::XContent>& rxContent);
+
+ uno::Reference<ucb::XContent> xContent;
+};
+
+DirectoryStream::Impl::Impl(const uno::Reference<ucb::XContent>& rxContent)
+ : xContent(rxContent)
+{
+}
+
+DirectoryStream::DirectoryStream(const css::uno::Reference<css::ucb::XContent>& xContent)
+ : m_pImpl(isDirectory(xContent) ? new Impl(xContent) : nullptr)
+{
+}
+
+DirectoryStream::~DirectoryStream() {}
+
+bool DirectoryStream::isDirectory(const css::uno::Reference<css::ucb::XContent>& xContent)
+{
+ try
+ {
+ if (!xContent.is())
+ return false;
+
+ ucbhelper::Content aContent(xContent, uno::Reference<ucb::XCommandEnvironment>(),
+ comphelper::getProcessComponentContext());
+ return aContent.isFolder();
+ }
+ catch (...)
+ {
+ return false;
+ }
+}
+
+std::unique_ptr<DirectoryStream>
+DirectoryStream::createForParent(const css::uno::Reference<css::ucb::XContent>& xContent)
+{
+ try
+ {
+ if (!xContent.is())
+ return nullptr;
+
+ std::unique_ptr<DirectoryStream> pDir;
+
+ const uno::Reference<css::container::XChild> xChild(xContent, uno::UNO_QUERY);
+ if (xChild.is())
+ {
+ const uno::Reference<ucb::XContent> xDirContent(xChild->getParent(), uno::UNO_QUERY);
+ if (xDirContent.is())
+ {
+ pDir = std::make_unique<DirectoryStream>(xDirContent);
+ if (!pDir->isStructured())
+ pDir.reset();
+ }
+ }
+
+ return pDir;
+ }
+ catch (...)
+ {
+ return nullptr;
+ }
+}
+
+css::uno::Reference<css::ucb::XContent> DirectoryStream::getContent() const
+{
+ if (!m_pImpl)
+ return css::uno::Reference<css::ucb::XContent>();
+ return m_pImpl->xContent;
+}
+
+bool DirectoryStream::isStructured() { return m_pImpl != nullptr; }
+
+unsigned DirectoryStream::subStreamCount()
+{
+ // TODO: implement me
+ return 0;
+}
+
+const char* DirectoryStream::subStreamName(unsigned /* id */)
+{
+ // TODO: implement me
+ return nullptr;
+}
+
+bool DirectoryStream::existsSubStream(const char* /* name */)
+{
+ // TODO: implement me
+ return false;
+}
+
+librevenge::RVNGInputStream* DirectoryStream::getSubStreamByName(const char* const pName)
+{
+ if (!m_pImpl)
+ return nullptr;
+
+ ucbhelper::Content aContent(m_pImpl->xContent, uno::Reference<ucb::XCommandEnvironment>(),
+ comphelper::getProcessComponentContext());
+ const uno::Reference<io::XInputStream> xInputStream(
+ findStream(aContent, OUString::createFromAscii(pName)));
+ if (xInputStream.is())
+ return new WPXSvInputStream(xInputStream);
+
+ return nullptr;
+}
+
+librevenge::RVNGInputStream* DirectoryStream::getSubStreamById(unsigned /* id */)
+{
+ // TODO: implement me
+ return nullptr;
+}
+
+const unsigned char* DirectoryStream::read(unsigned long, unsigned long& nNumBytesRead)
+{
+ nNumBytesRead = 0;
+ return nullptr;
+}
+
+int DirectoryStream::seek(long, librevenge::RVNG_SEEK_TYPE) { return -1; }
+
+long DirectoryStream::tell() { return 0; }
+
+bool DirectoryStream::isEnd() { return true; }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/writerperfect/source/common/DocumentHandler.cxx b/writerperfect/source/common/DocumentHandler.cxx
new file mode 100644
index 000000000..6b5ffe58a
--- /dev/null
+++ b/writerperfect/source/common/DocumentHandler.cxx
@@ -0,0 +1,181 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * For further information visit http://libwpd.sourceforge.net
+ */
+
+#include <DocumentHandler.hxx>
+
+#include <string.h>
+
+#include <com/sun/star/uno/Reference.hxx>
+#include <com/sun/star/xml/sax/XDocumentHandler.hpp>
+#include <com/sun/star/xml/sax/XAttributeList.hpp>
+
+#include <xmloff/attrlist.hxx>
+#include <xmloff/xmlimp.hxx>
+
+namespace writerperfect
+{
+const unsigned char librvng_utf8_skip_data[256]
+ = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 1, 1 };
+
+static const char* librvng_utf8_next_char(const char* p)
+{
+ return p + librvng_utf8_skip_data[*reinterpret_cast<unsigned char const*>(p)];
+}
+
+static void unescapeXML(const char* s, const unsigned long sz, librevenge::RVNGString& res)
+{
+ const char* p = s;
+ const char* const end = p + sz;
+ while (p != end)
+ {
+ const char* const next = librvng_utf8_next_char(p);
+ if (next > end)
+ {
+ // oops, the string is invalid
+ break;
+ }
+ if (p + 4 <= end && p + 1 == next && *p == '&')
+ {
+ // look for &amp; , &lt; , &gt; , &apos; , &quot;
+ bool escapedChar = false;
+ switch (*(p + 1))
+ {
+ case 'a':
+ if (p + 5 <= end && strncmp(p, "&amp;", 5) == 0)
+ {
+ res.append('&');
+ p += 5;
+ escapedChar = true;
+ }
+ else if (p + 6 <= end && strncmp(p, "&apos;", 6) == 0)
+ {
+ res.append('\'');
+ p += 6;
+ escapedChar = true;
+ }
+ break;
+ case 'g':
+ if (strncmp(p, "&gt;", 4) == 0)
+ {
+ res.append('>');
+ p += 4;
+ escapedChar = true;
+ }
+ break;
+ case 'l':
+ if (strncmp(p, "&lt;", 4) == 0)
+ {
+ res.append('<');
+ p += 4;
+ escapedChar = true;
+ }
+ break;
+ case 'q':
+ if (p + 6 <= end && strncmp(p, "&quot;", 6) == 0)
+ {
+ res.append('"');
+ p += 6;
+ escapedChar = true;
+ }
+ break;
+ default:
+ break;
+ }
+ if (escapedChar)
+ continue;
+ }
+
+ while (p != next)
+ {
+ res.append(*p);
+ ++p;
+ }
+ p = next;
+ }
+}
+
+using com::sun::star::uno::Reference;
+using com::sun::star::xml::sax::XAttributeList;
+using com::sun::star::xml::sax::XDocumentHandler;
+
+DocumentHandler::DocumentHandler(Reference<XDocumentHandler> const& xHandler)
+ : mxHandler(xHandler)
+{
+ if (SvXMLImport* pFastHandler = dynamic_cast<SvXMLImport*>(mxHandler.get()))
+ mxHandler.set(new SvXMLLegacyToFastDocHandler(pFastHandler));
+}
+
+void DocumentHandler::startDocument() { mxHandler->startDocument(); }
+
+void DocumentHandler::endDocument() { mxHandler->endDocument(); }
+
+void DocumentHandler::startElement(const char* psName,
+ const librevenge::RVNGPropertyList& xPropList)
+{
+ rtl::Reference<SvXMLAttributeList> pAttrList = new SvXMLAttributeList();
+ librevenge::RVNGPropertyList::Iter i(xPropList);
+ for (i.rewind(); i.next();)
+ {
+ // filter out librevenge elements
+ if (strncmp(i.key(), "librevenge", 10) != 0)
+ {
+ size_t keyLength = strlen(i.key());
+ OUString sName(i.key(), keyLength, RTL_TEXTENCODING_UTF8);
+ OUString sValue(i()->getStr().cstr(), i()->getStr().len(), RTL_TEXTENCODING_UTF8);
+
+ // libodfgen xml-encodes some attribute's value, so check if the value is encoded or not
+ for (int j = 0; j < 9; ++j)
+ {
+ // list of the encoded attributes followed by their lengths
+ static char const* listEncoded[9]
+ = { "draw:name", "svg:font-family", "style:condition",
+ "style:num-prefix", "style:num-suffix", "table:formula",
+ "text:bullet-char", "text:label", "xlink:href" };
+ static size_t const listEncodedLength[9] = { 9, 15, 15, 16, 16, 13, 16, 10, 10 };
+ if (keyLength == listEncodedLength[j]
+ && strncmp(i.key(), listEncoded[j], keyLength) == 0)
+ {
+ librevenge::RVNGString decodedValue("");
+ unescapeXML(i()->getStr().cstr(),
+ static_cast<unsigned long>(i()->getStr().len()), decodedValue);
+ sValue
+ = OUString(decodedValue.cstr(), decodedValue.len(), RTL_TEXTENCODING_UTF8);
+ break;
+ }
+ }
+ pAttrList->AddAttribute(sName, sValue);
+ }
+ }
+
+ OUString sElementName(psName, strlen(psName), RTL_TEXTENCODING_UTF8);
+ mxHandler->startElement(sElementName, pAttrList);
+}
+
+void DocumentHandler::endElement(const char* psName)
+{
+ OUString sElementName(psName, strlen(psName), RTL_TEXTENCODING_UTF8);
+ mxHandler->endElement(sElementName);
+}
+
+void DocumentHandler::characters(const librevenge::RVNGString& sCharacters)
+{
+ OUString sCharU16(sCharacters.cstr(), strlen(sCharacters.cstr()), RTL_TEXTENCODING_UTF8);
+ mxHandler->characters(sCharU16);
+}
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/writerperfect/source/common/WPFTEncodingDialog.cxx b/writerperfect/source/common/WPFTEncodingDialog.cxx
new file mode 100644
index 000000000..b0c955481
--- /dev/null
+++ b/writerperfect/source/common/WPFTEncodingDialog.cxx
@@ -0,0 +1,122 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sal/config.h>
+
+#include <cstddef>
+#include <string_view>
+#include <utility>
+
+#include <WPFTEncodingDialog.hxx>
+
+namespace writerperfect
+{
+namespace
+{
+std::pair<std::u16string_view, std::u16string_view> const s_encodings[]
+ = { { u"MacArabic", u"Arabic (Apple Macintosh)" },
+ { u"CP864", u"Arabic (DOS/OS2-864)" },
+ { u"CP1006", u"Arabic (IBM-1006)" },
+ { u"CP1256", u"Arabic (Windows-1256)" },
+ { u"CP775", u"Baltic (DOS/OS2-775)" },
+ { u"CP1257", u"Baltic (Windows-1257)" },
+ { u"MacCeltic", u"Celtic (Apple Macintosh)" },
+ { u"MacCyrillic", u"Cyrillic (Apple Macintosh)" },
+ { u"CP855", u"Cyrillic (DOS/OS2-855)" },
+ { u"CP866", u"Cyrillic (DOS/OS2-866/Russian)" },
+ { u"CP1251", u"Cyrillic (Windows-1251)" },
+ { u"MacCEurope", u"Eastern Europe (Apple Macintosh)" },
+ { u"MacCroatian", u"Eastern Europe (Apple Macintosh/Croatian)" },
+ { u"MacRomanian", u"Eastern Europe (Apple Macintosh/Romanian)" },
+ { u"CP852", u"Eastern Europe (DOS/OS2-852)" },
+ { u"CP1250", u"Eastern Europe (Windows-1250/WinLatin 2)" },
+ { u"MacGreek", u"Greek (Apple Macintosh)" },
+ { u"CP737", u"Greek (DOS/OS2-737)" },
+ { u"CP869", u"Greek (DOS/OS2-869/Greek-2)" },
+ { u"CP875", u"Greek (DOS/OS2-875)" },
+ { u"CP1253", u"Greek (Windows-1253)" },
+ { u"MacHebrew", u"Hebrew (Apple Macintosh)" },
+ { u"CP424", u"Hebrew (DOS/OS2-424)" },
+ { u"CP856", u"Hebrew (DOS/OS2-856)" },
+ { u"CP862", u"Hebrew (DOS/OS2-862)" },
+ { u"CP1255", u"Hebrew (Windows-1255)" },
+ { u"CP500", u"International (DOS/OS2-500)" },
+ { u"CP932", u"Japanese (Windows-932)" },
+ { u"MacThai", u"Thai (Apple Macintosh)" },
+ { u"CP874", u"Thai (DOS/OS2-874)" },
+ { u"CP950", u"Traditional Chinese (Windows-950)" },
+ { u"MacTurkish", u"Turkish (Apple Macintosh)" },
+ { u"CP857", u"Turkish (DOS/OS2-857)" },
+ { u"CP1026", u"Turkish (DOS/OS2-1026)" },
+ { u"CP1254", u"Turkish (Windows-1254)" },
+ { u"CP1258", u"Vietnamese (Windows-1258)" },
+ { u"MacRoman", u"Western Europe (Apple Macintosh)" },
+ { u"MacIceland", u"Western Europe (Apple Macintosh/Icelandic)" },
+ { u"CP037", u"Western Europe (DOS/OS2-037/US-Canada)" },
+ { u"CP437", u"Western Europe (DOS/OS2-437/US)" },
+ { u"CP850", u"Western Europe (DOS/OS2-850)" },
+ { u"CP860", u"Western Europe (DOS/OS2-860/Portuguese)" },
+ { u"CP861", u"Western Europe (DOS/OS2-861/Icelandic)" },
+ { u"CP863", u"Western Europe (DOS/OS2-863/French)" },
+ { u"CP865", u"Western Europe (DOS/OS2-865/Nordic)" },
+ { u"CP1252", u"Western Europe (Windows-1252/WinLatin 1)" } };
+
+std::size_t const numEncodings = SAL_N_ELEMENTS(s_encodings);
+
+void insertEncodings(weld::ComboBox& box)
+{
+ for (std::size_t i = 0; i < numEncodings; ++i)
+ box.append(OUString(s_encodings[i].first), OUString(s_encodings[i].second));
+}
+
+void selectEncoding(weld::ComboBox& box, const OUString& encoding) { box.set_active_id(encoding); }
+
+OUString getEncoding(const weld::ComboBox& box) { return box.get_active_id(); }
+}
+
+WPFTEncodingDialog::WPFTEncodingDialog(weld::Window* pParent, const OUString& title,
+ const OUString& encoding)
+ : GenericDialogController(pParent, "writerperfect/ui/wpftencodingdialog.ui",
+ "WPFTEncodingDialog")
+ , m_userHasCancelled(false)
+ , m_xLbCharset(m_xBuilder->weld_combo_box("comboboxtext"))
+ , m_xBtnOk(m_xBuilder->weld_button("ok"))
+ , m_xBtnCancel(m_xBuilder->weld_button("cancel"))
+{
+ m_xBtnCancel->connect_clicked(LINK(this, WPFTEncodingDialog, CancelHdl));
+
+ insertEncodings(*m_xLbCharset);
+ m_xLbCharset->make_sorted();
+ selectEncoding(*m_xLbCharset, encoding);
+
+ m_xDialog->set_title(title);
+}
+
+WPFTEncodingDialog::~WPFTEncodingDialog() {}
+
+OUString WPFTEncodingDialog::GetEncoding() const { return getEncoding(*m_xLbCharset); }
+
+IMPL_LINK_NOARG(WPFTEncodingDialog, CancelHdl, weld::Button&, void)
+{
+ m_userHasCancelled = true;
+ m_xDialog->response(RET_CANCEL);
+}
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/writerperfect/source/common/WPXSvInputStream.cxx b/writerperfect/source/common/WPXSvInputStream.cxx
new file mode 100644
index 000000000..3364b0509
--- /dev/null
+++ b/writerperfect/source/common/WPXSvInputStream.cxx
@@ -0,0 +1,960 @@
+/* -*- 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 <WPXSvInputStream.hxx>
+
+#include <com/sun/star/packages/zip/XZipFileAccess2.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+
+#include <comphelper/processfactory.hxx>
+#include <comphelper/seekableinput.hxx>
+#include <o3tl/safeint.hxx>
+#include <rtl/string.hxx>
+#include <sal/log.hxx>
+
+#include <sot/storage.hxx>
+
+#include <tools/stream.hxx>
+#include <unotools/streamwrap.hxx>
+#include <unotools/ucbstreamhelper.hxx>
+
+#include <climits>
+#include <limits>
+#include <memory>
+#include <string_view>
+#include <unordered_map>
+#include <vector>
+
+namespace writerperfect
+{
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::io;
+
+namespace container = com::sun::star::container;
+namespace packages = com::sun::star::packages;
+
+namespace
+{
+class PositionHolder
+{
+public:
+ explicit PositionHolder(const Reference<XSeekable>& rxSeekable);
+ ~PositionHolder();
+ PositionHolder(const PositionHolder&) = delete;
+ PositionHolder& operator=(const PositionHolder&) = delete;
+
+private:
+ const Reference<XSeekable> mxSeekable;
+ const sal_uInt64 mnPosition;
+};
+
+PositionHolder::PositionHolder(const Reference<XSeekable>& rxSeekable)
+ : mxSeekable(rxSeekable)
+ , mnPosition(rxSeekable->getPosition())
+{
+}
+
+PositionHolder::~PositionHolder()
+{
+ try
+ {
+ mxSeekable->seek(mnPosition);
+ }
+ catch (...)
+ {
+ }
+}
+
+} // anonymous namespace
+
+namespace
+{
+OUString lcl_normalizeSubStreamPath(const OUString& rPath)
+{
+ // accept paths which begin by '/'
+ // TODO: maybe this should do a full normalization
+ if (rPath.startsWith("/") && rPath.getLength() >= 2)
+ return rPath.copy(1);
+ return rPath;
+}
+}
+
+namespace
+{
+OUString concatPath(std::u16string_view lhs, const OUString& rhs)
+{
+ if (lhs.empty())
+ return rhs;
+ return OUString::Concat(lhs) + "/" + rhs;
+}
+
+struct OLEStreamData
+{
+ OLEStreamData(const OString& rName, const OString& rvngName);
+
+ tools::SvRef<SotStorageStream> stream;
+
+ /** Name of the stream.
+ *
+ * This is not @c OUString, because we need to be able to
+ * produce const char* from it.
+ */
+ OString name;
+ /** librevenge name of the stream.
+ *
+ * This is not @c OUString, because we need to be able to
+ * produce const char* from it.
+ */
+ OString RVNGname;
+};
+
+typedef std::unordered_map<OUString, std::size_t> NameMap_t;
+typedef std::unordered_map<OUString, tools::SvRef<SotStorage>> OLEStorageMap_t;
+
+/** Representation of an OLE2 storage.
+ *
+ * This class tries to bring a bit of sanity to use of SotStorage with
+ * respect to the needs of @c librevenge::RVNGInputStream API. It
+ * holds all nested storages for the whole lifetime (more precisely,
+ * since initialization, which is performed by calling @c
+ * initialize()), thus ensuring that no created stream is destroyed
+ * just because its parent storage went out of scope. It also holds a
+ * bidirectional map of stream names to their indexes (index of a
+ * stream is determined by deep-first traversal), which is also
+ * populated during initialization (member variables @c maStreams and
+ * @c maNameMap).
+ *
+ * Streams are created on demand (and saved, for the same reason as
+ * storages).
+ */
+struct OLEStorageImpl
+{
+ OLEStorageImpl();
+
+ void initialize(std::unique_ptr<SvStream> pStream);
+
+ tools::SvRef<SotStorageStream> getStream(const OUString& rPath);
+ tools::SvRef<SotStorageStream> const& getStream(std::size_t nId);
+
+private:
+ void traverse(const tools::SvRef<SotStorage>& rStorage, std::u16string_view rPath);
+
+ tools::SvRef<SotStorageStream> createStream(const OUString& rPath);
+
+public:
+ tools::SvRef<SotStorage> mxRootStorage; //< root storage of the OLE2
+ OLEStorageMap_t maStorageMap; //< map of all sub storages by name
+ ::std::vector<OLEStreamData> maStreams; //< list of streams and their names
+ NameMap_t maNameMap; //< map of stream names to indexes (into @c maStreams)
+ bool mbInitialized;
+};
+
+OLEStreamData::OLEStreamData(const OString& rName, const OString& rvngName)
+ : name(rName)
+ , RVNGname(rvngName)
+{
+}
+
+OLEStorageImpl::OLEStorageImpl()
+ : mbInitialized(false)
+{
+}
+
+void OLEStorageImpl::initialize(std::unique_ptr<SvStream> pStream)
+{
+ if (!pStream)
+ return;
+
+ mxRootStorage = new SotStorage(pStream.release(), true);
+
+ traverse(mxRootStorage, u"");
+
+ mbInitialized = true;
+}
+
+tools::SvRef<SotStorageStream> OLEStorageImpl::getStream(const OUString& rPath)
+{
+ const OUString aPath(lcl_normalizeSubStreamPath(rPath));
+ NameMap_t::iterator aIt = maNameMap.find(aPath);
+
+ // For the while don't return stream in this situation.
+ // Later, given how libcdr's zip stream implementation behaves,
+ // return the first stream in the storage if there is one.
+ if (maNameMap.end() == aIt)
+ return tools::SvRef<SotStorageStream>();
+
+ if (!maStreams[aIt->second].stream.is())
+ maStreams[aIt->second].stream
+ = createStream(OStringToOUString(maStreams[aIt->second].name, RTL_TEXTENCODING_UTF8));
+
+ return maStreams[aIt->second].stream;
+}
+
+tools::SvRef<SotStorageStream> const& OLEStorageImpl::getStream(const std::size_t nId)
+{
+ if (!maStreams[nId].stream.is())
+ maStreams[nId].stream
+ = createStream(OStringToOUString(maStreams[nId].name, RTL_TEXTENCODING_UTF8));
+
+ return maStreams[nId].stream;
+}
+
+void OLEStorageImpl::traverse(const tools::SvRef<SotStorage>& rStorage, std::u16string_view rPath)
+{
+ SvStorageInfoList infos;
+
+ rStorage->FillInfoList(&infos);
+
+ for (const auto& info : infos)
+ {
+ if (info.IsStream())
+ {
+ OUString baseName = info.GetName(), rvngName = baseName;
+ // librevenge::RVNGOLEStream ignores the first character when is a control code, so ...
+ if (!rvngName.isEmpty() && rvngName.toChar() < 32)
+ rvngName = rvngName.copy(1);
+ maStreams.emplace_back(
+ OUStringToOString(concatPath(rPath, baseName), RTL_TEXTENCODING_UTF8),
+ OUStringToOString(concatPath(rPath, rvngName), RTL_TEXTENCODING_UTF8));
+ maNameMap[concatPath(rPath, rvngName)] = maStreams.size() - 1;
+ }
+ else if (info.IsStorage())
+ {
+ const OUString aPath = concatPath(rPath, info.GetName());
+ tools::SvRef<SotStorage> aStorage
+ = rStorage->OpenSotStorage(info.GetName(), StreamMode::STD_READ);
+ maStorageMap[aPath] = aStorage;
+
+ // deep-first traversal
+ traverse(aStorage, aPath);
+ }
+ else
+ {
+ SAL_WARN("writerperfect",
+ "OLEStorageImpl::traverse: invalid storage entry, neither stream nor file");
+ }
+ }
+}
+
+tools::SvRef<SotStorageStream> OLEStorageImpl::createStream(const OUString& rPath)
+{
+ const sal_Int32 nDelim = rPath.lastIndexOf(u'/');
+
+ if (-1 == nDelim)
+ return mxRootStorage->OpenSotStream(rPath, StreamMode::STD_READ);
+
+ const OUString aDir = rPath.copy(0, nDelim);
+ const OUString aName = rPath.copy(nDelim + 1);
+
+ const OLEStorageMap_t::const_iterator aIt = maStorageMap.find(aDir);
+
+ if (maStorageMap.end() == aIt)
+ return nullptr;
+
+ return aIt->second->OpenSotStream(aName, StreamMode::STD_READ);
+}
+}
+
+namespace
+{
+struct ZipStreamData
+{
+ explicit ZipStreamData(const OString& rName);
+
+ Reference<XInputStream> xStream;
+
+ /** Name of the stream.
+ *
+ * This is not @c OUString, because we need to be able to
+ * produce const char* from it.
+ */
+ OString aName;
+};
+
+/** Representation of a Zip storage.
+ *
+ * This is quite similar to OLEStorageImpl, except that we do not need
+ * to keep all storages (folders) open.
+ */
+struct ZipStorageImpl
+{
+ explicit ZipStorageImpl(const Reference<container::XNameAccess>& rxContainer);
+
+ /** Initialize for access.
+ *
+ * This creates a bidirectional map of stream names to their
+ * indexes (index of a stream is determined by deep-first
+ * traversal).
+ */
+ void initialize();
+
+ Reference<XInputStream> getStream(const OUString& rPath);
+ Reference<XInputStream> const& getStream(std::size_t nId);
+
+private:
+ void traverse(const Reference<container::XNameAccess>& rxEnum);
+
+ Reference<XInputStream> createStream(const OUString& rPath);
+
+public:
+ Reference<container::XNameAccess> mxContainer; //< root of the Zip
+ ::std::vector<ZipStreamData> maStreams; //< list of streams and their names
+ NameMap_t maNameMap; //< map of stream names to indexes (into @c maStreams)
+ bool mbInitialized;
+};
+
+ZipStreamData::ZipStreamData(const OString& rName)
+ : aName(rName)
+{
+}
+
+ZipStorageImpl::ZipStorageImpl(const Reference<container::XNameAccess>& rxContainer)
+ : mxContainer(rxContainer)
+ , mbInitialized(false)
+{
+ assert(mxContainer.is());
+}
+
+void ZipStorageImpl::initialize()
+{
+ traverse(mxContainer);
+
+ mbInitialized = true;
+}
+
+Reference<XInputStream> ZipStorageImpl::getStream(const OUString& rPath)
+{
+ const OUString aPath(lcl_normalizeSubStreamPath(rPath));
+ NameMap_t::iterator aIt = maNameMap.find(aPath);
+
+ // For the while don't return stream in this situation.
+ // Later, given how libcdr's zip stream implementation behaves,
+ // return the first stream in the storage if there is one.
+ if (maNameMap.end() == aIt)
+ return Reference<XInputStream>();
+
+ if (!maStreams[aIt->second].xStream.is())
+ maStreams[aIt->second].xStream = createStream(aPath);
+
+ return maStreams[aIt->second].xStream;
+}
+
+Reference<XInputStream> const& ZipStorageImpl::getStream(const std::size_t nId)
+{
+ if (!maStreams[nId].xStream.is())
+ maStreams[nId].xStream
+ = createStream(OStringToOUString(maStreams[nId].aName, RTL_TEXTENCODING_UTF8));
+
+ return maStreams[nId].xStream;
+}
+
+void ZipStorageImpl::traverse(const Reference<container::XNameAccess>& rxContainer)
+{
+ const Sequence<OUString> lNames = rxContainer->getElementNames();
+
+ maStreams.reserve(lNames.getLength());
+
+ for (const auto& rName : lNames)
+ {
+ if (!rName.endsWith("/")) // skip dirs
+ {
+ maStreams.emplace_back(OUStringToOString(rName, RTL_TEXTENCODING_UTF8));
+ maNameMap[rName] = maStreams.size() - 1;
+ }
+ }
+}
+
+Reference<XInputStream> ZipStorageImpl::createStream(const OUString& rPath)
+{
+ Reference<XInputStream> xStream;
+
+ try
+ {
+ const Reference<XInputStream> xInputStream(mxContainer->getByName(rPath), UNO_QUERY_THROW);
+ const Reference<XSeekable> xSeekable(xInputStream, UNO_QUERY);
+
+ if (xSeekable.is())
+ xStream = xInputStream;
+ else
+ xStream.set(new comphelper::OSeekableInputWrapper(
+ xInputStream, comphelper::getProcessComponentContext()));
+ }
+ catch (const Exception&)
+ {
+ // nothing needed
+ }
+
+ return xStream;
+}
+}
+
+class WPXSvInputStreamImpl
+{
+public:
+ explicit WPXSvInputStreamImpl(css::uno::Reference<css::io::XInputStream> const& xStream);
+
+ bool isStructured();
+ unsigned subStreamCount();
+ const char* subStreamName(unsigned id);
+ bool existsSubStream(const char* name);
+ librevenge::RVNGInputStream* getSubStreamByName(const char* name);
+ librevenge::RVNGInputStream* getSubStreamById(unsigned id);
+
+ const unsigned char* read(unsigned long numBytes, unsigned long& numBytesRead);
+ int seek(tools::Long offset);
+ tools::Long tell();
+ bool isEnd();
+
+ void invalidateReadBuffer();
+
+private:
+ bool isOLE();
+ void ensureOLEIsInitialized();
+
+ bool isZip();
+ void ensureZipIsInitialized();
+
+ static librevenge::RVNGInputStream*
+ createWPXStream(const tools::SvRef<SotStorageStream>& rxStorage);
+ static librevenge::RVNGInputStream* createWPXStream(const Reference<XInputStream>& rxStream);
+
+private:
+ css::uno::Reference<css::io::XInputStream> mxStream;
+ css::uno::Reference<css::io::XSeekable> mxSeekable;
+ css::uno::Sequence<sal_Int8> maData;
+ std::unique_ptr<OLEStorageImpl> mpOLEStorage;
+ std::unique_ptr<ZipStorageImpl> mpZipStorage;
+ bool mbCheckedOLE;
+ bool mbCheckedZip;
+
+public:
+ sal_Int64 mnLength;
+ const unsigned char* mpReadBuffer;
+ unsigned long mnReadBufferLength;
+ unsigned long mnReadBufferPos;
+};
+
+WPXSvInputStreamImpl::WPXSvInputStreamImpl(Reference<XInputStream> const& xStream)
+ : mxStream(xStream)
+ , mxSeekable(xStream, UNO_QUERY)
+ , maData(0)
+ , mbCheckedOLE(false)
+ , mbCheckedZip(false)
+ , mnLength(0)
+ , mpReadBuffer(nullptr)
+ , mnReadBufferLength(0)
+ , mnReadBufferPos(0)
+{
+ if (!xStream.is() || !mxStream.is())
+ mnLength = 0;
+ else
+ {
+ if (!mxSeekable.is())
+ mnLength = 0;
+ else
+ {
+ try
+ {
+ mnLength = mxSeekable->getLength();
+ if (0 < mxSeekable->getPosition())
+ mxSeekable->seek(0);
+ }
+ catch (...)
+ {
+ SAL_WARN("writerperfect", "mnLength = mxSeekable->getLength() threw exception");
+ mnLength = 0;
+ }
+ }
+ }
+}
+
+const unsigned char* WPXSvInputStreamImpl::read(unsigned long numBytes, unsigned long& numBytesRead)
+{
+ numBytesRead = 0;
+
+ if (numBytes == 0 || isEnd())
+ return nullptr;
+
+ numBytesRead = mxStream->readSomeBytes(maData, numBytes);
+ if (numBytesRead == 0)
+ return nullptr;
+
+ return reinterpret_cast<const unsigned char*>(maData.getConstArray());
+}
+
+tools::Long WPXSvInputStreamImpl::tell()
+{
+ if ((mnLength == 0) || !mxStream.is() || !mxSeekable.is())
+ return -1;
+ else
+ {
+ const sal_Int64 tmpPosition = mxSeekable->getPosition();
+ if ((tmpPosition < 0) || (tmpPosition > LONG_MAX))
+ return -1;
+ return static_cast<tools::Long>(tmpPosition);
+ }
+}
+
+int WPXSvInputStreamImpl::seek(tools::Long offset)
+{
+ if ((mnLength == 0) || !mxStream.is() || !mxSeekable.is())
+ return -1;
+
+ const sal_Int64 tmpPosition = mxSeekable->getPosition();
+ if ((tmpPosition < 0) || (tmpPosition > LONG_MAX))
+ return -1;
+
+ try
+ {
+ mxSeekable->seek(offset);
+ return 0;
+ }
+ catch (...)
+ {
+ SAL_WARN("writerperfect", "mxSeekable->seek(offset) threw exception");
+ return -1;
+ }
+}
+
+bool WPXSvInputStreamImpl::isEnd()
+{
+ if ((mnLength == 0) || !mxStream.is() || !mxSeekable.is())
+ return true;
+ return (mxSeekable->getPosition() >= mnLength);
+}
+
+bool WPXSvInputStreamImpl::isStructured()
+{
+ if ((mnLength == 0) || !mxStream.is() || !mxSeekable.is())
+ return false;
+
+ PositionHolder pos(mxSeekable);
+ mxSeekable->seek(0);
+
+ if (isOLE())
+ return true;
+
+ mxSeekable->seek(0);
+
+ return isZip();
+}
+
+unsigned WPXSvInputStreamImpl::subStreamCount()
+{
+ if ((mnLength == 0) || !mxStream.is() || !mxSeekable.is())
+ return 0;
+
+ PositionHolder pos(mxSeekable);
+ mxSeekable->seek(0);
+
+ if (isOLE())
+ {
+ ensureOLEIsInitialized();
+
+ return mpOLEStorage->maStreams.size();
+ }
+
+ mxSeekable->seek(0);
+
+ if (isZip())
+ {
+ ensureZipIsInitialized();
+
+ return mpZipStorage->maStreams.size();
+ }
+
+ return 0;
+}
+
+const char* WPXSvInputStreamImpl::subStreamName(const unsigned id)
+{
+ if ((mnLength == 0) || !mxStream.is() || !mxSeekable.is())
+ return nullptr;
+
+ PositionHolder pos(mxSeekable);
+ mxSeekable->seek(0);
+
+ if (isOLE())
+ {
+ ensureOLEIsInitialized();
+
+ if (mpOLEStorage->maStreams.size() <= id)
+ return nullptr;
+
+ return mpOLEStorage->maStreams[id].RVNGname.getStr();
+ }
+
+ mxSeekable->seek(0);
+
+ if (isZip())
+ {
+ ensureZipIsInitialized();
+
+ if (mpZipStorage->maStreams.size() <= id)
+ return nullptr;
+
+ return mpZipStorage->maStreams[id].aName.getStr();
+ }
+
+ return nullptr;
+}
+
+bool WPXSvInputStreamImpl::existsSubStream(const char* const name)
+{
+ if (!name)
+ return false;
+
+ if ((mnLength == 0) || !mxStream.is() || !mxSeekable.is())
+ return false;
+
+ PositionHolder pos(mxSeekable);
+ mxSeekable->seek(0);
+
+ const OUString aName(OStringToOUString(std::string_view(name), RTL_TEXTENCODING_UTF8));
+
+ if (isOLE())
+ {
+ ensureOLEIsInitialized();
+ return mpOLEStorage->maNameMap.end() != mpOLEStorage->maNameMap.find(aName);
+ }
+
+ mxSeekable->seek(0);
+
+ if (isZip())
+ {
+ ensureZipIsInitialized();
+ return mpZipStorage->maNameMap.end() != mpZipStorage->maNameMap.find(aName);
+ }
+
+ return false;
+}
+
+librevenge::RVNGInputStream* WPXSvInputStreamImpl::getSubStreamByName(const char* const name)
+{
+ if (!name)
+ return nullptr;
+
+ if ((mnLength == 0) || !mxStream.is() || !mxSeekable.is())
+ return nullptr;
+
+ PositionHolder pos(mxSeekable);
+ mxSeekable->seek(0);
+
+ const OUString aName(OStringToOUString(std::string_view(name), RTL_TEXTENCODING_UTF8));
+
+ if (isOLE())
+ {
+ ensureOLEIsInitialized();
+ return createWPXStream(mpOLEStorage->getStream(aName));
+ }
+
+ mxSeekable->seek(0);
+
+ if (isZip())
+ {
+ ensureZipIsInitialized();
+
+ try
+ {
+ return createWPXStream(mpZipStorage->getStream(aName));
+ }
+ catch (const Exception&)
+ {
+ // nothing needed
+ }
+ }
+
+ return nullptr;
+}
+
+librevenge::RVNGInputStream* WPXSvInputStreamImpl::getSubStreamById(const unsigned id)
+{
+ if ((mnLength == 0) || !mxStream.is() || !mxSeekable.is())
+ return nullptr;
+
+ PositionHolder pos(mxSeekable);
+ mxSeekable->seek(0);
+
+ if (isOLE())
+ {
+ ensureOLEIsInitialized();
+
+ if (mpOLEStorage->maStreams.size() <= id)
+ return nullptr;
+
+ return createWPXStream(mpOLEStorage->getStream(id));
+ }
+
+ mxSeekable->seek(0);
+
+ if (isZip())
+ {
+ ensureZipIsInitialized();
+
+ if (mpZipStorage->maStreams.size() <= id)
+ return nullptr;
+
+ try
+ {
+ return createWPXStream(mpZipStorage->getStream(id));
+ }
+ catch (const Exception&)
+ {
+ // nothing needed
+ }
+ }
+ return nullptr;
+}
+
+void WPXSvInputStreamImpl::invalidateReadBuffer()
+{
+ if (mpReadBuffer)
+ {
+ seek(tell() + static_cast<tools::Long>(mnReadBufferPos)
+ - static_cast<tools::Long>(mnReadBufferLength));
+ mpReadBuffer = nullptr;
+ mnReadBufferPos = 0;
+ mnReadBufferLength = 0;
+ }
+}
+
+librevenge::RVNGInputStream*
+WPXSvInputStreamImpl::createWPXStream(const tools::SvRef<SotStorageStream>& rxStorage)
+{
+ if (rxStorage.is())
+ {
+ Reference<XInputStream> xContents(new utl::OSeekableInputStreamWrapper(rxStorage.get()));
+ return new WPXSvInputStream(xContents);
+ }
+ return nullptr;
+}
+
+librevenge::RVNGInputStream*
+WPXSvInputStreamImpl::createWPXStream(const Reference<XInputStream>& rxStream)
+{
+ if (rxStream.is())
+ return new WPXSvInputStream(rxStream);
+ else
+ return nullptr;
+}
+
+bool WPXSvInputStreamImpl::isOLE()
+{
+ if (!mbCheckedOLE)
+ {
+ assert(0 == mxSeekable->getPosition());
+
+ std::unique_ptr<SvStream> pStream(utl::UcbStreamHelper::CreateStream(mxStream));
+ if (pStream && SotStorage::IsOLEStorage(pStream.get()))
+ mpOLEStorage.reset(new OLEStorageImpl());
+
+ mbCheckedOLE = true;
+ }
+
+ return bool(mpOLEStorage);
+}
+
+bool WPXSvInputStreamImpl::isZip()
+{
+ if (!mbCheckedZip)
+ {
+ assert(0 == mxSeekable->getPosition());
+
+ try
+ {
+ const Reference<XComponentContext> xContext(comphelper::getProcessComponentContext(),
+ UNO_SET_THROW);
+ const Reference<packages::zip::XZipFileAccess2> xZip(
+ xContext->getServiceManager()->createInstanceWithArgumentsAndContext(
+ "com.sun.star.packages.zip.ZipFileAccess", { Any(mxStream) }, xContext),
+ UNO_QUERY_THROW);
+ mpZipStorage.reset(new ZipStorageImpl(xZip));
+ }
+ catch (const Exception&)
+ {
+ // ignore
+ }
+
+ mbCheckedZip = true;
+ }
+
+ return bool(mpZipStorage);
+}
+
+void WPXSvInputStreamImpl::ensureOLEIsInitialized()
+{
+ assert(mpOLEStorage);
+
+ if (!mpOLEStorage->mbInitialized)
+ mpOLEStorage->initialize(utl::UcbStreamHelper::CreateStream(mxStream));
+}
+
+void WPXSvInputStreamImpl::ensureZipIsInitialized()
+{
+ assert(mpZipStorage);
+
+ if (!mpZipStorage->mbInitialized)
+ mpZipStorage->initialize();
+}
+
+WPXSvInputStream::WPXSvInputStream(Reference<XInputStream> const& xStream)
+ : mpImpl(new WPXSvInputStreamImpl(xStream))
+{
+}
+
+WPXSvInputStream::~WPXSvInputStream() {}
+
+#define BUFFER_MAX 65536
+
+const unsigned char* WPXSvInputStream::read(unsigned long numBytes, unsigned long& numBytesRead)
+{
+ numBytesRead = 0;
+
+ if (numBytes == 0 || numBytes > std::numeric_limits<unsigned long>::max() / 2)
+ return nullptr;
+
+ if (mpImpl->mpReadBuffer)
+ {
+ if ((mpImpl->mnReadBufferPos + numBytes > mpImpl->mnReadBufferPos)
+ && (mpImpl->mnReadBufferPos + numBytes <= mpImpl->mnReadBufferLength))
+ {
+ const unsigned char* pTmp = mpImpl->mpReadBuffer + mpImpl->mnReadBufferPos;
+ mpImpl->mnReadBufferPos += numBytes;
+ numBytesRead = numBytes;
+ return pTmp;
+ }
+
+ mpImpl->invalidateReadBuffer();
+ }
+
+ unsigned long curpos = static_cast<unsigned long>(mpImpl->tell());
+ if (curpos == static_cast<unsigned long>(-1)) // returned ERROR
+ return nullptr;
+
+ if ((curpos + numBytes < curpos) /*overflow*/
+ || (curpos + numBytes
+ >= o3tl::make_unsigned(mpImpl->mnLength))) /*reading more than available*/
+ {
+ numBytes = mpImpl->mnLength - curpos;
+ }
+
+ if (numBytes < BUFFER_MAX)
+ {
+ if (BUFFER_MAX < mpImpl->mnLength - curpos)
+ mpImpl->mnReadBufferLength = BUFFER_MAX;
+ else /* BUFFER_MAX >= mpImpl->mnLength - curpos */
+ mpImpl->mnReadBufferLength = mpImpl->mnLength - curpos;
+ }
+ else
+ mpImpl->mnReadBufferLength = numBytes;
+
+ unsigned long tmpNumBytes(0);
+ mpImpl->mpReadBuffer = mpImpl->read(mpImpl->mnReadBufferLength, tmpNumBytes);
+ if (tmpNumBytes != mpImpl->mnReadBufferLength)
+ mpImpl->mnReadBufferLength = tmpNumBytes;
+
+ mpImpl->mnReadBufferPos = 0;
+ if (!mpImpl->mnReadBufferLength)
+ return nullptr;
+
+ if (numBytes <= mpImpl->mnReadBufferLength)
+ numBytesRead = numBytes;
+ else
+ numBytesRead = mpImpl->mnReadBufferLength;
+
+ mpImpl->mnReadBufferPos += numBytesRead;
+ return mpImpl->mpReadBuffer;
+}
+
+long WPXSvInputStream::tell()
+{
+ tools::Long retVal = mpImpl->tell();
+ return retVal - static_cast<tools::Long>(mpImpl->mnReadBufferLength)
+ + static_cast<tools::Long>(mpImpl->mnReadBufferPos);
+}
+
+int WPXSvInputStream::seek(long offset, librevenge::RVNG_SEEK_TYPE seekType)
+{
+ sal_Int64 tmpOffset = offset;
+ if (seekType == librevenge::RVNG_SEEK_CUR)
+ tmpOffset += tell();
+ if (seekType == librevenge::RVNG_SEEK_END)
+ tmpOffset += mpImpl->mnLength;
+
+ int retVal = 0;
+ if (tmpOffset < 0)
+ {
+ tmpOffset = 0;
+ retVal = -1;
+ }
+ if (tmpOffset > mpImpl->mnLength)
+ {
+ tmpOffset = mpImpl->mnLength;
+ retVal = -1;
+ }
+
+ if (tmpOffset < mpImpl->tell()
+ && o3tl::make_unsigned(tmpOffset)
+ >= static_cast<unsigned long>(mpImpl->tell()) - mpImpl->mnReadBufferLength)
+ {
+ mpImpl->mnReadBufferPos = static_cast<unsigned long>(
+ tmpOffset + static_cast<tools::Long>(mpImpl->mnReadBufferLength) - mpImpl->tell());
+ return retVal;
+ }
+
+ mpImpl->invalidateReadBuffer();
+
+ if (mpImpl->seek(tmpOffset))
+ return -1;
+ return retVal;
+}
+
+bool WPXSvInputStream::isEnd()
+{
+ return mpImpl->isEnd() && mpImpl->mnReadBufferPos == mpImpl->mnReadBufferLength;
+}
+
+bool WPXSvInputStream::isStructured()
+{
+ mpImpl->invalidateReadBuffer();
+ return mpImpl->isStructured();
+}
+
+unsigned WPXSvInputStream::subStreamCount()
+{
+ mpImpl->invalidateReadBuffer();
+ return mpImpl->subStreamCount();
+}
+
+const char* WPXSvInputStream::subStreamName(const unsigned id)
+{
+ mpImpl->invalidateReadBuffer();
+ return mpImpl->subStreamName(id);
+}
+
+bool WPXSvInputStream::existsSubStream(const char* const name)
+{
+ mpImpl->invalidateReadBuffer();
+ return mpImpl->existsSubStream(name);
+}
+
+librevenge::RVNGInputStream* WPXSvInputStream::getSubStreamByName(const char* name)
+{
+ mpImpl->invalidateReadBuffer();
+ return mpImpl->getSubStreamByName(name);
+}
+
+librevenge::RVNGInputStream* WPXSvInputStream::getSubStreamById(const unsigned id)
+{
+ mpImpl->invalidateReadBuffer();
+ return mpImpl->getSubStreamById(id);
+}
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/writerperfect/source/draw/CDRImportFilter.cxx b/writerperfect/source/draw/CDRImportFilter.cxx
new file mode 100644
index 000000000..34b490326
--- /dev/null
+++ b/writerperfect/source/draw/CDRImportFilter.cxx
@@ -0,0 +1,60 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* CDRImportFilter: Sets up the filter, and calls OdgExporter
+ * to do the actual filtering
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+/* "This product is not manufactured, approved, or supported by
+ * Corel Corporation or Corel Corporation Limited."
+ */
+
+#include <cppuhelper/supportsservice.hxx>
+
+#include <libcdr/libcdr.h>
+
+#include "CDRImportFilter.hxx"
+
+bool CDRImportFilter::doImportDocument(weld::Window*, librevenge::RVNGInputStream& rInput,
+ OdgGenerator& rGenerator, utl::MediaDescriptor&)
+{
+ return libcdr::CDRDocument::parse(&rInput, &rGenerator);
+}
+
+bool CDRImportFilter::doDetectFormat(librevenge::RVNGInputStream& rInput, OUString& rTypeName)
+{
+ if (libcdr::CDRDocument::isSupported(&rInput))
+ {
+ rTypeName = "draw_CorelDraw_Document";
+ return true;
+ }
+
+ return false;
+}
+
+// XServiceInfo
+OUString SAL_CALL CDRImportFilter::getImplementationName()
+{
+ return "com.sun.star.comp.Draw.CDRImportFilter";
+}
+
+sal_Bool SAL_CALL CDRImportFilter::supportsService(const OUString& rServiceName)
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+css::uno::Sequence<OUString> SAL_CALL CDRImportFilter::getSupportedServiceNames()
+{
+ return { "com.sun.star.document.ImportFilter", "com.sun.star.document.ExtendedTypeDetection" };
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+com_sun_star_comp_Draw_CDRImportFilter_get_implementation(
+ css::uno::XComponentContext* const context, const css::uno::Sequence<css::uno::Any>&)
+{
+ return cppu::acquire(new CDRImportFilter(context));
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/writerperfect/source/draw/CDRImportFilter.hxx b/writerperfect/source/draw/CDRImportFilter.hxx
new file mode 100644
index 000000000..0e8247131
--- /dev/null
+++ b/writerperfect/source/draw/CDRImportFilter.hxx
@@ -0,0 +1,39 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+/* "This product is not manufactured, approved, or supported by
+ * Corel Corporation or Corel Corporation Limited."
+ */
+#pragma once
+
+#include <ImportFilter.hxx>
+
+#include <DocumentHandlerForOdg.hxx>
+
+/* This component will be instantiated for both import or export. Whether it calls
+ * setSourceDocument or setTargetDocument determines which Impl function the filter
+ * member calls */
+class CDRImportFilter : public writerperfect::ImportFilter<OdgGenerator>
+{
+public:
+ explicit CDRImportFilter(const css::uno::Reference<css::uno::XComponentContext>& rxContext)
+ : writerperfect::ImportFilter<OdgGenerator>(rxContext)
+ {
+ }
+
+ // XServiceInfo
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override;
+ virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override;
+
+private:
+ virtual bool doDetectFormat(librevenge::RVNGInputStream& rInput, OUString& rTypeName) override;
+ virtual bool doImportDocument(weld::Window* pParent, librevenge::RVNGInputStream& rInput,
+ OdgGenerator& rGenerator, utl::MediaDescriptor&) override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/writerperfect/source/draw/CMXImportFilter.cxx b/writerperfect/source/draw/CMXImportFilter.cxx
new file mode 100644
index 000000000..23aab816a
--- /dev/null
+++ b/writerperfect/source/draw/CMXImportFilter.cxx
@@ -0,0 +1,60 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* CMXImportFilter: Sets up the filter, and calls OdgExporter
+ * to do the actual filtering
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+/* "This product is not manufactured, approved, or supported by
+ * Corel Corporation or Corel Corporation Limited."
+ */
+
+#include <cppuhelper/supportsservice.hxx>
+
+#include <libcdr/libcdr.h>
+
+#include "CMXImportFilter.hxx"
+
+bool CMXImportFilter::doImportDocument(weld::Window*, librevenge::RVNGInputStream& rInput,
+ OdgGenerator& rGenerator, utl::MediaDescriptor&)
+{
+ return libcdr::CMXDocument::parse(&rInput, &rGenerator);
+}
+
+bool CMXImportFilter::doDetectFormat(librevenge::RVNGInputStream& rInput, OUString& rTypeName)
+{
+ if (libcdr::CMXDocument::isSupported(&rInput))
+ {
+ rTypeName = "draw_Corel_Presentation_Exchange";
+ return true;
+ }
+
+ return false;
+}
+
+// XServiceInfo
+OUString SAL_CALL CMXImportFilter::getImplementationName()
+{
+ return "com.sun.star.comp.Draw.CMXImportFilter";
+}
+
+sal_Bool SAL_CALL CMXImportFilter::supportsService(const OUString& rServiceName)
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+css::uno::Sequence<OUString> SAL_CALL CMXImportFilter::getSupportedServiceNames()
+{
+ return { "com.sun.star.document.ImportFilter", "com.sun.star.document.ExtendedTypeDetection" };
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+com_sun_star_comp_Draw_CMXImportFilter_get_implementation(
+ css::uno::XComponentContext* const context, const css::uno::Sequence<css::uno::Any>&)
+{
+ return cppu::acquire(new CMXImportFilter(context));
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/writerperfect/source/draw/CMXImportFilter.hxx b/writerperfect/source/draw/CMXImportFilter.hxx
new file mode 100644
index 000000000..cc3b19428
--- /dev/null
+++ b/writerperfect/source/draw/CMXImportFilter.hxx
@@ -0,0 +1,39 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+/* "This product is not manufactured, approved, or supported by
+ * Corel Corporation or Corel Corporation Limited."
+ */
+#pragma once
+
+#include <ImportFilter.hxx>
+
+#include <DocumentHandlerForOdg.hxx>
+
+/* This component will be instantiated for both import or export. Whether it calls
+ * setSourceDocument or setTargetDocument determines which Impl function the filter
+ * member calls */
+class CMXImportFilter : public writerperfect::ImportFilter<OdgGenerator>
+{
+public:
+ explicit CMXImportFilter(const css::uno::Reference<css::uno::XComponentContext>& rxContext)
+ : writerperfect::ImportFilter<OdgGenerator>(rxContext)
+ {
+ }
+
+ // XServiceInfo
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override;
+ virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override;
+
+private:
+ virtual bool doDetectFormat(librevenge::RVNGInputStream& rInput, OUString& rTypeName) override;
+ virtual bool doImportDocument(weld::Window* pParent, librevenge::RVNGInputStream& rInput,
+ OdgGenerator& rGenerator, utl::MediaDescriptor&) override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/writerperfect/source/draw/FreehandImportFilter.cxx b/writerperfect/source/draw/FreehandImportFilter.cxx
new file mode 100644
index 000000000..68dd7b56b
--- /dev/null
+++ b/writerperfect/source/draw/FreehandImportFilter.cxx
@@ -0,0 +1,56 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* FreehandImportFilter: Sets up the filter, and calls OdgExporter
+ * to do the actual filtering
+ *
+ * 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 <cppuhelper/supportsservice.hxx>
+
+#include <libfreehand/libfreehand.h>
+
+#include "FreehandImportFilter.hxx"
+
+bool FreehandImportFilter::doImportDocument(weld::Window*, librevenge::RVNGInputStream& rInput,
+ OdgGenerator& rGenerator, utl::MediaDescriptor&)
+{
+ return libfreehand::FreeHandDocument::parse(&rInput, &rGenerator);
+}
+
+bool FreehandImportFilter::doDetectFormat(librevenge::RVNGInputStream& rInput, OUString& rTypeName)
+{
+ if (libfreehand::FreeHandDocument::isSupported(&rInput))
+ {
+ rTypeName = "draw_Freehand_Document";
+ return true;
+ }
+
+ return false;
+}
+
+// XServiceInfo
+OUString SAL_CALL FreehandImportFilter::getImplementationName()
+{
+ return "com.sun.star.comp.Draw.FreehandImportFilter";
+}
+
+sal_Bool SAL_CALL FreehandImportFilter::supportsService(const OUString& rServiceName)
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+css::uno::Sequence<OUString> SAL_CALL FreehandImportFilter::getSupportedServiceNames()
+{
+ return { "com.sun.star.document.ImportFilter", "com.sun.star.document.ExtendedTypeDetection" };
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+com_sun_star_comp_Draw_FreehandImportFilter_get_implementation(
+ css::uno::XComponentContext* const context, const css::uno::Sequence<css::uno::Any>&)
+{
+ return cppu::acquire(new FreehandImportFilter(context));
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/writerperfect/source/draw/FreehandImportFilter.hxx b/writerperfect/source/draw/FreehandImportFilter.hxx
new file mode 100644
index 000000000..083218117
--- /dev/null
+++ b/writerperfect/source/draw/FreehandImportFilter.hxx
@@ -0,0 +1,36 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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 <ImportFilter.hxx>
+
+#include <DocumentHandlerForOdg.hxx>
+
+/* This component will be instantiated for both import or export. Whether it calls
+ * setSourceDocument or setTargetDocument determines which Impl function the filter
+ * member calls */
+class FreehandImportFilter : public writerperfect::ImportFilter<OdgGenerator>
+{
+public:
+ explicit FreehandImportFilter(const css::uno::Reference<css::uno::XComponentContext>& rxContext)
+ : writerperfect::ImportFilter<OdgGenerator>(rxContext)
+ {
+ }
+
+ // XServiceInfo
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override;
+ virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override;
+
+private:
+ virtual bool doDetectFormat(librevenge::RVNGInputStream& rInput, OUString& rTypeName) override;
+ virtual bool doImportDocument(weld::Window* pParent, librevenge::RVNGInputStream& rInput,
+ OdgGenerator& rGenerator, utl::MediaDescriptor&) override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/writerperfect/source/draw/MSPUBImportFilter.cxx b/writerperfect/source/draw/MSPUBImportFilter.cxx
new file mode 100644
index 000000000..ba34cd2f1
--- /dev/null
+++ b/writerperfect/source/draw/MSPUBImportFilter.cxx
@@ -0,0 +1,56 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* MSPUBImportFilter: Sets up the filter, and calls OdgExporter
+ * to do the actual filtering
+ *
+ * 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 <cppuhelper/supportsservice.hxx>
+
+#include <libmspub/libmspub.h>
+
+#include "MSPUBImportFilter.hxx"
+
+bool MSPUBImportFilter::doImportDocument(weld::Window*, librevenge::RVNGInputStream& rInput,
+ OdgGenerator& rGenerator, utl::MediaDescriptor&)
+{
+ return libmspub::MSPUBDocument::parse(&rInput, &rGenerator);
+}
+
+bool MSPUBImportFilter::doDetectFormat(librevenge::RVNGInputStream& rInput, OUString& rTypeName)
+{
+ if (libmspub::MSPUBDocument::isSupported(&rInput))
+ {
+ rTypeName = "draw_Publisher_Document";
+ return true;
+ }
+
+ return false;
+}
+
+// XServiceInfo
+OUString SAL_CALL MSPUBImportFilter::getImplementationName()
+{
+ return "com.sun.star.comp.Draw.MSPUBImportFilter";
+}
+
+sal_Bool SAL_CALL MSPUBImportFilter::supportsService(const OUString& rServiceName)
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+css::uno::Sequence<OUString> SAL_CALL MSPUBImportFilter::getSupportedServiceNames()
+{
+ return { "com.sun.star.document.ImportFilter", "com.sun.star.document.ExtendedTypeDetection" };
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+com_sun_star_comp_Draw_MSPUBImportFilter_get_implementation(
+ css::uno::XComponentContext* const context, const css::uno::Sequence<css::uno::Any>&)
+{
+ return cppu::acquire(new MSPUBImportFilter(context));
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/writerperfect/source/draw/MSPUBImportFilter.hxx b/writerperfect/source/draw/MSPUBImportFilter.hxx
new file mode 100644
index 000000000..a84302703
--- /dev/null
+++ b/writerperfect/source/draw/MSPUBImportFilter.hxx
@@ -0,0 +1,36 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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 <ImportFilter.hxx>
+
+#include <DocumentHandlerForOdg.hxx>
+
+/* This component will be instantiated for both import or export. Whether it calls
+ * setSourceDocument or setTargetDocument determines which Impl function the filter
+ * member calls */
+class MSPUBImportFilter : public writerperfect::ImportFilter<OdgGenerator>
+{
+public:
+ explicit MSPUBImportFilter(const css::uno::Reference<css::uno::XComponentContext>& rxContext)
+ : writerperfect::ImportFilter<OdgGenerator>(rxContext)
+ {
+ }
+
+ // XServiceInfo
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override;
+ virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override;
+
+private:
+ virtual bool doDetectFormat(librevenge::RVNGInputStream& rInput, OUString& rTypeName) override;
+ virtual bool doImportDocument(weld::Window* pParent, librevenge::RVNGInputStream& rInput,
+ OdgGenerator& rGenerator, utl::MediaDescriptor&) override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/writerperfect/source/draw/MWAWDrawImportFilter.cxx b/writerperfect/source/draw/MWAWDrawImportFilter.cxx
new file mode 100644
index 000000000..000debdcb
--- /dev/null
+++ b/writerperfect/source/draw/MWAWDrawImportFilter.cxx
@@ -0,0 +1,116 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* MWAWDrawImportFilter: Sets up the filter, and calls DocumentCollector
+ * to do the actual filtering
+ *
+ * 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 <cppuhelper/supportsservice.hxx>
+
+#include <libmwaw/libmwaw.hxx>
+
+#include "MWAWDrawImportFilter.hxx"
+
+static bool handleEmbeddedMWAWGraphicObject(const librevenge::RVNGBinaryData& data,
+ OdfDocumentHandler* pHandler,
+ const OdfStreamType streamType)
+{
+ OdgGenerator exporter;
+ exporter.addDocumentHandler(pHandler, streamType);
+ return MWAWDocument::decodeGraphic(data, &exporter);
+}
+
+static bool handleEmbeddedMWAWSpreadsheetObject(const librevenge::RVNGBinaryData& data,
+ OdfDocumentHandler* pHandler,
+ const OdfStreamType streamType)
+{
+ OdsGenerator exporter;
+ exporter.registerEmbeddedObjectHandler("image/mwaw-odg", &handleEmbeddedMWAWGraphicObject);
+ exporter.addDocumentHandler(pHandler, streamType);
+ return MWAWDocument::decodeSpreadsheet(data, &exporter);
+}
+
+bool MWAWDrawImportFilter::doImportDocument(weld::Window*, librevenge::RVNGInputStream& rInput,
+ OdgGenerator& rGenerator, utl::MediaDescriptor&)
+{
+ return MWAWDocument::MWAW_R_OK == MWAWDocument::parse(&rInput, &rGenerator);
+}
+
+bool MWAWDrawImportFilter::doDetectFormat(librevenge::RVNGInputStream& rInput, OUString& rTypeName)
+{
+ rTypeName.clear();
+
+ MWAWDocument::Type docType = MWAWDocument::MWAW_T_UNKNOWN;
+ MWAWDocument::Kind docKind = MWAWDocument::MWAW_K_UNKNOWN;
+ const MWAWDocument::Confidence confidence
+ = MWAWDocument::isFileFormatSupported(&rInput, docType, docKind);
+
+ if (confidence == MWAWDocument::MWAW_C_EXCELLENT)
+ {
+ switch (docKind)
+ {
+ case MWAWDocument::MWAW_K_DRAW:
+ switch (docType)
+ {
+ case MWAWDocument::MWAW_T_CLARISWORKS:
+ rTypeName = "draw_ClarisWorks";
+ break;
+ default:
+ rTypeName = "MWAW_Drawing";
+ break;
+ }
+ break;
+ case MWAWDocument::MWAW_K_PAINT:
+ switch (docType)
+ {
+ case MWAWDocument::MWAW_T_CLARISWORKS:
+ rTypeName = "draw_ClarisWorks";
+ break;
+ default:
+ rTypeName = "MWAW_Bitmap";
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ return !rTypeName.isEmpty();
+}
+
+void MWAWDrawImportFilter::doRegisterHandlers(OdgGenerator& rGenerator)
+{
+ rGenerator.registerEmbeddedObjectHandler("image/mwaw-odg", &handleEmbeddedMWAWGraphicObject);
+ rGenerator.registerEmbeddedObjectHandler("image/mwaw-ods",
+ &handleEmbeddedMWAWSpreadsheetObject);
+}
+
+// XServiceInfo
+OUString SAL_CALL MWAWDrawImportFilter::getImplementationName()
+{
+ return "com.sun.star.comp.Draw.MWAWDrawImportFilter";
+}
+
+sal_Bool SAL_CALL MWAWDrawImportFilter::supportsService(const OUString& rServiceName)
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+css::uno::Sequence<OUString> SAL_CALL MWAWDrawImportFilter::getSupportedServiceNames()
+{
+ return { "com.sun.star.document.ImportFilter", "com.sun.star.document.ExtendedTypeDetection" };
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+com_sun_star_comp_Draw_MWAWDrawImportFilter_get_implementation(
+ css::uno::XComponentContext* const context, const css::uno::Sequence<css::uno::Any>&)
+{
+ return cppu::acquire(new MWAWDrawImportFilter(context));
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/writerperfect/source/draw/MWAWDrawImportFilter.hxx b/writerperfect/source/draw/MWAWDrawImportFilter.hxx
new file mode 100644
index 000000000..ed0571dad
--- /dev/null
+++ b/writerperfect/source/draw/MWAWDrawImportFilter.hxx
@@ -0,0 +1,41 @@
+/* -*- 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/uno/XComponentContext.hpp>
+
+#include <ImportFilter.hxx>
+
+#include <DocumentHandlerForOdg.hxx>
+
+/* This component will be instantiated for both import or export. Whether it calls
+ * setSourceDocument or setTargetDocument determines which Impl function the filter
+ * member calls */
+class MWAWDrawImportFilter : public writerperfect::ImportFilter<OdgGenerator>
+{
+public:
+ explicit MWAWDrawImportFilter(const css::uno::Reference<css::uno::XComponentContext>& rxContext)
+ : writerperfect::ImportFilter<OdgGenerator>(rxContext)
+ {
+ }
+
+ // XServiceInfo
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override;
+ virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override;
+
+private:
+ virtual bool doDetectFormat(librevenge::RVNGInputStream& rInput, OUString& rTypeName) override;
+ virtual bool doImportDocument(weld::Window* pParent, librevenge::RVNGInputStream& rInput,
+ OdgGenerator& rGenerator, utl::MediaDescriptor&) override;
+ virtual void doRegisterHandlers(OdgGenerator& rGenerator) override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/writerperfect/source/draw/PageMakerImportFilter.cxx b/writerperfect/source/draw/PageMakerImportFilter.cxx
new file mode 100644
index 000000000..5f5379de9
--- /dev/null
+++ b/writerperfect/source/draw/PageMakerImportFilter.cxx
@@ -0,0 +1,56 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* PageMakerImportFilter: Sets up the filter, and calls OdgExporter
+ * to do the actual filtering
+ *
+ * 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 <libpagemaker/libpagemaker.h>
+
+#include <cppuhelper/supportsservice.hxx>
+
+#include "PageMakerImportFilter.hxx"
+
+bool PageMakerImportFilter::doImportDocument(weld::Window*, librevenge::RVNGInputStream& rInput,
+ OdgGenerator& rGenerator, utl::MediaDescriptor&)
+{
+ return libpagemaker::PMDocument::parse(&rInput, &rGenerator);
+}
+
+bool PageMakerImportFilter::doDetectFormat(librevenge::RVNGInputStream& rInput, OUString& rTypeName)
+{
+ if (libpagemaker::PMDocument::isSupported(&rInput))
+ {
+ rTypeName = "draw_PageMaker_Document";
+ return true;
+ }
+
+ return false;
+}
+
+// XServiceInfo
+OUString SAL_CALL PageMakerImportFilter::getImplementationName()
+{
+ return "org.libreoffice.comp.Draw.PageMakerImportFilter";
+}
+
+sal_Bool SAL_CALL PageMakerImportFilter::supportsService(const OUString& rServiceName)
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+css::uno::Sequence<OUString> SAL_CALL PageMakerImportFilter::getSupportedServiceNames()
+{
+ return { "com.sun.star.document.ImportFilter", "com.sun.star.document.ExtendedTypeDetection" };
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+org_libreoffice_comp_Draw_PageMakerImportFilter_get_implementation(
+ css::uno::XComponentContext* const context, const css::uno::Sequence<css::uno::Any>&)
+{
+ return cppu::acquire(new PageMakerImportFilter(context));
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/writerperfect/source/draw/PageMakerImportFilter.hxx b/writerperfect/source/draw/PageMakerImportFilter.hxx
new file mode 100644
index 000000000..b98213a27
--- /dev/null
+++ b/writerperfect/source/draw/PageMakerImportFilter.hxx
@@ -0,0 +1,37 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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 <ImportFilter.hxx>
+
+#include <DocumentHandlerForOdg.hxx>
+
+/* This component will be instantiated for both import or export. Whether it calls
+ * setSourceDocument or setTargetDocument determines which Impl function the filter
+ * member calls */
+class PageMakerImportFilter : public writerperfect::ImportFilter<OdgGenerator>
+{
+public:
+ explicit PageMakerImportFilter(
+ const css::uno::Reference<css::uno::XComponentContext>& rxContext)
+ : writerperfect::ImportFilter<OdgGenerator>(rxContext)
+ {
+ }
+
+ // XServiceInfo
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override;
+ virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override;
+
+private:
+ virtual bool doDetectFormat(librevenge::RVNGInputStream& rInput, OUString& rTypeName) override;
+ virtual bool doImportDocument(weld::Window* pParent, librevenge::RVNGInputStream& rInput,
+ OdgGenerator& rGenerator, utl::MediaDescriptor&) override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/writerperfect/source/draw/QXPImportFilter.cxx b/writerperfect/source/draw/QXPImportFilter.cxx
new file mode 100644
index 000000000..c644ad470
--- /dev/null
+++ b/writerperfect/source/draw/QXPImportFilter.cxx
@@ -0,0 +1,60 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* QXPImportFilter: Sets up the filter, and calls OdgExporter
+ * to do the actual filtering
+ *
+ * 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 <libqxp/libqxp.h>
+
+#include <cppuhelper/supportsservice.hxx>
+
+#include "QXPImportFilter.hxx"
+
+using com::sun::star::uno::Sequence;
+using com::sun::star::uno::XComponentContext;
+using com::sun::star::uno::XInterface;
+
+bool QXPImportFilter::doImportDocument(weld::Window*, librevenge::RVNGInputStream& rInput,
+ OdgGenerator& rGenerator, utl::MediaDescriptor&)
+{
+ return libqxp::QXPDocument::parse(&rInput, &rGenerator) == libqxp::QXPDocument::RESULT_OK;
+}
+
+bool QXPImportFilter::doDetectFormat(librevenge::RVNGInputStream& rInput, OUString& rTypeName)
+{
+ if (libqxp::QXPDocument::isSupported(&rInput))
+ {
+ rTypeName = "draw_QXP_Document";
+ return true;
+ }
+
+ return false;
+}
+
+// XServiceInfo
+OUString SAL_CALL QXPImportFilter::getImplementationName()
+{
+ return "org.libreoffice.comp.Draw.QXPImportFilter";
+}
+
+sal_Bool SAL_CALL QXPImportFilter::supportsService(const OUString& rServiceName)
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+Sequence<OUString> SAL_CALL QXPImportFilter::getSupportedServiceNames()
+{
+ return { "com.sun.star.document.ImportFilter", "com.sun.star.document.ExtendedTypeDetection" };
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+org_libreoffice_comp_Draw_QXPImportFilter_get_implementation(
+ css::uno::XComponentContext* const context, const css::uno::Sequence<css::uno::Any>&)
+{
+ return cppu::acquire(new QXPImportFilter(context));
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/writerperfect/source/draw/QXPImportFilter.hxx b/writerperfect/source/draw/QXPImportFilter.hxx
new file mode 100644
index 000000000..5854125d6
--- /dev/null
+++ b/writerperfect/source/draw/QXPImportFilter.hxx
@@ -0,0 +1,36 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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 <ImportFilter.hxx>
+
+#include <DocumentHandlerForOdg.hxx>
+
+/* This component will be instantiated for both import or export. Whether it calls
+ * setSourceDocument or setTargetDocument determines which Impl function the filter
+ * member calls */
+class QXPImportFilter : public writerperfect::ImportFilter<OdgGenerator>
+{
+public:
+ explicit QXPImportFilter(const css::uno::Reference<css::uno::XComponentContext>& rxContext)
+ : writerperfect::ImportFilter<OdgGenerator>(rxContext)
+ {
+ }
+
+ // XServiceInfo
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override;
+ virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override;
+
+private:
+ virtual bool doDetectFormat(librevenge::RVNGInputStream& rInput, OUString& rTypeName) override;
+ virtual bool doImportDocument(weld::Window* pParent, librevenge::RVNGInputStream& rInput,
+ OdgGenerator& rGenerator, utl::MediaDescriptor&) override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/writerperfect/source/draw/StarOfficeDrawImportFilter.cxx b/writerperfect/source/draw/StarOfficeDrawImportFilter.cxx
new file mode 100644
index 000000000..1c335bfc4
--- /dev/null
+++ b/writerperfect/source/draw/StarOfficeDrawImportFilter.cxx
@@ -0,0 +1,101 @@
+/* -*- 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 <cppuhelper/supportsservice.hxx>
+
+#include <libstaroffice/libstaroffice.hxx>
+
+#include "StarOfficeDrawImportFilter.hxx"
+
+using com::sun::star::uno::Sequence;
+using com::sun::star::uno::XComponentContext;
+using com::sun::star::uno::XInterface;
+
+static bool handleEmbeddedSTOFFGraphicObject(const librevenge::RVNGBinaryData& data,
+ OdfDocumentHandler* pHandler,
+ const OdfStreamType streamType)
+{
+ OdgGenerator exporter;
+ exporter.addDocumentHandler(pHandler, streamType);
+ return STOFFDocument::decodeGraphic(data, &exporter);
+}
+
+static bool handleEmbeddedSTOFFSpreadsheetObject(const librevenge::RVNGBinaryData& data,
+ OdfDocumentHandler* pHandler,
+ const OdfStreamType streamType)
+{
+ OdsGenerator exporter;
+ exporter.registerEmbeddedObjectHandler("image/stoff-odg", &handleEmbeddedSTOFFGraphicObject);
+ exporter.addDocumentHandler(pHandler, streamType);
+ return STOFFDocument::decodeSpreadsheet(data, &exporter);
+}
+
+bool StarOfficeDrawImportFilter::doImportDocument(weld::Window*,
+ librevenge::RVNGInputStream& rInput,
+ OdgGenerator& rGenerator, utl::MediaDescriptor&)
+{
+ return STOFFDocument::STOFF_R_OK == STOFFDocument::parse(&rInput, &rGenerator);
+}
+
+bool StarOfficeDrawImportFilter::doDetectFormat(librevenge::RVNGInputStream& rInput,
+ OUString& rTypeName)
+{
+ rTypeName.clear();
+
+ STOFFDocument::Kind docKind = STOFFDocument::STOFF_K_UNKNOWN;
+ const STOFFDocument::Confidence confidence
+ = STOFFDocument::isFileFormatSupported(&rInput, docKind);
+
+ if (confidence == STOFFDocument::STOFF_C_EXCELLENT
+ || confidence == STOFFDocument::STOFF_C_SUPPORTED_ENCRYPTION)
+ {
+ switch (docKind)
+ {
+ case STOFFDocument::STOFF_K_DRAW:
+ rTypeName = "StarOffice_Drawing";
+ break;
+ default:
+ break;
+ }
+ }
+
+ return !rTypeName.isEmpty();
+}
+
+void StarOfficeDrawImportFilter::doRegisterHandlers(OdgGenerator& rGenerator)
+{
+ rGenerator.registerEmbeddedObjectHandler("image/stoff-odg", &handleEmbeddedSTOFFGraphicObject);
+ rGenerator.registerEmbeddedObjectHandler("image/stoff-ods",
+ &handleEmbeddedSTOFFSpreadsheetObject);
+}
+
+// XServiceInfo
+OUString SAL_CALL StarOfficeDrawImportFilter::getImplementationName()
+{
+ return "org.libreoffice.comp.Draw.StarOfficeDrawImportFilter";
+}
+
+sal_Bool SAL_CALL StarOfficeDrawImportFilter::supportsService(const OUString& rServiceName)
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+Sequence<OUString> SAL_CALL StarOfficeDrawImportFilter::getSupportedServiceNames()
+{
+ return { "com.sun.star.document.ImportFilter", "com.sun.star.document.ExtendedTypeDetection" };
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+org_libreoffice_comp_Draw_StarOfficeDrawImportFilter_get_implementation(
+ css::uno::XComponentContext* const context, const css::uno::Sequence<css::uno::Any>&)
+{
+ return cppu::acquire(new StarOfficeDrawImportFilter(context));
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/writerperfect/source/draw/StarOfficeDrawImportFilter.hxx b/writerperfect/source/draw/StarOfficeDrawImportFilter.hxx
new file mode 100644
index 000000000..ca44ceb48
--- /dev/null
+++ b/writerperfect/source/draw/StarOfficeDrawImportFilter.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 <com/sun/star/uno/XComponentContext.hpp>
+
+#include <ImportFilter.hxx>
+
+#include <DocumentHandlerForOdg.hxx>
+
+/* This component will be instantiated for both import or export. Whether it calls
+ * setSourceDocument or setTargetDocument determines which Impl function the filter
+ * member calls */
+class StarOfficeDrawImportFilter : public writerperfect::ImportFilter<OdgGenerator>
+{
+public:
+ explicit StarOfficeDrawImportFilter(
+ const css::uno::Reference<css::uno::XComponentContext>& rxContext)
+ : writerperfect::ImportFilter<OdgGenerator>(rxContext)
+ {
+ }
+
+ // XServiceInfo
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override;
+ virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override;
+
+private:
+ virtual bool doDetectFormat(librevenge::RVNGInputStream& rInput, OUString& rTypeName) override;
+ virtual bool doImportDocument(weld::Window* pParent, librevenge::RVNGInputStream& rInput,
+ OdgGenerator& rGenerator, utl::MediaDescriptor&) override;
+ virtual void doRegisterHandlers(OdgGenerator& rGenerator) override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/writerperfect/source/draw/VisioImportFilter.cxx b/writerperfect/source/draw/VisioImportFilter.cxx
new file mode 100644
index 000000000..33b23aae4
--- /dev/null
+++ b/writerperfect/source/draw/VisioImportFilter.cxx
@@ -0,0 +1,56 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* VisioImportFilter: Sets up the filter, and calls OdgExporter
+ * to do the actual filtering
+ *
+ * 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 <cppuhelper/supportsservice.hxx>
+
+#include <libvisio/libvisio.h>
+
+#include "VisioImportFilter.hxx"
+
+bool VisioImportFilter::doImportDocument(weld::Window*, librevenge::RVNGInputStream& rInput,
+ OdgGenerator& rGenerator, utl::MediaDescriptor&)
+{
+ return libvisio::VisioDocument::parse(&rInput, &rGenerator);
+}
+
+bool VisioImportFilter::doDetectFormat(librevenge::RVNGInputStream& rInput, OUString& rTypeName)
+{
+ if (libvisio::VisioDocument::isSupported(&rInput))
+ {
+ rTypeName = "draw_Visio_Document";
+ return true;
+ }
+
+ return false;
+}
+
+// XServiceInfo
+OUString SAL_CALL VisioImportFilter::getImplementationName()
+{
+ return "com.sun.star.comp.Draw.VisioImportFilter";
+}
+
+sal_Bool SAL_CALL VisioImportFilter::supportsService(const OUString& rServiceName)
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+css::uno::Sequence<OUString> SAL_CALL VisioImportFilter::getSupportedServiceNames()
+{
+ return { "com.sun.star.document.ImportFilter", "com.sun.star.document.ExtendedTypeDetection" };
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+com_sun_star_comp_Draw_VisioImportFilter_get_implementation(
+ css::uno::XComponentContext* const context, const css::uno::Sequence<css::uno::Any>&)
+{
+ return cppu::acquire(new VisioImportFilter(context));
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/writerperfect/source/draw/VisioImportFilter.hxx b/writerperfect/source/draw/VisioImportFilter.hxx
new file mode 100644
index 000000000..9d0e8cadb
--- /dev/null
+++ b/writerperfect/source/draw/VisioImportFilter.hxx
@@ -0,0 +1,36 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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 <ImportFilter.hxx>
+
+#include <DocumentHandlerForOdg.hxx>
+
+/* This component will be instantiated for both import or export. Whether it calls
+ * setSourceDocument or setTargetDocument determines which Impl function the filter
+ * member calls */
+class VisioImportFilter : public writerperfect::ImportFilter<OdgGenerator>
+{
+public:
+ explicit VisioImportFilter(const css::uno::Reference<css::uno::XComponentContext>& rxContext)
+ : writerperfect::ImportFilter<OdgGenerator>(rxContext)
+ {
+ }
+
+ // XServiceInfo
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override;
+ virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override;
+
+private:
+ virtual bool doDetectFormat(librevenge::RVNGInputStream& rInput, OUString& rTypeName) override;
+ virtual bool doImportDocument(weld::Window* pParent, librevenge::RVNGInputStream& rInput,
+ OdgGenerator& rGenerator, utl::MediaDescriptor&) override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/writerperfect/source/draw/WPGImportFilter.cxx b/writerperfect/source/draw/WPGImportFilter.cxx
new file mode 100644
index 000000000..10411ea3b
--- /dev/null
+++ b/writerperfect/source/draw/WPGImportFilter.cxx
@@ -0,0 +1,62 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* WPGImportFilter: Sets up the filter, and calls OdgExporter
+ * to do the actual filtering
+ *
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+/* "This product is not manufactured, approved, or supported by
+ * Corel Corporation or Corel Corporation Limited."
+ */
+
+#include <cppuhelper/supportsservice.hxx>
+
+#include <libwpg/libwpg.h>
+
+#include "WPGImportFilter.hxx"
+
+bool WPGImportFilter::doImportDocument(weld::Window*, librevenge::RVNGInputStream& rInput,
+ OdgGenerator& rGenerator, utl::MediaDescriptor&)
+{
+ return libwpg::WPGraphics::parse(&rInput, &rGenerator);
+}
+
+bool WPGImportFilter::doDetectFormat(librevenge::RVNGInputStream& rInput, OUString& rTypeName)
+{
+ if (libwpg::WPGraphics::isSupported(&rInput))
+ {
+ rTypeName = "draw_WordPerfect_Graphics";
+ return true;
+ }
+
+ return false;
+}
+
+// XServiceInfo
+OUString SAL_CALL WPGImportFilter::getImplementationName()
+{
+ return "com.sun.star.comp.Draw.WPGImportFilter";
+}
+
+sal_Bool SAL_CALL WPGImportFilter::supportsService(const OUString& rServiceName)
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+css::uno::Sequence<OUString> SAL_CALL WPGImportFilter::getSupportedServiceNames()
+{
+ return { "com.sun.star.document.ImportFilter", "com.sun.star.document.ExtendedTypeDetection" };
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+com_sun_star_comp_Draw_WPGImportFilter_get_implementation(
+ css::uno::XComponentContext* const context, const css::uno::Sequence<css::uno::Any>&)
+{
+ return cppu::acquire(new WPGImportFilter(context));
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/writerperfect/source/draw/WPGImportFilter.hxx b/writerperfect/source/draw/WPGImportFilter.hxx
new file mode 100644
index 000000000..c4777573d
--- /dev/null
+++ b/writerperfect/source/draw/WPGImportFilter.hxx
@@ -0,0 +1,41 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+/* "This product is not manufactured, approved, or supported by
+ * Corel Corporation or Corel Corporation Limited."
+ */
+#pragma once
+
+#include <ImportFilter.hxx>
+
+#include <DocumentHandlerForOdg.hxx>
+
+/* This component will be instantiated for both import or export. Whether it calls
+ * setSourceDocument or setTargetDocument determines which Impl function the filter
+ * member calls */
+class WPGImportFilter : public writerperfect::ImportFilter<OdgGenerator>
+{
+public:
+ explicit WPGImportFilter(const css::uno::Reference<css::uno::XComponentContext>& rxContext)
+ : writerperfect::ImportFilter<OdgGenerator>(rxContext)
+ {
+ }
+
+ // XServiceInfo
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override;
+ virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override;
+
+private:
+ virtual bool doDetectFormat(librevenge::RVNGInputStream& rInput, OUString& rTypeName) override;
+ virtual bool doImportDocument(weld::Window* pParent, librevenge::RVNGInputStream& rInput,
+ OdgGenerator& rGenerator, utl::MediaDescriptor&) override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/writerperfect/source/draw/ZMFImportFilter.cxx b/writerperfect/source/draw/ZMFImportFilter.cxx
new file mode 100644
index 000000000..0d1f16c97
--- /dev/null
+++ b/writerperfect/source/draw/ZMFImportFilter.cxx
@@ -0,0 +1,60 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ZMFImportFilter: Sets up the filter, and calls OdgExporter
+ * to do the actual filtering
+ *
+ * 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 <libzmf/libzmf.h>
+
+#include <cppuhelper/supportsservice.hxx>
+
+#include "ZMFImportFilter.hxx"
+
+using com::sun::star::uno::Sequence;
+using com::sun::star::uno::XComponentContext;
+using com::sun::star::uno::XInterface;
+
+bool ZMFImportFilter::doImportDocument(weld::Window*, librevenge::RVNGInputStream& rInput,
+ OdgGenerator& rGenerator, utl::MediaDescriptor&)
+{
+ return libzmf::ZMFDocument::parse(&rInput, &rGenerator);
+}
+
+bool ZMFImportFilter::doDetectFormat(librevenge::RVNGInputStream& rInput, OUString& rTypeName)
+{
+ if (libzmf::ZMFDocument::isSupported(&rInput))
+ {
+ rTypeName = "draw_ZMF_Document";
+ return true;
+ }
+
+ return false;
+}
+
+// XServiceInfo
+OUString SAL_CALL ZMFImportFilter::getImplementationName()
+{
+ return "org.libreoffice.comp.Draw.ZMFImportFilter";
+}
+
+sal_Bool SAL_CALL ZMFImportFilter::supportsService(const OUString& rServiceName)
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+Sequence<OUString> SAL_CALL ZMFImportFilter::getSupportedServiceNames()
+{
+ return { "com.sun.star.document.ImportFilter", "com.sun.star.document.ExtendedTypeDetection" };
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+org_libreoffice_comp_Draw_ZMFImportFilter_get_implementation(
+ css::uno::XComponentContext* const context, const css::uno::Sequence<css::uno::Any>&)
+{
+ return cppu::acquire(new ZMFImportFilter(context));
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/writerperfect/source/draw/ZMFImportFilter.hxx b/writerperfect/source/draw/ZMFImportFilter.hxx
new file mode 100644
index 000000000..686a1fb40
--- /dev/null
+++ b/writerperfect/source/draw/ZMFImportFilter.hxx
@@ -0,0 +1,36 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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 <ImportFilter.hxx>
+
+#include <DocumentHandlerForOdg.hxx>
+
+/* This component will be instantiated for both import or export. Whether it calls
+ * setSourceDocument or setTargetDocument determines which Impl function the filter
+ * member calls */
+class ZMFImportFilter : public writerperfect::ImportFilter<OdgGenerator>
+{
+public:
+ explicit ZMFImportFilter(const css::uno::Reference<css::uno::XComponentContext>& rxContext)
+ : writerperfect::ImportFilter<OdgGenerator>(rxContext)
+ {
+ }
+
+ // XServiceInfo
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override;
+ virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override;
+
+private:
+ virtual bool doDetectFormat(librevenge::RVNGInputStream& rInput, OUString& rTypeName) override;
+ virtual bool doImportDocument(weld::Window* pParent, librevenge::RVNGInputStream& rInput,
+ OdgGenerator& rGenerator, utl::MediaDescriptor&) override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/writerperfect/source/draw/wpftdraw.component b/writerperfect/source/draw/wpftdraw.component
new file mode 100644
index 000000000..1f9ced75a
--- /dev/null
+++ b/writerperfect/source/draw/wpftdraw.component
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * 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/.
+ *
+-->
+<component loader="com.sun.star.loader.SharedLibrary" environment="@CPPU_ENV@"
+ xmlns="http://openoffice.org/2010/uno-components">
+ <implementation name="com.sun.star.comp.Draw.CDRImportFilter"
+ constructor="com_sun_star_comp_Draw_CDRImportFilter_get_implementation">
+ <service name="com.sun.star.document.ImportFilter"/>
+ <service name="com.sun.star.document.ExtendedTypeDetection"/>
+ </implementation>
+ <implementation name="com.sun.star.comp.Draw.CMXImportFilter"
+ constructor="com_sun_star_comp_Draw_CMXImportFilter_get_implementation">
+ <service name="com.sun.star.document.ImportFilter"/>
+ <service name="com.sun.star.document.ExtendedTypeDetection"/>
+ </implementation>
+ <implementation name="com.sun.star.comp.Draw.FreehandImportFilter"
+ constructor="com_sun_star_comp_Draw_FreehandImportFilter_get_implementation">
+ <service name="com.sun.star.document.ImportFilter"/>
+ <service name="com.sun.star.document.ExtendedTypeDetection"/>
+ </implementation>
+ <implementation name="com.sun.star.comp.Draw.MSPUBImportFilter"
+ constructor="com_sun_star_comp_Draw_MSPUBImportFilter_get_implementation">
+ <service name="com.sun.star.document.ImportFilter"/>
+ <service name="com.sun.star.document.ExtendedTypeDetection"/>
+ </implementation>
+ <implementation name="com.sun.star.comp.Draw.MWAWDrawImportFilter"
+ constructor="com_sun_star_comp_Draw_MWAWDrawImportFilter_get_implementation">
+ <service name="com.sun.star.document.ImportFilter"/>
+ <service name="com.sun.star.document.ExtendedTypeDetection"/>
+ </implementation>
+ <implementation name="org.libreoffice.comp.Draw.StarOfficeDrawImportFilter"
+ constructor="org_libreoffice_comp_Draw_StarOfficeDrawImportFilter_get_implementation">
+ <service name="com.sun.star.document.ImportFilter"/>
+ <service name="com.sun.star.document.ExtendedTypeDetection"/>
+ </implementation>
+ <implementation name="com.sun.star.comp.Draw.VisioImportFilter"
+ constructor="com_sun_star_comp_Draw_VisioImportFilter_get_implementation">
+ <service name="com.sun.star.document.ImportFilter"/>
+ <service name="com.sun.star.document.ExtendedTypeDetection"/>
+ </implementation>
+ <implementation name="com.sun.star.comp.Draw.WPGImportFilter"
+ constructor="com_sun_star_comp_Draw_WPGImportFilter_get_implementation">
+ <service name="com.sun.star.document.ImportFilter"/>
+ <service name="com.sun.star.document.ExtendedTypeDetection"/>
+ </implementation>
+ <implementation name="org.libreoffice.comp.Draw.PageMakerImportFilter"
+ constructor="org_libreoffice_comp_Draw_PageMakerImportFilter_get_implementation">
+ <service name="com.sun.star.document.ImportFilter"/>
+ <service name="com.sun.star.document.ExtendedTypeDetection"/>
+ </implementation>
+ <implementation name="org.libreoffice.comp.Draw.QXPImportFilter"
+ constructor="org_libreoffice_comp_Draw_QXPImportFilter_get_implementation">
+ <service name="com.sun.star.document.ImportFilter"/>
+ <service name="com.sun.star.document.ExtendedTypeDetection"/>
+ </implementation>
+ <implementation name="org.libreoffice.comp.Draw.ZMFImportFilter"
+ constructor="org_libreoffice_comp_Draw_ZMFImportFilter_get_implementation">
+ <service name="com.sun.star.document.ImportFilter"/>
+ <service name="com.sun.star.document.ExtendedTypeDetection"/>
+ </implementation>
+</component>
diff --git a/writerperfect/source/impress/KeynoteImportFilter.cxx b/writerperfect/source/impress/KeynoteImportFilter.cxx
new file mode 100644
index 000000000..ccd93e3d2
--- /dev/null
+++ b/writerperfect/source/impress/KeynoteImportFilter.cxx
@@ -0,0 +1,247 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* KeynoteImportFilter: Sets up the filter, and calls OdpExporter
+ * to do the actual filtering
+ *
+ * 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 <memory>
+#include <com/sun/star/beans/NamedValue.hpp>
+#include <com/sun/star/beans/PropertyValue.hpp>
+#include <com/sun/star/io/XInputStream.hpp>
+#include <com/sun/star/uno/Reference.h>
+#include <com/sun/star/ucb/XContent.hpp>
+#include <comphelper/processfactory.hxx>
+#include <cppuhelper/supportsservice.hxx>
+
+#include <libetonyek/libetonyek.h>
+#include <ucbhelper/content.hxx>
+#include <unotools/ucbhelper.hxx>
+
+#include <DirectoryStream.hxx>
+#include <WPXSvInputStream.hxx>
+
+#include "KeynoteImportFilter.hxx"
+
+using writerperfect::WPXSvInputStream;
+
+namespace beans = com::sun::star::beans;
+namespace ucb = com::sun::star::ucb;
+
+bool KeynoteImportFilter::doImportDocument(weld::Window*, librevenge::RVNGInputStream& rInput,
+ OdpGenerator& rGenerator, utl::MediaDescriptor&)
+{
+ return libetonyek::EtonyekDocument::parse(&rInput, &rGenerator);
+}
+
+bool KeynoteImportFilter::doDetectFormat(librevenge::RVNGInputStream& rInput, OUString& rTypeName)
+{
+ if (libetonyek::EtonyekDocument::isSupported(&rInput))
+ {
+ rTypeName = "impress_Keynote_Document";
+ return true;
+ }
+
+ return false;
+}
+
+// XExtendedFilterDetection
+OUString SAL_CALL
+KeynoteImportFilter::detect(css::uno::Sequence<css::beans::PropertyValue>& Descriptor)
+{
+ sal_Int32 nLength = Descriptor.getLength();
+ sal_Int32 nNewLength = nLength + 2;
+ sal_Int32 nComponentDataLocation = -1;
+ sal_Int32 nTypeNameLocation = -1;
+ sal_Int32 nUCBContentLocation = -1;
+ bool bIsPackage = false;
+ bool bUCBContentChanged = false;
+ const beans::PropertyValue* pValue = Descriptor.getConstArray();
+ css::uno::Reference<com::sun::star::io::XInputStream> xInputStream;
+ css::uno::Reference<ucb::XContent> xContent;
+ css::uno::Sequence<beans::NamedValue> lComponentDataNV;
+ css::uno::Sequence<beans::PropertyValue> lComponentDataPV;
+ bool bComponentDataNV = true;
+
+ for (sal_Int32 i = 0; i < nLength; i++)
+ {
+ if (pValue[i].Name == "TypeName")
+ {
+ nTypeNameLocation = i;
+ --nNewLength;
+ }
+ if (pValue[i].Name == "ComponentData")
+ {
+ bComponentDataNV = pValue[i].Value >>= lComponentDataNV;
+ if (!bComponentDataNV)
+ pValue[i].Value >>= lComponentDataPV;
+ nComponentDataLocation = i;
+ --nNewLength;
+ }
+ else if (pValue[i].Name == "InputStream")
+ {
+ pValue[i].Value >>= xInputStream;
+ }
+ else if (pValue[i].Name == "UCBContent")
+ {
+ pValue[i].Value >>= xContent;
+ nUCBContentLocation = i;
+ }
+ }
+
+ assert(nNewLength >= nLength);
+
+ if (!xInputStream.is())
+ return OUString();
+
+ std::unique_ptr<librevenge::RVNGInputStream> input
+ = std::make_unique<WPXSvInputStream>(xInputStream);
+
+ /* Apple Keynote documents come in two variants:
+ * * actual files (zip), only produced by Keynote 5 (at least with
+ * default settings)
+ * * packages (IOW, directories), produced by Keynote 1-4 and again
+ * starting with 6.
+ * But since the libetonyek import only works with a stream, we need
+ * to pass it one for the whole package. Here we determine if that
+ * is needed.
+ *
+ * Note: for convenience, we also recognize that the main XML file
+ * from a package was passed and pass the whole package to the
+ * filter instead.
+ */
+ if (xContent.is())
+ {
+ ucbhelper::Content aContent(xContent, utl::UCBContentHelper::getDefaultCommandEnvironment(),
+ comphelper::getProcessComponentContext());
+ try
+ {
+ if (aContent.isFolder())
+ {
+ input = std::make_unique<writerperfect::DirectoryStream>(xContent);
+ bIsPackage = true;
+ }
+ }
+ catch (...)
+ {
+ return OUString();
+ }
+ }
+
+ libetonyek::EtonyekDocument::Type type = libetonyek::EtonyekDocument::TYPE_UNKNOWN;
+ const libetonyek::EtonyekDocument::Confidence confidence
+ = libetonyek::EtonyekDocument::isSupported(input.get(), &type);
+ if ((libetonyek::EtonyekDocument::CONFIDENCE_NONE == confidence)
+ || (libetonyek::EtonyekDocument::TYPE_KEYNOTE != type))
+ return OUString();
+
+ if (confidence == libetonyek::EtonyekDocument::CONFIDENCE_SUPPORTED_PART)
+ {
+ if (bIsPackage) // we passed a directory stream, but the filter claims it's APXL file?
+ return OUString();
+
+ std::unique_ptr<writerperfect::DirectoryStream> xDir
+ = writerperfect::DirectoryStream::createForParent(xContent);
+ auto pDir = xDir.get();
+ input = std::move(xDir);
+ if (bool(input))
+ {
+ if (libetonyek::EtonyekDocument::CONFIDENCE_EXCELLENT
+ == libetonyek::EtonyekDocument::isSupported(input.get()))
+ {
+ xContent = pDir->getContent();
+ bUCBContentChanged = true;
+ bIsPackage = true;
+ }
+ else
+ {
+ // The passed stream has been detected as APXL file, but its parent dir is not a valid Keynote
+ // package? Something is wrong here...
+ return OUString();
+ }
+ }
+ }
+
+ // we do not need to insert ComponentData if this is not a package
+ if (!bIsPackage && (nComponentDataLocation == -1))
+ --nNewLength;
+
+ if (nNewLength > nLength)
+ Descriptor.realloc(nNewLength);
+ auto pDescriptor = Descriptor.getArray();
+
+ if (nTypeNameLocation == -1)
+ {
+ assert(nLength < nNewLength);
+ nTypeNameLocation = nLength++;
+ pDescriptor[nTypeNameLocation].Name = "TypeName";
+ }
+
+ if (bIsPackage && (nComponentDataLocation == -1))
+ {
+ assert(nLength < nNewLength);
+ nComponentDataLocation = nLength++;
+ pDescriptor[nComponentDataLocation].Name = "ComponentData";
+ }
+
+ if (bIsPackage)
+ {
+ if (bComponentDataNV)
+ {
+ const sal_Int32 nCDSize = lComponentDataNV.getLength();
+ lComponentDataNV.realloc(nCDSize + 1);
+ beans::NamedValue aValue;
+ aValue.Name = "IsPackage";
+ aValue.Value <<= true;
+ lComponentDataNV.getArray()[nCDSize] = aValue;
+ pDescriptor[nComponentDataLocation].Value <<= lComponentDataNV;
+ }
+ else
+ {
+ const sal_Int32 nCDSize = lComponentDataPV.getLength();
+ lComponentDataPV.realloc(nCDSize + 1);
+ beans::PropertyValue aProp;
+ aProp.Name = "IsPackage";
+ aProp.Value <<= true;
+ aProp.Handle = -1;
+ aProp.State = beans::PropertyState_DIRECT_VALUE;
+ lComponentDataPV.getArray()[nCDSize] = aProp;
+ pDescriptor[nComponentDataLocation].Value <<= lComponentDataPV;
+ }
+ }
+
+ if (bUCBContentChanged)
+ pDescriptor[nUCBContentLocation].Value <<= xContent;
+
+ const OUString sTypeName("impress_AppleKeynote");
+ pDescriptor[nTypeNameLocation].Value <<= sTypeName;
+
+ return sTypeName;
+}
+
+// XServiceInfo
+OUString SAL_CALL KeynoteImportFilter::getImplementationName()
+{
+ return "org.libreoffice.comp.Impress.KeynoteImportFilter";
+}
+
+sal_Bool SAL_CALL KeynoteImportFilter::supportsService(const OUString& rServiceName)
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+css::uno::Sequence<OUString> SAL_CALL KeynoteImportFilter::getSupportedServiceNames()
+{
+ return { "com.sun.star.document.ImportFilter", "com.sun.star.document.ExtendedTypeDetection" };
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+org_libreoffice_comp_Impress_KeynoteImportFilter_get_implementation(
+ css::uno::XComponentContext* const context, const css::uno::Sequence<css::uno::Any>&)
+{
+ return cppu::acquire(new KeynoteImportFilter(context));
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/writerperfect/source/impress/KeynoteImportFilter.hxx b/writerperfect/source/impress/KeynoteImportFilter.hxx
new file mode 100644
index 000000000..7180a8c86
--- /dev/null
+++ b/writerperfect/source/impress/KeynoteImportFilter.hxx
@@ -0,0 +1,41 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/uno/XComponentContext.hpp>
+
+#include <ImportFilter.hxx>
+#include <DocumentHandlerForOdp.hxx>
+
+/* This component will be instantiated for both import or export. Whether it calls
+ * setSourceDocument or setTargetDocument determines which Impl function the filter
+ * member calls */
+class KeynoteImportFilter : public writerperfect::ImportFilter<OdpGenerator>
+{
+public:
+ explicit KeynoteImportFilter(const css::uno::Reference<css::uno::XComponentContext>& rxContext)
+ : writerperfect::ImportFilter<OdpGenerator>(rxContext)
+ {
+ }
+
+ //XExtendedFilterDetection
+ virtual OUString SAL_CALL
+ detect(css::uno::Sequence<css::beans::PropertyValue>& Descriptor) override;
+
+ // XServiceInfo
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override;
+ virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override;
+
+private:
+ virtual bool doDetectFormat(librevenge::RVNGInputStream& rInput, OUString& rTypeName) override;
+ virtual bool doImportDocument(weld::Window* pParent, librevenge::RVNGInputStream& rInput,
+ OdpGenerator& rGenerator, utl::MediaDescriptor&) override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/writerperfect/source/impress/MWAWPresentationImportFilter.cxx b/writerperfect/source/impress/MWAWPresentationImportFilter.cxx
new file mode 100644
index 000000000..c5de6984a
--- /dev/null
+++ b/writerperfect/source/impress/MWAWPresentationImportFilter.cxx
@@ -0,0 +1,104 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* MWAWPresentationImportFilter: Sets up the filter, and calls DocumentCollector
+ * to do the actual filtering
+ *
+ * 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 <cppuhelper/supportsservice.hxx>
+
+#include <libmwaw/libmwaw.hxx>
+
+#include "MWAWPresentationImportFilter.hxx"
+
+static bool handleEmbeddedMWAWGraphicObject(const librevenge::RVNGBinaryData& data,
+ OdfDocumentHandler* pHandler,
+ const OdfStreamType streamType)
+{
+ OdgGenerator exporter;
+ exporter.addDocumentHandler(pHandler, streamType);
+ return MWAWDocument::decodeGraphic(data, &exporter);
+}
+
+static bool handleEmbeddedMWAWSpreadsheetObject(const librevenge::RVNGBinaryData& data,
+ OdfDocumentHandler* pHandler,
+ const OdfStreamType streamType)
+{
+ OdsGenerator exporter;
+ exporter.registerEmbeddedObjectHandler("image/mwaw-odg", &handleEmbeddedMWAWGraphicObject);
+ exporter.addDocumentHandler(pHandler, streamType);
+ return MWAWDocument::decodeSpreadsheet(data, &exporter);
+}
+
+bool MWAWPresentationImportFilter::doImportDocument(weld::Window*,
+ librevenge::RVNGInputStream& rInput,
+ OdpGenerator& rGenerator, utl::MediaDescriptor&)
+{
+ return MWAWDocument::MWAW_R_OK == MWAWDocument::parse(&rInput, &rGenerator);
+}
+
+bool MWAWPresentationImportFilter::doDetectFormat(librevenge::RVNGInputStream& rInput,
+ OUString& rTypeName)
+{
+ rTypeName.clear();
+
+ MWAWDocument::Type docType = MWAWDocument::MWAW_T_UNKNOWN;
+ MWAWDocument::Kind docKind = MWAWDocument::MWAW_K_UNKNOWN;
+ const MWAWDocument::Confidence confidence
+ = MWAWDocument::isFileFormatSupported(&rInput, docType, docKind);
+
+ if (confidence == MWAWDocument::MWAW_C_EXCELLENT)
+ {
+ if (docKind == MWAWDocument::MWAW_K_PRESENTATION)
+ {
+ switch (docType)
+ {
+ case MWAWDocument::MWAW_T_CLARISWORKS:
+ rTypeName = "impress_ClarisWorks";
+ break;
+ case MWAWDocument::MWAW_T_RESERVED8:
+ rTypeName = "impress_PowerPoint3";
+ break;
+ default:
+ rTypeName = "MWAW_Presentation";
+ break;
+ }
+ }
+ }
+
+ return !rTypeName.isEmpty();
+}
+
+void MWAWPresentationImportFilter::doRegisterHandlers(OdpGenerator& rGenerator)
+{
+ rGenerator.registerEmbeddedObjectHandler("image/mwaw-odg", &handleEmbeddedMWAWGraphicObject);
+ rGenerator.registerEmbeddedObjectHandler("image/mwaw-ods",
+ &handleEmbeddedMWAWSpreadsheetObject);
+}
+
+// XServiceInfo
+OUString SAL_CALL MWAWPresentationImportFilter::getImplementationName()
+{
+ return "com.sun.star.comp.Impress.MWAWPresentationImportFilter";
+}
+sal_Bool SAL_CALL MWAWPresentationImportFilter::supportsService(const OUString& rServiceName)
+{
+ return cppu::supportsService(this, rServiceName);
+}
+css::uno::Sequence<OUString> SAL_CALL MWAWPresentationImportFilter::getSupportedServiceNames()
+{
+ return { "com.sun.star.document.ImportFilter", "com.sun.star.document.ExtendedTypeDetection" };
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+com_sun_star_comp_Impress_MWAWPresentationImportFilter_get_implementation(
+ css::uno::XComponentContext* const context, const css::uno::Sequence<css::uno::Any>&)
+{
+ return cppu::acquire(new MWAWPresentationImportFilter(context));
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/writerperfect/source/impress/MWAWPresentationImportFilter.hxx b/writerperfect/source/impress/MWAWPresentationImportFilter.hxx
new file mode 100644
index 000000000..ba6874834
--- /dev/null
+++ b/writerperfect/source/impress/MWAWPresentationImportFilter.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 <com/sun/star/uno/XComponentContext.hpp>
+
+#include <ImportFilter.hxx>
+
+#include <DocumentHandlerForOdp.hxx>
+
+/* This component will be instantiated for both import or export. Whether it calls
+ * setSourceDocument or setTargetDocument determines which Impl function the filter
+ * member calls */
+class MWAWPresentationImportFilter : public writerperfect::ImportFilter<OdpGenerator>
+{
+public:
+ explicit MWAWPresentationImportFilter(
+ const css::uno::Reference<css::uno::XComponentContext>& rxContext)
+ : writerperfect::ImportFilter<OdpGenerator>(rxContext)
+ {
+ }
+
+ // XServiceInfo
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override;
+ virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override;
+
+private:
+ virtual bool doDetectFormat(librevenge::RVNGInputStream& rInput, OUString& rTypeName) override;
+ virtual bool doImportDocument(weld::Window* pParent, librevenge::RVNGInputStream& rInput,
+ OdpGenerator& rGenerator, utl::MediaDescriptor&) override;
+ virtual void doRegisterHandlers(OdpGenerator& rGenerator) override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/writerperfect/source/impress/StarOfficePresentationImportFilter.cxx b/writerperfect/source/impress/StarOfficePresentationImportFilter.cxx
new file mode 100644
index 000000000..4f60f57e3
--- /dev/null
+++ b/writerperfect/source/impress/StarOfficePresentationImportFilter.cxx
@@ -0,0 +1,102 @@
+/* -*- 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 <cppuhelper/supportsservice.hxx>
+
+#include <libstaroffice/libstaroffice.hxx>
+
+#include "StarOfficePresentationImportFilter.hxx"
+
+using com::sun::star::uno::Sequence;
+using com::sun::star::uno::XComponentContext;
+using com::sun::star::uno::XInterface;
+
+static bool handleEmbeddedSTOFFGraphicObject(const librevenge::RVNGBinaryData& data,
+ OdfDocumentHandler* pHandler,
+ const OdfStreamType streamType)
+{
+ OdgGenerator exporter;
+ exporter.addDocumentHandler(pHandler, streamType);
+ return STOFFDocument::decodeGraphic(data, &exporter);
+}
+
+static bool handleEmbeddedSTOFFSpreadsheetObject(const librevenge::RVNGBinaryData& data,
+ OdfDocumentHandler* pHandler,
+ const OdfStreamType streamType)
+{
+ OdsGenerator exporter;
+ exporter.registerEmbeddedObjectHandler("image/stoff-odg", &handleEmbeddedSTOFFGraphicObject);
+ exporter.addDocumentHandler(pHandler, streamType);
+ return STOFFDocument::decodeSpreadsheet(data, &exporter);
+}
+
+bool StarOfficePresentationImportFilter::doImportDocument(weld::Window*,
+ librevenge::RVNGInputStream& rInput,
+ OdpGenerator& rGenerator,
+ utl::MediaDescriptor&)
+{
+ return STOFFDocument::STOFF_R_OK == STOFFDocument::parse(&rInput, &rGenerator);
+}
+
+bool StarOfficePresentationImportFilter::doDetectFormat(librevenge::RVNGInputStream& rInput,
+ OUString& rTypeName)
+{
+ rTypeName.clear();
+
+ STOFFDocument::Kind docKind = STOFFDocument::STOFF_K_UNKNOWN;
+ const STOFFDocument::Confidence confidence
+ = STOFFDocument::isFileFormatSupported(&rInput, docKind);
+
+ if (confidence == STOFFDocument::STOFF_C_EXCELLENT
+ || confidence == STOFFDocument::STOFF_C_SUPPORTED_ENCRYPTION)
+ {
+ switch (docKind)
+ {
+ case STOFFDocument::STOFF_K_PRESENTATION:
+ rTypeName = "StarOffice_Presentation";
+ break;
+ default:
+ break;
+ }
+ }
+
+ return !rTypeName.isEmpty();
+}
+
+void StarOfficePresentationImportFilter::doRegisterHandlers(OdpGenerator& rGenerator)
+{
+ rGenerator.registerEmbeddedObjectHandler("image/stoff-odg", &handleEmbeddedSTOFFGraphicObject);
+ rGenerator.registerEmbeddedObjectHandler("image/stoff-ods",
+ &handleEmbeddedSTOFFSpreadsheetObject);
+}
+
+// XServiceInfo
+OUString SAL_CALL StarOfficePresentationImportFilter::getImplementationName()
+{
+ return "org.libreoffice.comp.Impress.StarOfficePresentationImportFilter";
+}
+
+sal_Bool SAL_CALL StarOfficePresentationImportFilter::supportsService(const OUString& rServiceName)
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+Sequence<OUString> SAL_CALL StarOfficePresentationImportFilter::getSupportedServiceNames()
+{
+ return { "com.sun.star.document.ImportFilter", "com.sun.star.document.ExtendedTypeDetection" };
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+org_libreoffice_comp_Presentation_StarOfficePresentationImportFilter_get_implementation(
+ css::uno::XComponentContext* const context, const css::uno::Sequence<css::uno::Any>&)
+{
+ return cppu::acquire(new StarOfficePresentationImportFilter(context));
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/writerperfect/source/impress/StarOfficePresentationImportFilter.hxx b/writerperfect/source/impress/StarOfficePresentationImportFilter.hxx
new file mode 100644
index 000000000..0f10a9258
--- /dev/null
+++ b/writerperfect/source/impress/StarOfficePresentationImportFilter.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 <com/sun/star/uno/XComponentContext.hpp>
+
+#include <ImportFilter.hxx>
+
+#include <DocumentHandlerForOdp.hxx>
+
+/* This component will be instantiated for both import or export. Whether it calls
+ * setSourceDocument or setTargetDocument determines which Impl function the filter
+ * member calls */
+class StarOfficePresentationImportFilter : public writerperfect::ImportFilter<OdpGenerator>
+{
+public:
+ explicit StarOfficePresentationImportFilter(
+ const css::uno::Reference<css::uno::XComponentContext>& rxContext)
+ : writerperfect::ImportFilter<OdpGenerator>(rxContext)
+ {
+ }
+
+ // XServiceInfo
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override;
+ virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override;
+
+private:
+ virtual bool doDetectFormat(librevenge::RVNGInputStream& rInput, OUString& rTypeName) override;
+ virtual bool doImportDocument(weld::Window* pParent, librevenge::RVNGInputStream& rInput,
+ OdpGenerator& rGenerator, utl::MediaDescriptor&) override;
+ virtual void doRegisterHandlers(OdpGenerator& rGenerator) override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/writerperfect/source/impress/wpftimpress.component b/writerperfect/source/impress/wpftimpress.component
new file mode 100644
index 000000000..0f7df39fa
--- /dev/null
+++ b/writerperfect/source/impress/wpftimpress.component
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * 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/.
+ *
+-->
+<component loader="com.sun.star.loader.SharedLibrary" environment="@CPPU_ENV@"
+ xmlns="http://openoffice.org/2010/uno-components">
+ <implementation name="org.libreoffice.comp.Impress.KeynoteImportFilter"
+ constructor="org_libreoffice_comp_Impress_KeynoteImportFilter_get_implementation">
+ <service name="com.sun.star.document.ImportFilter"/>
+ <service name="com.sun.star.document.ExtendedTypeDetection"/>
+ </implementation>
+ <implementation name="com.sun.star.comp.Impress.MWAWPresentationImportFilter"
+ constructor="com_sun_star_comp_Impress_MWAWPresentationImportFilter_get_implementation">
+ <service name="com.sun.star.document.ImportFilter"/>
+ <service name="com.sun.star.document.ExtendedTypeDetection"/>
+ </implementation>
+ <implementation name="org.libreoffice.comp.Impress.StarOfficePresentationImportFilter"
+ constructor="org_libreoffice_comp_Presentation_StarOfficePresentationImportFilter_get_implementation">
+ <service name="com.sun.star.document.ImportFilter"/>
+ <service name="com.sun.star.document.ExtendedTypeDetection"/>
+ </implementation>
+</component>
diff --git a/writerperfect/source/writer/AbiWordImportFilter.cxx b/writerperfect/source/writer/AbiWordImportFilter.cxx
new file mode 100644
index 000000000..0661604bc
--- /dev/null
+++ b/writerperfect/source/writer/AbiWordImportFilter.cxx
@@ -0,0 +1,58 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* AbiWordImportFilter: Sets up the filter, and calls DocumentCollector
+ * to do the actual filtering
+ *
+ * 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 <cppuhelper/supportsservice.hxx>
+
+#include <libabw/libabw.h>
+
+#include "AbiWordImportFilter.hxx"
+
+bool AbiWordImportFilter::doImportDocument(weld::Window*, librevenge::RVNGInputStream& rInput,
+ OdtGenerator& rGenerator, utl::MediaDescriptor&)
+{
+ return libabw::AbiDocument::parse(&rInput, &rGenerator);
+}
+
+bool AbiWordImportFilter::doDetectFormat(librevenge::RVNGInputStream& rInput, OUString& rTypeName)
+{
+ if (libabw::AbiDocument::isFileFormatSupported(&rInput))
+ {
+ rTypeName = "writer_AbiWord_Document";
+ return true;
+ }
+
+ return false;
+}
+
+// XServiceInfo
+OUString SAL_CALL AbiWordImportFilter::getImplementationName()
+{
+ return "com.sun.star.comp.Writer.AbiWordImportFilter";
+}
+
+sal_Bool SAL_CALL AbiWordImportFilter::supportsService(const OUString& rServiceName)
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+css::uno::Sequence<OUString> SAL_CALL AbiWordImportFilter::getSupportedServiceNames()
+{
+ return { "com.sun.star.document.ImportFilter", "com.sun.star.document.ExtendedTypeDetection" };
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+com_sun_star_comp_Writer_AbiWordImportFilter_get_implementation(
+ css::uno::XComponentContext* const context, const css::uno::Sequence<css::uno::Any>&)
+{
+ return cppu::acquire(new AbiWordImportFilter(context));
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/writerperfect/source/writer/AbiWordImportFilter.hxx b/writerperfect/source/writer/AbiWordImportFilter.hxx
new file mode 100644
index 000000000..f9b0f99d9
--- /dev/null
+++ b/writerperfect/source/writer/AbiWordImportFilter.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 <com/sun/star/uno/XComponentContext.hpp>
+
+#include <ImportFilter.hxx>
+
+#include <DocumentHandlerForOdt.hxx>
+
+/* This component will be instantiated for both import or export. Whether it calls
+ * setSourceDocument or setTargetDocument determines which Impl function the filter
+ * member calls */
+class AbiWordImportFilter : public writerperfect::ImportFilter<OdtGenerator>
+{
+public:
+ explicit AbiWordImportFilter(const css::uno::Reference<css::uno::XComponentContext>& rxContext)
+ : writerperfect::ImportFilter<OdtGenerator>(rxContext)
+ {
+ }
+
+ // XServiceInfo
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override;
+ virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override;
+
+private:
+ virtual bool doDetectFormat(librevenge::RVNGInputStream& rInput, OUString& rTypeName) override;
+ virtual bool doImportDocument(weld::Window* pParent, librevenge::RVNGInputStream& rInput,
+ OdtGenerator& rGenerator, utl::MediaDescriptor&) override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/writerperfect/source/writer/EBookImportFilter.cxx b/writerperfect/source/writer/EBookImportFilter.cxx
new file mode 100644
index 000000000..3c53f2d9e
--- /dev/null
+++ b/writerperfect/source/writer/EBookImportFilter.cxx
@@ -0,0 +1,114 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* EBookImportFilter: Sets up the filter, and calls DocumentCollector
+ * to do the actual filtering
+ *
+ * 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 <cppuhelper/supportsservice.hxx>
+#include <sal/log.hxx>
+
+#include <libe-book/libe-book.h>
+
+#include "EBookImportFilter.hxx"
+
+using libebook::EBOOKDocument;
+
+bool EBookImportFilter::doImportDocument(weld::Window*, librevenge::RVNGInputStream& rInput,
+ OdtGenerator& rGenerator,
+ utl::MediaDescriptor& rDescriptor)
+{
+ OUString aFilterName;
+
+ rDescriptor[utl::MediaDescriptor::PROP_FILTERNAME] >>= aFilterName;
+ assert(!aFilterName.isEmpty());
+
+ if (aFilterName == "Palm_Text_Document")
+ {
+ return EBOOKDocument::RESULT_OK == EBOOKDocument::parse(&rInput, &rGenerator);
+ }
+ else
+ {
+ EBOOKDocument::Type type = EBOOKDocument::TYPE_UNKNOWN;
+
+ if (aFilterName == "BroadBand eBook")
+ type = EBOOKDocument::TYPE_BBEB;
+ else if (aFilterName == "FictionBook 2")
+ type = EBOOKDocument::TYPE_FICTIONBOOK2;
+ else if (aFilterName == "PalmDoc")
+ type = EBOOKDocument::TYPE_PALMDOC;
+ else if (aFilterName == "Plucker eBook")
+ type = EBOOKDocument::TYPE_PLUCKER;
+
+ if (EBOOKDocument::TYPE_UNKNOWN != type)
+ return EBOOKDocument::RESULT_OK == EBOOKDocument::parse(&rInput, &rGenerator, type);
+ }
+
+ return false;
+}
+
+bool EBookImportFilter::doDetectFormat(librevenge::RVNGInputStream& rInput, OUString& rTypeName)
+{
+ rTypeName.clear();
+
+ EBOOKDocument::Type type = EBOOKDocument::TYPE_UNKNOWN;
+
+ if (EBOOKDocument::CONFIDENCE_EXCELLENT == EBOOKDocument::isSupported(&rInput, &type))
+ {
+ switch (type)
+ {
+ case EBOOKDocument::TYPE_BBEB:
+ rTypeName = "writer_BroadBand_eBook";
+ break;
+ case EBOOKDocument::TYPE_FICTIONBOOK2:
+ rTypeName = "writer_FictionBook_2";
+ break;
+ case EBOOKDocument::TYPE_PALMDOC:
+ rTypeName = "writer_PalmDoc";
+ break;
+ case EBOOKDocument::TYPE_PLUCKER:
+ rTypeName = "writer_Plucker_eBook";
+ break;
+ case EBOOKDocument::TYPE_PEANUTPRESS:
+ case EBOOKDocument::TYPE_TEALDOC:
+ case EBOOKDocument::TYPE_ZTXT:
+ rTypeName = "Palm_Text_Document";
+ break;
+ default:
+ SAL_WARN_IF(type != EBOOKDocument::TYPE_UNKNOWN, "writerperfect",
+ "EBookImportFilter::doDetectFormat: document type "
+ << type << " detected, but ignored");
+ }
+ }
+
+ return !rTypeName.isEmpty();
+}
+
+// XServiceInfo
+OUString SAL_CALL EBookImportFilter::getImplementationName()
+{
+ return "org.libreoffice.comp.Writer.EBookImportFilter";
+}
+
+sal_Bool SAL_CALL EBookImportFilter::supportsService(const OUString& rServiceName)
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+css::uno::Sequence<OUString> SAL_CALL EBookImportFilter::getSupportedServiceNames()
+{
+ return { "com.sun.star.document.ImportFilter", "com.sun.star.document.ExtendedTypeDetection" };
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+org_libreoffice_comp_Writer_EBookImportFilter_get_implementation(
+ css::uno::XComponentContext* const context, const css::uno::Sequence<css::uno::Any>&)
+{
+ return cppu::acquire(new EBookImportFilter(context));
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/writerperfect/source/writer/EBookImportFilter.hxx b/writerperfect/source/writer/EBookImportFilter.hxx
new file mode 100644
index 000000000..9ebdc9234
--- /dev/null
+++ b/writerperfect/source/writer/EBookImportFilter.hxx
@@ -0,0 +1,44 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef EBOOKIMPORTFILTER_HXX
+#define EBOOKIMPORTFILTER_HXX
+
+#include <com/sun/star/uno/XComponentContext.hpp>
+
+#include <ImportFilter.hxx>
+
+#include <DocumentHandlerForOdt.hxx>
+
+/* This component will be instantiated for both import or export. Whether it calls
+ * setSourceDocument or setTargetDocument determines which Impl function the filter
+ * member calls */
+class EBookImportFilter : public writerperfect::ImportFilter<OdtGenerator>
+{
+public:
+ explicit EBookImportFilter(const css::uno::Reference<css::uno::XComponentContext>& rxContext)
+ : writerperfect::ImportFilter<OdtGenerator>(rxContext)
+ {
+ }
+
+ // XServiceInfo
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override;
+ virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override;
+
+private:
+ virtual bool doDetectFormat(librevenge::RVNGInputStream& rInput, OUString& rTypeName) override;
+ virtual bool doImportDocument(weld::Window* pParent, librevenge::RVNGInputStream& rInput,
+ OdtGenerator& rGenerator,
+ utl::MediaDescriptor& rDescriptor) override;
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/writerperfect/source/writer/EPUBExportDialog.cxx b/writerperfect/source/writer/EPUBExportDialog.cxx
new file mode 100644
index 000000000..0bba77a18
--- /dev/null
+++ b/writerperfect/source/writer/EPUBExportDialog.cxx
@@ -0,0 +1,224 @@
+/* -*- 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 "EPUBExportDialog.hxx"
+
+#include <libepubgen/libepubgen.h>
+
+#include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
+#include <com/sun/star/ui/dialogs/ExecutableDialogResults.hpp>
+#include <com/sun/star/ui/dialogs/XFolderPicker2.hpp>
+#include <comphelper/sequenceashashmap.hxx>
+#include <sfx2/filedlghelper.hxx>
+#include <sfx2/opengrf.hxx>
+#include <sax/tools/converter.hxx>
+#include <i18nlangtag/languagetag.hxx>
+
+#include "EPUBExportFilter.hxx"
+
+using namespace com::sun::star;
+
+namespace
+{
+/// Converts version value to a listbox entry position.
+sal_Int32 VersionToPosition(sal_Int32 nVersion)
+{
+ sal_Int32 nPosition = 0;
+
+ switch (nVersion)
+ {
+ case 30:
+ nPosition = 0;
+ break;
+ case 20:
+ nPosition = 1;
+ break;
+ default:
+ assert(false);
+ break;
+ }
+
+ return nPosition;
+}
+
+/// Converts listbox entry position to a version value.
+sal_Int32 PositionToVersion(sal_Int32 nPosition)
+{
+ sal_Int32 nVersion = 0;
+
+ switch (nPosition)
+ {
+ case 0:
+ nVersion = 30;
+ break;
+ case 1:
+ nVersion = 20;
+ break;
+ default:
+ assert(false);
+ break;
+ }
+
+ return nVersion;
+}
+}
+
+namespace writerperfect
+{
+EPUBExportDialog::EPUBExportDialog(weld::Window* pParent,
+ comphelper::SequenceAsHashMap& rFilterData,
+ uno::Reference<uno::XComponentContext> xContext,
+ css::uno::Reference<css::lang::XComponent> xDocument)
+ : GenericDialogController(pParent, "writerperfect/ui/exportepub.ui", "EpubDialog")
+ , m_xContext(std::move(xContext))
+ , m_rFilterData(rFilterData)
+ , m_xSourceDocument(std::move(xDocument))
+ , m_xVersion(m_xBuilder->weld_combo_box("versionlb"))
+ , m_xSplit(m_xBuilder->weld_combo_box("splitlb"))
+ , m_xLayout(m_xBuilder->weld_combo_box("layoutlb"))
+ , m_xCoverPath(m_xBuilder->weld_entry("coverpath"))
+ , m_xCoverButton(m_xBuilder->weld_button("coverbutton"))
+ , m_xMediaDir(m_xBuilder->weld_entry("mediadir"))
+ , m_xMediaButton(m_xBuilder->weld_button("mediabutton"))
+ , m_xOKButton(m_xBuilder->weld_button("ok"))
+ , m_xIdentifier(m_xBuilder->weld_entry("identifier"))
+ , m_xTitle(m_xBuilder->weld_entry("title"))
+ , m_xInitialCreator(m_xBuilder->weld_entry("author"))
+ , m_xLanguage(m_xBuilder->weld_entry("language"))
+ , m_xDate(m_xBuilder->weld_entry("date"))
+
+{
+ assert(PositionToVersion(m_xVersion->get_active()) == EPUBExportFilter::GetDefaultVersion());
+
+ auto it = rFilterData.find("EPUBVersion");
+ if (it != rFilterData.end())
+ {
+ sal_Int32 nVersion = 0;
+ if (it->second >>= nVersion)
+ m_xVersion->set_active(VersionToPosition(nVersion));
+ }
+ m_xVersion->connect_changed(LINK(this, EPUBExportDialog, VersionSelectHdl));
+
+ it = rFilterData.find("EPUBSplitMethod");
+ if (it != rFilterData.end())
+ {
+ sal_Int32 nSplitMethod = 0;
+ if (it->second >>= nSplitMethod)
+ // No conversion, 1:1 mapping between libepubgen::EPUBSplitMethod
+ // and entry positions.
+ m_xSplit->set_active(nSplitMethod);
+ }
+ else
+ m_xSplit->set_active(EPUBExportFilter::GetDefaultSplitMethod());
+ m_xSplit->connect_changed(LINK(this, EPUBExportDialog, SplitSelectHdl));
+
+ it = rFilterData.find("EPUBLayoutMethod");
+ if (it != rFilterData.end())
+ {
+ sal_Int32 nLayoutMethod = 0;
+ if (it->second >>= nLayoutMethod)
+ // No conversion, 1:1 mapping between libepubgen::EPUBLayoutMethod
+ // and entry positions.
+ m_xLayout->set_active(nLayoutMethod);
+ }
+ else
+ m_xLayout->set_active(EPUBExportFilter::GetDefaultLayoutMethod());
+ m_xLayout->connect_changed(LINK(this, EPUBExportDialog, LayoutSelectHdl));
+
+ m_xCoverButton->connect_clicked(LINK(this, EPUBExportDialog, CoverClickHdl));
+
+ m_xMediaButton->connect_clicked(LINK(this, EPUBExportDialog, MediaClickHdl));
+
+ uno::Reference<document::XDocumentPropertiesSupplier> xDPS(m_xSourceDocument, uno::UNO_QUERY);
+ uno::Reference<document::XDocumentProperties> xDP;
+ if (xDPS.is())
+ xDP = xDPS->getDocumentProperties();
+ if (xDP.is())
+ {
+ m_xTitle->set_text(xDP->getTitle());
+ m_xInitialCreator->set_text(xDP->getAuthor());
+
+ OUString aLanguage(LanguageTag::convertToBcp47(xDP->getLanguage(), false));
+ m_xLanguage->set_text(aLanguage);
+
+ OUStringBuffer aBuffer;
+ util::DateTime aDate(xDP->getModificationDate());
+ sax::Converter::convertDateTime(aBuffer, aDate, nullptr, true);
+ m_xDate->set_text(aBuffer.makeStringAndClear());
+ }
+
+ m_xOKButton->connect_clicked(LINK(this, EPUBExportDialog, OKClickHdl));
+}
+
+IMPL_LINK_NOARG(EPUBExportDialog, VersionSelectHdl, weld::ComboBox&, void)
+{
+ m_rFilterData["EPUBVersion"] <<= PositionToVersion(m_xVersion->get_active());
+}
+
+IMPL_LINK_NOARG(EPUBExportDialog, SplitSelectHdl, weld::ComboBox&, void)
+{
+ // No conversion, 1:1 mapping between entry positions and
+ // libepubgen::EPUBSplitMethod.
+ m_rFilterData["EPUBSplitMethod"] <<= static_cast<sal_Int32>(m_xSplit->get_active());
+}
+
+IMPL_LINK_NOARG(EPUBExportDialog, LayoutSelectHdl, weld::ComboBox&, void)
+{
+ // No conversion, 1:1 mapping between entry positions and
+ // libepubgen::EPUBLayoutMethod.
+ m_rFilterData["EPUBLayoutMethod"] <<= static_cast<sal_Int32>(m_xLayout->get_active());
+ m_xSplit->set_sensitive(m_xLayout->get_active() != libepubgen::EPUB_LAYOUT_METHOD_FIXED);
+}
+
+IMPL_LINK_NOARG(EPUBExportDialog, CoverClickHdl, weld::Button&, void)
+{
+ SvxOpenGraphicDialog aDlg("Import", m_xDialog.get());
+ aDlg.EnableLink(false);
+ if (aDlg.Execute() == ERRCODE_NONE)
+ m_xCoverPath->set_text(aDlg.GetPath());
+}
+
+IMPL_LINK_NOARG(EPUBExportDialog, MediaClickHdl, weld::Button&, void)
+{
+ uno::Reference<ui::dialogs::XFolderPicker2> xFolderPicker
+ = sfx2::createFolderPicker(m_xContext, m_xDialog.get());
+ if (xFolderPicker->execute() != ui::dialogs::ExecutableDialogResults::OK)
+ return;
+
+ m_xMediaDir->set_text(xFolderPicker->getDirectory());
+}
+
+IMPL_LINK_NOARG(EPUBExportDialog, OKClickHdl, weld::Button&, void)
+{
+ // General
+ if (!m_xCoverPath->get_text().isEmpty())
+ m_rFilterData["RVNGCoverImage"] <<= m_xCoverPath->get_text();
+ if (!m_xMediaDir->get_text().isEmpty())
+ m_rFilterData["RVNGMediaDir"] <<= m_xMediaDir->get_text();
+
+ // Metadata
+ if (!m_xIdentifier->get_text().isEmpty())
+ m_rFilterData["RVNGIdentifier"] <<= m_xIdentifier->get_text();
+ if (!m_xTitle->get_text().isEmpty())
+ m_rFilterData["RVNGTitle"] <<= m_xTitle->get_text();
+ if (!m_xInitialCreator->get_text().isEmpty())
+ m_rFilterData["RVNGInitialCreator"] <<= m_xInitialCreator->get_text();
+ if (!m_xLanguage->get_text().isEmpty())
+ m_rFilterData["RVNGLanguage"] <<= m_xLanguage->get_text();
+ if (!m_xDate->get_text().isEmpty())
+ m_rFilterData["RVNGDate"] <<= m_xDate->get_text();
+
+ m_xDialog->response(RET_OK);
+}
+
+EPUBExportDialog::~EPUBExportDialog() = default;
+
+} // namespace writerperfect
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/writerperfect/source/writer/EPUBExportDialog.hxx b/writerperfect/source/writer/EPUBExportDialog.hxx
new file mode 100644
index 000000000..9e11d5351
--- /dev/null
+++ b/writerperfect/source/writer/EPUBExportDialog.hxx
@@ -0,0 +1,61 @@
+/* -*- 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 <vcl/weld.hxx>
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <com/sun/star/lang/XComponent.hpp>
+
+namespace comphelper
+{
+class SequenceAsHashMap;
+}
+
+namespace writerperfect
+{
+/// EPUB export options dialog.
+class EPUBExportDialog : public weld::GenericDialogController
+{
+public:
+ EPUBExportDialog(weld::Window* pParent, comphelper::SequenceAsHashMap& rFilterData,
+ css::uno::Reference<css::uno::XComponentContext> xContext,
+ css::uno::Reference<css::lang::XComponent> xDocument);
+ ~EPUBExportDialog() override;
+
+private:
+ DECL_LINK(VersionSelectHdl, weld::ComboBox&, void);
+ DECL_LINK(SplitSelectHdl, weld::ComboBox&, void);
+ DECL_LINK(LayoutSelectHdl, weld::ComboBox&, void);
+ DECL_LINK(CoverClickHdl, weld::Button&, void);
+ DECL_LINK(MediaClickHdl, weld::Button&, void);
+ DECL_LINK(OKClickHdl, weld::Button&, void);
+
+ css::uno::Reference<css::uno::XComponentContext> m_xContext;
+ comphelper::SequenceAsHashMap& m_rFilterData;
+ css::uno::Reference<css::lang::XComponent> m_xSourceDocument;
+
+ std::unique_ptr<weld::ComboBox> m_xVersion;
+ std::unique_ptr<weld::ComboBox> m_xSplit;
+ std::unique_ptr<weld::ComboBox> m_xLayout;
+ std::unique_ptr<weld::Entry> m_xCoverPath;
+ std::unique_ptr<weld::Button> m_xCoverButton;
+ std::unique_ptr<weld::Entry> m_xMediaDir;
+ std::unique_ptr<weld::Button> m_xMediaButton;
+ std::unique_ptr<weld::Button> m_xOKButton;
+ std::unique_ptr<weld::Entry> m_xIdentifier;
+ std::unique_ptr<weld::Entry> m_xTitle;
+ std::unique_ptr<weld::Entry> m_xInitialCreator;
+ std::unique_ptr<weld::Entry> m_xLanguage;
+ std::unique_ptr<weld::Entry> m_xDate;
+};
+
+} // namespace writerperfect
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/writerperfect/source/writer/EPUBExportFilter.cxx b/writerperfect/source/writer/EPUBExportFilter.cxx
new file mode 100644
index 000000000..8ac55af19
--- /dev/null
+++ b/writerperfect/source/writer/EPUBExportFilter.cxx
@@ -0,0 +1,206 @@
+/* -*- 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 "EPUBExportFilter.hxx"
+
+#include <libepubgen/EPUBTextGenerator.h>
+#include <libepubgen/libepubgen-decls.h>
+
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/frame/XModel.hpp>
+#include <com/sun/star/lang/XInitialization.hpp>
+#include <com/sun/star/text/XPageCursor.hpp>
+#include <com/sun/star/text/XTextViewCursorSupplier.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+
+#include <comphelper/genericpropertyset.hxx>
+#include <comphelper/propertysetinfo.hxx>
+#include <cppuhelper/supportsservice.hxx>
+#include <svtools/DocumentToGraphicRenderer.hxx>
+#include <vcl/filter/SvmWriter.hxx>
+#include <vcl/gdimtf.hxx>
+#include <tools/stream.hxx>
+
+#include "exp/xmlimp.hxx"
+#include "EPUBPackage.hxx"
+
+using namespace com::sun::star;
+
+namespace writerperfect
+{
+EPUBExportFilter::EPUBExportFilter(uno::Reference<uno::XComponentContext> xContext)
+ : mxContext(std::move(xContext))
+{
+}
+
+sal_Int32 EPUBExportFilter::GetDefaultVersion() { return 30; }
+
+sal_Int32 EPUBExportFilter::GetDefaultSplitMethod()
+{
+ return libepubgen::EPUB_SPLIT_METHOD_HEADING;
+}
+
+sal_Int32 EPUBExportFilter::GetDefaultLayoutMethod()
+{
+ return libepubgen::EPUB_LAYOUT_METHOD_REFLOWABLE;
+}
+
+sal_Bool EPUBExportFilter::filter(const uno::Sequence<beans::PropertyValue>& rDescriptor)
+{
+ sal_Int32 nVersion = EPUBExportFilter::GetDefaultVersion();
+ sal_Int32 nSplitMethod = EPUBExportFilter::GetDefaultSplitMethod();
+ sal_Int32 nLayoutMethod = EPUBExportFilter::GetDefaultLayoutMethod();
+ uno::Sequence<beans::PropertyValue> aFilterData;
+ OUString aFilterOptions;
+ for (const auto& rProp : rDescriptor)
+ {
+ if (rProp.Name == "FilterData")
+ rProp.Value >>= aFilterData;
+ else if (rProp.Name == "FilterOptions")
+ rProp.Value >>= aFilterOptions;
+ }
+
+ if (aFilterOptions == "layout=fixed")
+ nLayoutMethod = libepubgen::EPUB_LAYOUT_METHOD_FIXED;
+
+ for (const auto& rProp : std::as_const(aFilterData))
+ {
+ if (rProp.Name == "EPUBVersion")
+ rProp.Value >>= nVersion;
+ else if (rProp.Name == "EPUBSplitMethod")
+ rProp.Value >>= nSplitMethod;
+ else if (rProp.Name == "EPUBLayoutMethod")
+ rProp.Value >>= nLayoutMethod;
+ }
+
+ // Build the export filter chain: the package has direct access to the ZIP
+ // file, the flat ODF filter has access to the doc model, everything else
+ // is in-between.
+ EPUBPackage aPackage(mxContext, rDescriptor);
+ libepubgen::EPUBTextGenerator aGenerator(&aPackage, nVersion);
+ aGenerator.setOption(libepubgen::EPUB_GENERATOR_OPTION_SPLIT, nSplitMethod);
+ aGenerator.setOption(libepubgen::EPUB_GENERATOR_OPTION_LAYOUT, nLayoutMethod);
+ OUString aSourceURL;
+ uno::Reference<frame::XModel> xSourceModel(mxSourceDocument, uno::UNO_QUERY);
+ if (xSourceModel.is())
+ aSourceURL = xSourceModel->getURL();
+
+ std::vector<exp::FixedLayoutPage> aPageMetafiles;
+ if (nLayoutMethod == libepubgen::EPUB_LAYOUT_METHOD_FIXED)
+ CreateMetafiles(aPageMetafiles);
+
+ uno::Reference<xml::sax::XDocumentHandler> xExportHandler(
+ new exp::XMLImport(mxContext, aGenerator, aSourceURL, rDescriptor, aPageMetafiles));
+
+ uno::Reference<lang::XInitialization> xInitialization(
+ mxContext->getServiceManager()->createInstanceWithContext(
+ "com.sun.star.comp.Writer.XMLOasisExporter", mxContext),
+ uno::UNO_QUERY);
+
+ // A subset of parameters are passed in as a property set.
+ static comphelper::PropertyMapEntry const aInfoMap[]
+ = { { OUString("BaseURI"), 0, cppu::UnoType<OUString>::get(),
+ beans::PropertyAttribute::MAYBEVOID, 0 } };
+ uno::Reference<beans::XPropertySet> xInfoSet(
+ comphelper::GenericPropertySet_CreateInstance(new comphelper::PropertySetInfo(aInfoMap)));
+ xInfoSet->setPropertyValue("BaseURI", uno::Any(aSourceURL));
+
+ xInitialization->initialize({ uno::Any(xExportHandler), uno::Any(xInfoSet) });
+ uno::Reference<document::XExporter> xExporter(xInitialization, uno::UNO_QUERY);
+ xExporter->setSourceDocument(mxSourceDocument);
+ uno::Reference<document::XFilter> xFilter(xInitialization, uno::UNO_QUERY);
+
+ return xFilter->filter(rDescriptor);
+}
+
+void EPUBExportFilter::CreateMetafiles(std::vector<exp::FixedLayoutPage>& rPageMetafiles)
+{
+ DocumentToGraphicRenderer aRenderer(mxSourceDocument, /*bSelectionOnly=*/false);
+ uno::Reference<frame::XModel> xModel(mxSourceDocument, uno::UNO_QUERY);
+ if (!xModel.is())
+ return;
+
+ uno::Reference<text::XTextViewCursorSupplier> xTextViewCursorSupplier(
+ xModel->getCurrentController(), uno::UNO_QUERY);
+ if (!xTextViewCursorSupplier.is())
+ return;
+
+ uno::Reference<text::XPageCursor> xCursor(xTextViewCursorSupplier->getViewCursor(),
+ uno::UNO_QUERY);
+ if (!xCursor.is())
+ return;
+
+ xCursor->jumpToLastPage();
+ sal_Int16 nPages = xCursor->getPage();
+ for (sal_Int16 nPage = 1; nPage <= nPages; ++nPage)
+ {
+ Size aDocumentSizePixel = aRenderer.getDocumentSizeInPixels(nPage);
+ Size aLogic = aRenderer.getDocumentSizeIn100mm(nPage);
+ // Get the CSS pixel size of the page (mm100 -> pixel using 96 DPI, independent from system DPI).
+ Size aCss(static_cast<double>(aLogic.getWidth()) / 26.4583,
+ static_cast<double>(aLogic.getHeight()) / 26.4583);
+ Graphic aGraphic = aRenderer.renderToGraphic(nPage, aDocumentSizePixel, aCss, COL_WHITE,
+ /*bExtOutDevData=*/true);
+ auto& rGDIMetaFile = const_cast<GDIMetaFile&>(aGraphic.GetGDIMetaFile());
+
+ // Set preferred map unit and size on the metafile, so the SVG size
+ // will be correct in MM.
+ MapMode aMapMode;
+ aMapMode.SetMapUnit(MapUnit::Map100thMM);
+ rGDIMetaFile.SetPrefMapMode(aMapMode);
+ rGDIMetaFile.SetPrefSize(aLogic);
+
+ SvMemoryStream aMemoryStream;
+ SvmWriter aWriter(aMemoryStream);
+ aWriter.Write(rGDIMetaFile);
+ uno::Sequence<sal_Int8> aSequence(static_cast<const sal_Int8*>(aMemoryStream.GetData()),
+ aMemoryStream.Tell());
+
+ exp::FixedLayoutPage aPage;
+ aPage.aMetafile = aSequence;
+ aPage.aCssPixels = aCss;
+ aPage.aChapterNames = aRenderer.getChapterNames();
+ rPageMetafiles.push_back(aPage);
+ }
+}
+
+void EPUBExportFilter::cancel() {}
+
+void EPUBExportFilter::setSourceDocument(const uno::Reference<lang::XComponent>& xDocument)
+{
+ mxSourceDocument = xDocument;
+}
+
+OUString EPUBExportFilter::getImplementationName()
+{
+ return "com.sun.star.comp.Writer.EPUBExportFilter";
+}
+
+sal_Bool EPUBExportFilter::supportsService(const OUString& rServiceName)
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+uno::Sequence<OUString> EPUBExportFilter::getSupportedServiceNames()
+{
+ uno::Sequence<OUString> aRet = { OUString("com.sun.star.document.ExportFilter") };
+ return aRet;
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface*
+com_sun_star_comp_Writer_EPUBExportFilter_get_implementation(
+ uno::XComponentContext* pContext, uno::Sequence<uno::Any> const& /*rSeq*/)
+{
+ return cppu::acquire(new EPUBExportFilter(pContext));
+}
+
+} // namespace writerperfect
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/writerperfect/source/writer/EPUBExportFilter.hxx b/writerperfect/source/writer/EPUBExportFilter.hxx
new file mode 100644
index 000000000..6cf007ff4
--- /dev/null
+++ b/writerperfect/source/writer/EPUBExportFilter.hxx
@@ -0,0 +1,71 @@
+/* -*- 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 <vector>
+
+#include <cppuhelper/implbase.hxx>
+
+#include <com/sun/star/document/XFilter.hpp>
+#include <com/sun/star/document/XExporter.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+
+namespace com::sun::star::uno
+{
+class XComponentContext;
+}
+
+namespace writerperfect
+{
+namespace exp
+{
+struct FixedLayoutPage;
+}
+
+/// EPUB export XFilter implementation.
+class EPUBExportFilter
+ : public cppu::WeakImplHelper<css::document::XFilter, css::document::XExporter,
+ css::lang::XServiceInfo>
+{
+ css::uno::Reference<css::uno::XComponentContext> mxContext;
+ css::uno::Reference<css::lang::XComponent> mxSourceDocument;
+
+public:
+ EPUBExportFilter(css::uno::Reference<css::uno::XComponentContext> xContext);
+
+ // XFilter
+ sal_Bool SAL_CALL
+ filter(const css::uno::Sequence<css::beans::PropertyValue>& rDescriptor) override;
+ void SAL_CALL cancel() override;
+
+ // XExporter
+ void SAL_CALL
+ setSourceDocument(const css::uno::Reference<css::lang::XComponent>& xDocument) override;
+
+ // XServiceInfo
+ OUString SAL_CALL getImplementationName() override;
+ sal_Bool SAL_CALL supportsService(const OUString& rServiceName) override;
+ css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override;
+
+ /// Gives the default EPUB version.
+ static sal_Int32 GetDefaultVersion();
+ /// Gives the default split method.
+ static sal_Int32 GetDefaultSplitMethod();
+ /// Gives the default layout method.
+ static sal_Int32 GetDefaultLayoutMethod();
+
+private:
+ /// Create page metafiles in case of fixed layout.
+ void CreateMetafiles(std::vector<exp::FixedLayoutPage>& rPageMetafiles);
+};
+
+} // namespace writerperfect
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/writerperfect/source/writer/EPUBExportUIComponent.cxx b/writerperfect/source/writer/EPUBExportUIComponent.cxx
new file mode 100644
index 000000000..e8d618b99
--- /dev/null
+++ b/writerperfect/source/writer/EPUBExportUIComponent.cxx
@@ -0,0 +1,102 @@
+/* -*- 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 "EPUBExportUIComponent.hxx"
+
+#include <com/sun/star/ui/dialogs/ExecutableDialogResults.hpp>
+#include <comphelper/namedvaluecollection.hxx>
+#include <cppuhelper/supportsservice.hxx>
+#include <vcl/svapp.hxx>
+
+#include "EPUBExportDialog.hxx"
+
+using namespace com::sun::star;
+
+namespace writerperfect
+{
+EPUBExportUIComponent::EPUBExportUIComponent(uno::Reference<uno::XComponentContext> xContext)
+ : mxContext(std::move(xContext))
+{
+}
+
+uno::Sequence<beans::PropertyValue> EPUBExportUIComponent::getPropertyValues()
+{
+ maMediaDescriptor["FilterData"] <<= maFilterData.getAsConstPropertyValueList();
+ return maMediaDescriptor.getAsConstPropertyValueList();
+}
+
+void EPUBExportUIComponent::setPropertyValues(
+ const uno::Sequence<beans::PropertyValue>& rProperties)
+{
+ maMediaDescriptor.clear();
+ maMediaDescriptor << rProperties;
+ auto it = maMediaDescriptor.find("FilterData");
+ if (it != maMediaDescriptor.end())
+ {
+ uno::Sequence<beans::PropertyValue> aFilterData;
+ if (it->second >>= aFilterData)
+ {
+ maFilterData.clear();
+ maFilterData << aFilterData;
+ }
+ }
+}
+
+OUString EPUBExportUIComponent::getImplementationName()
+{
+ return "com.sun.star.comp.Writer.EPUBExportUIComponent";
+}
+
+sal_Bool EPUBExportUIComponent::supportsService(const OUString& rServiceName)
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+uno::Sequence<OUString> EPUBExportUIComponent::getSupportedServiceNames()
+{
+ uno::Sequence<OUString> aRet = { OUString("com.sun.star.ui.dialogs.FilterOptionsDialog") };
+ return aRet;
+}
+
+void EPUBExportUIComponent::setTitle(const OUString& /*rTitle*/) {}
+
+void SAL_CALL EPUBExportUIComponent::initialize(const uno::Sequence<uno::Any>& rArguments)
+{
+ ::comphelper::NamedValueCollection aProperties(rArguments);
+ if (aProperties.has("ParentWindow"))
+ aProperties.get("ParentWindow") >>= mxDialogParent;
+}
+
+sal_Int16 EPUBExportUIComponent::execute()
+{
+ SolarMutexGuard aGuard;
+
+ EPUBExportDialog aDialog(Application::GetFrameWeld(mxDialogParent), maFilterData, mxContext,
+ mxSourceDocument);
+ if (aDialog.run() == RET_OK)
+ return ui::dialogs::ExecutableDialogResults::OK;
+ return ui::dialogs::ExecutableDialogResults::CANCEL;
+}
+
+void SAL_CALL EPUBExportUIComponent::setSourceDocument(
+ const css::uno::Reference<css::lang::XComponent>& xDocument)
+{
+ mxSourceDocument = xDocument;
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface*
+com_sun_star_comp_Writer_EPUBExportUIComponent_get_implementation(
+ uno::XComponentContext* pCtx, uno::Sequence<uno::Any> const& /*rSeq*/)
+{
+ return cppu::acquire(new EPUBExportUIComponent(pCtx));
+}
+
+} // namespace writerperfect
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/writerperfect/source/writer/EPUBExportUIComponent.hxx b/writerperfect/source/writer/EPUBExportUIComponent.hxx
new file mode 100644
index 000000000..71fcc0ace
--- /dev/null
+++ b/writerperfect/source/writer/EPUBExportUIComponent.hxx
@@ -0,0 +1,72 @@
+/* -*- 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/beans/XPropertyAccess.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/lang/XInitialization.hpp>
+#include <com/sun/star/ui/dialogs/XExecutableDialog.hpp>
+#include <com/sun/star/document/XExporter.hpp>
+#include <com/sun/star/awt/XWindow.hpp>
+
+#include <comphelper/sequenceashashmap.hxx>
+#include <cppuhelper/implbase.hxx>
+
+namespace com::sun::star::uno
+{
+class XComponentContext;
+}
+
+namespace writerperfect
+{
+/// EPUB export UI component implementation.
+class EPUBExportUIComponent
+ : public cppu::WeakImplHelper<css::beans::XPropertyAccess, css::lang::XInitialization,
+ css::lang::XServiceInfo, css::ui::dialogs::XExecutableDialog,
+ css::document::XExporter>
+{
+public:
+ EPUBExportUIComponent(css::uno::Reference<css::uno::XComponentContext> xContext);
+
+ // XPropertyAccess
+ css::uno::Sequence<css::beans::PropertyValue> SAL_CALL getPropertyValues() override;
+ void SAL_CALL
+ setPropertyValues(const css::uno::Sequence<css::beans::PropertyValue>& rProperties) override;
+
+ // XServiceInfo
+ OUString SAL_CALL getImplementationName() override;
+ sal_Bool SAL_CALL supportsService(const OUString& rServiceName) override;
+ css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override;
+
+ // XExecutableDialog
+ void SAL_CALL setTitle(const OUString& rTitle) override;
+ sal_Int16 SAL_CALL execute() override;
+
+ // XExporter
+ void SAL_CALL
+ setSourceDocument(const css::uno::Reference<css::lang::XComponent>& xDocument) override;
+
+ // XInitialization
+ void SAL_CALL initialize(const css::uno::Sequence<css::uno::Any>& rArguments) override;
+
+private:
+ /// The full set of property values.
+ comphelper::SequenceAsHashMap maMediaDescriptor;
+ /// The filter data key.
+ comphelper::SequenceAsHashMap maFilterData;
+ /// UNO context.
+ css::uno::Reference<css::uno::XComponentContext> mxContext;
+ css::uno::Reference<css::lang::XComponent> mxSourceDocument;
+ css::uno::Reference<css::awt::XWindow> mxDialogParent;
+};
+
+} // namespace writerperfect
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/writerperfect/source/writer/EPUBPackage.cxx b/writerperfect/source/writer/EPUBPackage.cxx
new file mode 100644
index 000000000..727a8ed7e
--- /dev/null
+++ b/writerperfect/source/writer/EPUBPackage.cxx
@@ -0,0 +1,215 @@
+/* -*- 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 "EPUBPackage.hxx"
+
+#include <com/sun/star/embed/ElementModes.hpp>
+#include <com/sun/star/embed/XStorage.hpp>
+#include <com/sun/star/embed/XTransactedObject.hpp>
+#include <com/sun/star/io/XSeekable.hpp>
+#include <com/sun/star/xml/sax/Writer.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/embed/XHierarchicalStorageAccess.hpp>
+
+#include <sal/log.hxx>
+#include <comphelper/storagehelper.hxx>
+#include <unotools/mediadescriptor.hxx>
+#include <xmloff/attrlist.hxx>
+
+using namespace com::sun::star;
+
+namespace writerperfect
+{
+EPUBPackage::EPUBPackage(uno::Reference<uno::XComponentContext> xContext,
+ const uno::Sequence<beans::PropertyValue>& rDescriptor)
+ : mxContext(std::move(xContext))
+{
+ // Extract the output stream from the descriptor.
+ utl::MediaDescriptor aMediaDesc(rDescriptor);
+ auto xStream = aMediaDesc.getUnpackedValueOrDefault(utl::MediaDescriptor::PROP_STREAMFOROUTPUT,
+ uno::Reference<io::XStream>());
+ const sal_Int32 nOpenMode = embed::ElementModes::READWRITE | embed::ElementModes::TRUNCATE;
+ mxStorage.set(comphelper::OStorageHelper::GetStorageOfFormatFromStream(
+ ZIP_STORAGE_FORMAT_STRING, xStream, nOpenMode, mxContext),
+ uno::UNO_QUERY);
+
+ // The zipped content represents an EPUB Publication.
+ mxOutputStream.set(
+ mxStorage->openStreamElementByHierarchicalName("mimetype", embed::ElementModes::READWRITE),
+ uno::UNO_QUERY);
+ const OString aMimeType("application/epub+zip");
+ uno::Sequence<sal_Int8> aData(reinterpret_cast<const sal_Int8*>(aMimeType.getStr()),
+ aMimeType.getLength());
+ mxOutputStream->writeBytes(aData);
+ uno::Reference<embed::XTransactedObject> xTransactedObject(mxOutputStream, uno::UNO_QUERY);
+ xTransactedObject->commit();
+
+ // MIME type must be uncompressed.
+ uno::Reference<beans::XPropertySet> xPropertySet(mxOutputStream, uno::UNO_QUERY);
+ xPropertySet->setPropertyValue("Compressed", uno::Any(false));
+ mxOutputStream.clear();
+}
+
+EPUBPackage::~EPUBPackage()
+{
+ uno::Reference<embed::XTransactedObject> xTransactedObject(mxStorage, uno::UNO_QUERY);
+ xTransactedObject->commit();
+}
+
+void EPUBPackage::openXMLFile(const char* pName)
+{
+ assert(pName);
+ assert(!mxOutputStream.is());
+ assert(!mxOutputWriter.is());
+
+ mxOutputStream.set(mxStorage->openStreamElementByHierarchicalName(
+ OUString::fromUtf8(pName), embed::ElementModes::READWRITE),
+ uno::UNO_QUERY);
+ mxOutputWriter = xml::sax::Writer::create(mxContext);
+ mxOutputWriter->setOutputStream(mxOutputStream);
+ mxOutputWriter->startDocument();
+}
+
+void EPUBPackage::openElement(const char* pName, const librevenge::RVNGPropertyList& rAttributes)
+{
+ assert(mxOutputWriter.is());
+
+ rtl::Reference<SvXMLAttributeList> pAttributeList(new SvXMLAttributeList());
+
+ librevenge::RVNGPropertyList::Iter it(rAttributes);
+ for (it.rewind(); it.next();)
+ pAttributeList->AddAttribute(OUString::fromUtf8(it.key()),
+ OUString::fromUtf8(it()->getStr().cstr()));
+
+ mxOutputWriter->startElement(OUString::fromUtf8(pName), pAttributeList);
+}
+
+void EPUBPackage::closeElement(const char* pName)
+{
+ assert(mxOutputWriter.is());
+
+ mxOutputWriter->endElement(OUString::fromUtf8(pName));
+}
+
+void EPUBPackage::insertCharacters(const librevenge::RVNGString& rCharacters)
+{
+ mxOutputWriter->characters(OUString::fromUtf8(rCharacters.cstr()));
+}
+
+void EPUBPackage::closeXMLFile()
+{
+ assert(mxOutputWriter.is());
+ assert(mxOutputStream.is());
+
+ mxOutputWriter->endDocument();
+ mxOutputWriter.clear();
+
+ uno::Reference<embed::XTransactedObject> xTransactedObject(mxOutputStream, uno::UNO_QUERY);
+ xTransactedObject->commit();
+ mxOutputStream.clear();
+}
+
+void EPUBPackage::openCSSFile(const char* pName)
+{
+ assert(pName);
+ assert(!mxOutputStream.is());
+
+ mxOutputStream.set(mxStorage->openStreamElementByHierarchicalName(
+ OUString::fromUtf8(pName), embed::ElementModes::READWRITE),
+ uno::UNO_QUERY);
+}
+
+void EPUBPackage::insertRule(const librevenge::RVNGString& rSelector,
+ const librevenge::RVNGPropertyList& rProperties)
+{
+ assert(mxOutputStream.is());
+
+ uno::Reference<io::XSeekable> xSeekable(mxOutputStream, uno::UNO_QUERY);
+ std::stringstream aStream;
+ if (xSeekable->getPosition() != 0)
+ aStream << '\n';
+ aStream << rSelector.cstr() << " {\n";
+
+ librevenge::RVNGPropertyList::Iter it(rProperties);
+ for (it.rewind(); it.next();)
+ {
+ if (it())
+ aStream << " " << it.key() << ": " << it()->getStr().cstr() << ";\n";
+ }
+
+ aStream << "}\n";
+ std::string aString = aStream.str();
+ uno::Sequence<sal_Int8> aData(reinterpret_cast<const sal_Int8*>(aString.c_str()),
+ aString.size());
+ mxOutputStream->writeBytes(aData);
+}
+
+void EPUBPackage::closeCSSFile()
+{
+ assert(mxOutputStream.is());
+
+ uno::Reference<embed::XTransactedObject> xTransactedObject(mxOutputStream, uno::UNO_QUERY);
+ xTransactedObject->commit();
+ mxOutputStream.clear();
+}
+
+void EPUBPackage::openBinaryFile(const char* pName)
+{
+ assert(pName);
+ assert(!mxOutputStream.is());
+
+ mxOutputStream.set(mxStorage->openStreamElementByHierarchicalName(
+ OUString::fromUtf8(pName), embed::ElementModes::READWRITE),
+ uno::UNO_QUERY);
+}
+
+void EPUBPackage::insertBinaryData(const librevenge::RVNGBinaryData& rData)
+{
+ assert(mxOutputStream.is());
+
+ if (rData.empty())
+ return;
+
+ uno::Sequence<sal_Int8> aData(reinterpret_cast<const sal_Int8*>(rData.getDataBuffer()),
+ rData.size());
+ mxOutputStream->writeBytes(aData);
+}
+
+void EPUBPackage::closeBinaryFile()
+{
+ assert(mxOutputStream.is());
+
+ uno::Reference<embed::XTransactedObject> xTransactedObject(mxOutputStream, uno::UNO_QUERY);
+ xTransactedObject->commit();
+ mxOutputStream.clear();
+}
+
+void EPUBPackage::openTextFile(const char* pName)
+{
+ SAL_WARN("writerperfect", "EPUBPackage::openTextFile, " << pName << ": implement me");
+}
+
+void EPUBPackage::insertText(const librevenge::RVNGString& /*rCharacters*/)
+{
+ SAL_WARN("writerperfect", "EPUBPackage::insertText: implement me");
+}
+
+void EPUBPackage::insertLineBreak()
+{
+ SAL_WARN("writerperfect", "EPUBPackage::insertLineBreak: implement me");
+}
+
+void EPUBPackage::closeTextFile()
+{
+ SAL_WARN("writerperfect", "EPUBPackage::closeTextFile: implement me");
+}
+
+} // namespace writerperfect
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/writerperfect/source/writer/EPUBPackage.hxx b/writerperfect/source/writer/EPUBPackage.hxx
new file mode 100644
index 000000000..726d20673
--- /dev/null
+++ b/writerperfect/source/writer/EPUBPackage.hxx
@@ -0,0 +1,90 @@
+/* -*- 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 <libepubgen/EPUBPackage.h>
+
+#include <com/sun/star/uno/Sequence.h>
+#include <com/sun/star/uno/Reference.h>
+
+namespace com::sun::star
+{
+namespace beans
+{
+struct PropertyValue;
+}
+namespace embed
+{
+class XHierarchicalStorageAccess;
+}
+namespace io
+{
+class XOutputStream;
+}
+namespace uno
+{
+class XComponentContext;
+}
+namespace xml::sax
+{
+class XWriter;
+}
+}
+
+namespace writerperfect
+{
+/// The epub package has direct access to the resulting ZIP file.
+class EPUBPackage : public libepubgen::EPUBPackage
+{
+ css::uno::Reference<css::uno::XComponentContext> mxContext;
+ css::uno::Reference<css::embed::XHierarchicalStorageAccess> mxStorage;
+ css::uno::Reference<css::io::XOutputStream> mxOutputStream;
+ css::uno::Reference<css::xml::sax::XWriter> mxOutputWriter;
+
+public:
+ explicit EPUBPackage(css::uno::Reference<css::uno::XComponentContext> xContext,
+ const css::uno::Sequence<css::beans::PropertyValue>& rDescriptor);
+
+ ~EPUBPackage() override;
+
+ void openXMLFile(const char* pName) override;
+
+ void openElement(const char* pName, const librevenge::RVNGPropertyList& rAttributes) override;
+ void closeElement(const char* pName) override;
+
+ void insertCharacters(const librevenge::RVNGString& rCharacters) override;
+
+ void closeXMLFile() override;
+
+ void openCSSFile(const char* pName) override;
+
+ void insertRule(const librevenge::RVNGString& rSelector,
+ const librevenge::RVNGPropertyList& rProperties) override;
+
+ void closeCSSFile() override;
+
+ void openBinaryFile(const char* pName) override;
+
+ void insertBinaryData(const librevenge::RVNGBinaryData& rData) override;
+
+ void closeBinaryFile() override;
+
+ void openTextFile(const char* pName) override;
+
+ void insertText(const librevenge::RVNGString& rCharacters) override;
+
+ void insertLineBreak() override;
+
+ void closeTextFile() override;
+};
+
+} // namespace writerperfect
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/writerperfect/source/writer/MSWorksImportFilter.cxx b/writerperfect/source/writer/MSWorksImportFilter.cxx
new file mode 100644
index 000000000..e79120408
--- /dev/null
+++ b/writerperfect/source/writer/MSWorksImportFilter.cxx
@@ -0,0 +1,157 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* MSWorksImportFilter: Sets up the filter, and calls DocumentCollector
+ * to do the actual filtering
+ *
+ * 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 <cppuhelper/supportsservice.hxx>
+#include <tools/diagnose_ex.h>
+
+#include <libwps/libwps.h>
+
+#include <WPFTEncodingDialog.hxx>
+#include <WPFTResMgr.hxx>
+#include "MSWorksImportFilter.hxx"
+#include <strings.hrc>
+
+static bool handleEmbeddedWKSObject(const librevenge::RVNGBinaryData& data,
+ OdfDocumentHandler* pHandler, const OdfStreamType streamType)
+{
+ OdsGenerator exporter;
+ exporter.addDocumentHandler(pHandler, streamType);
+ return libwps::WPSDocument::parse(data.getDataStream(), &exporter) == libwps::WPS_OK;
+}
+
+bool MSWorksImportFilter::doImportDocument(weld::Window* pParent,
+ librevenge::RVNGInputStream& rInput,
+ OdtGenerator& rGenerator,
+ utl::MediaDescriptor& mediaDescriptor)
+{
+ libwps::WPSKind kind = libwps::WPS_TEXT;
+ libwps::WPSCreator creator;
+ bool needEncoding = false;
+ const libwps::WPSConfidence confidence
+ = libwps::WPSDocument::isFileFormatSupported(&rInput, kind, creator, needEncoding);
+
+ std::string fileEncoding;
+ if ((kind == libwps::WPS_TEXT) && (confidence == libwps::WPS_CONFIDENCE_EXCELLENT)
+ && needEncoding)
+ {
+ OUString encoding;
+ // first check if we can find the encoding in the filter options (headless mode)
+ mediaDescriptor[utl::MediaDescriptor::PROP_FILTEROPTIONS] >>= encoding;
+ if (!encoding.isEmpty()) // TODO: check if the encoding string is valid
+ fileEncoding = encoding.toUtf8().getStr();
+ else
+ {
+ OUString title;
+
+ switch (creator)
+ {
+ case libwps::WPS_MSWORKS:
+ title = WpResId(STR_ENCODING_DIALOG_TITLE_MSWORKS);
+ encoding = "CP850";
+ break;
+ case libwps::WPS_RESERVED_0: // MS Write
+ title = WpResId(STR_ENCODING_DIALOG_TITLE_MSWRITE);
+ encoding = "CP1252";
+ break;
+ case libwps::WPS_RESERVED_1: // DosWord
+ title = WpResId(STR_ENCODING_DIALOG_TITLE_DOSWORD);
+ encoding = "CP850";
+ break;
+ default:
+ title = WpResId(STR_ENCODING_DIALOG_TITLE);
+ encoding = "CP850";
+ break;
+ }
+
+ fileEncoding = encoding.toUtf8().getStr(); // set default to the proposed encoding
+ try
+ {
+ writerperfect::WPFTEncodingDialog aDlg(pParent, title, encoding);
+ if (aDlg.run() == RET_OK)
+ {
+ if (!aDlg.GetEncoding().isEmpty())
+ fileEncoding = aDlg.GetEncoding().toUtf8().getStr();
+ }
+ // we can fail because we are in headless mode, the user has cancelled conversion, ...
+ else if (aDlg.hasUserCalledCancel())
+ return false;
+ }
+ catch (css::uno::Exception&)
+ {
+ TOOLS_WARN_EXCEPTION("writerperfect", "ignoring");
+ }
+ }
+ }
+ return libwps::WPS_OK
+ == libwps::WPSDocument::parse(&rInput, &rGenerator, "", fileEncoding.c_str());
+}
+
+bool MSWorksImportFilter::doDetectFormat(librevenge::RVNGInputStream& rInput, OUString& rTypeName)
+{
+ libwps::WPSKind kind = libwps::WPS_TEXT;
+ libwps::WPSCreator creator;
+ bool needEncoding;
+ const libwps::WPSConfidence confidence
+ = libwps::WPSDocument::isFileFormatSupported(&rInput, kind, creator, needEncoding);
+
+ if ((kind == libwps::WPS_TEXT) && (confidence == libwps::WPS_CONFIDENCE_EXCELLENT))
+ {
+ switch (creator)
+ {
+ case libwps::WPS_MSWORKS:
+ rTypeName = "writer_MS_Works_Document";
+ break;
+ case libwps::WPS_RESERVED_0:
+ rTypeName = "writer_MS_Write";
+ break;
+ case libwps::WPS_RESERVED_1:
+ rTypeName = "writer_DosWord";
+ break;
+ case libwps::WPS_RESERVED_4:
+ rTypeName = "writer_PocketWord_File";
+ break;
+ default:
+ break;
+ }
+ }
+
+ return !rTypeName.isEmpty();
+}
+
+void MSWorksImportFilter::doRegisterHandlers(OdtGenerator& rGenerator)
+{
+ rGenerator.registerEmbeddedObjectHandler("image/wks-ods", &handleEmbeddedWKSObject);
+}
+
+// XServiceInfo
+OUString SAL_CALL MSWorksImportFilter::getImplementationName()
+{
+ return "com.sun.star.comp.Writer.MSWorksImportFilter";
+}
+
+sal_Bool SAL_CALL MSWorksImportFilter::supportsService(const OUString& rServiceName)
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+css::uno::Sequence<OUString> SAL_CALL MSWorksImportFilter::getSupportedServiceNames()
+{
+ return { "com.sun.star.document.ImportFilter", "com.sun.star.document.ExtendedTypeDetection" };
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+com_sun_star_comp_Writer_MSWorksImportFilter_get_implementation(
+ css::uno::XComponentContext* const context, const css::uno::Sequence<css::uno::Any>&)
+{
+ return cppu::acquire(new MSWorksImportFilter(context));
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/writerperfect/source/writer/MSWorksImportFilter.hxx b/writerperfect/source/writer/MSWorksImportFilter.hxx
new file mode 100644
index 000000000..629904fda
--- /dev/null
+++ b/writerperfect/source/writer/MSWorksImportFilter.hxx
@@ -0,0 +1,41 @@
+/* -*- 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/uno/XComponentContext.hpp>
+
+#include <ImportFilter.hxx>
+
+#include <DocumentHandlerForOdt.hxx>
+
+/* This component will be instantiated for both import or export. Whether it calls
+ * setSourceDocument or setTargetDocument determines which Impl function the filter
+ * member calls */
+class MSWorksImportFilter : public writerperfect::ImportFilter<OdtGenerator>
+{
+public:
+ explicit MSWorksImportFilter(const css::uno::Reference<css::uno::XComponentContext>& rxContext)
+ : writerperfect::ImportFilter<OdtGenerator>(rxContext)
+ {
+ }
+
+ // XServiceInfo
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override;
+ virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override;
+
+private:
+ virtual bool doDetectFormat(librevenge::RVNGInputStream& rInput, OUString& rTypeName) override;
+ virtual bool doImportDocument(weld::Window* pParent, librevenge::RVNGInputStream& rInput,
+ OdtGenerator& rGenerator, utl::MediaDescriptor&) override;
+ virtual void doRegisterHandlers(OdtGenerator& rGenerator) override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/writerperfect/source/writer/MWAWImportFilter.cxx b/writerperfect/source/writer/MWAWImportFilter.cxx
new file mode 100644
index 000000000..33fe2d95f
--- /dev/null
+++ b/writerperfect/source/writer/MWAWImportFilter.cxx
@@ -0,0 +1,117 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* MWAWImportFilter: Sets up the filter, and calls DocumentCollector
+ * to do the actual filtering
+ *
+ * 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 <cppuhelper/supportsservice.hxx>
+
+#include <libmwaw/libmwaw.hxx>
+
+#include "MWAWImportFilter.hxx"
+
+static bool handleEmbeddedMWAWGraphicObject(const librevenge::RVNGBinaryData& data,
+ OdfDocumentHandler* pHandler,
+ const OdfStreamType streamType)
+{
+ OdgGenerator exporter;
+ exporter.addDocumentHandler(pHandler, streamType);
+ return MWAWDocument::decodeGraphic(data, &exporter);
+}
+
+static bool handleEmbeddedMWAWSpreadsheetObject(const librevenge::RVNGBinaryData& data,
+ OdfDocumentHandler* pHandler,
+ const OdfStreamType streamType)
+{
+ OdsGenerator exporter;
+ exporter.registerEmbeddedObjectHandler("image/mwaw-odg", &handleEmbeddedMWAWGraphicObject);
+ exporter.addDocumentHandler(pHandler, streamType);
+ return MWAWDocument::decodeSpreadsheet(data, &exporter);
+}
+
+bool MWAWImportFilter::doImportDocument(weld::Window*, librevenge::RVNGInputStream& rInput,
+ OdtGenerator& rGenerator, utl::MediaDescriptor&)
+{
+ return MWAWDocument::MWAW_R_OK == MWAWDocument::parse(&rInput, &rGenerator);
+}
+
+bool MWAWImportFilter::doDetectFormat(librevenge::RVNGInputStream& rInput, OUString& rTypeName)
+{
+ rTypeName.clear();
+
+ MWAWDocument::Type docType = MWAWDocument::MWAW_T_UNKNOWN;
+ MWAWDocument::Kind docKind = MWAWDocument::MWAW_K_UNKNOWN;
+ const MWAWDocument::Confidence confidence
+ = MWAWDocument::isFileFormatSupported(&rInput, docType, docKind);
+
+ if (confidence == MWAWDocument::MWAW_C_EXCELLENT)
+ {
+ if (docKind == MWAWDocument::MWAW_K_TEXT)
+ {
+ switch (docType)
+ {
+ case MWAWDocument::MWAW_T_CLARISWORKS:
+ rTypeName = "writer_ClarisWorks";
+ break;
+ case MWAWDocument::MWAW_T_MACWRITE:
+ case MWAWDocument::MWAW_T_MACWRITEPRO:
+ rTypeName = "writer_MacWrite";
+ break;
+ case MWAWDocument::MWAW_T_MARINERWRITE:
+ rTypeName = "writer_Mariner_Write";
+ break;
+ case MWAWDocument::MWAW_T_MICROSOFTWORD:
+ rTypeName = "writer_Mac_Word";
+ break;
+ case MWAWDocument::MWAW_T_MICROSOFTWORKS:
+ rTypeName = "writer_Mac_Works";
+ break;
+ case MWAWDocument::MWAW_T_WRITENOW:
+ rTypeName = "writer_WriteNow";
+ break;
+ default:
+ rTypeName = "MWAW_Text_Document";
+ break;
+ }
+ }
+ }
+
+ return !rTypeName.isEmpty();
+}
+
+void MWAWImportFilter::doRegisterHandlers(OdtGenerator& rGenerator)
+{
+ rGenerator.registerEmbeddedObjectHandler("image/mwaw-odg", &handleEmbeddedMWAWGraphicObject);
+ rGenerator.registerEmbeddedObjectHandler("image/mwaw-ods",
+ &handleEmbeddedMWAWSpreadsheetObject);
+}
+
+// XServiceInfo
+OUString SAL_CALL MWAWImportFilter::getImplementationName()
+{
+ return "com.sun.star.comp.Writer.MWAWImportFilter";
+}
+
+sal_Bool SAL_CALL MWAWImportFilter::supportsService(const OUString& rServiceName)
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+css::uno::Sequence<OUString> SAL_CALL MWAWImportFilter::getSupportedServiceNames()
+{
+ return { "com.sun.star.document.ImportFilter", "com.sun.star.document.ExtendedTypeDetection" };
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+com_sun_star_comp_Writer_MWAWImportFilter_get_implementation(
+ css::uno::XComponentContext* const context, const css::uno::Sequence<css::uno::Any>&)
+{
+ return cppu::acquire(new MWAWImportFilter(context));
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/writerperfect/source/writer/MWAWImportFilter.hxx b/writerperfect/source/writer/MWAWImportFilter.hxx
new file mode 100644
index 000000000..b7bb19268
--- /dev/null
+++ b/writerperfect/source/writer/MWAWImportFilter.hxx
@@ -0,0 +1,41 @@
+/* -*- 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/uno/XComponentContext.hpp>
+
+#include <ImportFilter.hxx>
+
+#include <DocumentHandlerForOdt.hxx>
+
+/* This component will be instantiated for both import or export. Whether it calls
+ * setSourceDocument or setTargetDocument determines which Impl function the filter
+ * member calls */
+class MWAWImportFilter : public writerperfect::ImportFilter<OdtGenerator>
+{
+public:
+ explicit MWAWImportFilter(const css::uno::Reference<css::uno::XComponentContext>& rxContext)
+ : writerperfect::ImportFilter<OdtGenerator>(rxContext)
+ {
+ }
+
+ // XServiceInfo
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override;
+ virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override;
+
+private:
+ virtual bool doDetectFormat(librevenge::RVNGInputStream& rInput, OUString& rTypeName) override;
+ virtual bool doImportDocument(weld::Window* pParent, librevenge::RVNGInputStream& rInput,
+ OdtGenerator& rGenerator, utl::MediaDescriptor&) override;
+ virtual void doRegisterHandlers(OdtGenerator& rGenerator) override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/writerperfect/source/writer/PagesImportFilter.cxx b/writerperfect/source/writer/PagesImportFilter.cxx
new file mode 100644
index 000000000..9d8bb5eb3
--- /dev/null
+++ b/writerperfect/source/writer/PagesImportFilter.cxx
@@ -0,0 +1,63 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* PagesImportFilter: Sets up the filter, and calls DocumentCollector
+ * to do the actual filtering
+ *
+ * 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 <libetonyek/libetonyek.h>
+
+#include <cppuhelper/supportsservice.hxx>
+
+#include "PagesImportFilter.hxx"
+
+using libetonyek::EtonyekDocument;
+
+bool PagesImportFilter::doImportDocument(weld::Window*, librevenge::RVNGInputStream& rInput,
+ OdtGenerator& rGenerator, utl::MediaDescriptor&)
+{
+ return EtonyekDocument::parse(&rInput, &rGenerator);
+}
+
+bool PagesImportFilter::doDetectFormat(librevenge::RVNGInputStream& rInput, OUString& rTypeName)
+{
+ EtonyekDocument::Type type = EtonyekDocument::TYPE_UNKNOWN;
+ const EtonyekDocument::Confidence confidence = EtonyekDocument::isSupported(&rInput, &type);
+ if ((confidence == EtonyekDocument::CONFIDENCE_EXCELLENT)
+ && (type == EtonyekDocument::TYPE_PAGES))
+ {
+ rTypeName = "writer_ApplePages";
+ return true;
+ }
+
+ return false;
+}
+
+// XServiceInfo
+OUString SAL_CALL PagesImportFilter::getImplementationName()
+{
+ return "org.libreoffice.comp.Writer.PagesImportFilter";
+}
+
+sal_Bool SAL_CALL PagesImportFilter::supportsService(const OUString& rServiceName)
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+css::uno::Sequence<OUString> SAL_CALL PagesImportFilter::getSupportedServiceNames()
+{
+ return { "com.sun.star.document.ImportFilter", "com.sun.star.document.ExtendedTypeDetection" };
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+org_libreoffice_comp_Writer_PagesImportFilter_get_implementation(
+ css::uno::XComponentContext* const context, const css::uno::Sequence<css::uno::Any>&)
+{
+ return cppu::acquire(new PagesImportFilter(context));
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/writerperfect/source/writer/PagesImportFilter.hxx b/writerperfect/source/writer/PagesImportFilter.hxx
new file mode 100644
index 000000000..83fc04618
--- /dev/null
+++ b/writerperfect/source/writer/PagesImportFilter.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 <com/sun/star/uno/XComponentContext.hpp>
+
+#include <DocumentHandlerForOdt.hxx>
+#include <ImportFilter.hxx>
+
+/* This component will be instantiated for both import or export. Whether it calls
+ * setSourceDocument or setTargetDocument determines which Impl function the filter
+ * member calls */
+class PagesImportFilter : public writerperfect::ImportFilter<OdtGenerator>
+{
+public:
+ explicit PagesImportFilter(const css::uno::Reference<css::uno::XComponentContext>& rxContext)
+ : writerperfect::ImportFilter<OdtGenerator>(rxContext)
+ {
+ }
+
+ // XServiceInfo
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override;
+ virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override;
+
+private:
+ virtual bool doDetectFormat(librevenge::RVNGInputStream& rInput, OUString& rTypeName) override;
+ virtual bool doImportDocument(weld::Window* pParent, librevenge::RVNGInputStream& rInput,
+ OdtGenerator& rGenerator,
+ utl::MediaDescriptor& rDescriptor) override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/writerperfect/source/writer/StarOfficeWriterImportFilter.cxx b/writerperfect/source/writer/StarOfficeWriterImportFilter.cxx
new file mode 100644
index 000000000..849ede0d7
--- /dev/null
+++ b/writerperfect/source/writer/StarOfficeWriterImportFilter.cxx
@@ -0,0 +1,128 @@
+/* -*- 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 <cppuhelper/supportsservice.hxx>
+
+#include <libstaroffice/libstaroffice.hxx>
+
+#include <sfx2/passwd.hxx>
+
+#include "StarOfficeWriterImportFilter.hxx"
+
+using com::sun::star::uno::Sequence;
+using com::sun::star::uno::XComponentContext;
+using com::sun::star::uno::XInterface;
+
+static bool handleEmbeddedSTOFFWriterGraphicObject(const librevenge::RVNGBinaryData& data,
+ OdfDocumentHandler* pHandler,
+ const OdfStreamType streamType)
+{
+ OdgGenerator exporter;
+ exporter.addDocumentHandler(pHandler, streamType);
+ return STOFFDocument::decodeGraphic(data, &exporter);
+}
+
+static bool handleEmbeddedSTOFFWriterSpreadsheetObject(const librevenge::RVNGBinaryData& data,
+ OdfDocumentHandler* pHandler,
+ const OdfStreamType streamType)
+{
+ OdsGenerator exporter;
+ exporter.registerEmbeddedObjectHandler("image/stoff-odg",
+ &handleEmbeddedSTOFFWriterGraphicObject);
+ exporter.addDocumentHandler(pHandler, streamType);
+ return STOFFDocument::decodeSpreadsheet(data, &exporter);
+}
+
+bool StarOfficeWriterImportFilter::doImportDocument(weld::Window* pParent,
+ librevenge::RVNGInputStream& rInput,
+ OdtGenerator& rGenerator, utl::MediaDescriptor&)
+{
+ STOFFDocument::Kind docKind = STOFFDocument::STOFF_K_UNKNOWN;
+ const STOFFDocument::Confidence confidence
+ = STOFFDocument::isFileFormatSupported(&rInput, docKind);
+ OString aUtf8Passwd;
+ if (confidence == STOFFDocument::STOFF_C_SUPPORTED_ENCRYPTION)
+ {
+ // try to ask for a password
+ try
+ {
+ SfxPasswordDialog aPasswdDlg(pParent);
+ aPasswdDlg.SetMinLen(0);
+ if (!aPasswdDlg.run())
+ return false;
+ OUString aPasswd = aPasswdDlg.GetPassword();
+ aUtf8Passwd = OUStringToOString(aPasswd, RTL_TEXTENCODING_UTF8);
+ }
+ catch (...)
+ {
+ // ok, we will probably guess it
+ }
+ }
+ return STOFFDocument::STOFF_R_OK
+ == STOFFDocument::parse(&rInput, &rGenerator,
+ !aUtf8Passwd.isEmpty() ? aUtf8Passwd.getStr() : nullptr);
+}
+
+bool StarOfficeWriterImportFilter::doDetectFormat(librevenge::RVNGInputStream& rInput,
+ OUString& rTypeName)
+{
+ rTypeName.clear();
+
+ STOFFDocument::Kind docKind = STOFFDocument::STOFF_K_UNKNOWN;
+ const STOFFDocument::Confidence confidence
+ = STOFFDocument::isFileFormatSupported(&rInput, docKind);
+
+ if (confidence == STOFFDocument::STOFF_C_EXCELLENT
+ || confidence == STOFFDocument::STOFF_C_SUPPORTED_ENCRYPTION)
+ {
+ switch (docKind)
+ {
+ case STOFFDocument::STOFF_K_TEXT:
+ rTypeName = "StarOffice_Writer";
+ break;
+ default:
+ break;
+ }
+ }
+
+ return !rTypeName.isEmpty();
+}
+
+void StarOfficeWriterImportFilter::doRegisterHandlers(OdtGenerator& rGenerator)
+{
+ rGenerator.registerEmbeddedObjectHandler("image/stoff-odg",
+ &handleEmbeddedSTOFFWriterGraphicObject);
+ rGenerator.registerEmbeddedObjectHandler("image/stoff-ods",
+ &handleEmbeddedSTOFFWriterSpreadsheetObject);
+}
+
+// XServiceInfo
+OUString SAL_CALL StarOfficeWriterImportFilter::getImplementationName()
+{
+ return "org.libreoffice.comp.Writer.StarOfficeWriterImportFilter";
+}
+
+sal_Bool SAL_CALL StarOfficeWriterImportFilter::supportsService(const OUString& rServiceName)
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+Sequence<OUString> SAL_CALL StarOfficeWriterImportFilter::getSupportedServiceNames()
+{
+ return { "com.sun.star.document.ImportFilter", "com.sun.star.document.ExtendedTypeDetection" };
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+org_libreoffice_comp_Writer_StarOfficeWriterImportFilter_get_implementation(
+ css::uno::XComponentContext* const context, const css::uno::Sequence<css::uno::Any>&)
+{
+ return cppu::acquire(new StarOfficeWriterImportFilter(context));
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/writerperfect/source/writer/StarOfficeWriterImportFilter.hxx b/writerperfect/source/writer/StarOfficeWriterImportFilter.hxx
new file mode 100644
index 000000000..8310f1cbf
--- /dev/null
+++ b/writerperfect/source/writer/StarOfficeWriterImportFilter.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 <com/sun/star/uno/XComponentContext.hpp>
+
+#include <ImportFilter.hxx>
+
+#include <DocumentHandlerForOdt.hxx>
+
+/* This component will be instantiated for both import or export. Whether it calls
+ * setSourceDocument or setTargetDocument determines which Impl function the filter
+ * member calls */
+class StarOfficeWriterImportFilter : public writerperfect::ImportFilter<OdtGenerator>
+{
+public:
+ explicit StarOfficeWriterImportFilter(
+ const css::uno::Reference<css::uno::XComponentContext>& rxContext)
+ : writerperfect::ImportFilter<OdtGenerator>(rxContext)
+ {
+ }
+
+ // XServiceInfo
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override;
+ virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override;
+
+private:
+ virtual bool doDetectFormat(librevenge::RVNGInputStream& rInput, OUString& rTypeName) override;
+ virtual bool doImportDocument(weld::Window* pParent, librevenge::RVNGInputStream& rInput,
+ OdtGenerator& rGenerator, utl::MediaDescriptor&) override;
+ virtual void doRegisterHandlers(OdtGenerator& rGenerator) override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/writerperfect/source/writer/WordPerfectImportFilter.cxx b/writerperfect/source/writer/WordPerfectImportFilter.cxx
new file mode 100644
index 000000000..46e3241ee
--- /dev/null
+++ b/writerperfect/source/writer/WordPerfectImportFilter.cxx
@@ -0,0 +1,238 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+/* "This product is not manufactured, approved, or supported by
+ * Corel Corporation or Corel Corporation Limited."
+ */
+
+#include <osl/diagnose.h>
+
+#include <com/sun/star/awt/XWindow.hpp>
+#include <com/sun/star/io/XInputStream.hpp>
+#include <com/sun/star/xml/sax/XFastDocumentHandler.hpp>
+#include <com/sun/star/uno/Reference.h>
+#include <cppuhelper/supportsservice.hxx>
+
+#include <DocumentHandler.hxx>
+#include <WPXSvInputStream.hxx>
+
+#include <sfx2/passwd.hxx>
+#include <ucbhelper/content.hxx>
+#include <vcl/svapp.hxx>
+#include <xmloff/xmlimp.hxx>
+
+#include <libwpd/libwpd.h>
+#include <libwpg/libwpg.h>
+
+#include "WordPerfectImportFilter.hxx"
+
+using com::sun::star::uno::Reference;
+
+using com::sun::star::awt::XWindow;
+using com::sun::star::document::XImporter;
+using com::sun::star::io::XInputStream;
+using com::sun::star::xml::sax::XFastDocumentHandler;
+
+using writerperfect::DocumentHandler;
+using writerperfect::WPXSvInputStream;
+
+static bool handleEmbeddedWPGObject(const librevenge::RVNGBinaryData& data,
+ OdfDocumentHandler* pHandler, const OdfStreamType streamType)
+{
+ OdgGenerator exporter;
+ exporter.addDocumentHandler(pHandler, streamType);
+
+ libwpg::WPGFileFormat fileFormat = libwpg::WPG_AUTODETECT;
+
+ if (!libwpg::WPGraphics::isSupported(data.getDataStream()))
+ fileFormat = libwpg::WPG_WPG1;
+
+ return libwpg::WPGraphics::parse(data.getDataStream(), &exporter, fileFormat);
+}
+
+static bool handleEmbeddedWPGImage(const librevenge::RVNGBinaryData& input,
+ librevenge::RVNGBinaryData& output)
+{
+ libwpg::WPGFileFormat fileFormat = libwpg::WPG_AUTODETECT;
+
+ if (!libwpg::WPGraphics::isSupported(input.getDataStream()))
+ fileFormat = libwpg::WPG_WPG1;
+
+ librevenge::RVNGStringVector svgOutput;
+ librevenge::RVNGSVGDrawingGenerator aSVGGenerator(svgOutput, "");
+
+ if (!libwpg::WPGraphics::parse(input.getDataStream(), &aSVGGenerator, fileFormat))
+ return false;
+
+ if (svgOutput.empty())
+ return false;
+
+ assert(1 == svgOutput.size());
+
+ output.clear();
+ output.append(reinterpret_cast<const unsigned char*>(svgOutput[0].cstr()), svgOutput[0].size());
+ return true;
+}
+
+bool WordPerfectImportFilter::importImpl(
+ const css::uno::Sequence<css::beans::PropertyValue>& aDescriptor)
+{
+ Reference<XInputStream> xInputStream;
+ Reference<XWindow> xDialogParent;
+ for (const auto& rValue : aDescriptor)
+ {
+ if (rValue.Name == "InputStream")
+ rValue.Value >>= xInputStream;
+ else if (rValue.Name == "ParentWindow")
+ rValue.Value >>= xDialogParent;
+ }
+ if (!xInputStream.is())
+ {
+ OSL_ASSERT(false);
+ return false;
+ }
+
+ WPXSvInputStream input(xInputStream);
+
+ OString aUtf8Passwd;
+
+ libwpd::WPDConfidence confidence = libwpd::WPDocument::isFileFormatSupported(&input);
+
+ if (libwpd::WPD_CONFIDENCE_SUPPORTED_ENCRYPTION == confidence)
+ {
+ int unsuccessfulAttempts = 0;
+ while (true)
+ {
+ SfxPasswordDialog aPasswdDlg(Application::GetFrameWeld(xDialogParent));
+ aPasswdDlg.SetMinLen(0);
+ if (!aPasswdDlg.run())
+ return false;
+ OUString aPasswd = aPasswdDlg.GetPassword();
+ aUtf8Passwd = OUStringToOString(aPasswd, RTL_TEXTENCODING_UTF8);
+ if (libwpd::WPD_PASSWORD_MATCH_OK
+ == libwpd::WPDocument::verifyPassword(&input, aUtf8Passwd.getStr()))
+ break;
+ else
+ unsuccessfulAttempts++;
+ if (unsuccessfulAttempts == 3) // timeout after 3 password attempts
+ return false;
+ }
+ }
+
+ // An XML import service: what we push sax messages to.
+ Reference<XInterface> xInternalFilter
+ = mxContext->getServiceManager()->createInstanceWithContext(
+ "com.sun.star.comp.Writer.XMLOasisImporter", mxContext);
+ assert(xInternalFilter);
+ css::uno::Reference<css::xml::sax::XFastDocumentHandler> xInternalHandler(xInternalFilter,
+ css::uno::UNO_QUERY);
+ assert(xInternalHandler);
+
+ // The XImporter sets up an empty target document for XDocumentHandler to write to.
+ Reference<XImporter> xImporter(xInternalHandler, css::uno::UNO_QUERY);
+ xImporter->setTargetDocument(mxDoc);
+
+ // OO Document Handler: abstract class to handle document SAX messages, concrete implementation here
+ // writes to in-memory target doc
+ DocumentHandler aHandler(
+ new SvXMLLegacyToFastDocHandler(static_cast<SvXMLImport*>(xInternalHandler.get())));
+
+ OdtGenerator collector;
+ collector.addDocumentHandler(&aHandler, ODF_FLAT_XML);
+ collector.registerEmbeddedObjectHandler("image/x-wpg", &handleEmbeddedWPGObject);
+ collector.registerEmbeddedImageHandler("image/x-wpg", &handleEmbeddedWPGImage);
+ return libwpd::WPD_OK
+ == libwpd::WPDocument::parse(&input, &collector,
+ aUtf8Passwd.isEmpty() ? nullptr : aUtf8Passwd.getStr());
+}
+
+sal_Bool SAL_CALL
+WordPerfectImportFilter::filter(const css::uno::Sequence<css::beans::PropertyValue>& aDescriptor)
+{
+ return importImpl(aDescriptor);
+}
+void SAL_CALL WordPerfectImportFilter::cancel() {}
+
+// XImporter
+void SAL_CALL
+WordPerfectImportFilter::setTargetDocument(const Reference<css::lang::XComponent>& xDoc)
+{
+ mxDoc = xDoc;
+}
+
+// XExtendedFilterDetection
+OUString SAL_CALL
+WordPerfectImportFilter::detect(css::uno::Sequence<css::beans::PropertyValue>& Descriptor)
+{
+ libwpd::WPDConfidence confidence = libwpd::WPD_CONFIDENCE_NONE;
+ OUString sTypeName;
+ sal_Int32 nLength = Descriptor.getLength();
+ sal_Int32 location = nLength;
+ const css::beans::PropertyValue* pValue = Descriptor.getConstArray();
+ Reference<XInputStream> xInputStream;
+ for (sal_Int32 i = 0; i < nLength; i++)
+ {
+ if (pValue[i].Name == "TypeName")
+ location = i;
+ else if (pValue[i].Name == "InputStream")
+ pValue[i].Value >>= xInputStream;
+ }
+
+ if (!xInputStream.is())
+ return OUString();
+
+ WPXSvInputStream input(xInputStream);
+
+ confidence = libwpd::WPDocument::isFileFormatSupported(&input);
+
+ if (confidence == libwpd::WPD_CONFIDENCE_EXCELLENT
+ || confidence == libwpd::WPD_CONFIDENCE_SUPPORTED_ENCRYPTION)
+ sTypeName = "writer_WordPerfect_Document";
+
+ if (!sTypeName.isEmpty())
+ {
+ if (location == nLength)
+ {
+ Descriptor.realloc(nLength + 1);
+ Descriptor.getArray()[location].Name = "TypeName";
+ }
+
+ Descriptor.getArray()[location].Value <<= sTypeName;
+ }
+
+ return sTypeName;
+}
+
+// XInitialization
+void SAL_CALL
+WordPerfectImportFilter::initialize(const css::uno::Sequence<css::uno::Any>& /*aArguments*/)
+{
+}
+
+// XServiceInfo
+OUString SAL_CALL WordPerfectImportFilter::getImplementationName()
+{
+ return "com.sun.star.comp.Writer.WordPerfectImportFilter";
+}
+
+sal_Bool SAL_CALL WordPerfectImportFilter::supportsService(const OUString& rServiceName)
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+css::uno::Sequence<OUString> SAL_CALL WordPerfectImportFilter::getSupportedServiceNames()
+{
+ return { "com.sun.star.document.ImportFilter", "com.sun.star.document.ExtendedTypeDetection" };
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+com_sun_star_comp_Writer_WordPerfectImportFilter_get_implementation(
+ css::uno::XComponentContext* const context, const css::uno::Sequence<css::uno::Any>&)
+{
+ return cppu::acquire(new WordPerfectImportFilter(context));
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/writerperfect/source/writer/WordPerfectImportFilter.hxx b/writerperfect/source/writer/WordPerfectImportFilter.hxx
new file mode 100644
index 000000000..a9fc331ae
--- /dev/null
+++ b/writerperfect/source/writer/WordPerfectImportFilter.hxx
@@ -0,0 +1,63 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+/* "This product is not manufactured, approved, or supported by
+ * Corel Corporation or Corel Corporation Limited."
+ */
+#pragma once
+
+#include <com/sun/star/document/XFilter.hpp>
+#include <com/sun/star/document/XImporter.hpp>
+#include <com/sun/star/document/XExtendedFilterDetection.hpp>
+#include <com/sun/star/lang/XInitialization.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <cppuhelper/implbase.hxx>
+
+/* This component will be instantiated for both import or export. Whether it calls
+ * setSourceDocument or setTargetDocument determines which Impl function the filter
+ * member calls */
+class WordPerfectImportFilter
+ : public cppu::WeakImplHelper<css::document::XFilter, css::document::XImporter,
+ css::document::XExtendedFilterDetection,
+ css::lang::XInitialization, css::lang::XServiceInfo>
+{
+ css::uno::Reference<css::uno::XComponentContext> mxContext;
+ css::uno::Reference<css::lang::XComponent> mxDoc;
+
+ /// @throws css::uno::RuntimeException
+ bool importImpl(const css::uno::Sequence<css::beans::PropertyValue>& aDescriptor);
+
+public:
+ explicit WordPerfectImportFilter(
+ const css::uno::Reference<css::uno::XComponentContext>& rxContext)
+ : mxContext(rxContext)
+ {
+ }
+
+ // XFilter
+ virtual sal_Bool SAL_CALL
+ filter(const css::uno::Sequence<css::beans::PropertyValue>& aDescriptor) override;
+ virtual void SAL_CALL cancel() override;
+
+ // XImporter
+ virtual void SAL_CALL
+ setTargetDocument(const css::uno::Reference<css::lang::XComponent>& xDoc) override;
+
+ //XExtendedFilterDetection
+ virtual OUString SAL_CALL
+ detect(css::uno::Sequence<css::beans::PropertyValue>& Descriptor) override;
+
+ // XInitialization
+ virtual void SAL_CALL initialize(const css::uno::Sequence<css::uno::Any>& aArguments) override;
+
+ // XServiceInfo
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override;
+ virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
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: */
diff --git a/writerperfect/source/writer/wpftwriter.component b/writerperfect/source/writer/wpftwriter.component
new file mode 100644
index 000000000..176d48750
--- /dev/null
+++ b/writerperfect/source/writer/wpftwriter.component
@@ -0,0 +1,72 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+<component loader="com.sun.star.loader.SharedLibrary" environment="@CPPU_ENV@"
+ xmlns="http://openoffice.org/2010/uno-components">
+ <implementation name="com.sun.star.comp.Writer.AbiWordImportFilter"
+ constructor="com_sun_star_comp_Writer_AbiWordImportFilter_get_implementation">
+ <service name="com.sun.star.document.ImportFilter"/>
+ <service name="com.sun.star.document.ExtendedTypeDetection"/>
+ <optional/>
+ </implementation>
+ <implementation name="com.sun.star.comp.Writer.MSWorksImportFilter"
+ constructor="com_sun_star_comp_Writer_MSWorksImportFilter_get_implementation">
+ <service name="com.sun.star.document.ImportFilter"/>
+ <service name="com.sun.star.document.ExtendedTypeDetection"/>
+ <optional/>
+ </implementation>
+ <implementation name="com.sun.star.comp.Writer.MWAWImportFilter"
+ constructor="com_sun_star_comp_Writer_MWAWImportFilter_get_implementation">
+ <service name="com.sun.star.document.ImportFilter"/>
+ <service name="com.sun.star.document.ExtendedTypeDetection"/>
+ <optional/>
+ </implementation>
+ <implementation name="com.sun.star.comp.Writer.WordPerfectImportFilter"
+ constructor="com_sun_star_comp_Writer_WordPerfectImportFilter_get_implementation">
+ <service name="com.sun.star.document.ExtendedTypeDetection"/>
+ <service name="com.sun.star.document.ImportFilter"/>
+ <optional/>
+ </implementation>
+ <implementation name="org.libreoffice.comp.Writer.EBookImportFilter"
+ constructor="org_libreoffice_comp_Writer_EBookImportFilter_get_implementation">
+ <service name="com.sun.star.document.ExtendedTypeDetection"/>
+ <service name="com.sun.star.document.ImportFilter"/>
+ <optional/>
+ </implementation>
+ <implementation name="org.libreoffice.comp.Writer.PagesImportFilter"
+ constructor="org_libreoffice_comp_Writer_PagesImportFilter_get_implementation">
+ <service name="com.sun.star.document.ExtendedTypeDetection"/>
+ <service name="com.sun.star.document.ImportFilter"/>
+ <optional/>
+ </implementation>
+ <implementation name="org.libreoffice.comp.Writer.StarOfficeWriterImportFilter"
+ constructor="org_libreoffice_comp_Writer_StarOfficeWriterImportFilter_get_implementation">
+ <service name="com.sun.star.document.ImportFilter"/>
+ <service name="com.sun.star.document.ExtendedTypeDetection"/>
+ </implementation>
+ <implementation name="com.sun.star.comp.Writer.EPUBExportFilter"
+ constructor="com_sun_star_comp_Writer_EPUBExportFilter_get_implementation">
+ <service name="com.sun.star.document.ExportFilter"/>
+ <optional/>
+ </implementation>
+ <implementation name="com.sun.star.comp.Writer.EPUBExportUIComponent"
+ constructor="com_sun_star_comp_Writer_EPUBExportUIComponent_get_implementation">
+ <service name="com.sun.star.ui.dialogs.FilterOptionsDialog"/>
+ <optional/>
+ </implementation>
+</component>
diff --git a/writerperfect/source/writer/wpftwriter.component.extended b/writerperfect/source/writer/wpftwriter.component.extended
new file mode 100644
index 000000000..577d05e96
--- /dev/null
+++ b/writerperfect/source/writer/wpftwriter.component.extended
@@ -0,0 +1,8 @@
+# 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/.
+
+com.sun.star.comp.Writer.EPUBExportFilter
+com.sun.star.comp.Writer.EPUBExportUIComponent
diff --git a/writerperfect/source/writer/wpftwriter.component.extended2 b/writerperfect/source/writer/wpftwriter.component.extended2
new file mode 100644
index 000000000..91cd0e046
--- /dev/null
+++ b/writerperfect/source/writer/wpftwriter.component.extended2
@@ -0,0 +1,12 @@
+# 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/.
+
+com.sun.star.comp.Writer.AbiWordImportFilter
+com.sun.star.comp.Writer.MSWorksImportFilter
+com.sun.star.comp.Writer.MWAWImportFilter
+com.sun.star.comp.Writer.WordPerfectImportFilter
+org.libreoffice.comp.Writer.EBookImportFilter
+org.libreoffice.comp.Writer.PagesImportFilter